예제 #1
0
파일: ubi.c 프로젝트: Noltari/u-boot
static int ubi_volume_continue_write(char *volume, void *buf, size_t size)
{
	int err = 1;
	struct ubi_volume *vol;

	vol = ubi_find_volume(volume);
	if (vol == NULL)
		return ENODEV;

	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(ubi, "volume %d on UBI device %d is corrupt",
				 vol->vol_id, ubi->ubi_num);
			vol->corrupted = 1;
		}

		vol->checked = 1;
		ubi_gluebi_updated(vol);
	}

	return 0;
}
예제 #2
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;
}
예제 #3
0
파일: barebox.c 프로젝트: gazoo74/barebox
static int ubi_volume_cdev_close(struct cdev *cdev)
{
	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) {
		int remaining = vol->usable_leb_size -
				(priv->written % vol->usable_leb_size);

		if (remaining && vol->vol_type == UBI_DYNAMIC_VOLUME) {
			void *buf = kmalloc(remaining, GFP_KERNEL);

			if (!buf)
				return -ENOMEM;

			memset(buf, 0xff, remaining);

			err = ubi_more_update_data(ubi, vol, buf, remaining);

			kfree(buf);

			if (err < 0) {
				ubi_err(ubi, "Couldnt or partially wrote data");
				return err;
			}
		}

		if (vol->vol_type == UBI_STATIC_VOLUME)
			cdev->size = priv->written;

		err = ubi_finish_update(ubi, vol);
		if (err)
			return err;

		err = ubi_check_volume(ubi, vol->vol_id);
		if (err < 0) {
			ubi_err(ubi, "ubi volume check failed: %s", strerror(err));
			return err;
		}

		if (err) {
			ubi_warn(ubi, "volume %d on UBI device %d is corrupted",
					vol->vol_id, ubi->ubi_num);
			vol->corrupted = 1;
		}

		vol->checked = 1;
		ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED);
	}

	return 0;
}
예제 #4
0
파일: cmd_ubi.c 프로젝트: jing-git/rt-n56u
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;
}
예제 #5
0
파일: cdev.c 프로젝트: maraz/linux-2.6
static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *offp)
{
	int err = 0;
	struct ubi_volume_desc *desc = file->private_data;
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;

	if (!vol->updating && !vol->changing_leb)
		return vol_cdev_direct_write(file, buf, count, offp);

	if (vol->updating)
		err = ubi_more_update_data(ubi, vol, buf, count);
	else
		err = ubi_more_leb_change_data(ubi, vol, buf, count);

	if (err < 0) {
		ubi_err("cannot accept more %zd bytes of data, error %d",
			count, err);
		return err;
	}

	if (err) {
		/*
		 * The operation is finished, @err contains number of actually
		 * written bytes.
		 */
		count = err;

		if (vol->changing_leb) {
			revoke_exclusive(desc, UBI_READWRITE);
			return count;
		}

		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);
		revoke_exclusive(desc, UBI_READWRITE);
	}

	return count;
}
예제 #6
0
파일: cdev.c 프로젝트: PennPanda/linux-repo
static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *offp)
{
	int err = 0;
	struct ubi_volume_desc *desc = file->private_data;
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;

	if (!vol->updating)
		return vol_cdev_direct_write(file, buf, count, offp);

	err = ubi_more_update_data(ubi, vol->vol_id, buf, count);
	if (err < 0) {
		ubi_err("cannot write %zd bytes of update data", count);
		return err;
	}

	if (err) {
		/*
		 * Update is finished, @err contains number of actually written
		 * bytes now.
		 */
		count = 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);
		revoke_exclusive(desc, UBI_READWRITE);
	}

	*offp += count;
	return count;
}
예제 #7
0
파일: kapi.c 프로젝트: 119-org/hi3518-osdrv
/**
 * ubi_open_volume - open UBI volume.
 * @ubi_num: UBI device number
 * @vol_id: volume ID
 * @mode: open mode
 *
 * The @mode parameter specifies if the volume should be opened in read-only
 * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that
 * nobody else will be able to open this volume. UBI allows to have many volume
 * readers and one writer at a time.
 *
 * If a static volume is being opened for the first time since boot, it will be
 * checked by this function, which means it will be fully read and the CRC
 * checksum of each logical eraseblock will be checked.
 *
 * This function returns volume descriptor in case of success and a negative
 * error code in case of failure.
 */
struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
{
	int err;
	struct ubi_volume_desc *desc;
	struct ubi_device *ubi;
	struct ubi_volume *vol;

	dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode);

	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
		return ERR_PTR(-EINVAL);

	if (mode != UBI_READONLY && mode != UBI_READWRITE &&
	    mode != UBI_EXCLUSIVE)
		return ERR_PTR(-EINVAL);

	/*
	 * First of all, we have to get the UBI device to prevent its removal.
	 */
	ubi = ubi_get_device(ubi_num);
	if (!ubi)
		return ERR_PTR(-ENODEV);

	if (vol_id < 0 || vol_id >= ubi->vtbl_slots) {
		err = -EINVAL;
		goto out_put_ubi;
	}

	desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL);
	if (!desc) {
		err = -ENOMEM;
		goto out_put_ubi;
	}

	err = -ENODEV;
	if (!try_module_get(THIS_MODULE))
		goto out_free;

	spin_lock(&ubi->volumes_lock);
	vol = ubi->volumes[vol_id];
	if (!vol)
		goto out_unlock;

	err = -EBUSY;
	switch (mode) {
	case UBI_READONLY:
		if (vol->exclusive)
			goto out_unlock;
		vol->readers += 1;
		break;

	case UBI_READWRITE:
		if (vol->exclusive || vol->writers > 0)
			goto out_unlock;
		vol->writers += 1;
		break;

	case UBI_EXCLUSIVE:
		if (vol->exclusive || vol->writers || vol->readers)
			goto out_unlock;
		vol->exclusive = 1;
		break;
	}
	get_device(&vol->dev);
	vol->ref_count += 1;
	spin_unlock(&ubi->volumes_lock);

	desc->vol = vol;
	desc->mode = mode;

	mutex_lock(&ubi->ckvol_mutex);
	if (!vol->checked) {
		/* This is the first open - check the volume */
		err = ubi_check_volume(ubi, vol_id);
		if (err < 0) {
			mutex_unlock(&ubi->ckvol_mutex);
			ubi_close_volume(desc);
			return ERR_PTR(err);
		}
		if (err == 1) {
			ubi_warn("volume %d on UBI device %d is corrupted",
				 vol_id, ubi->ubi_num);
			vol->corrupted = 1;
		}
		vol->checked = 1;
	}
	mutex_unlock(&ubi->ckvol_mutex);

	return desc;

out_unlock:
	spin_unlock(&ubi->volumes_lock);
	module_put(THIS_MODULE);
out_free:
	kfree(desc);
out_put_ubi:
	ubi_put_device(ubi);
	dbg_err("cannot open device %d, volume %d, error %d",
		ubi_num, vol_id, err);
	return ERR_PTR(err);
}
예제 #8
0
파일: kapi.c 프로젝트: cilynx/dd-wrt
/**
 * ubi_open_volume - open UBI volume.
 * @ubi_num: UBI device number
 * @vol_id: volume ID
 * @mode: open mode
 *
 * The @mode parameter specifies if the volume should be opened in read-only
 * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that
 * nobody else will be able to open this volume. UBI allows to have many volume
 * readers and one writer at a time.
 *
 * If a static volume is being opened for the first time since boot, it will be
 * checked by this function, which means it will be fully read and the CRC
 * checksum of each logical eraseblock will be checked.
 *
 * This function returns volume descriptor in case of success and a negative
 * error code in case of failure.
 */
struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
{
	int err;
	struct ubi_volume_desc *desc;
	struct ubi_device *ubi = ubi_devices[ubi_num];
	struct ubi_volume *vol;

	dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode);

	err = -ENODEV;
	if (!try_module_get(THIS_MODULE))
		return ERR_PTR(err);

	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi)
		goto out_put;

	err = -EINVAL;
	if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
		goto out_put;
	if (mode != UBI_READONLY && mode != UBI_READWRITE &&
	    mode != UBI_EXCLUSIVE)
		goto out_put;

	desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL);
	if (!desc) {
		err = -ENOMEM;
		goto out_put;
	}

	spin_lock(&ubi->volumes_lock);
	vol = ubi->volumes[vol_id];
	if (!vol) {
		err = -ENODEV;
		goto out_unlock;
	}

	err = -EBUSY;
	switch (mode) {
	case UBI_READONLY:
		if (vol->exclusive)
			goto out_unlock;
		vol->readers += 1;
		break;

	case UBI_READWRITE:
		if (vol->exclusive || vol->writers > 0)
			goto out_unlock;
		vol->writers += 1;
		break;

	case UBI_EXCLUSIVE:
		if (vol->exclusive || vol->writers || vol->readers)
			goto out_unlock;
		vol->exclusive = 1;
		break;
	}
	spin_unlock(&ubi->volumes_lock);

	desc->vol = vol;
	desc->mode = mode;

	/*
	 * To prevent simultaneous checks of the same volume we use @vtbl_mutex,
	 * although it is not the purpose it was introduced for.
	 */
	mutex_lock(&ubi->vtbl_mutex);
	if (!vol->checked) {
		/* This is the first open - check the volume */
		err = ubi_check_volume(ubi, vol_id);
		if (err < 0) {
			mutex_unlock(&ubi->vtbl_mutex);
			ubi_close_volume(desc);
			return ERR_PTR(err);
		}
		if (err == 1) {
			ubi_warn("volume %d on UBI device %d is corrupted",
				 vol_id, ubi->ubi_num);
			vol->corrupted = 1;
		}
		vol->checked = 1;
	}
	mutex_unlock(&ubi->vtbl_mutex);
	return desc;

out_unlock:
	spin_unlock(&ubi->volumes_lock);
	kfree(desc);
out_put:
	module_put(THIS_MODULE);
	return ERR_PTR(err);
}