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 <[email protected]>

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/


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to