diff options
author | Hung-Te Lin <hungte@chromium.org> | 2022-03-09 20:58:05 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-03-18 20:43:50 +0000 |
commit | 4cba64cfb67c0215eec140caedac3450ee837de9 (patch) | |
tree | 682edf8c4fb01657d2ea8ef26fa87e6083e5542e /futility/updater_utils.c | |
parent | 8f30263bde6636a58e1d33d7fdd007c3abb4f7ce (diff) | |
download | vboot-4cba64cfb67c0215eec140caedac3450ee837de9.tar.gz |
futility: updater: refactor {write,load}_system_firmware
The 'write_system_firmware' and 'load_system_firmware' have too many
parameters that are already contained in the updater_config.
To simplify the interfaces, we should just pass the updater_config to
{write,load}_system_firmware, and merge the write_firmware_sections
(only handling emulation and deciding the diff image) to the
write_system_firmware.
Also moved the utility functions only used by *_system_firmware (for
example is_the_same_programmer and emulate_write_firmware) to the
updater_utils.c.
The emulate_write_firmware is also revised to handle a list of sections
directly (so we don't need to handle that in write_system_firmware).
BUG=None
TEST=make; build and run test.
BRANCH=None
Change-Id: I4d123d12e8057da82d6c301899472e3773f3266e
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3508121
Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
Commit-Queue: Yu-Ping Wu <yupingso@chromium.org>
Diffstat (limited to 'futility/updater_utils.c')
-rw-r--r-- | futility/updater_utils.c | 167 |
1 files changed, 123 insertions, 44 deletions
diff --git a/futility/updater_utils.c b/futility/updater_utils.c index 079f16d4..82813ca7 100644 --- a/futility/updater_utils.c +++ b/futility/updater_utils.c @@ -524,25 +524,102 @@ char *host_detect_servo(int *need_prepare_ptr) return ret; } +/* + * Returns 1 if the programmers in image1 and image2 are the same. + */ +static int is_the_same_programmer(const struct firmware_image *image1, + const struct firmware_image *image2) +{ + assert(image1 && image2); + + /* Including if both are NULL. */ + if (image1->programmer == image2->programmer) + return 1; + + /* Not the same if either one is NULL. */ + if (!image1->programmer || !image2->programmer) + return 0; + + return strcmp(image1->programmer, image2->programmer) == 0; +} + +/* + * Emulates writing a firmware image to the system. + * Returns 0 if success, non-zero if error. + */ +static int emulate_write_firmware(const char *filename, + const struct firmware_image *image, + const char * const sections[]) +{ + int i, errorcnt = 0; + struct firmware_image to_image = {0}; + + INFO("Writing from %s to %s (emu=%s).\n", + image->file_name, image->programmer, filename); + + if (load_firmware_image(&to_image, filename, NULL)) { + ERROR("Cannot load image from %s.\n", filename); + return -1; + } + + if (image->size != to_image.size) { + ERROR("Image size is different (%s:%d != %s:%d)\n", + image->file_name, image->size, to_image.file_name, + to_image.size); + errorcnt++; + goto exit; + } + + if (!sections) { + VB2_DEBUG(" - write the whole image.\n"); + memmove(to_image.data, image->data, image->size); + } + for (i = 0; sections && sections[i]; i++) { + VB2_DEBUG(" - write the section: %s.\n", sections[i]); + if (preserve_firmware_section(image, &to_image, sections[i])) { + ERROR("Failed to write the section: %s\n", sections[i]); + errorcnt++; + /* + * Exit the loop, but still write the file to reflect + * the partial changes - same as real flashrom behavior. + */ + break; + } + } + + if (vb2_write_file(filename, to_image.data, to_image.size)) { + ERROR("Failed writing to file: %s\n", filename); + errorcnt++; + goto exit; + } + +exit: + free_firmware_image(&to_image); + return errorcnt; +} /* * Loads the active system firmware image (usually from SPI flash chip). * Returns 0 if success, non-zero if error. */ -int load_system_firmware(struct firmware_image *image, - struct tempfile *tempfiles, - int retries, int verbosity) +int load_system_firmware(struct updater_config *cfg, + struct firmware_image *image) { int r, i; + 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", - image->programmer, - verbosity ? " -V" : ""); + params.image->programmer, + params.verbose > 1 ? " -V" : ""); - for (i = 1, r = -1; i <= retries && r != 0; i++) { + for (i = 1, r = -1; i <= tries && r != 0; i++, params.verbose++) { if (i > 1) - WARN("Retry reading firmware (%d/%d)...\n", i, retries); - r = flashrom_read_image(image, NULL, verbosity + i); + WARN("Retry reading firmware (%d/%d)...\n", i, tries); + r = flashrom_read_image(params.image, NULL, params.verbose); } if (!r) r = parse_firmware_image(image); @@ -555,44 +632,46 @@ int load_system_firmware(struct firmware_image *image, * FMAP section names (and ended with a NULL). * Returns 0 if success, non-zero if error. */ -int write_system_firmware(const struct firmware_image *image, - const struct firmware_image *diff_image, - const char * const sections[], - struct tempfile *tempfiles, - int do_verify, int retries, int verbosity) +int write_system_firmware(struct updater_config *cfg, + const struct firmware_image *image, + const char * const sections[]) { - int r, i, len = 0; - char *partial = NULL; - - for (i = 0; sections && sections[i]; i++) - len += strlen(sections[i]) + strlen(" -i "); - if (len) { - partial = (char *)malloc(len + 1); - if (!partial) { - ERROR("Failed to allocate a string buffer.\n"); - return -1; - } - partial[0] = '\0'; - for (i = 0; sections[i]; i++) { - strcat(partial, " -i "); - strcat(partial, sections[i]); - } - assert(strlen(partial) == len); - } - - INFO("flashrom -w <IMAGE> -p %s%s%s%s%s\n", - image->programmer, - diff_image ? " --flash-contents <DIFF_IMAGE>" : "", - do_verify ? "" : " --noverify", - verbosity > 1 ? " -V" : "", - partial ? partial : ""); - free(partial); - - for (i = 1, r = -1; i <= retries && r != 0; i++) { + int r = 0, i; + const int tries = 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg); + struct flashrom_params params = {0}; + struct firmware_image *flash_contents = NULL; + + if (cfg->emulation) + return emulate_write_firmware(cfg->emulation, image, sections); + + if (cfg->use_diff_image && cfg->image_current.data && + is_the_same_programmer(&cfg->image_current, image)) + flash_contents = &cfg->image_current; + + params.image = (struct firmware_image *)image; + params.flash_contents = flash_contents; + params.regions = sections; + params.noverify = !cfg->do_verify; + 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" : ""); + + for (i = 1, r = -1; i <= tries && r != 0; i++, params.verbose++) { if (i > 1) - WARN("Retry writing firmware (%d/%d)...\n", i, retries); - r = flashrom_write_image(image, sections, diff_image, do_verify, - verbosity + i); + 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. |