diff options
Diffstat (limited to 'nandwrite.c')
-rw-r--r-- | nandwrite.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/nandwrite.c b/nandwrite.c index 6c4653f..a5462ae 100644 --- a/nandwrite.c +++ b/nandwrite.c @@ -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; |