Set up u-boot glue code and patching scripts.
authorCharles Manning <cdhmanning@gmail.com>
Mon, 16 Apr 2012 04:11:29 +0000 (16:11 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Mon, 16 Apr 2012 04:11:29 +0000 (16:11 +1200)
This should patch yaffs2 into a u-boot system.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
13 files changed:
direct/basic-test/Makefile
direct/basic-test/yaffs_osglue.c
direct/tests/Makefile
direct/u-boot/common/cmd_yaffs2.c
direct/u-boot/fs/yaffs2/Makefile
direct/u-boot/fs/yaffs2/assert.h [deleted file]
direct/u-boot/fs/yaffs2/yaffs_mtdif2.c
direct/u-boot/fs/yaffs2/yaffs_mtdif2.h
direct/u-boot/fs/yaffs2/yaffs_uboot_glue.c [moved from direct/u-boot/fs/yaffs2/yaffscfg.c with 50% similarity]
direct/u-boot/patch-u-boot.sh [new file with mode: 0755]
direct/yaffsfs.c
direct/yaffsfs.h
direct/ydirectenv.h

index 9ceaecb..47b3809 100644 (file)
@@ -18,7 +18,7 @@
 
 #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
 
-CFLAGS =      -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2  
+CFLAGS =      -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -D CONFIG_YAFFS_DEFINES_TYPES
 CFLAGS +=     -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE
 CFLAGS +=    -Wall -g $(EXTRA_COMPILE_FLAGS) -Werror=strict-aliasing 
 #CFLAGS +=    -fno-strict-aliasing
index 885fb80..4a149e2 100644 (file)
@@ -19,7 +19,7 @@
 #include "yaffs_nandemul2k.h"
 #include "yaffs_norif1.h"
 #include "yaffs_trace.h"
-
+#include <assert.h>
 
 #include <errno.h>
 
@@ -108,3 +108,9 @@ void yaffsfs_OSInitialisation(void)
 }
 
 
+void yaffs_bug_fn(const char *file_name, int line_no)
+{
+       printf("yaffs bug detected %s:%d\n",
+               file_name, line_no);
+       assert(0);
+}
index f7f628c..072944a 100644 (file)
@@ -18,7 +18,7 @@
 
 #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
 
-CFLAGS =      -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2  
+CFLAGS =      -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2  -DCONFIG_YAFFS_DEFINES_TYPES
 CFLAGS +=     -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES
 CFLAGS +=    -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing 
 #CFLAGS +=    -fno-strict-aliasing
index 69ccd09..d7851de 100644 (file)
@@ -24,6 +24,8 @@
 #define PRINTF(fmt,args...) do { } while(0)
 #endif
 
+extern void cmd_yaffs_dev_ls(void);
+extern void cmd_yaffs_tracemask(unsigned set, unsigned mask);
 extern void cmd_yaffs_devconfig(char *mp, int flash_dev, int start_block, int end_block);
 extern void cmd_yaffs_mount(char *mp);
 extern void cmd_yaffs_umount(char *mp);
@@ -40,6 +42,25 @@ extern void cmd_yaffs_mv(const char *oldPath, const char *newPath);
 extern int yaffs_dump_dev(const char *path);
 
 
