コード例 #1
0
ファイル: kapi.c プロジェクト: 119-org/hi3518-osdrv
/**
 * ubi_leb_write - write data.
 * @desc: volume descriptor
 * @lnum: logical eraseblock number to write to
 * @buf: data to write
 * @offset: offset within the logical eraseblock where to write
 * @len: how many bytes to write
 * @dtype: expected data type
 *
 * This function writes @len bytes of data from @buf to offset @offset of
 * logical eraseblock @lnum. The @dtype argument describes expected lifetime of
 * the data.
 *
 * This function takes care of physical eraseblock write failures. If write to
 * the physical eraseblock write operation fails, the logical eraseblock is
 * re-mapped to another physical eraseblock, the data is recovered, and the
 * write finishes. UBI has a pool of reserved physical eraseblocks for this.
 *
 * If all the data were successfully written, zero is returned. If an error
 * occurred and UBI has not been able to recover from it, this function returns
 * a negative error code. Note, in case of an error, it is possible that
 * something was still written to the flash media, but that may be some
 * garbage.
 *
 * If the volume is damaged because of an interrupted update this function just
 * returns immediately with %-EBADF code.
 */
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
		  int offset, int len, int dtype)
{
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;
	int vol_id = vol->vol_id;

	dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);

	if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
		return -EINVAL;

	if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
		return -EROFS;

	if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 ||
	    offset + len > vol->usable_leb_size ||
	    offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
		return -EINVAL;

	if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
	    dtype != UBI_UNKNOWN)
		return -EINVAL;

	if (vol->upd_marker)
		return -EBADF;

	if (len == 0)
		return 0;

	return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype);
}
コード例 #2
0
ファイル: kapi.c プロジェクト: 119-org/hi3518-osdrv
/**
 * ubi_leb_map - map logical eraseblock to a physical eraseblock.
 * @desc: volume descriptor
 * @lnum: logical eraseblock number
 * @dtype: expected data type
 *
 * This function maps an un-mapped logical eraseblock @lnum to a physical
 * eraseblock. This means, that after a successful invocation of this
 * function the logical eraseblock @lnum will be empty (contain only %0xFF
 * bytes) and be mapped to a physical eraseblock, even if an unclean reboot
 * happens.
 *
 * This function returns zero in case of success, %-EBADF if the volume is
 * damaged because of an interrupted update, %-EBADMSG if the logical
 * eraseblock is already mapped, and other negative error codes in case of
 * other failures.
 */
int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
{
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;

	dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);

	if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
		return -EROFS;

	if (lnum < 0 || lnum >= vol->reserved_pebs)
		return -EINVAL;

	if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
	    dtype != UBI_UNKNOWN)
		return -EINVAL;

	if (vol->upd_marker)
		return -EBADF;

	if (vol->eba_tbl[lnum] >= 0)
		return -EBADMSG;

	return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
}
コード例 #3
0
ファイル: upd.c プロジェクト: CDACBANG/u-boot-wingz
/**
 * write_leb - write update data.
 * @ubi: UBI device description object
 * @vol: volume description object
 * @lnum: logical eraseblock number
 * @buf: data to write
 * @len: data size
 * @used_ebs: how many logical eraseblocks will this volume contain (static
 * volumes only)
 *
 * This function writes update data to corresponding logical eraseblock. In
 * case of dynamic volume, this function checks if the data contains 0xFF bytes
 * at the end. If yes, the 0xFF bytes are cut and not written. So if the whole
 * buffer contains only 0xFF bytes, the LEB is left unmapped.
 *
 * The reason why we skip the trailing 0xFF bytes in case of dynamic volume is
 * that we want to make sure that more data may be appended to the logical
 * eraseblock in future. Indeed, writing 0xFF bytes may have side effects and
 * this PEB won't be writable anymore. So if one writes the file-system image
 * to the UBI volume where 0xFFs mean free space - UBI makes sure this free
 * space is writable after the update.
 *
 * We do not do this for static volumes because they are read-only. But this
 * also cannot be done because we have to store per-LEB CRC and the correct
 * data length.
 *
 * This function returns zero in case of success and a negative error code in
 * case of failure.
 */
