Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
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;
}
Exemple #6
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}