diff options
author | Hung-Te Lin <hungte@chromium.org> | 2019-02-28 23:13:54 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-03-05 12:58:42 -0800 |
commit | edf6a8889aaabfc6446957f897f98c7a7e622298 (patch) | |
tree | 526a3cb0c4fed66adbf99ac727946f99e38cb616 /futility | |
parent | 638b79822725ae41072a3342b796d333c1f0f23e (diff) | |
download | vboot-edf6a8889aaabfc6446957f897f98c7a7e622298.tar.gz |
futility: updater: Preserve all sections with FMAP_AREA_PRESERVE set
Many projects started their initial builds without knowing that some
sections must be preserved when being updated. This may be solved by
adding section name to 'preserved' list in firmware updater (for
instance, CL:1239797), or include that section as sub area of
{RO,RW}_PRESERVE.
However, there are problems in both solutions. For example, installing
an older image will run old updater, which will not preserve the new
names. Also, if there are multiple sections must be preserved (and not
contiguous - see CL:1493629) there will be problems. Additionally,
changing FMAP layout usually causes more problems.
As a result, adding the description in FMAP area would be the better
idea. A new FMAP_AREA_PRESERVE suggests firmware updater to preserve
a section if possible. In Coreboot, this can be easily set in *.fmd
using flag (PRESERVE). See https://review.coreboot.org/31709 for
example.
BUG=chromium:936768
TEST=make futil; tests/futility/run_test_scripts.sh $(pwd)/build/futility
BRANCH=None
Change-Id: Ie56f65dd418faa97ffb78b1acff613e7d7e268b8
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1495054
Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'futility')
-rw-r--r-- | futility/updater.c | 96 | ||||
-rw-r--r-- | futility/updater.h | 7 |
2 files changed, 71 insertions, 32 deletions
diff --git a/futility/updater.c b/futility/updater.c index 42ae7707..a7179dac 100644 --- a/futility/updater.c +++ b/futility/updater.c @@ -15,6 +15,7 @@ #include "2rsa.h" #include "crossystem.h" +#include "fmap.h" #include "futility.h" #include "host_misc.h" #include "updater.h" @@ -927,13 +928,13 @@ int preserve_firmware_section(const struct firmware_image *image_from, find_firmware_section(&from, image_from, section_name); find_firmware_section(&to, image_to, section_name); if (!from.data || !to.data) { - DEBUG("Cannot find section %s: from=%p, to=%p", section_name, - from.data, to.data); + DEBUG("Cannot find section %.*s: from=%p, to=%p", FMAP_NAMELEN, + section_name, from.data, to.data); return -1; } if (from.size > to.size) { - WARN("%s: Section %s is truncated after updated.", - __FUNCTION__, section_name); + WARN("%s: Section %.*s is truncated after updated.", + __FUNCTION__, FMAP_NAMELEN, section_name); } /* Use memmove in case if we need to deal with sections that overlap. */ memmove(to.data, from.data, Min(from.size, to.size)); @@ -1015,22 +1016,50 @@ static int preserve_management_engine(struct updater_config *cfg, return try_apply_quirk(QUIRK_UNLOCK_ME_FOR_UPDATE, cfg); } +/* Preserve firmware sections by FMAP area flags. */ +static int preserve_fmap_sections(struct firmware_image *from, + struct firmware_image *to, + int *count) +{ + int i, errcnt = 0; + FmapHeader *fmap = to->fmap_header; + FmapAreaHeader *ah = (FmapAreaHeader*)( + (uint8_t *)fmap + sizeof(FmapHeader)); + *count = 0; + + for (i = 0; i < fmap->fmap_nareas; i++, ah++) { + if (!(ah->area_flags & FMAP_AREA_PRESERVE)) + continue; + /* Warning: area_name 'may' not end with NUL. */ + if (!firmware_section_exists(from, ah->area_name)) { + DEBUG("FMAP area does not exist in source: %.*s", + FMAP_NAMELEN, ah->area_name); + continue; + } + DEBUG("Preserve FMAP area: %.*s", FMAP_NAMELEN, ah->area_name); + errcnt += preserve_firmware_section(from, to, ah->area_name); + (*count)++; + } + + return errcnt; +} + /* - * Preserves the critical sections from the current (active) firmware. - * Currently preserved sections: GBB (HWID and flags), x86 ME, {RO,RW}_PRESERVE, - * {RO,RW}_VPD, RW_NVRAM. - * Returns 0 if success, non-zero if error. + * Preserve old images without "preserve" information in FMAP. + * We have to use the legacy hard-coded list of names. */ -static int preserve_images(struct updater_config *cfg) +static int preserve_known_sections(struct firmware_image *from, + struct firmware_image *to) { int errcnt = 0, i; - struct firmware_image *from = &cfg->image_current, *to = &cfg->image; - const char * const optional_sections[] = { - FMAP_RO_PRESERVE, - FMAP_RW_PRESERVE, - FMAP_RW_NVRAM, - FMAP_RW_ELOG, - FMAP_RW_SMMSTORE, + const char * const names[] = { + "RO_PRESERVE", + "RW_PRESERVE", + "RO_VPD", + "RW_VPD", + "SMMSTORE", + "RW_NVRAM", + "RW_ELOG", /* * TODO(hungte): b/116326638: Remove RO_FSG after the migration * is finished. @@ -1041,23 +1070,40 @@ static int preserve_images(struct updater_config *cfg) * both migrated to the new FMAP based preserve method. */ "SI_GBE", - "SI_PDR" + "SI_PDR", }; - errcnt += preserve_gbb(from, to, !cfg->factory_update); - 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); - for (i = 0; i < ARRAY_SIZE(optional_sections); i++) { - if (!firmware_section_exists(from, optional_sections[i])) + for (i = 0; i < ARRAY_SIZE(names); i++) { + if (!firmware_section_exists(from, names[i])) continue; - errcnt += preserve_firmware_section( - from, to, optional_sections[i]); + DEBUG("Preserve firmware section: %s", names[i]); + errcnt += preserve_firmware_section(from, to, names[i]); } return errcnt; } /* + * Preserves the critical sections from the current (active) firmware. + * Currently preserved sections: GBB (HWID and flags), x86 ME, and any firmware + * sections with FMAP_AREA_PRESERVE flag set (or a list of known names). + * Returns 0 if success, non-zero if error. + */ +static int preserve_images(struct updater_config *cfg) +{ + int errcnt = 0, found; + struct firmware_image *from = &cfg->image_current, *to = &cfg->image; + + errcnt += preserve_gbb(from, to, !cfg->factory_update); + errcnt += preserve_management_engine(cfg, from, to); + errcnt += preserve_fmap_sections(from, to, &found); + + if (!found) + errcnt += preserve_known_sections(from, to); + + return errcnt; +} + +/* * Compares if two sections have same size and data. * Returns 0 if given sections are the same, otherwise non-zero. */ diff --git a/futility/updater.h b/futility/updater.h index c75493ae..65f0dd42 100644 --- a/futility/updater.h +++ b/futility/updater.h @@ -28,9 +28,6 @@ extern int debugging_enabled; static const char * const FMAP_RO_FRID = "RO_FRID", * const FMAP_RO_SECTION = "RO_SECTION", * const FMAP_RO_GBB = "GBB", - * const FMAP_RO_PRESERVE = "RO_PRESERVE", - * const FMAP_RO_VPD = "RO_VPD", - * const FMAP_RW_VPD = "RW_VPD", * const FMAP_RW_VBLOCK_A = "VBLOCK_A", * const FMAP_RW_VBLOCK_B = "VBLOCK_B", * const FMAP_RW_SECTION_A = "RW_SECTION_A", @@ -39,11 +36,7 @@ static const char * const FMAP_RO_FRID = "RO_FRID", * const FMAP_RW_FWID_A = "RW_FWID_A", * const FMAP_RW_FWID_B = "RW_FWID_B", * const FMAP_RW_SHARED = "RW_SHARED", - * const FMAP_RW_NVRAM = "RW_NVRAM", - * const FMAP_RW_ELOG = "RW_ELOG", - * const FMAP_RW_PRESERVE = "RW_PRESERVE", * const FMAP_RW_LEGACY = "RW_LEGACY", - * const FMAP_RW_SMMSTORE = "SMMSTORE", * const FMAP_SI_DESC = "SI_DESC", * const FMAP_SI_ME = "SI_ME"; |