Some fixes and add NOR integrity code
authorcharles <charles>
Fri, 7 Nov 2008 00:32:20 +0000 (00:32 +0000)
committercharles <charles>
Fri, 7 Nov 2008 00:32:20 +0000 (00:32 +0000)
15 files changed:
direct/Makefile
direct/dtest.c
direct/fsx_test/Makefile
direct/fsx_test/yaffs_fsx.c
direct/nor_stress.c [new file with mode: 0644]
direct/nor_stress.h [new file with mode: 0644]
direct/yaffs_norif1.c [new file with mode: 0644]
direct/yaffs_norif1.h [new file with mode: 0644]
direct/yaffs_test.c [new file with mode: 0644]
direct/yaffscfg2k.c
direct/ynorsim.c [new file with mode: 0644]
direct/ynorsim.h [new file with mode: 0644]
yaffs_guts.c
yaffs_guts.h
yaffs_tagscompat.c

index e816df1..9f4b606 100644 (file)
 #
 # NB Warning this Makefile does not include header dependencies.
 #
-# $Id: Makefile,v 1.18 2008-07-21 01:03:19 charles Exp $
+# $Id: Makefile,v 1.19 2008-11-07 00:32:21 charles Exp $
 
 #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 +=    -Wall -g $(EXTRA_COMPILE_FLAGS)
-#CFLAGS+=    -fstack-check -O0
+CFLAGS +=    -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing -fno-strict-aliasing
+CFLAGS +=    -O0
+#CFLAGS +=    -DVALGRIND_TEST
 
 #CFLAGS+=   -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
 #CFLAGS+=   -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
 
 
