summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHung-Te Lin <hungte@chromium.org>2018-08-30 23:23:53 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-09-05 21:04:17 -0700
commit9c5cf4bf47f3f58097d5fde3a1c03cdcd0c9449f (patch)
tree56c042c676b168baa0a7ddef49e905d2e020024e
parent90ee96f5c76a78aad8fddbd8eb7f9c6035d69996 (diff)
downloadvboot-9c5cf4bf47f3f58097d5fde3a1c03cdcd0c9449f.tar.gz
futility: cmd_update: Preserve sections blocked by management engine
On Intel platforms, when management engine is not in manufacturing mode the SI_DESC will be read only and SI_ME can't be accessed by CPU. For RW-FULL mode when we want to reflash whole firmware, flashrom will skip SI_ME but it'll still try to update SI_DESC if the content looks different, which would make all firmware update to fail when a new image is pushed with different SI_DESC contents. As a result, we have to preserve and skip SI_DESC changes when ME is locked. BUG=chromium:875551 TEST=make futil; tests/futility/run_test_scripts.sh $(pwd)/build/futility BRANCH=None Change-Id: I834405ad519dcb7ccd44073addfd63e844b74168 Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1197022 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--futility/cmd_update.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/futility/cmd_update.c b/futility/cmd_update.c
index 3996901e..3e44cd65 100644
--- a/futility/cmd_update.c
+++ b/futility/cmd_update.c
@@ -40,7 +40,9 @@ static const char * const FMAP_RO_FRID = "RO_FRID",
* const FMAP_RW_FWID_B = "RW_FWID_B",
* const FMAP_RW_SHARED = "RW_SHARED",
* const FMAP_RW_NVRAM = "RW_NVRAM",
- * const FMAP_RW_LEGACY = "RW_LEGACY";
+ * const FMAP_RW_LEGACY = "RW_LEGACY",
+ * const FMAP_SI_DESC = "SI_DESC",
+ * const FMAP_SI_ME = "SI_ME";
/* System environment values. */
static const char * const FWACT_A = "A",
@@ -442,6 +444,23 @@ static int firmware_section_exists(const struct firmware_image *image,
}
/*
+ * Checks if the section is filled with given character.
+ * If section size is 0, return 0. If section is not empty, return non-zero if
+ * the section is filled with same character c, otherwise 0.
+ */
+static int section_is_filled_with(const struct firmware_section *section,
+ uint8_t c)
+{
+ uint32_t i;
+ if (!section->size)
+ return 0;
+ for (i = 0; i < section->size; i++)
+ if (section->data[i] != c)
+ return 0;
+ return 1;
+}
+
+/*
* Loads the firmware information from an FMAP section in loaded firmware image.
* The section should only contain ASCIIZ string as firmware version.
* If successful, the return value is zero and *version points to a newly
@@ -844,6 +863,29 @@ 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,
+ struct firmware_image *image_to)
+{
+ struct firmware_section section;
+
+ find_firmware_section(&section, image_from, FMAP_SI_ME);
+ if (!section.data) {
+ Debug("%s: Skipped because no section %s\n", __FUNCTION__,
+ FMAP_SI_ME);
+ return 0;
+ }
+ if (section_is_filled_with(&section, 0xFF)) {
+ Debug("%s: ME is probably locked - preserving %s.\n",
+ __FUNCTION__, FMAP_SI_DESC);
+ return preserve_firmware_section(
+ image_from, image_to, FMAP_SI_DESC);
+ }
+ return 0;
+}
+
+/*
* Preserves the critical sections from the current (active) firmware.
* Currently only GBB, VPD (RO+RW) and NVRAM sections are preserved.
* Returns 0 if success, non-zero if error.
@@ -853,6 +895,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_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);