summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHung-Te Lin <hungte@chromium.org>2018-08-21 18:01:57 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-08-31 05:22:45 -0700
commit8c3a895e7f7ecef9147ffd8b421626db97216d6f (patch)
treeb639a5f77df0e76f672dcb4328a2e6d37a861d5c
parent6de8d9a5b1a84a7ed93eda6bdb11dcd4995d110a (diff)
downloadvboot-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.c102
-rwxr-xr-xtests/futility/test_update.sh4
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(&section, 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