Submitter | Paul Kocialkowski |
---|---|
Date | 2015-11-11 15:55:49 |
Message ID | <1447257350-17048-1-git-send-email-contact@paulk.fr> |
Download | mbox | patch |
Permalink | /patch/4334/ |
State | New |
Headers | show |
Comments
On 11.11.2015 16:55, Paul Kocialkowski wrote: > 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@paulk.fr> Acked-by: Nico Huber <nico.h@gmx.de> > --- > flash.h | 5 ++++- > flashrom.c | 39 +++++++++++++++++++++------------------ > 2 files changed, 25 insertions(+), 19 deletions(-) > > diff --git a/flash.h b/flash.h > index 24861ba..8d557fe 100644 > --- a/flash.h > +++ b/flash.h > @@ -123,6 +123,9 @@ 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) > + > +#define ERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff) > > enum test_state { > OK = 0, > @@ -275,7 +278,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, const uint8_t erased_value); > void print_version(void); > void print_buildinfo(void); > void print_banner(void); > diff --git a/flashrom.c b/flashrom.c > index c9c7e31..bd8ef3f 100644 > --- a/flashrom.c > +++ b/flashrom.c > @@ -673,12 +673,13 @@ int check_erased_range(struct flashctx *flash, unsigned int start, > { > int ret; > uint8_t *cmpbuf = malloc(len); > + const uint8_t erased_value = ERASED_VALUE(flash); > > if (!cmpbuf) { > msg_gerr("Could not allocate memory!\n"); > exit(1); > } > - memset(cmpbuf, 0xff, len); > + memset(cmpbuf, erased_value, len); > ret = verify_range(flash, cmpbuf, start, len); > free(cmpbuf); > return ret; > @@ -731,7 +732,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, const uint8_t erased_value) > { > unsigned int i, j, limit; > for (j = 0; j < len / gran; j++) { > @@ -741,7 +742,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_value) > return 1; > } > return 0; > @@ -761,7 +762,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, const uint8_t erased_value) > { > int result = 0; > unsigned int i; > @@ -776,31 +777,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_value)) { > 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_value); > break; > case write_gran_256bytes: > - result = need_erase_gran_bytes(have, want, len, 256); > + result = need_erase_gran_bytes(have, want, len, 256, erased_value); > break; > case write_gran_264bytes: > - result = need_erase_gran_bytes(have, want, len, 264); > + result = need_erase_gran_bytes(have, want, len, 264, erased_value); > break; > case write_gran_512bytes: > - result = need_erase_gran_bytes(have, want, len, 512); > + result = need_erase_gran_bytes(have, want, len, 512, erased_value); > break; > case write_gran_528bytes: > - result = need_erase_gran_bytes(have, want, len, 528); > + result = need_erase_gran_bytes(have, want, len, 528, erased_value); > break; > case write_gran_1024bytes: > - result = need_erase_gran_bytes(have, want, len, 1024); > + result = need_erase_gran_bytes(have, want, len, 1024, erased_value); > break; > case write_gran_1056bytes: > - result = need_erase_gran_bytes(have, want, len, 1056); > + result = need_erase_gran_bytes(have, want, len, 1056, erased_value); > break; > case write_gran_1byte_implicit_erase: > /* Do not erase, handle content changes from anything->0xff by writing 0xff. */ > @@ -1424,6 +1425,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; > + const uint8_t erased_value = ERASED_VALUE(flash); > > /* curcontents and newcontents are opaque to walk_eraseregions, and > * need to be adjusted here to keep the impression of proper abstraction > @@ -1431,7 +1433,7 @@ 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_value)) { > msg_cdbg("E"); > ret = erasefn(flash, start, len); > if (ret) > @@ -1441,7 +1443,7 @@ static int erase_and_write_block_helper(struct flashctx *flash, > return -1; > } > /* Erase was successful. Adjust curcontents. */ > - memset(curcontents, 0xff, len); > + memset(curcontents, erased_value, len); > skip = 0; > } > /* get_next_write() sets starthere to a new value after the call. */ > @@ -1938,6 +1940,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. */ > + const uint8_t erased_value = ERASED_VALUE(flash); > > if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) { > msg_cerr("Aborting.\n"); > @@ -1964,15 +1967,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_value, 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_value, 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 >
Patch
diff --git a/flash.h b/flash.h index 24861ba..8d557fe 100644 --- a/flash.h +++ b/flash.h @@ -123,6 +123,9 @@ 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) + +#define ERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff) enum test_state { OK = 0, @@ -275,7 +278,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, const uint8_t erased_value); void print_version(void); void print_buildinfo(void); void print_banner(void); diff --git a/flashrom.c b/flashrom.c index c9c7e31..bd8ef3f 100644 --- a/flashrom.c +++ b/flashrom.c @@ -673,12 +673,13 @@ int check_erased_range(struct flashctx *flash, unsigned int start, { int ret; uint8_t *cmpbuf = malloc(len); + const uint8_t erased_value = ERASED_VALUE(flash); if (!cmpbuf) { msg_gerr("Could not allocate memory!\n"); exit(1); } - memset(cmpbuf, 0xff, len); + memset(cmpbuf, erased_value, len); ret = verify_range(flash, cmpbuf, start, len); free(cmpbuf); return ret; @@ -731,7 +732,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, const uint8_t erased_value) { unsigned int i, j, limit; for (j = 0; j < len / gran; j++) { @@ -741,7 +742,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_value) return 1; } return 0; @@ -761,7 +762,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, const uint8_t erased_value) { int result = 0; unsigned int i; @@ -776,31 +777,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_value)) { 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_value); break; case write_gran_256bytes: - result = need_erase_gran_bytes(have, want, len, 256); + result = need_erase_gran_bytes(have, want, len, 256, erased_value); break; case write_gran_264bytes: - result = need_erase_gran_bytes(have, want, len, 264); + result = need_erase_gran_bytes(have, want, len, 264, erased_value); break; case write_gran_512bytes: - result = need_erase_gran_bytes(have, want, len, 512); + result = need_erase_gran_bytes(have, want, len, 512, erased_value); break; case write_gran_528bytes: - result = need_erase_gran_bytes(have, want, len, 528); + result = need_erase_gran_bytes(have, want, len, 528, erased_value); break; case write_gran_1024bytes: - result = need_erase_gran_bytes(have, want, len, 1024); + result = need_erase_gran_bytes(have, want, len, 1024, erased_value); break; case write_gran_1056bytes: - result = need_erase_gran_bytes(have, want, len, 1056); + result = need_erase_gran_bytes(have, want, len, 1056, erased_value); break; case write_gran_1byte_implicit_erase: /* Do not erase, handle content changes from anything->0xff by writing 0xff. */ @@ -1424,6 +1425,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; + const uint8_t erased_value = ERASED_VALUE(flash); /* curcontents and newcontents are opaque to walk_eraseregions, and * need to be adjusted here to keep the impression of proper abstraction @@ -1431,7 +1433,7 @@ 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_value)) { msg_cdbg("E"); ret = erasefn(flash, start, len); if (ret) @@ -1441,7 +1443,7 @@ static int erase_and_write_block_helper(struct flashctx *flash, return -1; } /* Erase was successful. Adjust curcontents. */ - memset(curcontents, 0xff, len); + memset(curcontents, erased_value, len); skip = 0; } /* get_next_write() sets starthere to a new value after the call. */ @@ -1938,6 +1940,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. */ + const uint8_t erased_value = ERASED_VALUE(flash); if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) { msg_cerr("Aborting.\n"); @@ -1964,15 +1967,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_value, 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_value, 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
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@paulk.fr> --- flash.h | 5 ++++- flashrom.c | 39 +++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 19 deletions(-)