diff options
Diffstat (limited to 'nand-utils')
-rw-r--r-- | nand-utils/Makemodule.am | 17 | ||||
-rw-r--r-- | nand-utils/nanddump.c | 39 | ||||
-rw-r--r-- | nand-utils/nandflipbits.c | 7 | ||||
-rw-r--r-- | nand-utils/nandtest.c | 49 | ||||
-rw-r--r-- | nand-utils/nandwrite.c | 13 |
5 files changed, 90 insertions, 35 deletions
diff --git a/nand-utils/Makemodule.am b/nand-utils/Makemodule.am index b5a15ac..cee6777 100644 --- a/nand-utils/Makemodule.am +++ b/nand-utils/Makemodule.am @@ -7,29 +7,24 @@ nandwrite_LDADD = libmtd.a nandtest_SOURCES = nand-utils/nandtest.c nandtest_LDADD = libmtd.a -nftldump_SOURCES = nand-utils/nftldump.c +nftldump_SOURCES = nand-utils/nftldump.c include/mtd_swab.h +nftldump_SOURCES += include/mtd/nftl-user.h include/mtd/ftl-user.h nftldump_LDADD = libmtd.a -nftl_format_SOURCES = nand-utils/nftl_format.c +nftl_format_SOURCES = nand-utils/nftl_format.c include/mtd_swab.h +nftl_format_SOURCES += include/mtd/nftl-user.h include/mtd/ftl-user.h nftl_format_LDADD = libmtd.a nandflipbits_SOURCES = nand-utils/nandflipbits.c nandflipbits_LDADD = libmtd.a -NAND_BINS = \ - nanddump nandwrite nandtest nftldump nftl_format nandflipbits - NAND_SH = \ nand-utils/load_nandsim.sh EXTRA_DIST += $(NAND_SH) -sbin_PROGRAMS += $(NAND_BINS) +sbin_PROGRAMS += nanddump nandwrite nandtest nftldump nftl_format nandflipbits if BUILD_TESTS -if INSTALL_TESTS -pkglibexec_SCRIPTS += $(NAND_SH) -else -noinst_SCRIPTS += $(NAND_SH) -endif +test_SCRIPTS += $(NAND_SH) endif diff --git a/nand-utils/nanddump.c b/nand-utils/nanddump.c index d7fc320..b4de05e 100644 --- a/nand-utils/nanddump.c +++ b/nand-utils/nanddump.c @@ -54,6 +54,7 @@ static void display_help(int status) "-s addr --startaddress=addr Start address\n" " --skip-bad-blocks-to-start\n" " Skip bad blocks when seeking to the start address\n" +"-C --continuous Continuous read up to a block of data at a time\n" "\n" "--bb=METHOD, where METHOD can be `padbad', `dumpbad', or `skipbad':\n" " padbad: dump flash data, substituting 0xFF for any bad blocks\n" @@ -89,6 +90,7 @@ static bool quiet = false; // suppress diagnostic output static bool canonical = false; // print nice + ascii static bool forcebinary = false; // force printing binary to tty static bool skip_bad_blocks_to_start = false; +static bool continuous = false; // leverage continuous reads static enum { padbad, // dump flash data, substituting 0xFF for any bad blocks @@ -100,10 +102,11 @@ static void process_options(int argc, char * const argv[]) { int error = 0; bool oob_default = true; + char *dumpfile_tmp = NULL; for (;;) { int option_index = 0; - static const char short_options[] = "hs:f:l:opqncaV"; + static const char short_options[] = "hs:f:l:opqncaVC"; static const struct option long_options[] = { {"version", no_argument, 0, 'V'}, {"bb", required_argument, 0, 0}, @@ -119,6 +122,7 @@ static void process_options(int argc, char * const argv[]) {"length", required_argument, 0, 'l'}, {"noecc", no_argument, 0, 'n'}, {"quiet", no_argument, 0, 'q'}, + {"continuous", no_argument, 0, 'C'}, {0, 0, 0, 0}, }; @@ -162,8 +166,8 @@ static void process_options(int argc, char * const argv[]) start_addr = simple_strtoll(optarg, &error); break; case 'f': - free(dumpfile); - dumpfile = xstrdup(optarg); + free(dumpfile_tmp); + dumpfile = dumpfile_tmp = xstrdup(optarg); break; case 'l': length = simple_strtoll(optarg, &error); @@ -191,6 +195,9 @@ static void process_options(int argc, char * const argv[]) case 'n': noecc = true; break; + case 'C': + continuous = true; + break; case 'h': display_help(EXIT_SUCCESS); break; @@ -220,6 +227,13 @@ static void process_options(int argc, char * const argv[]) exit(EXIT_FAILURE); } + if (continuous && !omitoob) { + fprintf(stderr, "Sequential/continuous reads (when available) will\n" + "always skip OOB data, so it is not possible to \n" + "request both at the same time.\n"); + exit(EXIT_FAILURE); + } + if ((argc - optind) != 1 || error) display_help(EXIT_FAILURE); @@ -332,7 +346,7 @@ static int ofd_write(int ofd, const void *buf, size_t nbyte) */ int main(int argc, char * const argv[]) { - long long ofs, end_addr = 0; + long long ofs, end_addr = 0, readbuf_sz; long long blockstart = 1; int i, fd, ofd = 0, bs, badblock = 0; struct mtd_dev_info mtd; @@ -362,8 +376,9 @@ int main(int argc, char * const argv[]) return errmsg("mtd_get_dev_info failed"); /* Allocate buffers */ + readbuf_sz = mtd.eb_size; oobbuf = xmalloc(mtd.oob_size); - readbuf = xmalloc(mtd.min_io_size); + readbuf = xmalloc(readbuf_sz); if (noecc) { if (ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW) != 0) { @@ -427,8 +442,6 @@ int main(int argc, char * const argv[]) if (!length || end_addr > mtd.size) end_addr = mtd.size; - bs = mtd.min_io_size; - /* Print informative message */ if (!quiet) { fprintf(stderr, "Block size %d, page size %d, OOB size %d\n", @@ -440,6 +453,8 @@ int main(int argc, char * const argv[]) /* Dump the flash contents */ for (ofs = start_addr; ofs < end_addr; ofs += bs) { + long long size_left = end_addr - ofs; + /* Check for bad block */ if (bb_method == dumpbad) { badblock = 0; @@ -453,16 +468,21 @@ int main(int argc, char * const argv[]) } } + if (continuous) + bs = MIN(size_left, mtd.eb_size); + else + bs = mtd.min_io_size; + if (badblock) { /* skip bad block, increase end_addr */ if (bb_method == skipbad) { end_addr += mtd.eb_size; - ofs += mtd.eb_size - bs; + ofs += mtd.eb_size - mtd.min_io_size; if (end_addr > mtd.size) end_addr = mtd.size; continue; } - memset(readbuf, 0xff, bs); + memset(readbuf, 0xff, readbuf_sz); } else { /* Read page data and exit on failure */ if (mtd_read(&mtd, fd, ofs / mtd.eb_size, ofs % mtd.eb_size, readbuf, bs)) { @@ -499,7 +519,6 @@ int main(int argc, char * const argv[]) } } else { /* Write requested length if oob is omitted */ - size_t size_left = end_addr - ofs; if (omitoob && (size_left < bs)) err = ofd_write(ofd, readbuf, size_left); else diff --git a/nand-utils/nandflipbits.c b/nand-utils/nandflipbits.c index aa6850f..a417189 100644 --- a/nand-utils/nandflipbits.c +++ b/nand-utils/nandflipbits.c @@ -203,7 +203,8 @@ int main(int argc, char **argv) int page; if (bits_to_flip[i].offset >= mtdlen) { - fprintf(stderr, "Invalid byte offset %lld (max %lld)\n", + fprintf(stderr, "Invalid byte offset %" PRId64 + " (max %" PRId64 ")\n", bits_to_flip[i].offset, mtdlen); ret = EXIT_FAILURE; goto free_buf; @@ -249,7 +250,9 @@ int main(int argc, char **argv) bufoffs += mtd.min_io_size; - ret = mtd_read_oob(mtd_desc, &mtd, fd, blkoffs, + ret = mtd_read_oob(mtd_desc, &mtd, fd, + (unsigned long long)bit_to_flip->block * mtd.eb_size + + blkoffs, mtd.oob_size, buffer + bufoffs); if (ret) { fprintf(stderr, "MTD OOB read failure\n"); diff --git a/nand-utils/nandtest.c b/nand-utils/nandtest.c index 06dec25..cac0dde 100644 --- a/nand-utils/nandtest.c +++ b/nand-utils/nandtest.c @@ -8,6 +8,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <limits.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/types.h> @@ -144,6 +145,26 @@ static int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf, return 0; } +static uint64_t get_mem_size(const char* device) +{ + const char* p = strrchr(device, '/'); + char path[PATH_MAX]; + int fd; + + snprintf(path, sizeof(path), "/sys/class/mtd/%s/size", p); + fd = open(path, O_RDONLY); + if (fd >= 0) { + char buffer[32]; + ssize_t n = read(fd, buffer, sizeof(buffer)); + close(fd); + if (n > 0) { + return strtoull(buffer, NULL, 0); + } + } + + fprintf(stderr, "Can't read size from %s\n", path); + exit(1); +} /* * Main program @@ -156,8 +177,9 @@ int main(int argc, char **argv) int nr_passes = 1; int nr_reads = 4; int keep_contents = 0; - uint32_t offset = 0; - uint32_t length = -1; + uint64_t offset = 0; + uint64_t length = -1; + uint64_t mem_size = 0; int error = 0; seed = time(NULL); @@ -212,11 +234,11 @@ int main(int argc, char **argv) break; case 'o': - offset = simple_strtoul(optarg, &error); + offset = simple_strtoull(optarg, &error); break; case 'l': - length = simple_strtoul(optarg, &error); + length = simple_strtoull(optarg, &error); break; } @@ -238,29 +260,34 @@ int main(int argc, char **argv) exit(1); } + mem_size = get_mem_size(argv[optind]); + if (length == -1) - length = meminfo.size; + length = mem_size; if (offset % meminfo.erasesize) { - fprintf(stderr, "Offset %x not multiple of erase size %x\n", + fprintf(stderr, "Offset %" PRIx64 + " not multiple of erase size %x\n", offset, meminfo.erasesize); exit(1); } if (length % meminfo.erasesize) { - fprintf(stderr, "Length %x not multiple of erase size %x\n", + fprintf(stderr, "Length %" PRIx64 + " not multiple of erase size %x\n", length, meminfo.erasesize); exit(1); } - if (length + offset > meminfo.size) { - fprintf(stderr, "Length %x + offset %x exceeds device size %x\n", - length, offset, meminfo.size); + if (length + offset > mem_size) { + fprintf(stderr, "Length %" PRIx64 " + offset %" PRIx64 + " exceeds device size %" PRIx64 "\n", + length, offset, mem_size); exit(1); } 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; diff --git a/nand-utils/nandwrite.c b/nand-utils/nandwrite.c index e8a210c..cd53a17 100644 --- a/nand-utils/nandwrite.c +++ b/nand-utils/nandwrite.c @@ -280,6 +280,7 @@ int main(int argc, char * const argv[]) libmtd_t mtd_desc; int ebsize_aligned; uint8_t write_mode; + size_t all_ffs_cnt = 0; process_options(argc, argv); @@ -417,6 +418,8 @@ int main(int argc, char * const argv[]) */ while ((imglen > 0 || writebuf < filebuf + filebuf_len) && mtdoffset < mtd.size) { + bool allffs; + /* * New eraseblock, check for bad block(s) * Stay in the loop to be sure that, if mtdoffset changes because @@ -555,7 +558,8 @@ int main(int argc, char * const argv[]) } ret = 0; - if (!skipallffs || !buffer_check_pattern(writebuf, mtd.min_io_size, 0xff)) { + allffs = buffer_check_pattern(writebuf, mtd.min_io_size, 0xff); + if (!allffs || !skipallffs) { /* Write out data */ ret = mtd_write(mtd_desc, &mtd, fd, mtdoffset / mtd.eb_size, mtdoffset % mtd.eb_size, @@ -564,6 +568,8 @@ int main(int argc, char * const argv[]) writeoob ? oobbuf : NULL, writeoob ? mtd.oob_size : 0, write_mode); + if (!ret && allffs) + all_ffs_cnt++; } if (ret) { @@ -615,6 +621,11 @@ closeall: || (writebuf < filebuf + filebuf_len)) sys_errmsg_die("Data was only partially written due to error"); + if (all_ffs_cnt) { + fprintf(stderr, "Written %zu blocks containing only 0xff bytes\n", all_ffs_cnt); + fprintf(stderr, "Those block may be incorrectly treated as empty!\n"); + } + /* Return happy */ return EXIT_SUCCESS; } |