mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-29 16:03:47 +02:00
Add support for selecting the erased bit value with a flag
Most flash chips are erased to ones and programmed to zeros. However, some other chips, such as the ENE KB9012 internal flash, work the opposite way. Change-Id: Ia7b0de8568e31f9bf263ba0ad6b051e837477b6b Signed-off-by: Mike Banon <mikebdp2@gmail.com> Signed-off-by: Paul Kocialkowski <contact@paulk.fr> Reviewed-on: https://review.coreboot.org/23258 Reviewed-by: Nico Huber <nico.h@gmx.de> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
31b5e3bfe6
commit
995f755ff5
9
flash.h
9
flash.h
@ -130,6 +130,13 @@ enum write_granularity {
|
|||||||
#define FEATURE_4BA_NATIVE (FEATURE_4BA_READ | FEATURE_4BA_FAST_READ | FEATURE_4BA_WRITE)
|
#define FEATURE_4BA_NATIVE (FEATURE_4BA_READ | FEATURE_4BA_FAST_READ | FEATURE_4BA_WRITE)
|
||||||
#define FEATURE_4BA (FEATURE_4BA_ENTER | FEATURE_4BA_EXT_ADDR | FEATURE_4BA_NATIVE)
|
#define FEATURE_4BA (FEATURE_4BA_ENTER | FEATURE_4BA_EXT_ADDR | FEATURE_4BA_NATIVE)
|
||||||
#define FEATURE_4BA_WREN (FEATURE_4BA_ENTER_WREN | FEATURE_4BA_EXT_ADDR | FEATURE_4BA_NATIVE)
|
#define FEATURE_4BA_WREN (FEATURE_4BA_ENTER_WREN | FEATURE_4BA_EXT_ADDR | FEATURE_4BA_NATIVE)
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#define FEATURE_ERASED_ZERO (1 << 16)
|
||||||
|
|
||||||
|
#define ERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff)
|
||||||
|
|
||||||
enum test_state {
|
enum test_state {
|
||||||
OK = 0,
|
OK = 0,
|
||||||
@ -309,7 +316,7 @@ int probe_flash(struct registered_master *mst, int startchip, struct flashctx *f
|
|||||||
int read_flash_to_file(struct flashctx *flash, const char *filename);
|
int read_flash_to_file(struct flashctx *flash, const char *filename);
|
||||||
char *extract_param(const char *const *haystack, const char *needle, const char *delim);
|
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 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_version(void);
|
||||||
void print_buildinfo(void);
|
void print_buildinfo(void);
|
||||||
void print_banner(void);
|
void print_banner(void);
|
||||||
|
32
flashrom.c
32
flashrom.c
@ -700,12 +700,13 @@ int check_erased_range(struct flashctx *flash, unsigned int start,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t *cmpbuf = malloc(len);
|
uint8_t *cmpbuf = malloc(len);
|
||||||
|
const uint8_t erased_value = ERASED_VALUE(flash);
|
||||||
|
|
||||||
if (!cmpbuf) {
|
if (!cmpbuf) {
|
||||||
msg_gerr("Could not allocate memory!\n");
|
msg_gerr("Could not allocate memory!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memset(cmpbuf, 0xff, len);
|
memset(cmpbuf, erased_value, len);
|
||||||
ret = verify_range(flash, cmpbuf, start, len);
|
ret = verify_range(flash, cmpbuf, start, len);
|
||||||
free(cmpbuf);
|
free(cmpbuf);
|
||||||
return ret;
|
return ret;
|
||||||
@ -758,7 +759,8 @@ out_free:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function for need_erase() that focuses on granularities of gran bytes. */
|
/* 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;
|
unsigned int i, j, limit;
|
||||||
for (j = 0; j < len / gran; j++) {
|
for (j = 0; j < len / gran; j++) {
|
||||||
@ -768,7 +770,7 @@ static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsig
|
|||||||
continue;
|
continue;
|
||||||
/* have needs to be in erased state. */
|
/* have needs to be in erased state. */
|
||||||
for (i = 0; i < limit; i++)
|
for (i = 0; i < limit; i++)
|
||||||
if (have[j * gran + i] != 0xff)
|
if (have[j * gran + i] != erased_value)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -788,7 +790,8 @@ static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsig
|
|||||||
* @gran write granularity (enum, not count)
|
* @gran write granularity (enum, not count)
|
||||||
* @return 0 if no erase is needed, 1 otherwise
|
* @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;
|
int result = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -803,31 +806,31 @@ int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum
|
|||||||
break;
|
break;
|
||||||
case write_gran_1byte:
|
case write_gran_1byte:
|
||||||
for (i = 0; i < len; i++)
|
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;
|
result = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case write_gran_128bytes:
|
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;
|
break;
|
||||||
case write_gran_256bytes:
|
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;
|
break;
|
||||||
case write_gran_264bytes:
|
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;
|
break;
|
||||||
case write_gran_512bytes:
|
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;
|
break;
|
||||||
case write_gran_528bytes:
|
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;
|
break;
|
||||||
case write_gran_1024bytes:
|
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;
|
break;
|
||||||
case write_gran_1056bytes:
|
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;
|
break;
|
||||||
case write_gran_1byte_implicit_erase:
|
case write_gran_1byte_implicit_erase:
|
||||||
/* Do not erase, handle content changes from anything->0xff by writing 0xff. */
|
/* Do not erase, handle content changes from anything->0xff by writing 0xff. */
|
||||||
@ -1772,11 +1775,12 @@ static int read_erase_write_block(struct flashctx *const flashctx,
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
bool skipped = true;
|
bool skipped = true;
|
||||||
uint8_t *const curcontents = info->curcontents + info->erase_start;
|
uint8_t *const curcontents = info->curcontents + info->erase_start;
|
||||||
if (need_erase(curcontents, newcontents, erase_len, flashctx->chip->gran)) {
|
const uint8_t erased_value = ERASED_VALUE(flashctx);
|
||||||
|
if (need_erase(curcontents, newcontents, erase_len, flashctx->chip->gran, erased_value)) {
|
||||||
if (erase_block(flashctx, info, erasefn))
|
if (erase_block(flashctx, info, erasefn))
|
||||||
goto _free_ret;
|
goto _free_ret;
|
||||||
/* Erase was successful. Adjust curcontents. */
|
/* Erase was successful. Adjust curcontents. */
|
||||||
memset(curcontents, 0xff, erase_len);
|
memset(curcontents, erased_value, erase_len);
|
||||||
skipped = false;
|
skipped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user