static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
		     void *buf, int len, int used_ebs)
{
	int err;

	if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
		int l = ALIGN(len, ubi->min_io_size);

		memset(buf + len, 0xFF, l - len);
		len = ubi_calc_data_len(ubi, buf, l);
		if (len == 0) {
			dbg_gen("all %d bytes contain 0xFF - skip", len);
			return 0;
		}

		err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
	} else {
		/*
		 * When writing static volume, and this is the last logical
		 * eraseblock, the length (@len) does not have to be aligned to
		 * the minimal flash I/O unit. The 'ubi_eba_write_leb_st()'
		 * function accepts exact (unaligned) length and stores it in
		 * the VID header. And it takes care of proper alignment by
		 * padding the buffer. Here we just make sure the padding will
		 * contain zeros, not random trash.
		 */
		memset(buf + len, 0, vol->usable_leb_size - len);
		err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
	}

	return err;
}
コード例 #4
0
ファイル: vtbl.c プロジェクト: ARMWorks/FA_2451_Linux_Kernel
/**
 * ubi_change_vtbl_record - change volume table record.
 * @ubi: UBI device description object
 * @idx: table index to change
 * @vtbl_rec: new volume table record
 *
 * This function changes volume table record @idx. If @vtbl_rec is %NULL, empty
 * volume table record is written. The caller does not have to calculate CRC of
 * the record as it is done by this function. Returns zero in case of success
 * and a negative error code in case of failure.
 */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
			   struct ubi_vtbl_record *vtbl_rec)
{
	int i, err;
	uint32_t crc;
	struct ubi_volume *layout_vol;

	ubi_assert(idx >= 0 && idx < ubi->vtbl_slots);
	layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];

	if (!vtbl_rec)
		vtbl_rec = &empty_vtbl_record;
	else {
		crc = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
		vtbl_rec->crc = cpu_to_be32(crc);
	}

	memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
		err = ubi_eba_unmap_leb(ubi, layout_vol, i);
		if (err)
			return err;

		err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
					ubi->vtbl_size);
		if (err)
			return err;
	}

	self_vtbl_check(ubi);
	return 0;
}
コード例 #5
0
static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
                     void *buf, int len, int used_ebs)
{
    int err;

    if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
        int l = ALIGN(len, ubi->min_io_size);

        memset(buf + len, 0xFF, l - len);
        len = ubi_calc_data_len(ubi, buf, l);
        if (len == 0) {
            dbg_gen("all %d bytes contain 0xFF - skip", len);
            return 0;
        }

        err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len,
                                UBI_UNKNOWN);
    } else {

        memset(buf + len, 0, vol->usable_leb_size - len);
        err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len,
                                   UBI_UNKNOWN, used_ebs);
    }

    return err;
}
コード例 #6
0
ファイル: gluebi.c プロジェクト: 3sOx/asuswrt-merlin
/**
 * gluebi_write - write operation of emulated MTD devices.
 * @mtd: MTD device description object
 * @to: absolute offset where to write
 * @len: how many bytes to write
 * @retlen: count of written bytes is returned here
 * @buf: buffer with data to write
 *
 * This function returns zero in case of success and a negative error code in
 * case of failure.
 */
static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
		       size_t *retlen, const u_char *buf)
{
	int err = 0, lnum, offs, total_written;
	struct ubi_volume *vol;
	struct ubi_device *ubi;
	uint64_t tmp = to;

	dbg_msg("write %zd bytes to offset %lld", len, to);

	if (len < 0 || to < 0 || len + to > mtd->size)
		return -EINVAL;

	vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
	ubi = vol->ubi;

	if (ubi->ro_mode)
		return -EROFS;

	offs = do_div(tmp, mtd->erasesize);
	lnum = tmp;

	if (len % mtd->writesize || offs % mtd->writesize)
		return -EINVAL;

	total_written = len;
	while (total_written) {
		size_t to_write = mtd->erasesize - offs;

		if (to_write > total_written)
			to_write = total_written;

		err = ubi_eba_write_leb(ubi, vol->vol_id, lnum, buf, offs,
					to_write, UBI_UNKNOWN);
		if (err)
			break;

		lnum += 1;
		offs = 0;
		total_written -= to_write;
		buf += to_write;
	}

	*retlen = len - total_written;
	return err;
}
コード例 #7
0
/**
 * ubi_change_vtbl_record - change volume table record.
 * @ubi: UBI device description object
 * @idx: table index to change
 * @vtbl_rec: new volume table record
 *
 * This function changes volume table record @idx. If @vtbl_rec is %NULL, empty
 * volume table record is written. The caller does not have to calculate CRC of
 * the record as it is done by this function. Returns zero in case of success
 * and a negative error code in case of failure.
 */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
			   struct ubi_vtbl_record *vtbl_rec)
{
	int i, err;
	uint32_t crc;
	struct ubi_volume *layout_vol;

