Index: dummyflasher.c |
diff --git a/dummyflasher.c b/dummyflasher.c |
index 473e45e9c3193915206e445147daed0f142117d4..91fbc8828468a3ded698d94b677d16ce6c25d81c 100644 |
--- a/dummyflasher.c |
+++ b/dummyflasher.c |
@@ -22,6 +22,7 @@ |
#include "flash.h" |
#include "chipdrivers.h" |
#include "programmer.h" |
+#include "flashchips.h" |
/* Remove the #define below if you don't want SPI flash chip emulation. */ |
#define EMULATE_SPI_CHIP 1 |
@@ -34,6 +35,13 @@ |
#if EMULATE_CHIP |
#include <sys/types.h> |
#include <sys/stat.h> |
+ |
+#if EMULATE_SPI_CHIP |
+/* The name of variable-size virtual chip. A 4MB flash example: |
+ * flashrom -p dummy:emulate=VARIABLE_SIZE,size=4194304 |
+ */ |
+#define VARIABLE_SIZE_CHIP_NAME "VARIABLE_SIZE" |
+#endif |
#endif |
#if EMULATE_CHIP |
@@ -43,6 +51,7 @@ enum emu_chip { |
EMULATE_ST_M25P10_RES, |
EMULATE_SST_SST25VF040_REMS, |
EMULATE_SST_SST25VF032B, |
+ EMULATE_VARIABLE_SIZE, |
}; |
static enum emu_chip emu_chip = EMULATE_NONE; |
static char *emu_persistent_image = NULL; |
@@ -66,6 +75,9 @@ int dummy_init(void) |
char *tmp = NULL; |
#if EMULATE_CHIP |
struct stat image_stat; |
+#if EMULATE_SPI_CHIP |
+ int size = -1; /* size for generic chip */ |
+#endif |
#endif |
msg_pspew("%s\n", __func__); |
@@ -110,6 +122,29 @@ int dummy_init(void) |
} |
#if EMULATE_CHIP |
+#if EMULATE_SPI_CHIP |
+ tmp = extract_programmer_param("size"); |
+ if (tmp) { |
+ int multiplier = 1; |
+ if (strlen(tmp)) { |
+ int remove_last_char = 1; |
+ switch (tmp[strlen(tmp) - 1]) { |
+ case 'k': case 'K': |
+ multiplier = 1024; |
+ break; |
+ case 'm': case 'M': |
+ multiplier = 1024 * 1024; |
+ break; |
+ default: |
+ remove_last_char = 0; |
+ break; |
+ } |
+ if (remove_last_char) tmp[strlen(tmp) - 1] = '\0'; |
+ } |
+ size = atoi(tmp) * multiplier; |
+ } |
+#endif |
+ |
tmp = extract_programmer_param("emulate"); |
if (!tmp) { |
msg_pdbg("Not emulating any flash chip.\n"); |
@@ -156,6 +191,26 @@ int dummy_init(void) |
msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI " |
"write)\n"); |
} |
+ if (!strncmp(tmp, VARIABLE_SIZE_CHIP_NAME, |
+ strlen(VARIABLE_SIZE_CHIP_NAME))) { |
+ if (size == -1) { |
+ msg_perr("%s: the size parameter is not given.\n", |
+ __func__); |
+ free(tmp); |
+ return 1; |
+ } |
+ emu_chip = EMULATE_VARIABLE_SIZE; |
+ emu_chip_size = size; |
+ 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 generic SPI flash chip (size=%d bytes)\n", |
+ emu_chip_size); |
+ } |
#endif |
if (emu_chip == EMULATE_NONE) { |
msg_perr("Invalid chip specified for emulation: %s\n", tmp); |
@@ -305,15 +360,22 @@ static int emulate_spi_chip_response(unsigned int writecnt, unsigned int readcnt |
readarr[1] = 0x44; |
break; |
case JEDEC_RDID: |
- if (emu_chip != EMULATE_SST_SST25VF032B) |
- break; |
- /* Respond with SST_SST25VF032B. */ |
- if (readcnt > 0) |
- readarr[0] = 0xbf; |
- if (readcnt > 1) |
- readarr[1] = 0x25; |
- if (readcnt > 2) |
- readarr[2] = 0x4a; |
+ if (emu_chip == EMULATE_SST_SST25VF032B) { |
+ /* Respond with SST_SST25VF032B. */ |
+ if (readcnt > 0) |
+ readarr[0] = 0xbf; |
+ if (readcnt > 1) |
+ readarr[1] = 0x25; |
+ if (readcnt > 2) |
+ readarr[2] = 0x4a; |
+ } else if (emu_chip == EMULATE_VARIABLE_SIZE) { |
+ const uint16_t man_id = VARIABLE_SIZE_MANUF_ID; |
+ const uint16_t dev_id = VARIABLE_SIZE_DEVICE_ID; |
+ if (readcnt > 0) readarr[0] = man_id >> 8; |
+ if (readcnt > 1) readarr[1] = man_id & 0xff; |
+ if (readcnt > 2) readarr[2] = dev_id >> 8; |
+ if (readcnt > 3) readarr[3] = dev_id & 0xff; |
+ } |
break; |
case JEDEC_RDSR: |
memset(readarr, 0, readcnt); |
@@ -495,6 +557,7 @@ int dummy_spi_send_command(unsigned int writecnt, unsigned int readcnt, |
case EMULATE_ST_M25P10_RES: |
case EMULATE_SST_SST25VF040_REMS: |
case EMULATE_SST_SST25VF032B: |
+ case EMULATE_VARIABLE_SIZE: |
if (emulate_spi_chip_response(writecnt, readcnt, writearr, |
readarr)) { |
msg_perr("Invalid command sent to flash chip!\n"); |
@@ -524,3 +587,47 @@ int dummy_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int le |
return spi_write_chunked(flash, buf, start, len, |
spi_write_256_chunksize); |
} |
+ |
+#if EMULATE_CHIP && EMULATE_SPI_CHIP |
+int probe_variable_size(struct flashchip *flash) |
+{ |
+ int i; |
+ |
+ /* Skip the probing if we don't emulate this chip. */ |
+ if (emu_chip != EMULATE_VARIABLE_SIZE) |
+ return 0; |
+ |
+ /* |
+ * This will break if one day flashchip becomes read-only. |
+ * Once that happens, we need to have special hacks in functions: |
+ * |
+ * erase_and_write_flash() in flashrom.c |
+ * read_flash_to_file() |
+ * handle_romentries() |
+ * ... |
+ * |
+ * Search "total_size * 1024" in code. |
+ */ |
+ if (emu_chip_size % 1024) |
+ msg_perr("%s: emu_chip_size is not multipler of 1024.\n", |
+ __func__); |
+ flash->total_size = emu_chip_size / 1024; |
+ msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__, |
+ flash->total_size); |
+ |
+ /* Update eraser count */ |
+ for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { |
+ struct block_eraser *eraser = &flash->block_erasers[i]; |
+ if (eraser->block_erase == NULL) |
+ break; |
+ |
+ eraser->eraseblocks[0].count = emu_chip_size / |
+ eraser->eraseblocks[0].size; |
+ msg_cdbg("%s: eraser.size=%d, .count=%d\n", |
+ __func__, eraser->eraseblocks[0].size, |
+ eraser->eraseblocks[0].count); |
+ } |
+ |
+ return 1; |
+} |
+#endif |