+/* ytrace - show/set yaffs trace mask */
+int do_ytrace (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       if(argc > 1)
+               cmd_yaffs_tracemask(1, simple_strtol(argv[1], NULL, 16));
+       else
+               cmd_yaffs_tracemask(0, 0);
+
+    return(0);
+}
+
+/* ydevls - lists yaffs mount points. */
+int do_ydevls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    cmd_yaffs_dev_ls();
+
+    return(0);
+}
+
 /* ydevconfig mount_pt mtd_dev_num start_block end_block */
 int do_ydevconfig (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
@@ -52,15 +73,12 @@ int do_ydevconfig (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        printf("Bad arguments: ydevconfig mount_pt mtd_dev start_block end_block\n");
        return -1;
     }
-    
+
     mtpoint = argv[1];
     mtd_dev = simple_strtol(argv[2], NULL, 16);
     start_block = simple_strtol(argv[3], NULL, 16);
     end_block = simple_strtol(argv[4], NULL, 16);
-    
-    printf("Configure yaffs2 mount point %s on nand device %d from block %x to block %x\n",
-       mtpoint, mtd_dev, start_block, end_block);
-    
+
     cmd_yaffs_devconfig(mtpoint, mtd_dev, start_block, end_block);
 
     return(0);
@@ -69,15 +87,15 @@ int do_ydevconfig (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 int do_ymount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
     char *mtpoint;
-    
+
     if(argc != 2) {
        printf("Bad arguments: ymount mount_pt\n");
        return -1;
     }
-    
+
     mtpoint = argv[1];
     printf("Mounting yaffs2 mount point %s\n",mtpoint);
-    
+
     cmd_yaffs_mount(mtpoint);
 
     return(0);
@@ -86,12 +104,12 @@ int do_ymount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 int do_yumount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
     char *mtpoint;
-    
+
     if(argc != 2) {
        printf("Bad arguments: yumount mount_pt\n");
        return -1;
     }
-    
+
     mtpoint = argv[1];
     printf("Unmounting yaffs2 mount point %s\n",mtpoint);
     cmd_yaffs_umount(mtpoint);
@@ -102,13 +120,13 @@ int do_yumount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 int do_yls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
     char *dirname;
-    
+
     if(argc < 2 || argc > 3 ||
        (argc == 3 && strcmp(argv[1],"-l"))) {
        printf("Bad arguments: yls [-l] dir\n");
        return -1;
     }
-    
+
     dirname = argv[argc-1];
 
     cmd_yaffs_ls(dirname, (argc>2)?1:0);
@@ -119,14 +137,14 @@ int do_yls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 int do_yrd (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
     char *filename;
-    
+
     if(argc != 2) {
        printf("Bad arguments: yrd file_name\n");
        return -1;
     }
-    
+
     filename = argv[1];
-    
+
     printf ("Reading file %s ", filename);
 
     cmd_yaffs_read_file(filename);
@@ -145,7 +163,7 @@ int do_ywr (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        printf("Bad arguments: ywr file_name value n_values\n");
        return -1;
     }
-    
+
     filename = argv[1];
     value = simple_strtoul(argv[2], NULL, 16);
     numValues = simple_strtoul(argv[3], NULL, 16);
@@ -186,7 +204,7 @@ int do_ywrm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        printf("Bad arguments: ywrm file_name addr size\n");
        return -1;
     }
-    
+
     filename = argv[1];
     addr = simple_strtoul(argv[2], NULL, 16);
     size = simple_strtoul(argv[3], NULL, 16);
@@ -261,6 +279,18 @@ int do_ymv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 
 U_BOOT_CMD(
+    ytrace, 2,  0,  do_ytrace,
+    "show/set yaffs trace mask",
+    "ytrace [new_mask]  show/set yaffs trace mask"
+);
+
+U_BOOT_CMD(
+    ydevls, 1,  0,  do_ydevls,
+    "list yaffs mount points",
+    "list yaffs mount points"
+);
+
+U_BOOT_CMD(
     ydevconfig, 5,  0,  do_ydevconfig,
     "configure yaffs mount point",
     "ydevconfig mtpoint mtd_id start_block end_block   configures a yaffs2 mount point"
index 0237f3c..f33dbcf 100644 (file)
 #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
 include $(TOPDIR)/config.mk
 
-LIB = $(obj)libyaffs2.o
+LIB = $(obj)libyaffs2.A_OR_O
 
 COBJS-$(CONFIG_YAFFS2) := \
-       yaffs_allocator.o yaffs_attribs.o yaffs_bitmap.o yaffscfg.o\
+       yaffs_allocator.o yaffs_attribs.o yaffs_bitmap.o yaffs_uboot_glue.o\
        yaffs_checkptrw.o yaffs_ecc.o yaffs_error.o \
        yaffsfs.o yaffs_guts.o yaffs_hweight.o yaffs_nameval.o yaffs_nand.o\
        yaffs_packedtags1.o yaffs_packedtags2.o yaffs_qsort.o \
@@ -41,7 +41,10 @@ CPPFLAGS +=  $(YCFLAGS)
 
 all:  $(LIB)
 
-$(LIB): $(obj).depend $(OBJS)
+$(obj)libyaffs2.a: $(obj).depend $(OBJS)
+       $(AR) $(ARFLAGS) $@ $(OBJS)
+
+$(obj)libyaffs2.o: $(obj).depend $(OBJS)
        $(call cmd_link_o_target, $(OBJS))
 
 .PHONY: clean distclean
diff --git a/direct/u-boot/fs/yaffs2/assert.h b/direct/u-boot/fs/yaffs2/assert.h
deleted file mode 100644 (file)
index 9f379d7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* Dummy header for u-boot */
index 2f29491..4d96872 100644 (file)
 #include "linux/time.h"
 
 #include "yaffs_trace.h"
-
 #include "yaffs_packedtags2.h"
 #include "string.h"
 
+#define yaffs_dev_to_mtd(dev) ((struct mtd_info *)((dev)->driver_context))
+#define yaffs_dev_to_lc(dev) ((struct yaffs_linux_context *)((dev)->os_context))
+
 
-int nandmtd2_WriteChunkWithTagsToNAND(struct yaffs_dev* dev, int chunkInNAND,
-                                     const u8 * data,
-                                     const struct yaffs_ext_tags * tags)
+/* NB For use with inband tags....
+ * We assume that the data buffer is of size total_bytes_per_chunk so
+ * that we can also use it to load the tags.
+ */
+int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
+                             const u8 *data,
+                             const struct yaffs_ext_tags *tags)
 {
-       struct mtd_info *mtd = (struct mtd_info *)(dev->driver_context);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
        struct mtd_oob_ops ops;
 #else
        size_t dummy;
 #endif
        int retval = 0;
 
-       loff_t addr = ((loff_t) chunkInNAND) * dev->data_bytes_per_chunk;
+       loff_t addr;
+       u8 local_spare[128];
 
        struct yaffs_packed_tags2 pt;
 
-       yaffs_trace(YAFFS_TRACE_MTD,
-               "nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p",
-               chunkInNAND, data, tags);
+       int packed_tags_size =
+           dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+       void *packed_tags_ptr =
+           dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
-       if (tags)
+       yaffs_trace(YAFFS_TRACE_MTD,
+               "nandmtd2_write_chunk_tags chunk %d data %p tags %p",
+               nand_chunk, data, tags);
+
+       addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+
+       /* 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 (!data || !tags)
+               BUG();
+       else if (dev->param.inband_tags) {
+               struct yaffs_packed_tags2_tags_only *pt2tp;
+               pt2tp =
+                   (struct yaffs_packed_tags2_tags_only *)(data +
+                                                       dev->
+                                                       data_bytes_per_chunk);
+               yaffs_pack_tags2_tags_only(pt2tp, tags);
+       } else {
                yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
-       else
-               BUG(); /* both tags and data should always be present */
-
-       if (data) {
-               ops.mode = MTD_OOB_AUTO;
-               ops.ooblen = sizeof(pt);
-               ops.len = dev->data_bytes_per_chunk;
-               ops.ooboffs = 0;
-               ops.datbuf = (u8 *)data;
-               ops.oobbuf = (void *)&pt;
-               retval = mtd->write_oob(mtd, addr, &ops);
-       } else
-               BUG(); /* both tags and data should always be present */
-#else
-       if (tags) {
-               yaffs_pack_tags2(&pt, tags);
        }
 
-       if (data && tags) {
-               if (dev->param.use_nand_ecc)
-                       retval =
-                           mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk,
-                                          &dummy, data, (u8 *) & pt, NULL);
-               else
-                       retval =
-                           mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk,
-                                          &dummy, data, (u8 *) & pt, NULL);
-       } else {
-               if (data)
-                       retval =
-                           mtd->write(mtd, addr, dev->data_bytes_per_chunk, &dummy,
-                                      data);
-               if (tags)
-                       retval =
-                           mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
-                                          (u8 *) & pt);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size;
+       ops.len = dev->param.total_bytes_per_chunk;
+       ops.ooboffs = 0;
+       ops.datbuf = (u8 *) data;
+       ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr;
+       retval = mtd->write_oob(mtd, addr, &ops);
 
+#else
+       if (!dev->param.inband_tags) {
+               retval =
+                   mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk,
+                                  &dummy, data, (u8 *) packed_tags_ptr, NULL);
+       } else {
+               retval =
+                   mtd->write(mtd, addr, dev->param.total_bytes_per_chunk,
+                              &dummy, data);
        }
 #endif
 
