From 30f7cb2f3c570c99b61bd5df72621f44f1bdd0d0 Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Mon, 15 Jun 2009 17:23:36 +0000 Subject: Flashrom only checks for very few chips if the erase worked And even when it checks if the erase worked, the result of that check is often ignored. Convert all erase functions and actually check return codes almost everywhere. Check inside all erase_* routines if erase worked, not outside. erase_sector_jedec and erase_block_jedec have changed prototypes to enable erase checking. Uwe successfully tested LPC on an CK804 box and SPI on some SB600 box. Corresponding to flashrom svn r595. Signed-off-by: Carl-Daniel Hailfinger Signed-off-by: Urja Rannikko Acked-by: Uwe Hermann --- 82802ab.c | 19 +++++++------ am29f040b.c | 19 +++++++++++-- en29f002a.c | 5 +++- flash.h | 10 ++++--- flashrom.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jedec.c | 33 +++++++++++++++------- m29f002.c | 46 +++++++++++++++++++----------- m29f400bt.c | 57 ++++++++++++++++++++++++++++++------- mx29f002.c | 9 +++++- pm29f002.c | 5 +++- pm49fl00x.c | 11 ++++++-- sb600spi.c | 5 +++- sharplhf00l04.c | 14 ++++++--- sst28sf040.c | 17 +++++++++-- sst49lf040.c | 11 ++++++-- sst49lfxxxc.c | 14 +++++++-- sst_fwhub.c | 22 +++++++-------- stm50flw0x0x.c | 27 +++++++++--------- w39v040c.c | 15 +++++----- w39v080fa.c | 21 +++++++------- w49f002u.c | 5 +++- wbsio_spi.c | 5 +++- 22 files changed, 345 insertions(+), 113 deletions(-) diff --git a/82802ab.c b/82802ab.c index 1dc997f..28fa177 100644 --- a/82802ab.c +++ b/82802ab.c @@ -110,7 +110,6 @@ int erase_82802ab_block(struct flashchip *flash, int offset) { chipaddr bios = flash->virtual_memory + offset; chipaddr wrprotect = flash->virtual_registers + offset + 2; - int j; uint8_t status; // clear status register @@ -129,11 +128,9 @@ int erase_82802ab_block(struct flashchip *flash, int offset) // now let's see what the register is status = wait_82802ab(flash->virtual_memory); //print_82802ab_status(status); - for (j = 0; j < flash->page_size; j++) { - if (chip_readb(bios + j) != 0xFF) { - printf("BLOCK ERASE failed at 0x%x\n", offset); - return -1; - } + if (check_erased_range(flash, offset, flash->page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; } printf("DONE BLOCK 0x%x\n", offset); @@ -148,7 +145,10 @@ int erase_82802ab(struct flashchip *flash) printf("total_size is %d; flash->page_size is %d\n", total_size, flash->page_size); for (i = 0; i < total_size; i += flash->page_size) - erase_82802ab_block(flash, i); + if (erase_82802ab_block(flash, i)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } printf("DONE ERASE\n"); return 0; @@ -199,7 +199,10 @@ int write_82802ab(struct flashchip *flash, uint8_t *buf) } /* erase block by block and write block by block; this is the most secure way */ - erase_82802ab_block(flash, i * page_size); + if (erase_82802ab_block(flash, i * page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_82802ab(bios, buf + i * page_size, bios + i * page_size, page_size); } diff --git a/am29f040b.c b/am29f040b.c index 2dc4c36..7f1269c 100644 --- a/am29f040b.c +++ b/am29f040b.c @@ -20,8 +20,11 @@ #include "flash.h" -static int erase_sector_29f040b(chipaddr bios, unsigned long address) +static int erase_sector_29f040b(struct flashchip *flash, unsigned long address) { + int page_size = flash->page_size; + chipaddr bios = flash->virtual_memory; + chip_writeb(0xAA, bios + 0x555); chip_writeb(0x55, bios + 0x2AA); chip_writeb(0x80, bios + 0x555); @@ -34,6 +37,10 @@ static int erase_sector_29f040b(chipaddr bios, unsigned long address) /* wait for Toggle bit ready */ toggle_ready_jedec(bios + address); + if (check_erased_range(flash, address, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -86,6 +93,7 @@ int probe_29f040b(struct flashchip *flash) int erase_29f040b(struct flashchip *flash) { + int total_size = flash->total_size * 1024; chipaddr bios = flash->virtual_memory; chip_writeb(0xAA, bios + 0x555); @@ -98,6 +106,10 @@ int erase_29f040b(struct flashchip *flash) programmer_delay(10); toggle_ready_jedec(bios); + if (check_erased_range(flash, 0, total_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -111,7 +123,10 @@ int write_29f040b(struct flashchip *flash, uint8_t *buf) printf("Programming page "); for (i = 0; i < total_size / page_size; i++) { /* erase the page before programming */ - erase_sector_29f040b(bios, i * page_size); + if (erase_sector_29f040b(flash, i * page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } /* write to the sector */ printf("%04d at address: ", i); diff --git a/en29f002a.c b/en29f002a.c index f4242f5..b89eb31 100644 --- a/en29f002a.c +++ b/en29f002a.c @@ -98,7 +98,10 @@ int write_en29f002a(struct flashchip *flash, uint8_t *buf) //chip_writeb(0xF0, bios); programmer_delay(10); - erase_chip_jedec(flash); + if (erase_chip_jedec(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } printf("Programming page: "); for (i = 0; i < total_size; i++) { diff --git a/flash.h b/flash.h index 25ec836..97e0778 100644 --- a/flash.h +++ b/flash.h @@ -364,6 +364,9 @@ extern int verbose; void map_flash_registers(struct flashchip *flash); int read_memmapped(struct flashchip *flash, uint8_t *buf); int min(int a, int b); +int max(int a, int b); +int check_erased_range(struct flashchip *flash, int start, int len); +int verify_range(struct flashchip *flash, uint8_t *cmpbuf, int start, int len, char *message); extern char *pcidev_bdf; /* layout.c */ @@ -471,8 +474,8 @@ int write_byte_program_jedec(chipaddr bios, uint8_t *src, int probe_jedec(struct flashchip *flash); int erase_chip_jedec(struct flashchip *flash); int write_jedec(struct flashchip *flash, uint8_t *buf); -int erase_sector_jedec(chipaddr bios, unsigned int page); -int erase_block_jedec(chipaddr bios, unsigned int page); +int erase_sector_jedec(struct flashchip *flash, unsigned int page, int pagesize); +int erase_block_jedec(struct flashchip *flash, unsigned int page, int blocksize); int write_sector_jedec(chipaddr bios, uint8_t *src, chipaddr dst, unsigned int page_size); @@ -484,8 +487,7 @@ int write_m29f002b(struct flashchip *flash, uint8_t *buf); /* m29f400bt.c */ int probe_m29f400bt(struct flashchip *flash); int erase_m29f400bt(struct flashchip *flash); -int block_erase_m29f400bt(chipaddr bios, - chipaddr dst); +int block_erase_m29f400bt(struct flashchip *flash, int start, int len); int write_m29f400bt(struct flashchip *flash, uint8_t *buf); int write_coreboot_m29f400bt(struct flashchip *flash, uint8_t *buf); void toggle_ready_m29f400bt(chipaddr dst); diff --git a/flashrom.c b/flashrom.c index bb2c160..fe5826f 100644 --- a/flashrom.c +++ b/flashrom.c @@ -206,6 +206,11 @@ int min(int a, int b) return (a < b) ? a : b; } +int max(int a, int b) +{ + return (a > b) ? a : b; +} + char *strcat_realloc(char *dest, const char *src) { dest = realloc(dest, strlen(dest) + strlen(src) + 1); @@ -246,6 +251,86 @@ char *flashbuses_to_text(enum chipbustype bustype) return ret; } +/* start is an offset to the base address of the flash chip */ +int check_erased_range(struct flashchip *flash, int start, int len) +{ + int ret; + uint8_t *cmpbuf = malloc(len); + + if (!cmpbuf) { + fprintf(stderr, "Could not allocate memory!\n"); + exit(1); + } + memset(cmpbuf, 0xff, len); + ret = verify_range(flash, cmpbuf, start, len, "ERASE"); + free(cmpbuf); + return ret; +} + +/** + * @cmpbuf buffer to compare against + * @start offset to the base address of the flash chip + * @len length of the verified area + * @message string to print in the "FAILED" message + * @return 0 for success, -1 for failure + */ +int verify_range(struct flashchip *flash, uint8_t *cmpbuf, int start, int len, char *message) +{ + int i, j, starthere, lenhere, ret = 0; + chipaddr bios = flash->virtual_memory; + int page_size = flash->page_size; + uint8_t *readbuf = malloc(page_size); + + if (!len) + goto out_free; + + if (!readbuf) { + fprintf(stderr, "Could not allocate memory!\n"); + exit(1); + } + + if (start + len > flash->total_size * 1024) { + fprintf(stderr, "Error: %s called with start 0x%x + len 0x%x >" + " total_size 0x%x\n", __func__, start, len, + flash->total_size * 1024); + ret = -1; + goto out_free; + } + if (!message) + message = "VERIFY"; + + /* Warning: This loop has a very unusual condition and body. + * The loop needs to go through each page with at least one affected + * byte. The lowest page number is (start / page_size) since that + * division rounds down. The highest page number we want is the page + * where the last byte of the range lives. That last byte has the + * address (start + len - 1), thus the highest page number is + * (start + len - 1) / page_size. Since we want to include that last + * page as well, the loop condition uses <=. + */ + for (i = start / page_size; i <= (start + len - 1) / page_size; i++) { + /* Byte position of the first byte in the range in this page. */ + starthere = max(start, i * page_size); + /* Length of bytes in the range in this page. */ + lenhere = min(start + len, (i + 1) * page_size) - starthere; + chip_readn(readbuf, bios + starthere, lenhere); + for (j = 0; j < lenhere; j++) { + if (cmpbuf[starthere - start + j] != readbuf[j]) { + fprintf(stderr, "%s FAILED at 0x%08x! " + "Expected=0x%02x, Read=0x%02x\n", + message, starthere + j, + cmpbuf[starthere - start + j], readbuf[j]); + ret = -1; + goto out_free; + } + } + } + +out_free: + free(readbuf); + return ret; +} + struct flashchip *probe_flash(struct flashchip *first_flash, int force) { struct flashchip *flash; @@ -389,6 +474,9 @@ int erase_flash(struct flashchip *flash) } 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"); diff --git a/jedec.c b/jedec.c index 26e9caa..711a56d 100644 --- a/jedec.c +++ b/jedec.c @@ -175,8 +175,10 @@ int probe_jedec(struct flashchip *flash) return 0; } -int erase_sector_jedec(chipaddr bios, unsigned int page) +int erase_sector_jedec(struct flashchip *flash, unsigned int page, int pagesize) { + chipaddr bios = flash->virtual_memory; + /* Issue the Sector Erase command */ chip_writeb(0xAA, bios + 0x5555); programmer_delay(10); @@ -195,11 +197,17 @@ int erase_sector_jedec(chipaddr bios, unsigned int page) /* wait for Toggle bit ready */ toggle_ready_jedec(bios); + if (check_erased_range(flash, page, pagesize)) { + fprintf(stderr,"ERASE FAILED!\n"); + return -1; + } return 0; } -int erase_block_jedec(chipaddr bios, unsigned int block) +int erase_block_jedec(struct flashchip *flash, unsigned int block, int blocksize) { + chipaddr bios = flash->virtual_memory; + /* Issue the Sector Erase command */ chip_writeb(0xAA, bios + 0x5555); programmer_delay(10); @@ -218,11 +226,16 @@ int erase_block_jedec(chipaddr bios, unsigned int block) /* wait for Toggle bit ready */ toggle_ready_jedec(bios); + if (check_erased_range(flash, block, blocksize)) { + fprintf(stderr,"ERASE FAILED!\n"); + return -1; + } return 0; } int erase_chip_jedec(struct flashchip *flash) { + int total_size = flash->total_size * 1024; chipaddr bios = flash->virtual_memory; /* Issue the JEDEC Chip Erase command */ @@ -242,6 +255,10 @@ int erase_chip_jedec(struct flashchip *flash) toggle_ready_jedec(bios); + if (check_erased_range(flash, 0, total_size)) { + fprintf(stderr,"ERASE FAILED!\n"); + return -1; + } return 0; } @@ -342,15 +359,11 @@ int write_jedec(struct flashchip *flash, uint8_t *buf) int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; - erase_chip_jedec(flash); - // dumb check if erase was successful. - for (i = 0; i < total_size; i++) { - if (chip_readb(bios + i) != 0xff) { - printf("ERASE FAILED @%d, val %02x!\n", i, chip_readb(bios + i)); - return -1; - } + if (erase_chip_jedec(flash)) { + fprintf(stderr,"ERASE FAILED!\n"); + return -1; } - + printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { printf("%04d at address: 0x%08x", i, i * page_size); diff --git a/m29f002.c b/m29f002.c index 8ad86d2..00cbbc1 100644 --- a/m29f002.c +++ b/m29f002.c @@ -31,12 +31,19 @@ int erase_m29f002(struct flashchip *flash) chip_writeb(0x10, bios + 0x555); programmer_delay(10); toggle_ready_jedec(bios); + if (check_erased_range(flash, 0, flash->total_size * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } -static void rewrite_block(chipaddr bios, uint8_t *src, - chipaddr dst, int size) +static int rewrite_block(struct flashchip *flash, uint8_t *src, + unsigned long start, int size) { + chipaddr bios = flash->virtual_memory; + chipaddr dst = bios + start; + /* erase */ chip_writeb(0xaa, bios + 0x555); chip_writeb(0x55, bios + 0xaaa); @@ -46,6 +53,10 @@ static void rewrite_block(chipaddr bios, uint8_t *src, chip_writeb(0x30, dst); programmer_delay(10); toggle_ready_jedec(bios); + if (check_erased_range(flash, start, size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } /* program */ while (size--) { @@ -57,20 +68,24 @@ static void rewrite_block(chipaddr bios, uint8_t *src, dst++; src++; } + return 0; } -static void do_block(chipaddr bios, uint8_t *src, int i, +static int do_block(struct flashchip *flash, uint8_t *src, int i, unsigned long start, int size) { + int ret; printf("%d at address: 0x%08lx", i, start); - rewrite_block(bios, src + start, bios + start, size); + ret = rewrite_block(flash, src + start, start, size); + if (ret) + return ret; printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); + return 0; } int write_m29f002t(struct flashchip *flash, uint8_t *buf) { int i, page_size = flash->page_size; - chipaddr bios = flash->virtual_memory; /* M29F002(N)T has 7 blocks. From bottom to top their sizes are: * 64k 64k 64k 32k 8k 8k 16k @@ -79,11 +94,11 @@ int write_m29f002t(struct flashchip *flash, uint8_t *buf) printf("Programming block: "); for (i = 0; i < 3; i++) - do_block(bios, buf, i, i * page_size, page_size); - do_block(bios, buf, i++, 0x30000, 32 * 1024); - do_block(bios, buf, i++, 0x38000, 8 * 1024); - do_block(bios, buf, i++, 0x3a000, 8 * 1024); - do_block(bios, buf, i, 0x3c000, 16 * 1024); + do_block(flash, buf, i, i * page_size, page_size); + do_block(flash, buf, i++, 0x30000, 32 * 1024); + do_block(flash, buf, i++, 0x38000, 8 * 1024); + do_block(flash, buf, i++, 0x3a000, 8 * 1024); + do_block(flash, buf, i, 0x3c000, 16 * 1024); printf("\n"); return 0; @@ -92,7 +107,6 @@ int write_m29f002t(struct flashchip *flash, uint8_t *buf) int write_m29f002b(struct flashchip *flash, uint8_t *buf) { int i = 0, page_size = flash->page_size; - chipaddr bios = flash->virtual_memory; /* M29F002B has 7 blocks. From bottom to top their sizes are: * 16k 8k 8k 32k 64k 64k 64k @@ -100,12 +114,12 @@ int write_m29f002b(struct flashchip *flash, uint8_t *buf) */ printf("Programming block: "); - do_block(bios, buf, i++, 0x00000, 16 * 1024); - do_block(bios, buf, i++, 0x04000, 8 * 1024); - do_block(bios, buf, i++, 0x06000, 8 * 1024); - do_block(bios, buf, i++, 0x08000, 32 * 1024); + do_block(flash, buf, i++, 0x00000, 16 * 1024); + do_block(flash, buf, i++, 0x04000, 8 * 1024); + do_block(flash, buf, i++, 0x06000, 8 * 1024); + do_block(flash, buf, i++, 0x08000, 32 * 1024); for (; i < 7; i++) - do_block(bios, buf, i, (i - 3) * page_size, page_size); + do_block(flash, buf, i, (i - 3) * page_size, page_size); printf("\n"); return 0; diff --git a/m29f400bt.c b/m29f400bt.c index 85f9dc0..ace6dae 100644 --- a/m29f400bt.c +++ b/m29f400bt.c @@ -98,11 +98,17 @@ int erase_m29f400bt(struct flashchip *flash) programmer_delay(10); toggle_ready_jedec(bios); + if (check_erased_range(flash, 0, flash->total_size * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } -int block_erase_m29f400bt(chipaddr bios, chipaddr dst) +int block_erase_m29f400bt(struct flashchip *flash, int start, int len) { + chipaddr bios = flash->virtual_memory; + chipaddr dst = bios + start; chip_writeb(0xAA, bios + 0xAAA); chip_writeb(0x55, bios + 0x555); @@ -116,6 +122,10 @@ int block_erase_m29f400bt(chipaddr bios, chipaddr dst) programmer_delay(10); toggle_ready_jedec(bios); + if (check_erased_range(flash, start, len)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -146,26 +156,41 @@ int write_m29f400bt(struct flashchip *flash, uint8_t *buf) printf("total_size/page_size = %d\n", total_size / page_size); for (i = 0; i < (total_size / page_size) - 1; i++) { printf("%04d at address: 0x%08x\n", i, i * page_size); - block_erase_m29f400bt(bios, bios + i * page_size); + if (block_erase_m29f400bt(flash, i * page_size, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + i * page_size, bios + i * page_size, page_size); printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); } printf("%04d at address: 0x%08x\n", 7, 0x70000); - block_erase_m29f400bt(bios, bios + 0x70000); + if (block_erase_m29f400bt(flash, 0x70000, 32 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x70000, bios + 0x70000, 32 * 1024); printf("%04d at address: 0x%08x\n", 8, 0x78000); - block_erase_m29f400bt(bios, bios + 0x78000); + if (block_erase_m29f400bt(flash, 0x78000, 8 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x78000, bios + 0x78000, 8 * 1024); printf("%04d at address: 0x%08x\n", 9, 0x7a000); - block_erase_m29f400bt(bios, bios + 0x7a000); + if (block_erase_m29f400bt(flash, 0x7a000, 8 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x7a000, bios + 0x7a000, 8 * 1024); printf("%04d at address: 0x%08x\n", 10, 0x7c000); - block_erase_m29f400bt(bios, bios + 0x7c000); + if (block_erase_m29f400bt(flash, 0x7c000, 16 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x7c000, bios + 0x7c000, 16 * 1024); printf("\n"); @@ -195,19 +220,31 @@ int write_coreboot_m29f400bt(struct flashchip *flash, uint8_t *buf) * 64 0x00000 0x0ffff BOTTOM *********************************/ printf("%04d at address: 0x%08x\n", 7, 0x00000); - block_erase_m29f400bt(bios, bios + 0x00000); + if (block_erase_m29f400bt(flash, 0x00000, 64 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x00000, bios + 0x00000, 64 * 1024); printf("%04d at address: 0x%08x\n", 7, 0x10000); - block_erase_m29f400bt(bios, bios + 0x10000); + if (block_erase_m29f400bt(flash, 0x10000, 64 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x10000, bios + 0x10000, 64 * 1024); printf("%04d at address: 0x%08x\n", 7, 0x20000); - block_erase_m29f400bt(bios, bios + 0x20000); + if (block_erase_m29f400bt(flash, 0x20000, 64 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x20000, bios + 0x20000, 64 * 1024); printf("%04d at address: 0x%08x\n", 7, 0x30000); - block_erase_m29f400bt(bios, bios + 0x30000); + if (block_erase_m29f400bt(flash, 0x30000, 64 * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } write_page_m29f400bt(bios, buf + 0x30000, bios + 0x30000, 64 * 1024); printf("\n"); diff --git a/mx29f002.c b/mx29f002.c index c96cc93..9d50b00 100644 --- a/mx29f002.c +++ b/mx29f002.c @@ -71,6 +71,10 @@ int erase_29f002(struct flashchip *flash) chip_writeb(0x30, bios + 0x3bfff); #endif + if (check_erased_range(flash, 0, flash->total_size * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -83,7 +87,10 @@ int write_29f002(struct flashchip *flash, uint8_t *buf) chip_writeb(0xF0, bios); programmer_delay(10); - erase_29f002(flash); + if (erase_29f002(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } //*bios = 0xF0; #if 1 printf("Programming page: "); diff --git a/pm29f002.c b/pm29f002.c index 374582b..a01df88 100644 --- a/pm29f002.c +++ b/pm29f002.c @@ -27,7 +27,10 @@ int write_pm29f002(struct flashchip *flash, uint8_t *buf) chipaddr dst = bios; /* Pm29F002T/B use the same erase method... */ - erase_29f040b(flash); + if (erase_29f040b(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } printf("Programming page: "); for (i = 0; i < total_size; i++) { diff --git a/pm49fl00x.c b/pm49fl00x.c index 8129654..3b284e6 100644 --- a/pm49fl00x.c +++ b/pm49fl00x.c @@ -53,7 +53,6 @@ int erase_49fl00x(struct flashchip *flash) int i; int total_size = flash->total_size * 1024; int page_size = flash->page_size; - chipaddr bios = flash->virtual_memory; /* unprotected */ write_lockbits_49fl00x(flash->virtual_registers, @@ -69,7 +68,10 @@ int erase_49fl00x(struct flashchip *flash) continue; /* erase the page */ - erase_block_jedec(bios, i * page_size); + if (erase_block_jedec(flash, i * page_size, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } printf("%04d at address: 0x%08x", i, i * page_size); printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); fflush(stdout); @@ -100,7 +102,10 @@ int write_49fl00x(struct flashchip *flash, uint8_t *buf) continue; /* erase the page before programming */ - erase_block_jedec(bios, i * page_size); + if (erase_block_jedec(flash, i * page_size, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } /* write to the sector */ printf("%04d at address: 0x%08x", i, i * page_size); diff --git a/sb600spi.c b/sb600spi.c index 10f1cb7..259ad27 100644 --- a/sb600spi.c +++ b/sb600spi.c @@ -63,7 +63,10 @@ int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf) /* Erase first */ printf("Erasing flash before programming... "); - flash->erase(flash); + if (flash->erase(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } printf("done.\n"); printf("Programming flash"); diff --git a/sharplhf00l04.c b/sharplhf00l04.c index 4d652ae..53b9931 100644 --- a/sharplhf00l04.c +++ b/sharplhf00l04.c @@ -124,6 +124,10 @@ int erase_lhf00l04_block(struct flashchip *flash, int offset) print_lhf00l04_status(status); printf("DONE BLOCK 0x%x\n", offset); + if (check_erased_range(flash, offset, flash->page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -135,7 +139,10 @@ int erase_lhf00l04(struct flashchip *flash) printf("total_size is %d; flash->page_size is %d\n", total_size, flash->page_size); for (i = 0; i < total_size; i += flash->page_size) - erase_lhf00l04_block(flash, i); + if (erase_lhf00l04_block(flash, i)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } printf("DONE ERASE\n"); return 0; @@ -161,9 +168,8 @@ int write_lhf00l04(struct flashchip *flash, uint8_t *buf) int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; - erase_lhf00l04(flash); - if (chip_readb(bios) != 0xff) { - printf("ERASE FAILED!\n"); + if (erase_lhf00l04(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); return -1; } printf("Programming page: "); diff --git a/sst28sf040.c b/sst28sf040.c index bbbdbd3..35f8c27 100644 --- a/sst28sf040.c +++ b/sst28sf040.c @@ -54,14 +54,20 @@ static void unprotect_28sf040(chipaddr bios) tmp = chip_readb(bios + 0x041A); } -static int erase_sector_28sf040(chipaddr bios, unsigned long address) +static int erase_sector_28sf040(struct flashchip *flash, unsigned long address, int sector_size) { + chipaddr bios = flash->virtual_memory; + chip_writeb(AUTO_PG_ERASE1, bios); chip_writeb(AUTO_PG_ERASE2, bios + address); /* wait for Toggle bit ready */ toggle_ready_jedec(bios); + if (check_erased_range(flash, address, sector_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -124,6 +130,10 @@ int erase_28sf040(struct flashchip *flash) programmer_delay(10); toggle_ready_jedec(bios); + if (check_erased_range(flash, 0, flash->total_size * 1024)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -139,7 +149,10 @@ int write_28sf040(struct flashchip *flash, uint8_t *buf) printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { /* erase the page before programming */ - erase_sector_28sf040(bios, i * page_size); + if (erase_sector_28sf040(flash, i * page_size, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } /* write to the sector */ printf("%04d at address: 0x%08x", i, i * page_size); diff --git a/sst49lf040.c b/sst49lf040.c index 1147c92..ab1c918 100644 --- a/sst49lf040.c +++ b/sst49lf040.c @@ -25,12 +25,14 @@ int erase_49lf040(struct flashchip *flash) int i; int total_size = flash->total_size * 1024; int page_size = flash->page_size; - chipaddr bios = flash->virtual_memory; for (i = 0; i < total_size / page_size; i++) { /* Chip erase only works in parallel programming mode * for the 49lf040. Use sector-erase instead */ - erase_sector_jedec(bios, i * page_size); + if (erase_sector_jedec(flash, i * page_size, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } } return 0; @@ -48,7 +50,10 @@ int write_49lf040(struct flashchip *flash, uint8_t *buf) /* erase the page before programming * Chip erase only works in parallel programming mode * for the 49lf040. Use sector-erase instead */ - erase_sector_jedec(bios, i * page_size); + if (erase_sector_jedec(flash, i * page_size, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } /* write to the sector */ if (i % 10 == 0) diff --git a/sst49lfxxxc.c b/sst49lfxxxc.c index 733864c..2875d64 100644 --- a/sst49lfxxxc.c +++ b/sst49lfxxxc.c @@ -75,9 +75,10 @@ static int write_lockbits_49lfxxxc(struct flashchip *flash, unsigned char bits) return 0; } -static int erase_sector_49lfxxxc(chipaddr bios, unsigned long address) +static int erase_sector_49lfxxxc(struct flashchip *flash, unsigned long address, int sector_size) { unsigned char status; + chipaddr bios = flash->virtual_memory; chip_writeb(SECTOR_ERASE, bios); chip_writeb(ERASE, bios + address); @@ -91,6 +92,10 @@ static int erase_sector_49lfxxxc(chipaddr bios, unsigned long address) } } while (!(status & STATUS_WSMS)); + if (check_erased_range(flash, address, sector_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } @@ -156,7 +161,7 @@ int erase_49lfxxxc(struct flashchip *flash) write_lockbits_49lfxxxc(flash, 0); for (i = 0; i < total_size; i += flash->page_size) - if (erase_sector_49lfxxxc(bios, i) != 0) + if (erase_sector_49lfxxxc(flash, i, flash->page_size)) return (-1); chip_writeb(RESET, bios); @@ -175,7 +180,10 @@ int write_49lfxxxc(struct flashchip *flash, uint8_t *buf) printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { /* erase the page before programming */ - erase_sector_49lfxxxc(bios, i * page_size); + if (erase_sector_49lfxxxc(flash, i * page_size, flash->page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } /* write to the sector */ printf("%04d at address: 0x%08x", i, i * page_size); diff --git a/sst_fwhub.c b/sst_fwhub.c index 5fbacdd..e7ae9e9 100644 --- a/sst_fwhub.c +++ b/sst_fwhub.c @@ -94,7 +94,7 @@ int probe_sst_fwhub(struct flashchip *flash) return 1; } -int erase_sst_fwhub_block(struct flashchip *flash, int offset) +int erase_sst_fwhub_block(struct flashchip *flash, int offset, int page_size) { uint8_t blockstatus = clear_sst_fwhub_block_lock(flash, offset); @@ -104,7 +104,10 @@ int erase_sst_fwhub_block(struct flashchip *flash, int offset) return 1; } - erase_block_jedec(flash->virtual_memory, offset); + if (erase_block_jedec(flash, offset, page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } toggle_ready_jedec(flash->virtual_memory); return 0; @@ -114,15 +117,10 @@ int erase_sst_fwhub(struct flashchip *flash) { int i; unsigned int total_size = flash->total_size * 1024; - chipaddr bios = flash->virtual_memory; - for (i = 0; i < total_size; i += flash->page_size) - erase_sst_fwhub_block(flash, i); - - // dumb check if erase was successful. - for (i = 0; i < total_size; i++) { - if (chip_readb(bios + i) != 0xff) { - printf("ERASE FAILED!\n"); + for (i = 0; i < total_size; i += flash->page_size) { + if (erase_sst_fwhub_block(flash, i, flash->page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); return -1; } } @@ -139,8 +137,10 @@ int write_sst_fwhub(struct flashchip *flash, uint8_t *buf) uint8_t blockstatus; // FIXME: We want block wide erase instead of ironing the whole chip - if (erase_sst_fwhub(flash)) + if (erase_sst_fwhub(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); return -1; + } printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { diff --git a/stm50flw0x0x.c b/stm50flw0x0x.c index a68b9ad..30b7d50 100644 --- a/stm50flw0x0x.c +++ b/stm50flw0x0x.c @@ -164,7 +164,6 @@ int unlock_block_stm50flw0x0x(struct flashchip *flash, int offset) int erase_block_stm50flw0x0x(struct flashchip *flash, int offset) { chipaddr bios = flash->virtual_memory + offset; - int j; // clear status register chip_writeb(0x50, bios); @@ -176,13 +175,10 @@ int erase_block_stm50flw0x0x(struct flashchip *flash, int offset) wait_stm50flw0x0x(flash->virtual_memory); - for (j = 0; j < flash->page_size; j++) { - if (chip_readb(bios + j) != 0xFF) { - printf("Erase failed at 0x%x\n", offset + j); - return -1; - } + if (check_erased_range(flash, offset, flash->page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; } - printf("DONE BLOCK 0x%x\n", offset); return 0; @@ -231,24 +227,29 @@ int write_page_stm50flw0x0x(chipaddr bios, uint8_t *src, */ int erase_stm50flw0x0x(struct flashchip *flash) { - int i, rc = 0; + int i; int total_size = flash->total_size * 1024; int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; printf("Erasing page:\n"); - for (i = 0; (i < total_size / page_size) && (rc == 0); i++) { + for (i = 0; i < total_size / page_size; i++) { printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); printf("%04d at address: 0x%08x ", i, i * page_size); - rc = unlock_block_stm50flw0x0x(flash, i * page_size); - if (!rc) - rc = erase_block_stm50flw0x0x(flash, i * page_size); + if (unlock_block_stm50flw0x0x(flash, i * page_size)) { + fprintf(stderr, "UNLOCK FAILED!\n"); + return -1; + } + if (erase_block_stm50flw0x0x(flash, i * page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } } printf("\n"); protect_stm50flw0x0x(bios); - return rc; + return 0; } int write_stm50flw0x0x(struct flashchip *flash, uint8_t * buf) diff --git a/w39v040c.c b/w39v040c.c index 48e9bd3..7fccd53 100644 --- a/w39v040c.c +++ b/w39v040c.c @@ -60,16 +60,13 @@ int erase_w39v040c(struct flashchip *flash) { int i; unsigned int total_size = flash->total_size * 1024; - chipaddr bios = flash->virtual_memory; - - for (i = 0; i < total_size; i += flash->page_size) - erase_sector_jedec(flash->virtual_memory, i); - for (i = 0; i < total_size; i++) - if (0xff != chip_readb(bios + i)) { - printf("ERASE FAILED at 0x%08x! Expected=0xff, Read=0x%02x\n", i, chip_readb(bios + i)); + for (i = 0; i < total_size; i += flash->page_size) { + if (erase_sector_jedec(flash, i, flash->page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); return -1; } + } return 0; } @@ -81,8 +78,10 @@ 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 (flash->erase(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); return -1; + } printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { diff --git a/w39v080fa.c b/w39v080fa.c index 8dc882a..31ef15f 100644 --- a/w39v080fa.c +++ b/w39v080fa.c @@ -142,9 +142,10 @@ int unlock_winbond_fwhub(struct flashchip *flash) return 0; } -static int erase_sector_winbond_fwhub(chipaddr bios, +static int erase_sector_winbond_fwhub(struct flashchip *flash, unsigned int sector) { + chipaddr bios = flash->virtual_memory; /* Remember: too much sleep can waste your day. */ printf("0x%08x\b\b\b\b\b\b\b\b\b\b", sector); @@ -161,30 +162,30 @@ static int erase_sector_winbond_fwhub(chipaddr bios, /* wait for Toggle bit ready */ toggle_ready_jedec(bios); + if (check_erased_range(flash, sector, flash->page_size)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } return 0; } int erase_winbond_fwhub(struct flashchip *flash) { int i, total_size = flash->total_size * 1024; - chipaddr bios = flash->virtual_memory; unlock_winbond_fwhub(flash); printf("Erasing: "); - for (i = 0; i < total_size; i += flash->page_size) - erase_sector_winbond_fwhub(bios, i); - - printf("\n"); - - for (i = 0; i < total_size; i++) { - if (chip_readb(bios + i) != 0xff) { - fprintf(stderr, "Error: Flash chip erase failed at 0x%08x(0x%02x)\n", i, chip_readb(bios + i)); + for (i = 0; i < total_size; i += flash->page_size) { + if (erase_sector_winbond_fwhub(flash, i)) { + fprintf(stderr, "ERASE FAILED!\n"); return -1; } } + printf("\n"); + return 0; } diff --git a/w49f002u.c b/w49f002u.c index 1c4177a..d12bc72 100644 --- a/w49f002u.c +++ b/w49f002u.c @@ -27,7 +27,10 @@ int write_49f002(struct flashchip *flash, uint8_t *buf) int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; - erase_chip_jedec(flash); + if (erase_chip_jedec(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { diff --git a/wbsio_spi.c b/wbsio_spi.c index dce6631..8ca0abc 100644 --- a/wbsio_spi.c +++ b/wbsio_spi.c @@ -196,7 +196,10 @@ int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf) return 1; } - flash->erase(flash); + if (flash->erase(flash)) { + fprintf(stderr, "ERASE FAILED!\n"); + return -1; + } result = spi_write_enable(); if (result) return result; -- cgit v1.1