From 44ecc1c216007272a6f99a104a71c9d410969d9e Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Thu, 4 Aug 2022 10:04:21 -0400 Subject: [PATCH] fw_setenv: fix bug when SPI flash write size != sector size Some SPI flash have a write size that is different (smaller) than the sector size. For example, the sst25vf016b has an erase size of 4096, but a write size of 1 byte. For this flash device, the write() function will be called with a size equal to the sector size of 4096, and the return value will incorrectly be set to 4096, indicating that 4096 bytes have been written to the device. However, after inspecting the flash content, only the first byte is written to the device, and the remaining 4095 bytes are all 0xFF. Fix this incorrect behavior by adapting mtdwrite() to use the write size obtained from the MEMGETINFO ioctl when writing data. Signed-off-by: Hugo Villeneuve Reviewed-by: Stefano Babic --- src/uboot_env.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/uboot_env.c b/src/uboot_env.c index 76e2619..c5eefe7 100644 --- a/src/uboot_env.c +++ b/src/uboot_env.c @@ -712,6 +712,8 @@ static int mtdwrite(struct uboot_flash_env *dev, void *data) sectors = dev->envsectors ? dev->envsectors : 1; buf = data; while (count > 0) { + int blockcount; + erase.start = start; skip = is_nand_badblock(dev, start); @@ -742,17 +744,26 @@ static int mtdwrite(struct uboot_flash_env *dev, void *data) ret =-EIO; goto devwrite_out; } - if (lseek(dev->fd, start, SEEK_SET) < 0) { - ret =-EIO; - goto devwrite_out; - } - if (write(dev->fd, buf, blocksize) != blocksize) { - ret =-EIO; - goto devwrite_out; + + blockcount = blocksize; + + /* writesize can be different than the sector size. */ + + while (blockcount > 0) { + if (lseek(dev->fd, start, SEEK_SET) < 0) { + ret =-EIO; + goto devwrite_out; + } + if (write(dev->fd, buf, dev->mtdinfo.writesize) != dev->mtdinfo.writesize) { + ret =-EIO; + goto devwrite_out; + } + + blockcount -= dev->mtdinfo.writesize; + start += dev->mtdinfo.writesize; + buf += dev->mtdinfo.writesize; } MTDLOCK(dev, &erase); - start += dev->sectorsize; - buf += blocksize; count -= blocksize; ret += blocksize; }