From 89aaa5dc801c05e1d11141fa7d0789b072bde655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 14 Dec 2010 20:24:10 +0100 Subject: [PATCH] flash_erase: wip to add NOR skip erased block option --- flash_erase.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 52 insertions(+), 1 deletions(-) diff --git a/flash_erase.c b/flash_erase.c index 1a7b52e..1000397 100644 --- a/flash_erase.c +++ b/flash_erase.c @@ -46,6 +46,7 @@ static int quiet; /* true -- don't output progress */ static int jffs2; /* format for jffs2 usage */ static int noskipbad; /* do not skip bad blocks */ static int unlock; /* unlock sectors before erasing */ +static int skip_erased; /* Skip erased NOR flash blocks, including cleanmarker check */ static struct jffs2_unknown_node cleanmarker; int target_endian = __BYTE_ORDER; @@ -68,6 +69,7 @@ static void display_help (void) " -N, --noskipbad don't skip bad blocks\n" " -u, --unlock unlock sectors before erasing\n" " -q, --quiet display progress messages\n" + " -s, --skip-erased skip erased NOR sectors\n" " --silent same as --quiet\n" " --help display this help and exit\n" " --version output version information and exit\n", @@ -104,7 +106,7 @@ int main(int argc, char *argv[]) */ for (;;) { int option_index = 0; - static const char *short_options = "jNqu"; + static const char *short_options = "sjNqu"; static const struct option long_options[] = { {"help", no_argument, 0, 0}, {"version", no_argument, 0, 0}, @@ -113,6 +115,7 @@ int main(int argc, char *argv[]) {"quiet", no_argument, 0, 'q'}, {"silent", no_argument, 0, 'q'}, {"unlock", no_argument, 0, 'u'}, + {"skip-erased", no_argument, 0, 's'}, {0, 0, 0, 0}, }; @@ -145,6 +148,9 @@ int main(int argc, char *argv[]) case 'u': unlock = 1; break; + case 's': + skip_erased = 1; + break; case '?': error = 1; break; @@ -250,8 +256,53 @@ int main(int argc, char *argv[]) } } + /* Can we skip this one if it is already erased? + * Perhaps NAND performance could be improved by adding support for + * those cleanmarkers as well? + * + * Currently this only works with JFFS2 NOR clean markers + */ + int skip = 0; + if (skip_erased && !isNAND) { + uint8_t *tmp = malloc(mtd.eb_size); + if (tmp == NULL) { + return errmsg("Out of memory"); + } + ssize_t actual = pread(fd, tmp, mtd.eb_size, offset); + if (actual != mtd.eb_size) { + return errmsg("%s: MTD read failure: %s", mtd_device, strerror(errno)); + } + ssize_t i = 0; + int ok = 1; + + if (jffs2) { + ok = memcmp(tmp, &cleanmarker, sizeof (cleanmarker)) == 0; + i = sizeof (cleanmarker); + } + + if (ok) + { + for (; i < mtd.eb_size; i++) + { + if (tmp[i] != 0xff) + break; + } + if (i == mtd.eb_size) + { + /* Yup! we can skip! Here we could improve things by + * adding support for NAND cleanmarkers + */ + skip = 1; + } + } + free(tmp); + } + show_progress(&mtd, offset, eb, eb_start, eb_cnt); + if (skip) + continue; + if (unlock) { if (mtd_unlock(&mtd, fd, eb) != 0) { sys_errmsg("%s: MTD unlock failure", mtd_device); -- 1.7.0.4