-DIRECTTESTOBJS = dtest.o yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
+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_checkptrw.o  yaffs_qsort.o\
+                yaffs_norif1.o  ynorsim.o nor_stress.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 = $(DIRECTTESTOBJS) $(BOOTTESTOBJS)
+ALLOBJS = $(sort $(DIRECTTESTOBJS) $(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 \
           yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h  yaffs_nandemul2k.h \
@@ -48,7 +52,7 @@ SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsin
 
 #all: directtest2k boottest
 
-all: directtest2k
+all: directtest2k yaffs_test
 
 $(ALLOBJS): %.o: %.c
        gcc -c $(CFLAGS) -o $@ $<
@@ -59,6 +63,9 @@ $(SYMLINKS):
 directtest2k: $(SYMLINKS) $(DIRECTTESTOBJS)
        gcc -o $@ $(DIRECTTESTOBJS)
 
+yaffs_test: $(SYMLINKS) $(YAFFSTESTOBJS)
+       gcc -o $@ $(YAFFSTESTOBJS)
+
 
 boottest: $(SYMLINKS) $(BOOTTESTOBJS)
        gcc -o $@ $(BOOTTESTOBJS)
index 8476743..fd4f966 100644 (file)
@@ -22,6 +22,8 @@
 
 #include "yaffsfs.h"
 
+#include "nor_stress.h"
+
 void dumpDir(const char *dname);
 
 char xx[600];
@@ -2284,6 +2286,7 @@ void random_small_file_test(const char *mountpt,int iterations)
 
 int main(int argc, char *argv[])
 {
+
        //return long_test(argc,argv);
        
        //return cache_read_test();
index 3d4b4fd..93d2bac 100644 (file)
@@ -14,7 +14,7 @@
 #
 # NB Warning this Makefile does not include header dependencies.
 #
-# $Id: Makefile,v 1.3 2008-08-07 22:45:44 charles Exp $
+# $Id: Makefile,v 1.4 2008-11-07 00:32:22 charles Exp $
 
 #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
 
@@ -31,6 +31,7 @@ FSXTESTOBJS = yaffs_fsx.o yaffscfg2k.o yaffs_ecc.o yaffs_fileem2k.o yaffs_fileem
                 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_norif1.o ynorsim.o
 #               yaffs_checkptrwtest.o\
                 
 
@@ -48,7 +49,8 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya
 
 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
+                      yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c\
+                      yaffs_norif1.c yaffs_norif1.h ynorsim.c ynorsim.h
 
 
 
index 64588c8..31b0751 100644 (file)
@@ -130,11 +130,7 @@ int        writebdy = 1;                   /* -w flag */
 long   monitorstart = -1;              /* -m flag */
 long   monitorend = -1;                /* -m flag */
 int    lite = 0;                       /* -L flag */
-<<<<<<< yaffs_fsx.c
-long   numops = 5000;                  /* -N flag */
-=======
-long   numops = /*-1 */ 100000;                        /* -N flag */
->>>>>>> 1.3
+long   numops = /*-1 */ 10000000;                      /* -N flag */
 int    randomoplen = 1;                /* -O flag disables it */
 int    seed = 1;                       /* -S flag */
 
@@ -778,7 +774,7 @@ getnum(char *s, char **e)
 }
 
 
-#define BASE_NAME "/flash/yaffs2"
+#define BASE_NAME "/flash/yaffs1"
 
 int
 main(int argc, char **argv)
diff --git a/direct/nor_stress.c b/direct/nor_stress.c
new file mode 100644 (file)
index 0000000..0eaaf1b
--- /dev/null
@@ -0,0 +1,353 @@
+#include "nor_stress.h"
+
+
+#include "yaffsfs.h"
+
+#include <stdio.h>
+
+
+
+static unsigned powerUps;
+static unsigned cycleStarts;
+static unsigned cycleEnds;
+
+
+char fullPathName[100];
+char fullPowerUpName[100];
+char fullStartName[100];
+char fullEndName[100];
+char fullMainName[100];
+char fullTempMainName[100];
+char fullTempCounterName[100];
+
+
+void MakeName(char *fullName,const char *prefix, const char *name)
+{
+  strcpy(fullName,prefix);
+  strcat(fullName,"/");
+  strcat(fullName,name);
+}
+
+
+void MakeFullNames(const char *prefix)
+{
+  MakeName(fullPathName,prefix,"");
+  MakeName(fullPowerUpName,prefix,"powerUps");
+  MakeName(fullStartName,prefix,"starts");
+  MakeName(fullEndName,prefix,"ends");
+  MakeName(fullMainName,prefix,"main");
+  MakeName(fullTempCounterName,prefix,"tmp-counter");
+  MakeName(fullTempMainName,prefix,"tmp-main");
+}
+
+static void FatalError(void)
+{
+  printf("Integrity error\n");
+  while(1){}
+}
+
+static void UpdateCounter(const char *name, unsigned *val,  int initialise)
+{
+  int inh;
+  int outh;
+  unsigned x[2];
+  int nread = 0;
+  int nwritten = 0;
+  
+  x[0] = x[1] = 0;
+  
+  if(initialise){
+    x[0] = 0; 
+    x[1] = 1;
+  } else {
+    inh = yaffs_open(name,O_RDONLY, S_IREAD | S_IWRITE);
+    if(inh >= 0){
+      nread = yaffs_read(inh,x,sizeof(x));
+      yaffs_close(inh);
+    }
+
+    if(nread != sizeof(x) ||
+       x[0] + 1 != x[1]){
+      printf("Error reading counter %s handle %d, x[0] %u x[1] %u last error %d\n",
+              name, inh, x[0], x[1],yaffsfs_GetLastError());
+      FatalError();
+              
+    }
+    x[0]++;
+    x[1]++;
+  }
+  
+  outh = yaffs_open(fullTempCounterName, O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
+  if(outh >= 0){
+    nwritten = yaffs_write(outh,x,sizeof(x));
+    yaffs_close(outh);
+    yaffs_rename(fullTempCounterName,name);
+  }
+  
+  if(nwritten != sizeof(x)){
+      printf("Error writing counter %s handle %d, x[0] %u x[1] %u\n",
+              name, inh, x[0], x[1]);
+      FatalError();
+  }
+  
+  *val = x[0];
+  
+  printf("##\n"
+         "## Set counter %s to %u\n"
+         "##\n", name,x[0]);
+}
+
+
+static void dump_directory_tree_worker(const char *dname,int recursive)
+{
+       yaffs_DIR *d;
+       yaffs_dirent *de;
+       struct yaffs_stat s;
+       char str[1000];
+                       
+       d = yaffs_opendir(dname);
+       
+       if(!d)
+       {
+               printf("opendir failed\n");
+       }
+       else
+       {
+               while((de = yaffs_readdir(d)) != NULL)
+               {
+                       strcpy(str,dname);
+                       strcat(str,"/");
+                       strcat(str,de->d_name);
+                       
+                       yaffs_lstat(str,&s);
+                       
+                       printf("%s inode %d obj %x length %d mode %X ",str,s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode);
+                       switch(s.st_mode & S_IFMT)
+                       {
+                               case S_IFREG: printf("data file"); break;
+                               case S_IFDIR: printf("directory"); break;
+                               case S_IFLNK: printf("symlink -->");
+                                                         if(yaffs_readlink(str,str,100) < 0)
+                                                               printf("no alias");
+                                                         else
+                                                               printf("\"%s\"",str);    
+                                                         break;
+                               default: printf("unknown"); break;
+                       }
+                       
+                       printf("\n");
+
+                       if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
+                               dump_directory_tree_worker(str,1);
+                                                       
+               }
+               
+               yaffs_closedir(d);
+       }
+
+}
+
+static void dump_directory_tree(const char *dname)
+{
+       dump_directory_tree_worker(dname,1);
+       printf("\n");
+       printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname));
+}
+
+
+
+
+#define XX_SIZE 500
+
+static unsigned xx[XX_SIZE];
+
+static int yWriteFile(const char *fname, unsigned sz32)
+{
+       int h;
+       int r;
+       int i;
+       unsigned checksum = 0;
+       
+       printf("Writing file %s\n",fname);
+
+       h = yaffs_open(fname,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+
+       if(h < 0){
+               printf("could not open file %s\n",fname);
+               return h;
+       }
+
+        xx[0] = sz32;
+        checksum ^= xx[0];
+
+       if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
+               goto WRITE_ERROR;
+       }
+               
+       while(sz32> 0){
+               for(i = 0; i < XX_SIZE; i++){
+                 xx[i] = sz32 + i;
+                 checksum ^= xx[i];
+                }
+
+               if((r = yaffs_write(h,xx,sizeof(xx))) != sizeof(xx)){
+                       goto WRITE_ERROR;
+               }
+               sz32--;
+       }
+
+       xx[0] = checksum;
+
+       if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
+               goto WRITE_ERROR;
+       }
+       
+       
+       yaffs_close(h);
+       return 0;
+
+WRITE_ERROR:
+       printf("ywrite error at position %d\n",(int)yaffs_lseek(h,0,SEEK_END));
+       yaffs_close(h);
+       return -1;
+       
+}
+
+static int yVerifyFile(const char *fName)
+{
+       unsigned checksum = 0;
+       unsigned totalSize;
+       unsigned sz32;
+       unsigned recordedSize = 0;
+       int r;
+       int h;
+       int i;
+       int retval = 0;
+
+
+        printf("Verifying file %s\n",fName);
+               
+       h = yaffs_open(fName, O_RDONLY,S_IREAD | S_IWRITE);
+
+       if(h < 0){
+               printf("could not open file %s\n",fName);
+               return -1;
+       }
+
+       totalSize = yaffs_lseek(h,0,SEEK_END);
+       yaffs_lseek(h,0,SEEK_SET);
+
+       r = yaffs_read(h,&sz32,sizeof(sz32));
+
+       if(r != sizeof(sz32)){
+               printf("reading size failed ... returned %d\n",r);
+               yaffs_close(h);
+               return -1;
+       }
+       
+       recordedSize = sz32 * sizeof(xx) + 8;
+
+       printf("verify %s: file size is %d, recorded size is %d\n", fName, totalSize, recordedSize);
+       if(totalSize != recordedSize){
+               printf("!!!!!!!!!!!!!!!!!!!!!!!!file size is wrong, should be %d, is %d\n", recordedSize,totalSize);
+               yaffs_close(h);
+               return -1;
+       }
+
+       checksum ^= sz32;
+
+
+       while(sz32 > 0){
+               r = yaffs_read(h,xx,sizeof(xx));
+               if(r != sizeof(xx)){
+                       printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
+                       yaffs_close(h);
+                       return -1;
+               }
+               for(i = 0; i < XX_SIZE; i++)
+                 checksum ^= xx[i];
+               sz32--;
+       }
+       r = yaffs_read(h,xx,sizeof(xx[0]));
+       if(r != sizeof(xx[0])){
+               printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
+               yaffs_close(h);
+               return -1;
+       }
+       
+       checksum ^= xx[0];
+
+       if(checksum != 0){
+               printf("!!!!!!!!!!!!!!!!!!!!! checksum failed\n");
+               retval = -1;
+        } else
+               printf("verified ok\n");
+       yaffs_close(h);
+
+       return retval;
+}
+
+static unsigned long next = 1;
+int myrand(void) {
+  next = next * 1103515245 + 12345;
+  return((unsigned)(next/65536) % 32768);
+}
+
+static void DoUpdateMainFile(void)
+{
+        int result;
+        int sz32;
+        sz32 = (myrand() % 1000)   + 20;
+        
+       result = yWriteFile(fullTempMainName,sz32);
+       if(result)
+           FatalError();
+       yaffs_rename(fullTempMainName,fullMainName);
+}
+
+static void DoVerifyMainFile(void)
+{
+        int result;
+       result = yVerifyFile(fullMainName);
+       if(result)
+           FatalError();
+
+}
+
+
+void NorStressTestInitialise(const char *prefix)
+{
+  MakeFullNames(prefix);
+  
+  yaffs_StartUp();
+  yaffs_mount(fullPathName);
+  UpdateCounter(fullPowerUpName,&powerUps,1);
+  UpdateCounter(fullStartName,&cycleStarts,1);
+  UpdateCounter(fullEndName,&cycleEnds,1);
+  UpdateCounter(fullPowerUpName,&powerUps,1);
+  DoUpdateMainFile();
+  DoVerifyMainFile();
+  yaffs_unmount(fullPathName);
+}
+
+
+void NorStressTestRun(const char *prefix)
+{
+  MakeFullNames(prefix);
+
+  yaffs_StartUp();
+  yaffs_mount(fullPathName);
+  
+  dump_directory_tree(fullPathName);
+  
+  UpdateCounter(fullPowerUpName,&powerUps,0);
+  
+  while(1){
+    UpdateCounter(fullStartName, &cycleStarts,0);
+    DoVerifyMainFile();
+    DoUpdateMainFile();
+    dump_directory_tree(fullPathName);
+  
+    UpdateCounter(fullEndName,&cycleEnds,0);
+  }
+}
diff --git a/direct/nor_stress.h b/direct/nor_stress.h
new file mode 100644 (file)
index 0000000..e17db29
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __NOR_STRESS_H__
+#define __NOR_STRESS_H__
+
+void NorStressTestInitialise(const char *path);
+void NorStressTestRun(const char *path);
+
+#endif
+
diff --git a/direct/yaffs_norif1.c b/direct/yaffs_norif1.c
new file mode 100644 (file)
index 0000000..c9534ac
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * 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.
+ */
+
+/*
+ * This is an interface module for handling NOR in yaffs1 mode.
+ */
+
+/* First set up for M18 with 1k chunks and 16-byte spares.
+ *
+ * NB We're using the oddball M18 modes of operation here 
+ * The chip is 64MB based at 0x0000, but YAFFS only going to use the top half
+ * ie. YAFFS will be from 32MB to 64MB.
+ *
+ * The M18 has two ways of writing data. Every Programming Region (1kbytes) 
+ * can be programmed in two modes:
+ * * Object Mode 1024 bytes of write once data.
+ * * Control Mode: 512bytes of bit-writeable data. 
+ *    This is arranged as 32 * (16 bytes of bit-writable followed by 16 bytes of "dont touch")
+ * 
+ * The block size is 256kB, making 128 blocks in the 32MB YAFFS area.
+ * Each block comprises:
+ *   Offset   0k: 248 x 1k data pages
+ *   Offset 248k: 248 x 32-byte spare areas implemented as 16 bytes of spare followed by 16 bytes untouched)
+ *   Offset 248k + (248 * 32): Format marker
+ *   
+ */
+
+const char *yaffs_norif1_c_version = "$Id: yaffs_norif1.c,v 1.1 2008-11-07 00:34:47 charles Exp $";
+
+#include "yaffs_norif1.h"
+
+#include "yportenv.h"
+
+#include "yaffs_flashif.h"
+#include "yaffs_guts.h"
+
+#include "devextras.h"
+
+#define SPARE_BYTES_PER_CHUNK  16
+#define M18_SKIP               16
+#define PROG_REGION_SIZE       1024
+#define BLOCK_SIZE_IN_BYTES    (256*1024)
+#define CHUNKS_PER_BLOCK       248
+#define SPARE_AREA_OFFSET      (CHUNKS_PER_BLOCK * PROG_REGION_SIZE)
+
+#define FORMAT_OFFSET          (SPARE_AREA_OFFSET + CHUNKS_PER_BLOCK * (SPARE_BYTES_PER_CHUNK + M18_SKIP))
+
+#define FORMAT_VALUE           0x1234
+
+#define DATA_BYTES_PER_CHUNK   1024
+#define BLOCKS_IN_DEVICE        (32*1024/256)
+
+
+#define YNOR_PREMARKER          (0xF6)
+#define YNOR_POSTMARKER         (0xF0)
+
+
+#if 1
+
+/* Compile this for a simulation */
+#include "ynorsim.h"
+#define ynorif1_FlashInit() ynorsim_Initialise()
+#define ynorif1_FlashDeinit() ynorsim_Shutdown()
+#define ynorif1_FlashWrite32(addr,buf,nwords) ynorsim_Write32(addr,buf,nwords) 
+#define ynorif1_FlashRead32(addr,buf,nwords) ynorsim_Read32(addr,buf,nwords) 
+#define ynorif1_FlashEraseBlock(addr) ynorsim_EraseBlock(addr)
+#define DEVICE_BASE     ynorsim_GetBase()
+#else
+
+/* Compile this for running on blob, hacked for yaffs access */
+#include "../blob/yflashrw.h"
+#define ynorif1_FlashInit()  do{} while(0)
+#define ynorif1_FlashDeinit() do {} while(0)
+#define ynorif1_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords) 
+#define ynorif1_FlashRead32(addr,buf,nwords)  Y_FlashRead(addr,buf,nwords) 
+#define ynorif1_FlashEraseBlock(addr)         Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES)
+#define DEVICE_BASE     (32 * 1024 * 1024)
+#endif
+
+__u32 *Block2Addr(yaffs_Device *dev, int blockNumber)
+{
+       __u32 addr;
+       
+       addr = (__u32) DEVICE_BASE;
+       addr += blockNumber * BLOCK_SIZE_IN_BYTES;
+       
+       return (__u32 *) addr;
+}
+
+__u32 *Block2FormatAddr(yaffs_Device *dev,int blockNumber)
+{
+       __u32 addr;
+       
+       addr = (__u32) Block2Addr(dev,blockNumber);
+       addr += FORMAT_OFFSET;
+       
+       return (__u32 *)addr;
+}
+__u32 *Chunk2DataAddr(yaffs_Device *dev,int chunkId)
+{
+       unsigned block;
+       unsigned chunkInBlock;
+       __u32  addr;
+       
+       block = chunkId/dev->nChunksPerBlock;
+       chunkInBlock = chunkId % dev->nChunksPerBlock;
+       
+       addr = (__u32) Block2Addr(dev,block);
+       addr += chunkInBlock * DATA_BYTES_PER_CHUNK;
+       
+       return (__u32 *)addr;
+}
+
+__u32 *Chunk2SpareAddr(yaffs_Device *dev,int chunkId)
+{
+       unsigned block;
+       unsigned chunkInBlock;
+       __u32 addr;
+       
+       block = chunkId/dev->nChunksPerBlock;
+       chunkInBlock = chunkId % dev->nChunksPerBlock;
+       
+       addr = (__u32) Block2Addr(dev,block);
+       addr += SPARE_AREA_OFFSET;
+       addr += chunkInBlock * (SPARE_BYTES_PER_CHUNK + M18_SKIP);
+       return (__u32 *)addr;
+}
+
+
+void ynorif1_AndBytes(__u8*target, const __u8   *src, int nbytes)
+{
+        while(nbytes > 0){
+                *target &= *src;
+                target++;
+                src++;
+                nbytes--;
+        }
+}
+
+int ynorif1_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare)
+{
+        __u32 *dataAddr = Chunk2DataAddr(dev,chunkInNAND);
+        __u32 *spareAddr = Chunk2SpareAddr(dev,chunkInNAND);
+        
+        yaffs_Spare tmpSpare;
+        
+        /* We should only be getting called for one of 3 reasons:
+         * Writing a chunk: data and spare will not be NULL
+         * Writing a deletion marker: data will be NULL, spare not NULL
+         * Writing a bad block marker: data will be NULL, spare not NULL
+         */
+         
+        if(sizeof(yaffs_Spare) != 16)
+                YBUG();
+        
+        if(data && spare)
+        {
+                if(spare->pageStatus != 0xff)
+                        YBUG();
+                /* Write a pre-marker */
+                memset(&tmpSpare,0xff,sizeof(tmpSpare));
+                tmpSpare.pageStatus = YNOR_PREMARKER;
+                ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,sizeof(yaffs_Spare)/4);
+
+                /* Write the data */            
+                ynorif1_FlashWrite32(dataAddr,(__u32 *)data,dev->totalBytesPerChunk / 4);
+                
+                
+                memcpy(&tmpSpare,spare,sizeof(yaffs_Spare));
+                
+                /* Write the real tags, but override the premarker*/
+                tmpSpare.pageStatus = YNOR_PREMARKER;
+                ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,sizeof(yaffs_Spare)/4);
+                
+                /* Write a post-marker */
+                tmpSpare.pageStatus = YNOR_POSTMARKER;
+                ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,sizeof(tmpSpare)/4);  
+
+        } else if(spare){
+                /* This has to be a read-modify-write operation to handle NOR-ness */
+
+                ynorif1_FlashRead32(spareAddr,(__u32 *)&tmpSpare,16/ 4);
+                
+                ynorif1_AndBytes((__u8 *)&tmpSpare,(__u8 *)spare,sizeof(yaffs_Spare));
+                
+                ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,16/ 4);
+        }
+        else {
+                YBUG();
+        }
+        
+
+       return YAFFS_OK;        
+
+}
+
+int ynorif1_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)
+{
+
+       __u32 *dataAddr = Chunk2DataAddr(dev,chunkInNAND);
+       __u32 *spareAddr = Chunk2SpareAddr(dev,chunkInNAND);
+       
+       if(data)
+       {
+               ynorif1_FlashRead32(dataAddr,(__u32 *)data,dev->totalBytesPerChunk / 4);
+       }
+       
+        if(spare)
+        {
+                ynorif1_FlashRead32(spareAddr,(__u32 *)spare,16/ 4);
+                
+                /* If the page status is 0xF then it was written properly
+                 * so change that to 0xFF so that the rest of yaffs is happy.
+                 */
+                if(spare->pageStatus == YNOR_POSTMARKER)
+                        spare->pageStatus = 0xFF;
+        }
+        
+
+       return YAFFS_OK;        
+
+}
+
+static int ynorif1_FormatBlock(yaffs_Device *dev, int blockNumber)
+{
+       __u32 *blockAddr = Block2Addr(dev,blockNumber);
+       __u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+       __u32 formatValue = FORMAT_VALUE;
+       
+       ynorif1_FlashEraseBlock(blockAddr);
+       ynorif1_FlashWrite32(formatAddr,&formatValue,1);
+       
+       return YAFFS_OK;
+}
+
+static int ynorif1_UnformatBlock(yaffs_Device *dev, int blockNumber)
+{
+       __u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+       __u32 formatValue = 0;
+       
+       ynorif1_FlashWrite32(formatAddr,&formatValue,1);
+       
+       return YAFFS_OK;
+}
+
+static int ynorif1_IsBlockFormatted(yaffs_Device *dev, int blockNumber)
+{
+       __u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+       __u32 formatValue;
+       
+       
+       ynorif1_FlashRead32(formatAddr,&formatValue,1);
+       
+       return (formatValue == FORMAT_VALUE);
+}
+
+int ynorif1_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
+{
+
+       if(blockNumber < 0 || blockNumber >= BLOCKS_IN_DEVICE)
+       {
+               T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
+               return YAFFS_FAIL;
+       }
+       else
+       {
+               ynorif1_UnformatBlock(dev,blockNumber);
+               ynorif1_FormatBlock(dev,blockNumber);
+               return YAFFS_OK;
+       }
+       
+}
+
+int ynorif1_InitialiseNAND(yaffs_Device *dev)
+{
+       int i;
+       
+       ynorif1_FlashInit();
+       /* Go through the blocks formatting them if they are not formatted */
+       for(i = dev->startBlock; i <= dev->endBlock; i++){
+               if(!ynorif1_IsBlockFormatted(dev,i)){
+                       ynorif1_FormatBlock(dev,i);
+               }
+       }
+       return YAFFS_OK;
+}
+
+int ynorif1_DeinitialiseNAND(yaffs_Device *dev)
+{
+       
+       ynorif1_FlashDeinit();
+
+       return YAFFS_OK;
+}
+
+
diff --git a/direct/yaffs_norif1.h b/direct/yaffs_norif1.h
new file mode 100644 (file)
index 0000000..bee10e9
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 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.
+ */
+
+
+#ifndef __YAFFS_NOR_IF1_H__
+#define __YAFFS_NOR_IF1_H__
+
+#include "yaffs_guts.h"
+
+int ynorif1_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare);
+int ynorif1_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);
+int ynorif1_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
+int ynorif1_InitialiseNAND(yaffs_Device *dev);
+int ynorif1_DeinitialiseNAND(yaffs_Device *dev);
+
+#endif
+
+
diff --git a/direct/yaffs_test.c b/direct/yaffs_test.c
new file mode 100644 (file)
index 0000000..381df44
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * YAFFS: Yet another FFS. A NAND-flash specific file system. 
+ *
+ * Copyright (C) 2002 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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "yaffsfs.h"
+
+#include "nor_stress.h"
+
+
+
+void BadUsage(void)
+{
+       printf("usage root_dir test_id\n");
+       printf(" test_id: fw_update fw_update_init\n");
+       exit(2);
+}
+int main(int argc, const char *argv[])
+{
+       yaffs_StartUp();
+       if(argc == 3) {
+               if(!strcmp(argv[2],"fw_update_init")){
+                       NorStressTestInitialise(argv[1]);
+               }
+               else if(!strcmp(argv[2],"fw_update")){
+                       NorStressTestRun(argv[1]);
+               }
+               else 
+                       BadUsage();
+       }
+       else
+               BadUsage();
+       return 0;
+}
index 0a91e3f..0a59d95 100644 (file)
 #include "yaffsfs.h"
 #include "yaffs_fileem2k.h"
 #include "yaffs_nandemul2k.h"
