diff options
-rw-r--r-- | flash.h | 25 | ||||
-rw-r--r-- | flashchips.c | 46 | ||||
-rw-r--r-- | flashrom.c | 80 | ||||
-rw-r--r-- | ft2232_spi.c | 2 | ||||
-rw-r--r-- | it87spi.c | 2 | ||||
-rw-r--r-- | sb600spi.c | 2 | ||||
-rw-r--r-- | spi.c | 4 | ||||
-rw-r--r-- | w39v040c.c | 2 |
8 files changed, 130 insertions, 33 deletions
@@ -149,6 +149,17 @@ enum chipbustype { CHIP_BUSTYPE_UNKNOWN = CHIP_BUSTYPE_PARALLEL | CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI, }; +/* + * How many different contiguous runs of erase blocks with one size each do + * we have for a given erase function? + */ +#define NUM_ERASEREGIONS 5 + +/* + * How many different erase functions do we have per chip? + */ +#define NUM_ERASEFUNCTIONS 5 + struct flashchip { const char *vendor; const char *name; @@ -177,6 +188,19 @@ struct flashchip { /* Delay after "enter/exit ID mode" commands in microseconds. */ int probe_timing; int (*erase) (struct flashchip *flash); + + /* + * Erase blocks and associated erase function. The default entry is a + * chip-sized virtual block together with the chip erase function. + */ + struct block_eraser { + struct eraseblock{ + unsigned int size; /* Eraseblock size */ + unsigned int count; /* Number of contiguous blocks with that size */ + } eraseblocks[NUM_ERASEREGIONS]; + int (*block_erase) (struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen); + } block_erasers[NUM_ERASEFUNCTIONS]; + int (*write) (struct flashchip *flash, uint8_t *buf); int (*read) (struct flashchip *flash, uint8_t *buf, int start, int len); @@ -417,6 +441,7 @@ extern const char *flashrom_version; #define printf_debug(x...) { if (verbose) printf(x); } void map_flash_registers(struct flashchip *flash); int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len); +int erase_flash(struct flashchip *flash); int min(int a, int b); int max(int a, int b); int check_erased_range(struct flashchip *flash, int start, int len); diff --git a/flashchips.c b/flashchips.c index 3b72cdfb..33ebd042 100644 --- a/flashchips.c +++ b/flashchips.c @@ -1229,7 +1229,30 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, + .erase = NULL, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 16} }, + .block_erase = spi_block_erase_20, + }, + { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = spi_block_erase_52, + }, + { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = spi_block_erase_d8, + }, + { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = spi_block_erase_60, + }, + { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = spi_block_erase_c7, + }, + }, .write = spi_chip_write_256, .read = spi_chip_read, }, @@ -1245,7 +1268,26 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, + .erase = NULL, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 32} }, + .block_erase = spi_block_erase_20, + }, + { + .eraseblocks = { {64 * 1024, 2} }, + .block_erase = spi_block_erase_d8, + }, + { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = spi_block_erase_60, + }, + { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = spi_block_erase_c7, + }, + }, .write = spi_chip_write_256, .read = spi_chip_read, }, @@ -474,36 +474,66 @@ int read_flash(struct flashchip *flash, char *filename) int erase_flash(struct flashchip *flash) { - uint32_t erasedbytes; - unsigned long size = flash->total_size * 1024; - unsigned char *buf = calloc(size, sizeof(char)); + int i, j, k, ret = 0, found = 0; + printf("Erasing flash chip... "); - if (NULL == flash->erase) { - printf("FAILED!\n"); + for (k = 0; k < NUM_ERASEFUNCTIONS; k++) { + unsigned long done = 0; + struct block_eraser eraser = flash->block_erasers[k]; + + printf_debug("Looking at blockwise erase function %i... ", k); + if (!eraser.block_erase && !eraser.eraseblocks[0].count) { + printf_debug("not defined. " + "Looking for another erase function.\n"); + continue; + } + if (!eraser.block_erase && eraser.eraseblocks[0].count) { + printf_debug("eraseblock layout is known, but no " + "matching block erase function found. " + "Looking for another erase function.\n"); + continue; + } + if (eraser.block_erase && !eraser.eraseblocks[0].count) { + printf_debug("block erase function found, but " + "eraseblock layout is unknown. " + "Looking for another erase function.\n"); + continue; + } + found = 1; + printf_debug("trying... "); + for (i = 0; i < NUM_ERASEREGIONS; i++) { + /* count==0 for all automatically initialized array + * members so the loop below won't be executed for them. + */ + for (j = 0; j < eraser.eraseblocks[i].count; j++) { + ret = eraser.block_erase(flash, done + eraser.eraseblocks[i].size * j, eraser.eraseblocks[i].size); + if (ret) + break; + } + if (ret) + break; + } + /* If everything is OK, don't try another erase function. */ + if (!ret) + break; + } + /* If no block erase function was found or block erase failed, retry. */ + if ((!found || ret) && (flash->erase)) { + found = 1; + printf_debug("Trying whole-chip erase function... "); + ret = flash->erase(flash); + } + if (!found) { fprintf(stderr, "ERROR: flashrom has no erase function for this flash chip.\n"); return 1; } - flash->erase(flash); - /* FIXME: The lines below are superfluous. We should check the result - * of flash->erase(flash) instead. - */ - if (!flash->read) { - printf("FAILED!\n"); - fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n"); - return 1; - } else - flash->read(flash, buf, 0, size); - - for (erasedbytes = 0; erasedbytes < size; erasedbytes++) - if (0xff != buf[erasedbytes]) { - printf("FAILED!\n"); - fprintf(stderr, "ERROR at 0x%08x: Expected=0xff, Read=0x%02x\n", - erasedbytes, buf[erasedbytes]); - return 1; - } - printf("SUCCESS.\n"); - return 0; + if (ret) { + fprintf(stderr, "FAILED!\n"); + } else { + printf("SUCCESS.\n"); + } + return ret; } void emergency_help_message() diff --git a/ft2232_spi.c b/ft2232_spi.c index 9bf1af3c..ee8d67dc 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c @@ -271,7 +271,7 @@ int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf) spi_disable_blockprotect(); /* Erase first */ printf("Erasing flash before programming... "); - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } @@ -279,7 +279,7 @@ int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf) spi_disable_blockprotect(); /* Erase first */ printf("Erasing flash before programming... "); - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } @@ -55,7 +55,7 @@ int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf) spi_disable_blockprotect(); /* Erase first */ printf("Erasing flash before programming... "); - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } @@ -972,7 +972,7 @@ int spi_chip_write_1(struct flashchip *flash, uint8_t *buf) spi_disable_blockprotect(); /* Erase first */ printf("Erasing flash before programming... "); - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } @@ -1021,7 +1021,7 @@ int spi_aai_write(struct flashchip *flash, uint8_t *buf) default: break; } - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } @@ -72,7 +72,7 @@ int write_w39v040c(struct flashchip *flash, uint8_t *buf) int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } |