Anastasia Klimchuk has uploaded this change for review.

View Change

[RFC] dummyflasher: Wire variable size feature via opaque infra

Wire "variable size" feature in dummy programmer via opaque
infra. This patch fixes the broken build with CONFIG_DUMMY=no.

Dummy registers both spi and opaque structs at the same time.
The reason why this combination is needed: opaque master is needed
to reuse opaque chip and fix the building with CONFIG_DUMMY=no, at
the same time spi master is needed to reuse existing functionality
in dummy_spi_send_command.

Fixes: https://ticket.coreboot.org/issues/365

TEST=the following scenarious run successfully

Testing build

$ make clean && make CONFIG_DUMMY=no
$ flashrom -h : dummy is not in the list
$ make clean && make CONFIG_EVERYTHING=yes
$ flashrom -h : dummy is in the list

Testing "variable size" feature

$ flashrom -p dummy:size=8388608,emulate=VARIABLE_SIZE -V
$ flashrom -p dummy:size=8388608,emulate=VARIABLE_SIZE -r /tmp/dump.bin -V
$ head -c 8388608 </dev/urandom >/tmp/image.bin
$ flashrom -p dummy:image=/tmp/image.bin,size=8388608,emulate=VARIABLE_SIZE -w /tmp/dump.bin -V

Testing standard flow

$ flashrom -p dummy:emulate=W25Q128FV -V
$ flashrom -p dummy:emulate=W25Q128FV -r /tmp/dump.bin -V
$ head -c 16777216 </dev/urandom >/tmp/image.bin
$ flashrom -p dummy:image=/tmp/image.bin,emulate=W25Q128FV -w /tmp/dump.bin -V

Change-Id: I76402bfdf8b1a75489e4509fec92c9a777d0cf58
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
---
M dummyflasher.c
M flashchips.c
M include/chipdrivers.h
3 files changed, 109 insertions(+), 73 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/88/64488/1
diff --git a/dummyflasher.c b/dummyflasher.c
index 50a84d4..3dbf282 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -119,6 +119,52 @@
emu_data->spi_write_256_chunksize);
}

+static int probe_variable_size(struct flashctx *flash)
+{
+ unsigned int i;
+ const struct emu_data *emu_data = flash->mst->opaque.data;
+
+ /* Skip the probing if we don't emulate this chip. */
+ if (!emu_data || emu_data->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
+ * do_read()
+ * handle_romentries()
+ * ...
+ *
+ * Search "total_size * 1024" in code.
+ */
+ flash->chip->total_size = emu_data->emu_chip_size / 1024;
+ msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__,
+ flash->chip->total_size);
+
+ flash->chip->feature_bits = FEATURE_4BA_READ | FEATURE_4BA_WRITE;
+ flash->chip->tested = TEST_OK_PREW;
+
+ if (emu_data->erase_to_zero)
+ flash->chip->feature_bits |= FEATURE_ERASED_ZERO;
+
+ /* Update the first count of each of the block_erasers. */
+ for (i = 0; i < NUM_ERASEFUNCTIONS; i++) {
+ struct block_eraser *eraser = &flash->chip->block_erasers[i];
+ if (!eraser->block_erase)
+ break;
+
+ eraser->eraseblocks[0].count = 1;
+ eraser->eraseblocks[0].size = emu_data->emu_chip_size;
+ msg_cdbg("%s: eraser.size=%d, .count=%d\n",
+ __func__, eraser->eraseblocks[0].size,
+ eraser->eraseblocks[0].count);
+ }
+
+ return 1;
+}
+
static void dummy_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%02x\n", __func__, addr, val);
@@ -814,6 +860,13 @@
.chip_writen = dummy_chip_writen,
};

+static const struct opaque_master opaque_master_dummyflasher = {
+ .probe = probe_variable_size,
+ .read = default_spi_read,
+ .write = dummy_spi_write_256,
+ .erase = spi_block_erase_c7,
+};
+
static int init_data(struct emu_data *data, enum chipbustype *dummy_buses_supported)
{

@@ -1176,6 +1229,52 @@
return 0;
}

