From e120ff0a0ef5c0f0125fc0e4b21bead8c67f8727 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 1 May 2011 00:26:38 +0000 Subject: Add basic NXFFS read logic git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3546 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/fs/nxffs/nxffs.h | 29 +----- nuttx/fs/nxffs/nxffs_cache.c | 66 ++++++-------- nuttx/fs/nxffs/nxffs_open.c | 4 +- nuttx/fs/nxffs/nxffs_read.c | 201 +++++++++++++++++++++++++++++++++++++++++- nuttx/fs/nxffs/nxffs_unlink.c | 2 +- nuttx/fs/nxffs/nxffs_write.c | 4 +- 6 files changed, 234 insertions(+), 72 deletions(-) diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h index d9c4f3c88..9ed65cf67 100644 --- a/nuttx/fs/nxffs/nxffs.h +++ b/nuttx/fs/nxffs/nxffs.h @@ -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 * diff --git a/nuttx/fs/nxffs/nxffs_cache.c b/nuttx/fs/nxffs/nxffs_cache.c index 41974bf93..7f563820f 100644 --- a/nuttx/fs/nxffs/nxffs_cache.c +++ b/nuttx/fs/nxffs/nxffs_cache.c @@ -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; -} diff --git a/nuttx/fs/nxffs/nxffs_open.c b/nuttx/fs/nxffs/nxffs_open.c index 45168d3da..09a82f6e9 100644 --- a/nuttx/fs/nxffs/nxffs_open.c +++ b/nuttx/fs/nxffs/nxffs_open.c @@ -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); diff --git a/nuttx/fs/nxffs/nxffs_read.c b/nuttx/fs/nxffs/nxffs_read.c index d8c2e9567..3648c1314 100644 --- a/nuttx/fs/nxffs/nxffs_read.c +++ b/nuttx/fs/nxffs/nxffs_read.c @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -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; } /**************************************************************************** diff --git a/nuttx/fs/nxffs/nxffs_unlink.c b/nuttx/fs/nxffs/nxffs_unlink.c index 8e25a1557..47abf61dd 100644 --- a/nuttx/fs/nxffs/nxffs_unlink.c +++ b/nuttx/fs/nxffs/nxffs_unlink.c @@ -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); diff --git a/nuttx/fs/nxffs/nxffs_write.c b/nuttx/fs/nxffs/nxffs_write.c index 3d7ad063d..8e91d2a7e 100644 --- a/nuttx/fs/nxffs/nxffs_write.c +++ b/nuttx/fs/nxffs/nxffs_write.c @@ -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); -- cgit v1.2.3