From: Charles Manning Date: Mon, 16 Apr 2012 04:11:29 +0000 (+1200) Subject: Set up u-boot glue code and patching scripts. X-Git-Tag: pre-driver-refactoring~19 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=8b348464b712730cbc18391924d805c1cab7b9ff Set up u-boot glue code and patching scripts. This should patch yaffs2 into a u-boot system. Signed-off-by: Charles Manning --- diff --git a/direct/basic-test/Makefile b/direct/basic-test/Makefile index 9ceaecb..47b3809 100644 --- a/direct/basic-test/Makefile +++ b/direct/basic-test/Makefile @@ -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 diff --git a/direct/basic-test/yaffs_osglue.c b/direct/basic-test/yaffs_osglue.c index 885fb80..4a149e2 100644 --- a/direct/basic-test/yaffs_osglue.c +++ b/direct/basic-test/yaffs_osglue.c @@ -19,7 +19,7 @@ #include "yaffs_nandemul2k.h" #include "yaffs_norif1.h" #include "yaffs_trace.h" - +#include #include @@ -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); +} diff --git a/direct/tests/Makefile b/direct/tests/Makefile index f7f628c..072944a 100644 --- a/direct/tests/Makefile +++ b/direct/tests/Makefile @@ -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 diff --git a/direct/u-boot/common/cmd_yaffs2.c b/direct/u-boot/common/cmd_yaffs2.c index 69ccd09..d7851de 100644 --- a/direct/u-boot/common/cmd_yaffs2.c +++ b/direct/u-boot/common/cmd_yaffs2.c @@ -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); @@ -260,6 +278,18 @@ int do_ymv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return(0); } +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", diff --git a/direct/u-boot/fs/yaffs2/Makefile b/direct/u-boot/fs/yaffs2/Makefile index 0237f3c..f33dbcf 100644 --- a/direct/u-boot/fs/yaffs2/Makefile +++ b/direct/u-boot/fs/yaffs2/Makefile @@ -19,10 +19,10 @@ #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 index 9f379d7..0000000 --- a/direct/u-boot/fs/yaffs2/assert.h +++ /dev/null @@ -1 +0,0 @@ -/* Dummy header for u-boot */ diff --git a/direct/u-boot/fs/yaffs2/yaffs_mtdif2.c b/direct/u-boot/fs/yaffs2/yaffs_mtdif2.c index 2f29491..4d96872 100644 --- a/direct/u-boot/fs/yaffs2/yaffs_mtdif2.c +++ b/direct/u-boot/fs/yaffs2/yaffs_mtdif2.c @@ -27,71 +27,80 @@ #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); diff --git a/direct/u-boot/fs/yaffs2/yaffs_mtdif2.h b/direct/u-boot/fs/yaffs2/yaffs_mtdif2.h index 3b842be..46ec3c6 100644 --- a/direct/u-boot/fs/yaffs2/yaffs_mtdif2.h +++ b/direct/u-boot/fs/yaffs2/yaffs_mtdif2.h @@ -18,13 +18,13 @@ #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 diff --git a/direct/u-boot/fs/yaffs2/yaffscfg.c b/direct/u-boot/fs/yaffs2/yaffs_uboot_glue.c 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 --- a/direct/u-boot/fs/yaffs2/yaffscfg.c +++ b/direct/u-boot/fs/yaffs2/yaffs_uboot_glue.c @@ -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 index 0000000..8caa2e8 --- /dev/null +++ b/direct/u-boot/patch-u-boot.sh @@ -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 +# +# 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 + + + diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index fffc11e..917c202 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -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. */ diff --git a/direct/yaffsfs.h b/direct/yaffsfs.h index 657f364..0d4ea15 100644 --- a/direct/yaffsfs.h +++ b/direct/yaffsfs.h @@ -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); diff --git a/direct/ydirectenv.h b/direct/ydirectenv.h index fbf4606..f2bb496 100644 --- a/direct/ydirectenv.h +++ b/direct/ydirectenv.h @@ -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