	ubi_assert(idx >= 0 && idx < ubi->vtbl_slots);
	layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];

	if (!vtbl_rec)
		vtbl_rec = &empty_vtbl_record;
	else {
		crc = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
		vtbl_rec->crc = cpu_to_be32(crc);
	}

	memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
		err = ubi_eba_unmap_leb(ubi, layout_vol, i);
		if (err)
			return err;
#ifdef CONFIG_PWR_LOSS_MTK_SPOH
        if(i==0)
        {
            PL_RESET_ON_CASE("NAND", "CreateVol_1");
        }
        else if(i==1)
        {
            PL_RESET_ON_CASE("NAND", "CreateVol_2");
        }
#endif

		err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
					ubi->vtbl_size);
		if (err)
			return err;
	}

	paranoid_vtbl_check(ubi);
	return 0;
}
コード例 #8
0
ファイル: kapi.c プロジェクト: Lyude/linux
/**
 * ubi_leb_map - map logical eraseblock to a physical eraseblock.
 * @desc: volume descriptor
 * @lnum: logical eraseblock number
 *
 * This function maps an un-mapped logical eraseblock @lnum to a physical
 * eraseblock. This means, that after a successful invocation of this
 * function the logical eraseblock @lnum will be empty (contain only %0xFF
 * bytes) and be mapped to a physical eraseblock, even if an unclean reboot
 * happens.
 *
 * This function returns zero in case of success, %-EBADF if the volume is
 * damaged because of an interrupted update, %-EBADMSG if the logical
 * eraseblock is already mapped, and other negative error codes in case of
 * other failures.
 */
int ubi_leb_map(struct ubi_volume_desc *desc, int lnum)
{
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;

	dbg_gen("map LEB %d:%d", vol->vol_id, lnum);

	if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
		return -EROFS;

	if (!ubi_leb_valid(vol, lnum))
		return -EINVAL;

	if (vol->upd_marker)
		return -EBADF;

	if (ubi_eba_is_mapped(vol, lnum))
		return -EBADMSG;

	return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
}
コード例 #9
0
ファイル: cdev.c プロジェクト: maraz/linux-2.6
/*
 * This function allows to directly write to dynamic UBI volumes, without
 * issuing the volume update operation. Available only as a debugging feature.
 * Very useful for testing UBI.
 */
static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
				     size_t count, loff_t *offp)
{
	struct ubi_volume_desc *desc = file->private_data;
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;
	int lnum, off, len, tbuf_size, err = 0;
	size_t count_save = count;
	char *tbuf;
	uint64_t tmp;

	dbg_msg("requested: write %zd bytes to offset %lld of volume %u",
		count, *offp, vol->vol_id);

	if (vol->vol_type == UBI_STATIC_VOLUME)
		return -EROFS;

	tmp = *offp;
	off = do_div(tmp, vol->usable_leb_size);
	lnum = tmp;

	if (off % ubi->min_io_size) {
		dbg_err("unaligned position");
		return -EINVAL;
	}

	if (*offp + count > vol->used_bytes)
		count_save = count = vol->used_bytes - *offp;

	/* We can write only in fractions of the minimum I/O unit */
	if (count % ubi->min_io_size) {
		dbg_err("unaligned write length");
		return -EINVAL;
	}

	tbuf_size = vol->usable_leb_size;
	if (count < tbuf_size)
		tbuf_size = ALIGN(count, ubi->min_io_size);
	tbuf = vmalloc(tbuf_size);
	if (!tbuf)
		return -ENOMEM;

	len = count > tbuf_size ? tbuf_size : count;

	while (count) {
		cond_resched();

		if (off + len >= vol->usable_leb_size)
			len = vol->usable_leb_size - off;

		err = copy_from_user(tbuf, buf, len);
		if (err) {
			err = -EFAULT;
			break;
		}

		err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len,
					UBI_UNKNOWN);
		if (err)
			break;

		off += len;
		if (off == vol->usable_leb_size) {
			lnum += 1;
			off -= vol->usable_leb_size;
		}

		count -= len;
		*offp += len;
		buf += len;
		len = count > tbuf_size ? tbuf_size : count;
	}

	vfree(tbuf);
	return err ? err : count_save - count;
}