Add support for the byte write method to MTD partition logic; Beef up the MTD partition test -- and fix resulting bugs detected
This commit is contained in:
parent
0d1cf112cf
commit
4f15d37b62
@ -4659,3 +4659,5 @@
|
|||||||
* arch/arm/src/kl/chip/kl25z128_pinmux.h: Corrections fo the
|
* arch/arm/src/kl/chip/kl25z128_pinmux.h: Corrections fo the
|
||||||
pin multiplexing definitions from Alan Carvalho de Assis
|
pin multiplexing definitions from Alan Carvalho de Assis
|
||||||
(2013-5-2).
|
(2013-5-2).
|
||||||
|
* drivers/mtd/mtd_partition.c: Fix a few bugs and add support for the
|
||||||
|
(option) byte write method (2013-5-3).
|
||||||
|
@ -97,7 +97,7 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, si
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the file position into a sector number an offset. */
|
/* Convert the file position into a sector number and offset. */
|
||||||
|
|
||||||
sector = offset / bch->sectsize;
|
sector = offset / bch->sectsize;
|
||||||
sectoffset = offset - sector * bch->sectsize;
|
sectoffset = offset - sector * bch->sectsize;
|
||||||
|
@ -221,8 +221,8 @@ static ssize_t ftl_flush(FAR void *priv, FAR const uint8_t *buffer,
|
|||||||
* alignment.
|
* alignment.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mask = dev->blkper - 1;
|
mask = dev->blkper - 1;
|
||||||
alignedblock = (startblock + mask) & ~mask;
|
alignedblock = (startblock + mask) & ~mask;
|
||||||
|
|
||||||
/* Handle partial erase blocks before the first unaligned block */
|
/* Handle partial erase blocks before the first unaligned block */
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ static ssize_t ftl_flush(FAR void *priv, FAR const uint8_t *buffer,
|
|||||||
|
|
||||||
memcpy(dev->eblock + offset, buffer, nbytes);
|
memcpy(dev->eblock + offset, buffer, nbytes);
|
||||||
|
|
||||||
/* And write the erase back to flash */
|
/* And write the erase block back to flash */
|
||||||
|
|
||||||
nxfrd = MTD_BWRITE(dev->mtd, rwblock, dev->blkper, dev->eblock);
|
nxfrd = MTD_BWRITE(dev->mtd, rwblock, dev->blkper, dev->eblock);
|
||||||
if (nxfrd != dev->blkper)
|
if (nxfrd != dev->blkper)
|
||||||
@ -333,7 +333,7 @@ static ssize_t ftl_flush(FAR void *priv, FAR const uint8_t *buffer,
|
|||||||
{
|
{
|
||||||
/* Read the full erase block into the buffer */
|
/* Read the full erase block into the buffer */
|
||||||
|
|
||||||
nxfrd = MTD_BREAD(dev->mtd, alignedblock, dev->blkper, dev->eblock);
|
nxfrd = MTD_BREAD(dev->mtd, alignedblock, dev->blkper, dev->eblock);
|
||||||
if (nxfrd != dev->blkper)
|
if (nxfrd != dev->blkper)
|
||||||
{
|
{
|
||||||
fdbg("Read erase block %d failed: %d\n", alignedblock, nxfrd);
|
fdbg("Read erase block %d failed: %d\n", alignedblock, nxfrd);
|
||||||
|
@ -46,8 +46,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/fs/ioctl.h>
|
|
||||||
#include <nuttx/mtd.h>
|
#include <nuttx/mtd.h>
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <nuttx/fs/ioctl.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
@ -95,12 +96,50 @@ static ssize_t part_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t n
|
|||||||
FAR const uint8_t *buf);
|
FAR const uint8_t *buf);
|
||||||
static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
|
static ssize_t part_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
||||||
|
FAR const uint8_t *buffer);
|
||||||
|
#endif
|
||||||
static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: part_blockcheck
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check if the provided block offset lies within the partition
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static bool part_blockcheck(FAR struct mtd_partition_s *priv, off_t block)
|
||||||
|
{
|
||||||
|
off_t partsize;
|
||||||
|
|
||||||
|
partsize = priv->neraseblocks * priv->blkpererase;
|
||||||
|
return block < partsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: part_bytecheck
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check if the provided byte offset lies within the partition
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static bool part_bytecheck(FAR struct mtd_partition_s *priv, off_t byoff)
|
||||||
|
{
|
||||||
|
off_t erasesize;
|
||||||
|
off_t readend;
|
||||||
|
|
||||||
|
erasesize = priv->blocksize * priv->blkpererase;
|
||||||
|
readend = (byoff + erasesize - 1) / erasesize;
|
||||||
|
return readend < priv->neraseblocks;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -117,14 +156,13 @@ static int part_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
size_t nblocks)
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
||||||
off_t partsize;
|
off_t eoffset;
|
||||||
|
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
|
|
||||||
/* Make sure that erase would not extend past the end of the partition */
|
/* Make sure that erase would not extend past the end of the partition */
|
||||||
|
|
||||||
partsize = priv->neraseblocks * priv->blkpererase;
|
if (!part_blockcheck(priv, startblock + nblocks - 1))
|
||||||
if ((startblock + nblocks) > partsize)
|
|
||||||
{
|
{
|
||||||
fdbg("ERROR: Read beyond the end of the partition\n");
|
fdbg("ERROR: Read beyond the end of the partition\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
@ -132,10 +170,14 @@ static int part_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
|
|
||||||
/* Just add the partition offset to the requested block and let the
|
/* Just add the partition offset to the requested block and let the
|
||||||
* underlying MTD driver perform the erase.
|
* underlying MTD driver perform the erase.
|
||||||
|
*
|
||||||
|
* NOTE: the offset here is in units of erase blocks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return priv->parent->erase(priv->parent, startblock + priv->firstblock,
|
eoffset = priv->firstblock / priv->blkpererase;
|
||||||
nblocks);
|
DEBUGASSERT(eoffset * priv->blkpererase == priv->firstblock);
|
||||||
|
|
||||||
|
return priv->parent->erase(priv->parent, startblock + eoffset, nblocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -150,14 +192,12 @@ static ssize_t part_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
size_t nblocks, FAR uint8_t *buf)
|
size_t nblocks, FAR uint8_t *buf)
|
||||||
{
|
{
|
||||||
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
||||||
off_t partsize;
|
|
||||||
|
|
||||||
DEBUGASSERT(priv && (buf || nblocks == 0));
|
DEBUGASSERT(priv && (buf || nblocks == 0));
|
||||||
|
|
||||||
/* Make sure that read would not extend past the end of the partition */
|
/* Make sure that read would not extend past the end of the partition */
|
||||||
|
|
||||||
partsize = priv->neraseblocks * priv->blkpererase;
|
if (!part_blockcheck(priv, startblock + nblocks - 1))
|
||||||
if ((startblock + nblocks) > partsize)
|
|
||||||
{
|
{
|
||||||
fdbg("ERROR: Read beyond the end of the partition\n");
|
fdbg("ERROR: Read beyond the end of the partition\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
@ -183,14 +223,12 @@ static ssize_t part_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
size_t nblocks, FAR const uint8_t *buf)
|
size_t nblocks, FAR const uint8_t *buf)
|
||||||
{
|
{
|
||||||
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
||||||
off_t partsize;
|
|
||||||
|
|
||||||
DEBUGASSERT(priv && (buf || nblocks == 0));
|
DEBUGASSERT(priv && (buf || nblocks == 0));
|
||||||
|
|
||||||
/* Make sure that write would not extend past the end of the partition */
|
/* Make sure that write would not extend past the end of the partition */
|
||||||
|
|
||||||
partsize = priv->neraseblocks * priv->blkpererase;
|
if (!part_blockcheck(priv, startblock + nblocks - 1))
|
||||||
if ((startblock + nblocks) > partsize)
|
|
||||||
{
|
{
|
||||||
fdbg("ERROR: Write beyond the end of the partition\n");
|
fdbg("ERROR: Write beyond the end of the partition\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
@ -216,8 +254,6 @@ static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
||||||
off_t erasesize;
|
|
||||||
off_t readend;
|
|
||||||
off_t newoffset;
|
off_t newoffset;
|
||||||
|
|
||||||
DEBUGASSERT(priv && (buffer || nbytes == 0));
|
DEBUGASSERT(priv && (buffer || nbytes == 0));
|
||||||
@ -228,10 +264,7 @@ static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
{
|
{
|
||||||
/* Make sure that read would not extend past the end of the partition */
|
/* Make sure that read would not extend past the end of the partition */
|
||||||
|
|
||||||
erasesize = priv->blocksize * priv->blkpererase;
|
if (!part_bytecheck(priv, offset + nbytes - 1))
|
||||||
readend = (offset + nbytes + erasesize - 1) / erasesize;
|
|
||||||
|
|
||||||
if (readend > priv->neraseblocks)
|
|
||||||
{
|
{
|
||||||
fdbg("ERROR: Read beyond the end of the partition\n");
|
fdbg("ERROR: Read beyond the end of the partition\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
@ -250,6 +283,45 @@ static ssize_t part_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: part_write
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
|
static ssize_t part_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
||||||
|
FAR const uint8_t *buffer)
|
||||||
|
{
|
||||||
|
FAR struct mtd_partition_s *priv = (FAR struct mtd_partition_s *)dev;
|
||||||
|
off_t newoffset;
|
||||||
|
|
||||||
|
DEBUGASSERT(priv && (buffer || nbytes == 0));
|
||||||
|
|
||||||
|
/* Does the underlying MTD device support the write method? */
|
||||||
|
|
||||||
|
if (priv->parent->write)
|
||||||
|
{
|
||||||
|
/* Make sure that write would not extend past the end of the partition */
|
||||||
|
|
||||||
|
if (!part_bytecheck(priv, offset + nbytes - 1))
|
||||||
|
{
|
||||||
|
fdbg("ERROR: Write beyond the end of the partition\n");
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just add the partition offset to the requested block and let the
|
||||||
|
* underlying MTD driver perform the write.
|
||||||
|
*/
|
||||||
|
|
||||||
|
newoffset = offset + priv->firstblock * priv->blocksize;
|
||||||
|
return priv->parent->write(priv->parent, newoffset, nbytes, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The underlying MTD driver does not support the write() method */
|
||||||
|
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: part_ioctl
|
* Name: part_ioctl
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user