diff options
author | Randall Spangler <rspangler@chromium.org> | 2011-07-26 16:26:59 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2011-07-27 10:16:14 -0700 |
commit | 99275128b44a8de53c5c72987148c8d0bffc0689 (patch) | |
tree | 5d45a608f0517ab871395e8d3c35f4edf0a8afef | |
parent | 57e91f713f7e647e79ecdf7a6de878f638661e05 (diff) | |
download | vboot-99275128b44a8de53c5c72987148c8d0bffc0689.tar.gz |
If trying firmware B and found invalid kernel, just reboot
When we're trying a new firmware B with a new kernel subkey, if it
can't find any kernels there may still be a kernel which the old
firmware A likes. So instead of going to recovery mode, just reboot
so we fall back to firmware A. If firmware A doesn't find any valid
kernels we'll still go to recovery mode.
BUG=chrome-os-partner:1657
TEST=manual:
Do a firmware+OS update which involves kernel subkey rotation. After
installing the new firmware but before rebooting into the new OS,
corrupt the new kernel so that it'll fail validation. Then reboot.
On previous firmware, this would go to recovery mode. Now it should
simply reboot and be back in firmware A / kernel A.
Change-Id: I12796f428fd6969ea5ef36f39c4f58cb0a2bff0d
Reviewed-on: http://gerrit.chromium.org/gerrit/4770
Reviewed-by: Gaurav Shah <gauravsh@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 692e3b08..5331526c 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -625,11 +625,30 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams* cparams, /* Normal boot */ retval = VbBootNormal(cparams, &p); - /* See if we need to update the TPM. */ - if (!((1 == shared->firmware_index) && (shared->flags & VBSD_FWB_TRIED))) { - /* We don't advance the TPM if we're trying a new firmware B, because - * that firmware may have a key change and roll forward the TPM too - * soon. */ + if ((1 == shared->firmware_index) && (shared->flags & VBSD_FWB_TRIED)) { + /* Special cases for when we're trying a new firmware B. These are + * needed because firmware updates also usually change the kernel key, + * which means that the B firmware can only boot a new kernel, and the + * old firmware in A can only boot the previous kernel. */ + + /* Don't advance the TPM if we're trying a new firmware B, because we + * don't yet know if the new kernel will successfully boot. We still + * want to be able to fall back to the previous firmware+kernel if the + * new firmware+kernel fails. */ + + /* If we found only invalid kernels, reboot and try again. This allows + * us to fall back to the previous firmware+kernel instead of giving up + * and going to recovery mode right away. We'll still go to recovery + * mode if we run out of tries and the old firmware can't find a kernel + * it likes. */ + if (VBERROR_INVALID_KERNEL_FOUND == retval) { + VBDEBUG(("Trying firmware B, and only found invalid kernels.\n")); + VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED); + goto VbSelectAndLoadKernel_exit; + } + } else { + /* Not trying a new firmware B. */ + /* See if we need to update the TPM. */ VBDEBUG(("Checking if TPM kernel version needs advancing\n")); if (shared->kernel_version_tpm > shared->kernel_version_tpm_start) { tpm_status = RollbackKernelWrite(shared->kernel_version_tpm); |