| diff -aruN a/nandtest.c b/nandtest.c |
| --- a/nandtest.c 2011-11-16 11:20:33.715549264 -0800 |
| +++ b/nandtest.c 2011-11-16 11:20:46.135549260 -0800 |
| @@ -4,6 +4,7 @@ |
| #include <ctype.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| +#include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| @@ -37,6 +38,9 @@ |
| int markbad=0; |
| int seed; |
| |
| +/* |
| + * Erase and write block by block, checking for errors |
| + */ |
| int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf) |
| { |
| struct erase_info_user er; |
| @@ -126,6 +130,71 @@ |
| return 0; |
| } |
| |
| +/* |
| + * Restore page by page, skipping empty writes (writing all 0xff can result in non-0xff |
| + * OOB bytes in empty blocks, which will be a problem for the fs after the test is complete). |
| + */ |
| +int erase_and_restore(loff_t ofs, unsigned char *data) |
| +{ |
| + struct erase_info_user er; |
| + ssize_t len; |
| + int page; |
| + int page_count = (meminfo.erasesize/meminfo.writesize); |
| + int i; |
| + bool isempty; |
| + unsigned char *data_page = data; |
| + |
| + printf("\r%08x: erasing... ", (unsigned)ofs); |
| + fflush(stdout); |
| + |
| + er.start = ofs; |
| + er.length = meminfo.erasesize; |
| + |
| + /* Erase the whole block */ |
| + if (ioctl(fd, MEMERASE, &er)) { |
| + perror("MEMERASE"); |
| + if (markbad) { |
| + printf("Mark block bad at %08lx\n", (long)ofs); |
| + ioctl(fd, MEMSETBADBLOCK, &ofs); |
| + } |
| + return 1; |
| + } |
| + |
| + printf("\r%08x: writing...", (unsigned)ofs); |
| + fflush(stdout); |
| + |
| + /* Write back page by page */ |
| + for (page = 0; page < page_count; page++, data_page += meminfo.writesize, ofs += meminfo.writesize) { |
| + isempty = true; |
| + for (i = 0; i < meminfo.writesize; i++) { |
| + if (data_page[i] != 0xff) { |
| + isempty = false; |
| + break; |
| + } |
| + } |
| + |
| + if (isempty == false) { |
| + len = pwrite(fd, data_page, meminfo.writesize, ofs); |
| + |
| + if (len < 0) { |
| + printf("\n"); |
| + perror("write"); |
| + if (markbad) { |
| + printf("Mark block bad at %08lx\n", (long)ofs); |
| + ioctl(fd, MEMSETBADBLOCK, &ofs); |
| + } |
| + return 1; |
| + } |
| + if (len < meminfo.writesize) { |
| + printf("\n"); |
| + fprintf(stderr, "Short write (%zd bytes)\n", len); |
| + exit(1); |
| + } |
| + } |
| + } |
| + |
| + return 0; |
| +} |
| |
| /* |
| * Main program |
| @@ -226,7 +295,7 @@ |
| wbuf = malloc(meminfo.erasesize * 3); |
| if (!wbuf) { |
| fprintf(stderr, "Could not allocate %d bytes for buffer\n", |
| - meminfo.erasesize * 2); |
| + meminfo.erasesize * 3); |
| exit(1); |
| } |
| rbuf = wbuf + meminfo.erasesize; |
| @@ -277,7 +346,7 @@ |
| if (erase_and_write(test_ofs, wbuf, rbuf)) |
| continue; |
| if (keep_contents) |
| - erase_and_write(test_ofs, kbuf, rbuf); |
| + erase_and_restore(test_ofs, kbuf); |
| } |
| printf("\nFinished pass %d successfully\n", pass+1); |
| } |