[flashrom] [PATCH] SPI flash chip emulator
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Wed Oct 27 06:40:43 CEST 2010
Add SPI flash emulation capability to dummyflasher.
You have to choose at compile time between
- no emulation
- ST M25P10.RES SPI flash chip (RES, page write)
- SST SST25VF040.REMS SPI flash chip (REMS, byte write)
- SST SST25VF032B SPI flash chip (RDID, AAI write)
This code helped me find and fix various bugs in the SPI write code
(patches forthcoming).
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
Index: flashrom-emulate_spi_flashchip/dummyflasher.c
===================================================================
--- flashrom-emulate_spi_flashchip/dummyflasher.c (Revision 1216)
+++ flashrom-emulate_spi_flashchip/dummyflasher.c (Arbeitskopie)
@@ -25,6 +25,45 @@
#include "chipdrivers.h"
#include "programmer.h"
+//#define EMULATE_ST_M25P10_RES 1
+//#define EMULATE_SST_SST25VF040_REMS 1
+//#define EMULATE_SST_SST25VF032B 1
+
+#if EMULATE_ST_M25P10_RES + EMULATE_SST_SST25VF040_REMS + EMULATE_SST_SST25VF032B > 1
+#error Only one chip can be emulated. Please decide which one you want.
+#endif
+
+#if EMULATE_ST_M25P10_RES || EMULATE_SST_SST25VF040_REMS || EMULATE_SST_SST25VF032B
+#define EMULATE_SPI_CHIP 1
+#endif
+
+#if EMULATE_SPI_CHIP
+#define EMULATE_CHIP 1
+#include "spi.h"
+#endif
+
+#if EMULATE_ST_M25P10_RES
+#define EMU_FLASHCHIP_SIZE 128 * 1024
+#define MAX_BYTEPROGRAM_SIZE 128
+#define MAX_AAI_SIZE 0
+#endif
+
+#if EMULATE_SST_SST25VF040_REMS
+#define EMU_FLASHCHIP_SIZE 512 * 1024
+#define MAX_BYTEPROGRAM_SIZE 1
+#define MAX_AAI_SIZE 0
+#endif
+
+#if EMULATE_SST_SST25VF032B
+#define EMU_FLASHCHIP_SIZE 4 * 1024 * 1024
+#define MAX_BYTEPROGRAM_SIZE 1
+#define MAX_AAI_SIZE 2
+#endif
+
+#if EMULATE_CHIP
+static uint8_t flashchip_contents[EMU_FLASHCHIP_SIZE];
+#endif
+
static void tolower_string(char *str)
{
for (; *str != '\0'; str++)
@@ -65,6 +104,25 @@
if (buses_supported == CHIP_BUSTYPE_NONE)
msg_pdbg("Support for all flash bus types disabled.\n");
free(bustext);
+
+#if EMULATE_ST_M25P10_RES
+ msg_pdbg("Emulating ST M25P10.RES SPI flash chip (RES, page write)\n");
+#endif
+#if EMULATE_SST_SST25VF040_REMS
+ msg_pdbg("Emulating SST SST25VF040.REMS SPI flash chip (REMS, byte "
+ "write)\n");
+#endif
+#if EMULATE_SST_SST25VF032B
+ msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI "
+ "write)\n");
+#endif
+#if EMULATE_CHIP
+ msg_pdbg("Filling fake flash chip with 0xff, size %i\n",
+ sizeof(flashchip_contents));
+ memset(flashchip_contents, 0xff, sizeof(flashchip_contents));
+#else
+ msg_pdbg("Not emulating any flash chip.\n");
+#endif
return 0;
}
@@ -140,6 +198,123 @@
return;
}
+#if EMULATE_SPI_CHIP
+static int emulate_spi_chip_response(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+ int offs;
+#if EMULATE_SST_SST25VF032B
+ static int aai_offs;
+ static int aai_active = 0;
+#endif
+ if (writecnt == 0) {
+ msg_cerr("No command sent to the chip!\n");
+ return 1;
+ }
+ switch (writearr[0]) {
+#if EMULATE_ST_M25P10_RES
+ case JEDEC_RES:
+ /* Respond with ST_M25P10_RES. */
+ if (readcnt > 0)
+ readarr[0] = 0x10;
+ break;
+#endif
+#if EMULATE_SST_SST25VF040_REMS
+ case JEDEC_REMS:
+ /* Respond with SST_SST25VF040_REMS. */
+ if (readcnt > 0)
+ readarr[0] = 0xbf;
+ if (readcnt > 1)
+ readarr[1] = 0x44;
+ break;
+#endif
+#if EMULATE_SST_SST25VF032B
+ case JEDEC_RDID:
+ /* Respond with SST_SST25VF032B. */
+ if (readcnt > 0)
+ readarr[0] = 0xbf;
+ if (readcnt > 1)
+ readarr[1] = 0x25;
+ if (readcnt > 2)
+ readarr[2] = 0x4a;
+ break;
+#endif
+ case JEDEC_RDSR:
+ memset(readarr, 0, readcnt);
+#if EMULATE_SST_SST25VF032B
+ if (aai_active)
+ memset(readarr, 1 << 6, readcnt);
+#endif
+ break;
+ case JEDEC_READ:
+ offs = writearr[1] << 16 | writearr[2] << 8 |
+ writearr[3];
+ /* Truncate to EMU_FLASHCHIP_SIZE. */
+ offs %= EMU_FLASHCHIP_SIZE;
+ if (readcnt > 0)
+ memcpy(readarr, flashchip_contents + offs, readcnt);
+ break;
+ case JEDEC_BYTE_PROGRAM:
+ offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
+ /* Truncate to EMU_FLASHCHIP_SIZE. */
+ offs %= EMU_FLASHCHIP_SIZE;
+ if (writecnt < 5) {
+ msg_cerr("BYTE PROGRAM size too short!\n");
+ return 1;
+ }
+ if (writecnt - 4 > MAX_BYTEPROGRAM_SIZE) {
+ msg_cerr("Max BYTE PROGRAM size exceeded!\n");
+ return 1;
+ }
+ memcpy(flashchip_contents + offs, writearr + 4, writecnt - 4);
+ break;
+#if EMULATE_SST_SST25VF032B
+ case JEDEC_AAI_WORD_PROGRAM:
+ if (!aai_active) {
+ if (writecnt < JEDEC_AAI_WORD_PROGRAM_OUTSIZE) {
+ msg_cerr("Initial AAI WORD PROGRAM size too "
+ "short!\n");
+ return 1;
+ }
+ if (writecnt > JEDEC_AAI_WORD_PROGRAM_OUTSIZE) {
+ msg_cerr("Initial AAI WORD PROGRAM size too "
+ "long!\n");
+ return 1;
+ }
+ aai_active = 1;
+ aai_offs = writearr[1] << 16 | writearr[2] << 8 |
+ writearr[3];
+ /* Truncate to EMU_FLASHCHIP_SIZE. */
+ aai_offs %= EMU_FLASHCHIP_SIZE;
+ memcpy(flashchip_contents + aai_offs, writearr + 4, 2);
+ aai_offs += 2;
+ } else {
+ if (writecnt < JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) {
+ msg_cerr("Continuation AAI WORD PROGRAM size "
+ "too short!\n");
+ return 1;
+ }
+ if (writecnt > JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) {
+ msg_cerr("Continuation AAI WORD PROGRAM size "
+ "too long!\n");
+ return 1;
+ }
+ memcpy(flashchip_contents + aai_offs, writearr + 1, 2);
+ aai_offs += 2;
+ }
+ break;
+ case JEDEC_WRDI:
+ aai_active = 0;
+ break;
+#endif
+ default:
+ /* No special response. */
+ break;
+ }
+ return 0;
+}
+#endif
+
int dummy_spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
@@ -157,6 +332,9 @@
readarr[i] = 0xff;
}
+#if EMULATE_SPI_CHIP
+ emulate_spi_chip_response(writecnt, readcnt, writearr, readarr);
+#endif
msg_pspew("\n");
return 0;
}
--
http://www.hailfinger.org/
More information about the flashrom
mailing list