+#include "yaffs_norif1.h"
 
 #include <errno.h>
 
 unsigned yaffs_traceMask = 
 
        YAFFS_TRACE_SCAN |  
-       YAFFS_TRACE_GC | YAFFS_TRACE_GC_DETAIL | 
+       YAFFS_TRACE_GC |
        YAFFS_TRACE_ERASE | 
+       YAFFS_TRACE_ERROR | 
        YAFFS_TRACE_TRACING | 
        YAFFS_TRACE_ALLOCATE | 
        YAFFS_TRACE_CHECKPOINT |
        YAFFS_TRACE_BAD_BLOCKS |
+
+/*     YAFFS_TRACE_VERIFY |  */
        
        0;
         
@@ -108,26 +112,20 @@ void yaffsfs_LocalInitialisation(void)
 #include "yaffs_flashif2.h"
 #include "yaffs_nandemul2k.h"
 
-static yaffs_Device ramDev;
-static yaffs_Device bootDev;
+static yaffs_Device ram1Dev;
+static yaffs_Device nand2;
 static yaffs_Device flashDev;
 static yaffs_Device ram2kDev;
+static yaffs_Device m18_1Dev;
 
 static yaffsfs_DeviceConfiguration yaffsfs_config[] = {
-#if 0
-       { "/ram", &ramDev},
-       { "/boot", &bootDev},
-       { "/flash/", &flashDev},
-       { "/ram2k", &ram2kDev},
-       {(void *)0,(void *)0}
-#else
-       //{ "/", &ramDev},
-       { "/flash/yaffs1", &bootDev},
-       { "/flash/yaffs2", &flashDev},
+
+       { "/ram1", &ram1Dev},
+       { "/M18-1", &m18_1Dev},
+       { "/yaffs2", &flashDev},
        { "/ram2k", &ram2kDev},
        { "/flash/bigblock", &flashDev},
        {(void *)0,(void *)0} /* Null entry to terminate list */
-#endif
 };
 
 
