/** * open_ubi - parse UBI device name string and open the UBI device. * @name: UBI volume name * @mode: UBI volume open mode * * There are several ways to specify UBI volumes when mounting UBIFS: * o ubiX_Y - UBI device number X, volume Y; * o ubiY - UBI device number 0, volume Y; * o ubiX:NAME - mount UBI device X, volume with name NAME; * o ubi:NAME - mount UBI device 0, volume with name NAME. * * Alternative '!' separator may be used instead of ':' (because some shells * like busybox may interpret ':' as an NFS host name separator). This function * returns ubi volume object in case of success and a negative error code in * case of failure. */ static struct ubi_volume_desc *open_ubi(const char *name, int mode) { int dev, vol; char *endptr; if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i') return ERR_PTR(-EINVAL); /* ubi:NAME method */ if ((name[3] == ':' || name[3] == '!') && name[4] != '\0') return ubi_open_volume_nm(0, name + 4, mode); if (!isdigit(name[3])) return ERR_PTR(-EINVAL); dev = simple_strtoul(name + 3, &endptr, 0); /* ubiY method */ if (*endptr == '\0') return ubi_open_volume(0, dev, mode); /* ubiX_Y method */ if (*endptr == '_' && isdigit(endptr[1])) { vol = simple_strtoul(endptr + 1, &endptr, 0); if (*endptr != '\0') return ERR_PTR(-EINVAL); return ubi_open_volume(dev, vol, mode); } /* ubiX:NAME method */ if ((*endptr == ':' || *endptr == '!') && endptr[1] != '\0') return ubi_open_volume_nm(dev, ++endptr, mode); return ERR_PTR(-EINVAL); }
/** * ubi_open_volume_path - open UBI volume by its character device node path. * @pathname: volume character device node path * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume the path * to its character device node. */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { int error, ubi_num, vol_id, mod; struct inode *inode; struct path path; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); error = kern_path(pathname, LOOKUP_FOLLOW, &path); if (error) return ERR_PTR(error); inode = path.dentry->d_inode; mod = inode->i_mode; ubi_num = ubi_major2num(imajor(inode)); vol_id = iminor(inode) - 1; path_put(&path); if (!S_ISCHR(mod)) return ERR_PTR(-EINVAL); if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); }
/** * gluebi_get_device - get MTD device reference. * @mtd: the MTD device description object * * This function is called every time the MTD device is being opened and * implements the MTD get_device() operation. Returns zero in case of success * and a negative error code in case of failure. */ static int gluebi_get_device(struct mtd_info *mtd) { struct ubi_volume *vol; vol = container_of(mtd, struct ubi_volume, gluebi_mtd); /* * We do not introduce locks for gluebi reference count because the * get_device()/put_device() calls are already serialized at MTD. */ if (vol->gluebi_refcount > 0) { /* * The MTD device is already referenced and this is just one * more reference. MTD allows many users to open the same * volume simultaneously and do not distinguish between * readers/writers/exclusive openers as UBI does. So we do not * open the UBI volume again - just increase the reference * counter and return. */ vol->gluebi_refcount += 1; return 0; } /* * This is the first reference to this UBI volume via the MTD device * interface. Open the corresponding volume in read-write mode. */ vol->gluebi_desc = ubi_open_volume(vol->ubi->ubi_num, vol->vol_id, UBI_READWRITE); if (IS_ERR(vol->gluebi_desc)) return PTR_ERR(vol->gluebi_desc); vol->gluebi_refcount += 1; return 0; }
static int vol_cdev_open(struct inode *inode, struct file *file) { struct ubi_volume_desc *desc; int vol_id = iminor(inode) - 1, mode, ubi_num; lock_kernel(); ubi_num = ubi_major2num(imajor(inode)); if (ubi_num < 0) { unlock_kernel(); return ubi_num; } if (file->f_mode & FMODE_WRITE) mode = UBI_READWRITE; else mode = UBI_READONLY; dbg_msg("open volume %d, mode %d", vol_id, mode); desc = ubi_open_volume(ubi_num, vol_id, mode); unlock_kernel(); if (IS_ERR(desc)) return PTR_ERR(desc); file->private_data = desc; return 0; }
int ubifs_size(const char *filename, loff_t *size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; int err = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { err = -1; goto out; } inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } *size = inode->i_size; ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
/** * ubi_open_volume_path - open UBI volume by its character device node path. * @pathname: volume character device node path * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume the path * to its character device node. */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { int error, ubi_num, vol_id; struct path path; struct kstat stat; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); error = kern_path(pathname, LOOKUP_FOLLOW, &path); if (error) return ERR_PTR(error); error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); path_put(&path); if (error) return ERR_PTR(error); if (!S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); ubi_num = ubi_major2num(MAJOR(stat.rdev)); vol_id = MINOR(stat.rdev) - 1; if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); }
int ubifs_exists(const char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, (char *)filename); ubi_close_volume(c->ubi); return inum != 0; }
/** * ubi_open_volume_nm - open UBI volume by name. * @ubi_num: UBI device number * @name: volume name * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume by name. */ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, int mode) { int i, vol_id = -1, len; struct ubi_device *ubi; struct ubi_volume_desc *ret; dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode); if (!name) return ERR_PTR(-EINVAL); len = strnlen(name, UBI_VOL_NAME_MAX + 1); if (len > UBI_VOL_NAME_MAX) return ERR_PTR(-EINVAL); if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) return ERR_PTR(-EINVAL); ubi = ubi_get_device(ubi_num); if (!ubi) return ERR_PTR(-ENODEV); spin_lock(&ubi->volumes_lock); /* Walk all volumes of this UBI device */ for (i = 0; i < ubi->vtbl_slots; i++) { struct ubi_volume *vol = ubi->volumes[i]; if (vol && len == vol->name_len && !strcmp(name, vol->name)) { vol_id = i; break; } } spin_unlock(&ubi->volumes_lock); if (vol_id >= 0) ret = ubi_open_volume(ubi_num, vol_id, mode); else ret = ERR_PTR(-ENODEV); /* * We should put the UBI device even in case of success, because * 'ubi_open_volume()' took a reference as well. */ ubi_put_device(ubi); return ret; }
int ubifs_ls(char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; struct file *file; struct dentry *dentry; struct inode *dir; void *dirent = NULL; unsigned long inum; int ret = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { ret = -1; goto out; } file = kzalloc(sizeof(struct file), 0); dentry = kzalloc(sizeof(struct dentry), 0); dir = kzalloc(sizeof(struct inode), 0); if (!file || !dentry || !dir) { printf("%s: Error, no memory for malloc!\n", __func__); ret = -ENOMEM; goto out_mem; } dir->i_sb = ubifs_sb; file->f_path.dentry = dentry; file->f_path.dentry->d_parent = dentry; file->f_path.dentry->d_inode = dir; file->f_path.dentry->d_inode->i_ino = inum; file->f_pos = 1; file->private_data = NULL; ubifs_printdir(file, dirent); out_mem: if (file) free(file); if (dentry) free(dentry); if (dir) free(dir); out: ubi_close_volume(c->ubi); return ret; }
/** * ubi_open_volume_nm - open UBI volume by name. * @ubi_num: UBI device number * @name: volume name * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume by name. */ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, int mode) { int i, vol_id = -1, len; struct ubi_volume_desc *ret; struct ubi_device *ubi; dbg_msg("open volume %s, mode %d", name, mode); if (!name) return ERR_PTR(-EINVAL); len = strnlen(name, UBI_VOL_NAME_MAX + 1); if (len > UBI_VOL_NAME_MAX) return ERR_PTR(-EINVAL); ret = ERR_PTR(-ENODEV); if (!try_module_get(THIS_MODULE)) return ret; if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi_devices[ubi_num]) goto out_put; ubi = ubi_devices[ubi_num]; spin_lock(&ubi->volumes_lock); /* Walk all volumes of this UBI device */ for (i = 0; i < ubi->vtbl_slots; i++) { struct ubi_volume *vol = ubi->volumes[i]; if (vol && len == vol->name_len && !strcmp(name, vol->name)) { vol_id = i; break; } } spin_unlock(&ubi->volumes_lock); if (vol_id < 0) goto out_put; ret = ubi_open_volume(ubi_num, vol_id, mode); out_put: module_put(THIS_MODULE); return ret; }
int ubifs_filesize(char *filename, u32* size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum=0; struct inode *inode=NULL; int err = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); goto out_no_close; } inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * If no size was specified or if size bigger than filesize * set size to filesize */ //if ((size == 0) || (size > inode->i_size)) *size = inode->i_size; printf("ubifs_filesize %08x \n", *size); //return 0; out: ubi_close_volume(c->ubi); out_no_close: return err; }
static int vol_cdev_open(struct inode *inode, struct file *file) { struct ubi_volume_desc *desc; const struct ubi_device *ubi = major_to_device(imajor(inode)); int vol_id = iminor(inode) - 1; int mode; if (file->f_mode & FMODE_WRITE) mode = UBI_READWRITE; else mode = UBI_READONLY; dbg_msg("open volume %d, mode %d", vol_id, mode); desc = ubi_open_volume(ubi->ubi_num, vol_id, mode); if (IS_ERR(desc)) return PTR_ERR(desc); file->private_data = desc; return 0; }
/** * ubi_open_volume_path - open UBI volume by its character device node path. * @pathname: volume character device node path * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume the path * to its character device node. */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { int error, ubi_num, vol_id; struct kstat stat; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); error = vfs_stat(pathname, &stat); if (error) return ERR_PTR(error); if (!S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); ubi_num = ubi_major2num(MAJOR(stat.rdev)); vol_id = MINOR(stat.rdev) - 1; if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); }
static int ubi_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; struct ubi_device *ubi; struct ubi_volume_desc *desc; void __user *argp = (void __user *)arg; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; ubi = ubi_get_by_major(imajor(inode)); if (!ubi) return -ENODEV; switch (cmd) { /* Create volume command */ case UBI_IOCMKVOL: { struct ubi_mkvol_req req; dbg_msg("create volume"); err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); if (err) { err = -EFAULT; break; } err = verify_mkvol_req(ubi, &req); if (err) break; req.name[req.name_len] = '\0'; mutex_lock(&ubi->volumes_mutex); err = ubi_create_volume(ubi, &req); mutex_unlock(&ubi->volumes_mutex); if (err) break; err = put_user(req.vol_id, (__user int32_t *)argp); if (err) err = -EFAULT; break; } /* Remove volume command */ case UBI_IOCRMVOL: { int vol_id; dbg_msg("remove volume"); err = get_user(vol_id, (__user int32_t *)argp); if (err) { err = -EFAULT; break; } desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } mutex_lock(&ubi->volumes_mutex); err = ubi_remove_volume(desc); mutex_unlock(&ubi->volumes_mutex); /* * The volume is deleted (unless an error occurred), and the * 'struct ubi_volume' object will be freed when * 'ubi_close_volume()' will call 'put_device()'. */ ubi_close_volume(desc); break; } /* Re-size volume command */ case UBI_IOCRSVOL: { int pebs; uint64_t tmp; struct ubi_rsvol_req req; dbg_msg("re-size volume"); err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); if (err) { err = -EFAULT; break; } err = verify_rsvol_req(ubi, &req); if (err) break; desc = ubi_open_volume(ubi->ubi_num, req.vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } tmp = req.bytes; pebs = !!do_div(tmp, desc->vol->usable_leb_size); pebs += tmp; mutex_lock(&ubi->volumes_mutex); err = ubi_resize_volume(desc, pebs); mutex_unlock(&ubi->volumes_mutex); ubi_close_volume(desc); break; } default: err = -ENOTTY; break; } ubi_put_device(ubi); return err; }
int ubifs_load(char *filename, u32 addr, u32 size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; struct page page; int err = 0; int i; int count; char link_name[64]; struct ubifs_inode *ui; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * Check for symbolic link */ ui = ubifs_inode(inode); if (((inode->i_mode & S_IFMT) == S_IFLNK) && ui->data_len) { memcpy(link_name, ui->data, ui->data_len); printf("%s is linked to %s!\n", filename, link_name); ubifs_iput(inode); /* * Now we have the "real" filename, call ubifs_load() * again (recursive call) to load this file instead */ return ubifs_load(link_name, addr, size); } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > inode->i_size)) size = inode->i_size; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", filename, addr, size, size); page.addr = (void *)addr; page.index = 0; page.inode = inode; for (i = 0; i < count; i++) { err = do_readpage(c, inode, &page); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) printf("Error reading file '%s'\n", filename); else printf("Done\n"); ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
static int ubi_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; struct ubi_device *ubi; struct ubi_volume_desc *desc; void __user *argp = (void __user *)arg; if (_IOC_NR(cmd) > UBI_CDEV_IOC_MAX_SEQ || _IOC_TYPE(cmd) != UBI_IOC_MAGIC) return -ENOTTY; if (_IOC_DIR(cmd) && _IOC_READ) err = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) && _IOC_WRITE) err = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd)); if (err) return -EFAULT; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; ubi = major_to_device(imajor(inode)); if (IS_ERR(ubi)) return PTR_ERR(ubi); switch (cmd) { /* Create volume command */ case UBI_IOCMKVOL: { struct ubi_mkvol_req req; dbg_msg("create volume"); err = __copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); if (err) { err = -EFAULT; break; } err = verify_mkvol_req(ubi, &req); if (err) break; req.name[req.name_len] = '\0'; err = ubi_create_volume(ubi, &req); if (err) break; err = __put_user(req.vol_id, (__user int32_t *)argp); if (err) err = -EFAULT; break; } /* Remove volume command */ case UBI_IOCRMVOL: { int vol_id; dbg_msg("remove volume"); err = __get_user(vol_id, (__user int32_t *)argp); if (err) { err = -EFAULT; break; } desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } err = ubi_remove_volume(desc); if (err) ubi_close_volume(desc); break; } /* Re-size volume command */ case UBI_IOCRSVOL: { int pebs; uint64_t tmp; struct ubi_rsvol_req req; dbg_msg("re-size volume"); err = __copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); if (err) { err = -EFAULT; break; } err = verify_rsvol_req(ubi, &req); if (err) break; desc = ubi_open_volume(ubi->ubi_num, req.vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } tmp = req.bytes; pebs = !!do_div(tmp, desc->vol->usable_leb_size); pebs += tmp; err = ubi_resize_volume(desc, pebs); ubi_close_volume(desc); break; } default: err = -ENOTTY; break; } return err; }
int ubifs_read(const char *filename, void *buf, loff_t offset, loff_t size, loff_t *actread) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; struct page page; int err = 0; int i; int count; int last_block_size = 0; *actread = 0; if (offset & (PAGE_SIZE - 1)) { printf("ubifs: Error offset must be a multple of %d\n", PAGE_SIZE); return -1; } c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get * the real file here */ inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } if (offset > inode->i_size) { printf("ubifs: Error offset (%lld) > file-size (%lld)\n", offset, size); err = -1; goto put_inode; } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > (inode->i_size - offset))) size = inode->i_size - offset; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; page.addr = buf; page.index = offset / PAGE_SIZE; page.inode = inode; for (i = 0; i < count; i++) { /* * Make sure to not read beyond the requested size */ if (((i + 1) == count) && (size < inode->i_size)) last_block_size = size - (i * PAGE_SIZE); err = do_readpage(c, inode, &page, last_block_size); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) { printf("Error reading file '%s'\n", filename); *actread = i * PAGE_SIZE; } else { *actread = size; } put_inode: ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
/* * Set up our internal device. */ static void setup_device(struct ubiblk_dev *dev, int which) { memset (dev, 0, sizeof (struct ubiblk_dev)); spin_lock_init(&dev->lock); /* get each ubi device that we're working with. Each mtd device claimed * by the ubi layer is a device. Note that this can be a chip or a * partition. */ if(ubi_get_device_info(which, &dev->ubi_dev)) { printk("ubiblk: Failed to get device info for ubi%d\n", which); goto out_vfree; } /* each ubi device is either empty, corrupted, or contains some number * of volumes. For now, I'm assuming that there's exactly one volume, * and it's volume id is 0. This is a bit inapproriate, because ubi * volumes are supposed to be like partitions. The proper solution * would be to allow the ubi userspace tools to create partitions much * like fdisk would. */ dev->ubi_vol = ubi_open_volume(which, 0, UBI_READWRITE); if(IS_ERR(dev->ubi_vol)) { printk("Failed to open ubi volume 0 on device %d\n", which); dev->ubi_vol = 0; goto out_vfree; } dev->hardsect_size = dev->ubi_dev.min_io_size; dev->size = nsectors*dev->hardsect_size; /* setup blk dev queuing */ dev->queue = blk_init_queue(ubiblk_request, &dev->lock); if (dev->queue == NULL) goto out_vfree; blk_queue_hardsect_size(dev->queue, dev->hardsect_size); dev->queue->queuedata = dev; /* setup gendisk structure */ dev->gd = alloc_disk(UBIBLK_MINORS); if (! dev->gd) { printk (KERN_NOTICE "alloc_disk failure\n"); goto out_vfree; } dev->gd->major = ubiblk_major; dev->gd->first_minor = which*UBIBLK_MINORS; dev->gd->fops = &ubiblk_ops; dev->gd->queue = dev->queue; dev->gd->private_data = dev; snprintf (dev->gd->disk_name, 32, "ubiblk%c", which + 'a'); set_capacity(dev->gd, nsectors*(dev->hardsect_size/KERNEL_SECTOR_SIZE)); add_disk(dev->gd); return; out_vfree: if (dev->queue) blk_cleanup_queue(dev->queue); }
int ubifs_load(char *filename, u32 addr, u32 size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; struct page page; int err = 0; int i; int count; int last_block_size = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get * the real file here */ inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > inode->i_size)) size = inode->i_size; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", filename, addr, size, size); page.addr = (void *)addr; page.index = 0; page.inode = inode; for (i = 0; i < count; i++) { /* * Make sure to not read beyond the requested size */ if ((i + 1) == count) last_block_size = size - (i * PAGE_SIZE); err = do_readpage(c, inode, &page, last_block_size); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) printf("Error reading file '%s'\n", filename); else printf("Done\n"); ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
static int ubifs_fill_super(struct super_block *sb, void *data, int silent) { struct ubi_volume_desc *ubi = sb->s_fs_info; struct ubifs_info *c; struct inode *root; int err; c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); if (!c) return -ENOMEM; spin_lock_init(&c->cnt_lock); spin_lock_init(&c->cs_lock); spin_lock_init(&c->buds_lock); spin_lock_init(&c->space_lock); spin_lock_init(&c->orphan_lock); init_rwsem(&c->commit_sem); mutex_init(&c->lp_mutex); mutex_init(&c->tnc_mutex); mutex_init(&c->log_mutex); mutex_init(&c->mst_mutex); mutex_init(&c->umount_mutex); init_waitqueue_head(&c->cmt_wq); c->buds = RB_ROOT; c->old_idx = RB_ROOT; c->size_tree = RB_ROOT; c->orph_tree = RB_ROOT; INIT_LIST_HEAD(&c->infos_list); INIT_LIST_HEAD(&c->idx_gc); INIT_LIST_HEAD(&c->replay_list); INIT_LIST_HEAD(&c->replay_buds); INIT_LIST_HEAD(&c->uncat_list); INIT_LIST_HEAD(&c->empty_list); INIT_LIST_HEAD(&c->freeable_list); INIT_LIST_HEAD(&c->frdi_idx_list); INIT_LIST_HEAD(&c->unclean_leb_list); INIT_LIST_HEAD(&c->old_buds); INIT_LIST_HEAD(&c->orph_list); INIT_LIST_HEAD(&c->orph_new); c->highest_inum = UBIFS_FIRST_INO; c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; ubi_get_volume_info(ubi, &c->vi); ubi_get_device_info(c->vi.ubi_num, &c->di); /* Re-open the UBI device in read-write mode */ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); goto out_free; } c->vfs_sb = sb; sb->s_fs_info = c; sb->s_magic = UBIFS_SUPER_MAGIC; sb->s_blocksize = UBIFS_BLOCK_SIZE; sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; sb->s_dev = c->vi.cdev; sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); if (c->max_inode_sz > MAX_LFS_FILESIZE) sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; if (c->rw_incompat) { ubifs_err("the file-system is not R/W-compatible"); ubifs_msg("on-flash format version is w%d/r%d, but software " "only supports up to version w%d/r%d", c->fmt_version, c->ro_compat_version, UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION); return -EROFS; } mutex_lock(&c->umount_mutex); err = mount_ubifs(c); if (err) { ubifs_assert(err < 0); goto out_unlock; } /* Read the root inode */ root = ubifs_iget(sb, UBIFS_ROOT_INO); if (IS_ERR(root)) { err = PTR_ERR(root); goto out_umount; } sb->s_root = NULL; mutex_unlock(&c->umount_mutex); return 0; out_umount: ubifs_umount(c); out_unlock: mutex_unlock(&c->umount_mutex); ubi_close_volume(c->ubi); out_free: kfree(c); return err; }
/** * ubi_open_volume_nm - open UBI volume by name. * @ubi_num: UBI device number * @name: volume name * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume by name. */ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, int mode) { int i, vol_id = -1, len; struct ubi_device *ubi; struct ubi_volume_desc *ret; int k; dbg_msg("open volume %s, mode %d", name, mode); if (!name) return ERR_PTR(-EINVAL); len = strnlen(name, UBI_VOL_NAME_MAX + 1); if (len > UBI_VOL_NAME_MAX) return ERR_PTR(-EINVAL); if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) return ERR_PTR(-EINVAL); ubi = ubi_get_device(ubi_num); if (!ubi) return ERR_PTR(-ENODEV); for( k=0; k<(UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT); k++) { if (ubi->volumes[i]) { printf("ubi volume name = %s\n", ubi->volumes[i]->name); } } spin_lock(&ubi->volumes_lock); /* Walk all volumes of this UBI device */ for (i = 0; i < (ubi->vtbl_slots+UBI_INT_VOL_COUNT); i++) { struct ubi_volume *vol = ubi->volumes[i]; if (vol) { // printf("ubi_open_volume_nm found i=%d\n", i); // printf("ubi_open_volume_nm found volume vol->name=%s\n", vol->name); // printf("ubi_open_volume_nm found volume name=%s\n", name); // printf("ubi_open_volume_nm found len=%d\n", len); // printf("ubi_open_volume_nm found vol->name_len=%d\n", vol->name_len); k = strcmp(name, vol->name); if (0==k) { vol_id=i; // printf("ubi_open_volume_nm found strings are compared\n"); } break; } } spin_unlock(&ubi->volumes_lock); if (vol_id >= 0) ret = ubi_open_volume(ubi_num, vol_id, mode); else ret = ERR_PTR(-ENODEV); // printf("ubi_open_volume_nm volume =%d!\n", i); /* * We should put the UBI device even in case of success, because * 'ubi_open_volume()' took a reference as well. */ ubi_put_device(ubi); return ret; }
int ubifs_part_load(char *filename, u32 addr, u32 offset, u32 size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum=0; struct inode *inode=NULL; struct page page; int err = 0; int i=0; int count=0; int last_block_size = 0; char link_name[64]; struct ubifs_inode *ui=NULL; if(offset % PAGE_SIZE != 0) { printf("%s: offset(0x%x) should align to page size(0x%x), at %d\n", __func__, offset, PAGE_SIZE, __LINE__); return 1; } c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); goto out_no_close; } inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * Check for symbolic link */ ui = ubifs_inode(inode); if (((inode->i_mode & S_IFMT) == S_IFLNK) && ui->data_len) { memcpy(link_name, ui->data, ui->data_len); link_name[ui->data_len] = '\0'; printf("%s is linked to %s!\n", filename, link_name); ubifs_iput(inode); /* * Now we have the "real" filename, call ubifs_load() * again (recursive call) to load this file instead */ return ubifs_part_load(link_name, addr, offset, size); } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > inode->i_size)) size = inode->i_size; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", filename, addr, size, size); page.addr = (void *)addr; page.index = (offset / PAGE_SIZE); page.inode = inode; //offset for (i = 0; i < count; i++) { /* * Make sure to not read beyond the requested size */ if (((i + 1) == count) && (size < inode->i_size)) last_block_size = size - (i * PAGE_SIZE); err = do_readpage(c, inode, &page, last_block_size); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) printf("Error reading file '%s'\n", filename); else printf("Done\n"); ubifs_iput(inode); out: ubi_close_volume(c->ubi); out_no_close: return err; }