From 89aaa5dc801c05e1d11141fa7d0789b072bde655 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=98yvind=20Harboe?= <oyvind.harboe@zylin.com>
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(-)
@@ -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