From 7df37bbc221988458367d4b2fa26adbb4038407a Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 28 Apr 2011 19:26:46 +0000 Subject: [PATCH] Add first NXFFS files git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3536 42af7a65-404d-4744-a932-0658087f49c3 --- fs/Makefile | 8 +- fs/fat/Make.defs | 14 +- fs/nxffs/Make.defs | 44 +++ fs/nxffs/nxffs.h | 690 ++++++++++++++++++++++++++++++++++++ fs/nxffs/nxffs_block.c | 166 +++++++++ fs/nxffs/nxffs_blockstats.c | 153 ++++++++ fs/nxffs/nxffs_cache.c | 243 +++++++++++++ fs/nxffs/nxffs_initialize.c | 272 ++++++++++++++ fs/nxffs/nxffs_inode.c | 380 ++++++++++++++++++++ fs/nxffs/nxffs_reformat.c | 281 +++++++++++++++ fs/nxffs/nxffs_util.c | 112 ++++++ fs/romfs/Make.defs | 12 +- 12 files changed, 2364 insertions(+), 11 deletions(-) create mode 100644 fs/nxffs/Make.defs create mode 100644 fs/nxffs/nxffs.h create mode 100644 fs/nxffs/nxffs_block.c create mode 100644 fs/nxffs/nxffs_blockstats.c create mode 100644 fs/nxffs/nxffs_cache.c create mode 100644 fs/nxffs/nxffs_initialize.c create mode 100644 fs/nxffs/nxffs_inode.c create mode 100644 fs/nxffs/nxffs_reformat.c create mode 100644 fs/nxffs/nxffs_util.c diff --git a/fs/Makefile b/fs/Makefile index 3423250baf..3f93563919 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -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 diff --git a/fs/fat/Make.defs b/fs/fat/Make.defs index 2f1a010032..111217efca 100644 --- a/fs/fat/Make.defs +++ b/fs/fat/Make.defs @@ -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 # # 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 diff --git a/fs/nxffs/Make.defs b/fs/nxffs/Make.defs new file mode 100644 index 0000000000..23e9d3ec2c --- /dev/null +++ b/fs/nxffs/Make.defs @@ -0,0 +1,44 @@ +############################################################################ +# fs/nxffs/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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 diff --git a/fs/nxffs/nxffs.h b/fs/nxffs/nxffs.h new file mode 100644 index 0000000000..13f93644e6 --- /dev/null +++ b/fs/nxffs/nxffs.h @@ -0,0 +1,690 @@ +/**************************************************************************** + * fs/nxffs/nxffs.h + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __FS_NXFFS_NXFFS_H +#define __FS_NXFFS_NXFFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +#ifndef CONFIG_NXFFS_ERASEDSTATE +# define CONFIG_NXFFS_ERASEDSTATE 0xff +#endif + +#if CONFIG_NXFFS_ERASEDSTATE != 0xff && CONFIG_NXFFS_ERASEDSTATE != 0x00 +# error "CONFIG_NXFFS_ERASEDSTATE must be either 0x00 or 0xff" +#endif + +/* NXFFS Definitions ********************************************************/ +/* General NXFFS organization. The following example assumes 4 logical + * blocks per FLASH erase block. The actual relationship is determined by + * the FLASH geometry reported by the MTD driver. + * + * ERASE LOGICAL Inodes begin with a inode header. inode may + * BLOCK BLOCK CONTENTS be marked as "deleted," pending clean-up. + * n 4*n --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |IIIIIIIIIIIIII| Inodes begin with a inode header + * |DDDDDDDDDDDDD| Data block containing inode data block + * | (Inode Data) | + * 4*n+1 --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |DDDDDDDDDDDDDD| Inodes may consist of multiple data blocks + * | (Inode Data) | + * |IIIIIIIIIIIIII| Next inode header + * | | Possibly a few unused bytes at the end of a block + * 4*n+2 --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |DDDDDDDDDDDDDD| + * | (Inode Data) | + * 4*n+3 --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * |IIIIIIIIIIIIII| Next inode header + * |DDDDDDDDDDDDDD| + * | (Inode Data) | + * n+1 4*(n+1) --+--------------+ + * |BBBBBBBBBBBBBB| Logic block header + * | | All FLASH is unused after the end of the final + * | | inode. + * --+--------------+ + * + * General operation: + * Inodes are written starting at the beginning of FLASH. As inodes are + * deleted, they are marked as deleted but not removed. As new inodes are + * written, allocations proceed to toward the end of the FLASH -- thus, + * supporting wear leveling by using all FLASH blocks equally. + * + * When the FLASH becomes full (no more space at the end of the FLASH), a + * clean-up operation must be performed: All inodes marked deleted are + * finally removed and the remaining inodes are packed at the beginning of + * the FLASH. Allocations then continue at the freed FLASH memory at the + * end of the FLASH. + * + * BLOCK HEADER: + * The block header is used to determine if the block has every been + * formatted and also indicates bad blocks which should never be used. + * + * INODE HEADER: + * Each inode begins with an inode header that contains, among other things, + * the name of the inode, the offset to the first data block, and the + * length of the inode data. + * + * At present, the only kind of inode support is a file. So for now, the + * term file and inode are interchangeable. + * + * INODE DATA HEADER: + * Inode data is enclosed in a data header. For a given inode, there + * is at most one inode data block per logical block. If the inode data + * spans more than one logical block, then the inode data may be enclosed + * in multiple data blocks, one per logical block. + * + * NXFFS Limitations: + * 1. Since the files are contiguous in FLASH and since allocations always + * proceed toward the end of the FLASH, there can only be one file opened + * for writing at a time. Multiple files may be opened for reading. + * 2. Files may not be increased in size after they have been closed. The + * O_APPEND open flag is not supported. + * 3. Files are always written sequential. Seeking within a file opened for + * writing will not work. + * 4. There are no directories, however, '/' may be used within a file name + * string providing some illusion of directories. + * 5. Files may be opened for reading or for writing, but not both: The O_RDWR + * open flag is not supported. + * 6. The clean-up process occurs only during a write when the free FLASH + * memory at the end of the FLASH is exhausted. Thus, occasionally, file + * writing may take a long time. + * + */ + +/* Values for logical block state. Basically, there are only two, perhaps + * three, states: + * + * BLOCK_STATE_GOOD - The block is not known to be bad. + * BLOCK_STATE_BAD - An error was found on the block and it is marked bad. + * Other values - The block is bad and has an invalid state. + */ + +#define BLOCK_STATE_GOOD CONFIG_NXFFS_ERASEDSTATE +#define BLOCK_STATE_BAD 0xaa + +/* Values for NXFFS inode state. Similar there are 2 (maybe 3) inode states: + * + * INODE_STATE_FILE - The inode is a valid usuable, file + * INODE_STATE_DELETED - The inode has been deleted. + */ + +#define INODE_STATE_FILE CONFIG_NXFFS_ERASEDSTATE +#define INODE_STATE_DELETED 0x55 + +/* Number of bytes in an the NXFFS magic sequences */ + +#define NXFFS_MAGICSIZE 4 + +/* Internal definitions *****************************************************/ +/* Values for volume flags */ + +#define VOL_FLAGS_WRITER (1 << 0) /* Only one writer of the volune */ + +#define VOL_FLAGS_SET(p,f) ((p)->flags &= ~(f)) +#define VOL_FLAGS_CLEAR(p,f) ((p)->flags |= (f)) +#define VOL_FLAGS_TEST(p,f) (((p)->flags & (f)) == 0) + +/* If we encounter this number of erased bytes, we assume that all of the + * flash beyond this point is erased. + */ + +#define NXFFS_NERASED 128 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure defines each packed block on the FLASH media */ + +struct nxffs_block_s +{ + uint8_t magic[4]; /* 0-3: Magic number for valid block */ + uint8_t state; /* 4: Block state: See BLOCK_STATE_* */ +}; +#define SIZEOF_NXFFS_BLOCK_HDR 5 + +/* This structure defines each packed NXFFS inode header on the FLASH media */ + +struct nxffs_inode_s +{ + uint8_t magic[4]; /* 0-3: Magic number for valid inode */ + uint8_t state; /* 4: Inode state: See INODE_STATE_* */ + uint8_t noffset; /* 5: Offset to the file name from the header */ + uint8_t doffset; /* 5: Offset to data from file header */ + uint8_t utc[4]; /* 7-9: Creation time */ + uint8_t crc[4]; /* 10-13: CRC32 */ + uint8_t datlen[4]; /* 14-17: Length of data in bytes */ + /* 18-: Variable length file name follows */ +}; +#define SIZEOF_NXFFS_INODE_HDR 18 + +/* This structure defines each packed NXFFS data header on the FLASH media */ + +struct nxffs_data_s +{ + uint8_t magic[4]; /* 0-3: Magic number for valid data */ + uint8_t crc[4]; /* 4-7: CRC32 */ + uint8_t datlen[4]; /* 8-11: Length of data in bytes */ + /* 12-: Variable length data follows */ +}; +#define SIZEOF_NXFFS_DATA_HDR 12 + +/* This is an in-memory representation of the NXFFS inode as extracted from + * FLASH and with additional state information. + */ + +struct nxffs_entry_s +{ + off_t hoffset; /* Offset to the inode on the media */ + off_t doffset; /* Offset to the data on the media */ + FAR char *name; /* inode name */ + uint32_t utc; /* Time stamp */ + uint32_t datlen; /* Length of inode data */ +}; + +/* This structure represents the overall state of on NXFFS instance. */ + +struct nxffs_volume_s +{ + FAR struct mtd_dev_s *mtd; /* Supports FLASH access */ + sem_t exclsem; /* Used to assure thread-safe access */ + struct mtd_geometry_s geo; /* Device geometry */ + uint8_t wrbusy: 1; /* 1: Volume open for writing */ + uint8_t blkper; /* R/W blocks per erase block */ + uint8_t ncached; /* Number of blocks in cache */ + uint16_t iooffset; /* Next offset in read/write access (in ioblock) */ + off_t inoffset; /* Offset to the first valid inode header */ + off_t froffset; /* Offset to the first free byte */ + off_t ioblock; /* Current block number being accessed */ + off_t cblock; /* Starting block number in cache */ + FAR uint8_t *cache; /* Allocated erase block */ +}; + +/* This structure describes the state of one open file. This structure + * is protected by the volume semaphore. + */ + +struct nxffs_ofile_s +{ + struct nxffs_ofile_s *flink; /* Supports a singly linked list */ + int16_t crefs; /* Reference count */ + mode_t mode; /* Open mode */ + struct nxffs_entry_s entry; /* Describes the NXFFS inode entry */ +}; + +/* A file opened for writing require some additional information */ + +struct nxffs_wrfile_s +{ + /* The following fields provide the common open file information. */ + + struct nxffs_ofile_s ofile; + + /* The following fields are required to support the current write + * operation. Note that the size of the current block can be determined + * from (wroffset - dathdr - SIZEOF_NXFFS_DATA_HDR). Basic write + * operation: + * + * 1. Inode header location determined (but not yet written). + * 2. Block header location determined (but not yet written). + * 3. Check FLASH memory to make sure that it is erased. + * 4. As data is written, wrlen is updated and the data is written to FLASH. + * 5. If the end of the FLASH block is encountered, the data block CRC is + * calculated and the block header is also written to flash. + * 6. When the file is closed, the final, partial data block is written to + * FLASH in the same way. The final file size is determined, the header + * CRC is calculated, and the inode header is written to FLASH, completing + * the write operation. + */ + + uint16_t wrlen; /* Number of bytes written in data block */ + off_t dathdr; /* FLASH offset to the current data header */ +}; + +/* This structure describes the state of the blocks on the NXFFS volume */ + +struct nxffs_blkstats_s +{ + off_t nblocks; /* Total number of FLASH blocks */ + off_t ngood; /* Number of good FLASH blocks found */ + off_t nbad; /* Number of well-formatted FLASH blocks marked as bad */ + off_t nunformat; /* Number of unformatted FLASH blocks */ + off_t ncorrupt; /* Number of blocks with correupted format info */ +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* A singly-linked list of open files */ + +extern struct nxffs_ofile_s *g_ofiles; + +/* The magic number that appears that the beginning of each NXFFS (logical) + * block + */ + +extern const uint8_t g_blockmagic[NXFFS_MAGICSIZE]; + +/* The magic number that appears that the beginning of each NXFFS inode */ + +extern const uint8_t g_inodemagic[NXFFS_MAGICSIZE]; + +/* The magic number that appears that the beginning of each NXFFS inode + * data block. + */ + +extern const uint8_t g_datamagic[NXFFS_MAGICSIZE]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * 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. + * + * Defined in nxffs_initialize.c + * + ****************************************************************************/ + +extern int nxffs_limits(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * 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 + * + * Defined in nxffs_util.c + * + ****************************************************************************/ + +extern uint16_t nxffs_rdle16(const uint8_t *val); + +/**************************************************************************** + * 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 + * + * Defined in nxffs_util.c + * + ****************************************************************************/ + +extern uint32_t nxffs_rdle32(const uint8_t *val); + +/**************************************************************************** + * Name: nxffs_rdcache + * + * Description: + * Read one or more logical blocks into the volume 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. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block, + uint8_t nblocks); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern int nxffs_getc(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_cache.c + * + ****************************************************************************/ + +extern ssize_t nxffs_rddata(FAR struct nxffs_volume_s *volume, + FAR uint8_t *buffer, size_t buflen); + +/**************************************************************************** + * 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 + * + * Defined in nxffs_inode.c + * + ****************************************************************************/ + +extern void nxffs_freeentry(FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_inode.c + * + ****************************************************************************/ + +extern int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset, + FAR struct nxffs_entry_s *entry); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_inode.c + * + ****************************************************************************/ + +extern int nxffs_findinode(FAR struct nxffs_volume_s *volume, + FAR const char *name, + struct nxffs_entry_s *entry); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_block.c + * + ****************************************************************************/ + +extern int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_block.c + * + ****************************************************************************/ + +extern int nxffs_validblock(struct nxffs_volume_s *volume, off_t *block); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_blockstats.c + * + ****************************************************************************/ + +extern int nxffs_blockstats(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_blkstats_s *stats); + +/**************************************************************************** + * 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. + * + * Defined in nxffs_reformat.c + * + ****************************************************************************/ + +extern int nxffs_reformat(FAR struct nxffs_volume_s *volume); + +/**************************************************************************** + * Standard mountpoint operation methods + * + * Description: + * See include/nuttx/fs.h + * + * - nxffs_open() and nxffs_close() are defined in nxffs_open.c + * - nxffs_ioctl() is defined in nxffs_ioctl.c + * - nxffs_opendir(), nxffs_readdir(), and nxffs_rewindir() are defined in + * nxffs_dir.c + * - nxffs_stat() and nxffs_statfs() are defined in nxffs_stat.c + * - nxffs_unlink() is defined nxffs_unlink.c + * + ****************************************************************************/ + +struct file; /* Forward references */ +struct inode; +struct fs_dirent_s; +struct statfs; +struct stat; + +extern int nxffs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +extern int nxffs_close(FAR struct file *filep); +extern ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +extern ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +extern int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +extern int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct fs_dirent_s *dir); +extern int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); +extern int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); +extern int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data, + FAR void **handle); +extern int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver); +extern int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf); +extern int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct stat *buf); +extern int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath); + +#endif /* __FS_NXFFS_NXFFS_H */ + + diff --git a/fs/nxffs/nxffs_block.c b/fs/nxffs/nxffs_block.c new file mode 100644 index 0000000000..fd49df8f27 --- /dev/null +++ b/fs/nxffs/nxffs_block.c @@ -0,0 +1,166 @@ +/**************************************************************************** + * fs/nxffs/nxffs_block.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#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; +} diff --git a/fs/nxffs/nxffs_blockstats.c b/fs/nxffs/nxffs_blockstats.c new file mode 100644 index 0000000000..8ad6f09787 --- /dev/null +++ b/fs/nxffs/nxffs_blockstats.c @@ -0,0 +1,153 @@ +/**************************************************************************** + * fs/nxffs/nxffs_blockstats.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include + +#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; +} + + diff --git a/fs/nxffs/nxffs_cache.c b/fs/nxffs/nxffs_cache.c new file mode 100644 index 0000000000..0e7cff2561 --- /dev/null +++ b/fs/nxffs/nxffs_cache.c @@ -0,0 +1,243 @@ +/**************************************************************************** + * fs/nxffs/nxffs_cache.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include + +#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; +} + diff --git a/fs/nxffs/nxffs_initialize.c b/fs/nxffs/nxffs_initialize.c new file mode 100644 index 0000000000..f473d55c50 --- /dev/null +++ b/fs/nxffs/nxffs_initialize.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * fs/nxffs/nxffs_initialize.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include +#include +#include +#include + +#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" +} + diff --git a/fs/nxffs/nxffs_inode.c b/fs/nxffs/nxffs_inode.c new file mode 100644 index 0000000000..a0b2fc0ef1 --- /dev/null +++ b/fs/nxffs/nxffs_inode.c @@ -0,0 +1,380 @@ +/**************************************************************************** + * fs/nxffs/nxffs_inode.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/fs/nxffs/nxffs_reformat.c b/fs/nxffs/nxffs_reformat.c new file mode 100644 index 0000000000..8f34a93734 --- /dev/null +++ b/fs/nxffs/nxffs_reformat.c @@ -0,0 +1,281 @@ +/**************************************************************************** + * fs/nxffs/nxffs_reformat.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include + +#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; +} diff --git a/fs/nxffs/nxffs_util.c b/fs/nxffs/nxffs_util.c new file mode 100644 index 0000000000..9eea32243e --- /dev/null +++ b/fs/nxffs/nxffs_util.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * fs/nxffs/nxffs_util.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#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); +} + diff --git a/fs/romfs/Make.defs b/fs/romfs/Make.defs index 172eb27b9a..56b4c9862a 100644 --- a/fs/romfs/Make.defs +++ b/fs/romfs/Make.defs @@ -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 # # 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