This all makes for a far cleaner layout of test code.
The new yaffs direct list management allows partitions to be added synamically rather than
statically. This is better for OSs that install partitions at runtime (eg. WInCE).
The nand abstraction makes it tidier to add a new nand driver to yaffs direct and test code.
The test code has been repartitioned to make porting and file management cleaner.
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
#define __EXTRAS_H__
+#include "yportenv.h"
+
#if !(defined __KERNEL__)
/* Definition of types */
#endif
-/*
- * This is a simple doubly linked list implementation that matches the
- * way the Linux kernel doubly linked list implementation works.
- */
-
-struct ylist_head {
- struct ylist_head *next; /* next in chain */
- struct ylist_head *prev; /* previous in chain */
-};
-
-
-/* Initialise a static list */
-#define YLIST_HEAD(name) \
-struct ylist_head name = { &(name), &(name)}
-
-
-
-/* Initialise a list head to an empty list */
-#define YINIT_LIST_HEAD(p) \
-do { \
- (p)->next = (p);\
- (p)->prev = (p); \
-} while (0)
-
-
-/* Add an element to a list */
-static __inline__ void ylist_add(struct ylist_head *newEntry,
- struct ylist_head *list)
-{
- struct ylist_head *listNext = list->next;
-
- list->next = newEntry;
- newEntry->prev = list;
- newEntry->next = listNext;
- listNext->prev = newEntry;
-
-}
-
-static __inline__ void ylist_add_tail(struct ylist_head *newEntry,
- struct ylist_head *list)
-{
- struct ylist_head *listPrev = list->prev;
-
- list->prev = newEntry;
- newEntry->next = list;
- newEntry->prev = listPrev;
- listPrev->next = newEntry;
-
-}
-
-
-/* Take an element out of its current list, with or without
- * reinitialising the links.of the entry*/
-static __inline__ void ylist_del(struct ylist_head *entry)
-{
- struct ylist_head *listNext = entry->next;
- struct ylist_head *listPrev = entry->prev;
-
- listNext->prev = listPrev;
- listPrev->next = listNext;
-
-}
-
-static __inline__ void ylist_del_init(struct ylist_head *entry)
-{
- ylist_del(entry);
- entry->next = entry->prev = entry;
-}
-
-
-/* Test if the list is empty */
-static __inline__ int ylist_empty(struct ylist_head *entry)
-{
- return (entry->next == entry);
-}
-
-
-/* ylist_entry takes a pointer to a list entry and offsets it to that
- * we can find a pointer to the object it is embedded in.
- */
-
-
-#define ylist_entry(entry, type, member) \
- ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
-
-
-/* ylist_for_each and list_for_each_safe iterate over lists.
- * ylist_for_each_safe uses temporary storage to make the list delete safe
- */
-
-#define ylist_for_each(itervar, list) \
- for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
-
-#define ylist_for_each_safe(itervar, saveVar, list) \
- for (itervar = (list)->next, saveVar = (list)->next->next; \
- itervar != (list); itervar = saveVar, saveVar = saveVar->next)
-
#if !(defined __KERNEL__)
#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
-
COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
yaffs_checkptrw.o yaffs_qsort.o\
yaffs_nameval.o \
- yaffs_norif1.o ynorsim.o \
- yaffs_allocator.o yaffs_yaffs1.o \
+ yaffs_norif1.o ynorsim.o nor_stress.o yaffs_fsx.o \
+ yaffs_allocator.o \
+ yaffs_bitmap.o \
+ yaffs_yaffs1.o \
yaffs_yaffs2.o \
- yaffs_bitmap.o yaffs_verify.o
+ yaffs_verify.o
# yaffs_checkptrwtest.o\
-DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o
+YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o
-BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o
-
-#ALLOBJS = dtest.o nand_ecc.o yaffscfg.o yaffs_fileem.o yaffsfs.o yaffs_ramdisk.o bootldtst.o yboot.o yaffs_ramem2k.o
-ALLOBJS = $(sort $(DIRECTTESTOBJS) $(YAFFSTESTOBJS))
+ALLOBJS = $(sort $(YAFFSTESTOBJS))
-SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
+YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_nandemul2k.h \
- yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
+ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h yaffs_list.h \
yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
- yaffs_nameval.h yaffs_nameval.c \
+ yaffs_nameval.c yaffs_nameval.h \
yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \
yaffs_allocator.c yaffs_allocator.h \
- yaffs_bitmap.c yaffs_bitmap.h \
yaffs_yaffs1.c yaffs_yaffs1.h \
yaffs_yaffs2.c yaffs_yaffs2.h \
+ yaffs_bitmap.c yaffs_bitmap.h \
yaffs_verify.c yaffs_verify.h
-#all: directtest2k boottest
+YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
+ yaffsfs.h yaffs_malloc.h ydirectenv.h \
+ yaffs_flashif.c \
+ yaffs_nandif.c yaffs_nandif.h
+
-all: directtest2k
+
+SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS)
+
+
+
+
+COMMONTESTOBJS = yaffsnewcfg.o yramsim.o \
+ yaffsfs.o yaffs_guts.o yaffs_ecc.o yaffs_nandif.o \
+ yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
+ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
+ yaffs_checkptrw.o yaffs_qsort.o\
+ yaffs_nameval.o \
+ yaffs_norif1.o ynorsim.o \
+ yaffs_allocator.o yaffs_yaffs1.o \
+ yaffs_yaffs2.o \
+ yaffs_bitmap.o yaffs_verify.o
+
+# yaffs_checkptrwtest.o\
+
+DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o
+
+BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o
+
+ALLOBJS = $(sort $(DIRECTTESTOBJS) $(YAFFSTESTOBJS))
+
+TARGETS = directtest2k
+
+all: $(TARGETS)
$(ALLOBJS): %.o: %.c
gcc -c $(CFLAGS) -o $@ $<
-$(SYMLINKS):
+
+$(YAFFSSYMLINKS):
+ ln -s ../../$@ $@
+
+$(YAFFSDIRECTSYMLINKS):
ln -s ../$@ $@
+
directtest2k: $(SYMLINKS) $(DIRECTTESTOBJS)
gcc -o $@ $(DIRECTTESTOBJS)
clean:
- rm -f $(ALLOBJS) core core $(SYMLINKS)
+ rm -f $(TARGETS) $(ALLOBJS) core core $(SYMLINKS)
__u32 *Block2Addr(yaffs_Device *dev, int blockNumber)
{
__u32 addr;
+ dev=dev;
addr = (__u32) DEVICE_BASE;
addr += blockNumber * BLOCK_SIZE_IN_BYTES;
__u32 *Block2FormatAddr(yaffs_Device *dev,int blockNumber)
{
__u32 addr;
-
+
addr = (__u32) Block2Addr(dev,blockNumber);
addr += FORMAT_OFFSET;
int ynorif1_DeinitialiseNAND(yaffs_Device *dev)
{
-
+ dev=dev;
ynorif1_FlashDeinit();
return YAFFS_OK;
#include "yaffsfs.h"
#include <errno.h>
+
+#include "yramsim.h"
+
unsigned yaffs_traceMask = 0xFFFFFFFF;
// Stuff to initialise anything special (eg lock semaphore).
yaffsfs_LocalInitialisation();
+#if 1
+ yramsim_CreateSim("yaffs2");
+#else
// Set up devices
// /ram
flashDev.initialiseNAND = yflash_InitialiseNAND;
yaffs_initialise(yaffsfs_config);
+#endif
return 0;
}
#include "yportenv.h"
+#include "devextras.h"
#define YAFFSFS_N_HANDLES 100
*/
#include "yaffscfg.h"
+#include "yaffs_guts.h"
#include "yaffsfs.h"
#include "yaffs_fileem2k.h"
#include "yaffs_nandemul2k.h"
#include "yaffs_norif1.h"
#include "yaffs_trace.h"
+
#include <errno.h>
unsigned yaffs_traceMask =
#include "yaffs_flashif2.h"
#include "yaffs_nandemul2k.h"
-static yaffs_Device ram1Dev;
-static yaffs_Device flashDev;
-static yaffs_Device ram2kDev;
-static yaffs_Device m18_1Dev;
-
-static yaffsfs_DeviceConfiguration yaffsfs_config[] = {
-
- { "/ram1", &ram1Dev},
- { "/M18-1", &m18_1Dev},
- { "/yaffs2", &flashDev},
- { "/ram2k", &ram2kDev},
- { NULL, NULL } /* Null entry to terminate list */
-};
-
+struct yaffs_DeviceStruct ram1Dev;
+struct yaffs_DeviceStruct flashDev;
+struct yaffs_DeviceStruct m18_1Dev;
int yaffs_StartUp(void)
{
// Set up devices
// /ram1 ram, yaffs1
memset(&ram1Dev,0,sizeof(ram1Dev));
+ ram1Dev.param.name = "ram1";
ram1Dev.param.totalBytesPerChunk = 512;
ram1Dev.param.nChunksPerBlock = 32;
ram1Dev.param.nReservedBlocks = 2; // Set this smaller for RAM
ram1Dev.param.endBlock = 127; // Last block in 2MB.
//ram1Dev.param.useNANDECC = 1;
ram1Dev.param.nShortOpCaches = 0; // Disable caching on this device.
- ram1Dev.context = (void *) 0; // Used to identify the device in fstat.
+ ram1Dev.driverContext = (void *) 0; // Used to identify the device in fstat.
ram1Dev.param.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND;
ram1Dev.param.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND;
ram1Dev.param.eraseBlockInNAND = yramdisk_EraseBlockInNAND;
ram1Dev.param.initialiseNAND = yramdisk_InitialiseNAND;
+
+ yaffs_AddDevice(&ram1Dev);
// /M18-1 yaffs1 on M18 nor sim
memset(&m18_1Dev,0,sizeof(m18_1Dev));
+ m18_1Dev.param.name = "M18-1";
m18_1Dev.param.totalBytesPerChunk = 1024;
m18_1Dev.param.nChunksPerBlock =248;
m18_1Dev.param.nReservedBlocks = 2;
m18_1Dev.param.endBlock = 31; // Last block
m18_1Dev.param.useNANDECC = 0; // use YAFFS's ECC
m18_1Dev.param.nShortOpCaches = 10; // Use caches
- m18_1Dev.context = (void *) 1; // Used to identify the device in fstat.
+ m18_1Dev.driverContext = (void *) 1; // Used to identify the device in fstat.
m18_1Dev.param.writeChunkToNAND = ynorif1_WriteChunkToNAND;
m18_1Dev.param.readChunkFromNAND = ynorif1_ReadChunkFromNAND;
m18_1Dev.param.eraseBlockInNAND = ynorif1_EraseBlockInNAND;
m18_1Dev.param.initialiseNAND = ynorif1_InitialiseNAND;
m18_1Dev.param.deinitialiseNAND = ynorif1_DeinitialiseNAND;
+ yaffs_AddDevice(&m18_1Dev);
// /yaffs2 yaffs2 file emulation
// 2kpage/64chunk per block
//
memset(&flashDev,0,sizeof(flashDev));
-
+ flashDev.param.name = "yaffs2";
flashDev.param.totalBytesPerChunk = 2048;
flashDev.param.nChunksPerBlock = 64;
flashDev.param.nReservedBlocks = 5;
flashDev.param.wideTnodesDisabled=0;
flashDev.param.refreshPeriod = 1000;
flashDev.param.nShortOpCaches = 10; // Use caches
- flashDev.context = (void *) 2; // Used to identify the device in fstat.
+ flashDev.driverContext = (void *) 2; // Used to identify the device in fstat.
flashDev.param.writeChunkWithTagsToNAND = yflash2_WriteChunkWithTagsToNAND;
flashDev.param.readChunkWithTagsFromNAND = yflash2_ReadChunkWithTagsFromNAND;
flashDev.param.eraseBlockInNAND = yflash2_EraseBlockInNAND;
flashDev.param.queryNANDBlock = yflash2_QueryNANDBlock;
flashDev.param.enableXattr = 1;
+ yaffs_AddDevice(&flashDev);
- yaffs_initialise(yaffsfs_config);
+// todo yaffs_initialise(yaffsfs_config);
return 0;
}
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * yaffscfg2k.c The configuration for the "direct" use of yaffs.
+ *
+ * This file is intended to be modified to your requirements.
+ * There is no need to redistribute this file.
+ */
+
+#include "yaffscfg.h"
+#include "yaffsfs.h"
+#include "yaffs_trace.h"
+#include "yramsim.h"
+
+unsigned yaffs_traceMask =
+
+ YAFFS_TRACE_SCAN |
+ YAFFS_TRACE_GC |
+ YAFFS_TRACE_ERASE |
+ YAFFS_TRACE_ERROR |
+ YAFFS_TRACE_TRACING |
+ YAFFS_TRACE_ALLOCATE |
+ YAFFS_TRACE_BAD_BLOCKS |
+ YAFFS_TRACE_VERIFY |
+
+ 0;
+
+
+static int yaffsfs_lastError;
+
+void yaffsfs_SetError(int err)
+{
+ //Do whatever to set error
+ yaffsfs_lastError = err;
+}
+
+
+int yaffsfs_GetLastError(void)
+{
+ return yaffsfs_lastError;
+}
+
+void yaffsfs_Lock(void)
+{
+}
+
+void yaffsfs_Unlock(void)
+{
+}
+
+__u32 yaffsfs_CurrentTime(void)
+{
+ return 0;
+}
+
+
+static int yaffs_kill_alloc = 0;
+static size_t total_malloced = 0;
+static size_t malloc_limit = 0 & 6000000;
+
+void *yaffs_malloc(size_t size)
+{
+ void * this;
+ if(yaffs_kill_alloc)
+ return NULL;
+ if(malloc_limit && malloc_limit <(total_malloced + size) )
+ return NULL;
+
+ this = malloc(size);
+ if(this)
+ total_malloced += size;
+ return this;
+}
+
+void yaffs_free(void *ptr)
+{
+ free(ptr);
+}
+
+void yaffsfs_LocalInitialisation(void)
+{
+ // Define locking semaphore.
+}
+
+// Configuration
+
+
+int yaffs_StartUp(void)
+{
+ // Stuff to configure YAFFS
+ // Stuff to initialise anything special (eg lock semaphore).
+ yaffsfs_LocalInitialisation();
+
+ yramsim_CreateSim("yaffs2",200);
+ yramsim_CreateSim("yaffs2-2",50);
+
+ return 0;
+}
+
+
+
--- /dev/null
+// NAND Simulator for testing YAFFS\r
+\r
+#include <string.h>\r
+\r
+#include "yramsim.h"\r
+\r
+#include "yaffs_nandif.h"\r
+\r
+\r
+#ifdef __WINCE__\r
+#include <windows.h>\r
+#else\r
+#define DebugBreak() do { } while(0)\r
+#endif\r
+\r
+\r
+#define DATA_SIZE 2048\r
+#define SPARE_SIZE 64\r
+#define PAGE_SIZE (DATA_SIZE + SPARE_SIZE)\r
+#define PAGES_PER_BLOCK 64\r
+\r
+\r
+typedef struct {\r
+ unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];\r
+ unsigned blockOk;\r
+} Block;\r
+\r
+typedef struct {\r
+ Block **blockList;\r
+ int nBlocks;\r
+} SymData;\r
+\r
+\r
+static SymData *DevToSym(yaffs_Device *dev)\r
+{\r
+ ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext);\r
+ SymData * sym = (SymData*)(geom->privateData);\r
+ return sym;\r
+} \r
+\r
+\r
+static void CheckInitialised(void)\r
+{\r
+\r
+}\r
+\r
+static int yramsim_EraseBlockInternal(SymData *sym, unsigned blockId,int force)\r
+{\r
+ if(blockId < 0 || blockId >= sym->nBlocks){\r
+ DebugBreak();\r
+ return 0;\r
+ }\r
+\r
+ if(!sym->blockList[blockId]){\r
+ DebugBreak();\r
+ return 0;\r
+ }\r
+\r
+ if(!force && !sym->blockList[blockId]->blockOk){\r
+ DebugBreak();\r
+ return 0;\r
+ }\r
+\r
+ memset(sym->blockList[blockId],0xff,sizeof(Block));\r
+ sym->blockList[blockId]->blockOk = 1;\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+\r
+\r
+static int yramsim_Initialise(yaffs_Device *dev)\r
+{\r
+ SymData *sym = DevToSym(dev);\r
+ Block **blockList = sym->blockList;\r
+ return blockList != NULL;\r
+}\r
+\r
+\r
+static int yramsim_Deinitialise(yaffs_Device *dev)\r
+{\r
+ return 1;\r
+}\r
+\r
+static int yramsim_ReadChunk (yaffs_Device *dev, unsigned pageId, \r
+ unsigned char *data, unsigned dataLength,\r
+ unsigned char *spare, unsigned spareLength,\r
+ int *eccStatus)\r
+{\r
+ SymData *sym = DevToSym(dev);\r
+ Block **blockList = sym->blockList;\r
+\r
+ unsigned blockId = pageId / PAGES_PER_BLOCK;\r
+ unsigned pageOffset = pageId % PAGES_PER_BLOCK;\r
+ unsigned char * d;\r
+ unsigned char *s;\r
+ if(blockId >= sym->nBlocks ||\r
+ pageOffset >= PAGES_PER_BLOCK ||\r
+ dataLength >DATA_SIZE ||\r
+ spareLength > SPARE_SIZE ||\r
+ !eccStatus ||\r
+ !blockList[blockId]->blockOk){\r
+ DebugBreak();\r
+ return 0;\r
+ }\r
+\r
+ d = blockList[blockId]->page[pageOffset];\r
+ s = d + DATA_SIZE;\r
+\r
+ if(data)\r
+ memcpy(data,d,dataLength);\r
+\r
+ if(spare)\r
+ memcpy(spare,s,spareLength);\r
+\r
+ *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable\r
+\r
+ return 1;\r
+ \r
+}\r
+\r
+static int yramsim_WriteChunk (yaffs_Device *dev,unsigned pageId, \r
+ const unsigned char *data, unsigned dataLength,\r
+ const unsigned char *spare, unsigned spareLength)\r
+{\r
+ SymData *sym = DevToSym(dev);\r
+ Block **blockList = sym->blockList;\r
+\r
+ unsigned blockId = pageId / PAGES_PER_BLOCK;\r
+ unsigned pageOffset = pageId % PAGES_PER_BLOCK;\r
+ unsigned char * d;\r
+ unsigned char *s;\r
+ if(blockId >= sym->nBlocks ||\r
+ pageOffset >= PAGES_PER_BLOCK ||\r
+ dataLength >DATA_SIZE ||\r
+ spareLength > SPARE_SIZE ||\r
+ !blockList[blockId]->blockOk){\r
+ DebugBreak();\r
+ return 0;\r
+ }\r
+\r
+ d = blockList[blockId]->page[pageOffset];\r
+ s = d + DATA_SIZE;\r
+\r
+ if(data)\r
+ memcpy(d,data,dataLength);\r
+\r
+ if(spare)\r
+ memcpy(s,spare,spareLength);\r
+\r
+ return 1;\r
+ \r
+}\r
+\r
+\r
+static int yramsim_EraseBlock(yaffs_Device *dev,unsigned blockId)\r
+{\r
+ SymData *sym = DevToSym(dev);\r
+\r
+ CheckInitialised();\r
+ return yramsim_EraseBlockInternal(sym,blockId,0);\r
+}\r
+\r
+static int yramsim_CheckBlockOk(yaffs_Device *dev,unsigned blockId)\r
+{\r
+ SymData *sym = DevToSym(dev);\r
+ Block **blockList = sym->blockList;\r
+ if(blockId >= sym->nBlocks){\r
+ DebugBreak();\r
+ return 0;\r
+ }\r
+\r
+ return blockList[blockId]->blockOk ? 1 : 0;\r
+}\r
+\r
+static int yramsim_MarkBlockBad(yaffs_Device *dev,unsigned blockId)\r
+{\r
+ SymData *sym = DevToSym(dev);\r
+ Block **blockList = sym->blockList;\r
+ if(blockId >= sym->nBlocks){\r
+ DebugBreak();\r
+ return 0;\r
+ }\r
+\r
+ blockList[blockId]->blockOk = 0;\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+static SymData *yramsim_AllocSymData(int nBlocks)\r
+{\r
+ int ok = 1;\r
+\r
+ Block **blockList;\r
+ SymData *sym;\r
+ Block *b;\r
+ int i;\r
+\r
+ sym = malloc(sizeof (SymData));\r
+ if(!sym)\r
+ return NULL;\r
+\r
+ blockList = malloc(nBlocks * sizeof(Block *));\r
+ \r
+ sym->blockList = blockList;\r
+ sym->nBlocks = nBlocks;\r
+ if(!blockList){\r
+ free(sym);\r
+ return NULL;\r
+ }\r
+\r
+ for(i = 0; i < nBlocks; i++)\r
+ blockList[i] = NULL;\r
+\r
+ for(i = 0; i < nBlocks && ok; i++){\r
+ b= malloc(sizeof(Block));\r
+ if(b){\r
+ blockList[i] = b;\r
+ yramsim_EraseBlockInternal(sym,i,1);\r
+ }\r
+ else\r
+ ok = 0;\r
+ }\r
+\r
+ if(!ok){\r
+ for(i = 0; i < nBlocks; i++)\r
+ if(blockList[i]){\r
+ free(blockList[i]);\r
+ blockList[i] = NULL;\r
+ }\r
+ free(blockList);\r
+ blockList = NULL;\r
+ free(sym);\r
+ sym = NULL;\r
+ }\r
+\r
+ return sym;\r
+}\r
+\r
+\r
+struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name,int nBlocks)\r
+{\r
+ void *sym = (void *)yramsim_AllocSymData(nBlocks);\r
+ ynandif_Geometry *g;\r
+\r
+ g = YMALLOC(sizeof(ynandif_Geometry));\r
+ \r
+ if(!sym || !g){\r
+ if(sym)\r
+ YFREE(sym);\r
+ if(g)\r
+ YFREE(g);\r
+ return NULL;\r
+ }\r
+\r
+ memset(g,0,sizeof(ynandif_Geometry));\r
+ g->startBlock = 0;\r
+ g->endBlock = nBlocks - 1;\r
+ g->dataSize = DATA_SIZE;\r
+ g->spareSize= SPARE_SIZE;\r
+ g->pagesPerBlock = PAGES_PER_BLOCK;\r
+ g->hasECC = 1;\r
+ g->inbandTags = 0;\r
+ g->useYaffs2 = 1;\r
+ g->initialise = yramsim_Initialise;\r
+ g->deinitialise = yramsim_Deinitialise; \r
+ g->readChunk = yramsim_ReadChunk, \r
+ g->writeChunk = yramsim_WriteChunk,\r
+ g->eraseBlock = yramsim_EraseBlock,\r
+ g->checkBlockOk = yramsim_CheckBlockOk,\r
+ g->markBlockBad = yramsim_MarkBlockBad,\r
+ g->privateData = sym;\r
+\r
+ return yaffs_AddDeviceFromGeometry(name,g);\r
+}
--- /dev/null
+// NAND Simulator for testing YAFFS\r
+#ifndef __YAFF_RAM_SIM_H__\r
+#define __YAFF_RAM_SIM_H__\r
+\r
+\r
+#include "yaffs_guts.h"\r
+\r
+struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name, int nBlocks);\r
+\r
+\r
+#endif\r
#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
-COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
+COMMONTESTOBJS = yaffsnewcfg.o yramsim.o \
+ yaffs_nandif.o \
+ yaffsfs.o yaffs_ecc.o yaffs_guts.o \
yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
yaffs_checkptrw.o yaffs_qsort.o\
YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_nandemul2k.h \
- yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
+ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h yaffs_list.h \
yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
yaffs_nameval.c yaffs_nameval.h \
yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \
yaffs_verify.c yaffs_verify.h
-YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
- yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \
- yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c\
- yaffs_norif1.c yaffs_norif1.h ynorsim.c ynorsim.h \
+YAFFSDIRECTSYMLINKS = yaffsfs.c yaffsfs.h yaffs_malloc.h ydirectenv.h \
+ yaffs_flashif.c yaffs_flashif.h\
yaffs_nandif.c yaffs_nandif.h
-
-SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS)
+DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffscfg.h yaffs_fileem2k.c yaffs_fileem2k.h\
+ yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \
+ yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \
+ yaffsnewcfg.c yramsim.c yramsim.h \
+ ynorsim.h ynorsim.c
+
+SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS)
all: libyaffsfs.so
$(YAFFSDIRECTSYMLINKS):
ln -s ../$@ $@
+$(DIRECTEXTRASYMLINKS):
+ ln -s ../basic-test/$@ $@
libyaffsfs.so: $(SYMLINKS) $(YAFFSLIBOBJS)
clean:
- rm -f $(YAFFSLIBOBJS) core $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS)
+ rm -f $(YAFFSLIBOBJS) core $(SYMLINKS)
rm -f libyaffsfs.so
rm -f *.pyc
#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2
-CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE
+CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES
CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing
#CFLAGS += -fno-strict-aliasing
CFLAGS += -O0
YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o
-#ALLOBJS = dtest.o nand_ecc.o yaffscfg.o yaffs_fileem.o yaffsfs.o yaffs_ramdisk.o bootldtst.o yboot.o yaffs_ramem2k.o
-
ALLOBJS = $(sort $(YAFFSTESTOBJS))
YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_nandemul2k.h \
- yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
+ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h yaffs_list.h \
yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
yaffs_nameval.c yaffs_nameval.h \
yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \
yaffs_bitmap.c yaffs_bitmap.h \
yaffs_verify.c yaffs_verify.h
-YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
- yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \
- yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c\
- yaffs_norif1.c yaffs_norif1.h ynorsim.c ynorsim.h \
+YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
+ yaffsfs.h yaffs_malloc.h ydirectenv.h \
+ yaffs_flashif.c \
yaffs_nandif.c yaffs_nandif.h
-SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS)
+DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffscfg.h yaffs_fileem2k.c yaffs_fileem2k.h\
+ yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \
+ yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \
+ ynorsim.h ynorsim.c
+
+SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS)
#all: directtest2k boottest
all: yaffs_test fuzzer
$(YAFFSDIRECTSYMLINKS):
ln -s ../$@ $@
+$(DIRECTEXTRASYMLINKS):
+ ln -s ../basic-test/$@ $@
+
yaffs_test: $(SYMLINKS) $(YAFFSTESTOBJS)
gcc $(CFLLAG) -o $@ $(YAFFSTESTOBJS)
clean:
- rm -f yaffs_test fuzzer fuzzer.o $(ALLOBJS) core $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS)
+ rm -f yaffs_test fuzzer fuzzer.o $(ALLOBJS) core $(SYMLINKS)
-/*\r
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.\r
- *\r
- * Copyright (C) 2002-2010 Aleph One Ltd.\r
- * for Toby Churchill Ltd and Brightstar Engineering\r
- *\r
- * Created by Charles Manning <charles@aleph1.co.uk>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License version 2 as\r
- * published by the Free Software Foundation.\r
- */\r
-\r
-\r
-\r
-\r
-#include "yportenv.h"\r
-#include "yaffs_guts.h"\r
-#include "devextras.h"\r
-\r
-\r
-#include "yaffs_nandif.h"\r
-#include "yaffs_packedtags2.h"\r
-\r
-\r
-#if 0\r
-\r
-\r
-static unsigned char *DevBufferIn(yaffs_Device *dev)\r
-{\r
- yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
- return cedev->bufferIn;\r
-}\r
-static unsigned char *DevBufferOut(yaffs_Device *dev)\r
-{\r
- yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
- return cedev->bufferOut;\r
-}\r
-\r
-static unsigned DevBufferSize(yaffs_Device *dev)\r
-{\r
- yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
- return cedev->bufferSize;\r
-}\r
-\r
-#endif\r
-\r
-/* NB For use with inband tags....\r
- * We assume that the data buffer is of size totalBytersPerChunk so that we can also\r
- * use it to load the tags.\r
- */\r
-int ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,\r
- const __u8 * data,\r
- const yaffs_ExtendedTags * tags)\r
-{\r
-\r
- int retval = 0;\r
- yaffs_PackedTags2 pt;\r
- void *spare;\r
- unsigned spareSize = 0;\r
-\r
- unsigned char *bufferIn = DevBufferIn(dev);\r
- unsigned char *bufferOut = DevBufferOut(dev);\r
- unsigned bufferSize = DevBufferSize(dev);\r
-\r
- T(YAFFS_TRACE_MTD,\r
- (TSTR\r
- ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"\r
- TENDSTR), chunkInNAND, data, tags));\r
- \r
-\r
- /* For yaffs2 writing there must be both data and tags.\r
- * If we're using inband tags, then the tags are stuffed into\r
- * the end of the data buffer.\r
- */\r
-\r
- if(dev->inbandTags){\r
- yaffs_PackedTags2TagsPart *pt2tp;\r
- pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);\r
- yaffs_PackTags2TagsPart(pt2tp,tags);\r
- spare = NULL;\r
- spareSize = 0;\r
- }\r
- else{\r
- yaffs_PackTags2(&pt, tags);\r
- spare = &pt;\r
- spareSize = sizeof(yaffs_PackedTags2);\r
- }\r
- \r
- yramsim_WritePage(chunkInNAND,\r
- data, dev->totalBytesPerChunk, spare, spareSize);\r
-\r
- return YAFFS_OK;\r
-}\r
-\r
-int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,\r
- __u8 * data, yaffs_ExtendedTags * tags)\r
-{\r
- yaffs_PackedTags2 pt;\r
- int localData = 0;\r
- void *spare = NULL;\r
- unsigned spareSize;\r
- int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed\r
-\r
- unsigned char *bufferIn = DevBufferIn(dev);\r
- unsigned char *bufferOut = DevBufferOut(dev);\r
- unsigned bufferSize = DevBufferSize(dev);\r
-\r
- T(YAFFS_TRACE_MTD,\r
- (TSTR\r
- ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"\r
- TENDSTR), chunkInNAND, data, tags));\r
- \r
- if(!tags){\r
- spare = NULL;\r
- spareSize = 0;\r
- }else if(dev->inbandTags){\r
- \r
- if(!data) {\r
- localData = 1;\r
- data = yaffs_GetTempBuffer(dev,__LINE__);\r
- }\r
- spare = NULL;\r
- spareSize = 0;\r
- }\r
- else {\r
- spare = &pt;\r
- spareSize = sizeof(yaffs_PackedTags2);\r
- }\r
-\r
- yramsim_ReadPage(chunkInNAND,\r
- data,data ? dev->totalBytesPerChunk : 0,\r
- spare,spareSize,\r
- &eccStatus);\r
-\r
-\r
-\r
- if(dev->inbandTags){\r
- if(tags){\r
- yaffs_PackedTags2TagsPart * pt2tp;\r
- pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; \r
- yaffs_UnpackTags2TagsPart(tags,pt2tp);\r
- }\r
- }\r
- else {\r
- if (tags){\r
- yaffs_UnpackTags2(tags, &pt);\r
- }\r
- }\r
-\r
- if(tags && tags->chunkUsed){\r
- if(eccStatus == 0)\r
- tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR;\r
- else if(eccStatus < 0)\r
- tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;\r
- else\r
- tags->eccResult = YAFFS_ECC_RESULT_FIXED;\r
- }\r
-\r
- if(localData)\r
- yaffs_ReleaseTempBuffer(dev,data,__LINE__);\r
- \r
- return YAFFS_OK;\r
-}\r
-\r
-int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId)\r
-{\r
-\r
- yramsim_MarkBlockBad(blockId);\r
-\r
- return YAFFS_OK;\r
-}\r
-\r
-int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId)\r
-{\r
-\r
- yramsim_EraseBlock(blockId);\r
-\r
- return YAFFS_OK;\r
-}\r
-\r
-\r
-static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId)\r
-{\r
- return yramsim_CheckBlockOk(blockId);\r
-}\r
-\r
-int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber)\r
-{\r
- unsigned chunkNo;\r
- yaffs_ExtendedTags tags;\r
-\r
- *sequenceNumber = 0;\r
- \r
- chunkNo = blockId * dev->nChunksPerBlock;\r
- \r
- if(!ynandif_IsBlockOk(dev,blockId)){\r
- *state = YAFFS_BLOCK_STATE_DEAD;\r
- } \r
- else \r
- {\r
- ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);\r
-\r
- if(!tags.chunkUsed)\r
- {\r
- *state = YAFFS_BLOCK_STATE_EMPTY;\r
- }\r
- else \r
- {\r
- *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;\r
- *sequenceNumber = tags.sequenceNumber;\r
- }\r
- }\r
-\r
- return YAFFS_OK;\r
-}\r
-\r
-\r
-int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry)\r
-{\r
-\r
- yramsim_Geometry g;\r
-\r
- yramsim_GetGeometry(&g);\r
- geometry->startBlock = g.startBlock;\r
- geometry->endBlock = g.endBlock;\r
- geometry->dataSize = g.dataSize;\r
- geometry->spareSize = g.spareSize;\r
- geometry->pagesPerBlock = g.pagesPerBlock;\r
- geometry->hasECC = g.hasECC;\r
- geometry->inbandTags = g.inbandTags;\r
- geometry->useYaffs2 = g.useYaffs2;\r
-\r
- return YAFFS_OK;\r
-\r
-}\r
-\r
-int ynandif_InitialiseNAND(yaffs_Device *dev)\r
-{\r
-\r
- yramsim_Initialise();\r
-\r
- return YAFFS_OK;\r
-}\r
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "yportenv.h"
+#include "yaffs_guts.h"
+#include "devextras.h"
+
+
+#include "yaffs_nandif.h"
+#include "yaffs_packedtags2.h"
+
+#include "yramsim.h"
+
+#include "yaffs_trace.h"
+
+
+
+/* NB For use with inband tags....
+ * We assume that the data buffer is of size totalBytersPerChunk so that we can also
+ * use it to load the tags.
+ */
+int ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data,
+ const yaffs_ExtendedTags * tags)
+{
+
+ int retval = 0;
+ yaffs_PackedTags2 pt;
+ void *spare;
+ unsigned spareSize = 0;
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ T(YAFFS_TRACE_MTD,
+ (TSTR
+ ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
+ TENDSTR), chunkInNAND, data, tags));
+
+
+ /* For yaffs2 writing there must be both data and tags.
+ * If we're using inband tags, then the tags are stuffed into
+ * the end of the data buffer.
+ */
+
+ if(dev->param.inbandTags){
+ yaffs_PackedTags2TagsPart *pt2tp;
+ pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
+ yaffs_PackTags2TagsPart(pt2tp,tags);
+ spare = NULL;
+ spareSize = 0;
+ }
+ else{
+ yaffs_PackTags2(&pt, tags,!dev->param.noTagsECC);
+ spare = &pt;
+ spareSize = sizeof(yaffs_PackedTags2);
+ }
+
+ retval = geometry->writeChunk(dev,chunkInNAND,
+ data, dev->param.totalBytesPerChunk, spare, spareSize);
+
+ return retval;
+}
+
+int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
+ __u8 * data, yaffs_ExtendedTags * tags)
+{
+ yaffs_PackedTags2 pt;
+ int localData = 0;
+ void *spare = NULL;
+ unsigned spareSize;
+ int retval = 0;
+ int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ T(YAFFS_TRACE_MTD,
+ (TSTR
+ ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
+ TENDSTR), chunkInNAND, data, tags));
+
+ if(!tags){
+ spare = NULL;
+ spareSize = 0;
+ }else if(dev->param.inbandTags){
+
+ if(!data) {
+ localData = 1;
+ data = yaffs_GetTempBuffer(dev,__LINE__);
+ }
+ spare = NULL;
+ spareSize = 0;
+ }
+ else {
+ spare = &pt;
+ spareSize = sizeof(yaffs_PackedTags2);
+ }
+
+ retval = geometry->readChunk(dev,chunkInNAND,
+ data,
+ data ? dev->param.totalBytesPerChunk : 0,
+ spare,spareSize,
+ &eccStatus);
+
+ if(dev->param.inbandTags){
+ if(tags){
+ yaffs_PackedTags2TagsPart * pt2tp;
+ pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
+ yaffs_UnpackTags2TagsPart(tags,pt2tp);
+ }
+ }
+ else {
+ if (tags){
+ yaffs_UnpackTags2(tags, &pt,!dev->param.noTagsECC);
+ }
+ }
+
+ if(tags && tags->chunkUsed){
+ if(eccStatus < 0 ||
+ tags->eccResult == YAFFS_ECC_RESULT_UNFIXED)
+ tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
+ else if(eccStatus > 0 ||
+ tags->eccResult == YAFFS_ECC_RESULT_FIXED)
+ tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+ else
+ tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+ }
+
+ if(localData)
+ yaffs_ReleaseTempBuffer(dev,data,__LINE__);
+
+ return retval;
+}
+
+int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId)
+{
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ return geometry->markBlockBad(dev,blockId);
+}
+
+int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId)
+{
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ return geometry->eraseBlock(dev,blockId);
+
+}
+
+
+static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId)
+{
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ return geometry->checkBlockOk(dev,blockId);
+}
+
+int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber)
+{
+ unsigned chunkNo;
+ yaffs_ExtendedTags tags;
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ *sequenceNumber = 0;
+
+ chunkNo = blockId * dev->param.nChunksPerBlock;
+
+ if(!ynandif_IsBlockOk(dev,blockId)){
+ *state = YAFFS_BLOCK_STATE_DEAD;
+ }
+ else
+ {
+ ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
+
+ if(!tags.chunkUsed)
+ {
+ *state = YAFFS_BLOCK_STATE_EMPTY;
+ }
+ else
+ {
+ *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+ *sequenceNumber = tags.sequenceNumber;
+ }
+ }
+
+ return YAFFS_OK;
+}
+
+
+int ynandif_InitialiseNAND(yaffs_Device *dev)
+{
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ geometry->initialise(dev);
+
+ return YAFFS_OK;
+}
+
+int ynandif_DeinitialiseNAND(yaffs_Device *dev)
+{
+ ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext);
+
+ geometry->deinitialise(dev);
+
+ return YAFFS_OK;
+}
+
+
+struct yaffs_DeviceStruct *
+ yaffs_AddDeviceFromGeometry(const YCHAR *name,
+ const ynandif_Geometry *geometry)
+{
+ YCHAR *clonedName = YMALLOC(sizeof(YCHAR) * (yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH)+1));
+ struct yaffs_DeviceStruct *dev = YMALLOC(sizeof(struct yaffs_DeviceStruct));
+
+ if(dev && clonedName){
+ memset(dev,0,sizeof(struct yaffs_DeviceStruct));
+ yaffs_strcpy(clonedName,name);
+
+ dev->param.name = clonedName;
+ dev->param.writeChunkWithTagsToNAND = ynandif_WriteChunkWithTagsToNAND;
+ dev->param.readChunkWithTagsFromNAND = ynandif_ReadChunkWithTagsFromNAND;
+ dev->param.eraseBlockInNAND = ynandif_EraseBlockInNAND;
+ dev->param.initialiseNAND = ynandif_InitialiseNAND;
+ dev->param.queryNANDBlock = ynandif_QueryNANDBlock;
+ dev->param.markNANDBlockBad = ynandif_MarkNANDBlockBad;
+ dev->param.nShortOpCaches = 20;
+ dev->param.startBlock = geometry->startBlock;
+ dev->param.endBlock = geometry->endBlock;
+ dev->param.totalBytesPerChunk = geometry->dataSize;
+ dev->param.spareBytesPerChunk = geometry->spareSize;
+ dev->param.inbandTags = geometry->inbandTags;
+ dev->param.nChunksPerBlock = geometry->pagesPerBlock;
+ dev->param.useNANDECC = geometry->hasECC;
+ dev->param.isYaffs2 = geometry->useYaffs2;
+ dev->param.nReservedBlocks = 5;
+ dev->driverContext = (void *)geometry;
+
+ yaffs_AddDevice(dev);
+
+ return dev;
+ }
+
+ if(dev)
+ YFREE(dev);
+ if(clonedName)
+ YFREE(clonedName);
+
+ return NULL;
+}
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
- * Copyright (C) 2002-2010 Aleph One Ltd.
+ * Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
#include "yaffs_guts.h"
+
typedef struct {
- unsigned startBlock;
- unsigned endBlock;
- unsigned dataSize; // Number of data bytes per page
- unsigned spareSize; // Number of spare bytes per chunk
- unsigned pagesPerBlock;
- unsigned hasECC;
- unsigned inbandTags; // Use inband tags on this device
- unsigned useYaffs2;
+ unsigned startBlock;
+ unsigned endBlock;
+ unsigned dataSize;
+ unsigned spareSize;
+ unsigned pagesPerBlock;
+ unsigned hasECC;
+ unsigned inbandTags;
+ unsigned useYaffs2;
+
+ int (*initialise)(yaffs_Device *dev);
+ int (*deinitialise)(yaffs_Device *dev);
+
+ int (*readChunk) (yaffs_Device *dev,
+ unsigned pageId,
+ unsigned char *data, unsigned dataLength,
+ unsigned char *spare, unsigned spareLength,
+ int *eccStatus);
+// ECC status is set to 0 for OK, 1 for fixed, -1 for unfixed.
+
+ int (*writeChunk)(yaffs_Device *dev,
+ unsigned pageId,
+ const unsigned char *data, unsigned dataLength,
+ const unsigned char *spare, unsigned spareLength);
+
+ int (*eraseBlock)(yaffs_Device *dev, unsigned blockId);
+
+ int (*checkBlockOk)(yaffs_Device *dev, unsigned blockId);
+ int (*markBlockBad)(yaffs_Device *dev, unsigned blockId);
+
+ void *privateData;
+
} ynandif_Geometry;
+struct yaffs_DeviceStruct *
+ yaffs_AddDeviceFromGeometry(const YCHAR *name,
+ const ynandif_Geometry *geometry);
+
+#if 0
+
int ynandif_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
int ynandif_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
int ynandif_QueryNANDBlock(yaffs_Device *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber);
int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry);
#endif
+
+
+#endif
#define YAFFSFS_RW_SHIFT (13)
#define YAFFSFS_RW_SIZE (1<<YAFFSFS_RW_SHIFT)
-
-const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.35 2010-02-25 22:38:03 charles Exp $";
-
-/* configurationList is the list of devices that are supported */
-static yaffsfs_DeviceConfiguration *yaffsfs_configurationList;
-
-
/* Some forward references */
static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path, int symDepth);
static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj);
return 0;
}
+
+
+YLIST_HEAD(yaffsfs_deviceList);
+
/*
* yaffsfs_FindDevice
* yaffsfs_FindRoot
*/
static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath)
{
- yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;
+ struct ylist_head *cfg;
const YCHAR *leftOver;
const YCHAR *p;
yaffs_Device *retval = NULL;
+ yaffs_Device *dev = NULL;
int thisMatchLength;
int longestMatch = -1;
int matching;
* 1) Actually matches a prefix (ie /a amd /abc will not match
* 2) Matches the longest.
*/
- while(cfg && cfg->prefix && cfg->dev){
+ ylist_for_each(cfg, &yaffsfs_deviceList){
+ dev = ylist_entry(cfg, yaffs_Device, devList);
leftOver = path;
- p = cfg->prefix;
+ p = dev->param.name;
thisMatchLength = 0;
matching = 1;
/* Skip over any /s in leftOver */
while(yaffsfs_IsPathDivider(*leftOver))
leftOver++;
-
- if( matching && (thisMatchLength > longestMatch)){
- /* Matched prefix */
+ // Skip over any /s in p
+ while(yaffsfs_IsPathDivider(*p))
+ p++;
+
+ // p should now be at the end of the string (ie. fully matched)
+ if(*p)
+ matching = 0;
+
+ if( matching && (thisMatchLength > longestMatch))
+ {
+ // Matched prefix
*restOfPath = (YCHAR *)leftOver;
- retval = cfg->dev;
+ retval = dev;
longestMatch = thisMatchLength;
}
- cfg++;
}
return retval;
}
obj = yaffs_GetEquivalentObject(obj);
if(obj && buf){
- buf->st_dev = (int)obj->myDev->context;
+ buf->st_dev = (int)obj->myDev->osContext;
buf->st_ino = obj->objectId;
buf->st_mode = obj->yst_mode & ~S_IFMT; /* clear out file type bits */
}
-
-void yaffs_initialise(yaffsfs_DeviceConfiguration *cfgList)
+void yaffs_AddDevice(yaffs_Device *dev)
{
+ dev->isMounted = 0;
+ dev->param.removeObjectCallback = yaffsfs_RemoveObjectCallback;
- yaffsfs_DeviceConfiguration *cfg;
+ if(!dev->devList.next)
+ YINIT_LIST_HEAD(&dev->devList);
- yaffsfs_configurationList = cfgList;
-
- yaffsfs_InitHandles();
-
- cfg = yaffsfs_configurationList;
+ ylist_add(&dev->devList,&yaffsfs_deviceList);
+}
- while(cfg && cfg->prefix && cfg->dev){
- cfg->dev->isMounted = 0;
- cfg->dev->param.removeObjectCallback = yaffsfs_RemoveObjectCallback;
- cfg++;
- }
+void yaffs_RemoveDevice(yaffs_Device *dev)
+{
+ ylist_del_init(&dev->devList);
+}
-}
/* Directory search stuff. */
#endif
-#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES
-
-#ifndef O_RDONLY
-#define O_RDONLY 00
-#endif
-
-#ifndef O_WRONLY
-#define O_WRONLY 01
-#endif
-
-#ifndef O_RDWR
-#define O_RDWR 02
-#endif
-
-#ifndef O_CREAT
-#define O_CREAT 0100
-#endif
-
-#ifndef O_EXCL
-#define O_EXCL 0200
-#endif
-
-#ifndef O_TRUNC
-#define O_TRUNC 01000
-#endif
-
-#ifndef O_APPEND
-#define O_APPEND 02000
-#endif
-
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
-#endif
-
-#ifndef SEEK_END
-#define SEEK_END 2
-#endif
-
-#ifndef EBUSY
-#define EBUSY 16
-#endif
-
-#ifndef ENODEV
-#define ENODEV 19
-#endif
-
-#ifndef EINVAL
-#define EINVAL 22
-#endif
-
-#ifndef EBADF
-#define EBADF 9
-#endif
-
-#ifndef EACCES
-#define EACCES 13
-#endif
-
-#ifndef EXDEV
-#define EXDEV 18
-#endif
-
-#ifndef ENOENT
-#define ENOENT 2
-#endif
-
-#ifndef ENOSPC
-#define ENOSPC 28
-#endif
-
-#ifndef ERANGE
-#define ERANGE 34
-#endif
-
-#ifndef ENODATA
-#define ENODATA 61
-#endif
-
-#ifndef ENOTEMPTY
-#define ENOTEMPTY 39
-#endif
-
-#ifndef ENAMETOOLONG
-#define ENAMETOOLONG 36
-#endif
-
-#ifndef ENOMEM
-#define ENOMEM 12
-#endif
-
-#ifndef EEXIST
-#define EEXIST 17
-#endif
-
-#ifndef ENOTDIR
-#define ENOTDIR 20
-#endif
-
-#ifndef EISDIR
-#define EISDIR 21
-#endif
-
-
-// Mode flags
-
-#ifndef S_IFMT
-#define S_IFMT 0170000
-#endif
-
-#ifndef S_IFLNK
-#define S_IFLNK 0120000
-#endif
-
-#ifndef S_IFDIR
-#define S_IFDIR 0040000
-#endif
-
-#ifndef S_IFREG
-#define S_IFREG 0100000
-#endif
-
-#ifndef S_IREAD
-#define S_IREAD 0000400
-#endif
-
-#ifndef S_IWRITE
-#define S_IWRITE 0000200
-#endif
-
-#ifndef S_IEXEC
-#define S_IEXEC 0000100
-#endif
-
-#ifndef XATTR_CREATE
-#define XATTR_CREATE 1
-#endif
-
-#ifndef XATTR_REPLACE
-#define XATTR_REPLACE 2
-#endif
-
-#ifndef R_OK
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#define F_OK 0
-#endif
-
-#else
-#include <errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#endif
-
-
struct yaffs_dirent{
long d_ino; /* inode number */
off_t d_off; /* offset to this dirent */
int yaffs_inodecount(const YCHAR *path);
-
+struct yaffs_DeviceStruct;
+void yaffs_AddDevice(struct yaffs_DeviceStruct *dev);
int yaffs_StartUp(void);
// Direct interface
-#include "devextras.h"
-
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#ifdef NO_Y_INLINE
#define Y_INLINE
#else
-#define Y_INLINE inline
+#define Y_INLINE __inline__
#endif
#define YMALLOC(x) yaffs_malloc(x)
static void yaffs_GrossLock(yaffs_Device *dev)
{
T(YAFFS_TRACE_LOCK, (TSTR("yaffs locking %p\n"), current));
- down(&(yaffs_DeviceToContext(dev)->grossLock));
+ down(&(yaffs_DeviceToLC(dev)->grossLock));
T(YAFFS_TRACE_LOCK, (TSTR("yaffs locked %p\n"), current));
}
static void yaffs_GrossUnlock(yaffs_Device *dev)
{
T(YAFFS_TRACE_LOCK, (TSTR("yaffs unlocking %p\n"), current));
- up(&(yaffs_DeviceToContext(dev)->grossLock));
+ up(&(yaffs_DeviceToLC(dev)->grossLock));
}
#ifdef YAFFS_COMPILE_EXPORTFS
dir->variant.directoryVariant.children.next,
yaffs_Object,siblings);
YINIT_LIST_HEAD(&sc->others);
- ylist_add(&sc->others,&(yaffs_DeviceToContext(dev)->searchContexts));
+ ylist_add(&sc->others,&(yaffs_DeviceToLC(dev)->searchContexts));
}
return sc;
}
struct ylist_head *i;
struct yaffs_SearchContext *sc;
- struct ylist_head *search_contexts = &(yaffs_DeviceToContext(obj->myDev)->searchContexts);
+ struct ylist_head *search_contexts = &(yaffs_DeviceToLC(obj->myDev)->searchContexts);
/* Iterate through the directory search contexts.
yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
- if(current != yaffs_DeviceToContext(dev)->readdirProcess)
+ if(current != yaffs_DeviceToLC(dev)->readdirProcess)
yaffs_GrossLock(dev);
T(YAFFS_TRACE_OS,
obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */
/* Can't hold gross lock when calling yaffs_get_inode() */
- if(current != yaffs_DeviceToContext(dev)->readdirProcess)
+ if(current != yaffs_DeviceToLC(dev)->readdirProcess)
yaffs_GrossUnlock(dev);
if (obj) {
yaffs_GrossLock(dev);
- yaffs_DeviceToContext(dev)->readdirProcess = current;
+ yaffs_DeviceToLC(dev)->readdirProcess = current;
offset = f->f_pos;
out:
yaffs_EndSearch(sc);
- yaffs_DeviceToContext(dev)->readdirProcess = NULL;
+ yaffs_DeviceToLC(dev)->readdirProcess = NULL;
yaffs_GrossUnlock(dev);
return retVal;
static unsigned yaffs_bg_gc_urgency(yaffs_Device *dev)
{
unsigned erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
- struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev);
+ struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev);
unsigned scatteredFree = 0; /* Free chunks not in an erased block */
if(erasedChunks < dev->nFreeChunks)
static int yaffs_BackgroundThread(void *data)
{
yaffs_Device *dev = (yaffs_Device *)data;
- struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev);
+ struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev);
unsigned long now = jiffies;
unsigned long next_dir_update = now;
unsigned long next_gc = now;
static int yaffs_BackgroundStart(yaffs_Device *dev)
{
int retval = 0;
- struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev);
+ struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev);
context->bgRunning = 1;
static void yaffs_BackgroundStop(yaffs_Device *dev)
{
- struct yaffs_LinuxContext *ctxt = yaffs_DeviceToContext(dev);
+ struct yaffs_LinuxContext *ctxt = yaffs_DeviceToLC(dev);
ctxt->bgRunning = 0;
T(YAFFS_TRACE_OS,
(TSTR("yaffs_read_inode for %d\n"), (int)inode->i_ino));
- if(current != yaffs_DeviceToContext(dev)->readdirProcess)
+ if(current != yaffs_DeviceToLC(dev)->readdirProcess)
yaffs_GrossLock(dev);
obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
yaffs_FillInodeFromObject(inode, obj);
- if(current != yaffs_DeviceToContext(dev)->readdirProcess)
+ if(current != yaffs_DeviceToLC(dev)->readdirProcess)
yaffs_GrossUnlock(dev);
}
static YLIST_HEAD(yaffs_context_list);
struct semaphore yaffs_context_lock;
-#if 0 /* not used */
-static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
-{
- yaffs_Device *dev = yaffs_SuperToDevice(sb);
-
- if (*flags & MS_RDONLY) {
- struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice;
-
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_remount_fs: %s: RO\n"), dev->name));
-
- yaffs_GrossLock(dev);
-
- yaffs_FlushSuperBlock(sb,1);
-
- if (mtd->sync)
- mtd->sync(mtd);
-
- yaffs_GrossUnlock(dev);
- } else {
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_remount_fs: %s: RW\n"), dev->name));
- }
-
- return 0;
-}
-#endif
-
static void yaffs_put_super(struct super_block *sb)
{
yaffs_Device *dev = yaffs_SuperToDevice(sb);
yaffs_FlushSuperBlock(sb,1);
- if (yaffs_DeviceToContext(dev)->putSuperFunc)
- yaffs_DeviceToContext(dev)->putSuperFunc(sb);
+ if (yaffs_DeviceToLC(dev)->putSuperFunc)
+ yaffs_DeviceToLC(dev)->putSuperFunc(sb);
yaffs_Deinitialise(dev);
yaffs_GrossUnlock(dev);
down(&yaffs_context_lock);
- ylist_del_init(&(yaffs_DeviceToContext(dev)->contextList));
+ ylist_del_init(&(yaffs_DeviceToLC(dev)->contextList));
up(&yaffs_context_lock);
- if (yaffs_DeviceToContext(dev)->spareBuffer) {
- YFREE(yaffs_DeviceToContext(dev)->spareBuffer);
- yaffs_DeviceToContext(dev)->spareBuffer = NULL;
+ if (yaffs_DeviceToLC(dev)->spareBuffer) {
+ YFREE(yaffs_DeviceToLC(dev)->spareBuffer);
+ yaffs_DeviceToLC(dev)->spareBuffer = NULL;
}
kfree(dev);
static void yaffs_MTDPutSuper(struct super_block *sb)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(yaffs_SuperToDevice(sb))->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(yaffs_SuperToDevice(sb));
if (mtd->sync)
mtd->sync(mtd);
static void yaffs_MarkSuperBlockDirty(yaffs_Device *dev)
{
- struct super_block *sb = yaffs_DeviceToContext(dev)->superBlock;
+ struct super_block *sb = yaffs_DeviceToLC(dev)->superBlock;
T(YAFFS_TRACE_OS, (TSTR("yaffs_MarkSuperBlockDirty() sb = %p\n"), sb));
if (sb)
param = &(dev->param);
memset(context,0,sizeof(struct yaffs_LinuxContext));
- dev->context = context;
+ dev->osContext = context;
YINIT_LIST_HEAD(&(context->contextList));
context->dev = dev;
context->superBlock = sb;
sb->u.generic_sbp = dev;
#endif
- yaffs_DeviceToContext(dev)->mtd = mtd;
+ dev->driverContext = mtd;
param->name = mtd->name;
/* Set up the memory size parameters.... */
nandmtd2_ReadChunkWithTagsFromNAND;
param->markNANDBlockBad = nandmtd2_MarkNANDBlockBad;
param->queryNANDBlock = nandmtd2_QueryNANDBlock;
- yaffs_DeviceToContext(dev)->spareBuffer = YMALLOC(mtd->oobsize);
+ yaffs_DeviceToLC(dev)->spareBuffer = YMALLOC(mtd->oobsize);
param->isYaffs2 = 1;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
param->totalBytesPerChunk = mtd->writesize;
param->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
param->initialiseNAND = nandmtd_InitialiseNAND;
- yaffs_DeviceToContext(dev)->putSuperFunc = yaffs_MTDPutSuper;
+ yaffs_DeviceToLC(dev)->putSuperFunc = yaffs_MTDPutSuper;
param->markSuperBlockDirty = yaffs_MarkSuperBlockDirty;
param->gcControl = yaffs_gc_control_callback;
- yaffs_DeviceToContext(dev)->superBlock= sb;
+ yaffs_DeviceToLC(dev)->superBlock= sb;
#ifndef CONFIG_YAFFS_DOES_ECC
}
context->mount_id = mount_id;
- ylist_add_tail(&(yaffs_DeviceToContext(dev)->contextList), &yaffs_context_list);
+ ylist_add_tail(&(yaffs_DeviceToLC(dev)->contextList), &yaffs_context_list);
up(&yaffs_context_lock);
/* Directory search handling...*/
- YINIT_LIST_HEAD(&(yaffs_DeviceToContext(dev)->searchContexts));
+ YINIT_LIST_HEAD(&(yaffs_DeviceToLC(dev)->searchContexts));
param->removeObjectCallback = yaffs_RemoveObjectCallback;
- init_MUTEX(&(yaffs_DeviceToContext(dev)->grossLock));
+ init_MUTEX(&(yaffs_DeviceToLC(dev)->grossLock));
yaffs_GrossLock(dev);
const __u8 *data,
yaffs_ExtendedTags *tags);
+
+static void yaffs_LoadNameFromObjectHeader(yaffs_Device *dev,YCHAR *name, const YCHAR *ohName, int bufferSize);
+static void yaffs_LoadObjectHeaderFromName(yaffs_Device *dev,YCHAR *ohName, const YCHAR *name);
+
+
/* Function to calculate chunk and offset */
static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut,
obj->sum = yaffs_CalcNameSum(name);
}
+void yaffs_SetObjectNameFromOH(yaffs_Object *obj, const yaffs_ObjectHeader *oh)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ YCHAR tmpName[YAFFS_MAX_NAME_LENGTH+1];
+ memset(tmpName,0,sizeof(tmpName));
+ yaffs_LoadNameFromObjectHeader(obj->myDev,tmpName,oh->name,YAFFS_MAX_NAME_LENGTH+1);
+ yaffs_SetObjectName(obj,tmpName);
+#else
+ yaffs_SetObjectName(obj,oh->name);
+#endif
+}
+
/*-------------------- TNODES -------------------
* List of spare tnodes
if (name && *name) {
memset(oh->name, 0, sizeof(oh->name));
- yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH);
+ yaffs_LoadObjectHeaderFromName(dev,oh->name,name);
} else if (prevChunkId > 0)
memcpy(oh->name, oldName, sizeof(oh->name));
else
yaffs_Device *dev;
if(!obj)
return;
+#ifndef CONFIG_YAFFS_WINCE
dev = obj->myDev;
obj->dirty = 1;
} else
yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, NULL);
+#endif
}
void yaffs_UpdateDirtyDirectories(yaffs_Device *dev)
return obj;
}
-int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize)
-{
- memset(name, 0, buffSize * sizeof(YCHAR));
-
- yaffs_CheckObjectDetailsLoaded(obj);
+/*
+ * A note or two on object names.
+ * * If the object name is missing, we then make one up in the form objnnn
+ *
+ * * ASCII names are stored in the object header's name field from byte zero
+ * * Unicode names are historically stored starting from byte zero.
+ *
+ * Then there are automatic Unicode names...
+ * The purpose of these is to save names in a way that can be read as
+ * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII
+ * system to share files.
+ *
+ * These automatic unicode are stored slightly differently...
+ * - If the name can fit in the ASCII character space then they are saved as
+ * ascii names as per above.
+ * - If the name needs Unicode then the name is saved in Unicode
+ * starting at oh->name[1].
- if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
- yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
- } else if (obj->hdrChunk <= 0) {
+ */
+static void yaffs_FixNullName(yaffs_Object * obj,YCHAR * name, int buffSize)
+{
+ /* Create an object name if we could not find one. */
+ if(yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH) == 0){
YCHAR locName[20];
YCHAR numString[20];
YCHAR *x = &numString[19];
unsigned v = obj->objectId;
numString[19] = 0;
- while (v > 0) {
+ while(v>0){
x--;
*x = '0' + (v % 10);
v /= 10;
}
/* make up a name */
yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX);
- yaffs_strcat(locName, x);
+ yaffs_strcat(locName,x);
yaffs_strncpy(name, locName, buffSize - 1);
+ }
+}
+
+static void yaffs_LoadNameFromObjectHeader(yaffs_Device *dev,YCHAR *name, const YCHAR *ohName, int bufferSize)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ if(dev->param.autoUnicode){
+ if(*ohName){
+ /* It is an ASCII name, so do an ASCII to unicode conversion */
+ const char *asciiOhName = (const char *)ohName;
+ int n = bufferSize - 1;
+ while(n > 0 && *asciiOhName){
+ *name = *asciiOhName;
+ name++;
+ asciiOhName++;
+ n--;
+ }
+ } else
+ yaffs_strncpy(name,ohName+1, bufferSize -1);
+ } else
+#endif
+ yaffs_strncpy(name, ohName, bufferSize - 1);
+}
+
+
+static void yaffs_LoadObjectHeaderFromName(yaffs_Device *dev, YCHAR *ohName, const YCHAR *name)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+
+ int isAscii;
+ YCHAR *w;
+
+ if(dev->param.autoUnicode){
+ isAscii = 1;
+ w = name;
+
+ /* Figure out if the name will fit in ascii character set */
+ while(isAscii && *w){
+ if((*w) & 0xff00)
+ isAscii = 0;
+ w++;
+ }
+
+ if(isAscii){
+ /* It is an ASCII name, so do a unicode to ascii conversion */
+ char *asciiOhName = (char *)ohName;
+ int n = YAFFS_MAX_NAME_LENGTH - 1;
+ while(n > 0 && *name){
+ *asciiOhName= *name;
+ name++;
+ asciiOhName++;
+ n--;
+ }
+ } else{
+ /* It is a unicode name, so save starting at the second YCHAR */
+ *ohName = 0;
+ yaffs_strncpy(ohName+1,name, YAFFS_MAX_NAME_LENGTH -2);
+ }
}
+ else
+#endif
+ yaffs_strncpy(ohName,name, YAFFS_MAX_NAME_LENGTH - 1);
+
+}
+
+int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
+{
+ memset(name, 0, buffSize * sizeof(YCHAR));
+
+ yaffs_CheckObjectDetailsLoaded(obj);
+
+ if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
+ yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
+ }
#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
- else if (obj->shortName[0])
- yaffs_strncpy(name, obj->shortName,YAFFS_SHORT_NAME_LENGTH+1);
+ else if (obj->shortName[0]) {
+ yaffs_strcpy(name, obj->shortName);
+ }
#endif
- else {
+ else if(obj->hdrChunk > 0) {
int result;
__u8 *buffer = yaffs_GetTempBuffer(obj->myDev, __LINE__);
obj->hdrChunk, buffer,
NULL);
}
- yaffs_strncpy(name, oh->name, buffSize - 1);
- name[buffSize-1]=0;
+ yaffs_LoadNameFromObjectHeader(obj->myDev,name,oh->name,buffSize);
yaffs_ReleaseTempBuffer(obj->myDev, buffer, __LINE__);
}
- return yaffs_strnlen(name,buffSize-1);
+ yaffs_FixNullName(obj,name,buffSize);
+
+ return yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH);
}
+
int yaffs_GetObjectFileLength(yaffs_Object *obj)
{
/* Dereference any hard linking */
#ifndef __YAFFS_GUTS_H__
#define __YAFFS_GUTS_H__
-#include "devextras.h"
#include "yportenv.h"
+#include "devextras.h"
+#include "yaffs_list.h"
#define YAFFS_OK 1
#define YAFFS_FAIL 0
int disableSoftDelete; /* yaffs 1 only: Set to disable the use of softdeletion. */
int deferDirectoryUpdate; /* Set to defer directory updates */
+
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ int autoUnicode;
+#endif
};
/* Context storage. Holds extra OS specific data for this device */
- void *context;
+ void *osContext;
+ void *driverContext;
+
+ struct ylist_head devList;
/* Runtime parameters. Set up by YAFFS. */
int nDataBytesPerChunk;
int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode,
int chunkInNAND, int inScan);
void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name);
+void yaffs_SetObjectNameFromOH(yaffs_Object *obj, const yaffs_ObjectHeader *oh);
void yaffs_AddObjectToDirectory(yaffs_Object *directory,
yaffs_Object *obj);
YCHAR *yaffs_CloneString(const YCHAR *str);
__u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
* at compile time so we have to allocate it.
*/
- struct mtd_info *mtd;
struct ylist_head searchContexts;
void (*putSuperFunc)(struct super_block *sb);
unsigned mount_id;
};
-#define yaffs_DeviceToContext(dev) ((struct yaffs_LinuxContext *)((dev)->context))
+#define yaffs_DeviceToLC(dev) ((struct yaffs_LinuxContext *)((dev)->osContext))
+#define yaffs_DeviceToMtd(dev) ((struct mtd_info *)((dev)->driverContext))
#endif
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * This file is just holds extra declarations of macros that would normally
+ * be providesd in the Linux kernel. These macros have been written from
+ * scratch but are functionally equivalent to the Linux ones.
+ *
+ */
+
+#ifndef __YAFFS_LIST_H__
+#define __YAFFS_LIST_H__
+
+
+#include "yportenv.h"
+
+/*
+ * This is a simple doubly linked list implementation that matches the
+ * way the Linux kernel doubly linked list implementation works.
+ */
+
+struct ylist_head {
+ struct ylist_head *next; /* next in chain */
+ struct ylist_head *prev; /* previous in chain */
+};
+
+
+/* Initialise a static list */
+#define YLIST_HEAD(name) \
+struct ylist_head name = { &(name), &(name)}
+
+
+
+/* Initialise a list head to an empty list */
+#define YINIT_LIST_HEAD(p) \
+do { \
+ (p)->next = (p);\
+ (p)->prev = (p); \
+} while (0)
+
+
+/* Add an element to a list */
+static Y_INLINE void ylist_add(struct ylist_head *newEntry,
+ struct ylist_head *list)
+{
+ struct ylist_head *listNext = list->next;
+
+ list->next = newEntry;
+ newEntry->prev = list;
+ newEntry->next = listNext;
+ listNext->prev = newEntry;
+
+}
+
+static Y_INLINE void ylist_add_tail(struct ylist_head *newEntry,
+ struct ylist_head *list)
+{
+ struct ylist_head *listPrev = list->prev;
+
+ list->prev = newEntry;
+ newEntry->next = list;
+ newEntry->prev = listPrev;
+ listPrev->next = newEntry;
+
+}
+
+
+/* Take an element out of its current list, with or without
+ * reinitialising the links.of the entry*/
+static Y_INLINE void ylist_del(struct ylist_head *entry)
+{
+ struct ylist_head *listNext = entry->next;
+ struct ylist_head *listPrev = entry->prev;
+
+ listNext->prev = listPrev;
+ listPrev->next = listNext;
+
+}
+
+static Y_INLINE void ylist_del_init(struct ylist_head *entry)
+{
+ ylist_del(entry);
+ entry->next = entry->prev = entry;
+}
+
+
+/* Test if the list is empty */
+static Y_INLINE int ylist_empty(struct ylist_head *entry)
+{
+ return (entry->next == entry);
+}
+
+
+/* ylist_entry takes a pointer to a list entry and offsets it to that
+ * we can find a pointer to the object it is embedded in.
+ */
+
+
+#define ylist_entry(entry, type, member) \
+ ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
+
+
+/* ylist_for_each and list_for_each_safe iterate over lists.
+ * ylist_for_each_safe uses temporary storage to make the list delete safe
+ */
+
+#define ylist_for_each(itervar, list) \
+ for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
+
+#define ylist_for_each_safe(itervar, saveVar, list) \
+ for (itervar = (list)->next, saveVar = (list)->next->next; \
+ itervar != (list); itervar = saveVar, saveVar = saveVar->next)
+
+
+#endif
int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
__u32 addr =
((loff_t) blockNumber) * dev->param.totalBytesPerChunk
* dev->param.nChunksPerBlock;
int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,
int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *etags)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int chunkBytes = dev->nDataBytesPerChunk;
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
struct mtd_oob_ops ops;
int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
int chunkInNAND, __u8 *data, yaffs_ExtendedTags *etags)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int chunkBytes = dev->nDataBytesPerChunk;
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
int eccres = YAFFS_ECC_RESULT_NO_ERROR;
*/
int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int blocksize = dev->param.nChunksPerBlock * dev->nDataBytesPerChunk;
int retval;
int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState *pState, __u32 *pSequenceNumber)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int chunkNo = blockNo * dev->param.nChunksPerBlock;
loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
yaffs_ExtendedTags etags;
const __u8 *data,
const yaffs_ExtendedTags *tags)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#else
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
__u8 *data, yaffs_ExtendedTags *tags)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#endif
ops.len = data ? dev->nDataBytesPerChunk : packed_tags_size;
ops.ooboffs = 0;
ops.datbuf = data;
- ops.oobbuf = yaffs_DeviceToContext(dev)->spareBuffer;
+ ops.oobbuf = yaffs_DeviceToLC(dev)->spareBuffer;
retval = mtd->read_oob(mtd, addr, &ops);
}
#else
}
} else {
if (tags) {
- memcpy(packed_tags_ptr, yaffs_DeviceToContext(dev)->spareBuffer, packed_tags_size);
+ memcpy(packed_tags_ptr, yaffs_DeviceToLC(dev)->spareBuffer, packed_tags_size);
yaffs_UnpackTags2(tags, &pt, !dev->param.noTagsECC);
}
}
int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int retval;
T(YAFFS_TRACE_MTD,
(TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState *state, __u32 *sequenceNumber)
{
- struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+ struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int retval;
T(YAFFS_TRACE_MTD,
in->hdrChunk = chunk;
in->serial = tags.serialNumber;
- yaffs_SetObjectName(in, oh->name);
+ yaffs_SetObjectNameFromOH(in, oh);
in->dirty = 0;
/* directory stuff...
- yaffs_SetObjectName(in, oh->name);
+ yaffs_SetObjectNameFromOH(in, oh);
parent =
yaffs_FindOrCreateObjectByNumber
(dev, oh->parentObjectId,
#define yaffs_sprintf sprintf
#define yaffs_toupper(a) toupper(a)
-#define Y_INLINE inline
+#define Y_INLINE __inline__
#define YAFFS_LOSTNFOUND_NAME "lost+found"
#define YAFFS_LOSTNFOUND_PREFIX "obj"
#include "stdio.h"
#include "string.h"
-#include "devextras.h"
#define YMALLOC(x) malloc(x)
#define YFREE(x) free(x)
#endif
+#if defined(CONFIG_YAFFS_DIRECT) || defined(CONFIG_YAFFS_WINCE)
+
+#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES
+
+#ifndef O_RDONLY
+#define O_RDONLY 00
+#endif
+
+#ifndef O_WRONLY
+#define O_WRONLY 01
+#endif
+
+#ifndef O_RDWR
+#define O_RDWR 02
+#endif
+
+#ifndef O_CREAT
+#define O_CREAT 0100
+#endif
+
+#ifndef O_EXCL
+#define O_EXCL 0200
+#endif
+
+#ifndef O_TRUNC
+#define O_TRUNC 01000
+#endif
+
+#ifndef O_APPEND
+#define O_APPEND 02000
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef EBUSY
+#define EBUSY 16
+#endif
+
+#ifndef ENODEV
+#define ENODEV 19
+#endif
+
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+
+#ifndef EBADF
+#define EBADF 9
+#endif
+
+#ifndef EACCES
+#define EACCES 13
+#endif
+
+#ifndef EXDEV
+#define EXDEV 18
+#endif
+
+#ifndef ENOENT
+#define ENOENT 2
+#endif
+
+#ifndef ENOSPC
+#define ENOSPC 28
+#endif
+
+#ifndef ERANGE
+#define ERANGE 34
+#endif
+
+#ifndef ENODATA
+#define ENODATA 61
+#endif
+
+#ifndef ENOTEMPTY
+#define ENOTEMPTY 39
+#endif
+
+#ifndef ENAMETOOLONG
+#define ENAMETOOLONG 36
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+
+#ifndef EEXIST
+#define EEXIST 17
+#endif
+
+#ifndef ENOTDIR
+#define ENOTDIR 20
+#endif
+
+#ifndef EISDIR
+#define EISDIR 21
+#endif
+
+
+// Mode flags
+
+#ifndef S_IFMT
+#define S_IFMT 0170000
+#endif
+
+#ifndef S_IFLNK
+#define S_IFLNK 0120000
+#endif
+
+#ifndef S_IFDIR
+#define S_IFDIR 0040000
+#endif
+
+#ifndef S_IFREG
+#define S_IFREG 0100000
+#endif
+
+#ifndef S_IREAD
+#define S_IREAD 0000400
+#endif
+
+#ifndef S_IWRITE
+#define S_IWRITE 0000200
+#endif
+
+#ifndef S_IEXEC
+#define S_IEXEC 0000100
+#endif
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE 1
+#endif
+
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#define F_OK 0
+#endif
+
+#else
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+
+#endif
+
#ifndef Y_DUMP_STACK
#define Y_DUMP_STACK() do { } while (0)
#endif
} while (0)
#endif
+
#endif