+static int register_double_master(const struct spi_master *s_mst,
+ const struct opaque_master *o_mst,
+ void *data)
+{
+ struct registered_master rmst = {0};
+
+ if (s_mst->shutdown) {
+ if (register_shutdown(s_mst->shutdown, data)) {
+ s_mst->shutdown(data); /* cleanup */
+ return 1;
+ }
+ }
+ if (o_mst->shutdown) {
+ if (register_shutdown(o_mst->shutdown, data)) {
+ o_mst->shutdown(data); /* cleanup */
+ return 1;
+ }
+ }
+
+ if (!s_mst->write_aai || !s_mst->write_256 || !s_mst->read || !s_mst->command ||
+ !s_mst->multicommand ||
+ ((s_mst->command == default_spi_send_command) &&
+ (s_mst->multicommand == default_spi_send_multicommand))) {
+ msg_perr("%s called with incomplete master definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+ if (!o_mst->probe || !o_mst->read || !o_mst->write || !o_mst->erase) {
+ msg_perr("%s called with incomplete master definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+
+
+ rmst.buses_supported = BUS_PROG;
+ rmst.spi = *s_mst;
+ rmst.opaque = *o_mst;
+ if (data) {
+ rmst.spi.data = data;
+ rmst.opaque.data = data;
+ }
+ return register_master(&rmst);
+}
+
static int dummy_init(void)
{
struct stat image_stat;
@@ -1241,57 +1340,19 @@
free(data);
return 1;
}
- if (dummy_buses_supported & BUS_NONSPI)
- register_par_master(&par_master_dummyflasher,
- dummy_buses_supported & BUS_NONSPI,
- data);
- if (dummy_buses_supported & BUS_SPI)
- register_spi_master(&spi_master_dummyflasher, data);

- return 0;
-}
-
-int probe_variable_size(struct flashctx *flash)
-{
- unsigned int i;
- const struct emu_data *emu_data = flash->mst->spi.data;
-
- /* Skip the probing if we don't emulate this chip. */
- if (!emu_data || emu_data->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
- * do_read()
- * handle_romentries()
- * ...
- *
- * Search "total_size * 1024" in code.
- */
- flash->chip->total_size = emu_data->emu_chip_size / 1024;
- msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__,
- flash->chip->total_size);
-
- if (emu_data->erase_to_zero)
- flash->chip->feature_bits |= FEATURE_ERASED_ZERO;
-
- /* Update the first count of each of the block_erasers. */
- for (i = 0; i < NUM_ERASEFUNCTIONS; i++) {
- struct block_eraser *eraser = &flash->chip->block_erasers[i];
- if (!eraser->block_erase)
- break;
-
- eraser->eraseblocks[0].count = 1;
- eraser->eraseblocks[0].size = emu_data->emu_chip_size;
- msg_cdbg("%s: eraser.size=%d, .count=%d\n",
- __func__, eraser->eraseblocks[0].size,
- eraser->eraseblocks[0].count);
+ if (data->emu_chip == EMULATE_VARIABLE_SIZE) {
+ register_double_master(&spi_master_dummyflasher, &opaque_master_dummyflasher, data);
+ } else {
+ if (dummy_buses_supported & BUS_NONSPI)
+ register_par_master(&par_master_dummyflasher,
+ dummy_buses_supported & BUS_NONSPI,
+ data);
+ if (dummy_buses_supported & BUS_SPI)
+ register_spi_master(&spi_master_dummyflasher, data);
}

- return 1;
+ return 0;
}

const struct programmer_entry programmer_dummy = {
diff --git a/flashchips.c b/flashchips.c
index d155b24..1136e69 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -19915,28 +19915,6 @@

{
.vendor = "Generic",
- .name = "Variable Size SPI chip",
- .bustype = BUS_SPI,
- .manufacture_id = PROGMANUF_ID,
- .model_id = PROGDEV_ID,
- .total_size = 64, /* This size is set temporarily */
- .page_size = 256,
- .feature_bits = FEATURE_4BA_READ | FEATURE_4BA_WRITE,
- .tested = TEST_OK_PREW,
- .probe = probe_variable_size,
- .block_erasers =
- {
- {
- .eraseblocks = { {64 * 1024, 1} },
- .block_erase = spi_block_erase_c7,
- }
- },
- .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/include/chipdrivers.h b/include/chipdrivers.h
index 0695993..33e2914 100644
--- a/include/chipdrivers.h
+++ b/include/chipdrivers.h
@@ -201,9 +201,6 @@
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);

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

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I76402bfdf8b1a75489e4509fec92c9a777d0cf58
Gerrit-Change-Number: 64488
Gerrit-PatchSet: 1
Gerrit-Owner: Anastasia Klimchuk <aklm@chromium.org>
Gerrit-MessageType: newchange