Example #1
0
static int write_eraseblock(int ebnum)
{
	size_t written;
	int err = 0;
	loff_t addr = ebnum * mtd->erasesize;

	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
	if (unlikely(err || written != subpgsize)) {
		pr_err("error: write failed at %#llx\n",
		       (long long)addr);
		if (written != subpgsize) {
			pr_err("  write size: %#x\n", subpgsize);
			pr_err("  written: %#zx\n", written);
		}
		return err ? err : -1;
	}

	addr += subpgsize;

	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
	if (unlikely(err || written != subpgsize)) {
		pr_err("error: write failed at %#llx\n",
		       (long long)addr);
		if (written != subpgsize) {
			pr_err("  write size: %#x\n", subpgsize);
			pr_err("  written: %#zx\n", written);
		}
		return err ? err : -1;
	}

	return err;
}
static int write_eraseblock_by_2pages(int ebnum)
{
	size_t written, sz = pgsize * 2;
	int i, n = pgcnt / 2, err = 0;
	loff_t addr = ebnum * mtd->erasesize;
	void *buf = iobuf;

	for (i = 0; i < n; i++) {
		err = mtd_write(mtd, addr, sz, &written, buf);
		if (err || written != sz) {
			printk(PRINT_PREF "error: write failed at %#llx\n",
			       addr);
			if (!err)
				err = -EINVAL;
			return err;
		}
		addr += sz;
		buf += sz;
	}
	if (pgcnt % 2) {
		err = mtd_write(mtd, addr, pgsize, &written, buf);
		if (err || written != pgsize) {
			printk(PRINT_PREF "error: write failed at %#llx\n",
			       addr);
			if (!err)
				err = -EINVAL;
		}
	}

	return err;
}
Example #3
0
/**
 * nor_erase_prepare - prepare a NOR flash PEB for erasure.
 * @ubi: UBI device description object
 * @pnum: physical eraseblock number to prepare
 *
 * NOR flash, or at least some of them, have peculiar embedded PEB erasure
 * algorithm: the PEB is first filled with zeroes, then it is erased. And
 * filling with zeroes starts from the end of the PEB. This was observed with
 * Spansion S29GL512N NOR flash.
 *
 * This means that in case of a power cut we may end up with intact data at the
 * beginning of the PEB, and all zeroes at the end of PEB. In other words, the
 * EC and VID headers are OK, but a large chunk of data at the end of PEB is
 * zeroed. This makes UBI mistakenly treat this PEB as used and associate it
 * with an LEB, which leads to subsequent failures (e.g., UBIFS fails).
 *
 * This function is called before erasing NOR PEBs and it zeroes out EC and VID
 * magic numbers in order to invalidate them and prevent the failures. Returns
 * zero in case of success and a negative error code in case of failure.
 */
static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
{
	int err;
	size_t written;
	loff_t addr;
	uint32_t data = 0;
	struct ubi_ec_hdr ec_hdr;
	struct ubi_vid_io_buf vidb;

	/*
	 * Note, we cannot generally define VID header buffers on stack,
	 * because of the way we deal with these buffers (see the header
	 * comment in this file). But we know this is a NOR-specific piece of
	 * code, so we can do this. But yes, this is error-prone and we should
	 * (pre-)allocate VID header buffer instead.
	 */
	struct ubi_vid_hdr vid_hdr;

	/*
	 * If VID or EC is valid, we have to corrupt them before erasing.
	 * It is important to first invalidate the EC header, and then the VID
	 * header. Otherwise a power cut may lead to valid EC header and
	 * invalid VID header, in which case UBI will treat this PEB as
	 * corrupted and will try to preserve it, and print scary warnings.
	 */
	addr = (loff_t)pnum * ubi->peb_size;
	err = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
	if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR &&
	    err != UBI_IO_FF){
		err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
		if(err)
			goto error;
	}

	ubi_init_vid_buf(ubi, &vidb, &vid_hdr);
	ubi_assert(&vid_hdr == ubi_get_vid_hdr(&vidb));

	err = ubi_io_read_vid_hdr(ubi, pnum, &vidb, 0);
	if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR &&
	    err != UBI_IO_FF){
		addr += ubi->vid_hdr_aloffset;
		err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
		if (err)
			goto error;
	}
	return 0;