@@ -101,81 +110,109 @@ int nandmtd2_WriteChunkWithTagsToNAND(struct yaffs_dev* dev, int chunkInNAND,
                return YAFFS_FAIL;
 }
 
-int nandmtd2_ReadChunkWithTagsFromNAND(struct yaffs_dev * dev, int chunkInNAND,
-                                      u8 * data, struct yaffs_ext_tags * tags)
+int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
+                            u8 *data, struct yaffs_ext_tags *tags)
 {
-       static u8 *spare_buffer = NULL;
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
 
-       struct mtd_info *mtd = (struct mtd_info *)(dev->driver_context);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+       u8 local_spare[128];
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
        struct mtd_oob_ops ops;
 #endif
        size_t dummy;
        int retval = 0;
+       int local_data = 0;
 
-       loff_t addr = ((loff_t) chunkInNAND) * dev->data_bytes_per_chunk;
+       loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
 
        struct yaffs_packed_tags2 pt;
-       
-       if(!spare_buffer)
-               spare_buffer = kmalloc(mtd->oobsize, GFP_NOFS);
+
+       int packed_tags_size =
+           dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+       void *packed_tags_ptr =
+           dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
 
        yaffs_trace(YAFFS_TRACE_MTD,
-               "nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p",
-               chunkInNAND, data, tags);
+               "nandmtd2_read_chunk_tags chunk %d data %p tags %p",
+               nand_chunk, data, tags);
+
+       if (dev->param.inband_tags) {
+
+               if (!data) {
+                       local_data = 1;
+                       data = yaffs_get_temp_buffer(dev);
+               }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
-       if (data && !tags)
-               retval = mtd->read(mtd, addr, dev->data_bytes_per_chunk,
-                               &dummy, data);
+       }
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+       if (dev->param.inband_tags || (data && !tags))
+               retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk,
+                                  &dummy, data);
        else if (tags) {
                ops.mode = MTD_OOB_AUTO;
-               ops.ooblen = sizeof(pt);
-               ops.len = data ? dev->data_bytes_per_chunk : sizeof(pt);
+               ops.ooblen = packed_tags_size;
+               ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
                ops.ooboffs = 0;
                ops.datbuf = data;
-               ops.oobbuf = spare_buffer;
+               ops.oobbuf = local_spare;
                retval = mtd->read_oob(mtd, addr, &ops);
        }
 #else
-       if (data && tags) {
-               if (dev->useNANDECC) {
-                       retval =
-                           mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk,
-                                         &dummy, data, dev->spare_buffer,
-                                         NULL);
-               } else {
-                       retval =
-                           mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk,
-                                         &dummy, data, dev->spare_buffer,
-                                         NULL);
-               }
+       if (!dev->param.inband_tags && data && tags) {
+
+               retval = mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk,
+                                      &dummy, data, dev->spare_buffer, NULL);
        } else {
                if (data)
                        retval =
-                           mtd->read(mtd, addr, dev->data_bytes_per_chunk, &dummy,
-                                     data);
-               if (tags)
+                           mtd->read(mtd, addr, dev->data_bytes_per_chunk,
+                                     &dummy, data);
+               if (!dev->param.inband_tags && tags)
                        retval =
                            mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
                                          dev->spare_buffer);
        }
 #endif
 
-       memcpy(&pt, spare_buffer, sizeof(pt));
+       if (dev->param.inband_tags) {
+               if (tags) {
+                       struct yaffs_packed_tags2_tags_only *pt2tp;
+                       pt2tp =
+                               (struct yaffs_packed_tags2_tags_only *)
+                               &data[dev->data_bytes_per_chunk];
+                       yaffs_unpack_tags2_tags_only(tags, pt2tp);
+               }
+       } else {
+               if (tags) {
+                       memcpy(packed_tags_ptr,
+                              local_spare,
+                              packed_tags_size);
+                       yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
+               }
+       }
 
-       if (tags)
-               yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
+       if (local_data)
+               yaffs_release_temp_buffer(dev, data);
 
-       if(tags && retval == -EBADMSG && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR)
+       if (tags && retval == -EBADMSG
+           && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
                tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
-
+               dev->n_ecc_unfixed++;
+       }
+       if (tags && retval == -EUCLEAN
+           && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
+               tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
+               dev->n_ecc_fixed++;
+       }
        if (retval == 0)
                return YAFFS_OK;
        else
                return YAFFS_FAIL;
 }
 