@@ -138,36 +136,36 @@ int yaffs_StartUp(void)
        yaffsfs_LocalInitialisation();
        
        // Set up devices
-       // /ram
-       memset(&ramDev,0,sizeof(ramDev));
-       ramDev.totalBytesPerChunk = 512;
-       ramDev.nChunksPerBlock = 32;
-       ramDev.nReservedBlocks = 2; // Set this smaller for RAM
-       ramDev.startBlock = 0; // Can use block 0
-       ramDev.endBlock = 127; // Last block in 2MB.    
-       //ramDev.useNANDECC = 1;
-       ramDev.nShortOpCaches = 0;      // Disable caching on this device.
-       ramDev.genericDevice = (void *) 0;      // Used to identify the device in fstat.
-       ramDev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND;
-       ramDev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND;
-       ramDev.eraseBlockInNAND = yramdisk_EraseBlockInNAND;
-       ramDev.initialiseNAND = yramdisk_InitialiseNAND;
-
-       // /boot (yaffs1)
-       memset(&bootDev,0,sizeof(bootDev));
-       bootDev.totalBytesPerChunk = 512;
-       bootDev.nChunksPerBlock = 32;
-       bootDev.nReservedBlocks = 5;
-       bootDev.startBlock = 0; // Can use block 0
-       bootDev.endBlock = 63; // Last block
-       //bootDev.useNANDECC = 0; // use YAFFS's ECC
-       bootDev.nShortOpCaches = 10; // Use caches
-       bootDev.genericDevice = (void *) 1;     // Used to identify the device in fstat.
-       bootDev.writeChunkToNAND = yflash_WriteChunkToNAND;
-       bootDev.readChunkFromNAND = yflash_ReadChunkFromNAND;
-       bootDev.eraseBlockInNAND = yflash_EraseBlockInNAND;
-       bootDev.initialiseNAND = yflash_InitialiseNAND;
-
+       // /ram1   ram, yaffs1
+       memset(&ram1Dev,0,sizeof(ram1Dev));
+       ram1Dev.totalBytesPerChunk = 512;
+       ram1Dev.nChunksPerBlock = 32;
+       ram1Dev.nReservedBlocks = 2; // Set this smaller for RAM
+       ram1Dev.startBlock = 0; // Can use block 0
+       ram1Dev.endBlock = 127; // Last block in 2MB.   
+       //ram1Dev.useNANDECC = 1;
+       ram1Dev.nShortOpCaches = 0;     // Disable caching on this device.
+       ram1Dev.genericDevice = (void *) 0;     // Used to identify the device in fstat.
+       ram1Dev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND;
+       ram1Dev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND;
+       ram1Dev.eraseBlockInNAND = yramdisk_EraseBlockInNAND;
+       ram1Dev.initialiseNAND = yramdisk_InitialiseNAND;
+
+       // /M18-1 yaffs1 on M18 nor sim
+       memset(&m18_1Dev,0,sizeof(m18_1Dev));
+       m18_1Dev.totalBytesPerChunk = 1024;
+       m18_1Dev.nChunksPerBlock =248;
+       m18_1Dev.nReservedBlocks = 2;
+       m18_1Dev.startBlock = 0; // Can use block 0
+       m18_1Dev.endBlock = 127; // Last block
+       m18_1Dev.useNANDECC = 0; // use YAFFS's ECC
+       m18_1Dev.nShortOpCaches = 10; // Use caches
+       m18_1Dev.genericDevice = (void *) 1;    // Used to identify the device in fstat.
+       m18_1Dev.writeChunkToNAND = ynorif1_WriteChunkToNAND;
+       m18_1Dev.readChunkFromNAND = ynorif1_ReadChunkFromNAND;
+       m18_1Dev.eraseBlockInNAND = ynorif1_EraseBlockInNAND;
+       m18_1Dev.initialiseNAND = ynorif1_InitialiseNAND;
+       m18_1Dev.deinitialiseNAND = ynorif1_DeinitialiseNAND;
 
 
        // /flash (yaffs2)
