mtd/progmem: fix incorrect target address calculation
authorHeesub Shin <heesub.shin@samsung.com>
Sat, 18 Mar 2017 06:07:57 +0000 (15:07 +0900)
committerHeesub Shin <heesub.shin@samsung.com>
Mon, 17 Apr 2017 09:55:39 +0000 (18:55 +0900)
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.

Change-Id: I6b3e731c48b707ecc8274b73723387fb92adf2aa
Signed-off-by: Heesub Shin <heesub.shin@samsung.com>
os/fs/driver/mtd/mtd_progmem.c

index a6dbdf4..eb9ae8d 100644 (file)
@@ -245,14 +245,18 @@ static ssize_t progmem_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_
 
 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 block;
 
        /* 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);
+       block = offset >> priv->blkshift;
+       src = (FAR const uint8_t *)up_progmem_getaddress(block) +
+                               (offset & ((1 << priv->blkshift) - 1));
        memcpy(buffer, src, nbytes);
        return nbytes;
 }
@@ -271,12 +275,15 @@ static ssize_t progmem_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nby
 {
        FAR struct progmem_dev_s *priv = (FAR struct progmem_dev_s *)dev;
        ssize_t result;
+       off_t block;
 
        /* 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);
+       block = offset >> priv->blkshift;
+       result = up_progmem_write(up_progmem_getaddress(block) +
+                       (offset & ((1 << priv->blkshift) - 1)), buffer, nbytes);
        return result < 0 ? result : nbytes;
 }
 #endif