summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam McNally <sammc@chromium.org>2022-10-18 20:38:52 +1100
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-12-12 17:16:09 +0000
commitff29ee63ed52b698afcaa4c2619d7163322a3785 (patch)
tree98996e7bb92f18a696b3e26245f4a89b4f427e03
parent65a1a07908c28abe07237a4bd57bfc5af6f64942 (diff)
downloadvboot-ff29ee63ed52b698afcaa4c2619d7163322a3785.tar.gz
futility: updater: Detect the model via FRID for non-host programmers
When updating with --archive and a non-host programmer (and thus no reliable crosid to discover the appropriate firmware manifest key), and no explicit --model parameter is passed, try to detect the model by matching the FRID of the current firmware with one of the host firmware images in the archive. Add a --detect-model-only flag to perform the same matching, but report the detected model name and exit. This can be used in combination with the manifest to automatically select an appropriate EC image to pass to flash_ec. BUG=b:253966060 TEST=futility update -a firmware.tar.bz2 --servo BRANCH=None Signed-off-by: Sam McNally <sammc@chromium.org> Change-Id: I25fa0f109d0d8052179b220251d4720438b93bc4 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3965584 Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
-rw-r--r--futility/cmd_update.c6
-rw-r--r--futility/updater.c23
-rw-r--r--futility/updater.h11
-rw-r--r--futility/updater_manifest.c52
-rwxr-xr-xtests/futility/test_update.sh17
5 files changed, 108 insertions, 1 deletions
diff --git a/futility/cmd_update.c b/futility/cmd_update.c
index 57c54029..d501aca2 100644
--- a/futility/cmd_update.c
+++ b/futility/cmd_update.c
@@ -19,6 +19,7 @@ enum {
OPT_DUMMY = 0x100,
OPT_CCD,
+ OPT_DETECT_MODEL_ONLY,
OPT_EMULATE,
OPT_FACTORY,
OPT_FAST,
@@ -58,6 +59,7 @@ static struct option const long_opts[] = {
{"ccd", 0, NULL, OPT_CCD},
{"servo", 0, NULL, OPT_SERVO},
{"servo_port", 1, NULL, OPT_SERVO_PORT},
+ {"detect-model-only", 0, NULL, OPT_DETECT_MODEL_ONLY},
{"emulate", 1, NULL, OPT_EMULATE},
{"factory", 0, NULL, OPT_FACTORY},
{"fast", 0, NULL, OPT_FAST},
@@ -133,6 +135,7 @@ static void print_help(int argc, char *argv[])
" --host_only \tUpdate only AP (host) firmware\n"
" --emulate=FILE \tEmulate system firmware using file\n"
" --model=MODEL \tOverride system model for images\n"
+ " --detect-model-only\tDetect model by reading the FRID and exit\n"
" --gbb_flags=FLAG\tOverride new GBB flags\n"
" --ccd \tDo fast,force,wp=0,p=raiden_debug_spi\n"
" --servo \tFlash using Servo (v2, v4, micro, ...)\n"
@@ -226,6 +229,9 @@ static int do_update(int argc, char *argv[])
case OPT_MODEL:
args.model = optarg;
break;
+ case OPT_DETECT_MODEL_ONLY:
+ args.detect_model_only = true;
+ break;
case OPT_SIGNATURE:
args.signature_id = optarg;
break;
diff --git a/futility/updater.c b/futility/updater.c
index 941ef125..5b3eed61 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -1423,10 +1423,20 @@ static int updater_setup_archive(
return errorcnt;
}
- model = manifest_find_model(manifest, arg->model);
+ if (cfg->detect_model)
+ model = manifest_detect_model_from_frid(cfg, manifest);
+ else
+ model = manifest_find_model(manifest, arg->model);
+
if (!model)
return ++errorcnt;
+ if (arg->detect_model_only) {
+ puts(model->name);
+ /* No additional error. */
+ return errorcnt;
+ }
+
/* Load images now so we can get quirks in custom label checks. */
errorcnt += updater_load_images(
cfg, arg, model->image, model->ec_image,
@@ -1504,6 +1514,14 @@ int updater_setup_config(struct updater_config *cfg,
}
*do_update = 0;
}
+ if (arg->detect_model_only) {
+ if (!arg->archive) {
+ ERROR("--detect-model-only needs --archive.\n");
+ return ++errorcnt;
+ }
+ cfg->detect_model = true;
+ *do_update = 0;
+ }
/* Setup update mode. */
if (arg->try_update)
@@ -1545,6 +1563,9 @@ int updater_setup_config(struct updater_config *cfg,
cfg->original_programmer = arg->programmer;
VB2_DEBUG("AP (host) programmer changed to %s.\n",
arg->programmer);
+
+ if (arg->archive && !arg->model)
+ cfg->detect_model = true;
}
if (arg->emulation) {
VB2_DEBUG("Using file %s for emulation.\n", arg->emulation);
diff --git a/futility/updater.h b/futility/updater.h
index 3f77c332..4af2ccaf 100644
--- a/futility/updater.h
+++ b/futility/updater.h
@@ -88,6 +88,7 @@ struct updater_config {
const char *original_programmer;
int override_gbb_flags;
uint32_t gbb_flags;
+ bool detect_model;
};
struct updater_config_arguments {
@@ -103,6 +104,7 @@ struct updater_config_arguments {
int verbosity;
int override_gbb_flags;
uint32_t gbb_flags;
+ bool detect_model_only;
};
struct patch_config {
@@ -295,6 +297,15 @@ const struct model_config *manifest_find_model(const struct manifest *manifest,
const char *model_name);
/*
+ * Finds the first existing model_config from manifest that matches current
+ * system by reading RO_FRID from the existing host firmware.
+ * Returns a model_config from manifest, or NULL if not found.
+ */
+const struct model_config *
+manifest_detect_model_from_frid(struct updater_config *cfg,
+ struct manifest *manifest);
+
+/*
* Applies custom label information to an existing model configuration.
* Collects signature ID information from either parameter signature_id or
* image file (via VPD) and updates model.patches for key files.
diff --git a/futility/updater_manifest.c b/futility/updater_manifest.c
index 339bfd8a..ca338c40 100644
--- a/futility/updater_manifest.c
+++ b/futility/updater_manifest.c
@@ -706,6 +706,58 @@ const struct model_config *manifest_find_model(const struct manifest *manifest,
return model;
}
+const struct model_config *
+manifest_detect_model_from_frid(struct updater_config *cfg,
+ struct manifest *manifest)
+{
+ const struct model_config *result = NULL;
+ struct firmware_image current_ro_frid = {0};
+ current_ro_frid.programmer = cfg->image_current.programmer;
+ int error = flashrom_read_region(&current_ro_frid, FMAP_RO_FRID,
+ cfg->verbosity + 1);
+ const char *from_dot;
+ int len;
+
+ if (error)
+ return NULL;
+
+ current_ro_frid.data[current_ro_frid.size - 1] = '\0';
+ from_dot = strchr((const char *)current_ro_frid.data, '.');
+ if (!from_dot) {
+ VB2_DEBUG("Missing dot (%s)\n",
+ (const char *)current_ro_frid.data);
+ goto cleanup;
+ }
+ len = from_dot - (const char *)current_ro_frid.data + 1;
+
+ for (int i = 0; i < manifest->num && !result; ++i) {
+ struct model_config *m = &manifest->models[i];
+ struct firmware_image image = {0};
+
+ if (load_firmware_image(&image, m->image, manifest->archive))
+ return NULL;
+
+ VB2_DEBUG("Comparing '%*.*s' with '%*.*s'\n", len, len,
+ (const char *)current_ro_frid.data, len, len,
+ image.ro_version);
+ if (strncasecmp((const char *)current_ro_frid.data,
+ image.ro_version, len) == 0) {
+ result = m;
+ }
+ free_firmware_image(&image);
+ }
+ if (result) {
+ INFO("Detected model: '%s'\n", result->name);
+ } else {
+ ERROR("Unsupported FRID: '%*.*s'.\n", len - 1, len - 1,
+ (const char *)current_ro_frid.data);
+ }
+cleanup:
+ free_firmware_image(&current_ro_frid);
+
+ return result;
+}
+
/*
* Determines the signature ID to use for custom label.
* Returns the signature ID for looking up rootkey and vblock files.
diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh
index 41dd3608..9724659d 100755
--- a/tests/futility/test_update.sh
+++ b/tests/futility/test_update.sh
@@ -33,6 +33,7 @@ test "$(test_quirks " enlarge_image, enlarge_image=2")" = \
# Test data files
LINK_BIOS="${SCRIPT_DIR}/futility/data/bios_link_mp.bin"
PEPPY_BIOS="${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin"
+VOXEL_BIOS="${SCRIPT_DIR}/futility/data/bios_voxel_dev.bin"
RO_VPD_BLOB="${SCRIPT_DIR}/futility/data/ro_vpd.bin"
# Work in scratch directory
@@ -475,8 +476,10 @@ cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.customtip-cl"
cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.customtip-cl"
cp -f "${PEPPY_BIOS}" "${FROM_IMAGE}.ap"
cp -f "${LINK_BIOS}" "${FROM_IMAGE}.al"
+cp -f "${VOXEL_BIOS}" "${FROM_IMAGE}.av"
patch_file "${FROM_IMAGE}.ap" FW_MAIN_A 0 "corrupted"
patch_file "${FROM_IMAGE}.al" FW_MAIN_A 0 "corrupted"
+patch_file "${FROM_IMAGE}.av" FW_MAIN_A 0 "corrupted"
test_update "Full update (--archive, model=link)" \
"${FROM_IMAGE}.al" "${LINK_BIOS}" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=link
@@ -491,6 +494,20 @@ test_update "Full update (--archive, model=customtip, signature_id=CL)" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=customtip \
--signature_id=customtip-cl
+test_update "Full update (--archive, detect-model)" \
+ "${FROM_IMAGE}.ap" "${PEPPY_BIOS}" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 \
+ --programmer raiden_debug_spi:target=AP
+test_update "Full update (--archive, detect-model, unsupported FRID)" \
+ "${FROM_IMAGE}.av" "!Unsupported FRID: 'Google_Voxel'" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 \
+ --programmer raiden_debug_spi:target=AP
+
+echo "*** Test Item: Detect model (--archive, --detect-model-only)"
+"${FUTILITY}" update -a "${A}" \
+ --emulate "${FROM_IMAGE}.ap" --detect-model-only >"${TMP}.model.out"
+cmp "${TMP}.model.out" <(echo peppy)
+
CL_TAG="cl" PATH="${A}/bin:${PATH}" \
test_update "Full update (-a, model=customtip, fake VPD)" \
"${FROM_IMAGE}.al" "${LINK_BIOS}" \