diff --git a/direct/ynorsim.c b/direct/ynorsim.c
new file mode 100644 (file)
index 0000000..569e0de
--- /dev/null
@@ -0,0 +1,156 @@
+
+
+#include "ynorsim.h"
+
+
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <time.h>
+
+#define YNORSIM_FNAME "ynorsimdata"
+
+/* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to 
+ *simulate bit flipping as the programming happens. 
+ * A low value results in faster simulation with less chance of encountering a partially programmed
+ * word. 
+ */
+   
+//#define YNORSIM_BIT_CHANGES 15
+#define YNORSIM_BIT_CHANGES 1
+
+/* Simulate 32MB of flash in 256k byte blocks.
+ * This stuff is x32.
+ */
+
+#define YNORSIM_BLOCK_SIZE_U32  (256*1024/4)
+#define YNORSIM_DEV_SIZE_U32   (32*1024 * 1024/4)
+
+static __u32 word[YNORSIM_DEV_SIZE_U32];
+
+
+static void NorError(void)
+{
+  printf("Nor error\n");
+  while(1){}
+}
+
+static void ynorsim_SaveImage(void)
+{
+  int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+  write(h,word,sizeof(word));
+  close(h);
+}
+
+static void ynorsim_RestoreImage(void)
+{
+  int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE);
+  memset(word,0xFF,sizeof(word));
+  read(h,word,sizeof(word));
+  close(h);
+}
+
+
+static void ynorsim_PowerFail(void)
+{
+  ynorsim_SaveImage();
+  exit(1);
+}
+
+static int initialised = 0;
+static int remaining_ops;
+static int nops_so_far;
+
+static void ynorsim_MaybePowerFail(void)
+{
+
+   nops_so_far++;
+   
+   
+   remaining_ops--;
+   if(remaining_ops < 1){
+       printf("Simulated power failure after %d operations\n",nops_so_far);
+       ynorsim_PowerFail();
+  }
+}
+
+static void ynorsim_Ready(void)
+{
+  if(initialised) 
+    return;
+  srand(time(NULL));
+  remaining_ops = 1000000000;
+  remaining_ops = (rand() % 10000) * 10000;
+  ynorsim_RestoreImage();
+}
+
+void ynorsim_Read32(__u32 *addr,__u32 *buf, int nwords)
+{ 
+   while(nwords > 0){
+     *buf = *addr;
+     buf++;
+     addr++;
+     nwords--;
+   }
+}
+
+void ynorsim_WriteOneWord32(__u32 *addr,__u32 val)
+{
+  __u32 tmp;
+  __u32 m;
+  int i;
+
+  tmp = *addr;
+  if(val & ~tmp){
+    // Fail due to trying to change a zero into a 1
+    printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val);
+    NorError();
+  }
+  
+  for(i = 0; i < YNORSIM_BIT_CHANGES; i++){
+    m = 1 << (rand() & 31);
+    if(!(m & val)){
+      tmp &= ~m;
+      *addr = tmp;
+      ynorsim_MaybePowerFail();
+    }
+       
+  }
+  
+  *addr = tmp & val;
+  ynorsim_MaybePowerFail();
+}
+
+void ynorsim_Write32(__u32 *addr, __u32 *buf, int nwords)
+{
+  while(nwords >0){
+    ynorsim_WriteOneWord32(addr,*buf);
+    addr++;
+    buf++;
+    nwords--;
+  }
+}
+
+void ynorsim_EraseBlock(__u32 *addr)
+{
+  /* Todo... bit flipping */
+  memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4);
+}
+
+void ynorsim_Initialise(void)
+{
+  ynorsim_Ready();
+}
+
+void ynorsim_Shutdown(void)
+{
+  ynorsim_SaveImage();
+  initialised=0;
+}
+
+__u32 *ynorsim_GetBase(void)
+{
+  return word;
+}
diff --git a/direct/ynorsim.h b/direct/ynorsim.h
new file mode 100644 (file)
index 0000000..2c70ad9
--- /dev/null
@@ -0,0 +1,14 @@
+
+#ifndef __Y_NORSIM_H__
+#define __Y_NORSIM_H__
+
+#include "yaffs_guts.h"
+
+void ynorsim_Read32(__u32 *addr, __u32 *data, int nwords);
+void ynorsim_Write32(__u32 *addr, __u32 *data, int nwords);
+void ynorsim_EraseBlock(__u32 *addr);
+void ynorsim_Shutdown(void);
+void ynorsim_Initialise(void);
+__u32 * ynorsim_GetBase(void);
+
+#endif
index eb34115..a16ec55 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.61 2008-10-30 18:25:21 charles Exp $";
+    "$Id: yaffs_guts.c,v 1.62 2008-11-07 00:32:20 charles Exp $";
 
 #include "yportenv.h"
 
