diff options
-rw-r--r-- | futility/cmd_update.c | 6 | ||||
-rw-r--r-- | futility/updater.c | 23 | ||||
-rw-r--r-- | futility/updater.h | 11 | ||||
-rw-r--r-- | futility/updater_manifest.c | 52 | ||||
-rwxr-xr-x | tests/futility/test_update.sh | 17 |
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(¤t_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(¤t_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}" \ |