aboutsummaryrefslogtreecommitdiff
path: root/nand-utils
diff options
context:
space:
mode:
Diffstat (limited to 'nand-utils')
-rw-r--r--nand-utils/nanddump.c39
-rw-r--r--nand-utils/nandflipbits.c2
2 files changed, 30 insertions, 11 deletions
diff --git a/nand-utils/nanddump.c b/nand-utils/nanddump.c
index 47539f5..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 */
- long long 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 7066408..a417189 100644
--- a/nand-utils/nandflipbits.c
+++ b/nand-utils/nandflipbits.c
@@ -251,7 +251,7 @@ int main(int argc, char **argv)
bufoffs += mtd.min_io_size;
ret = mtd_read_oob(mtd_desc, &mtd, fd,
- bit_to_flip->block * mtd.eb_size +
+ (unsigned long long)bit_to_flip->block * mtd.eb_size +
blkoffs,
mtd.oob_size, buffer + bufoffs);
if (ret) {