Am 20.02.2012 17:07 schrieb Stefan Tauner:
TODO:
- how should the SFDP data be supplied/selected by the user?
- option A (suggested one): add a default table with a legit complete table
Good idea.
and a programmer option to use a binary file instead.
I think having the file+builtin combination is overkill. Builtin should be sufficient, unless you plan to focus more on making flashrom a verification tool for flash vendors.
- Manpage
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at
dummyflasher.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 82 insertions(+), 8 deletions(-)
diff --git a/dummyflasher.c b/dummyflasher.c index afe0518..6d8b9a2 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -45,6 +45,7 @@ enum emu_chip { EMULATE_ST_M25P10_RES, EMULATE_SST_SST25VF040_REMS, EMULATE_SST_SST25VF032B,
- EMULATE_WINBOND_W25Q64CV,
}; static enum emu_chip emu_chip = EMULATE_NONE; static char *emu_persistent_image = NULL; @@ -61,6 +62,40 @@ unsigned char spi_blacklist[256]; unsigned char spi_ignorelist[256]; int spi_blacklist_size = 0; int spi_ignorelist_size = 0;
+/* legit intel version */ +/* +static const uint8_t const sfdp_table[256] = {
- 0x53, 0x46, 0x44, 0x50, // @0x00
- 0x00, 0x01, 0x00, 0xFF, // @0x04
- 0x00, 0x00, 0x01, 0x04, // @0x08: len = 4 instead of 9
- 0x14, 0x00, 0x00, 0xFF, // @0x0C: PTP0 = 0x14 instead of 0x80
- 0xFF, 0xFF, 0xFF, 0xFF, // @0x10
- 0xE5, 0x20, 0xF1, 0xFF, // @0x14
- 0xFF, 0xFF, 0xFF, 0x03, // @0x18
- 0x44, 0xEB, 0x08, 0x6B, // @0x1C
- 0x08, 0x3B, 0x80, 0xBB, // @0x20
+}; +*/ +/* legit complete table */ +static const uint8_t const sfdp_table[256] = {
- 0x53, 0x46, 0x44, 0x50, // @0x00
- 0x00, 0x01, 0x00, 0xFF, // @0x04
- 0x00, 0x00, 0x01, 0x09, // @0x08
- 0x14, 0x00, 0x00, 0xFF, // @0x0C: PTP0 = 0x14 instead of 0x80
- 0xFF, 0xFF, 0xFF, 0xFF, // @0x10
- 0xE5, 0x20, 0xF1, 0xFF, // @0x14
- 0xFF, 0xFF, 0xFF, 0x03, // @0x18
- 0x44, 0xEB, 0x08, 0x6B, // @0x1C
- 0x08, 0x3B, 0x80, 0xBB, // @0x20
- 0xEE, 0xFF, 0xFF, 0xFF, // @0x24
- 0xFF, 0xFF, 0x00, 0x00, // @0x28
- 0xFF, 0xFF, 0x00, 0x00, // @0x2C
- 0x0C, 0x20, 0x0F, 0x52, // @0x30
- 0x10, 0xD8, 0x00, 0x00, // @0x34
+};
#endif #endif
@@ -296,6 +331,19 @@ int dummy_init(void) msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI " "write)\n"); }
- if (!strcmp(tmp, "W25Q64CV")) {
emu_chip = EMULATE_WINBOND_W25Q64CV;
emu_chip_size = 8 * 1024 * 1024;
emu_max_byteprogram_size = 256;
emu_max_aai_size = 0;
emu_jedec_se_size = 4 * 1024;
emu_jedec_be_52_size = 32 * 1024;
emu_jedec_be_d8_size = 64 * 1024;
emu_jedec_ce_60_size = emu_chip_size;
emu_jedec_ce_c7_size = emu_chip_size;
msg_pdbg("Emulating Winbond W25Q64CV SPI flash chip (RDID, "
"SFDP)\n");
- }
#endif if (emu_chip == EMULATE_NONE) { msg_perr("Invalid chip specified for emulation: %s\n", tmp); @@ -471,15 +519,26 @@ static int emulate_spi_chip_response(unsigned int writecnt, readarr[1] = 0x44; break; case JEDEC_RDID:
if (emu_chip != EMULATE_SST_SST25VF032B)
switch (emu_chip) {
case EMULATE_SST_SST25VF032B:
if (readcnt > 0)
readarr[0] = 0xbf;
if (readcnt > 1)
readarr[1] = 0x25;
if (readcnt > 2)
readarr[2] = 0x4a; break;
/* Respond with SST_SST25VF032B. */
if (readcnt > 0)
readarr[0] = 0xbf;
if (readcnt > 1)
readarr[1] = 0x25;
if (readcnt > 2)
readarr[2] = 0x4a;
case EMULATE_WINBOND_W25Q64CV:
if (readcnt > 0)
readarr[0] = 0xef;
if (readcnt > 1)
readarr[1] = 0x40;
if (readcnt > 2)
readarr[2] = 0x17;
break;
default: /* ignore */
break;
break; case JEDEC_RDSR: memset(readarr, 0, readcnt);}
@@ -629,6 +688,20 @@ static int emulate_spi_chip_response(unsigned int writecnt, /* emu_jedec_ce_c7_size is emu_chip_size. */ memset(flashchip_contents, 0xff, emu_jedec_ce_c7_size); break;
- case JEDEC_SFDP:
if (emu_chip != EMULATE_WINBOND_W25Q64CV)
break;
offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
/*
* FIXME: There is one dummy byte (i.e. 8 clock cycles) to be
* transferred after the address. Since we can not observe the
* clock, we would need to check for appropriate writecnt and/or
* readcnt and recalculate the parameters below.
*/
/* FIXME: this could be more sophisticated. */
memcpy(readarr, sfdp_table + offs,
min(sizeof(sfdp_table) - offs, readcnt));
That memcpy will segfault if offs>sizeof(sfdp_table). Suggestion: Replace the whole case statement with this (some 80 col reformatting may be needed):
case JEDEC_SFDP: int toread; if (emu_chip != EMULATE_WINBOND_W25Q64CV) break; if (writecnt < 4) break; offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; /* The response is shifted if more than 4 bytes are written. */ offs += writecnt - 4; /* The SFDP spec suggests wraparound is allowed. */ offs %= sizeof(sfdp_table); toread = min(sizeof(sfdp_table) - offs, readcnt); memcpy(readarr, sfdp_table + offs, toread); if (toread < readcnt) memcpy(readarr + toread, sfdp_table, min(sizeof(sfdp_table),readcnt - toread)); if (readcnt - toread > sizeof(sfdp_table)) msg_pdbg("Reading more than SFDP table size in one " "chunk, contents may be incomplete.\n");
default: /* No special response. */ break;break;
@@ -657,6 +730,7 @@ static int dummy_spi_send_command(struct flashctx *flash, unsigned int writecnt, case EMULATE_ST_M25P10_RES: case EMULATE_SST_SST25VF040_REMS: case EMULATE_SST_SST25VF032B:
- case EMULATE_WINBOND_W25Q64CV: if (emulate_spi_chip_response(writecnt, readcnt, writearr, readarr)) { msg_pdbg("Invalid command sent to flash chip!\n");
Regards, Carl-Daniel