Add basic NXFFS read logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3546 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
478aaafea4
commit
e4e2f34200
6 changed files with 234 additions and 72 deletions
|
|
@ -496,19 +496,15 @@ extern int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
|
|||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the current volume
|
||||
* block - The first logical block to write
|
||||
* nblocks - The number of logical blocks to be write.
|
||||
*
|
||||
* Returned Value:
|
||||
* Negated errnos are returned only in the case of MTD reported failures.
|
||||
* Nothing in the volume data itself will generate errors.
|
||||
*
|
||||
* Defined in nxffs_cache.c
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume, off_t block,
|
||||
uint8_t nblocks);
|
||||
extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_ioseek
|
||||
|
|
@ -594,29 +590,6 @@ extern int nxffs_getc(FAR struct nxffs_volume_s *volume);
|
|||
extern ssize_t nxffs_rddata(FAR struct nxffs_volume_s *volume,
|
||||
FAR uint8_t *buffer, size_t buflen);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_wrdata
|
||||
*
|
||||
* Description:
|
||||
* Write a sequence of data bytes into volume cache memory. Nothing is
|
||||
* actually written to FLASH! This function allows the data in the formatted
|
||||
* FLASH blocks to be read as a continuous byte stream, skipping over bad
|
||||
* blocks and block headers as necessary.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume.
|
||||
* buffer - A pointer to memory to containing the data to write to FLASH.
|
||||
* buflen - The maximum number of bytes to write to FLASH.
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of bytes written is returned on success. Otherwise, a negated
|
||||
* errno indicating the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
extern ssize_t nxffs_wrdata(FAR struct nxffs_volume_s *volume,
|
||||
FAR const uint8_t *buffer, size_t buflen);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_freeentry
|
||||
*
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
|
|||
if (nxfrd != nblocks)
|
||||
{
|
||||
fdbg("Read block %d-%d failed: %d\n",
|
||||
block, block + nblocks -1, nxfrd);
|
||||
block, block + nblocks - 1, nxfrd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
@ -123,22 +123,41 @@ int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
|
|||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the current volume
|
||||
* block - The first logical block to write
|
||||
* nblocks - The number of logical blocks to be write.
|
||||
*
|
||||
* Returned Value:
|
||||
* Negated errnos are returned only in the case of MTD reported failures.
|
||||
* Nothing in the volume data itself will generate errors.
|
||||
*
|
||||
* Defined in nxffs_cache.c
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_wrcache(FAR struct nxffs_volume_s *volume, off_t block,
|
||||
uint8_t nblocks)
|
||||
int nxffs_wrcache(FAR struct nxffs_volume_s *volume)
|
||||
{
|
||||
#warning "Missing logic"
|
||||
return OK;
|
||||
size_t nxfrd;
|
||||
|
||||
/* Check if there are blocks in the cache */
|
||||
|
||||
if (volume->ncached > 0)
|
||||
{
|
||||
/* Read the specified blocks into cache */
|
||||
|
||||
nxfrd = MTD_BWRITE(volume->mtd, volume->cblock, volume->ncached,
|
||||
volume->cache);
|
||||
if (nxfrd != volume->ncached)
|
||||
{
|
||||
fdbg("Write block %d-%d failed: %d\n",
|
||||
volume->cblock, volume->cblock + volume->ncached - 1, nxfrd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Write was successful */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Probably won't get here because there is almost always something in
|
||||
* the cache
|
||||
*/
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -287,30 +306,3 @@ ssize_t nxffs_rddata(FAR struct nxffs_volume_s *volume,
|
|||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_wrdata
|
||||
*
|
||||
* Description:
|
||||
* Write a sequence of data bytes into volume cache memory. Nothing is
|
||||
* actually written to FLASH! This function allows the data in the formatted
|
||||
* FLASH blocks to be read as a continuous byte stream, skipping over bad
|
||||
* blocks and block headers as necessary.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume.
|
||||
* buffer - A pointer to memory to containing the data to write to FLASH.
|
||||
* buflen - The maximum number of bytes to write to FLASH.
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of bytes written is returned on success. Otherwise, a negated
|
||||
* errno indicating the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t nxffs_wrdata(FAR struct nxffs_volume_s *volume,
|
||||
FAR const uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
#warning "Missing Logic"
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -820,7 +820,7 @@ static int nxffs_wrclose(FAR struct nxffs_volume_s *volume,
|
|||
{
|
||||
/* Write the block with the inode header */
|
||||
|
||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
||||
ret = nxffs_wrcache(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to write inode header block %d: %d\n", volume->ioblock, -ret);
|
||||
|
|
@ -842,7 +842,7 @@ static int nxffs_wrclose(FAR struct nxffs_volume_s *volume,
|
|||
/* Finally, copy the inode name to the cache and write the inode name block */
|
||||
|
||||
memcpy(&volume->cache[namoffset], wrfile->ofile.entry.name, namlen);
|
||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
||||
ret = nxffs_wrcache(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to write inode header block %d: %d\n", volume->ioblock, -ret);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <crc32.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
|
@ -68,6 +69,178 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_rdblkhdr
|
||||
*
|
||||
* Description:
|
||||
* Read the dataa block header at this offset. Called only from nxffs_nextblock().
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the current volume.
|
||||
* offset - The byte offset from the beginning of FLASH where the data block
|
||||
* header is expected.
|
||||
* datlen - A memory location to return the data block length.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success. Otherwise, a negater errno value is returned
|
||||
* indicating the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
|
||||
FAR size_t *datlen)
|
||||
{
|
||||
struct nxffs_data_s blkhdr;
|
||||
uint32_t ecrc;
|
||||
uint32_t crc;
|
||||
uint16_t doffset;
|
||||
uint16_t dlen;
|
||||
int ret;
|
||||
|
||||
/* Read the header at the FLASH offset */
|
||||
|
||||
nxffs_ioseek(volume, offset);
|
||||
ret = nxffs_rddata(volume, (FAR uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to read data block header, offset %d: %d\n", offset, -ret);
|
||||
return -EIO;
|
||||
}
|
||||
doffset = volume->iooffset;
|
||||
|
||||
/* Extract the data length */
|
||||
|
||||
dlen = nxffs_rdle16(blkhdr.datlen);
|
||||
if ((uint32_t)doffset + (uint32_t)dlen > (uint32_t)volume->geo.blocksize)
|
||||
{
|
||||
fdbg("Data length=%d is unreasonable at offset=%d\n", dlen, doffset);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Extract the expected CRC and calculate the CRC of the data block */
|
||||
|
||||
ecrc = nxffs_rdle32(blkhdr.crc);
|
||||
|
||||
nxffs_wrle16(blkhdr.crc, 0);
|
||||
crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR);
|
||||
crc = crc32part(&volume->cache[doffset], dlen, crc);
|
||||
if (crc != ecrc)
|
||||
{
|
||||
fdbg("CRC failure\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Looks good! Return the data length and success */
|
||||
|
||||
*datlen = dlen;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_nextblock
|
||||
*
|
||||
* Description:
|
||||
* Search for the next valid data block starting at the provided FLASH offset.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume.
|
||||
* offset - The FLASH memory offset to begin searching.
|
||||
* datlen - A memory location to return the data block length.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success. Otherwise, a negated errno is returned
|
||||
* that indicates the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
|
||||
FAR size_t *datlen)
|
||||
{
|
||||
int nmagic;
|
||||
int ch;
|
||||
int nerased;
|
||||
int ret;
|
||||
|
||||
/* Seek to the first FLASH offset provided by the caller. */
|
||||
|
||||
nxffs_ioseek(volume, offset);
|
||||
|
||||
/* Then begin searching */
|
||||
|
||||
nerased = 0;
|
||||
nmagic = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Read the next character */
|
||||
|
||||
ch = nxffs_getc(volume);
|
||||
if (ch < 0)
|
||||
{
|
||||
fvdbg("nxffs_getc failed: %d\n", -ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* Check for another erased byte */
|
||||
|
||||
else if (ch == CONFIG_NXFFS_ERASEDSTATE)
|
||||
{
|
||||
/* If we have encountered NXFFS_NERASED number of consecutive
|
||||
* erased bytes, then presume we have reached the end of valid
|
||||
* data.
|
||||
*/
|
||||
|
||||
if (++nerased >= NXFFS_NERASED)
|
||||
{
|
||||
fvdbg("No entry found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nerased = 0;
|
||||
|
||||
/* Check for the magic sequence indicating the start of an NXFFS
|
||||
* data block or start of the next inode. There is the possibility
|
||||
* of this magic sequnce occurring in FLASH data. However, the
|
||||
* data block CRC should distinguish between real NXFFS data blocks
|
||||
* headers and such false alarms.
|
||||
*/
|
||||
|
||||
if (ch != g_datamagic[nmagic])
|
||||
{
|
||||
nmagic = 0;
|
||||
}
|
||||
else if (nmagic < NXFFS_MAGICSIZE - 1)
|
||||
{
|
||||
nmagic++;
|
||||
}
|
||||
|
||||
/* We have found the magic sequence in the FLASH data that may
|
||||
* indicate the beginning of an NXFFS data block.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
ret = nxffs_rdblkhdr(volume, offset, datlen);
|
||||
if (ret == OK)
|
||||
{
|
||||
fdbg("Found a valid fileheader\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* False alarm.. keep looking */
|
||||
|
||||
nmagic = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We won't get here, but to keep some compilers happy: */
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_rdseek
|
||||
*
|
||||
|
|
@ -88,8 +261,32 @@ static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume,
|
|||
FAR struct nxffs_entry_s *entry,
|
||||
off_t fpos)
|
||||
{
|
||||
#warning "Missing Logic"
|
||||
return 0;
|
||||
size_t datlen = 0;
|
||||
size_t blklen = 0;
|
||||
off_t offset = fpos;
|
||||
int ret;
|
||||
|
||||
/* Loop until we read the data block containing the desired position */
|
||||
|
||||
do
|
||||
{
|
||||
/* Get the data offset at the start of the next data block */
|
||||
|
||||
datlen += blklen;
|
||||
|
||||
/* Get the length of the next data block */
|
||||
|
||||
ret = nxffs_nextblock(volume, offset, &blklen);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("nxffs_nextblock failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
while (datlen <= fpos && datlen + blklen > fpos);
|
||||
|
||||
volume->iooffset += (fpos - datlen);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name)
|
|||
|
||||
/* Then write the cached block back to FLASH */
|
||||
|
||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
||||
ret = nxffs_wrcache(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to read data into cache: %d\n", ret);
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ static inline ssize_t nxffs_wrappend(FAR struct nxffs_volume_s *volume,
|
|||
|
||||
if (nbytesleft > 0)
|
||||
{
|
||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
||||
ret = nxffs_wrcache(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("nxffs_wrcache failed: %d\n", -ret);
|
||||
|
|
@ -811,7 +811,7 @@ int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume,
|
|||
|
||||
/* And write the data block to FLASH */
|
||||
|
||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
||||
ret = nxffs_wrcache(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("nxffs_wrcache failed: %d\n", -ret);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue