X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_nand.c;h=8d6c959584f64de348c3fc0d5276f186c7c08ebc;hb=3f105faa64b9826e088711fdfcaa70cb1230397a;hp=4fb3b65960d924e184bf03e3900c55257b28b70b;hpb=034df411c1feecf8fe9f382a52b28a36a8f5d933;p=u-boot diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 4fb3b65960..8d6c959584 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -19,23 +19,24 @@ */ #include -#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#if defined(CONFIG_CMD_NAND) #include #include #include #include - -#ifdef CONFIG_SHOW_BOOT_PROGRESS -# include -# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) -#else -# define SHOW_BOOT_PROGRESS(arg) -#endif - #include #include +#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + +/* parition handling routines */ +int mtdparts_init(void); +int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num); +int find_dev_and_part(const char *id, struct mtd_device **dev, + u8 *part_num, struct part_info **part); +#endif + extern nand_info_t nand_info[]; /* info for NAND chips */ static int nand_dump_oob(nand_info_t *nand, ulong off) @@ -83,50 +84,75 @@ static int nand_dump(nand_info_t *nand, ulong off) /* ------------------------------------------------------------------------- */ -static void -arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize) +static inline int str2long(char *p, ulong *num) { - *off = 0; - *size = 0; - -#if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART) - if (argc >= 1 && strcmp(argv[0], "partition") == 0) { - int part_num; - struct part_info *part; - const char *partstr; - - if (argc >= 2) - partstr = argv[1]; - else - partstr = getenv("partition"); + char *endptr; - if (partstr) - part_num = (int)simple_strtoul(partstr, NULL, 10); - else - part_num = 0; + *num = simple_strtoul(p, &endptr, 16); + return (*p != '\0' && *endptr == '\0') ? 1 : 0; +} - part = jffs2_part_info(part_num); - if (part == NULL) { - printf("\nInvalid partition %d\n", part_num); - return; +static int +arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, ulong *size) +{ + int idx = nand_curr_device; +#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + struct mtd_device *dev; + struct part_info *part; + u8 pnum; + + if (argc >= 1 && !(str2long(argv[0], off))) { + if ((mtdparts_init() == 0) && + (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) { + if (dev->id->type != MTD_DEV_TYPE_NAND) { + puts("not a NAND device\n"); + return -1; + } + *off = part->offset; + if (argc >= 2) { + if (!(str2long(argv[1], size))) { + printf("'%s' is not a number\n", argv[1]); + return -1; + } + if (*size > part->size) + *size = part->size; + } else { + *size = part->size; + } + idx = dev->id->num; + *nand = nand_info[idx]; + goto out; } - *size = part->size; - *off = (ulong)part->offset; - } else + } #endif - { - if (argc >= 1) - *off = (ulong)simple_strtoul(argv[0], NULL, 16); - else - *off = 0; - if (argc >= 2) - *size = (ulong)simple_strtoul(argv[1], NULL, 16); - else - *size = totsize - *off; + if (argc >= 1) { + if (!(str2long(argv[0], off))) { + printf("'%s' is not a number\n", argv[0]); + return -1; + } + } else { + *off = 0; + } + if (argc >= 2) { + if (!(str2long(argv[1], size))) { + printf("'%s' is not a number\n", argv[1]); + return -1; + } + } else { + *size = nand->size - *off; } +#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) +out: +#endif + printf("device %d ", idx); + if (*size == nand->size) + puts("whole chip\n"); + else + printf("offset 0x%x, size 0x%x\n", *off, *size); + return 0; } int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) @@ -135,7 +161,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) ulong addr, off, size; char *cmd, *s; nand_info_t *nand; +#ifdef CFG_NAND_QUIET + int quiet = CFG_NAND_QUIET; +#else int quiet = 0; +#endif const char *quiet_str = getenv("quiet"); /* at least two arguments please */ @@ -213,35 +243,22 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 0; } + /* + * Syntax is: + * 0 1 2 3 4 + * nand erase [clean] [off size] + */ if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) { nand_erase_options_t opts; - int clean = argc >= 3 && !strcmp("clean", argv[2]); - int rest_argc = argc - 2; - char **rest_argv = argv + 2; + /* "clean" at index 2 means request to write cleanmarker */ + int clean = argc > 2 && !strcmp("clean", argv[2]); + int o = clean ? 3 : 2; int scrub = !strcmp(cmd, "scrub"); - if (clean) { - rest_argc--; - rest_argv++; - } - - if (rest_argc == 0) { - - printf("\nNAND %s: device %d whole chip\n", - cmd, - nand_curr_device); - - off = size = 0; - } else { - arg_off_size(rest_argc, rest_argv, &off, &size, - nand->size); - - if (off == 0 && size == 0) - return 1; - - printf("\nNAND %s: device %d offset 0x%x, size 0x%x\n", - cmd, nand_curr_device, off, size); - } + printf("\nNAND %s: ", scrub ? "scrub" : "erase"); + /* skip first two or three arguments, look for offset and size */ + if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0) + return 1; memset(&opts, 0, sizeof(opts)); opts.offset = off; @@ -250,23 +267,22 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) opts.quiet = quiet; if (scrub) { - printf("Warning: " - "scrub option will erase all factory set " - "bad blocks!\n" - " " - "There is no reliable way to recover them.\n" - " " - "Use this command only for testing purposes " - "if you\n" - " " - "are sure of what you are doing!\n" - "\nReally scrub this NAND flash? \n" - ); + puts("Warning: " + "scrub option will erase all factory set " + "bad blocks!\n" + " " + "There is no reliable way to recover them.\n" + " " + "Use this command only for testing purposes " + "if you\n" + " " + "are sure of what you are doing!\n" + "\nReally scrub this NAND flash? \n"); if (getc() == 'y' && getc() == '\r') { opts.scrub = 1; } else { - printf("scrub aborted\n"); + puts("scrub aborted\n"); return -1; } } @@ -301,13 +317,10 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) addr = (ulong)simple_strtoul(argv[2], NULL, 16); - arg_off_size(argc - 3, argv + 3, &off, &size, nand->size); - if (off == 0 && size == 0) - return 1; - read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ - printf("\nNAND %s: device %d offset %u, size %u ... ", - read ? "read" : "write", nand_curr_device, off, size); + printf("\nNAND %s: ", read ? "read" : "write"); + if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) + return 1; s = strchr(cmd, '.'); if (s != NULL && @@ -334,15 +347,21 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) opts.quiet = quiet; ret = nand_write_opts(nand, &opts); } - printf("%s\n", ret ? "ERROR" : "OK"); - return ret == 0 ? 0 : 1; + } else if (s != NULL && !strcmp(s, ".oob")) { + /* read out-of-band data */ + if (read) + ret = nand->read_oob(nand, off, size, (size_t *) &size, + (u_char *) addr); + else + ret = nand->write_oob(nand, off, size, (size_t *) &size, + (u_char *) addr); + } else { + if (read) + ret = nand_read(nand, off, &size, (u_char *)addr); + else + ret = nand_write(nand, off, &size, (u_char *)addr); } - if (read) - ret = nand_read(nand, off, &size, (u_char *)addr); - else - ret = nand_write(nand, off, &size, (u_char *)addr); - printf(" %d bytes %s: %s\n", size, read ? "read" : "written", ret ? "ERROR" : "OK"); @@ -412,9 +431,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } } else { if (!nand_lock(nand, tight)) { - printf ("NAND flash successfully locked\n"); + puts("NAND flash successfully locked\n"); } else { - printf ("Error locking NAND flash. \n"); + puts("Error locking NAND flash\n"); return 1; } } @@ -422,19 +441,14 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } if (strcmp(cmd, "unlock") == 0) { - if (argc == 2) { - off = 0; - size = nand->size; - } else { - arg_off_size(argc - 2, argv + 2, &off, &size, - nand->size); - } + if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0) + return 1; if (!nand_unlock(nand, off, size)) { - printf("NAND flash successfully unlocked\n"); + puts("NAND flash successfully unlocked\n"); } else { - printf("Error unlocking NAND flash. " - "Write and erase will probably fail\n"); + puts("Error unlocking NAND flash, " + "write and erase will probably fail\n"); return 1; } return 0; @@ -449,8 +463,8 @@ U_BOOT_CMD(nand, 5, 1, do_nand, "nand - NAND sub-system\n", "info - show available NAND devices\n" "nand device [dev] - show or set current device\n" - "nand read[.jffs2] - addr off size\n" - "nand write[.jffs2] - addr off size - read/write `size' bytes starting\n" + "nand read[.jffs2] - addr off|partition size\n" + "nand write[.jffs2] - addr off|partition size - read/write `size' bytes starting\n" " at offset `off' to/from memory address `addr'\n" "nand erase [clean] [off size] - erase `size' bytes from\n" " offset `off' (entire device if not specified)\n" @@ -462,84 +476,72 @@ U_BOOT_CMD(nand, 5, 1, do_nand, "nand lock [tight] [status] - bring nand to lock state or display locked pages\n" "nand unlock [offset] [size] - unlock section\n"); -int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, + ulong offset, ulong addr, char *cmd) { - char *boot_device = NULL; - char *ep; - int dev; int r; - ulong addr, cnt, offset = 0; + char *ep, *s; + ulong cnt; image_header_t *hdr; - nand_info_t *nand; + int jffs2 = 0; - switch (argc) { - case 1: - addr = CFG_LOAD_ADDR; - boot_device = getenv("bootdevice"); - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = getenv("bootdevice"); - break; - case 3: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = argv[2]; - break; - case 4: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = argv[2]; - offset = simple_strtoul(argv[3], NULL, 16); - break; - default: - printf("Usage:\n%s\n", cmdtp->usage); - SHOW_BOOT_PROGRESS(-1); - return 1; - } + s = strchr(cmd, '.'); + if (s != NULL && + (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) + jffs2 = 1; - if (!boot_device) { - puts("\n** No boot device **\n"); - SHOW_BOOT_PROGRESS(-1); - return 1; - } - - dev = simple_strtoul(boot_device, &ep, 16); + printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset); - if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) { - printf("\n** Device %d not available\n", dev); - SHOW_BOOT_PROGRESS(-1); - return 1; + cnt = nand->oobblock; + if (jffs2) { + nand_read_options_t opts; + memset(&opts, 0, sizeof(opts)); + opts.buffer = (u_char*) addr; + opts.length = cnt; + opts.offset = offset; + opts.quiet = 1; + r = nand_read_opts(nand, &opts); + } else { + r = nand_read(nand, offset, &cnt, (u_char *) addr); } - nand = &nand_info[dev]; - printf("\nLoading from device %d: %s (offset 0x%lx)\n", - dev, nand->name, offset); - - cnt = nand->oobblock; - r = nand_read(nand, offset, &cnt, (u_char *) addr); if (r) { - printf("** Read error on %d\n", dev); - SHOW_BOOT_PROGRESS(-1); + puts("** Read error\n"); + show_boot_progress (-56); return 1; } + show_boot_progress (56); hdr = (image_header_t *) addr; if (ntohl(hdr->ih_magic) != IH_MAGIC) { printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); - SHOW_BOOT_PROGRESS(-1); + show_boot_progress (-57); return 1; } + show_boot_progress (57); print_image_hdr(hdr); cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t)); + if (jffs2) { + nand_read_options_t opts; + memset(&opts, 0, sizeof(opts)); + opts.buffer = (u_char*) addr; + opts.length = cnt; + opts.offset = offset; + opts.quiet = 1; + r = nand_read_opts(nand, &opts); + } else { + r = nand_read(nand, offset, &cnt, (u_char *) addr); + } - r = nand_read(nand, offset, &cnt, (u_char *) addr); if (r) { - printf("** Read error on %d\n", dev); - SHOW_BOOT_PROGRESS(-1); + puts("** Read error\n"); + show_boot_progress (-58); return 1; } + show_boot_progress (58); /* Loading ok, update default load address */ @@ -550,7 +552,7 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) char *local_args[2]; extern int do_bootm(cmd_tbl_t *, int, int, char *[]); - local_args[0] = argv[0]; + local_args[0] = cmd; local_args[1] = NULL; printf("Automatic boot of image at addr 0x%08lx ...\n", addr); @@ -561,11 +563,89 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 0; } -U_BOOT_CMD(nboot, 4, 1, do_nandboot, - "nboot - boot from NAND device\n", "loadAddr dev\n"); +int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + char *boot_device = NULL; + int idx; + ulong addr, offset = 0; +#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + struct mtd_device *dev; + struct part_info *part; + u8 pnum; + + if (argc >= 2) { + char *p = (argc == 2) ? argv[1] : argv[2]; + if (!(str2long(p, &addr)) && (mtdparts_init() == 0) && + (find_dev_and_part(p, &dev, &pnum, &part) == 0)) { + if (dev->id->type != MTD_DEV_TYPE_NAND) { + puts("Not a NAND device\n"); + return 1; + } + if (argc > 3) + goto usage; + if (argc == 3) + addr = simple_strtoul(argv[1], NULL, 16); + else + addr = CFG_LOAD_ADDR; + return nand_load_image(cmdtp, &nand_info[dev->id->num], + part->offset, addr, argv[0]); + } + } +#endif + show_boot_progress(52); + switch (argc) { + case 1: + addr = CFG_LOAD_ADDR; + boot_device = getenv("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv("bootdevice"); + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + break; + case 4: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + offset = simple_strtoul(argv[3], NULL, 16); + break; + default: +#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) +usage: +#endif + printf("Usage:\n%s\n", cmdtp->usage); + show_boot_progress(-53); + return 1; + } + + show_boot_progress(53); + if (!boot_device) { + puts("\n** No boot device **\n"); + show_boot_progress(-54); + return 1; + } + show_boot_progress(54); -#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ + idx = simple_strtoul(boot_device, NULL, 16); + + if (idx < 0 || idx >= CFG_MAX_NAND_DEVICE || !nand_info[idx].name) { + printf("\n** Device %d not available\n", idx); + show_boot_progress(-55); + return 1; + } + show_boot_progress(55); + + return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]); +} + +U_BOOT_CMD(nboot, 4, 1, do_nandboot, + "nboot - boot from NAND device\n", + "[.jffs2] [partition] | [[[loadAddr] dev] offset]\n"); + +#endif #else /* CFG_NAND_LEGACY */ /* @@ -578,14 +658,14 @@ U_BOOT_CMD(nboot, 4, 1, do_nandboot, #include #include -#ifdef CONFIG_SHOW_BOOT_PROGRESS +#ifdef CONFIG_show_boot_progress # include -# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) +# define show_boot_progress(arg) show_boot_progress(arg) #else -# define SHOW_BOOT_PROGRESS(arg) +# define show_boot_progress(arg) #endif -#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#if defined(CONFIG_CMD_NAND) #include #if 0 #include @@ -642,178 +722,182 @@ extern int nand_write_oob(struct nand_chip *nand, size_t ofs, size_t len, size_t *retlen, const u_char *buf); -int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - int rcode = 0; - - switch (argc) { - case 0: - case 1: - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - case 2: - if (strcmp(argv[1],"info") == 0) { - int i; - - putc ('\n'); + int rcode = 0; - for (i=0; iusage); + return 1; + case 2: + if (strcmp (argv[1], "info") == 0) { + int i; - } else if (strcmp(argv[1],"device") == 0) { - if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) { - puts ("\nno devices available\n"); - return 1; - } - printf ("\nDevice %d: ", curr_device); - nand_print(&nand_dev_desc[curr_device]); - return 0; + putc ('\n'); - } else if (strcmp(argv[1],"bad") == 0) { - if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) { - puts ("\nno devices available\n"); - return 1; - } - printf ("\nDevice %d bad blocks:\n", curr_device); - nand_print_bad(&nand_dev_desc[curr_device]); - return 0; + for (i = 0; i < CFG_MAX_NAND_DEVICE; ++i) { + if (nand_dev_desc[i].ChipID == + NAND_ChipID_UNKNOWN) + continue; /* list only known devices */ + printf ("Device %d: ", i); + nand_print (&nand_dev_desc[i]); + } + return 0; - } - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - case 3: - if (strcmp(argv[1],"device") == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); + } else if (strcmp (argv[1], "device") == 0) { + if ((curr_device < 0) + || (curr_device >= CFG_MAX_NAND_DEVICE)) { + puts ("\nno devices available\n"); + return 1; + } + printf ("\nDevice %d: ", curr_device); + nand_print (&nand_dev_desc[curr_device]); + return 0; - printf ("\nDevice %d: ", dev); - if (dev >= CFG_MAX_NAND_DEVICE) { - puts ("unknown device\n"); - return 1; - } - nand_print(&nand_dev_desc[dev]); - /*nand_print (dev);*/ + } else if (strcmp (argv[1], "bad") == 0) { + if ((curr_device < 0) + || (curr_device >= CFG_MAX_NAND_DEVICE)) { + puts ("\nno devices available\n"); + return 1; + } + printf ("\nDevice %d bad blocks:\n", curr_device); + nand_print_bad (&nand_dev_desc[curr_device]); + return 0; - if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) { - return 1; } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 3: + if (strcmp (argv[1], "device") == 0) { + int dev = (int) simple_strtoul (argv[2], NULL, 10); - curr_device = dev; + printf ("\nDevice %d: ", dev); + if (dev >= CFG_MAX_NAND_DEVICE) { + puts ("unknown device\n"); + return 1; + } + nand_print (&nand_dev_desc[dev]); + /*nand_print (dev); */ - puts ("... is now current device\n"); + if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) { + return 1; + } - return 0; - } - else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) { - struct nand_chip* nand = &nand_dev_desc[curr_device]; - ulong off = 0; - ulong size = nand->totlen; - int ret; + curr_device = dev; - printf ("\nNAND erase: device %d offset %ld, size %ld ... ", - curr_device, off, size); + puts ("... is now current device\n"); - ret = nand_legacy_erase (nand, off, size, 1); + return 0; + } else if (strcmp (argv[1], "erase") == 0 + && strcmp (argv[2], "clean") == 0) { + struct nand_chip *nand = &nand_dev_desc[curr_device]; + ulong off = 0; + ulong size = nand->totlen; + int ret; - printf("%s\n", ret ? "ERROR" : "OK"); + printf ("\nNAND erase: device %d offset %ld, size %ld ... ", curr_device, off, size); - return ret; - } + ret = nand_legacy_erase (nand, off, size, 1); - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - default: - /* at least 4 args */ - - if (strncmp(argv[1], "read", 4) == 0 || - strncmp(argv[1], "write", 5) == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong off = simple_strtoul(argv[3], NULL, 16); - ulong size = simple_strtoul(argv[4], NULL, 16); - int cmd = (strncmp(argv[1], "read", 4) == 0) ? - NANDRW_READ : NANDRW_WRITE; - int ret, total; - char* cmdtail = strchr(argv[1], '.'); + printf ("%s\n", ret ? "ERROR" : "OK"); - if (cmdtail && !strncmp(cmdtail, ".oob", 2)) { - /* read out-of-band data */ - if (cmd & NANDRW_READ) { - ret = nand_read_oob(nand_dev_desc + curr_device, - off, size, (size_t *)&total, - (u_char*)addr); - } - else { - ret = nand_write_oob(nand_dev_desc + curr_device, - off, size, (size_t *)&total, - (u_char*)addr); - } return ret; } - else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2)) - cmd |= NANDRW_JFFS2; /* skip bad blocks */ - else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) { - cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ - if (cmd & NANDRW_READ) - cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ - } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + default: + /* at least 4 args */ + + if (strncmp (argv[1], "read", 4) == 0 || + strncmp (argv[1], "write", 5) == 0) { + ulong addr = simple_strtoul (argv[2], NULL, 16); + ulong off = simple_strtoul (argv[3], NULL, 16); + ulong size = simple_strtoul (argv[4], NULL, 16); + int cmd = (strncmp (argv[1], "read", 4) == 0) ? + NANDRW_READ : NANDRW_WRITE; + int ret, total; + char *cmdtail = strchr (argv[1], '.'); + + if (cmdtail && !strncmp (cmdtail, ".oob", 2)) { + /* read out-of-band data */ + if (cmd & NANDRW_READ) { + ret = nand_read_oob (nand_dev_desc + curr_device, + off, size, (size_t *) & total, + (u_char *) addr); + } else { + ret = nand_write_oob (nand_dev_desc + curr_device, + off, size, (size_t *) & total, + (u_char *) addr); + } + return ret; + } else if (cmdtail && !strncmp (cmdtail, ".jffs2", 2)) + cmd |= NANDRW_JFFS2; /* skip bad blocks */ + else if (cmdtail && !strncmp (cmdtail, ".jffs2s", 2)) { + cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ + if (cmd & NANDRW_READ) + cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ + } #ifdef SXNI855T - /* need ".e" same as ".j" for compatibility with older units */ - else if (cmdtail && !strcmp(cmdtail, ".e")) - cmd |= NANDRW_JFFS2; /* skip bad blocks */ + /* need ".e" same as ".j" for compatibility with older units */ + else if (cmdtail && !strcmp (cmdtail, ".e")) + cmd |= NANDRW_JFFS2; /* skip bad blocks */ #endif #ifdef CFG_NAND_SKIP_BAD_DOT_I - /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */ - /* ".i" for image -> read skips bad block (no 0xff) */ - else if (cmdtail && !strcmp(cmdtail, ".i")) { - cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ - if (cmd & NANDRW_READ) - cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ - } + /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */ + /* ".i" for image -> read skips bad block (no 0xff) */ + else if (cmdtail && !strcmp (cmdtail, ".i")) { + cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ + if (cmd & NANDRW_READ) + cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ + } #endif /* CFG_NAND_SKIP_BAD_DOT_I */ - else if (cmdtail) { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - } + else if (cmdtail) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } - printf ("\nNAND %s: device %d offset %ld, size %ld ...\n", - (cmd & NANDRW_READ) ? "read" : "write", - curr_device, off, size); + printf ("\nNAND %s: device %d offset %ld, size %ld ...\n", + (cmd & NANDRW_READ) ? "read" : "write", + curr_device, off, size); - ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size, - (size_t *)&total, (u_char*)addr); + ret = nand_legacy_rw (nand_dev_desc + curr_device, + cmd, off, size, + (size_t *) & total, + (u_char *) addr); - printf (" %d bytes %s: %s\n", total, - (cmd & NANDRW_READ) ? "read" : "written", - ret ? "ERROR" : "OK"); + printf (" %d bytes %s: %s\n", total, + (cmd & NANDRW_READ) ? "read" : "written", + ret ? "ERROR" : "OK"); - return ret; - } else if (strcmp(argv[1],"erase") == 0 && - (argc == 4 || strcmp("clean", argv[2]) == 0)) { - int clean = argc == 5; - ulong off = simple_strtoul(argv[2 + clean], NULL, 16); - ulong size = simple_strtoul(argv[3 + clean], NULL, 16); - int ret; + return ret; + } else if (strcmp (argv[1], "erase") == 0 && + (argc == 4 || strcmp ("clean", argv[2]) == 0)) { + int clean = argc == 5; + ulong off = + simple_strtoul (argv[2 + clean], NULL, 16); + ulong size = + simple_strtoul (argv[3 + clean], NULL, 16); + int ret; - printf ("\nNAND erase: device %d offset %ld, size %ld ...\n", - curr_device, off, size); + printf ("\nNAND erase: device %d offset %ld, size %ld ...\n", + curr_device, off, size); - ret = nand_legacy_erase (nand_dev_desc + curr_device, - off, size, clean); + ret = nand_legacy_erase (nand_dev_desc + curr_device, + off, size, clean); - printf("%s\n", ret ? "ERROR" : "OK"); + printf ("%s\n", ret ? "ERROR" : "OK"); - return ret; - } else { - printf ("Usage:\n%s\n", cmdtp->usage); - rcode = 1; - } + return ret; + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + rcode = 1; + } - return rcode; - } + return rcode; + } } U_BOOT_CMD( @@ -841,6 +925,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong offset = 0; image_header_t *hdr; int rcode = 0; + show_boot_progress (52); switch (argc) { case 1: addr = CFG_LOAD_ADDR; @@ -861,24 +946,27 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; default: printf ("Usage:\n%s\n", cmdtp->usage); - SHOW_BOOT_PROGRESS (-1); + show_boot_progress (-53); return 1; } + show_boot_progress (53); if (!boot_device) { puts ("\n** No boot device **\n"); - SHOW_BOOT_PROGRESS (-1); + show_boot_progress (-54); return 1; } + show_boot_progress (54); dev = simple_strtoul(boot_device, &ep, 16); if ((dev >= CFG_MAX_NAND_DEVICE) || (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) { printf ("\n** Device %d not available\n", dev); - SHOW_BOOT_PROGRESS (-1); + show_boot_progress (-55); return 1; } + show_boot_progress (55); printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n", dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR, @@ -887,9 +975,10 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset, SECTORSIZE, NULL, (u_char *)addr)) { printf ("** Read error on %d\n", dev); - SHOW_BOOT_PROGRESS (-1); + show_boot_progress (-56); return 1; } + show_boot_progress (56); hdr = (image_header_t *)addr; @@ -901,17 +990,19 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) cnt -= SECTORSIZE; } else { printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic)); - SHOW_BOOT_PROGRESS (-1); + show_boot_progress (-57); return 1; } + show_boot_progress (57); if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset + SECTORSIZE, cnt, NULL, (u_char *)(addr+SECTORSIZE))) { printf ("** Read error on %d\n", dev); - SHOW_BOOT_PROGRESS (-1); + show_boot_progress (-58); return 1; } + show_boot_progress (58); /* Loading ok, update default load address */ @@ -939,6 +1030,6 @@ U_BOOT_CMD( "loadAddr dev\n" ); -#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ +#endif #endif /* CFG_NAND_LEGACY */