mirror of
https://github.com/apache/nuttx.git
synced 2026-05-13 10:38:40 +08:00
Add first NXFFS files
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3536 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
+5
-3
@@ -63,6 +63,7 @@ CSRCS += fs_mount.c fs_umount.c fs_fsync.c fs_unlink.c fs_rename.c \
|
||||
fs_mkdir.c fs_rmdir.c
|
||||
include fat/Make.defs
|
||||
include romfs/Make.defs
|
||||
include nxffs/Make.defs
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -73,8 +74,8 @@ OBJS = $(AOBJS) $(COBJS)
|
||||
|
||||
BIN = libfs$(LIBEXT)
|
||||
|
||||
SUBDIRS = fat romfs
|
||||
VPATH = fat:romfs
|
||||
SUBDIRS = fat romfs nxffs
|
||||
VPATH = fat:romfs:nxffs
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
@@ -90,7 +91,8 @@ $(BIN): $(OBJS)
|
||||
done ; )
|
||||
|
||||
.depend: Makefile $(SRCS)
|
||||
@$(MKDEP) --dep-path . --dep-path fat --dep-path romfs $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
|
||||
@$(MKDEP) --dep-path . $(FATDEPPATH) $(ROMFSDEPPATH) $(NXFFSDEPPATH) \
|
||||
$(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
|
||||
@touch $@
|
||||
|
||||
depend: .depend
|
||||
|
||||
+9
-5
@@ -1,7 +1,7 @@
|
||||
############################################################################
|
||||
# Make.defs
|
||||
#
|
||||
# Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,11 +36,15 @@
|
||||
ifeq ($(CONFIG_FS_FAT),y)
|
||||
# Files required for FAT file system support
|
||||
|
||||
ASRCS +=
|
||||
CSRCS += fs_fat32.c fs_fat32attrib.c fs_fat32util.c
|
||||
ASRCS +=
|
||||
CSRCS += fs_fat32.c fs_fat32attrib.c fs_fat32util.c
|
||||
|
||||
# Files required for mkfatfs utility function
|
||||
|
||||
ASRCS +=
|
||||
CSRCS += fs_mkfatfs.c fs_configfat.c fs_writefat.c
|
||||
ASRCS +=
|
||||
CSRCS += fs_mkfatfs.c fs_configfat.c fs_writefat.c
|
||||
|
||||
# Argument for dependency checking
|
||||
|
||||
FATDEPPATH = --dep-path fat
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
############################################################################
|
||||
# fs/nxffs/Make.defs
|
||||
#
|
||||
# Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name Nuttx nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifeq ($(CONFIG_FS_NXFFS),y)
|
||||
ASRCS +=
|
||||
CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c \
|
||||
nxffs_initialize.c nxffs_inode.c nxffs_reformat.c nxffs_util.c
|
||||
|
||||
# Argument for dependency checking
|
||||
|
||||
NXFFSDEPPATH = --dep-path nxffs
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_block.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mtd.h>
|
||||
|
||||
#include "nxffs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_verifyblock
|
||||
*
|
||||
* Description:
|
||||
* Assure the the provided (logical) block number is in the block cache
|
||||
* and that it has a valid block header (i.e., proper magic and
|
||||
* marked good)
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume
|
||||
* block - The (logical) block number to load and verify.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero is returned on success. Otherwise, a negated errno value is
|
||||
* returned indicating the nature of the failure. -ENOENT is returned
|
||||
* if the block is a bad block.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block)
|
||||
{
|
||||
FAR struct nxffs_block_s *blkhdr;
|
||||
int ret;
|
||||
|
||||
/* Make sure the the block is in the cache */
|
||||
|
||||
ret = nxffs_rdcache(volume, block, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to read data into cache: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if the block has a magic number (meaning that it is not
|
||||
* erased) and that it is valid (meaning that it is not marked
|
||||
* for cleanup)
|
||||
*/
|
||||
|
||||
blkhdr = (FAR struct nxffs_block_s *)volume->cache;
|
||||
if (memcmp(blkhdr->magic, g_blockmagic, 4) == 0 &&
|
||||
blkhdr->state == BLOCK_STATE_GOOD)
|
||||
{
|
||||
/* The block is valid */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_validblock
|
||||
*
|
||||
* Description:
|
||||
* Find the next valid (logical) block in the volume.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume
|
||||
* block - On entry, this provides the starting block number. If the
|
||||
* function is succesfful, then this memory location will hold the
|
||||
* block number of the next valid block on return.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success otherwise a negated errno value indicating the nature
|
||||
* of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_validblock(struct nxffs_volume_s *volume, off_t *block)
|
||||
{
|
||||
off_t i;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(volume && block);
|
||||
|
||||
/* Loop for each possible block or until a valid block is found */
|
||||
|
||||
for (i = *block; i < volume->geo.neraseblocks * volume->blkper; i++)
|
||||
{
|
||||
/* Loop until we find a valid block */
|
||||
|
||||
ret = nxffs_verifyblock(volume, i);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* We found it, return the block number */
|
||||
|
||||
*block = i;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
fdbg("No valid block found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_blockstats.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mtd.h>
|
||||
|
||||
#include "nxffs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_blockstats
|
||||
*
|
||||
* Description:
|
||||
* Analyze the NXFFS volume. This operation must be performed when the
|
||||
* volume is first mounted in order to detect if the volume has been
|
||||
* formatted and contains a usable NXFFS file system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the current NXFFS volume.
|
||||
* stats - On return, will hold nformation describing the state of the
|
||||
* volume.
|
||||
*
|
||||
* Returned Value:
|
||||
* Negated errnos are returned only in the case of MTD reported failures.
|
||||
* Nothing in the volume data itself will generate errors.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_blockstats(FAR struct nxffs_volume_s *volume,
|
||||
FAR struct nxffs_blkstats_s *stats)
|
||||
{
|
||||
FAR uint8_t *bptr; /* Pointer to next block data */
|
||||
off_t eblock; /* Erase block number */
|
||||
int lblock; /* Logical block index */
|
||||
int ret;
|
||||
|
||||
/* Process each erase block */
|
||||
|
||||
memset(stats, 0, sizeof(struct nxffs_blkstats_s));
|
||||
|
||||
for (eblock = 0; eblock < volume->geo.neraseblocks; eblock++)
|
||||
{
|
||||
/* Read the full erase block */
|
||||
|
||||
volume->ioblock = eblock * volume->blkper;
|
||||
volume->iooffset = 0;
|
||||
ret = nxffs_rdcache(volume, volume->ioblock, volume->blkper);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to read erase block %d: %d\n", eblock, -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Process each logical block */
|
||||
|
||||
for (bptr = volume->cache, lblock = 0;
|
||||
lblock < volume->blkper;
|
||||
bptr += SIZEOF_NXFFS_BLOCK_HDR, lblock++)
|
||||
{
|
||||
FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)bptr;
|
||||
|
||||
/* Collect statistics */
|
||||
|
||||
stats->nblocks++;
|
||||
if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0)
|
||||
{
|
||||
stats->nunformat++;
|
||||
}
|
||||
else if (blkhdr->state == BLOCK_STATE_BAD)
|
||||
{
|
||||
stats->nbad++;
|
||||
}
|
||||
else if (blkhdr->state == BLOCK_STATE_GOOD)
|
||||
{
|
||||
stats-> ngood++;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats->ncorrupt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fdbg("Number blocks: %d\n", stats->nblocks);
|
||||
fdbg(" Good blocks: %d\n", stats->ngood);
|
||||
fdbg(" Bad blocks: %d\n", stats->nbad);
|
||||
fdbg(" Unformatted blocks: %d\n", stats->nunformat);
|
||||
fdbg(" Corrupt blocks: %d\n", stats->ncorrupt);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_cache.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mtd.h>
|
||||
|
||||
#include "nxffs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_rdcache
|
||||
*
|
||||
* Description:
|
||||
* Read one or more logical blocks into the volume block cache memory.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the current volume
|
||||
* block - The first logical block to read
|
||||
* nblocks - The number of logical blocks to be read.
|
||||
*
|
||||
* Returned Value:
|
||||
* Negated errnos are returned only in the case of MTD reported failures.
|
||||
* Nothing in the volume data itself will generate errors.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
|
||||
uint8_t nblocks)
|
||||
{
|
||||
size_t nxfrd;
|
||||
|
||||
DEBUGASSERT(nblocks <= volume->blkper);
|
||||
|
||||
/* Check if the requested data is already in the cache */
|
||||
|
||||
if (block != volume->cblock || nblocks <= volume->ncached)
|
||||
{
|
||||
/* Read the specified blocks into cache */
|
||||
|
||||
nxfrd = MTD_BREAD(volume->mtd, block, nblocks, volume->cache);
|
||||
if (nxfrd != nblocks)
|
||||
{
|
||||
fdbg("Read block %d-%d failed: %d\n",
|
||||
block, block + nblocks -1, nxfrd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Remember what is in the cache */
|
||||
|
||||
volume->cblock = block;
|
||||
volume->ncached = nblocks;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_ioseek
|
||||
*
|
||||
* Description:
|
||||
* Seek to a position in FLASH memory. This simply sets up the offsets
|
||||
* and pointer values. This is a necessary step prior to using
|
||||
* nxffs_getc().
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume
|
||||
* offset - The physical offset in bytes from the beginning of the FLASH
|
||||
* in bytes.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset)
|
||||
{
|
||||
/* Convert the offset into a block number and a byte offset into the
|
||||
* block.
|
||||
*/
|
||||
|
||||
volume->ioblock = offset / volume->geo.blocksize;
|
||||
volume->iooffset = offset - volume->geo.blocksize * volume->ioblock;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_getc
|
||||
*
|
||||
* Description:
|
||||
* Get the next byte from 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. The paramters ioblock and iooffset
|
||||
* in the volume structure determine the behavior of nxffs_getc().
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success. Otherwise, a negated errno indicating the
|
||||
* nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_getc(FAR struct nxffs_volume_s *volume)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Loop to skip over bad blocks */
|
||||
|
||||
do
|
||||
{
|
||||
/* Check if we have read past the current block */
|
||||
|
||||
if (volume->iooffset >= volume->geo.blocksize)
|
||||
{
|
||||
volume->ioblock++;
|
||||
volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR;
|
||||
}
|
||||
|
||||
/* Make sure that the block is in the cache. The special error
|
||||
* -ENOENT indicates the block was read successfully but was not
|
||||
* marked as a good block. In this case we need to skip to the
|
||||
* next block. All other errors are fatal.
|
||||
*/
|
||||
|
||||
ret = nxffs_verifyblock(volume, volume->ioblock);
|
||||
if (ret < 0 && ret != -ENOENT)
|
||||
{
|
||||
fdbg("Failed to read valid data into cache: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
while (ret == -ENOENT);
|
||||
|
||||
/* Return the the character at this offset. Note that on return,
|
||||
* iooffset could point to the byte outside of the current block.
|
||||
*/
|
||||
|
||||
ret = (int)volume->cache[volume->iooffset];
|
||||
volume->iooffset++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_rddata
|
||||
*
|
||||
* Description:
|
||||
* Read a sequence of data bytes from the FLASH memory. 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. The paramters ioblock and iooffset
|
||||
* in the volume structure determine the behavior of nxffs_getc().
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of bytes read is returned on success. Otherwise, a negated
|
||||
* errno indicating the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t nxffs_rddata(FAR struct nxffs_volume_s *volume,
|
||||
FAR uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
size_t nbytes;
|
||||
int ch;
|
||||
|
||||
for (nbytes = buflen; nbytes > 0; nbytes--)
|
||||
{
|
||||
/* Read the next character (which could be in the next block) */
|
||||
|
||||
ch = nxffs_getc(volume);
|
||||
if (ch < 0)
|
||||
{
|
||||
fdbg("Failed to read byte: %d\n", -ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* Add the next character to the user buffer */
|
||||
|
||||
*buffer++ = (uint8_t)ch;
|
||||
}
|
||||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_initialize.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mtd.h>
|
||||
#include <nuttx/fs.h>
|
||||
#include <nuttx/ioctl.h>
|
||||
|
||||
#include "nxffs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
|
||||
/* See fs_mount.c -- this structure is explicitly externed there.
|
||||
* We use the old-fashioned kind of initializers so that this will compile
|
||||
* with any compiler.
|
||||
*/
|
||||
|
||||
const struct mountpt_operations nxffs_operations =
|
||||
{
|
||||
nxffs_open, /* open */
|
||||
nxffs_close, /* close */
|
||||
nxffs_read, /* read */
|
||||
nxffs_write, /* write */
|
||||
NULL, /* seek -- Use f_pos in struct file */
|
||||
nxffs_ioctl, /* ioctl */
|
||||
NULL, /* sync -- No buffered data */
|
||||
|
||||
nxffs_opendir, /* opendir */
|
||||
NULL, /* closedir */
|
||||
nxffs_readdir, /* readdir */
|
||||
nxffs_rewinddir, /* rewinddir */
|
||||
|
||||
nxffs_bind, /* bind */
|
||||
nxffs_unbind, /* unbind */
|
||||
nxffs_statfs, /* statfs */
|
||||
|
||||
nxffs_unlink, /* unlink */
|
||||
NULL, /* mkdir -- no directories */
|
||||
NULL, /* rmdir -- no directories */
|
||||
NULL, /* rename -- cannot rename in place if name is longer */
|
||||
nxffs_stat /* stat */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/* A singly-linked list of open files */
|
||||
|
||||
struct nxffs_ofile_s *g_ofiles;
|
||||
|
||||
/* The magic number that appears that the beginning of each NXFFS (logical)
|
||||
* block
|
||||
*/
|
||||
|
||||
const uint8_t g_blockmagic[NXFFS_MAGICSIZE] = { 'B', 'l', 'c', 'k' };
|
||||
|
||||
/* The magic number that appears that the beginning of each NXFFS inode */
|
||||
|
||||
const uint8_t g_inodemagic[NXFFS_MAGICSIZE] = { 'I', 'n', 'o', 'd' };
|
||||
|
||||
/* The magic number that appears that the beginning of each NXFFS inode
|
||||
* data block.
|
||||
*/
|
||||
|
||||
const uint8_t g_datamagic[NXFFS_MAGICSIZE] = { 'D', 'a', 't', 'a' };
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize to provide NXFFS on an MTD interface
|
||||
*
|
||||
* Input Parameters:
|
||||
* mtd - The MTD device that supports the FLASH interface.
|
||||
* start - The first block of the file system begins at this block number
|
||||
* in the FLASH
|
||||
* nblocks - This number of blocks is set aside for the file system.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_initialize(FAR struct mtd_dev_s *mtd, off_t start, off_t nblocks)
|
||||
{
|
||||
FAR struct nxffs_volume_s *volume;
|
||||
struct nxffs_blkstats_s stats;
|
||||
off_t threshold;
|
||||
int ret;
|
||||
|
||||
/* Allocate a NXFFS volume structure */
|
||||
|
||||
volume = (FAR struct nxffs_volume_s *)kzalloc(sizeof(struct nxffs_volume_s));
|
||||
if (!volume)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Initialize the NXFFS volume structure */
|
||||
|
||||
volume->mtd = mtd;
|
||||
|
||||
/* Get the volume geometry. (casting to uintptr_t first eliminates
|
||||
* complaints on some architectures where the sizeof long is different
|
||||
* from the size of a pointer).
|
||||
*/
|
||||
|
||||
ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&volume->geo));
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret);
|
||||
goto errout_with_volume;
|
||||
}
|
||||
|
||||
/* Allocate one, in-memory erase block buffer */
|
||||
|
||||
volume->cache = (FAR uint8_t *)kmalloc(volume->geo.erasesize);
|
||||
if (!volume->cache)
|
||||
{
|
||||
fdbg("Failed to allocate an erase block buffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_volume;
|
||||
}
|
||||
|
||||
/* Get the number of R/W blocks per erase block */
|
||||
|
||||
volume->blkper = volume->geo.erasesize / volume->geo.blocksize;
|
||||
DEBUGASSERT((off_t)volume->blkper * volume->geo.blocksize == volume->geo.erasesize);
|
||||
|
||||
/* Check if there is a valid NXFFS file system on the flash */
|
||||
|
||||
ret = nxffs_blockstats(volume, &stats);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to collect block statistics: %d\n", -ret);
|
||||
goto errout_with_iobuffer;
|
||||
}
|
||||
|
||||
/* If the proportion of good blocks is low or the proportion of unformatted
|
||||
* blocks is high, then reformat the FLASH.
|
||||
*/
|
||||
|
||||
threshold = stats.nblocks / 5;
|
||||
if (stats.ngood < threshold || stats.nunformat > threshold)
|
||||
{
|
||||
/* Reformat the volume */
|
||||
|
||||
ret = nxffs_reformat(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to reformat the volume: %d\n", -ret);
|
||||
goto errout_with_iobuffer;
|
||||
}
|
||||
|
||||
/* Get statistics on the re-formatted volume */
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS)
|
||||
ret = nxffs_blockstats(volume, &stats);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to collect block statistics: %d\n", -ret);
|
||||
goto errout_with_iobuffer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_iobuffer:
|
||||
kfree(volume->cache);
|
||||
errout_with_volume:
|
||||
kfree(volume);
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_limits
|
||||
*
|
||||
* Description:
|
||||
* Recalculate file system limits: (1) the FLASH offset to the first,
|
||||
* valid inode, and (2) the FLASH offset to the first, unused byte after
|
||||
* the last inode (invalid or not).
|
||||
*
|
||||
* The first, lower limit must be recalculated: (1) initially, (2)
|
||||
* whenever the first inode is deleted, or (3) whenever inode is moved
|
||||
* as part of the clean-up operation.
|
||||
*
|
||||
* The second, upper limit must be (1) incremented whenever new file
|
||||
* data is written, or (2) recalculated as part of the clean-up operation.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Identifies the NXFFS volume
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success. Otherwise, a negated error is returned indicating the
|
||||
* nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_limits(FAR struct nxffs_volume_s *volume)
|
||||
{
|
||||
#warning "Missing Logic"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_inode.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mtd.h>
|
||||
|
||||
#include "nxffs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_rdentry
|
||||
*
|
||||
* Description:
|
||||
* Read the inode entry at this offset. Called only from nxffs_nextentry().
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the current volume.
|
||||
* offset - The byte offset from the beginning of FLASH where the inode
|
||||
* header is expected.
|
||||
* entry - A memory location to return the expanded inode header
|
||||
* information.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success. Otherwise, a negater errno value is returned
|
||||
* indicating the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nxffs_rdentry(FAR struct nxffs_volume_s *volume, off_t offset,
|
||||
FAR struct nxffs_entry_s *entry)
|
||||
{
|
||||
struct nxffs_inode_s inode;
|
||||
uint32_t ecrc;
|
||||
uint32_t crc;
|
||||
int namelen;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(volume && entry);
|
||||
memset(entry, 0, sizeof(struct nxffs_entry_s));
|
||||
|
||||
/* Read the header at the FLASH offset */
|
||||
|
||||
nxffs_ioseek(volume, offset);
|
||||
ret = nxffs_rddata(volume, (FAR uint8_t *)&inode, SIZEOF_NXFFS_INODE_HDR);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to read inode, offset %d: %d\n", offset, -ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Check if the file is marked as deleted. */
|
||||
|
||||
if (inode.state != INODE_STATE_FILE)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Copy the packed header into the user-friendly buffer */
|
||||
|
||||
entry->hoffset = offset;
|
||||
entry->doffset = offset + inode.doffset;
|
||||
entry->utc = nxffs_rdle32(inode.utc);
|
||||
entry->datlen = nxffs_rdle32(inode.datlen);
|
||||
|
||||
/* Modify the packed header and perform the (partial) CRC calculation */
|
||||
|
||||
ecrc = nxffs_rdle32(inode.crc);
|
||||
inode.state = CONFIG_NXFFS_ERASEDSTATE;
|
||||
memset(inode.crc, 0, 4);
|
||||
crc = crc32((FAR const uint8_t *)&inode, SIZEOF_NXFFS_INODE_HDR);
|
||||
|
||||
/* Allocate memory to hold the variable-length file name */
|
||||
|
||||
namelen = (int)inode.doffset - (int)inode.noffset;
|
||||
if (namelen < 0)
|
||||
{
|
||||
fdbg("Bad offsets, name: %d data: %d\n", inode.noffset, inode.doffset);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
entry->name = (FAR char *)kmalloc(namelen+1);
|
||||
if (!entry->name)
|
||||
{
|
||||
fdbg("Failed to allocate name, namelen: %d\n", namelen);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Read the file name from the expected offset in FLASH */
|
||||
|
||||
nxffs_ioseek(volume, offset + inode.noffset);
|
||||
ret = nxffs_rddata(volume, (FAR uint8_t*)entry->name, namelen);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to read inode, offset %d: %d\n", offset, -ret);
|
||||
return -EIO;
|
||||
}
|
||||
entry->name[namelen] = '\0';
|
||||
|
||||
/* Finish the CRC calculation and verify the entry */
|
||||
|
||||
crc = crc32part(entry->name, namelen, crc);
|
||||
if (crc != ecrc)
|
||||
{
|
||||
fdbg("CRC entry: %08x CRC calculated: %08x\n", ecrc, crc);
|
||||
nxffs_freeentry(entry);
|
||||
return -EIO;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_freeentry
|
||||
*
|
||||
* Description:
|
||||
* The inode values returned by nxffs_nextentry() include allocated memory
|
||||
* (specifically, the file name string). This function should be called
|
||||
* to dispose of that memory when the inode entry is no longer needed.
|
||||
*
|
||||
* Note that the nxffs_entry_s containing structure is not freed. The
|
||||
* caller may call kfree upon return of this function if necessary to
|
||||
* free the entry container.
|
||||
*
|
||||
* Input parameters:
|
||||
* entry - The entry to be freed.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nxffs_freeentry(FAR struct nxffs_entry_s *entry)
|
||||
{
|
||||
if (entry->name)
|
||||
{
|
||||
kfree(entry->name);
|
||||
entry->name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_nextentry
|
||||
*
|
||||
* Description:
|
||||
* Search for the next valid inode starting at the provided FLASH offset.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume.
|
||||
* offset - The FLASH memory offset to begin searching.
|
||||
* entry - A pointer to memory provided by the caller in which to return
|
||||
* the inode description.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success. Otherwise, a negated errno is returned
|
||||
* that indicates the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
|
||||
FAR struct nxffs_entry_s *entry)
|
||||
{
|
||||
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
|
||||
* inode. There is the possibility of this magic sequnce occurring
|
||||
* in FLASH data. However, the header CRC should distinguish
|
||||
* between real NXFFS inode headers and such false alarms.
|
||||
*/
|
||||
|
||||
if (ch != g_inodemagic[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 inode.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
ret = nxffs_rdentry(volume, offset, entry);
|
||||
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_findinode
|
||||
*
|
||||
* Description:
|
||||
* Search for an inode with the provided name starting with the first
|
||||
* valid inode and proceeding to the end FLASH or until the matching
|
||||
* inode is found.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume
|
||||
* name - The name of the inode to find
|
||||
* entry - The location to return information about the inode.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success. Otherwise, a negated errno is returned
|
||||
* that indicates the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
|
||||
struct nxffs_entry_s *entry)
|
||||
{
|
||||
off_t offset;
|
||||
int ret;
|
||||
|
||||
/* Start with the first valid inode that was discovered when the volume
|
||||
* was created (or modified after the last cleanup).
|
||||
*/
|
||||
|
||||
offset = volume->inoffset;
|
||||
|
||||
/* Loop, checking each NXFFS inode until either: (1) we find the NXFFS inode
|
||||
* with the matching name, or (2) we reach the end of data written on the
|
||||
* media.
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Get the next, valid NXFFS inode entry */
|
||||
|
||||
ret = nxffs_nextentry(volume, offset, entry);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("No inode found: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Is this the NXFFS inode we are looking for? */
|
||||
|
||||
else if (strcmp(name, entry->name) == 0)
|
||||
{
|
||||
/* Yes, return success with the entry data in 'enty' */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Discard this entry and try the next one. Here we set the
|
||||
* next offset using the raw data length as the offset
|
||||
* increment. This is, of course, not accurate because it
|
||||
* does not account for the data headers that inclose the
|
||||
* data. But it is guaranteed to be less than or equal to
|
||||
* the correct offset and, hence, better then seraching
|
||||
* byte-for-byte.
|
||||
*/
|
||||
|
||||
offset = entry->doffset + entry->datlen;
|
||||
nxffs_freeentry(entry);
|
||||
}
|
||||
|
||||
/* We won't get here, but for some compilers: */
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_reformat.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mtd.h>
|
||||
|
||||
#include "nxffs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_format
|
||||
*
|
||||
* Description:
|
||||
* Erase and reformat the entire volume.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume to be reformatted.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success or a negated errno on a failure. Failures will be
|
||||
* returned n the case of MTD reported failures o.
|
||||
* Nothing in the volume data itself will generate errors.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nxffs_format(FAR struct nxffs_volume_s *volume)
|
||||
{
|
||||
FAR uint8_t *blkptr; /* Pointer to next block data */
|
||||
off_t eblock; /* Erase block number */
|
||||
off_t lblock; /* Logical block number */
|
||||
ssize_t nxfrd; /* Number of blocks transferred */
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
/* Create an image of one properly formatted erase sector */
|
||||
|
||||
memset(volume->cache, CONFIG_NXFFS_ERASEDSTATE, volume->geo.erasesize);
|
||||
for (blkptr = volume->cache, i = 0;
|
||||
i < volume->blkper;
|
||||
blkptr += SIZEOF_NXFFS_BLOCK_HDR, i++)
|
||||
{
|
||||
FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr;
|
||||
memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE);
|
||||
blkhdr->state = BLOCK_STATE_GOOD;
|
||||
}
|
||||
|
||||
/* Erase and format each erase block */
|
||||
|
||||
for (eblock = 0; eblock < volume->geo.neraseblocks; eblock++)
|
||||
{
|
||||
/* Erase the block */
|
||||
|
||||
ret = MTD_ERASE(volume->mtd, eblock, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Erase block %d failed: %d\n", eblock, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Write the formatted image to the erase block */
|
||||
|
||||
lblock = eblock * volume->blkper;
|
||||
nxfrd = MTD_BWRITE(volume->mtd, lblock, volume->blkper, volume->cache);
|
||||
if (nxfrd != volume->blkper)
|
||||
{
|
||||
fdbg("Write erase block %d failed: %d\n", alignedblock, nxfrd);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_badblocks
|
||||
*
|
||||
* Description:
|
||||
* Verify each block and mark improperly erased blocks as bad.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume to be reformatted.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success or a negated errno on a failure. Failures will be
|
||||
* returned n the case of MTD reported failures o.
|
||||
* Nothing in the volume data itself will generate errors.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nxffs_badblocks(FAR struct nxffs_volume_s *volume)
|
||||
{
|
||||
FAR uint8_t *blkptr; /* Pointer to next block data */
|
||||
FAR uint8_t *datptr; /* Pointer to next data byte */
|
||||
off_t eblock; /* Erase block number */
|
||||
off_t lblock; /* Logical block number */
|
||||
ssize_t nxfrd; /* Number of blocks transferred */
|
||||
uint16_t blkndx; /* Logical block data index */
|
||||
bool bad; /* TRUE: block is bad */
|
||||
bool modified; /* TRUE: The erase block has been modified */
|
||||
int i;
|
||||
|
||||
/* Read and verify each erase block */
|
||||
|
||||
for (eblock = 0; eblock < volume->geo.neraseblocks; eblock++)
|
||||
{
|
||||
/* Read the entire erase block */
|
||||
|
||||
lblock = eblock * volume->blkper;
|
||||
nxfrd = MTD_BREAD(volume->mtd, lblock, volume->blkper, volume->cache);
|
||||
if (nxfrd != volume->blkper)
|
||||
{
|
||||
fdbg("Read erase block %d failed: %d\n", lblock, nxfrd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Process each logical block */
|
||||
|
||||
modified = false;
|
||||
for (blkptr = volume->cache, i = 0;
|
||||
i < volume->blkper;
|
||||
blkptr += SIZEOF_NXFFS_BLOCK_HDR, i++)
|
||||
{
|
||||
FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr;
|
||||
|
||||
/* Check block header */
|
||||
|
||||
bad = false;
|
||||
if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0 ||
|
||||
blkhdr->state == BLOCK_STATE_GOOD)
|
||||
{
|
||||
bad = true;;
|
||||
}
|
||||
|
||||
/* Check that block data is erased */
|
||||
|
||||
else
|
||||
{
|
||||
/* Check every byte in the block payload */
|
||||
|
||||
for (blkndx = SIZEOF_NXFFS_BLOCK_HDR, datptr = &blkptr[blkndx];
|
||||
blkndx < volume->geo.blocksize;
|
||||
blkndx++)
|
||||
{
|
||||
/* If the data byte is not in the erased state, then the block is bad */
|
||||
|
||||
uint8_t byte = *datptr++;
|
||||
if (byte != CONFIG_NXFFS_ERASEDSTATE)
|
||||
{
|
||||
bad = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the block is bad, attempt to re-write the block header indicating
|
||||
* a bad block (of course, if the block has failed, this may not be
|
||||
* possible, depending upon failure modes.
|
||||
*/
|
||||
|
||||
if (bad)
|
||||
{
|
||||
memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE);
|
||||
blkhdr->state = BLOCK_STATE_BAD;
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the erase block was modified, then re-write it */
|
||||
|
||||
nxfrd = MTD_BWRITE(volume->mtd, lblock, volume->blkper, volume->cache);
|
||||
if (nxfrd != volume->blkper)
|
||||
{
|
||||
fdbg("Write erase block %d failed: %d\n", alignedblock, nxfrd);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_reformat
|
||||
*
|
||||
* Description:
|
||||
* Erase and reformat the entire volume. Verify each block and mark
|
||||
* improperly erased blocks as bad.
|
||||
*
|
||||
* Input Parameters:
|
||||
* volume - Describes the NXFFS volume to be reformatted.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success or a negated errno on a failure. Failures will be
|
||||
* returned n the case of MTD reported failures o.
|
||||
* Nothing in the volume data itself will generate errors.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxffs_reformat(FAR struct nxffs_volume_s *volume)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Erase and reformat the entire volume */
|
||||
|
||||
ret = nxffs_format(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Failed to reformat the volume: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check for bad blocks */
|
||||
|
||||
ret = nxffs_badblocks(volume);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("Bad block check failed: %d\n", -ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/****************************************************************************
|
||||
* fs/nxffs/nxffs_util.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* References: Linux/Documentation/filesystems/romfs.txt
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mtd.h>
|
||||
|
||||
#include "nxffs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_rdle16
|
||||
*
|
||||
* Description:
|
||||
* Get a (possibly unaligned) 16-bit little endian value.
|
||||
*
|
||||
* Input Parameters:
|
||||
* val - A pointer to the first byte of the little endian value.
|
||||
*
|
||||
* Returned Values:
|
||||
* A uint16_t representing the whole 16-bit integer value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint16_t nxffs_rdle16(const uint8_t *val)
|
||||
{
|
||||
return (uint16_t)val[1] << 8 | (uint16_t)val[0];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxffs_rdle32
|
||||
*
|
||||
* Description:
|
||||
* Get a (possibly unaligned) 32-bit little endian value.
|
||||
*
|
||||
* Input Parameters:
|
||||
* val - A pointer to the first byte of the little endian value.
|
||||
*
|
||||
* Returned Values:
|
||||
* A uint32_t representing the whole 32-bit integer value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t nxffs_rdle32(const uint8_t *val)
|
||||
{
|
||||
/* Little endian means LS halfword first in byte stream */
|
||||
|
||||
return (uint32_t)nxffs_rdle16(&val[2]) << 16 | (uint32_t)nxffs_rdle16(val);
|
||||
}
|
||||
|
||||
+9
-3
@@ -1,7 +1,7 @@
|
||||
############################################################################
|
||||
# fs/romfs/Make.defs
|
||||
#
|
||||
# Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,6 +34,12 @@
|
||||
############################################################################
|
||||
|
||||
ifeq ($(CONFIG_FS_ROMFS),y)
|
||||
ASRCS +=
|
||||
CSRCS += fs_romfs.c fs_romfsutil.c
|
||||
# Files required for ROMFS file system support
|
||||
|
||||
ASRCS +=
|
||||
CSRCS += fs_romfs.c fs_romfsutil.c
|
||||
|
||||
# Argument for dependency checking
|
||||
|
||||
ROMFSDEPPATH = --dep-path romfs
|
||||
endif
|
||||
|
||||
Reference in New Issue
Block a user