[flashrom] [PATCH] dummyflasher.c: add support for SFDP by adding a new emulator chip: W25Q64CV
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Mon Feb 20 19:49:38 CET 2012
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 at 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");
> + 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");
Regards,
Carl-Daniel
--
http://www.hailfinger.org/
More information about the flashrom
mailing list