mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 14:27:37 +08:00
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:
+1
-28
@@ -496,19 +496,15 @@ extern int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* volume - Describes the current volume
|
* volume - Describes the current volume
|
||||||
* block - The first logical block to write
|
|
||||||
* nblocks - The number of logical blocks to be write.
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Negated errnos are returned only in the case of MTD reported failures.
|
* 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
|
* Defined in nxffs_cache.c
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume, off_t block,
|
extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume);
|
||||||
uint8_t nblocks);
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxffs_ioseek
|
* 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,
|
extern ssize_t nxffs_rddata(FAR struct nxffs_volume_s *volume,
|
||||||
FAR uint8_t *buffer, size_t buflen);
|
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
|
* Name: nxffs_freeentry
|
||||||
*
|
*
|
||||||
|
|||||||
+28
-36
@@ -103,7 +103,7 @@ int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
|
|||||||
if (nxfrd != nblocks)
|
if (nxfrd != nblocks)
|
||||||
{
|
{
|
||||||
fdbg("Read block %d-%d failed: %d\n",
|
fdbg("Read block %d-%d failed: %d\n",
|
||||||
block, block + nblocks -1, nxfrd);
|
block, block + nblocks - 1, nxfrd);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,22 +123,41 @@ int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* volume - Describes the current volume
|
* volume - Describes the current volume
|
||||||
* block - The first logical block to write
|
|
||||||
* nblocks - The number of logical blocks to be write.
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Negated errnos are returned only in the case of MTD reported failures.
|
* 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,
|
int nxffs_wrcache(FAR struct nxffs_volume_s *volume)
|
||||||
uint8_t nblocks)
|
|
||||||
{
|
{
|
||||||
#warning "Missing logic"
|
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;
|
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;
|
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 */
|
/* Write the block with the inode header */
|
||||||
|
|
||||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
ret = nxffs_wrcache(volume);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fdbg("Failed to write inode header block %d: %d\n", volume->ioblock, -ret);
|
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 */
|
/* Finally, copy the inode name to the cache and write the inode name block */
|
||||||
|
|
||||||
memcpy(&volume->cache[namoffset], wrfile->ofile.entry.name, namlen);
|
memcpy(&volume->cache[namoffset], wrfile->ofile.entry.name, namlen);
|
||||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
ret = nxffs_wrcache(volume);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fdbg("Failed to write inode header block %d: %d\n", volume->ioblock, -ret);
|
fdbg("Failed to write inode header block %d: %d\n", volume->ioblock, -ret);
|
||||||
|
|||||||
+199
-2
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <crc32.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -68,6 +69,178 @@
|
|||||||
* Private Functions
|
* 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
|
* Name: nxffs_rdseek
|
||||||
*
|
*
|
||||||
@@ -88,8 +261,32 @@ static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume,
|
|||||||
FAR struct nxffs_entry_s *entry,
|
FAR struct nxffs_entry_s *entry,
|
||||||
off_t fpos)
|
off_t fpos)
|
||||||
{
|
{
|
||||||
#warning "Missing Logic"
|
size_t datlen = 0;
|
||||||
return 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 */
|
/* Then write the cached block back to FLASH */
|
||||||
|
|
||||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
ret = nxffs_wrcache(volume);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fdbg("Failed to read data into cache: %d\n", ret);
|
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)
|
if (nbytesleft > 0)
|
||||||
{
|
{
|
||||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
ret = nxffs_wrcache(volume);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fdbg("nxffs_wrcache failed: %d\n", -ret);
|
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 */
|
/* And write the data block to FLASH */
|
||||||
|
|
||||||
ret = nxffs_wrcache(volume, volume->ioblock, 1);
|
ret = nxffs_wrcache(volume);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fdbg("nxffs_wrcache failed: %d\n", -ret);
|
fdbg("nxffs_wrcache failed: %d\n", -ret);
|
||||||
|
|||||||
Reference in New Issue
Block a user