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(a)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");
--
1.7.1