summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nandwrite.c46
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;