diff options
author | Hung-Te Lin <hungte@chromium.org> | 2018-08-31 15:43:02 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-10 01:13:20 -0700 |
commit | f5223d920707f24724390019c14c2f759d51f71a (patch) | |
tree | b70b168cd9bbfc508d7f5c6abb9b9934fe794d18 | |
parent | 8c564a18969b14f7a86ffd93089bba9f37cb53a5 (diff) | |
download | vboot-f5223d920707f24724390019c14c2f759d51f71a.tar.gz |
futility: cmd_update: Add quirk 'unlock_me_for_update'
On recent Intel platforms, flashing to SI_ME may get corrupted due to ME
execution in parallel. If we lock SI_ME immediately (by writing the new
SI_DESC), the device may fail to boot due to ME execution failure.
As a result, a quirk is added so the firmware updater will never lock
SI_ME. The Flash Master values are always unlocked when updating SI_ME,
and after system reboot, a board-postinst script should check ME status
and reflash SI_DESC only if SI_ME looks all good.
BUG=chromium:875551
TEST=make futil; tests/futility/run_test_scripts.sh $(pwd)/build/futility
BRANCH=None
Change-Id: I584aa373797e2b4c2608f07aac21c16cdb34a5c4
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1198807
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | futility/cmd_update.c | 50 | ||||
-rwxr-xr-x | tests/futility/test_update.sh | 28 |
2 files changed, 65 insertions, 13 deletions
diff --git a/futility/cmd_update.c b/futility/cmd_update.c index 1551627c..b4f57f71 100644 --- a/futility/cmd_update.c +++ b/futility/cmd_update.c @@ -123,6 +123,7 @@ struct quirk_entry { enum quirk_types { QUIRK_ENLARGE_IMAGE, + QUIRK_UNLOCK_ME_FOR_UPDATE, QUIRK_MAX, }; @@ -1040,7 +1041,8 @@ static int preserve_gbb(const struct firmware_image *image_from, /* * Preserves the regions locked by Intel management engine. */ -static int preserve_management_engine(const struct firmware_image *image_from, +static int preserve_management_engine(struct updater_config *cfg, + const struct firmware_image *image_from, struct firmware_image *image_to) { struct firmware_section section; @@ -1055,7 +1057,8 @@ static int preserve_management_engine(const struct firmware_image *image_from, return preserve_firmware_section( image_from, image_to, FMAP_SI_DESC); } - return 0; + + return try_apply_quirk(QUIRK_UNLOCK_ME_FOR_UPDATE, cfg); } /* @@ -1068,7 +1071,7 @@ static int preserve_images(struct updater_config *cfg) int errcnt = 0; struct firmware_image *from = &cfg->image_current, *to = &cfg->image; errcnt += preserve_gbb(from, to); - errcnt += preserve_management_engine(from, to); + errcnt += preserve_management_engine(cfg, from, to); errcnt += preserve_firmware_section(from, to, FMAP_RO_VPD); errcnt += preserve_firmware_section(from, to, FMAP_RW_VPD); errcnt += preserve_firmware_section(from, to, FMAP_RW_NVRAM); @@ -1442,6 +1445,40 @@ static int quirk_enlarge_image(struct updater_config *cfg) return reload_image(tmp_path, image_to); } +/* + * Quirk to unlock a firmware image with SI_ME (management engine) when updating + * so the system has a chance to make sure SI_ME won't be corrupted on next boot + * before locking the Flash Master values in SI_DESC. + * Returns 0 on success, otherwise failure. + */ +static int quirk_unlock_me_for_update(struct updater_config *cfg) +{ + struct firmware_section section; + struct firmware_image *image_to = &cfg->image; + const int flash_master_offset = 128; + const uint8_t flash_master[] = { + 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff + }; + + find_firmware_section(§ion, image_to, FMAP_SI_DESC); + if (section.size < flash_master_offset + ARRAY_SIZE(flash_master)) + return 0; + if (memcmp(section.data + flash_master_offset, flash_master, + ARRAY_SIZE(flash_master)) == 0) { + DEBUG("Target ME not locked."); + return 0; + } + /* + * b/35568719: We should only update with unlocked ME and let + * board-postinst lock it. + */ + printf("%s: Changed Flash Master Values to unlocked.\n", __FUNCTION__); + memcpy(section.data + flash_master_offset, flash_master, + ARRAY_SIZE(flash_master)); + return 0; +} + enum updater_error_codes { UPDATE_ERR_DONE, UPDATE_ERR_NEED_RO_UPDATE, @@ -1766,7 +1803,12 @@ static int do_update(int argc, char *argv[]) .help="Enlarge firmware image by flash size.", .apply=quirk_enlarge_image, }, - + [QUIRK_UNLOCK_ME_FOR_UPDATE] = { + .name="unlock_me_for_update", + .help="b/35568719: Only lock management engine " + "by board-postinst.", + .apply=quirk_unlock_me_for_update, + }, }, }; diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh index 4748f10a..6902a0cf 100755 --- a/tests/futility/test_update.sh +++ b/tests/futility/test_update.sh @@ -49,24 +49,26 @@ cp -f ${PEPPY_BIOS} ${FROM_IMAGE} patch_file() { local file="$1" local section="$2" - local data="$3" + local section_offset="$3" + local data="$4" # NAME OFFSET SIZE local fmap_info="$(${FUTILITY} dump_fmap -p ${file} ${section})" - local offset="$(echo "${fmap_info}" | sed 's/^[^ ]* //; s/ [^ ]*$//')" + local base="$(echo "${fmap_info}" | sed 's/^[^ ]* //; s/ [^ ]*$//')" + local offset=$((base + section_offset)) echo "offset: ${offset}" - echo -n "${data}" | dd of="${file}" bs=1 seek="${offset}" conv=notrunc + printf "${data}" | dd of="${file}" bs=1 seek="${offset}" conv=notrunc } # PEPPY and LINK have different platform element ("Google_Link" and # "Google_Peppy") in firmware ID so we want to hack them by changing # "Google_" to "Google.". -patch_file ${TO_IMAGE} RW_FWID_A Google. -patch_file ${TO_IMAGE} RW_FWID_B Google. -patch_file ${TO_IMAGE} RO_FRID Google. -patch_file ${FROM_IMAGE} RW_FWID_A Google. -patch_file ${FROM_IMAGE} RW_FWID_B Google. -patch_file ${FROM_IMAGE} RO_FRID Google. +patch_file ${TO_IMAGE} RW_FWID_A 0 Google. +patch_file ${TO_IMAGE} RW_FWID_B 0 Google. +patch_file ${TO_IMAGE} RO_FRID 0 Google. +patch_file ${FROM_IMAGE} RW_FWID_A 0 Google. +patch_file ${FROM_IMAGE} RW_FWID_B 0 Google. +patch_file ${FROM_IMAGE} RO_FRID 0 Google. unpack_image() { local folder="${TMP}.$1" @@ -112,6 +114,9 @@ cp -f "${FROM_IMAGE}" "${TMP}.expected.legacy" RW_LEGACY:${TMP}.to/RW_LEGACY cp -f "${TMP}.expected.full" "${TMP}.expected.large" dd if=/dev/zero bs=8388608 count=1 | tr '\000' '\377' >>"${TMP}.expected.large" +cp -f "${TMP}.expected.full" "${TMP}.expected.me_unlocked" +patch_file "${TMP}.expected.me_unlocked" SI_DESC 128 \ + "\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff" test_update() { local test_name="$1" @@ -228,3 +233,8 @@ test_update "Full update (wrong size)" \ test_update "Full update (--quirks enlarge_image)" \ "${FROM_IMAGE}.large" "${TMP}.expected.large" --quirks enlarge_image \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 + +test_update "Full update (--quirks unlock_me_for_update)" \ + "${FROM_IMAGE}" "${TMP}.expected.me_unlocked" \ + --quirks unlock_me_for_update \ + -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 |