X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fcmd_nand.c;h=7bd37de78dee9e717f4c521c2eeaa51fe2825de3;hb=eed1a7b1cfccd427d940a281e21000d8a2f669aa;hp=41aaf7f266f11b36a82f073f41f383fc2810e948;hpb=ea533c260a801c4e51f92f75165cebe6d7b01e35;p=oweals%2Fu-boot.git diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 41aaf7f266..7bd37de78d 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -37,10 +37,16 @@ int find_dev_and_part(const char *id, struct mtd_device **dev, u8 *part_num, struct part_info **part); #endif -static int nand_dump(nand_info_t *nand, ulong off, int only_oob) +static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) { int i; u_char *datbuf, *oobbuf, *p; + static loff_t last; + + if (repeat) + off = last + nand->writesize; + + last = off; datbuf = malloc(nand->writesize + nand->oobsize); oobbuf = malloc(nand->oobsize); @@ -381,6 +387,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) #endif const char *quiet_str = getenv("quiet"); int dev = nand_curr_device; + int repeat = flag & CMD_FLAG_REPEAT; /* at least two arguments please */ if (argc < 2) @@ -391,6 +398,10 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) cmd = argv[1]; + /* Only "dump" is repeatable. */ + if (repeat && strcmp(cmd, "dump")) + return 0; + if (strcmp(cmd, "info") == 0) { putc('\n'); @@ -449,14 +460,40 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) * 0 1 2 3 4 * nand erase [clean] [off size] */ - if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) { + if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) { nand_erase_options_t opts; /* "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"); + int scrub = !strncmp(cmd, "scrub", 5); + int part = 0; + int chip = 0; + int spread = 0; + int args = 2; + + if (cmd[5] != 0) { + if (!strcmp(&cmd[5], ".spread")) { + spread = 1; + } else if (!strcmp(&cmd[5], ".part")) { + part = 1; + args = 1; + } else if (!strcmp(&cmd[5], ".chip")) { + chip = 1; + args = 0; + } else { + goto usage; + } + } - printf("\nNAND %s: ", scrub ? "scrub" : "erase"); + /* + * Don't allow missing arguments to cause full chip/partition + * erases -- easy to do accidentally, e.g. with a misspelled + * variable name. + */ + if (argc != o + args) + goto usage; + + printf("\nNAND %s: ", cmd); /* skip first two or three arguments, look for offset and size */ if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0) return 1; @@ -468,6 +505,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) opts.length = size; opts.jffs2 = clean; opts.quiet = quiet; + opts.spread = spread; if (scrub) { puts("Warning: " @@ -505,16 +543,10 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) if (argc < 3) goto usage; - s = strchr(cmd, '.'); off = (int)simple_strtoul(argv[2], NULL, 16); - - if (s != NULL && strcmp(s, ".oob") == 0) - ret = nand_dump(nand, off, 1); - else - ret = nand_dump(nand, off, 0); + ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat); return ret == 0 ? 1 : 0; - } if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { @@ -542,7 +574,15 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) (u_char *)addr); else ret = nand_write_skip_bad(nand, off, &rwsize, - (u_char *)addr); + (u_char *)addr, 0); +#ifdef CONFIG_CMD_NAND_YAFFS + } else if (!strcmp(s, ".yaffs")) { + if (read) { + printf("Unknown nand command suffix '%s'.\n", s); + return 1; + } + ret = nand_write_skip_bad(nand, off, &rwsize, (u_char *)addr, 1); +#endif } else if (!strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { @@ -621,7 +661,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) } if (strcmp(cmd, "unlock") == 0) { - if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0) + if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0) return 1; if (!nand_unlock(&nand_info[dev], off, size)) { @@ -648,11 +688,21 @@ U_BOOT_CMD( "nand write - addr off|partition size\n" " read/write 'size' bytes starting at offset 'off'\n" " to/from memory address 'addr', skipping bad blocks.\n" - "nand erase [clean] [off size] - erase 'size' bytes from\n" - " offset 'off' (entire device if not specified)\n" +#ifdef CONFIG_CMD_NAND_YAFFS + "nand write.yaffs - addr off|partition size\n" + " write 'size' bytes starting at offset 'off' with yaffs format\n" + " from memory address 'addr', skipping bad blocks.\n" +#endif + "nand erase[.spread] [clean] [off [size]] - erase 'size' bytes " + "from offset 'off'\n" + " With '.spread', erase enough for given file size, otherwise,\n" + " 'size' includes skipped bad blocks.\n" + "nand erase.part [clean] partition - erase entire mtd partition'\n" + "nand erase.chip [clean] - erase entire chip'\n" "nand bad - show bad blocks\n" "nand dump[.oob] off - dump page\n" - "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n" + "nand scrub off size | scrub.part partition | scrub.chip\n" + " really clean NAND erasing bad blocks (UNSAFE)\n" "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n" "nand biterr off - make a bit error at offset (UNSAFE)" #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK @@ -752,7 +802,6 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, /* Check if we should attempt an auto-start */ if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) { char *local_args[2]; - extern int do_bootm(cmd_tbl_t *, int, int, char *[]); local_args[0] = cmd; local_args[1] = NULL;