summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJae Hoon Kim <kimjae@chromium.org>2022-05-23 16:21:33 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-05-26 15:48:16 +0000
commit6dba972b6ab1246864d3af0eaa3effcda29407d1 (patch)
tree9e189ab7e3ff1d922dcdf22ad92178ab5fd16133
parentff1f3b91c31706d1e73a82ec928fd9bdd080f96f (diff)
downloadvboot-6dba972b6ab1246864d3af0eaa3effcda29407d1.tar.gz
futility: [deferredupdates] Defer setting firmware cookies
This is the firmware part of go/deferredupdates. During autoupdates, it's required to defer firmware cookies (a.k.a. slot switching) to not try the updated RW firmware. Instead it is deferred for the values to be updated at a later time, when the actual update should be applied. Since there is not a clear communication method between futility and postinstall+autoupdater, it'll be the case that STATUS will be used as the IPC for postinstall+autoupdater to determine when to update firmware cookies w/ a UUID. ``` // autoupdate localhost ~ # chromeos-firmwareupdate --mode=autoupdate --wp=1 Machine Model: gimble Write Protect: HW=0 SW=0 Last Boot Version: RO=Google_Gimble.14498.0.0 ACT/B=Google_Gimble.14498.0.0 Firmware Updater: RO=Google_Gimble.14505.93.0 RW=Google_Gimble.14505.93.0 >> Starting firmware updater. >> Target image: images/bios-gimble.ro-14505-93-0.rw-14505-93-0.bin (RO:Google_Gimble.14505.93.0, RW/A:Google_Gimble.14505.93.0, RW/B:Google_Gimble.14505.93.0). >> Current system: <sys-flash> (RO:Google_Gimble.14498.0.0, RW/A:Google_Gimble.14505.93.0, RW/B:Google_Gimble.14498.0.0). >> Write protection: 1 (enabled; HW=1, SW=1). >> TRY-RW UPDATE: Updating RW_SECTION_A to try on reboot. >> DONE: Firmware updater exits successfully. fw_prev_result = trying # [RO/str] Firmware result of previous boot fw_prev_tried = B # [RO/str] Firmware tried on previous boot (A or B) fw_result = success # [RW/str] Firmware result this boot fw_tried = B # [RO/str] Firmware tried this boot (A or B) fw_try_count = 10 # [RW/int] Number of times to try fw_try_next fw_try_next = A # [RW/str] Firmware to try next (A or B) fw_vboot2 = 1 # [RO/int] 1 if firmware was selected by vboot2 or 0 otherwise fwb_tries = 10 # [RW/int] Try firmware B count fwid = Google_Gimble.14498.0.0 # [RO/str] Active firmware ID fwupdate_tries = 0 # [RW/int] Times to try OS firmware update (inside kern_nv) mainfw_act = B # [RO/str] Active main firmware // deferupdate HOLD localhost ~ # chromeos-firmwareupdate --mode=deferupdate_hold --wp=1 Machine Model: gimble Write Protect: HW=0 SW=0 Last Boot Version: RO=Google_Gimble.14498.0.0 ACT/B=Google_Gimble.14498.0.0 Firmware Updater: RO=Google_Gimble.14505.93.0 RW=Google_Gimble.14505.93.0 >> Starting firmware updater. >> Target image: images/bios-gimble.ro-14505-93-0.rw-14505-93-0.bin (RO:Google_Gimble.14505.93.0, RW/A:Google_Gimble.14505.93.0, RW/B:Google_Gimble.14505.93.0). >> Current system: <sys-flash> (RO:Google_Gimble.14498.0.0, RW/A:Google_Gimble.14505.93.0, RW/B:Google_Gimble.14498.0.0). >> Write protection: 1 (enabled; HW=1, SW=1). >> TRY-RW UPDATE: Updating RW_SECTION_A to try on reboot. >> DEFER UPDATE: Defer setting cookies for RW_SECTION_A. >> DONE: Firmware updater exits successfully. fw_prev_result = trying # [RO/str] Firmware result of previous boot fw_prev_tried = B # [RO/str] Firmware tried on previous boot (A or B) fw_result = success # [RW/str] Firmware result this boot fw_tried = B # [RO/str] Firmware tried this boot (A or B) fw_try_count = 0 # [RW/int] Number of times to try fw_try_next fw_try_next = B # [RW/str] Firmware to try next (A or B) fw_vboot2 = 1 # [RO/int] 1 if firmware was selected by vboot2 or 0 otherwise fwb_tries = 0 # [RW/int] Try firmware B count fwid = Google_Gimble.14498.0.0 # [RO/str] Active firmware ID fwupdate_tries = 0 # [RW/int] Times to try OS firmware update (inside kern_nv) mainfw_act = B # [RO/str] Active main firmware // deferupdate APPLY localhost ~ # chromeos-firmwareupdate --mode=deferupdate_apply --wp=1 Machine Model: gimble Write Protect: HW=0 SW=1 Last Boot Version: RO=Google_Gimble.14498.0.0 ACT/B=Google_Gimble.14498.0.0 Firmware Updater: RO=Google_Gimble.14505.106.0 RW=Google_Gimble.14505.106.0 >> Starting firmware updater. INFO: update_firmware: Apply defer updates, only setting cookies for the next boot slot. >> DONE: Firmware updater exits successfully. fw_prev_result = trying # [RO/str] Firmware result of previous boot fw_prev_tried = B # [RO/str] Firmware tried on previous boot (A or B) fw_result = success # [RW/str] Firmware result this boot fw_tried = B # [RO/str] Firmware tried this boot (A or B) fw_try_count = 10 # [RW/int] Number of times to try fw_try_next fw_try_next = A # [RW/str] Firmware to try next (A or B) fw_vboot2 = 1 # [RO/int] 1 if firmware was selected by vboot2 or 0 otherwise fwb_tries = 10 # [RW/int] Try firmware B count fwid = Google_Gimble.14498.0.0 # [RO/str] Active firmware ID fwupdate_tries = 0 # [RW/int] Times to try OS firmware update (inside kern_nv) mainfw_act = B # [RO/str] Active main firmware ``` BUG=b:232304971 TEST=chromeos-firmwareupdate w/ comment above BRANCH=None Signed-off-by: Jae Hoon Kim <kimjae@chromium.org> Change-Id: Idcfc5864a2cfc2b46a8b936bbab61e3da7c62596 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3661357 Commit-Queue: Yu-Ping Wu <yupingso@chromium.org> Reviewed-by: Hung-Te Lin <hungte@chromium.org> Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
-rw-r--r--futility/updater.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/futility/updater.c b/futility/updater.c
index dcbc4450..c28c5bae 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -20,6 +20,13 @@
static const char ROOTKEY_HASH_DEV[] =
"b11d74edd286c144e1135b49e7f0bc20cf041f10";
+enum try_update_type {
+ TRY_UPDATE_OFF = 0,
+ TRY_UPDATE_AUTO,
+ TRY_UPDATE_DEFERRED_HOLD,
+ TRY_UPDATE_DEFERRED_APPLY,
+};
+
enum target_type {
TARGET_SELF,
TARGET_UPDATE,
@@ -951,7 +958,7 @@ static enum updater_error_codes update_try_rw_firmware(
struct firmware_image *image_to,
int wp_enabled)
{
- const char *target;
+ const char *target, *self_target;
int has_update = 1;
int is_vboot2 = get_system_property(SYS_PROP_FW_VBOOT2, cfg);
@@ -967,7 +974,7 @@ static enum updater_error_codes update_try_rw_firmware(
return UPDATE_ERR_TPM_ROLLBACK;
VB2_DEBUG("Firmware %s vboot2.\n", is_vboot2 ? "is" : "is NOT");
- target = decide_rw_target(cfg, TARGET_SELF, is_vboot2);
+ self_target = target = decide_rw_target(cfg, TARGET_SELF, is_vboot2);
if (target == NULL) {
ERROR("TRY-RW update needs system to boot in RW firmware.\n");
return UPDATE_ERR_TARGET;
@@ -979,7 +986,7 @@ static enum updater_error_codes update_try_rw_firmware(
target, image_to->file_name);
return UPDATE_ERR_INVALID_IMAGE;
}
- if (!cfg->force_update)
+ if (!(cfg->force_update || cfg->try_update == TRY_UPDATE_DEFERRED_HOLD))
has_update = section_needs_update(image_from, image_to, target);
if (has_update) {
@@ -989,6 +996,24 @@ static enum updater_error_codes update_try_rw_firmware(
if (write_firmware(cfg, image_to, target))
return UPDATE_ERR_WRITE_FIRMWARE;
+
+ /*
+ * If the firmware update requested is part of a deferred update
+ * HOLD action, the autoupdater/postinstall will later call
+ * defer update APPLY action to set the correct cookies. So here
+ * it is valid to keep the self slot as the active firmware even
+ * though the target slot is always updated (whether the current
+ * active firmware is the same version or not).
+ */
+ if (cfg->try_update == TRY_UPDATE_DEFERRED_HOLD) {
+ STATUS(
+ "DEFERRED UPDATE: Defer setting cookies for %s\n",
+ target);
+ target = self_target;
+ has_update = 0;
+ }
+ } else {
+ STATUS("NO RW UPDATE: No update for RW firmware.\n");
}
/* Always set right cookies for next boot. */
@@ -1002,9 +1027,6 @@ static enum updater_error_codes update_try_rw_firmware(
write_firmware(cfg, image_to, FMAP_RW_LEGACY);
}
- if (!has_update)
- STATUS("NO UPDATE: No need to update.\n");
-
return UPDATE_ERR_DONE;
}
@@ -1149,6 +1171,23 @@ enum updater_error_codes update_firmware(struct updater_config *cfg)
int wp_enabled, done = 0;
enum updater_error_codes r = UPDATE_ERR_UNKNOWN;
+ /*
+ * For deferred update APPLY action, the only requirement is to set the
+ * correct cookies to the update target slot.
+ */
+ if (cfg->try_update == TRY_UPDATE_DEFERRED_APPLY) {
+ INFO("Apply deferred updates, only setting cookies for the "
+ "next boot slot.\n");
+ int vboot2 = get_system_property(SYS_PROP_FW_VBOOT2, cfg);
+ if (set_try_cookies(
+ cfg,
+ decide_rw_target(cfg, TARGET_UPDATE, vboot2),
+ /*has_update=*/1,
+ vboot2))
+ return UPDATE_ERR_SET_COOKIES;
+ return UPDATE_ERR_DONE;
+ }
+
struct firmware_image *image_from = &cfg->image_current,
*image_to = &cfg->image;
if (!image_to->data)
@@ -1473,12 +1512,16 @@ int updater_setup_config(struct updater_config *cfg,
/* Setup update mode. */
if (arg->try_update)
- cfg->try_update = 1;
+ cfg->try_update = TRY_UPDATE_AUTO;
if (arg->mode) {
if (strcmp(arg->mode, "autoupdate") == 0) {
- cfg->try_update = 1;
+ cfg->try_update = TRY_UPDATE_AUTO;
+ } else if (strcmp(arg->mode, "deferupdate_hold") == 0) {
+ cfg->try_update = TRY_UPDATE_DEFERRED_HOLD;
+ } else if (strcmp(arg->mode, "deferupdate_apply") == 0) {
+ cfg->try_update = TRY_UPDATE_DEFERRED_APPLY;
} else if (strcmp(arg->mode, "recovery") == 0) {
- cfg->try_update = 0;
+ cfg->try_update = TRY_UPDATE_OFF;
} else if (strcmp(arg->mode, "legacy") == 0) {
cfg->legacy_update = 1;
} else if (strcmp(arg->mode, "factory") == 0 ||
@@ -1494,7 +1537,7 @@ int updater_setup_config(struct updater_config *cfg,
if (cfg->factory_update) {
/* factory_update must be processed after arg->mode. */
check_wp_disabled = 1;
- cfg->try_update = 0;
+ cfg->try_update = TRY_UPDATE_OFF;
}
cfg->gbb_flags = arg->gbb_flags;
cfg->override_gbb_flags = arg->override_gbb_flags;