Anastasia Klimchuk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/64488 )
Change subject: [RFC] dummyflasher: Wire variable size feature via opaque infra ......................................................................
[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);