Namyoon Woo has uploaded this change for review.

View Change

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

To view, visit change 44879. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: Iff266e151459561b126ecfd1c47420b385be1db2
Gerrit-Change-Number: 44879
Gerrit-PatchSet: 1
Gerrit-Owner: Namyoon Woo <namyoon@google.com>
Gerrit-MessageType: newchange