From 9c5cf4bf47f3f58097d5fde3a1c03cdcd0c9449f Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Thu, 30 Aug 2018 23:23:53 +0800 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/1197022 Reviewed-by: Randall Spangler --- futility/cmd_update.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'futility/cmd_update.c') 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", @@ -441,6 +443,23 @@ static int firmware_section_exists(const struct firmware_image *image, return section.data != NULL; } +/* + * 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. @@ -843,6 +862,29 @@ static int preserve_gbb(const struct firmware_image *image_from, return 0; } +/* + * 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(§ion, 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(§ion, 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. @@ -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); -- cgit v1.2.1