static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf, size_t size, loff_t offset, unsigned long flags) { struct ubi_volume_cdev_priv *priv = cdev->priv; struct ubi_volume *vol = priv->vol; struct ubi_device *ubi = priv->ubi; int err; if (!priv->written && !vol->updating) { if (vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; err = ubi_start_update(ubi, vol, vol->used_bytes); if (err < 0) { ubi_err(ubi, "Cannot start volume update"); return err; } } err = ubi_more_update_data(ubi, vol, buf, size); if (err < 0) { ubi_err(ubi, "Couldnt or partially wrote data"); return err; } priv->written += size; return size; }
static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf, size_t size, loff_t offset, unsigned long flags) { struct ubi_volume_cdev_priv *priv = cdev->priv; struct ubi_volume *vol = priv->vol; struct ubi_device *ubi = priv->ubi; int err; if (!priv->written) { err = ubi_start_update(ubi, vol, vol->used_bytes); if (err < 0) { ubi_err("Cannot start volume update\n"); return err; } } err = ubi_more_update_data(ubi, vol, buf, size); if (err < 0) { ubi_err("Couldnt or partially wrote data \n"); return err; } priv->written += size; return size; }
int ubi_volume_begin_write(char *volume, void *buf, size_t size, size_t full_size) { int err = 1; int rsvd_bytes = 0; struct ubi_volume *vol; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); if (size > rsvd_bytes) { printf("size > volume size! Aborting!\n"); return EINVAL; } err = ubi_start_update(ubi, vol, full_size); if (err < 0) { printf("Cannot start volume update\n"); return -err; } return ubi_volume_continue_write(volume, buf, size); }
static int ubi_volume_write(char *volume, void *buf, size_t size) { int i = 0, err = -1; int rsvd_bytes = 0; int found = 0; struct ubi_volume *vol; for (i = 0; i < ubi->vtbl_slots; i++) { vol = ubi->volumes[i]; if (vol && !strcmp(vol->name, volume)) { printf("Volume \"%s\" found at volume id %d\n", volume, i); found = 1; break; } } if (!found) { printf("%s volume not found\n", volume); return 1; } rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); if (size < 0 || size > rsvd_bytes) { printf("rsvd_bytes=%d vol->reserved_pebs=%d ubi->leb_size=%d\n", rsvd_bytes, vol->reserved_pebs, ubi->leb_size); printf("vol->data_pad=%d\n", vol->data_pad); printf("Size > volume size !!\n"); return 1; } err = ubi_start_update(ubi, vol, size); if (err < 0) { printf("Cannot start volume update\n"); return err; } err = ubi_more_update_data(ubi, vol, buf, size); if (err < 0) { printf("Couldnt or partially wrote data \n"); return err; } if (err) { size = err; err = ubi_check_volume(ubi, vol->vol_id); if ( err < 0 ) return err; if (err) { ubi_warn("volume %d on UBI device %d is corrupted", vol->vol_id, ubi->ubi_num); vol->corrupted = 1; } vol->checked = 1; ubi_gluebi_updated(vol); } return 0; }
static int ubi_volume_write(char *volume, void *buf, size_t size) { int err = 1; int rsvd_bytes = 0; struct ubi_volume *vol; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); if (size < 0 || size > rsvd_bytes) { printf("size > volume size! Aborting!\n"); return EINVAL; } if (!strncmp(vol->name, "Factory", 7) && (!size || size != rsvd_bytes)) { printf("Partial write to volume %s is inhibited\n", vol->name); return EROFS; } err = ubi_start_update(ubi, vol, size); if (err < 0) { printf("Cannot start volume update\n"); return -err; } err = ubi_more_update_data(ubi, vol, buf, size); if (err < 0) { printf("Couldnt or partially wrote data\n"); return -err; } if (err) { size = err; err = ubi_check_volume(ubi, vol->vol_id); if (err < 0) return -err; if (err) { ubi_warn("volume %d on UBI device %d is corrupted", vol->vol_id, ubi->ubi_num); vol->corrupted = 1; } vol->checked = 1; ubi_gluebi_updated(vol); } printf("\n0x%x bytes written to volume %s\n", size, volume); return 0; }
static int ubi_volume_cdev_ioctl(struct cdev *cdev, int cmd, void *buf) { struct ubi_volume_cdev_priv *priv = cdev->priv; struct ubi_device *ubi = priv->ubi; struct ubi_volume *vol = priv->vol; int err = 0; switch (cmd) { /* Volume update command */ case UBI_IOCVOLUP: { int64_t bytes, rsvd_bytes; err = copy_from_user(&bytes, buf, sizeof(int64_t)); if (err) { err = -EFAULT; break; } rsvd_bytes = (long long)vol->reserved_pebs * ubi->leb_size - vol->data_pad; if (bytes < 0 || bytes > rsvd_bytes) { err = -EINVAL; break; } err = ubi_start_update(ubi, vol, bytes); if (bytes == 0) ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED); break; } default: err = -ENOTTY; break; } return err; }
static int vol_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; struct ubi_volume_desc *desc = file->private_data; struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; void __user *argp = (void __user *)arg; switch (cmd) { /* Volume update command */ case UBI_IOCVOLUP: { int64_t bytes, rsvd_bytes; if (!capable(CAP_SYS_RESOURCE)) { err = -EPERM; break; } err = copy_from_user(&bytes, argp, sizeof(int64_t)); if (err) { err = -EFAULT; break; } if (desc->mode == UBI_READONLY) { err = -EROFS; break; } rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad); if (bytes < 0 || bytes > rsvd_bytes) { err = -EINVAL; break; } err = get_exclusive(desc); if (err < 0) break; err = ubi_start_update(ubi, vol, bytes); if (bytes == 0) revoke_exclusive(desc, UBI_READWRITE); break; } /* Atomic logical eraseblock change command */ case UBI_IOCEBCH: { struct ubi_leb_change_req req; err = copy_from_user(&req, argp, sizeof(struct ubi_leb_change_req)); if (err) { err = -EFAULT; break; } if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) { err = -EROFS; break; } /* Validate the request */ err = -EINVAL; if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || req.bytes < 0 || req.lnum >= vol->usable_leb_size) break; if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM && req.dtype != UBI_UNKNOWN) break; err = get_exclusive(desc); if (err < 0) break; err = ubi_start_leb_change(ubi, vol, &req); if (req.bytes == 0) revoke_exclusive(desc, UBI_READWRITE); break; } #ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO /* Logical eraseblock erasure command */ case UBI_IOCEBER: { int32_t lnum; err = get_user(lnum, (__user int32_t *)argp); if (err) { err = -EFAULT; break; } if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) { err = -EROFS; break; } if (lnum < 0 || lnum >= vol->reserved_pebs) { err = -EINVAL; break; } dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); err = ubi_eba_unmap_leb(ubi, vol, lnum); if (err) break; err = ubi_wl_flush(ubi); break; } #endif default: err = -ENOTTY; break; } return err; }
static int vol_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; struct ubi_volume_desc *desc = file->private_data; struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; void __user *argp = (void __user *)arg; if (_IOC_NR(cmd) > VOL_CDEV_IOC_MAX_SEQ || _IOC_TYPE(cmd) != UBI_VOL_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; switch (cmd) { /* Volume update command */ case UBI_IOCVOLUP: { int64_t bytes, rsvd_bytes; if (!capable(CAP_SYS_RESOURCE)) { err = -EPERM; break; } err = copy_from_user(&bytes, argp, sizeof(int64_t)); if (err) { err = -EFAULT; break; } if (desc->mode == UBI_READONLY) { err = -EROFS; break; } rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad); if (bytes < 0 || bytes > rsvd_bytes) { err = -EINVAL; break; } err = get_exclusive(desc); if (err < 0) break; err = ubi_start_update(ubi, vol->vol_id, bytes); if (bytes == 0) revoke_exclusive(desc, UBI_READWRITE); file->f_pos = 0; break; } #ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO /* Logical eraseblock erasure command */ case UBI_IOCEBER: { int32_t lnum; err = __get_user(lnum, (__user int32_t *)argp); if (err) { err = -EFAULT; break; } if (desc->mode == UBI_READONLY) { err = -EROFS; break; } if (lnum < 0 || lnum >= vol->reserved_pebs) { err = -EINVAL; break; } if (vol->vol_type != UBI_DYNAMIC_VOLUME) { err = -EROFS; break; } dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); err = ubi_eba_unmap_leb(ubi, vol->vol_id, lnum); if (err) break; err = ubi_wl_flush(ubi); break; } #endif default: err = -ENOTTY; break; } return err; }