From d35d0566f16122195b210c365ee8e831a2544f61 Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Sat, 22 Sep 2018 12:06:59 +0800 Subject: futility: update: Refactor 'emulation' (--emulate). In order to support overriding programmer, we need to clean up the 'emulation' first. The firmware_image.emulation was implemented as a flashrom emulate programmer so we can emulate with calling flashrom in the very beginning; and then replaced by native FMAP library because calling flashrom add too much dependency and much slower in unit tests. As a result, we can replace emulation to be the real file name being emulated, and only keep that in the global config. BRANCH=None BUG=b:116326638 TEST=make futil; tests/futility/run_test_scripts.sh $(pwd)/build/futility Change-Id: I5423e64d66be03a09ccfde29ecc3f4ef114c9453 Signed-off-by: Hung-Te Lin Reviewed-on: https://chromium-review.googlesource.com/1239816 Commit-Ready: ChromeOS CL Exonerator Bot Reviewed-by: Randall Spangler --- futility/cmd_update.c | 101 ++++++++++++-------------------------------------- 1 file changed, 23 insertions(+), 78 deletions(-) diff --git a/futility/cmd_update.c b/futility/cmd_update.c index 632296c2..6bc68524 100644 --- a/futility/cmd_update.c +++ b/futility/cmd_update.c @@ -61,7 +61,6 @@ static const char * const FWACT_A = "A", /* flashrom programmers. */ static const char * const PROG_HOST = "host", - * const PROG_EMULATE = "dummy:emulate", * const PROG_EC = "ec", * const PROG_PD = "ec:dev=1"; @@ -89,7 +88,6 @@ enum flashrom_ops { struct firmware_image { const char *programmer; - char *emulation; uint32_t size; uint8_t *data; char *file_name; @@ -141,7 +139,7 @@ struct updater_config { int try_update; int force_update; int legacy_update; - int emulate; + char *emulation; }; struct tempfile { @@ -331,10 +329,6 @@ static int host_flashrom(enum flashrom_ops op, const char *image_path, section_name = ""; } - if (strncmp(programmer, PROG_EMULATE, strlen(PROG_EMULATE)) == 0) { - ignore_lock = "--ignore-lock"; - } - switch (op) { case FLASHROM_READ: op_cmd = "-r"; @@ -704,27 +698,6 @@ static int load_image(const char *file_name, struct firmware_image *image) return 0; } -/* - * Loads and emulates system firmware by an image file. - * This will set a emulation programmer in image->emulation so flashrom - * can access the file as system firmware storage. - * Returns 0 if success, non-zero if error. - */ -static int emulate_system_image(const char *file_name, - struct firmware_image *image) -{ - if (load_image(file_name, image)) - return -1; - - if (asprintf(&image->emulation, - "%s=VARIABLE_SIZE,image=%s,size=%u", - PROG_EMULATE, file_name, image->size) < 0) { - ERROR("Failed to allocate programmer buffer: %s.", file_name); - return -1; - } - return 0; -} - /* * Loads the active system firmware image (usually from SPI flash chip). * Returns 0 if success, non-zero if error. @@ -751,31 +724,8 @@ static void free_image(struct firmware_image *image) free(image->ro_version); free(image->rw_version_a); free(image->rw_version_b); - free(image->emulation); memset(image, 0, sizeof(*image)); } -/* - * Reloads a firmware image from file. - * Keeps special configuration like emulation. - * Returns 0 on success, otherwise failure. - */ -static int reload_image(const char *file_name, struct firmware_image *image) -{ - char *emulation = image->emulation; - int r; - - /* - * All values except emulation and programmer will be re-constructed - * in load_image. `programmer` is not touched in free_image so we only - * need to keep `emulation`. - */ - image->emulation = NULL; - free_image(image); - r = load_image(file_name, image); - if (r == 0) - image->emulation = emulation; - return r; -} /* * Decides which target in RW firmware to manipulate. @@ -831,7 +781,7 @@ static int set_try_cookies(struct updater_config *cfg, const char *target, return -1; } - if (cfg->emulate) { + if (cfg->emulation) { printf("(emulation) Setting try_next to %s, try_count to %d.\n", slot, tries); return 0; @@ -919,29 +869,19 @@ static int write_firmware(struct updater_config *cfg, const char *section_name) { const char *tmp_file = create_temp_file(); - const char *programmer = cfg->emulate ? image->emulation : - image->programmer; + const char *programmer = image->programmer; if (!tmp_file) return -1; - if (cfg->emulate) { - printf("%s: (emulation) %s %s from %s to %s.\n", + if (cfg->emulation) { + printf("%s: (emulation) Writing %s from %s to %s (emu=%s).\n", __FUNCTION__, - image->emulation ? "Writing" : "Skipped writing", section_name ? section_name : "whole image", - image->file_name, programmer); + image->file_name, programmer, cfg->emulation); - if (!image->emulation) - return 0; - - /* - * TODO(hungte): Extract the real target from image->emulation, - * and allow to emulate writing with flashrom. - */ return emulate_write_firmware( - cfg->image_current.file_name, image, - section_name); + cfg->emulation, image, section_name); } if (vb2_write_file(tmp_file, image->data, image->size) != VB2_SUCCESS) { @@ -1505,7 +1445,8 @@ static int quirk_enlarge_image(struct updater_config *cfg) while (to_write-- > 0) fputc('\xff', fp); fclose(fp); - return reload_image(tmp_path, image_to); + free_image(image_to); + return load_image(tmp_path, image_to); } /* @@ -1646,7 +1587,7 @@ static enum updater_error_codes update_try_rw_firmware( return UPDATE_ERR_SET_COOKIES; } else { /* Clear trial cookies for vboot1. */ - if (!is_vboot2 && !cfg->emulate) + if (!is_vboot2 && !cfg->emulation) VbSetSystemPropertyInt("fwb_tries", 0); } @@ -1820,7 +1761,8 @@ static void unload_updater_config(struct updater_config *cfg) free_image(&cfg->image_current); free_image(&cfg->ec_image); free_image(&cfg->pd_image); - cfg->emulate = 0; + free(cfg->emulation); + cfg->emulation = NULL; } /* Command line options */ @@ -1961,14 +1903,9 @@ static int do_update(int argc, char *argv[]) override_system_property(SYS_PROP_WP_SW, &cfg, r); break; case 'E': - cfg.emulate = 1; - errorcnt += !!emulate_system_image( - optarg, &cfg.image_current); - /* Both image and image_current need emulation. */ - if (!errorcnt) { - cfg.image.emulation = strdup( - cfg.image_current.emulation); - } + free(cfg.emulation); + cfg.emulation = strdup(optarg); + DEBUG("Emulate with file: %s", cfg.emulation); break; case 'F': cfg.force_update = 1; @@ -2006,6 +1943,14 @@ static int do_update(int argc, char *argv[]) errorcnt++; Error("Unexpected arguments.\n"); } + if (cfg.emulation) { + if (cfg.ec_image.data || cfg.pd_image.data) { + errorcnt++; + Error("EC/PD images are not supported in emulation.\n"); + } + /* We only support emulating AP firmware. */ + errorcnt += load_image(cfg.emulation, &cfg.image_current); + } if (check_wp_disabled && is_write_protection_enabled(&cfg)) { errorcnt++; Error("Factory mode needs WP disabled.\n"); -- cgit v1.2.1