diff options
author | Jae Hoon Kim <kimjae@chromium.org> | 2022-05-23 16:21:33 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-05-26 15:48:16 +0000 |
commit | 6dba972b6ab1246864d3af0eaa3effcda29407d1 (patch) | |
tree | 9e189ab7e3ff1d922dcdf22ad92178ab5fd16133 | |
parent | ff1f3b91c31706d1e73a82ec928fd9bdd080f96f (diff) | |
download | vboot-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.c | 63 |
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; |