static int ext4_read_super(struct super_block *sb, void *data, int flags) { int ret; struct inode *in; struct dentry *root; ret = ext4_fill_super(sb); if (ret < 0) { // ... return ret; } GEN_DBG("\n"); in = ext4_iget(sb, 2); if (!in) { // ... return -EINVAL; } root = d_make_root(in); if (!root) return EINVAL; sb->s_root = root; return 0; }
static int __flash_erase(struct mtd_info *mtd, struct erase_info *opt) { int ret; #if 0 struct erase_info opt; memset(&opt, 0, sizeof(opt)); opt.estart = start; opt.esize = size; opt.flags = flags; #endif if (opt->len & (mtd->erase_size - 1)) { #ifdef CONFIG_DEBUG size_t size = opt->len; #endif ALIGN_UP(opt->len, mtd->erase_size); GEN_DBG("size (0x%08x) not aligned with mtd erase size (0x%08x)!" " adjusted to 0x%08x\n", size, mtd->erase_size, opt->len); } ret = mtd->erase(mtd, opt); #ifdef CONFIG_DEBUG if (ret < 0) printf("%s() failed! (errno = %d)\n", __func__, ret); #endif return ret; }
static int __extent_idx(struct ext4_extent_header *extent_header) { // fixme GEN_DBG("extent_idx not support\n"); return 0; }
static int ext4_dx_readdir(struct file *fp, void *dirent, filldir_t filldir) { // fixme GEN_DBG("Not support dx read!\n"); return 0; }
static int ext4_get_extent_blkbums(struct inode *in, size_t skip, __le32 block[], size_t nums) { struct ext4_inode *ext4_in; struct ext4_inode_info *ext4_ini; struct ext4_extent_header *extent_header; struct ext4_extent *extent; struct ext4_extent_idx *extent_idx; int i; int iter; ext4_ini = EXT4_I(in); ext4_in = ext4_ini->i_e4in; extent_header = (struct ext4_extent_header *)ext4_in->i_block; if (extent_header->eh_magic != EXT4_EXT_MAGIC) { GEN_DBG("check extent magic num error!\n"); return -EINVAL; } if (extent_header->eh_depth > 0) { extent_idx = (void *)extent_header + sizeof(*extent_header); for (i = 0; i < extent_header->eh_entries; i++) { // ... __extent_idx(extent_header); extent_idx += sizeof(*extent_idx); } return 0; } extent = (void *)extent_header + sizeof(*extent_header); i = 0; iter = 0; while (i < extent_header->eh_entries) { size_t start = extent->ee_block; size_t len = extent->ee_len; size_t addr = extent->ee_start_lo; // fixme while (iter < nums && (iter + skip) >= start && (iter + skip) < (start + len)) { block[iter] = addr + (iter + skip - start); iter++; } if (iter == nums) { break; } extent += sizeof(*extent); i++; } return 0; }
char * GAPI getcwd(char *buff, size_t size) { long ret; size_t max_size = min(size, PATH_MAX); ret = sys_getcwd(buff, max_size); if (ret < 0) { GEN_DBG("ret = %d\n", ret); return NULL; } return buff; }
static ssize_t ext4_read(struct file *fp, void *buff, size_t size, loff_t *off) { struct inode *in; struct dentry *de; size_t cur_blk; size_t offset; size_t blks; __le32 blk_num[(size - 1) / fp->f_dentry->d_sb->s_blocksize + 2]; size_t blk_size = fp->f_dentry->d_sb->s_blocksize; int ret; int i = 0; size_t count = 0; de = fp->f_dentry; in = de->d_inode; if (fp->f_pos >= in->i_size) return 0; cur_blk = fp->f_pos / in->i_sb->s_blocksize; offset = fp->f_pos % in->i_sb->s_blocksize; if (offset != 0) { blks = (size - (blk_size - offset) - 1) / blk_size + 2; } else { blks = (size - 1) / blk_size + 1; } ret = ext4_get_blknums(in, cur_blk, blk_num, blks); if (ret < 0) { GEN_DBG("Fail to get blk num 0x%x\n", cur_blk); return ret; } if (offset != 0) { __ext4_read_buff(in->i_sb, blk_num[0] * blk_size, buff, blk_size - (offset + 1)); count += blk_size - (offset + 1); i = 1; } for (; i < blks - 1; i++) { __ext4_read_block(in->i_sb, buff + i * blk_size, blk_num[i]); count += blk_size; } __ext4_read_buff(in->i_sb, blk_num[i] * blk_size, buff + count, size - count); fp->f_pos += size; return size; }
static unsigned long ext4_inode_by_name(struct inode *inode, struct qstr *unit) { struct super_block *sb = inode->i_sb; struct ext4_sb_info *e4_sbi; struct ext4_inode_info *e4_ini = EXT4_I(inode); struct ext4_dir_entry_2 *e4_de; struct ext4_inode *parent = e4_ini->i_e4in; char buff[inode->i_sb->s_blocksize]; size_t len = 0; int blocks, i; size_t block_size; e4_sbi = sb->s_fs_info; block_size = 1024 << e4_sbi->e4_sb.s_log_block_size; blocks = (parent->i_size_lo + block_size - 1) / block_size; __le32 block_indexs[blocks]; ext4_get_blknums(inode, 0, block_indexs, blocks); for (i = 0; i < blocks; i++) { __ext4_read_block(sb, buff, block_indexs[i]); e4_de = (struct ext4_dir_entry_2 *)buff; while (e4_de->rec_len > 0 && len < parent->i_size_lo && len < (i + 1) * block_size) { e4_de->name[e4_de->name_len] = '\0'; DPRINT("%s: inode = %d, e4_de size = %d, name size = %d, block = %d\n", e4_de->name, e4_de->inode, e4_de->rec_len, e4_de->name_len, i); if (unit->len == e4_de->name_len && \ !strncmp(e4_de->name, unit->name, e4_de->name_len)) return e4_de->inode; e4_de = (struct ext4_dir_entry_2 *)((char *)e4_de + e4_de->rec_len); len += e4_de->rec_len; } } GEN_DBG("\"%s\" not found!\n", unit->name); return 0; }
static int ext4_readdir(struct file *fp, void *dirent, filldir_t filldir) { struct inode *in; struct dentry *de; size_t cur_blk; size_t offset; __le32 blk_num; int ret; char blk_buff[fp->f_dentry->d_sb->s_blocksize]; struct ext4_dir_entry_2 *ext4_de; de = fp->f_dentry; in = de->d_inode; if (is_hbtree_dir(in)) { return ext4_dx_readdir(fp, dirent, filldir); } if (fp->f_pos >= in->i_size) return 0; cur_blk = fp->f_pos / in->i_sb->s_blocksize; offset = fp->f_pos % in->i_sb->s_blocksize; ret = ext4_get_blknums(in, cur_blk, &blk_num, 1); if (ret < 0) { GEN_DBG("Fail to get blk num 0x%x\n", cur_blk); return ret; } __ext4_read_block(in->i_sb, blk_buff, blk_num); ext4_de = (struct ext4_dir_entry_2 *)(blk_buff + offset); filldir(dirent, ext4_de->name, ext4_de->name_len, ext4_de->rec_len, ext4_de->inode, ext4_de->file_type); fp->f_pos += ext4_de->rec_len; return ext4_de->rec_len; }
image_t image_type_detect(const void *data, size_t size) { if (GTH_MAGIC == *(const __u32 *)(data + GTH_MAGIC_OFFSET)) { GEN_DBG("witrom image\n"); return IMG_GTH; } if (GBH_MAGIC == *(const __u32 *)(data + GBH_MAGIC_OFFSET)) { GEN_DBG("g-bios image\n"); return IMG_GBH; } if (LINUX_MAGIC == *(const __u32 *)(data + LINUX_MAGIC_OFFSET)) { GEN_DBG("Linux kernel image\n"); return IMG_LINUX; } if (JFFS2_MAGIC == *(const __u16 *)(data + JFFS2_MAGIC_OFFSET)) { GEN_DBG("JFFS2 image\n"); return IMG_JFFS2; } if (UBIFS_MAGIC == *(const __u32 *)(data + UBIFS_MAGIC_OFFSET)) { GEN_DBG("UBIFS image\n"); return IMG_UBIFS; } if (check_yaffs1_image(data + YAFFS_OOB_SIZE)) { GEN_DBG("YAFFS1 image\n"); return IMG_YAFFS1; } // TODO: check other image types GEN_DBG("Unknown image type!\n"); return IMG_UNKNOWN; }
int i2c_write_byte (__u8 addr, __u8 reg, __u8 val) { int errno = 0, to; __u16 stat; omap_i2c_outw(0xFFFF, I2C_STAT); for (to = 0; to < I2C_TIMEOUT; to++) { stat = omap_i2c_inw(I2C_STAT); if (!(stat & I2C_STAT_BB)) break; omap_i2c_outw(stat, I2C_STAT); udelay (50000); } if (I2C_TIMEOUT == to) { GEN_DBG("I2C bus busy! stat = 0x%08x\n", stat); return -EBUSY; } omap_i2c_outw(0xFFFF, I2C_STAT); omap_i2c_outw(2, I2C_CNT); omap_i2c_outw(addr, I2C_SA); omap_i2c_outw(0x8603, I2C_CON); stat = i2c_wait_ready(); if (!(stat & I2C_STAT_XRDY)) return -ETIMEDOUT; omap_i2c_outb(reg, I2C_DATA); omap_i2c_outw(I2C_STAT_XRDY, I2C_STAT); stat = i2c_wait_ready(); if (!(stat & I2C_STAT_XRDY)) return -ETIMEDOUT; omap_i2c_outb(val, I2C_DATA); omap_i2c_outw(I2C_STAT_XRDY, I2C_STAT); udelay (50000); stat = omap_i2c_inw(I2C_STAT); if (stat & I2C_STAT_NACK) return -EIO; to = 200; omap_i2c_outw(I2C_CON_EN, I2C_CON); while ((stat = omap_i2c_inw(I2C_STAT)) || \ (omap_i2c_inw(I2C_CON) & I2C_CON_MST)) { udelay (1000); omap_i2c_outw(0xFFFF, I2C_STAT); to--; if(to == 0) break; } i2c_flush(); omap_i2c_outw(0xFFFF, I2C_STAT); omap_i2c_outw(0, I2C_CNT); return errno; }
static int ext4_fill_super(struct super_block *sb) { int ret; int group_count; unsigned int bpg; // blocks per groups char buff[KB(1)]; struct ext4_sb_info *e4_sbi; struct ext4_super_block *e4_sb; struct ext4_group_desc *gdt; struct bio *bio; size_t off; bio = bio_alloc(); if (!bio) return -ENOMEM; bio->bdev = sb->s_bdev; bio->sect = 1024 / SECT_SIZE; bio->size = sizeof(buff); bio->data = buff; submit_bio(READ, bio); // TODO: check flags here bio_free(bio); if (ext4_check_fstype(buff, sizeof(struct ext4_super_block)) == false) { GEN_DBG("Invalid EXT4 magic number!\n"); // ((struct ext4_super_block *)buff)->s_magic); ret = -EINVAL; goto L1; } e4_sbi = zalloc(sizeof(*e4_sbi)); if (!e4_sbi) { ret = -ENOMEM; goto L1; } #if 1 // fixme e4_sb = &e4_sbi->e4_sb; memcpy(e4_sb, buff, sizeof(*e4_sb)); #endif sb->s_fs_info = e4_sbi; sb->s_blocksize = 1024 << e4_sb->s_log_block_size; bpg = e4_sb->s_blocks_per_group; group_count = (e4_sb->s_blocks_count_lo + bpg - 1) / bpg; DPRINT("super block information:\n" "label = \"%s\", inode size = %d, block size = %d\n", e4_sb->s_volume_name[0] ? e4_sb->s_volume_name : "<N/A>", e4_sb->s_inode_size, sb->s_blocksize); gdt = malloc(group_count * sizeof(struct ext4_group_desc)); if (NULL == gdt) { ret = -ENOMEM; goto L2; } e4_sbi->gdt = gdt; off = (e4_sb->s_first_data_block + 1) * sb->s_blocksize; __ext4_read_buff(sb, off, gdt, group_count * sizeof(struct ext4_group_desc)); DPRINT("group descrition:\n" "block groups = %d, free blocks = %d, free inodes = %d\n", group_count, gdt->bg_free_blocks_count_lo, gdt->bg_free_inodes_count_lo); return 0; L2: free(e4_sbi); L1: return ret; }