diff options
author | Hung-Te Lin <hungte@chromium.org> | 2018-08-21 18:34:04 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-08-31 05:22:46 -0700 |
commit | 09c1c22dff11a588e9f27c57c4574930f2e168dd (patch) | |
tree | 782d7f4f3b680001084906ab071c8a74be7b36c3 | |
parent | 8c3a895e7f7ecef9147ffd8b421626db97216d6f (diff) | |
download | vboot-09c1c22dff11a588e9f27c57c4574930f2e168dd.tar.gz |
futility: cmd_update: Access system firmware using external flashrom
To manipulate the firmware contents on device, we need to access the
flash chipset (usually via SPI) on system. The `host_flashrom` provides
a way to call external program "flashrom" for reading and writing
firmware. So the `update_firmware` can now load "system current
firmware" using flashrom.
Note in the future we may want to statically link the flashrom as
library so there won't be external dependency.
BUG=chromium:875551
TEST=make futil; futility update -i IMAGE
tests/futility/run_test_scripts.sh $(pwd)/build/futility
BRANCH=None
Change-Id: I52f2d4fe4fe4dd660f762a5a75e3367820717e19
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1183650
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | futility/cmd_update.c | 98 | ||||
-rwxr-xr-x | tests/futility/test_update.sh | 6 |
2 files changed, 100 insertions, 4 deletions
diff --git a/futility/cmd_update.c b/futility/cmd_update.c index 5c724731..0ddaa01b 100644 --- a/futility/cmd_update.c +++ b/futility/cmd_update.c @@ -16,6 +16,8 @@ #include "host_misc.h" #include "utility.h" +#define RETURN_ON_FAILURE(x) do {int r = (x); if (r) return r;} while (0); + /* FMAP section names. */ static const char * const FMAP_RO_FRID = "RO_FRID", * const FMAP_RW_FWID = "RW_FWID", @@ -27,6 +29,11 @@ static const char * const PROG_HOST = "host", * const PROG_EC = "ec", * const PROG_PD = "ec:dev=1"; +enum flashrom_ops { + FLASHROM_READ, + FLASHROM_WRITE, +}; + struct firmware_image { const char *programmer; uint32_t size; @@ -47,6 +54,64 @@ struct updater_config { }; /* + * A helper function to invoke flashrom(8) command. + * Returns 0 if success, non-zero if error. + */ +static int host_flashrom(enum flashrom_ops op, const char *image_path, + const char *programmer, int verbose, + const char *section_name) +{ + char *command; + const char *op_cmd, *dash_i = "-i", *postfix = ""; + int r; + + if (debugging_enabled) + verbose = 1; + + if (!verbose) + postfix = " >/dev/null 2>&1"; + + if (!section_name || !*section_name) { + dash_i = ""; + section_name = ""; + } + + switch (op) { + case FLASHROM_READ: + op_cmd = "-r"; + assert(image_path); + break; + + case FLASHROM_WRITE: + op_cmd = "-w"; + assert(image_path); + break; + + default: + assert(0); + return -1; + } + + /* TODO(hungte) In future we should link with flashrom directly. */ + r = asprintf(&command, "flashrom %s %s -p %s %s %s %s", op_cmd, + image_path, programmer, dash_i, section_name, postfix); + + if (r == -1) { + /* `command` will be not available. */ + Error("%s: Cannot allocate memory for command to execute.\n", + __FUNCTION__); + return -1; + } + + if (verbose) + printf("Executing: %s\n", command); + + r = system(command); + free(command); + return r; +} + +/* * Finds a firmware section by given name in the firmware image. * If successful, return zero and *section argument contains the address and * size of the section; otherwise failure. @@ -147,6 +212,21 @@ static int load_image(const char *file_name, struct firmware_image *image) } /* + * Loads the active system firmware image (usually from SPI flash chip). + * Returns 0 if success, non-zero if error. + */ +static int load_system_image(struct updater_config *cfg, + struct firmware_image *image) +{ + /* TODO(hungte) replace by mkstemp */ + const char *tmp_file = "/tmp/.fwupdate.read"; + + RETURN_ON_FAILURE(host_flashrom( + FLASHROM_READ, tmp_file, image->programmer, 0, NULL)); + return load_image(tmp_file, image); +} + +/* * Frees the allocated resource from a firmware image object. */ static void free_image(struct firmware_image *image) @@ -162,12 +242,14 @@ static void free_image(struct firmware_image *image) enum updater_error_codes { UPDATE_ERR_DONE, UPDATE_ERR_NO_IMAGE, + UPDATE_ERR_SYSTEM_IMAGE, UPDATE_ERR_UNKNOWN, }; static const char * const updater_error_messages[] = { [UPDATE_ERR_DONE] = "Done (no error)", [UPDATE_ERR_NO_IMAGE] = "No image to update; try specify with -i.", + [UPDATE_ERR_SYSTEM_IMAGE] = "Cannot load system active firmware.", [UPDATE_ERR_UNKNOWN] = "Unknown error.", }; @@ -177,7 +259,8 @@ static const char * const updater_error_messages[] = { */ static enum updater_error_codes update_firmware(struct updater_config *cfg) { - struct firmware_image *image_to = &cfg->image; + struct firmware_image *image_from = &cfg->image_current, + *image_to = &cfg->image; if (!image_to->data) return UPDATE_ERR_NO_IMAGE; @@ -185,6 +268,19 @@ static enum updater_error_codes update_firmware(struct updater_config *cfg) image_to->file_name, image_to->ro_version, image_to->rw_version_a, image_to->rw_version_b); + if (!image_from->data) { + /* + * TODO(hungte) Read only RO_SECTION, VBLOCK_A, VBLOCK_B, + * RO_VPD, RW_VPD, RW_NVRAM, RW_LEGACY. + */ + printf("Loading current system firmware...\n"); + if (load_system_image(cfg, image_from) != 0) + return UPDATE_ERR_SYSTEM_IMAGE; + } + printf(">> Current system: %s (RO:%s, RW/A:%s, RW/B:%s).\n", + image_from->file_name, image_from->ro_version, + image_from->rw_version_a, image_from->rw_version_b); + return UPDATE_ERR_DONE; } diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh index c7ade51a..aaf46904 100755 --- a/tests/futility/test_update.sh +++ b/tests/futility/test_update.sh @@ -16,6 +16,6 @@ cd "$OUTDIR" set -o pipefail # Test command execution. -"${FUTILITY}" update -i "${LINK_BIOS}" | - grep "RO:${LINK_VERSION}, RW/A:${LINK_VERSION}, RW/B:${LINK_VERSION}" -"${FUTILITY}" --debug update -i "${LINK_BIOS}" | grep 8388608 + +# The updater is now currently always loading system firmware using flashrom(8) +# and can't be tested until an emulation interface is implemented. |