Anastasia Klimchuk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/87341?usp=email )
Change subject: libflashrom: Add probing v2 which can find all mathching chips ......................................................................
libflashrom: Add probing v2 which can find all mathching chips
Probing v2 can (if requested) go through all flashchips and find all the matching chip definitions. This is the way cli behaves, so cli becomes a client of probing v2.
Previously cli and libflashrom had different probing logic, and different code in different source files.
TODO here is to create double set of tests. In the first version of the patch all probing tests are force-redirected to probe_v2, just to quickly get test coverage.
Testing from the cli: ./flashrom -p dummy:emulate=W25Q128FV -r dump.rom ./flashrom -p dummy:emulate=MX25L6436 -r dump.rom ./flashrom -p dummy:emulate=MX25L6436 -c "MX25L6405" -r dump.rom ./flashrom -p dummy:emulate=SST25VF032B -E ./flashrom -p dummy:emulate=S25FL128L -r dump.rom
Change-Id: Idfcf377a8071e22028ba98515f08495ed2a6e9f0 Signed-off-by: Anastasia Klimchuk aklm@flashrom.org --- M cli_classic.c M include/libflashrom.h M libflashrom.c M libflashrom.map M tests/lifecycle.c 5 files changed, 101 insertions(+), 25 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/41/87341/1
diff --git a/cli_classic.c b/cli_classic.c index 3e5dab9..798c218 100644 --- a/cli_classic.c +++ b/cli_classic.c @@ -1050,7 +1050,7 @@ struct flashctx flashes[8] = {{0}}; struct flashctx *fill_flash; char *tempstr = NULL; - int startchip = -1, chipcount = 0; + int startchip = -1; int i, j; int ret = 0;
@@ -1209,26 +1209,21 @@ msg_pdbg("The following protocols are supported: %s.\n", tempstr ? tempstr : "?"); free(tempstr);
- for (j = 0; j < registered_master_count; j++) { - startchip = 0; - while (chipcount < (int)ARRAY_SIZE(flashes)) { - startchip = probe_flash(®istered_masters[j], startchip, &flashes[chipcount], 0, options.chip_to_probe); - if (startchip == -1) - break; - chipcount++; - startchip++; - } - } + const char *all_matched_names[20]; + unsigned int all_matched_count;
- if (chipcount > 1) { + flashrom_flash_probe_v2(&flashes[0], all_matched_names, &all_matched_count, + NULL, options.chip_to_probe); + + if (all_matched_count > 1) { msg_cinfo("Multiple flash chip definitions match the detected chip(s): "%s"", flashes[0].chip->name); - for (i = 1; i < chipcount; i++) - msg_cinfo(", "%s"", flashes[i].chip->name); + for (unsigned int ind = 1; ind < all_matched_count; ind++) + msg_cinfo(", "%s"", all_matched_names[ind]); msg_cinfo("\nPlease specify which chip definition to use with the -c <chipname> option.\n"); ret = 1; goto out_shutdown; - } else if (!chipcount) { + } else if (!all_matched_count) { msg_cinfo("No EEPROM/flash device found.\n"); if (!options.force || !options.chip_to_probe) { msg_cinfo("Note: flashrom can never write if the flash chip isn't found " @@ -1535,9 +1530,9 @@ out_shutdown: flashrom_programmer_shutdown(NULL); out: - for (i = 0; i < chipcount; i++) { - flashrom_layout_release(flashes[i].default_layout); - free(flashes[i].chip); + for (unsigned int ind = 0; ind < all_matched_count; ind++) { + flashrom_layout_release(flashes[ind].default_layout); + free(flashes[ind].chip); }
free_options(&options); diff --git a/include/libflashrom.h b/include/libflashrom.h index f30ad6b..19e5b97 100644 --- a/include/libflashrom.h +++ b/include/libflashrom.h @@ -279,6 +279,42 @@ * or 1 on any other error. */ int flashrom_flash_probe(struct flashrom_flashctx **flashctx, const struct flashrom_programmer *flashprog, const char *chip_name); + + +/** + * @brief Probe for a flash chip, v2 + * + * Probes for a flash chip and returns a flash context, that can be used + * later with flash chip and @ref flashrom-ops "image operations", if + * exactly one matching chip is found. + * + * Returns the list of names for all chips that matched, and the count of + * how many chips matched. + * + * @param[out] flashctx Points to a struct flashrom_flashctx + * that will be set if exactly one chip is found. *flashctx + * has to be freed by the caller with @ref flashrom_flash_release. + * @param[out] all_matched_names list of all names of chips that were probed + * successfully during probing process, or empty + if no chips found. + * @param[out] all_matched_count the total number of chip that were probed + successfully during probing process, or 0 + if no chips found. + * @param[in] flashprog The flash programmer used to access the chip, + currently unused. + * @param[in] chip_name Name of a chip to probe for, or NULL to probe for + * all known chips. + * @return 0 on success, + * 3 if multiple chips were found, + * 2 if no chip was found, + * or 1 on any other error. + */ +int flashrom_flash_probe_v2(struct flashrom_flashctx *flashctx, + const char **all_matched_names, + unsigned int *all_matched_count, + const struct flashrom_programmer *flashprog, + const char *chip_name); + /** * @brief Returns the size of the specified flash chip in bytes. * diff --git a/libflashrom.c b/libflashrom.c index d6bd098..c72c7a7 100644 --- a/libflashrom.c +++ b/libflashrom.c @@ -329,8 +329,6 @@ return programmer_shutdown(); }
-/* TODO: flashrom_programmer_capabilities()? */ - int flashrom_flash_probe(struct flashrom_flashctx **const flashctx, const struct flashrom_programmer *const flashprog, const char *const chip_name) @@ -363,6 +361,47 @@ return ret; }
+int flashrom_flash_probe_v2(struct flashrom_flashctx *flashctx, + const char **all_matched_names, + unsigned int *all_matched_count, + const struct flashrom_programmer *flashprog, + const char *chip_name) +{ + int startchip; + int ret = 2; // return code 2 means chip not found, start with this + + *all_matched_count = 0; + + for (int i = 0; i < registered_master_count; i++) { + startchip = 0; + while (*all_matched_count < flashchips_size) { + struct flashrom_flashctx second_flashctx = { 0, }; // used for second and more matches + struct flashctx *context_for_probing = (*all_matched_count > 0) ? &second_flashctx : flashctx; + startchip = probe_flash(®istered_masters[i], startchip, context_for_probing, 0, chip_name); + + if (startchip == -1) + break; + + all_matched_names[*all_matched_count] = context_for_probing->chip->name; + (*all_matched_count)++; + startchip++; + ret = 0; + + if (*all_matched_count > 1) { + ret = 3; + /* It's used for the second and subsequent probing. */ + flashrom_layout_release(second_flashctx.default_layout); + free(second_flashctx.chip); + } + } + } + + all_matched_names[*all_matched_count] = 0; + + return ret; +} + + size_t flashrom_flash_getsize(const struct flashrom_flashctx *const flashctx) { return flashctx->chip->total_size * 1024; diff --git a/libflashrom.map b/libflashrom.map index fc6724a..2b757e5 100644 --- a/libflashrom.map +++ b/libflashrom.map @@ -6,6 +6,7 @@ flashrom_flash_erase; flashrom_flash_getsize; flashrom_flash_probe; + flashrom_flash_probe_v2; flashrom_flash_release; flashrom_image_read; flashrom_image_verify; diff --git a/tests/lifecycle.c b/tests/lifecycle.c index 95c4249..f5509c8 100644 --- a/tests/lifecycle.c +++ b/tests/lifecycle.c @@ -19,13 +19,18 @@ struct flashrom_programmer *flashprog, const char *const chip_name) { - struct flashrom_flashctx *flashctx; + struct flashrom_flashctx flashctx = { 0 }; + unsigned int all_matched_count; + const char *all_matched_names[20];
- printf("Testing flashrom_flash_probe for programmer=%s, chip=%s ... \n", prog->name, chip_name); - assert_int_equal(0, flashrom_flash_probe(&flashctx, flashprog, chip_name)); - printf("... flashrom_flash_probe for programmer=%s successful\n", prog->name); + printf("Testing flashrom_flash_probe_v2 for programmer=%s, chip=%s ... \n", prog->name, chip_name); + assert_int_equal(0, flashrom_flash_probe_v2(&flashctx, all_matched_names, &all_matched_count, + flashprog, chip_name)); + printf("... flashrom_flash_probe_v2 for programmer=%s successful\n", prog->name);
- flashrom_flash_release(flashctx); /* cleanup */ + /* cleanup */ + flashrom_layout_release(flashctx.default_layout); + free(flashctx.chip); }
static void run_lifecycle(void **state, const struct io_mock *io, const struct programmer_entry *prog,