[flashrom] [PATCH 2/3] Flag-driven erased bit value

Paul Kocialkowski contact at paulk.fr
Sat Oct 10 16:20:20 CEST 2015


Most flash chips are erased to ones and programmed to zeros. However, some other
flash chips, such as the ENE KB9012 internal flash, work the opposite way.

Signed-off-by: Paul Kocialkowski <contact at paulk.fr>
---
 flash.h    |  3 ++-
 flashrom.c | 42 ++++++++++++++++++++++--------------------
 2 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/flash.h b/flash.h
index 24861ba..3d14d56 100644
--- a/flash.h
+++ b/flash.h
@@ -123,6 +123,7 @@ enum write_granularity {
 #define FEATURE_WRSR_EITHER	(FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN)
 #define FEATURE_OTP		(1 << 8)
 #define FEATURE_QPI		(1 << 9)
+#define FEATURE_ERASED_ZERO	(1 << 10)
 
 enum test_state {
 	OK = 0,
@@ -275,7 +276,7 @@ int probe_flash(struct registered_master *mst, int startchip, struct flashctx *f
 int read_flash_to_file(struct flashctx *flash, const char *filename);
 char *extract_param(const char *const *haystack, const char *needle, const char *delim);
 int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int start, unsigned int len);
-int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum write_granularity gran);
+int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum write_granularity gran, uint8_t erased);
 void print_version(void);
 void print_buildinfo(void);
 void print_banner(void);
diff --git a/flashrom.c b/flashrom.c
index c9c7e31..e463a18 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -669,7 +669,7 @@ static int compare_range(const uint8_t *wantbuf, const uint8_t *havebuf, unsigne
 
 /* start is an offset to the base address of the flash chip */
 int check_erased_range(struct flashctx *flash, unsigned int start,
-		       unsigned int len)
+		       unsigned int len, uint8_t erased)
 {
 	int ret;
 	uint8_t *cmpbuf = malloc(len);
@@ -678,7 +678,7 @@ int check_erased_range(struct flashctx *flash, unsigned int start,
 		msg_gerr("Could not allocate memory!\n");
 		exit(1);
 	}
-	memset(cmpbuf, 0xff, len);
+	memset(cmpbuf, erased, len);
 	ret = verify_range(flash, cmpbuf, start, len);
 	free(cmpbuf);
 	return ret;
@@ -731,7 +731,7 @@ out_free:
 }
 
 /* Helper function for need_erase() that focuses on granularities of gran bytes. */
-static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsigned int len, unsigned int gran)
+static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsigned int len, unsigned int gran, uint8_t erased)
 {
 	unsigned int i, j, limit;
 	for (j = 0; j < len / gran; j++) {
@@ -741,7 +741,7 @@ static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsig
 			continue;
 		/* have needs to be in erased state. */
 		for (i = 0; i < limit; i++)
-			if (have[j * gran + i] != 0xff)
+			if (have[j * gran + i] != erased)
 				return 1;
 	}
 	return 0;
@@ -761,7 +761,7 @@ static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsig
  * @gran	write granularity (enum, not count)
  * @return      0 if no erase is needed, 1 otherwise
  */
-int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum write_granularity gran)
+int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum write_granularity gran, uint8_t erased)
 {
 	int result = 0;
 	unsigned int i;
@@ -776,31 +776,31 @@ int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum
 		break;
 	case write_gran_1byte:
 		for (i = 0; i < len; i++)
-			if ((have[i] != want[i]) && (have[i] != 0xff)) {
+			if ((have[i] != want[i]) && (have[i] != erased)) {
 				result = 1;
 				break;
 			}
 		break;
 	case write_gran_128bytes:
-		result = need_erase_gran_bytes(have, want, len, 128);
+		result = need_erase_gran_bytes(have, want, len, 128, erased);
 		break;
 	case write_gran_256bytes:
-		result = need_erase_gran_bytes(have, want, len, 256);
+		result = need_erase_gran_bytes(have, want, len, 256, erased);
 		break;
 	case write_gran_264bytes:
-		result = need_erase_gran_bytes(have, want, len, 264);
+		result = need_erase_gran_bytes(have, want, len, 264, erased);
 		break;
 	case write_gran_512bytes:
-		result = need_erase_gran_bytes(have, want, len, 512);
+		result = need_erase_gran_bytes(have, want, len, 512, erased);
 		break;
 	case write_gran_528bytes:
-		result = need_erase_gran_bytes(have, want, len, 528);
+		result = need_erase_gran_bytes(have, want, len, 528, erased);
 		break;
 	case write_gran_1024bytes:
-		result = need_erase_gran_bytes(have, want, len, 1024);
+		result = need_erase_gran_bytes(have, want, len, 1024, erased);
 		break;
 	case write_gran_1056bytes:
-		result = need_erase_gran_bytes(have, want, len, 1056);
+		result = need_erase_gran_bytes(have, want, len, 1056, erased);
 		break;
 	case write_gran_1byte_implicit_erase:
 		/* Do not erase, handle content changes from anything->0xff by writing 0xff. */
@@ -1424,6 +1424,7 @@ static int erase_and_write_block_helper(struct flashctx *flash,
 	unsigned int starthere = 0, lenhere = 0;
 	int ret = 0, skip = 1, writecount = 0;
 	enum write_granularity gran = flash->chip->gran;
+	uint8_t erased = (flash->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff;
 
 	/* curcontents and newcontents are opaque to walk_eraseregions, and
 	 * need to be adjusted here to keep the impression of proper abstraction
@@ -1431,17 +1432,17 @@ static int erase_and_write_block_helper(struct flashctx *flash,
 	curcontents += start;
 	newcontents += start;
 	msg_cdbg(":");
-	if (need_erase(curcontents, newcontents, len, gran)) {
+	if (need_erase(curcontents, newcontents, len, gran, erased)) {
 		msg_cdbg("E");
 		ret = erasefn(flash, start, len);
 		if (ret)
 			return ret;
-		if (check_erased_range(flash, start, len)) {
+		if (check_erased_range(flash, start, len, erased)) {
 			msg_cerr("ERASE FAILED!\n");
 			return -1;
 		}
 		/* Erase was successful. Adjust curcontents. */
-		memset(curcontents, 0xff, len);
+		memset(curcontents, erased, len);
 		skip = 0;
 	}
 	/* get_next_write() sets starthere to a new value after the call. */
@@ -1938,6 +1939,7 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 	int ret = 0;
 	unsigned long size = flash->chip->total_size * 1024;
 	int read_all_first = 1; /* FIXME: Make this configurable. */
+	uint8_t erased = (flash->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff;
 
 	if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) {
 		msg_cerr("Aborting.\n");
@@ -1964,15 +1966,15 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 		msg_gerr("Out of memory!\n");
 		exit(1);
 	}
-	/* Assume worst case: All bits are 0. */
-	memset(oldcontents, 0x00, size);
+	/* Assume worst case: All bits are not erased. */
+	memset(oldcontents, ~erased, size);
 	newcontents = malloc(size);
 	if (!newcontents) {
 		msg_gerr("Out of memory!\n");
 		exit(1);
 	}
-	/* Assume best case: All bits should be 1. */
-	memset(newcontents, 0xff, size);
+	/* Assume best case: All bits should be erased. */
+	memset(newcontents, erased, size);
 	/* Side effect of the assumptions above: Default write action is erase
 	 * because newcontents looks like a completely erased chip, and
 	 * oldcontents being completely 0x00 means we have to erase everything
-- 
1.9.1





More information about the flashrom mailing list