Blockwise erase infrastructure, 6th try. The description is pretty long and has not changed since last time. I can repost it if desired.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-eraseblocks/flash.h =================================================================== --- flashrom-eraseblocks/flash.h (Revision 664) +++ flashrom-eraseblocks/flash.h (Arbeitskopie) @@ -140,6 +140,17 @@ 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; @@ -168,6 +179,19 @@ /* 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);
@@ -383,6 +407,7 @@ #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); Index: flashrom-eraseblocks/flashchips.c =================================================================== --- flashrom-eraseblocks/flashchips.c (Revision 664) +++ flashrom-eraseblocks/flashchips.c (Arbeitskopie) @@ -1220,7 +1220,30 @@ .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, }, @@ -1236,7 +1259,26 @@ .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, }, Index: flashrom-eraseblocks/spi.c =================================================================== --- flashrom-eraseblocks/spi.c (Revision 664) +++ flashrom-eraseblocks/spi.c (Arbeitskopie) @@ -1006,7 +1006,7 @@ default: break; } - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } Index: flashrom-eraseblocks/wbsio_spi.c =================================================================== --- flashrom-eraseblocks/wbsio_spi.c (Revision 664) +++ flashrom-eraseblocks/wbsio_spi.c (Arbeitskopie) @@ -197,7 +197,7 @@ return 1; }
- if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } Index: flashrom-eraseblocks/w39v040c.c =================================================================== --- flashrom-eraseblocks/w39v040c.c (Revision 664) +++ flashrom-eraseblocks/w39v040c.c (Arbeitskopie) @@ -78,7 +78,7 @@ 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; } Index: flashrom-eraseblocks/sb600spi.c =================================================================== --- flashrom-eraseblocks/sb600spi.c (Revision 664) +++ flashrom-eraseblocks/sb600spi.c (Arbeitskopie) @@ -54,7 +54,7 @@
/* Erase first */ printf("Erasing flash before programming... "); - if (flash->erase(flash)) { + if (erase_flash(flash)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } Index: flashrom-eraseblocks/flashrom.c =================================================================== --- flashrom-eraseblocks/flashrom.c (Revision 664) +++ flashrom-eraseblocks/flashrom.c (Arbeitskopie) @@ -443,36 +443,66 @@
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 usage(const char *name)