@@ -97,6 +97,7 @@ static void yaffs_VerifyFreeChunks(yaffs_Device * dev);
 
 static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
 
+static void yaffs_VerifyDirectory(yaffs_Object *directory);
 #ifdef YAFFS_PARANOID
 static int yaffs_CheckFileSanity(yaffs_Object * in);
 #else
@@ -721,12 +722,6 @@ static void yaffs_VerifyFile(yaffs_Object *obj)
 
 }
 
-static void yaffs_VerifyDirectory(yaffs_Object *obj)
-{
-       if(obj && yaffs_SkipVerification(obj->myDev))
-               return;
-       
-}
 
 static void yaffs_VerifyHardLink(yaffs_Object *obj)
 {
@@ -1108,7 +1103,7 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name)
        __u16 sum = 0;
        __u16 i = 1;
 
-       YUCHAR *bname = (YUCHAR *) name;
+       const YUCHAR *bname = (const YUCHAR *) name;
        if (bname) {
                while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {
 
@@ -1121,12 +1116,14 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name)
                        bname++;
                }
        }
+       
        return sum;
 }
 
 static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
 {
 #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
+       memset(obj->shortName,0,sizeof (YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); 
        if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
                yaffs_strcpy(obj->shortName, name);
        } else {
@@ -1911,6 +1908,9 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
 {
        yaffs_Object *tn = NULL;
 
+#ifdef VALGRIND_TEST
+       tn = YMALLOC(sizeof(yaffs_Object));
+#else
        /* If there are none left make more */
        if (!dev->freeObjects) {
                yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
@@ -1921,7 +1921,9 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
                dev->freeObjects =
                    (yaffs_Object *) (dev->freeObjects->siblings.next);
                dev->nFreeObjects--;
-
+       }
+#endif
+       if(tn){
                /* Now sweeten it up... */
 
                memset(tn, 0, sizeof(yaffs_Object));
@@ -1931,6 +1933,13 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
                YINIT_LIST_HEAD(&(tn->hardLinks));
                YINIT_LIST_HEAD(&(tn->hashLink));
                YINIT_LIST_HEAD(&tn->siblings);
+               
+
+               /* Now make the directory sane */
+               if(dev->rootDir){
+                       tn->parent = dev->rootDir;
+                       ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children);
+               }
 
                 /* Add it to the lost and found directory.
                  * NB Can't put root or lostNFound in lostNFound so
@@ -1987,6 +1996,13 @@ static void yaffs_FreeObject(yaffs_Object * tn)
 
        yaffs_Device *dev = tn->myDev;
 
+       
+       if(tn->parent)
+               YBUG();
+       if(!ylist_empty(&tn->siblings))
+               YBUG();
+
+
 #ifdef  __KERNEL__
        if (tn->myInode) {
                /* We're still hooked up to a cached inode.
@@ -1999,11 +2015,14 @@ static void yaffs_FreeObject(yaffs_Object * tn)
 
         yaffs_UnhashObject(tn);
 
+#ifdef VALGRIND_TEST
+       YFREE(tn);
+#else
         /* Link into the free list. */
         tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
         dev->freeObjects = tn;
         dev->nFreeObjects++;
-
+#endif
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 
 }
@@ -2201,6 +2220,12 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
                theObject->yst_atime = theObject->yst_mtime =
                    theObject->yst_ctime = Y_CURRENT_TIME;
 #endif
+
+#if 0
+               theObject->sum_prev = 12345;
+               theObject->sum_trailer = 6789;
+#endif
+
                switch (type) {
                case YAFFS_OBJECT_TYPE_FILE:
                        theObject->variant.fileVariant.fileSize = 0;
@@ -2467,9 +2492,15 @@ static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir,
 int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
                       yaffs_Object * newDir, const YCHAR * newName)
 {
-       yaffs_Object *obj;
-       yaffs_Object *existingTarget;
+       yaffs_Object *obj=NULL;
+       yaffs_Object *existingTarget=NULL;
        int force = 0;
+       
+       
+       if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+               YBUG();
+       if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+               YBUG();
 
 #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
        /* Special case for case insemsitive systems (eg. WinCE).
@@ -2481,17 +2512,12 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
        }
 #endif
 
-       obj = yaffs_FindObjectByName(oldDir, oldName);
-       /* Check new name to long. */
-       if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
-           yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
-         /* ENAMETOOLONG */
-         return YAFFS_FAIL;
-       else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
-                yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
+       else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
          /* ENAMETOOLONG */
          return YAFFS_FAIL;
 
+       obj = yaffs_FindObjectByName(oldDir, oldName);
+
        if (obj && obj->renameAllowed) {
 
                /* Now do the handling for an existing target, if there is one */
@@ -2846,7 +2872,8 @@ static int yaffs_FindBlockForAllocation(yaffs_Device * dev)
 
 static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
 {
-       if(!dev->nCheckpointBlocksRequired){
+       if(!dev->nCheckpointBlocksRequired &&
+          dev->isYaffs2){
                /* Not a valid value so recalculate */
                int nBytes = 0;
                int nBlocks;
@@ -2885,9 +2912,14 @@ static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
        int reservedBlocks = dev->nReservedBlocks;
        int checkpointBlocks;
        
-       checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
-       if(checkpointBlocks < 0)
-               checkpointBlocks = 0;
+       if(dev->isYaffs2){
+               checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) - 
+                                   dev->blocksInCheckpoint;
+               if(checkpointBlocks < 0)
+                       checkpointBlocks = 0;
+       } else {
+               checkpointBlocks =0;
+       }
        
        reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
        
@@ -3063,9 +3095,11 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
                                            tags.objectId, tags.chunkId, tags.byteCount));
                                }
 
-                               if (object && object->deleted
-                                   && tags.chunkId != 0) {
-                                       /* Data chunk in a deleted file, throw it away
+                               if (object && 
+                                   object->deleted &&
+                                   object->softDeleted &&
+                                   tags.chunkId != 0) {
+                                       /* Data chunk in a soft deleted file, throw it away
                                         * It's a soft deleted data chunk,
                                         * No need to copy this, just forget about it and 
                                         * fix up the object.
@@ -3640,6 +3674,14 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,
        newTags.serialNumber =
            (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
        newTags.byteCount = nBytes;
+       
+       if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){
+         T(YAFFS_TRACE_ERROR,
+         (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes));
+         while(1){}
+        }
+       
+       
 
        newChunkId =
            yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
@@ -4796,6 +4838,12 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
                //chunk = offset / dev->nDataBytesPerChunk + 1;
                //start = offset % dev->nDataBytesPerChunk;
                yaffs_AddrToChunk(dev,offset,&chunk,&start);
+               
+               if(chunk * dev->nDataBytesPerChunk + start != offset ||
+                  start >= dev->nDataBytesPerChunk){
+                  T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR),
+                                       (int)offset, chunk,start));
+               }
                chunk++;
 
                /* OK now check for the curveball where the start and end are in
@@ -5149,62 +5197,66 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)
  * and the inode associated with the file.
  * It does not delete the links associated with the file.
  */
 static int yaffs_UnlinkFile(yaffs_Object * in)
 {
 
        int retVal;
        int immediateDeletion = 0;
 
-       if (1) {
 #ifdef __KERNEL__
-               if (!in->myInode) {
-                       immediateDeletion = 1;
-
-               }
+       if (!in->myInode) {
+               immediateDeletion = 1;
+       }
 #else
-               if (in->inUse <= 0) {
-                       immediateDeletion = 1;
-
-               }
+       if (in->inUse <= 0) {
+               immediateDeletion = 1;
+       }
 #endif
-               if (immediateDeletion) {
-                       retVal =
-                           yaffs_ChangeObjectName(in, in->myDev->deletedDir,
-                                                  _Y("deleted"), 0, 0);
-                       T(YAFFS_TRACE_TRACING,
-                         (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
-                          in->objectId));
-                       in->deleted = 1;
-                       in->myDev->nDeletedFiles++;
-                       if (0 && in->myDev->isYaffs2) {
-                               yaffs_ResizeFile(in, 0);
-                       }
-                       yaffs_SoftDeleteFile(in);
-               } else {
-                       retVal =
-                           yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
-                                                  _Y("unlinked"), 0, 0);
-               }
 
+       if (immediateDeletion) {
+               retVal =
+                   yaffs_ChangeObjectName(in, in->myDev->deletedDir,
+                                          _Y("deleted"), 0, 0);
+               T(YAFFS_TRACE_TRACING,
+                 (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
+                  in->objectId));
+               in->deleted = 1;
+               in->myDev->nDeletedFiles++;
+               if (1 || in->myDev->isYaffs2) {
+                       yaffs_ResizeFile(in, 0);
+               }
+               yaffs_SoftDeleteFile(in);
+       } else {
+               retVal =
+                   yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
+                                          _Y("unlinked"), 0, 0);
        }
+
+
        return retVal;
 }
 
 int yaffs_DeleteFile(yaffs_Object * in)
 {
        int retVal = YAFFS_OK;
+       int deleted = in->deleted;
+       
+       yaffs_ResizeFile(in,0);
 
        if (in->nDataChunks > 0) {
-               /* Use soft deletion if there is data in the file */
+               /* Use soft deletion if there is data in the file.
+                * That won't be the case if it has been resized to zero.
+                */
                if (!in->unlinked) {
                        retVal = yaffs_UnlinkFile(in);
                }
                if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
-                       in->deleted = 1;
+                       in->deleted = deleted = 1;
                        in->myDev->nDeletedFiles++;
                        yaffs_SoftDeleteFile(in);
                }
-               return in->deleted ? YAFFS_OK : YAFFS_FAIL;
+               return deleted ? YAFFS_OK : YAFFS_FAIL;
        } else {
                /* The file has no data chunks so we toss it immediately */
                yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
@@ -5238,7 +5290,7 @@ static int yaffs_DeleteHardLink(yaffs_Object * in)
         /* remove this hardlink from the list assocaited with the equivalent
          * object
          */
-        ylist_del(&in->hardLinks);
+        ylist_del_init(&in->hardLinks);
         return yaffs_DoGenericObjectDeletion(in);
 }
 
@@ -5799,10 +5851,12 @@ static int yaffs_Scan(yaffs_Device * dev)
                                                break;
                                        }
 
-                                       if (parent == dev->deletedDir) {
+/*
+                                       if (parent == dev->deletedDir) {
                                                yaffs_DestroyObject(in);
                                                bi->hasShrinkHeader = 1;
                                        }
+*/
                                }
                        }
                }
@@ -6627,15 +6681,91 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
 
 /*------------------------------  Directory Functions ----------------------------- */
 
+static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj)
+{
+        struct ylist_head *lh;
+        yaffs_Object *listObj;
+        
+        int count = 0;
+
+       if(!obj)
+               YBUG();
+
+        if(yaffs_SkipVerification(obj->myDev))
+                return;
+
+       if(!obj->parent)
+               YBUG();
+               
+       if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+               YBUG();
+       
+        /* Iterate through the objects in each hash entry */
+         
+        ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) {
+               if (lh) {
+                        listObj = ylist_entry(lh, yaffs_Object, siblings);
+                       yaffs_VerifyObject(listObj);
+                       if(obj == listObj)
+                               count ++;
+                }
+        }
+        
+        if(count != 1)
+               YBUG();
+        
+
+}
+
+static void yaffs_VerifyDirectory(yaffs_Object *directory)
+{
+
+        struct ylist_head *lh;
+        yaffs_Object *listObj;
+        
+       if(!directory)
+               YBUG();
+
+        if(yaffs_SkipVerification(directory->myDev))
+                return;
+
+               
+       if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+               YBUG();
+       
+        /* Iterate through the objects in each hash entry */
+         
+        ylist_for_each(lh, &directory->variant.directoryVariant.children) {
+               if (lh) {
+                        listObj = ylist_entry(lh, yaffs_Object, siblings);
+                       if(listObj->parent != directory)
+                               YBUG();
+                       yaffs_VerifyObjectInDirectory(listObj);
+                }
+        }
+        
+}
+
+
 static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
 {
        yaffs_Device *dev = obj->myDev;
+       yaffs_Object *parent;
        
+        yaffs_VerifyObjectInDirectory(obj);
+       parent = obj->parent;
+       
+       yaffs_VerifyDirectory(parent);
+
         if(dev && dev->removeObjectCallback)
                 dev->removeObjectCallback(obj);
+
            
         ylist_del_init(&obj->siblings);
         obj->parent = NULL;
+
+       yaffs_VerifyDirectory(parent);
+
 }
 
 
