diff options
author | Hung-Te Lin <hungte@chromium.org> | 2018-08-21 18:01:57 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-08-31 05:22:45 -0700 |
commit | 8c3a895e7f7ecef9147ffd8b421626db97216d6f (patch) | |
tree | b639a5f77df0e76f672dcb4328a2e6d37a861d5c | |
parent | 6de8d9a5b1a84a7ed93eda6bdb11dcd4995d110a (diff) | |
download | vboot-8c3a895e7f7ecef9147ffd8b421626db97216d6f.tar.gz |
futility: cmd_update: Process FMAP and parse image version
Add `find_firmware_section` and `firmware_section_exists` utility
functions to manipulate FMAP based sections easily. It is used by
parsing of image version strings, which helps indicating the firmware
versions going to be updated.
BUG=chromium:875551
TEST=make futil; futility update -i /build/eve/firmware/image.bin
tests/futility/run_test_scripts.sh $(pwd)/build/futility
BRANCH=None
Change-Id: I458fa8c31c45dbbd29614c3d6ccd586e46a3ed0b
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1183649
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | futility/cmd_update.c | 102 | ||||
-rwxr-xr-x | tests/futility/test_update.sh | 4 |
2 files changed, 105 insertions, 1 deletions
diff --git a/futility/cmd_update.c b/futility/cmd_update.c index 7061292c..5c724731 100644 --- a/futility/cmd_update.c +++ b/futility/cmd_update.c @@ -11,10 +11,17 @@ #include <stdio.h> #include <stdlib.h> +#include "fmap.h" #include "futility.h" #include "host_misc.h" #include "utility.h" +/* FMAP section names. */ +static const char * const FMAP_RO_FRID = "RO_FRID", + * const FMAP_RW_FWID = "RW_FWID", + * const FMAP_RW_FWID_A = "RW_FWID_A", + * const FMAP_RW_FWID_B = "RW_FWID_B"; + /* flashrom programmers. */ static const char * const PROG_HOST = "host", * const PROG_EC = "ec", @@ -26,6 +33,12 @@ struct firmware_image { uint8_t *data; char *file_name; char *ro_version, *rw_version_a, *rw_version_b; + FmapHeader *fmap_header; +}; + +struct firmware_section { + uint8_t *data; + size_t size; }; struct updater_config { @@ -34,6 +47,62 @@ struct updater_config { }; /* + * 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. + */ +static int find_firmware_section(struct firmware_section *section, + const struct firmware_image *image, + const char *section_name) +{ + FmapAreaHeader *fah = NULL; + uint8_t *ptr; + + section->data = NULL; + section->size = 0; + ptr = fmap_find_by_name( + image->data, image->size, image->fmap_header, + section_name, &fah); + if (!ptr) + return -1; + section->data = (uint8_t *)ptr; + section->size = fah->area_size; + return 0; +} + +/* + * Returns true if the given FMAP section exists in the firmware image. + */ +static int firmware_section_exists(const struct firmware_image *image, + const char *section_name) +{ + struct firmware_section section; + find_firmware_section(§ion, image, section_name); + return section.data != NULL; +} + +/* + * Loads the firmware information from an FMAP section in loaded firmware image. + * The section should only contain ASCIIZ string as firmware version. + * If successful, the return value is zero and *version points to a newly + * allocated string as firmware version (caller must free it); otherwise + * failure. + */ +static int load_firmware_version(struct firmware_image *image, + const char *section_name, + char **version) +{ + struct firmware_section fwid; + find_firmware_section(&fwid, image, section_name); + if (fwid.size) { + *version = strndup((const char*)fwid.data, fwid.size); + return 0; + } + *version = strdup(""); + return -1; +} + +/* * Loads a firmware image from file. * Returns 0 on success, otherwise failure. */ @@ -51,6 +120,29 @@ static int load_image(const char *file_name, struct firmware_image *image) assert(image->data); image->file_name = strdup(file_name); + image->fmap_header = fmap_find(image->data, image->size); + if (!image->fmap_header) { + Error("Invalid image file (missing FMAP): %s\n", file_name); + return -1; + } + + if (!firmware_section_exists(image, FMAP_RO_FRID)) { + Error("Does not look like VBoot firmware image: %s", file_name); + return -1; + } + + load_firmware_version(image, FMAP_RO_FRID, &image->ro_version); + if (firmware_section_exists(image, FMAP_RW_FWID_A)) { + char **a = &image->rw_version_a, **b = &image->rw_version_b; + load_firmware_version(image, FMAP_RW_FWID_A, a); + load_firmware_version(image, FMAP_RW_FWID_B, b); + } else if (firmware_section_exists(image, FMAP_RW_FWID)) { + char **a = &image->rw_version_a, **b = &image->rw_version_b; + load_firmware_version(image, FMAP_RW_FWID, a); + load_firmware_version(image, FMAP_RW_FWID, b); + } else { + Error("Unsupported VBoot firmware (no RW ID): %s", file_name); + } return 0; } @@ -69,11 +161,13 @@ static void free_image(struct firmware_image *image) enum updater_error_codes { UPDATE_ERR_DONE, + UPDATE_ERR_NO_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_UNKNOWN] = "Unknown error.", }; @@ -83,6 +177,14 @@ 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; + if (!image_to->data) + return UPDATE_ERR_NO_IMAGE; + + printf(">> Target image: %s (RO:%s, RW/A:%s, RW/B:%s).\n", + image_to->file_name, image_to->ro_version, + image_to->rw_version_a, image_to->rw_version_b); + return UPDATE_ERR_DONE; } diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh index 6aa12ceb..c7ade51a 100755 --- a/tests/futility/test_update.sh +++ b/tests/futility/test_update.sh @@ -8,6 +8,7 @@ TMP="$me.tmp" # Test data files LINK_BIOS="${SCRIPTDIR}/data/bios_link_mp.bin" +LINK_VERSION="Google_Link.2695.1.133" # Work in scratch directory cd "$OUTDIR" @@ -15,5 +16,6 @@ cd "$OUTDIR" set -o pipefail # Test command execution. -"${FUTILITY}" update +"${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 |