+
 int nandmtd2_MarkNANDBlockBad(struct yaffs_dev *dev, int blockNo)
 {
        struct mtd_info *mtd = (struct mtd_info *)(dev->driver_context);
@@ -197,7 +234,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_dev *dev, int blockNo)
 }
 
 int nandmtd2_QueryNANDBlock(struct yaffs_dev *dev, int blockNo,
-                           enum yaffs_block_state * state, int *sequenceNumber)
+                           enum yaffs_block_state * state, u32 *sequenceNumber)
 {
        struct mtd_info *mtd = (struct mtd_info *)(dev->driver_context);
        int retval;
@@ -215,7 +252,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs_dev *dev, int blockNo,
                *sequenceNumber = 0;
        } else {
                struct yaffs_ext_tags t;
-               nandmtd2_ReadChunkWithTagsFromNAND(dev,
+               nandmtd2_read_chunk_tags(dev,
                                                   blockNo *
                                                   dev->param.chunks_per_block, NULL,
                                                   &t);
index 3b842be..46ec3c6 100644 (file)
 
 #include "yaffs_guts.h"
 
-int nandmtd2_WriteChunkWithTagsToNAND(struct yaffs_dev * dev, int chunkInNAND,
+int nandmtd2_write_chunk_tags(struct yaffs_dev * dev, int chunkInNAND,
                                      const u8 * data,
                                      const struct yaffs_ext_tags * tags);
-int nandmtd2_ReadChunkWithTagsFromNAND(struct yaffs_dev * dev, int chunkInNAND,
+int nandmtd2_read_chunk_tags(struct yaffs_dev * dev, int chunkInNAND,
                                       __u8 * data, struct yaffs_ext_tags * tags);
 int nandmtd2_MarkNANDBlockBad(struct yaffs_dev *dev, int blockNo);
 int nandmtd2_QueryNANDBlock(struct yaffs_dev *dev, int blockNo,
-                           enum yaffs_block_state * state, int *sequenceNumber);
+                           enum yaffs_block_state * state, u32 *sequenceNumber);
 
 #endif
similarity index 50%
rename from direct/u-boot/fs/yaffs2/yaffscfg.c
rename to direct/u-boot/fs/yaffs2/yaffs_uboot_glue.c
index 49bd596..c9d5604 100644 (file)
@@ -39,6 +39,12 @@ static int yaffs_errno = 0;
 
 
 
+
+void yaffs_bug_fn(const char *fn, int n)
+{
+       printf("yaffs bug at %s:%d\n", fn, n);
+}
+
 void *yaffsfs_malloc(size_t x)
 {
        return malloc(x);
@@ -94,27 +100,123 @@ void yaffsfs_LocalInitialisation(void)
        // Define locking semaphore.
 }
 
+
+static const char * yaffs_file_type_str(struct yaffs_stat *stat)
+{
+       switch(stat->st_mode & S_IFMT) {
+               case S_IFREG: return "regular file";
+               case S_IFDIR: return "directory";
+               case S_IFLNK: return "symlink";
+               default: return "unknown";
+       }
+}
+
+static const char * yaffs_error_str(void)
+{
+       int error = yaffsfs_GetLastError();
+
+       if(error < 0)
+               error = -error;
+
+       switch (error) {
+               case EBUSY: return "Busy";
+               case ENODEV: return "No such device";
+               case EINVAL: return "Invalid parameter";
+               case ENFILE: return "Too many open files";
+               case EBADF:  return "Bad handle";
+               case EACCES: return "Wrong permissions";
+               case EXDEV:  return "Not on same device";
+               case ENOENT: return "No such entry";
+               case ENOSPC: return "Device full";
+               case EROFS:  return "Read only file system";
+               case ERANGE: return "Range error";
+               case ENOTEMPTY: return "Not empty";
+               case ENAMETOOLONG: return "Name too long";
+               case ENOMEM: return "Out of memory";
+               case EFAULT: return "Fault";
+               case EEXIST: return "Name exists";
+               case ENOTDIR: return "Not a directory";
+               case EISDIR: return "Not permitted on a directory";
+               case ELOOP:  return "Symlink loop";
+               case 0: return "No error";
+               default: return "Unknown error";
+       }
+}
+
 extern nand_info_t nand_info[];
 
+void cmd_yaffs_tracemask(unsigned set, unsigned mask)
+{
+       if(set)
+               yaffs_trace_mask = mask;
+
+       printf("yaffs trace mask: %08x\n",yaffs_trace_mask);
+}
+
+static int yaffs_regions_overlap(int a, int b, int x, int y)
+{
+       return
+               (a <= x && x <= b) ||
+               (a <= y && y <= b) ||
+               (x <= a && a <= y) ||
+               (x <= b && b <= y);
+}
 
 void cmd_yaffs_devconfig(char *_mp, int flash_dev, int start_block, int end_block)
 {
        struct mtd_info *mtd = NULL;
-       struct yaffs_dev *dev;
-       char *mp;
-       
+       struct yaffs_dev *dev = NULL;
+       struct yaffs_dev *chk;
+       char *mp = NULL;
+       struct nand_chip *chip;
+
        dev = calloc(1, sizeof(*dev));
        mp = strdup(_mp);
-       
+
        mtd = &nand_info[flash_dev];
+
        if(!dev || !mp) {
                /* Alloc error */
-               return;
+               printf("Failed to allocate memory\n");
+               goto err;
        }
 
-       if(end_block < start_block)
-               end_block = mtd->size / mtd->erasesize;
+       if(flash_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
+               printf("Flash device invalid\n");
+       }
+       
+       if(end_block == 0)
+               end_block = mtd->size / mtd->erasesize - 1;
+
+       if(end_block < start_block) {
+               printf("Bad start/end\n");
+               goto err;
+       }
+
+       chip =  mtd->priv;
+
+       /* Check for any conflicts */
+       yaffs_dev_rewind();
+       while(1) {
+               chk = yaffs_next_dev();
+               if(!chk)
+                       break;
+               if(strcmp(chk->param.name, mp) == 0) {
+                       printf("Mount point name already used\n");
+                       goto err;
+               }
+               if(chk->driver_context == mtd &&
+                       yaffs_regions_overlap(
+                               chk->param.start_block, chk->param.end_block,
+                               start_block, end_block)) {
+                       printf("Region overlaps with partition %s\n",
+                               chk->param.name);
+                       goto err;
+               }
 
+       }
+
+       /* Seems sane, so configure */
        memset(dev, 0, sizeof(*dev));
        dev->param.name = mp;
        dev->driver_context = mtd;
@@ -125,19 +227,55 @@ void cmd_yaffs_devconfig(char *_mp, int flash_dev, int start_block, int end_bloc
        dev->param.is_yaffs2 = 1;
        dev->param.use_nand_ecc = 1;
        dev->param.n_reserved_blocks = 5;
-       dev->param.inband_tags = 0;
+       if (chip->ecc.layout->oobavail < sizeof(struct yaffs_packed_tags2))
+               dev->param.inband_tags =1;
        dev->param.n_caches = 10;
-       dev->param.write_chunk_tags_fn = nandmtd2_WriteChunkWithTagsToNAND;
-       dev->param.read_chunk_tags_fn = nandmtd2_ReadChunkWithTagsFromNAND;
+       dev->param.write_chunk_tags_fn = nandmtd2_write_chunk_tags;
+       dev->param.read_chunk_tags_fn = nandmtd2_read_chunk_tags;
        dev->param.erase_fn = nandmtd_EraseBlockInNAND;
        dev->param.initialise_flash_fn = nandmtd_InitialiseNAND;
        dev->param.bad_block_fn = nandmtd2_MarkNANDBlockBad;
        dev->param.query_block_fn = nandmtd2_QueryNANDBlock;
-       
+
        yaffs_add_device(dev);
+
+       printf("Configures yaffs mount %s: dev %d start block %d, end block %d %s\n",
+               mp, flash_dev, start_block, end_block, 
+               dev->param.inband_tags ? "using inband tags" : "");
+       return;
+
+err:
+       free(dev);
+       free(mp);
 }
-       
 
+void cmd_yaffs_dev_ls(void)
+{
+       struct yaffs_dev *dev;
+       int flash_dev;
+       int free_space;
+
+       yaffs_dev_rewind();
+
+       while(1) {
+               dev = yaffs_next_dev();
+               if(!dev)
+                       return;
+               flash_dev = ((unsigned) dev->driver_context - (unsigned) nand_info)/
+                               sizeof(nand_info[0]);
+               printf("%-10s %5d 0x%05x 0x%05x %s",
+                       dev->param.name, flash_dev,
+                       dev->param.start_block, dev->param.end_block,
+                       dev->param.inband_tags ? "using inband tags, " : "");
+
+               free_space = yaffs_freespace(dev->param.name);
+               if(free_space < 0)
+                       printf("not mounted\n");
+               else
+                       printf("free 0x%x\n", free_space);
+
+       }
+}
 
 void make_a_file(char *yaffsName,char bval,int sizeOfFile)
 {
@@ -148,7 +286,7 @@ void make_a_file(char *yaffsName,char bval,int sizeOfFile)
        outh = yaffs_open(yaffsName, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
        if (outh < 0)
        {
-               printf("Error opening file: %d\n", outh);
+               printf("Error opening file: %d. %s\n", outh, yaffs_error_str());
                return;
        }
 
@@ -198,14 +336,16 @@ void cmd_yaffs_mount(char *mp)
 {
        int retval = yaffs_mount(mp);
        if( retval < 0)
-               printf("Error mounting %s, return value: %d\n", mp, yaffsfs_GetError());
+               printf("Error mounting %s, return value: %d, %s\n", mp,
+                       yaffsfs_GetError(), yaffs_error_str());
 }
 
 
 void cmd_yaffs_umount(char *mp)
 {
        if( yaffs_unmount(mp) == -1)
-               printf("Error umounting %s, return value: %d\n", mp, yaffsfs_GetError());
+               printf("Error umounting %s, return value: %d, %s\n", mp,
+                       yaffsfs_GetError(), yaffs_error_str());
 }
 
 void cmd_yaffs_write_file(char *yaffsName,char bval,int sizeOfFile)
@@ -249,7 +389,7 @@ void cmd_yaffs_mwrite_file(char *fn, char *addr, int size)
        outh = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
        if (outh < 0)
        {
-               printf("Error opening file: %d\n", outh);
+               printf("Error opening file: %d, %s\n", outh, yaffs_error_str());
        }
 
        yaffs_write(outh,addr,size);
@@ -268,26 +408,27 @@ void cmd_yaffs_ls(const char *mountpt, int longlist)
 
        d = yaffs_opendir(mountpt);
 
-       if(!d)
-       {
-               printf("opendir failed\n");
+       if(!d) {
+               printf("opendir failed, %s\n", yaffs_error_str());
+               return;
        }
-       else
-       {
-               for(i = 0; (de = yaffs_readdir(d)) != NULL; i++)
-               {
-                       if (longlist)
-                       {
-                               sprintf(tempstr, "%s/%s", mountpt, de->d_name);
-                               yaffs_stat(tempstr, &stat);
-                               printf("%-25s\t%7ld\n",de->d_name, stat.st_size);
-                       }
-                       else
-                       {
-                               printf("%s\n",de->d_name);
-                       }
+
+       for(i = 0; (de = yaffs_readdir(d)) != NULL; i++) {
+               if (longlist) {
+                       sprintf(tempstr, "%s/%s", mountpt, de->d_name);
+                       yaffs_lstat(tempstr, &stat);
+                       printf("%-25s\t%7ld",
+                                       de->d_name,
+                                       (long)stat.st_size);
+                       printf(" %5d %s\n",
+                                       stat.st_ino,
+                                       yaffs_file_type_str(&stat));
+               } else {
+                       printf("%s\n",de->d_name);
                }
        }
+
+       yaffs_closedir(d);
 }
 
 
@@ -296,7 +437,8 @@ void cmd_yaffs_mkdir(const char *dir)
        int retval = yaffs_mkdir(dir, 0);
 
        if ( retval < 0)
-               printf("yaffs_mkdir returning error: %d\n", retval);
+               printf("yaffs_mkdir returning error: %d, %s\n",
+                       retval, yaffs_error_str());
 }
 
 void cmd_yaffs_rmdir(const char *dir)
@@ -304,7 +446,8 @@ void cmd_yaffs_rmdir(const char *dir)
        int retval = yaffs_rmdir(dir);
 
        if ( retval < 0)
-               printf("yaffs_rmdir returning error: %d\n", retval);
+               printf("yaffs_rmdir returning error: %d, %s\n",
+                       retval, yaffs_error_str());
 }
 
 void cmd_yaffs_rm(const char *path)
@@ -312,7 +455,8 @@ void cmd_yaffs_rm(const char *path)
        int retval = yaffs_unlink(path);
 
        if ( retval < 0)
-               printf("yaffs_unlink returning error: %d\n", retval);
+               printf("yaffs_unlink returning error: %d, %s\n",
+                       retval, yaffs_error_str());
 }
 
 void cmd_yaffs_mv(const char *oldPath, const char *newPath)
@@ -320,5 +464,6 @@ void cmd_yaffs_mv(const char *oldPath, const char *newPath)
        int retval = yaffs_rename(newPath, oldPath);
 
        if ( retval < 0)
-               printf("yaffs_unlink returning error: %d\n", retval);
+               printf("yaffs_unlink returning error: %d, %s\n",
+                       retval, yaffs_error_str());
 }
diff --git a/direct/u-boot/patch-u-boot.sh b/direct/u-boot/patch-u-boot.sh
new file mode 100755 (executable)
index 0000000..8caa2e8
--- /dev/null
@@ -0,0 +1,118 @@
+#!/bin/sh
+#
+# YAFFS: Yet another FFS. A NAND-flash specific file system.
+#
+# Copyright (C) 2002-2010 Aleph One Ltd.
+#
+# 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.
+#
+# Patch yaffs2 into u-boot
+#
+#  args: 
+#        u-boot-path  : Full path to u-boot sources to be patched
+#
+#  Inspired yaffs kernel patching script
+
+set -e -x
+
+UBOOTDIR=$1
+
+# Display usage of this script
+usage () {
+       echo "usage:  $0 u-boot-path"
+       exit 1
+}
+
+not_u_boot () {
+       echo "$1 does not seem to be a u-boot directory"
+       exit 1
+}
+
+
+if [ -z $UBOOTDIR ]
+then
+    usage;
+fi
+
+# Basic sanity check:
+# Check it has a Makefile, common and fs sub-directories
+
+if [ ! -f "$UBOOTDIR/Makefile" ]
+then
+       not_u_boot
+fi
+
+if [ ! -d "$UBOOTDIR/common" ]
+then
+       not_u_boot
+fi
+
+if [ ! -d "$UBOOTDIR/fs" ]
+then
+       not_u_boot
+fi
+
+
+YAFFS_IN_MAKEFILE=`grep -s libyaffs2 <$UBOOTDIR/Makefile | head -n 1`
+YAFFS_IN_COMMON=`grep -s yaffs2 <$UBOOTDIR/common/Makefile | head -n 1`
+LIB_A=`grep -s libnet\.a <$UBOOTDIR/Makefile | head -n 1`
+
+if [ ! -z "$LIB_A" ]
+then
+    A_OR_O="a"
+else
+    A_OR_O="o"
+fi
+
+# Patch Makefile if it does not mention yaffs2
+if [ ! -z "$YAFFS_IN_MAKEFILE" ]
+then
+    echo "$UBOOTDIR/Makefile already makes yaffs library"
+else
+   # Update the Makefile
+   mv -f $UBOOTDIR/Makefile $UBOOTDIR/Makefile.old
+   sed -n -e "/libnet/,99999 ! p" < $UBOOTDIR/Makefile.old > $UBOOTDIR/Makefile
+   echo "LIBS += fs/yaffs2/libyaffs2.$A_OR_O" >> $UBOOTDIR/Makefile
+   sed -n -e "/libnet/,99999 p" < $UBOOTDIR/Makefile.old >> $UBOOTDIR/Makefile
+fi
+
+# Patch common/Makefile if it does not mention yaffs2
+if [ ! -z "$YAFFS_IN_COMMON" ]
+then
+    echo "$UBOOTDIR/common/Makefile already makes yaffs commands"
+else
+   # Update the Makefile
+   mv -f $UBOOTDIR/common/Makefile $UBOOTDIR/common/Makefile.old
+   sed -n -e "/cmd_jffs/,99999 ! p" <$UBOOTDIR/common/Makefile.old > $UBOOTDIR/common/Makefile
+   echo "COBJS-\$(CONFIG_YAFFS2) += cmd_yaffs2.o" >> $UBOOTDIR/common/Makefile
+   sed -n -e "/cmd_jffs/,99999 p" <$UBOOTDIR/common/Makefile.old >> $UBOOTDIR/common/Makefile
+fi
+
+
+#
+# Ensure the direct code is up to date
+#
+
+RUN_DIR=`pwd`
+cd ..
+./handle_common.sh copy
+cd $RUN_DIR
+
+#
+# Copy in the files we need
+#
+
+cp common/* $UBOOTDIR/common/
+
+mkdir -p $UBOOTDIR/fs/yaffs2
+cp ../*.[ch] $UBOOTDIR/fs/yaffs2/
+cp fs/yaffs2/*.[ch] $UBOOTDIR/fs/yaffs2/
+
+sed -e "s/A_OR_O/$A_OR_O/" < fs/yaffs2/Makefile > $UBOOTDIR/fs/yaffs2/Makefile
+
+
+
index fffc11e..917c202 100644 (file)
@@ -2768,8 +2768,27 @@ void yaffs_remove_device(struct yaffs_dev *dev)
        list_del_init(&dev->dev_list);
 }
 
+/* Functions to iterate through devices. NB Use with extreme care! */
 
+static struct list_head *dev_iterator;
+void yaffs_dev_rewind(void)
+{
+       dev_iterator = yaffsfs_deviceList.next;
+}
 
+struct yaffs_dev *yaffs_next_dev(void)
+{
+       struct yaffs_dev *retval;
+
+       if(!dev_iterator)
+               return NULL;
+       if(dev_iterator == &yaffsfs_deviceList)
+               return NULL;
+
+       retval = list_entry(dev_iterator, struct yaffs_dev, dev_list);
+       dev_iterator = dev_iterator->next;
+       return retval;
+}
 
 /* Directory search stuff. */
 
index 657f364..0d4ea15 100644 (file)
@@ -180,13 +180,16 @@ int yaffs_n_handles(const YCHAR *path);
 #define YAFFS_SHARE_WRITE 2
 int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int shareMode) ;
 
-
 struct yaffs_dev;
 void yaffs_add_device(struct yaffs_dev *dev);
 
 int yaffs_start_up(void);
 int yaffsfs_GetLastError(void);
 
+/* Functions to iterate through devices. NB Use with extreme care! */
+void yaffs_dev_rewind(void);
+struct yaffs_dev *yaffs_next_dev(void);
+
 /* Function to get the last error */
 int yaffs_get_error(void);
 const char * yaffs_error_to_str(int err);
index fbf4606..f2bb496 100644 (file)
@@ -28,9 +28,9 @@
 #include "yaffs_osglue.h"
 #include "yaffs_hweight.h"
 
-#include "assert.h"
-#define BUG() assert(0)
-//#define BUG() do { *((int *)0) =1;} while(0)
+void yaffs_bug_fn(const char *file_name, int line_no);
+
+#define BUG() do { yaffs_bug_fn(__FILE__, __LINE__); } while (0)
 
 
 #define YCHAR char