diff options
author | Hung-Te Lin <hungte@chromium.org> | 2022-03-08 20:35:38 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-03-18 20:43:52 +0000 |
commit | 67d21be99c7ce35bc0580c4fd4e062da90bd1cbb (patch) | |
tree | f6414ee80a59d7502a58db69d1b248d037041807 | |
parent | 4cba64cfb67c0215eec140caedac3450ee837de9 (diff) | |
download | vboot-67d21be99c7ce35bc0580c4fd4e062da90bd1cbb.tar.gz |
futility: updater: support external flashrom
The libflashrom is still different from the real flashrom program.
To easily debug and compare the execution results (especially for
devices under development), we want to allow the updater to
switch between the libflashrom and the external flashrom.
The real switch (either a quirk or a command line argument) will
be added in a follow up change.
BUG=None
TEST=build and run test
BRANCH=None
Change-Id: I3f3226fd555dc9e7c40838cd1474e0d018b27ccc
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3500339
Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
Commit-Queue: Yu-Ping Wu <yupingso@chromium.org>
-rw-r--r-- | futility/updater_utils.c | 178 |
1 files changed, 156 insertions, 22 deletions
diff --git a/futility/updater_utils.c b/futility/updater_utils.c index 82813ca7..a581c8f6 100644 --- a/futility/updater_utils.c +++ b/futility/updater_utils.c @@ -543,6 +543,72 @@ static int is_the_same_programmer(const struct firmware_image *image1, return strcmp(image1->programmer, image2->programmer) == 0; } +enum flash_command { + FLASH_READ = 0, + FLASH_WRITE, +}; + +/* Converts the flashrom_params to an equivalent flashrom command. */ +static char *get_flashrom_command(enum flash_command flash_cmd, + struct flashrom_params *params, + const char *image_name, + const char *contents_name) +{ + int i, len = 0; + char *partial = NULL; + char *cmd = NULL; + + if (!image_name) + image_name = "<IMAGE>"; + if (!contents_name) + contents_name = "<OLD-IMAGE>"; + + for (i = 0; params->regions && params->regions[i]; i++) + len += strlen(params->regions[i]) + strlen(" -i "); + + if (len) { + partial = (char *)malloc(len + 1); + if (!partial) { + ERROR("Failed to allocate a string buffer.\n"); + return NULL; + } + + partial[0] = '\0'; + for (i = 0; params->regions[i]; i++) { + strcat(partial, " -i "); + strcat(partial, params->regions[i]); + } + assert(strlen(partial) == len); + } + + switch (flash_cmd) { + case FLASH_READ: + ASPRINTF(&cmd, "flashrom -r %s -p %s%s%s", + image_name, + params->image->programmer, + params->verbose > 1 ? " -V" : "", + partial ? partial : ""); + break; + + case FLASH_WRITE: + ASPRINTF(&cmd, "flashrom -w %s -p %s%s%s%s%s%s", + image_name, + params->image->programmer, + params->flash_contents ? " --flash-contents " : "", + params->flash_contents ? contents_name : "", + params->noverify ? " --noverify" : "", + params->verbose > 1 ? " -V" : "", + partial ? partial : ""); + break; + + default: + ERROR("Unknown command: %d.\n", flash_cmd); + break; + } + free(partial); + return cmd; +} + /* * Emulates writing a firmware image to the system. * Returns 0 if success, non-zero if error. @@ -598,6 +664,86 @@ exit: return errorcnt; } +static int external_flashrom(enum flash_command flash_cmd, + struct flashrom_params *params, + struct tempfile *tempfiles) +{ + int r; + char *cmd; + const char *image_name = NULL, *contents_name = NULL; + + switch (flash_cmd) { + case FLASH_READ: + image_name = create_temp_file(tempfiles); + break; + + case FLASH_WRITE: + image_name = get_firmware_image_temp_file( + params->image, tempfiles); + if (params->flash_contents) + contents_name = get_firmware_image_temp_file( + params->flash_contents, tempfiles); + break; + + default: + ERROR("Unknown command: %d\n", flash_cmd); + return -1; + } + + cmd = get_flashrom_command(flash_cmd, params, image_name, + contents_name); + if (!cmd) + return -1; + + VB2_DEBUG(cmd); + r = system(cmd); + free(cmd); + if (r) + return r; + + switch (flash_cmd) { + case FLASH_READ: + r = load_firmware_image(params->image, image_name, NULL); + break; + default: + break; + } + + return r; +} + +static int read_flash(struct flashrom_params *params, + struct updater_config *cfg) +{ + /* TODO(hungte): Add a quirk to allow switching to external flashrom. */ + if (0) + return external_flashrom(FLASH_READ, params, &cfg->tempfiles); + + return flashrom_read_image(params->image, NULL, params->verbose); +} + +static int write_flash(struct flashrom_params *params, + struct updater_config *cfg) +{ + int r; + + /* TODO(hungte): Add a quirk to allow switching to external flashrom. */ + if (0) + return external_flashrom(FLASH_WRITE, params, &cfg->tempfiles); + + r = flashrom_write_image(params->image, + params->regions, + params->flash_contents, + !params->noverify, + params->verbose); + /* + * Force a newline to flush stdout in case if + * flashrom_write_image left some messages in the buffer. + */ + fprintf(stdout, "\n"); + return r; +} + /* * Loads the active system firmware image (usually from SPI flash chip). * Returns 0 if success, non-zero if error. @@ -606,20 +752,21 @@ int load_system_firmware(struct updater_config *cfg, struct firmware_image *image) { int r, i; + char *cmd; const int tries = 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg); struct flashrom_params params = {0}; params.image = image; params.verbose = cfg->verbosity + 1; /* libflashrom verbose 1 = WARN. */ - INFO("flashrom -r <IMAGE> -p %s%s\n", - params.image->programmer, - params.verbose > 1 ? " -V" : ""); + cmd = get_flashrom_command(FLASH_READ, ¶ms, NULL, NULL); + INFO("%s\n", cmd); + free(cmd); for (i = 1, r = -1; i <= tries && r != 0; i++, params.verbose++) { if (i > 1) WARN("Retry reading firmware (%d/%d)...\n", i, tries); - r = flashrom_read_image(params.image, NULL, params.verbose); + r = read_flash(¶ms, cfg); } if (!r) r = parse_firmware_image(image); @@ -637,6 +784,7 @@ int write_system_firmware(struct updater_config *cfg, const char * const sections[]) { int r = 0, i; + char *cmd; const int tries = 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg); struct flashrom_params params = {0}; struct firmware_image *flash_contents = NULL; @@ -655,28 +803,14 @@ int write_system_firmware(struct updater_config *cfg, params.noverify_all = true; params.verbose = cfg->verbosity + 1; /* libflashrom verbose 1 = WARN. */ - INFO("flashrom -w <IMAGE> -p %s%s%s%s%s%s%s\n", - params.image->programmer, - params.flash_contents ? " --flash-contents" : "", - params.flash_contents ? "<OLD-IMAGE>" : "", - params.regions ? " -i <REGIONS>" : "", - params.noverify ? " --noverify" : "", - params.noverify_all ? " --noverify-all" : "", - params.verbose > 1 ? " -V" : ""); + cmd = get_flashrom_command(FLASH_WRITE, ¶ms, NULL, NULL); + INFO("%s\n", cmd); + free(cmd); for (i = 1, r = -1; i <= tries && r != 0; i++, params.verbose++) { if (i > 1) WARN("Retry writing firmware (%d/%d)...\n", i, tries); - r = flashrom_write_image(params.image, - params.regions, - params.flash_contents, - !params.noverify, - params.verbose); - /* - * Force a newline to flush stdout in case if - * flashrom_write_image left some messages in the buffer. - */ - fprintf(stdout, "\n"); + r = write_flash(¶ms, cfg); } return r; } |