error:
	/*
	 * The PEB contains a valid VID or EC header, but we cannot invalidate
	 * it. Supposedly the flash media or the driver is screwed up, so
	 * return an error.
	 */
	ubi_err(ubi, "cannot invalidate PEB %d, write returned %d", pnum, err);
	ubi_dump_flash(ubi, pnum, 0, ubi->peb_size);
	return -EIO;
}
Example #4
0
static void test_mtd_write_nooob(void **state)
{
	struct libmtd *lib = mock_libmtd_open();
	int mock_fd = 4;
	int eb = 0xE0;
	int offs = 64;
	int len = 64;
	off_t seek;
	char buf[64];
	memset(buf, 0xAA, len);
	struct mtd_dev_info mtd;
	memset(&mtd, 0, sizeof(mtd));
	mtd.bb_allowed = 1;
	mtd.eb_cnt = 1024;
	mtd.eb_size = 128;
	mtd.subpage_size = 64;
	seek = (off_t)eb * mtd.eb_size + offs;
	expect_lseek(seek, SEEK_SET, seek);
	expect_write(buf, len, len);
	int r = mtd_write(lib, &mtd, mock_fd, eb, offs, buf, len, NULL, 0, 0);
	assert_int_equal(r, 0);

	libmtd_close(lib);
	(void)state;
}
Example #5
0
int nandmtd_WriteChunkToNAND(struct yaffs_dev *dev, int chunkInNAND,
			     const u8 *data, const struct yaffs_spare *spare)
{
	struct mtd_info *mtd = (struct mtd_info *)(dev->driver_context);
	struct mtd_oob_ops ops;
	size_t dummy;
	int retval = 0;
	loff_t addr = ((loff_t) chunkInNAND) * dev->data_bytes_per_chunk;
	u8 spareAsBytes[8]; /* OOB */

	if (data && !spare)
		retval = mtd_write(mtd, addr, dev->data_bytes_per_chunk,
				&dummy, data);
	else if (spare) {
		if (dev->param.use_nand_ecc) {
			translate_spare2oob(spare, spareAsBytes);
			ops.mode = MTD_OPS_AUTO_OOB;
			ops.ooblen = 8; /* temp hack */
		} else {
			ops.mode = MTD_OPS_RAW;
			ops.ooblen = YAFFS_BYTES_PER_SPARE;
		}
		ops.len = data ? dev->data_bytes_per_chunk : ops.ooblen;
		ops.datbuf = (u8 *)data;
		ops.ooboffs = 0;
		ops.oobbuf = spareAsBytes;
		retval = mtd_write_oob(mtd, addr, &ops);
	}

	if (retval == 0)
		return YAFFS_OK;
	else
		return YAFFS_FAIL;
}
Example #6
0
static void test_mtd_write_withoob(void **state)
{
	struct libmtd *lib = mock_libmtd_open();
	int mock_fd = 4;
	int eb = 0xE0;
	int offs = 64;
	int len = 64;
	int oob_len = 64;
	uint8_t mode = 3;
	off_t seek;
	char buf[64], oob_data[64];
	struct mtd_dev_info mtd;
	struct mtd_write_req req;
	memset(buf, 0xAA, len);
	memset(oob_data, 0xBA, oob_len);
	memset(&mtd, 0, sizeof(mtd));
	memset(&req, 0, sizeof(req));
	mtd.bb_allowed = 1;
	mtd.eb_cnt = 1024;
	mtd.eb_size = 128;
	mtd.subpage_size = 64;
	seek = (off_t)eb * mtd.eb_size + offs;
	req.start = seek;
	req.len = len;
	req.ooblen = oob_len;
	req.usr_data = (uint64_t)(unsigned long)buf;
	req.usr_oob = (uint64_t)(unsigned long)oob_data;
	req.mode = mode;
	expect_ioctl(MEMWRITE, 0, &req);
	int r = mtd_write(lib, &mtd, mock_fd, eb, offs, buf, len, oob_data, oob_len, mode);
	assert_int_equal(r, 0);

	libmtd_close(lib);
	(void) state;
}
static inline int write_pattern(int ebnum, void *buf)
{
	int err;
	size_t written;
	loff_t addr = ebnum * mtd->erasesize;
	size_t len = mtd->erasesize;

	if (pgcnt) {
		addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
		len = pgcnt * pgsize;
	}
	err = mtd_write(mtd, addr, len, &written, buf);
	if (err) {
		pr_err("error %d while writing EB %d, written %zd"
		      " bytes\n", err, ebnum, written);
		return err;
	}
	if (written != len) {
		pr_info("written only %zd bytes of %zd, but no error"
		       " reported\n", written, len);
		return -EIO;
	}

	return 0;
}
static int mtd_blockdev_erase_write(struct vmm_request *r,
				    physical_addr_t off,
				    physical_size_t len,
				    struct mtd_info *mtd)
{
	struct erase_info info;
	unsigned int retlen = 0;

