* 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;
+ }
+ }
+
+ /*
+ * 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: ", scrub ? "scrub" : "erase");
+ 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;
opts.length = size;
opts.jffs2 = clean;
opts.quiet = quiet;
+ opts.spread = spread;
if (scrub) {
puts("Warning: "
"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"
+ "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
{
struct jffs2_unknown_node cleanmarker;
erase_info_t erase;
- ulong erase_length;
+ unsigned long erase_length, erased_length; /* in blocks */
int bbtest = 1;
int result;
int percent_complete = -1;
struct mtd_oob_ops oob_opts;
struct nand_chip *chip = meminfo->priv;
+ if ((opts->offset & (meminfo->writesize - 1)) != 0) {
+ printf("Attempt to erase non page aligned data\n");
+ return -1;
+ }
+
memset(&erase, 0, sizeof(erase));
memset(&oob_opts, 0, sizeof(oob_opts));
erase.mtd = meminfo;
erase.len = meminfo->erasesize;
erase.addr = opts->offset;
- erase_length = opts->length;
+ erase_length = lldiv(opts->length + meminfo->erasesize - 1,
+ meminfo->erasesize);
cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
priv_nand->bbt = NULL;
}
- if (erase_length < meminfo->erasesize) {
- printf("Warning: Erase size 0x%08lx smaller than one " \
- "erase block 0x%08x\n",erase_length, meminfo->erasesize);
- printf(" Erasing 0x%08x instead\n", meminfo->erasesize);
- erase_length = meminfo->erasesize;
- }
-
- for (;
- erase.addr < opts->offset + erase_length;
+ for (erased_length = 0;
+ erased_length < erase_length;
erase.addr += meminfo->erasesize) {
WATCHDOG_RESET ();
"0x%08llx "
" \n",
erase.addr);
+
+ if (!opts->spread)
+ erased_length++;
+
continue;
} else if (ret < 0) {
}
}
+ erased_length++;
+
result = meminfo->erase(meminfo, &erase);
if (result != 0) {
printf("\n%s: MTD Erase failure: %d\n",
}
if (!opts->quiet) {
- unsigned long long n =(unsigned long long)
- (erase.addr + meminfo->erasesize - opts->offset)
- * 100;
+ unsigned long long n = erased_length * 100ULL;
int percent;
do_div(n, erase_length);
typedef struct nand_read_options nand_read_options_t;
struct nand_erase_options {
- ulong length; /* number of bytes to erase */
- ulong offset; /* first address in NAND to erase */
+ loff_t length; /* number of bytes to erase */
+ loff_t offset; /* first address in NAND to erase */
int quiet; /* don't display progress messages */
int jffs2; /* if true: format for jffs2 usage
* (write appropriate cleanmarker blocks) */
int scrub; /* if true, really clean NAND by erasing
* bad blocks (UNSAFE) */
+
+ /* Don't include skipped bad blocks in size to be erased */
+ int spread;
};
typedef struct nand_erase_options nand_erase_options_t;