]> www.infradead.org Git - mtd-utils.git/commitdiff
Copy with write errors in nandwrite, add 'markbad' option too.
authorDavid Woodhouse <dwmw2@infradead.org>
Mon, 6 Aug 2007 08:13:30 +0000 (16:13 +0800)
committerDavid Woodhouse <dwmw2@infradead.org>
Mon, 6 Aug 2007 08:13:30 +0000 (16:13 +0800)
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
nandwrite.c

index 6c4653f8387a23e5be15c8171faf4c2ef253833e..a5462ae47fbdee485df924a9b59ffb9b26d74b56 100644 (file)
@@ -78,7 +78,8 @@ void display_help (void)
                        "  -a, --autoplace      Use auto oob layout\n"
                        "  -j, --jffs2          force jffs2 oob layout (legacy support)\n"
                        "  -y, --yaffs          force yaffs oob layout (legacy support)\n"
-                       "  -f, --forcelegacy     force legacy support on autoplacement enabled mtd device\n"
+                       "  -f, --forcelegacy    force legacy support on autoplacement enabled mtd device\n"
+                       "  -m, --markbad                mark blocks bad if write fails\n"
                        "  -n, --noecc          write without ecc\n"
                        "  -o, --oob            image contains oob data\n"
                        "  -s addr, --start=addr set start address (default is 0)\n"
@@ -109,6 +110,7 @@ char        *mtd_device, *img;
 int    mtdoffset = 0;
 int    quiet = 0;
 int    writeoob = 0;
+int    markbad = 0;
 int    autoplace = 0;
 int    forcejffs2 = 0;
 int    forceyaffs = 0;
@@ -123,7 +125,7 @@ void process_options (int argc, char *argv[])
 
        for (;;) {
                int option_index = 0;
-               static const char *short_options = "ab:fjnopqs:y";
+               static const char *short_options = "ab:fjmnopqs:y";
                static const struct option long_options[] = {
                        {"help", no_argument, 0, 0},
                        {"version", no_argument, 0, 0},
@@ -131,6 +133,7 @@ void process_options (int argc, char *argv[])
                        {"blockalign", required_argument, 0, 'b'},
                        {"forcelegacy", no_argument, 0, 'f'},
                        {"jffs2", no_argument, 0, 'j'},
+                       {"markbad", no_argument, 0, 'm'},
                        {"noecc", no_argument, 0, 'n'},
                        {"oob", no_argument, 0, 'o'},
                        {"pad", no_argument, 0, 'p'},
@@ -175,6 +178,9 @@ void process_options (int argc, char *argv[])
                        case 'n':
                                noecc = 1;
                                break;
+                       case 'm':
+                               markbad = 1;
+                               break;
                        case 'o':
                                writeoob = 1;
                                break;
@@ -450,8 +456,42 @@ int main(int argc, char **argv)
 
                /* Write out the Page data */
                if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) {
+                       int rewind_blocks;
+                       off_t rewind_bytes;
+                       erase_info_t erase;
+
                        perror ("pwrite");
-                       goto closeall;
+                       /* Must rewind to blockstart if we can */
+                       rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */
+                       rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen;
+                       if (writeoob)
+                               rewind_bytes += (rewind_blocks + 1) * meminfo.oobsize;
+                       if (lseek(ifd, -rewind_bytes, SEEK_CUR) == -1) {
+                               perror("lseek");
+                               fprintf(stderr, "Failed to seek backwards to recover from write error\n");
+                               goto closeall;
+                       }
+                       erase.start = blockstart;
+                       erase.length = meminfo.erasesize;
+                       fprintf(stderr, "Erasing failed write from %08lx-%08lx\n",
+                               (long)erase.start, (long)erase.start+erase.length-1);
+                       if (ioctl(fd, MEMERASE, &erase) != 0) {
+                               perror("MEMERASE");
+                               goto closeall;
+                       }
+
+                       if (markbad) {
+                               loff_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1);
+                               fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr);
+                               if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) {
+                                       perror("MEMSETBADBLOCK");
+                                       /* But continue anyway */
+                               }
+                       }
+                       mtdoffset = blockstart + meminfo.erasesize;
+                       imglen += rewind_blocks * meminfo.writesize;
+
+                       continue;
                }
                imglen -= readlen;
                mtdoffset += meminfo.writesize;