| 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
|
|
|