[flashrom] [PATCH v3 1/2] Add support for selecting the erased bit value with a flag
Nico Huber
nico.h at gmx.de
Wed Nov 11 21:25:45 CET 2015
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 at paulk.fr>
Acked-by: Nico Huber <nico.h at 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
>
More information about the flashrom
mailing list