This should also fix broken write for non-uniform sectored FWH-like chips. These are: Intel 28F001 Sharp LHF00L04 ST M50FW002 ST M50LPW116
Signed-off-by: Michael Karcher flashrom@mkarcher.dialup.fu-berlin.de --- 82802ab.c | 85 +++++++++++++++++++++++++++++-------------- chipdrivers.h | 3 ++ flash.h | 2 +- flashchips.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ flashchips.h | 4 ++ 5 files changed, 175 insertions(+), 29 deletions(-)
diff --git a/82802ab.c b/82802ab.c index aa7e45e..27acaa3 100644 --- a/82802ab.c +++ b/82802ab.c @@ -48,6 +48,12 @@ int probe_82802ab(struct flashchip *flash) chipaddr bios = flash->virtual_memory; uint8_t id1, id2; uint8_t flashcontent1, flashcontent2; + int id2_offset; + + if (flash->feature_bits & FEATURE_ADDR_SHIFTED) + id2_offset = 2; + else + id2_offset = 1;
/* Reset to get a clean state */ chip_writeb(0xFF, bios); @@ -58,7 +64,7 @@ int probe_82802ab(struct flashchip *flash) programmer_delay(10);
id1 = chip_readb(bios); - id2 = chip_readb(bios + 0x01); + id2 = chip_readb(bios + id2_offset);
/* Leave ID mode */ chip_writeb(0xFF, bios); @@ -72,7 +78,7 @@ int probe_82802ab(struct flashchip *flash)
/* Read the product ID location again. We should now see normal flash contents. */ flashcontent1 = chip_readb(bios); - flashcontent2 = chip_readb(bios + 0x01); + flashcontent2 = chip_readb(bios + id2_offset);
if (id1 == flashcontent1) msg_cdbg(", id1 is normal flash content"); @@ -177,41 +183,64 @@ void write_page_82802ab(chipaddr bios, uint8_t *src,
int write_82802ab(struct flashchip *flash, uint8_t *buf) { - int i; - int total_size = flash->total_size * 1024; + int i, j, blocknum; + int blockoffset = 0; int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; uint8_t *tmpbuf = malloc(page_size); + struct eraseblock * blocks; + int (*erase) (struct flashchip *flash, unsigned int blockaddr, + unsigned int blocklen); + + /* find first erase layout with a working erase function */ + for (i = 0; flash->block_erasers[i].block_erase == NULL && + i < NUM_ERASEFUNCTIONS; i++); + + if (i == NUM_ERASEFUNCTIONS) + { + msg_perr("No working erase function found - can't write\n"); + return -1; + } + msg_pdbg("Chosing block layout #%d\n", i); + blocks = flash->block_erasers[i].eraseblocks; + erase = flash->block_erasers[i].block_erase;
if (!tmpbuf) { msg_cerr("Could not allocate memory!\n"); exit(1); } - msg_cinfo("Programming page: \n"); - for (i = 0; i < total_size / page_size; i++) { - msg_cinfo("\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"); - msg_cinfo("%04d at address: 0x%08x", i, i * page_size); - - /* Auto Skip Blocks, which already contain the desired data - * Faster, because we only write, what has changed - * More secure, because blocks, which are excluded - * (with the exclude or layout feature) - * or not erased and rewritten; their data is retained also in - * sudden power off situations - */ - chip_readn(tmpbuf, bios + i * page_size, page_size); - if (!memcmp((void *)(buf + i * page_size), tmpbuf, page_size)) { - msg_cdbg("SKIPPED\n"); - continue; - } - - /* erase block by block and write block by block; this is the most secure way */ - if (erase_block_82802ab(flash, i * page_size, page_size)) { - msg_cerr("ERASE FAILED!\n"); - return -1; + msg_cinfo("Programming block: \n"); + blocknum = 0; + for (i = 0; blocks[i].size != 0; i++) { + for(j = 0; j < blocks[i].count; j++) { + msg_cinfo("\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"); + msg_cinfo("%04d at address: 0x%08x", blocknum, + blockoffset); + + /* Auto Skip Blocks, which already contain the + * desired data: + * Faster, because we only write, what has changed + * More secure, because blocks, which are excluded + * (with the exclude or layout feature) + * or not erased and rewritten; their data is + * retained also in sudden power off situations + */ + chip_readn(tmpbuf, bios + blockoffset, blocks[i].size); + if (!memcmp((void *)(buf + i * page_size), tmpbuf, + blocks[i].size)) { + msg_cdbg("SKIPPED\n"); + } else { + if (erase(flash, blockoffset, page_size)) { + msg_cerr("ERASE FAILED!\n"); + return -1; + } + write_page_82802ab(bios, buf + blockoffset, + bios + blockoffset, blocks[i].size); + } + blockoffset += blocks[i].size; + blocknum++; } - write_page_82802ab(bios, buf + i * page_size, - bios + i * page_size, page_size); } msg_cinfo("DONE!\n"); free(tmpbuf); diff --git a/chipdrivers.h b/chipdrivers.h index 6d5cef0..816088a 100644 --- a/chipdrivers.h +++ b/chipdrivers.h @@ -53,6 +53,9 @@ int spi_nbyte_read(int addr, uint8_t *bytes, int len); int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize); int spi_aai_write(struct flashchip *flash, uint8_t *buf);
+/* i28f00x.c */ +int write_28f00x(struct flashchip *flash, uint8_t *buf); + /* 82802ab.c */ uint8_t wait_82802ab(chipaddr bios); int probe_82802ab(struct flashchip *flash); diff --git a/flash.h b/flash.h index aee95a3..0a74363 100644 --- a/flash.h +++ b/flash.h @@ -166,7 +166,7 @@ enum chipbustype { #define FEATURE_ADDR_MASK (3 << 2) #define FEATURE_ADDR_2AA (1 << 2) #define FEATURE_ADDR_AAA (2 << 2) -#define FEATURE_ADDR_SHIFTED 0 +#define FEATURE_ADDR_SHIFTED (1 << 5)
struct flashchip { const char *vendor; diff --git a/flashchips.c b/flashchips.c index 2dbc1e0..f838ab2 100644 --- a/flashchips.c +++ b/flashchips.c @@ -2385,6 +2385,116 @@ struct flashchip flashchips[] = {
{ .vendor = "Intel", + .name = "28F004BV/BE-B", + .bustype = CHIP_BUSTYPE_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = P28F004BB, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {16 * 1024, 1}, + {8 * 1024, 2}, + {96 * 1024, 1}, + {128 * 1024, 3}, + }, + .block_erase = erase_block_82802ab, + }, + }, + .write = write_82802ab, + .read = read_memmapped, + }, + + { + .vendor = "Intel", + .name = "28F004BV/BE-T", + .bustype = CHIP_BUSTYPE_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = P28F004BT, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {128 * 1024, 3}, + {96 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}, + }, + .block_erase = erase_block_82802ab, + }, + }, + .write = write_82802ab, + .read = read_memmapped, + }, + + { + .vendor = "Intel", + .name = "28F400BV/CV/CE-B", + .bustype = CHIP_BUSTYPE_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = P28F400BB, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .feature_bits = FEATURE_ADDR_SHIFTED, + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {16 * 1024, 1}, + {8 * 1024, 2}, + {96 * 1024, 1}, + {128 * 1024, 3}, + }, + .block_erase = erase_block_82802ab, + }, + }, + .write = write_82802ab, + .read = read_memmapped, + }, + + { + .vendor = "Intel", + .name = "28F004BV/BE-T", + .bustype = CHIP_BUSTYPE_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = P28F400BT, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .feature_bits = FEATURE_ADDR_SHIFTED, + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {128 * 1024, 3}, + {96 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}, + }, + .block_erase = erase_block_82802ab, + }, + }, + .write = write_82802ab, + .read = read_memmapped, + }, + + { + .vendor = "Intel", .name = "82802AB", .bustype = CHIP_BUSTYPE_FWH, .manufacture_id = INTEL_ID, diff --git a/flashchips.h b/flashchips.h index 4337e52..b6c2e8b 100644 --- a/flashchips.h +++ b/flashchips.h @@ -259,6 +259,10 @@ #define E_28F016S5 0xAA #define P28F001BXT 0x94 /* 28F001BX-T */ #define P28F001BXB 0x95 /* 28F001BX-B */ +#define P28F004BT 0x78 /* 28F004BV/BE-T */ +#define P28F004BB 0x79 /* 28F004BV/BE-B */ +#define P28F400BT 0x70 /* 28F400BV/CV/CE-T */ +#define P28F400BB 0x71 /* 28F400BV/CV/CE-B */ #define SHARP_LH28F008SA 0xA2 /* Sharp chip, Intel Vendor ID */ #define SHARP_LH28F008SC 0xA6 /* Sharp chip, Intel Vendor ID */