From 6de8d9a5b1a84a7ed93eda6bdb11dcd4995d110a Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Tue, 21 Aug 2018 17:49:06 +0800 Subject: futility: cmd_update: Support loading image files by -i, -e, --pd_image To specify images, we want to read them from files specified from command line: -i: AP (host) firmware image. -e: EC firmware image. --pd_image: PD firmware image (deprecated). BUG=chromium:875551 TEST=make futil; futility update -i /build/eve/firmware/image.bin tests/futility/run_test_script.sh $(pwd)/build/futility BRANCH=None Change-Id: I3c2dbe3d3ce4619aa7e044a154be3aba7ab9181c Signed-off-by: Hung-Te Lin Reviewed-on: https://chromium-review.googlesource.com/1183648 Reviewed-by: Randall Spangler --- futility/cmd_update.c | 88 ++++++++++++++++++++++++++++++++++++++++++- tests/futility/test_update.sh | 6 +++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/futility/cmd_update.c b/futility/cmd_update.c index ac1246e4..7061292c 100644 --- a/futility/cmd_update.c +++ b/futility/cmd_update.c @@ -6,16 +6,67 @@ * A reference implementation for AP (and supporting images) firmware updater. */ +#include #include #include #include #include "futility.h" +#include "host_misc.h" #include "utility.h" +/* flashrom programmers. */ +static const char * const PROG_HOST = "host", + * const PROG_EC = "ec", + * const PROG_PD = "ec:dev=1"; + +struct firmware_image { + const char *programmer; + uint32_t size; + uint8_t *data; + char *file_name; + char *ro_version, *rw_version_a, *rw_version_b; +}; + struct updater_config { + struct firmware_image image, image_current; + struct firmware_image ec_image, pd_image; }; +/* + * Loads a firmware image from file. + * Returns 0 on success, otherwise failure. + */ +static int load_image(const char *file_name, struct firmware_image *image) +{ + Debug("%s: Load image file from %s...\n", __FUNCTION__, file_name); + + if (vb2_read_file(file_name, &image->data, &image->size) != VB2_SUCCESS) + { + Error("%s: Failed to load %s\n", __FUNCTION__, file_name); + return -1; + } + + Debug("%s: Image size: %d\n", __FUNCTION__, image->size); + assert(image->data); + image->file_name = strdup(file_name); + + return 0; +} + +/* + * Frees the allocated resource from a firmware image object. + */ +static void free_image(struct firmware_image *image) +{ + free(image->data); + free(image->file_name); + free(image->ro_version); + free(image->rw_version_a); + free(image->rw_version_b); + memset(image, 0, sizeof(*image)); +} + enum updater_error_codes { UPDATE_ERR_DONE, UPDATE_ERR_UNKNOWN, @@ -35,20 +86,37 @@ static enum updater_error_codes update_firmware(struct updater_config *cfg) return UPDATE_ERR_DONE; } +/* + * Releases all loaded images in an updater configuration object. + */ +static void unload_updater_config(struct updater_config *cfg) +{ + free_image(&cfg->image); + free_image(&cfg->image_current); + free_image(&cfg->ec_image); + free_image(&cfg->pd_image); +} + /* Command line options */ static struct option const long_opts[] = { /* name has_arg *flag val */ + {"image", 1, NULL, 'i'}, + {"ec_image", 1, NULL, 'e'}, + {"pd_image", 1, NULL, 'P'}, {"help", 0, NULL, 'h'}, {NULL, 0, NULL, 0}, }; -static const char * const short_opts = "h"; +static const char * const short_opts = "hi:e:"; static void print_help(int argc, char *argv[]) { printf("\n" "Usage: " MYNAME " %s [OPTIONS]\n" "\n" + "-i, --image=FILE \tAP (host) firmware image (image.bin)\n" + "-e, --ec_image=FILE \tEC firmware image (i.e, ec.bin)\n" + " --pd_image=FILE \tPD firmware image (i.e, pd.bin)\n" "", argv[0]); } @@ -56,13 +124,28 @@ static void print_help(int argc, char *argv[]) static int do_update(int argc, char *argv[]) { int i, errorcnt = 0; - struct updater_config cfg = {}; + struct updater_config cfg = { + .image = { .programmer = PROG_HOST, }, + .image_current = { .programmer = PROG_HOST, }, + .ec_image = { .programmer = PROG_EC, }, + .pd_image = { .programmer = PROG_PD, }, + }; printf(">> Firmware updater started.\n"); opterr = 0; while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { switch (i) { + case 'i': + errorcnt += load_image(optarg, &cfg.image); + break; + case 'e': + errorcnt += load_image(optarg, &cfg.ec_image); + break; + case 'P': + errorcnt += load_image(optarg, &cfg.pd_image); + break; + case 'h': print_help(argc, argv); return !!errorcnt; @@ -97,6 +180,7 @@ static int do_update(int argc, char *argv[]) errorcnt ? "FAILED": "DONE", errorcnt ? "stopped due to error" : "exited successfully"); + unload_updater_config(&cfg); return !!errorcnt; } diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh index 7f747c61..6aa12ceb 100755 --- a/tests/futility/test_update.sh +++ b/tests/futility/test_update.sh @@ -6,8 +6,14 @@ me=${0##*/} TMP="$me.tmp" +# Test data files +LINK_BIOS="${SCRIPTDIR}/data/bios_link_mp.bin" + # Work in scratch directory cd "$OUTDIR" +set -o pipefail + # Test command execution. "${FUTILITY}" update +"${FUTILITY}" --debug update -i "${LINK_BIOS}" | grep 8388608 -- cgit v1.2.1