	info.mtd = mtd;
	info.addr = off;
	info.len = len;
	info.callback = mtd_blockdev_erase_callback;

	if (mtd_erase(mtd, &info)) {
		dev_err(&r->bdev->dev, "Erasing at 0x%08X failed\n", off);
		return VMM_EIO;
	}

	if (mtd_write(mtd, off, len, &retlen, r->data)) {
		dev_err(&r->bdev->dev, "Writing at 0x%08X failed\n", off);
		return VMM_EIO;
	}

	if (retlen < len) {
		dev_warn(&r->bdev->dev, "Only 0x%X/0x%X bytes have been "
			 "written at 0x%08X\n", retlen, len, off);
		return VMM_EIO;
	}
	return VMM_OK;
}
Example #9
0
static int write_eraseblock2(int ebnum)
{
	size_t written;
	int err = 0, k;
	loff_t addr = ebnum * mtd->erasesize;

	for (k = 1; k < 33; ++k) {
		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
			break;
		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
		err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
		if (unlikely(err || written != subpgsize * k)) {
			pr_err("error: write failed at %#llx\n",
			       (long long)addr);
			if (written != subpgsize) {
				pr_err("  write size: %#x\n",
				       subpgsize * k);
				pr_err("  written: %#08zx\n",
				       written);
			}
			return err ? err : -1;
		}
		addr += subpgsize * k;
	}

	return err;
}
static int erasetest(void)
{
	size_t read, written;
	int err = 0, i, ebnum, ok = 1;
	loff_t addr0;

	printk(PRINT_PREF "erasetest\n");

	ebnum = 0;
	addr0 = 0;
	for (i = 0; i < ebcnt && bbt[i]; ++i) {
		addr0 += mtd->erasesize;
		ebnum += 1;
	}

	printk(PRINT_PREF "erasing block %d\n", ebnum);
	err = erase_eraseblock(ebnum);
	if (err)
		return err;

	printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
	set_random_data(writebuf, pgsize);
	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
	if (err || written != pgsize) {
		printk(PRINT_PREF "error: write failed at %#llx\n",
		       (long long)addr0);
		return err ? err : -1;
	}

	printk(PRINT_PREF "erasing block %d\n", ebnum);
	err = erase_eraseblock(ebnum);
	if (err)
		return err;

	printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
	err = mtd_read(mtd, addr0, pgsize, &read, twopages);
	if (mtd_is_bitflip(err))
		err = 0;
	if (err || read != pgsize) {
		printk(PRINT_PREF "error: read failed at %#llx\n",
		       (long long)addr0);
		return err ? err : -1;
	}

	printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n",
	       ebnum);
	for (i = 0; i < pgsize; ++i)
		if (twopages[i] != 0xff) {
			printk(PRINT_PREF "verifying all 0xff failed at %d\n",
			       i);
			errcnt += 1;
			ok = 0;
			break;
		}

	if (ok && !err)
		printk(PRINT_PREF "erasetest ok\n");

	return err;
}
Example #11
0
static void mtdoops_write(struct mtdoops_context *cxt, int panic)
{
	struct mtd_info *mtd = cxt->mtd;
	size_t retlen;
	u32 *hdr;
	int ret;

	/* Add mtdoops header to the buffer */
	hdr = cxt->oops_buf;
	hdr[0] = cxt->nextcount;
	hdr[1] = MTDOOPS_KERNMSG_MAGIC;

	if (panic) {
		ret = mtd_panic_write(mtd, cxt->nextpage * record_size,
				      record_size, &retlen, cxt->oops_buf);
		if (ret == -EOPNOTSUPP) {
			printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
			return;
		}
	} else
		ret = mtd_write(mtd, cxt->nextpage * record_size,
				record_size, &retlen, cxt->oops_buf);

	if (retlen != record_size || ret < 0)
		printk(KERN_ERR "mtdoops: write failure at %ld (%td of %ld written), error %d\n",
		       cxt->nextpage * record_size, retlen, record_size, ret);
	mark_page_used(cxt, cxt->nextpage);
	memset(cxt->oops_buf, 0xff, record_size);

	mtdoops_inc_counter(cxt);
}
Example #12
0
int bc_ll_set_rootfs_healthy( struct bootconfig * bc, unsigned int block )
{
        int    err;
        char  *page;
        struct btblock * curr;

        if (! initialised) {
                bc_log( LOG_ERR, "Internal error: called before initialisation!\n");
                exit(1);
        }

        curr = &bc->blocks[ block ];

        if ( curr->rootfs.n_healthy == 1)
        {
                curr->rootfs.n_healthy = 0;
                page = malloc( bc->info.min_io_size );
                if( NULL == page )
                {
                        bc_log( LOG_ERR, "Error #%d malloc()ing %d bytes: %s.\n",errno, bc->info.min_io_size, strerror(errno));
                        return -1;
                }

                memset( page, 0xFF, bc->info.min_io_size );
                memcpy( page, &bc->blocks[ block ], sizeof( *bc->blocks ) );
                err = mtd_write( bc->mtd, &bc->info, bc->fd, block, 0, page, bc->info.min_io_size , NULL, 0, 0 );
                free( page );

                if (0 > err)
                        return 1;
        }

	return 0;

}
Example #13
0
static int _do_write_bootblock( struct bootconfig * bc, unsigned int block_idx )
{
    int    err;
    char  *page;
   
    err = mtd_erase( bc->mtd, &bc->info, bc->fd, block_idx );
    if (0 > err)
        return 1;

    page = malloc( bc->info.min_io_size );
    if( NULL == page ) {
        bc_log( LOG_ERR, "Error #%d malloc()ing %d bytes: %s.\n", 
                errno, bc->info.min_io_size, strerror(errno));
        return -1;
    }

    memset( page, 0xFF, bc->info.min_io_size );
    memcpy( page, &bc->blocks[ block_idx ], sizeof( *bc->blocks ) );
    err = mtd_write( bc->mtd, &bc->info, bc->fd, block_idx, 0,
                     page, bc->info.min_io_size , NULL, 0, 0 );
    free( page );

    if (0 > err)
        return 1;

    return 0;
}
int mtd_torture(const struct mtd_dev_info *mtd, int fd, int eb)
{
	int err, i, patt_count;
	void *buf;

	normsg("run torture test for PEB %d", eb);
	patt_count = ARRAY_SIZE(patterns);

	buf = malloc(mtd->eb_size);
	if (!buf) {
		errmsg("cannot allocate %d bytes of memory", mtd->eb_size);
		return -1;
	}

	for (i = 0; i < patt_count; i++) {
		err = mtd_erase(mtd, fd, eb);
		if (err)
			goto out;

		/* Make sure the PEB contains only 0xFF bytes */
		err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
		if (err)
			goto out;

		err = check_pattern(buf, 0xFF, mtd->eb_size);
		if (err == 0) {
			errmsg("erased PEB %d, but a non-0xFF byte found", eb);
			errno = EIO;
			goto out;
		}

		/* Write a pattern and check it */
		memset(buf, patterns[i], mtd->eb_size);
		err = mtd_write(mtd, fd, eb, 0, buf, mtd->eb_size);
		if (err)
			goto out;

		memset(buf, ~patterns[i], mtd->eb_size);
		err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
		if (err)
			goto out;

		err = check_pattern(buf, patterns[i], mtd->eb_size);
		if (err == 0) {
			errmsg("pattern %x checking failed for PEB %d",
				patterns[i], eb);
			errno = EIO;
			goto out;
		}
	}

	err = 0;
	normsg("PEB %d passed torture test, do not mark it a bad", eb);

out:
	free(buf);
	return -1;
}
Example #15
0
void images_write(Image* image, void* data, unsigned int length, int encrypt) {
	bufferPrintf("images_write(%x, %x, %x)\r\n", image, data, length);
	if(image == NULL)
		return;

	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	uint32_t padded = length;
	if((length & 0xF) != 0) {
		padded = (padded & ~0xF) + 0x10;
	}

	if(image->next != NULL && (image->offset + sizeof(Img2Header) + padded) >= image->next->offset) {
		bufferPrintf("**ABORTED** requested length greater than available space.\r\n");
		return;
	}

	uint32_t totalLen = sizeof(Img2Header) + padded;
	uint8_t* writeBuffer = (uint8_t*) malloc(totalLen);

	mtd_read(dev, writeBuffer, image->offset, sizeof(Img2Header));

	memcpy(writeBuffer + sizeof(Img2Header), data, length);

	if(encrypt)
		aes_838_encrypt(writeBuffer + sizeof(Img2Header), padded, NULL);

	Img2Header* header = (Img2Header*) writeBuffer;
	header->dataLen = length;
	header->dataLenPadded = padded;

	calculateDataHash(writeBuffer + sizeof(Img2Header), padded, header->dataHash);

	uint32_t checksum = 0;
	crc32(&checksum, writeBuffer, 0x64);
	header->header_checksum = checksum;

	calculateHash(header, header->hash);

	bufferPrintf("mtd_write(0x%p, %x, %x, %x)\r\n", dev, writeBuffer, image->offset, totalLen);

	mtd_write(dev, writeBuffer, image->offset, totalLen);

	bufferPrintf("mtd_write(0x%p, %x, %x, %x) done\r\n", dev, writeBuffer, image->offset, totalLen);

	free(writeBuffer);

	mtd_finish(dev);

	images_release();
	images_setup();

}
Example #16
0
int main(void)
{
	while(1){
		mtd_erase();
		mtd_write();
		sleep(1);
	}
	
	return 0;
}
Example #17
0
static ssize_t mtd_op_write(struct cdev* cdev, const void *buf, size_t _count,
			  loff_t _offset, ulong flags)
{
	struct mtd_info *mtd = cdev->priv;
	size_t retlen;
	int ret;

	ret = mtd_write(mtd, _offset, _count, &retlen, buf);

	return ret ? ret : _count;
}
Example #18
0
void images_from_template(Image* image, uint32_t type, int index, void* dataBuffer, unsigned int len, int encrypt) {
	if(image == NULL)
		return;

	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	uint32_t offset = MaxOffset + (SegmentSize - (MaxOffset % SegmentSize));
	uint32_t padded = len;
	if((len & 0xF) != 0) {
		padded = (padded & ~0xF) + 0x10;
	}

	uint32_t totalLen = sizeof(Img2Header) + padded;
	uint8_t* buffer = (uint8_t*) malloc(totalLen);

	mtd_read(dev, buffer, image->offset, sizeof(Img2Header));
	Img2Header* header = (Img2Header*) buffer;
	header->imageType = type;

	if(index >= 0)
		header->index = index;

	header->dataLen = len;
	header->dataLenPadded = padded;

	memcpy(buffer + sizeof(Img2Header), dataBuffer, len);
	if(encrypt)
		aes_838_encrypt(buffer + sizeof(Img2Header), padded, NULL);

	calculateDataHash(buffer + sizeof(Img2Header), image->padded, header->dataHash);

	uint32_t checksum = 0;
	crc32(&checksum, buffer, 0x64);
	header->header_checksum = checksum;

	calculateHash(header, header->hash);

	mtd_write(dev, buffer, offset, totalLen);

	free(buffer);

	mtd_finish(dev);

	images_release();
	images_setup();
}
Example #19
0
int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
		const void *buf)
{
	size_t written;
	int err;

	err = mtd_write(mtd, addr, size, &written, buf);
	if (!err && written != size)
		err = -EIO;
	if (err)
		pr_err("error: write failed at %#llx\n", addr);

	return err;
}
static int write_eraseblock(int ebnum)
{
	int err = 0;
	size_t written;
	loff_t addr = ebnum * mtd->erasesize;

	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
	cond_resched();
	err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
	if (err || written != mtd->erasesize)
		pr_err("error: write failed at %#llx\n",
		       (long long)addr);

	return err;
}
static int write_eraseblock(int ebnum)
{
	int err = 0;
	size_t written;
	loff_t addr = ebnum * mtd->erasesize;

	set_random_data(writebuf, mtd->erasesize);
	cond_resched();
	err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
	if (err || written != mtd->erasesize)
		printk(PRINT_PREF "error: write failed at %#llx\n",
		       (long long)addr);

	return err;
}
static int write_eraseblock(int ebnum)
{
	size_t written;
	int err = 0;
	loff_t addr = ebnum * mtd->erasesize;

	err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf);
	if (err || written != mtd->erasesize) {
		printk(PRINT_PREF "error: write failed at %#llx\n", addr);
		if (!err)
			err = -EINVAL;
	}

	return err;
}
Example #23
0
void images_append(void* data, int len) {
	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	if(MaxOffset >= 0xfc000 || (MaxOffset + len) >= 0xfc000) {
		bufferPrintf("**ABORTED** Writing image of size %d at %x would overflow NOR!\r\n", len, MaxOffset);
	} else {
		mtd_write(dev, data, MaxOffset, len);

		// Destroy any following image
		if((MaxOffset + len) < 0xfc000) {
			uint8_t zero = 0;
			mtd_write(dev, &zero, MaxOffset + len, 1);
		}

		images_release();
		images_setup();
	}

	mtd_finish(dev);
}
Example #24
0
static int _dev_write(const struct lfs_config *c, lfs_block_t block,
                  lfs_off_t off, const void *buffer, lfs_size_t size)
{
    littlefs_desc_t *fs = c->context;
    mtd_dev_t *mtd = fs->dev;

    DEBUG("lfs_write: c=%p, block=%" PRIu32 ", off=%" PRIu32 ", buf=%p, size=%" PRIu32 "\n",
          (void *)c, block, off, buffer, size);

    int ret = mtd_write(mtd, buffer, ((fs->base_addr + block) * c->block_size) + off, size);
    if (ret >= 0) {
        return 0;
    }

    return ret;
}
Example #25
0
int saveenv(void)
{
    env_t	env_new;
    ssize_t	len;
    char	*res;
    struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
    struct onenand_chip *this = &onenand_chip;
#endif
    loff_t	env_addr = CONFIG_ENV_ADDR;
    size_t	retlen;
    struct erase_info instr = {
        .callback	= NULL,
    };

    res = (char *)&env_new.data;
    len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
    if (len < 0) {
        error("Cannot export environment: errno = %d\n", errno);
        return 1;
    }
    env_new.crc = crc32(0, env_new.data, ENV_SIZE);

    instr.len = CONFIG_ENV_SIZE;
#ifdef CONFIG_ENV_ADDR_FLEX
    if (FLEXONENAND(this)) {
        env_addr = CONFIG_ENV_ADDR_FLEX;
        instr.len = CONFIG_ENV_SIZE_FLEX;
        instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
                      1 : 0;
    }
#endif
    instr.addr = env_addr;
    instr.mtd = mtd;
    if (mtd_erase(mtd, &instr)) {
        printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
        return 1;
    }

    if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
                  (u_char *)&env_new)) {
        printf("OneNAND: write failed at 0x%llx\n", instr.addr);
        return 2;
    }

    return 0;
}
Example #26
0
static int erase_write (struct mtd_info *mtd, unsigned long pos,
			int len, const char *buf)
{
	struct erase_info erase;
	DECLARE_WAITQUEUE(wait, current);
	wait_queue_head_t wait_q;
	size_t retlen;
	int ret;

	/*
	 * First, let's erase the flash block.
	 */

	init_waitqueue_head(&wait_q);
	erase.mtd = mtd;
	erase.callback = erase_callback;
	erase.addr = pos;
	erase.len = len;
	erase.priv = (u_long)&wait_q;

	set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue(&wait_q, &wait);

	ret = mtd_erase(mtd, &erase);
	if (ret) {
		set_current_state(TASK_RUNNING);
		remove_wait_queue(&wait_q, &wait);
		printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] "
				     "on \"%s\" failed\n",
			pos, len, mtd->name);
		return ret;
	}

	schedule();  /* Wait for erase to finish. */
	remove_wait_queue(&wait_q, &wait);

	/*
	 * Next, write the data to flash.
	 */

	ret = mtd_write(mtd, pos, len, &retlen, buf);
	if (ret)
		return ret;
	if (retlen != len)
		return -EIO;
	return 0;
}
Example #27
0
static int
concat_write(struct mtd_info *mtd, loff_t to, size_t len,
	     size_t * retlen, const u_char * buf)
{
	struct mtd_concat *concat = CONCAT(mtd);
	int err = -EINVAL;
	int i;

	if (!(mtd->flags & MTD_WRITEABLE))
		return -EROFS;

	*retlen = 0;

	for (i = 0; i < concat->num_subdev; i++) {
		struct mtd_info *subdev = concat->subdev[i];
		size_t size, retsize;

		if (to >= subdev->size) {
			size = 0;
			to -= subdev->size;
			continue;
		}
		if (to + len > subdev->size)
			size = subdev->size - to;
		else
			size = len;

		if (!(subdev->flags & MTD_WRITEABLE))
			err = -EROFS;
		else
			err = mtd_write(subdev, to, size, &retsize, buf);

		if (err)
			break;

		*retlen += retsize;
		len -= size;
		if (len == 0)
			break;

		err = -EINVAL;
		buf += size;
		to = 0;
	}
	return err;
}
static int bitfliptest_do_write(void)
{
	int err = 0;
	loff_t addr = 0;
	size_t written = 0;
	int eb = bitfliptest_rand_eb();
	unsigned int offs = 0, len = 0;

	offs = offsets[eb];
	if (offs >= mtd->erasesize) {
		err = mtd_test_erase_eraseblock(eb, 0);
		if (err)
			return err;
		offs = offsets[eb] = 0;
	}
	len = bitfliptest_rand_len(offs);
	len = ((len + pgsize - 1) / pgsize) * pgsize;
	if (offs + len > mtd->erasesize) {
		if (bbt[eb + 1])
			len = mtd->erasesize - offs;
		else {
//			pr_info("erase, block: %d\n", eb + 1);
			err = mtd_test_erase_eraseblock(eb + 1, 0);
			if (err)
				return err;
			offsets[eb + 1] = 0;
		}
	}
	addr = eb * mtd->erasesize + offs;
//	pr_info("write, addr: 0x%.8x len: %d\n", (unsigned int)addr, len);
	err = mtd_write(mtd, addr, len, &written, writebuf);
	if (unlikely(err || written != len)) {
		pr_err("error: write failed at 0x%llx\n",
		       (long long)addr);
		if (!err)
			err = -EINVAL;
		return err;
	}
	offs += len;
	while (offs > mtd->erasesize) {
		offsets[eb++] = mtd->erasesize;
		offs -= mtd->erasesize;
	}
	offsets[eb] = offs;
	return 0;
}
Example #29
0
static int cmd_flash_write(struct vmm_chardev *cdev,
			   int  argc,
			   char **argv)
{
	int err = VMM_OK;
	int idx = 0;
	size_t retlen = 0;
	flash_op op;
	u_char *buf = NULL;

	if (VMM_OK != (err = flash_args_common(cdev, argc, argv, &op))) {
		return err;
	}

	vmm_cprintf(cdev, "Before writing, the %s block at 0x%08X must have "
		    "been erased?\n", op.mtd->name,
		    op.offset & ~op.mtd->erasesize_mask);
	if (!flash_question(cdev)) {
		vmm_cprintf(cdev, "Exiting...\n");
		return VMM_OK;
	}

	if (argc - 4 <= 0) {
		vmm_cprintf(cdev, "Nothing to write, exiting\n");
		return VMM_OK;
	}

	if (NULL == (buf = vmm_malloc(argc - 5))) {
		return VMM_ENOMEM;
	}

	for (idx = 0; idx < argc - 4; ++idx) {
		buf[idx] = strtoull(argv[idx + 4], NULL, 16);
		vmm_cprintf(cdev, "Writing at 0x%08X 0x%02X\n",
			    op.offset + idx, buf[idx]);
	}
	if (0 != mtd_write(op.mtd, op.offset, argc - 4, &retlen, buf)) {
		vmm_cprintf(cdev, "Failed to write %s at 0x%08X\n",
			    op.mtd->name, op.offset);
	}
	vmm_free(buf);

	return err;
}
Example #30
0
static int env_onenand_save(void)
{
	env_t	env_new;
	int ret;
	struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
	struct onenand_chip *this = &onenand_chip;
#endif
	loff_t	env_addr = CONFIG_ENV_ADDR;
	size_t	retlen;
	struct erase_info instr = {
		.callback	= NULL,
	};

	ret = env_export(&env_new);
	if (ret)
		return ret;

	instr.len = CONFIG_ENV_SIZE;
#ifdef CONFIG_ENV_ADDR_FLEX
	if (FLEXONENAND(this)) {
		env_addr = CONFIG_ENV_ADDR_FLEX;
		instr.len = CONFIG_ENV_SIZE_FLEX;
		instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
				1 : 0;
	}
#endif
	instr.addr = env_addr;
	instr.mtd = mtd;
	if (mtd_erase(mtd, &instr)) {
		printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
		return 1;
	}

	if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
			(u_char *)&env_new)) {
		printf("OneNAND: write failed at 0x%llx\n", instr.addr);
		return 2;
	}

	return 0;
}