summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHung-Te Lin <hungte@chromium.org>2019-02-28 23:13:54 +0800
committerchrome-bot <chrome-bot@chromium.org>2019-03-05 12:58:42 -0800
commitedf6a8889aaabfc6446957f897f98c7a7e622298 (patch)
tree526a3cb0c4fed66adbf99ac727946f99e38cb616
parent638b79822725ae41072a3342b796d333c1f0f23e (diff)
downloadvboot-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>
-rw-r--r--futility/updater.c96
-rw-r--r--futility/updater.h7
-rw-r--r--host/lib/include/fmap.h8
3 files changed, 79 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";
diff --git a/host/lib/include/fmap.h b/host/lib/include/fmap.h
index d6c33c65..02f97c2d 100644
--- a/host/lib/include/fmap.h
+++ b/host/lib/include/fmap.h
@@ -27,6 +27,14 @@ typedef struct _FmapHeader {
uint16_t fmap_nareas;
} __attribute__((packed)) FmapHeader;
+enum fmap_flags {
+ FMAP_AREA_STATIC = 1 << 0,
+ FMAP_AREA_COMPRESSED = 1 << 1,
+ FMAP_AREA_RO = 1 << 2,
+ /* Should be preserved on update or rollback. */
+ FMAP_AREA_PRESERVE = 1 << 3,
+};
+
typedef struct _FmapAreaHeader {
uint32_t area_offset;
uint32_t area_size;