Namyoon Woo has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/44879 )
Change subject: support variable-size SPI chip for dummy programmer ......................................................................
support variable-size SPI chip for dummy programmer
This is designed for firmware updater to pack firmware image preserving some specific partitions in any size.
BUG=none TEST=ran the command line below: $ flashrom -p dummy:image=${TMP_FILE},size=16777216, \ emulate=VARIABLE_SIZE -w ${IMG} -V -f
$ flashrom -p dummy:image=${TMP_FILE},size=auto, \ emulate=VARIABLE_SIZE -w ${IMG} -V -f
Signed-off-by: Namyoon Woo namyoon@google.com Change-Id: Iff266e151459561b126ecfd1c47420b385be1db2 --- M chipdrivers.h M dummyflasher.c M flashchips.c M flashchips.h 4 files changed, 159 insertions(+), 6 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/79/44879/1
diff --git a/chipdrivers.h b/chipdrivers.h index 3c7d146..cf03811 100644 --- a/chipdrivers.h +++ b/chipdrivers.h @@ -196,6 +196,9 @@ int probe_en29lv640b(struct flashctx *flash); int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
+/* dummyflasher.c */ +int probe_variable_size(struct flashctx *flash); + /* edi.c */ int edi_chip_block_erase(struct flashctx *flash, unsigned int page, unsigned int size); int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); diff --git a/dummyflasher.c b/dummyflasher.c index e1a1d80..4024f2a 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -21,6 +21,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 @@ -33,6 +34,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 @@ -44,6 +52,7 @@ EMULATE_SST_SST25VF032B, EMULATE_MACRONIX_MX25L6436, EMULATE_WINBOND_W25Q128FV, + EMULATE_VARIABLE_SIZE, }; static enum emu_chip emu_chip = EMULATE_NONE; static char *emu_persistent_image = NULL; @@ -147,6 +156,12 @@ return 0; }
+/* Values for the 'size' parameter */ +enum { + SIZE_UNKNOWN = -1, + SIZE_AUTO = -2, +}; + int dummy_init(void) { char *bustext = NULL; @@ -154,6 +169,7 @@ unsigned int i; #if EMULATE_SPI_CHIP char *status = NULL; + int size = SIZE_UNKNOWN; /* size for VARIOUS_SIZE chip device */ #endif #if EMULATE_CHIP struct stat image_stat; @@ -272,6 +288,31 @@ free(tmp);
#if EMULATE_CHIP +#if EMULATE_SPI_CHIP + tmp = extract_programmer_param("size"); + if (tmp) { + int multiplier = 1; + if (!strcmp(tmp, "auto")) + size = SIZE_AUTO; + else 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"); @@ -343,6 +384,42 @@ emu_jedec_ce_c7_size = emu_chip_size; msg_pdbg("Emulating Winbond W25Q128FV SPI flash chip (RDID)\n"); } + + emu_persistent_image = extract_programmer_param("image"); + /* Will be freed by shutdown function if necessary. */ + if (!emu_persistent_image) { + /* Nothing else to do. */ + goto dummy_init_out; + } + + if (!strncmp(tmp, VARIABLE_SIZE_CHIP_NAME, + strlen(VARIABLE_SIZE_CHIP_NAME))) { + if (size == SIZE_UNKNOWN) { + msg_perr("%s: the size parameter is not given.\n", + __func__); + free(tmp); + return 1; + } else if (size == SIZE_AUTO) { + if (stat(emu_persistent_image, &image_stat)) { + msg_perr("%s: no image so cannot use automatic size.\n", + __func__); + free(tmp); + return 1; + } + size = image_stat.st_size; + } + 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); @@ -376,12 +453,6 @@ msg_pdbg("Filling fake flash chip with 0xff, size %i\n", emu_chip_size); memset(flashchip_contents, 0xff, emu_chip_size);
- /* Will be freed by shutdown function if necessary. */ - emu_persistent_image = extract_programmer_param("image"); - if (!emu_persistent_image) { - /* Nothing else to do. */ - goto dummy_init_out; - } /* We will silently (in default verbosity) ignore the file if it does not exist (yet) or the size does * not match the emulated chip. */ if (!stat(emu_persistent_image, &image_stat)) { @@ -610,6 +681,16 @@ if (readcnt > 2) readarr[2] = 0x18; break; + case EMULATE_VARIABLE_SIZE: + if (readcnt > 0) + readarr[0] = (VARIABLE_SIZE_MANUF_ID >> 8) & 0xff; + if (readcnt > 1) + readarr[1] = VARIABLE_SIZE_MANUF_ID & 0xff; + if (readcnt > 2) + readarr[2] = (VARIABLE_SIZE_DEVICE_ID >> 8) & 0xff; + if (readcnt > 3) + readarr[3] = VARIABLE_SIZE_DEVICE_ID & 0xff; + break; default: /* ignore */ break; } @@ -840,6 +921,7 @@ case EMULATE_SST_SST25VF032B: case EMULATE_MACRONIX_MX25L6436: case EMULATE_WINBOND_W25Q128FV: + case EMULATE_VARIABLE_SIZE: if (emulate_spi_chip_response(writecnt, readcnt, writearr, readarr)) { msg_pdbg("Invalid command sent to flash chip!\n"); @@ -862,3 +944,47 @@ return spi_write_chunked(flash, buf, start, len, spi_write_256_chunksize); } + +#if EMULATE_CHIP && EMULATE_SPI_CHIP +int probe_variable_size(struct flashctx *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 flashctx 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->chip->total_size = emu_chip_size / 1024; + msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__, + flash->chip->total_size); + + /* Update eraser count */ + for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { + struct block_eraser *eraser = &flash->chip->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 diff --git a/flashchips.c b/flashchips.c index 8b5b5cc..e99073b 100644 --- a/flashchips.c +++ b/flashchips.c @@ -18759,6 +18759,27 @@
{ .vendor = "Generic", + .name = "Variable Size SPI chip", + .bustype = BUS_SPI, + .manufacture_id = VARIABLE_SIZE_MANUF_ID, + .model_id = VARIABLE_SIZE_DEVICE_ID, + .total_size = 64, /* This size is set temporarily */ + .page_size = 256, + .tested = TEST_OK_PREW, + .probe = probe_variable_size, + .block_erasers = + { + { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = spi_block_erase_d8, + } + }, + .write = spi_chip_write_256, + .read = spi_chip_read, + }, + + { + .vendor = "Generic", .name = "unknown SPI chip (RDID)", .bustype = BUS_SPI, .manufacture_id = GENERIC_MANUF_ID, diff --git a/flashchips.h b/flashchips.h index 5b7937f..85010ea 100644 --- a/flashchips.h +++ b/flashchips.h @@ -36,6 +36,9 @@ #define PROGMANUF_ID 0xFFFE /* dummy ID for opaque chips behind a programmer */ #define PROGDEV_ID 0x01 /* dummy ID for opaque chips behind a programmer */
+#define VARIABLE_SIZE_MANUF_ID 0x3eaf +#define VARIABLE_SIZE_DEVICE_ID 0x10af + #define ALLIANCE_ID 0x52 /* Alliance Semiconductor */ #define ALLIANCE_AS29F002B 0x34 #define ALLIANCE_AS29F002T 0xB0