From a10735b50d781f5006ed0dd9ac464bb8582dee73 Mon Sep 17 00:00:00 2001 From: Heesub Shin Date: Sat, 18 Mar 2017 22:27:06 +0900 Subject: [PATCH] mtd/progmem: fix incorrect target address calculation progmem_read/write() is incorrectly calculating the target address, expecting the offset argument is given in a block number. This is completely wrong and as a result invalid flash region is accessed. Byte-oriented read/write interfaces of mtd device accept the target address in a byte offset, not a block number. Signed-off-by: Heesub Shin --- drivers/mtd/mtd_progmem.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/mtd_progmem.c b/drivers/mtd/mtd_progmem.c index 3d76402fd8..9785a4c360 100644 --- a/drivers/mtd/mtd_progmem.c +++ b/drivers/mtd/mtd_progmem.c @@ -245,14 +245,18 @@ static ssize_t progmem_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, static ssize_t progmem_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, FAR uint8_t *buffer) { + FAR struct progmem_dev_s *priv = (FAR struct progmem_dev_s *)dev; FAR const uint8_t *src; + off_t startblock; /* Read the specified bytes into the provided user buffer and return * status (The positive, number of bytes actually read or a negated * errno) */ - src = (FAR const uint8_t *)up_progmem_getaddress(offset); + startblock = offset >> priv->blkshift; + src = (FAR const uint8_t *)up_progmem_getaddress(startblock) + + (offset & ((1 << priv->blkshift) - 1)); memcpy(buffer, src, nbytes); return nbytes; } @@ -271,13 +275,16 @@ static ssize_t progmem_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes, FAR const uint8_t *buffer) { FAR struct progmem_dev_s *priv = (FAR struct progmem_dev_s *)dev; + off_t startblock; ssize_t result; /* Write the specified blocks from the provided user buffer and return status * (The positive, number of blocks actually written or a negated errno) */ - result = up_progmem_write(up_progmem_getaddress(offset), buffer, nbytes); + startblock = offset >> priv->blkshift; + result = up_progmem_write(up_progmem_getaddress(startblock) + + (offset & ((1 << priv->blkshift) - 1)), buffer, nbytes); return result < 0 ? result : nbytes; } #endif