summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHung-Te Lin <hungte@chromium.org>2018-08-31 15:43:02 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-09-10 01:13:20 -0700
commitf5223d920707f24724390019c14c2f759d51f71a (patch)
treeb70b168cd9bbfc508d7f5c6abb9b9934fe794d18
parent8c564a18969b14f7a86ffd93089bba9f37cb53a5 (diff)
downloadvboot-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.c50
-rwxr-xr-xtests/futility/test_update.sh28
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(&section, 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