@@ -6660,12 +6790,18 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory,
 
         if (obj->siblings.prev == NULL) {
                 /* Not initialised */
-                YINIT_LIST_HEAD(&obj->siblings);
+                YBUG();
 
-        } else if (!ylist_empty(&obj->siblings)) {
-                /* If it is holed up somewhere else, un hook it */
-                yaffs_RemoveObjectFromDirectory(obj);
-        }
+        } else if (ylist_empty(&obj->siblings)) {
+               YBUG();
+        } 
+
+
+       yaffs_VerifyDirectory(directory);
+
+       yaffs_RemoveObjectFromDirectory(obj);
+        
+        
         /* Now add it */
         ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
         obj->parent = directory;
@@ -6676,6 +6812,11 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory,
                obj->myDev->nUnlinkedFiles++;
                obj->renameAllowed = 0;
        }
+
+       yaffs_VerifyDirectory(directory);
+        yaffs_VerifyObjectInDirectory(obj);
+
+
 }
 
 yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
@@ -6712,6 +6853,9 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
                 if (i) {
                         l = ylist_entry(i, yaffs_Object, siblings);
                         
+                        if(l->parent != directory)
+                               YBUG();
+                        
                         yaffs_CheckObjectDetailsLoaded(l);
 
                        /* Special case for lost-n-found */
@@ -7078,7 +7222,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev)
        /* Check geometry parameters. */
 
        if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || 
-           (!dev->isYaffs2 && dev->totalBytesPerChunk != 512) || 
+           (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || 
            (dev->inbandTags && !dev->isYaffs2 ) ||
             dev->nChunksPerBlock < 2 || 
             dev->nReservedBlocks < 2 || 
@@ -7372,6 +7516,9 @@ void yaffs_Deinitialise(yaffs_Device * dev)
 
 
                dev->isMounted = 0;
+               
+               if(dev->deinitialiseNAND)
+                       dev->deinitialiseNAND(dev);
        }
 
 }
index a193625..3c73583 100644 (file)
@@ -132,12 +132,12 @@ typedef struct {
 
 #ifndef CONFIG_YAFFS_NO_YAFFS1
 typedef struct {
-       unsigned chunkId:20;
-       unsigned serialNumber:2;
-       unsigned byteCount:10;
-       unsigned objectId:18;
-       unsigned ecc:12;
-       unsigned unusedStuff:2;
+        unsigned chunkId:20;
+        unsigned serialNumber:2;
+        unsigned byteCountLSB:10;
+        unsigned objectId:18;
+        unsigned ecc:12;
+        unsigned byteCountMSB:2;
 
 } yaffs_Tags;
 
@@ -420,10 +420,12 @@ struct yaffs_ObjectStruct {
        __u8 deferedFree:1;     /* For Linux kernel. Object is removed from NAND, but is
                                 * still in the inode cache. Free of object is defered.
                                 * until the inode is released.
-                                */
+                                 */
 
-       __u8 serial;            /* serial number of chunk in NAND. Cached here */
-       __u16 sum;              /* sum of the name to speed searching */
+        __u8 serial;            /* serial number of chunk in NAND. Cached here */
+/*        __u16 sum_prev; */
+        __u16 sum;              /* sum of the name to speed searching */
+/*        __u16 sum_trailer; */
 
         struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
 
@@ -443,10 +445,10 @@ struct yaffs_ObjectStruct {
 
        __u32 objectId;         /* the object id value */
 
-       __u32 yst_mode;
+        __u32 yst_mode;
 
 #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
-       YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
+        YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
 #endif
 
 #ifndef __KERNEL__
@@ -572,12 +574,13 @@ struct yaffs_DeviceStruct {
        int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
                                  int chunkInNAND, __u8 * data,
                                  yaffs_Spare * spare);
-       int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
-                                int blockInNAND);
-       int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
+        int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
+                                 int blockInNAND);
+        int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
+        int (*deinitialiseNAND) (struct yaffs_DeviceStruct * dev);
 
 #ifdef CONFIG_YAFFS_YAFFS2
-       int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
+        int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
                                         int chunkInNAND, const __u8 * data,
                                         const yaffs_ExtendedTags * tags);
        int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
index 3e5e8a4..f6c4053 100644 (file)
@@ -418,7 +418,16 @@ int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
        } else {
                tags.objectId = eTags->objectId;
                tags.chunkId = eTags->chunkId;
-               tags.byteCount = eTags->byteCount;
+
+               tags.byteCountLSB = eTags->byteCount & 0x3ff;
+               
+               if(dev->nDataBytesPerChunk >= 1024){
+                       tags.byteCountMSB = (eTags->byteCount >> 10) & 3;
+               } else {
+                       tags.byteCountMSB = 3;
+               }
+               
+
                tags.serialNumber = eTags->serialNumber;
 
                if (!dev->useNANDECC && data) {
@@ -470,7 +479,11 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
 
                                eTags->objectId = tags.objectId;
                                eTags->chunkId = tags.chunkId;
-                               eTags->byteCount = tags.byteCount;
+                               eTags->byteCount = tags.byteCountLSB;
+
+                               if(dev->nDataBytesPerChunk >= 1024)
+                                       eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10);
+
                                eTags->serialNumber = tags.serialNumber;
                        }
                }