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 and a programmer option to use a binary file instead. - option B: add multiple legit and invalid tables to cover most useful test cases and add a programmer option to select which table should be used. - option C: some combination of A and B - 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)); + break; default: /* No special response. */ 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");