diff options
Diffstat (limited to 'firmware/lib/vboot_api_kernel.c')
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index d1afc4f7..08254a47 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -406,6 +406,101 @@ static void vb2_kernel_cleanup(struct vb2_context *ctx, VbCommonParams *cparams) shared->timer_vb_select_and_load_kernel_exit = VbExGetTimer(); } +int VbAltOSForceChromeOS(void) { + return 0; +} + +VbError_t VbCheckAltOS(struct vb2_context *ctx, VbCommonParams *cparams, + int trusted_ec) { + VbSharedDataHeader *shared = + (VbSharedDataHeader *)cparams->shared_data_blob; + + int req_enable = vb2_nv_get(ctx, VB2_NV_ENABLE_ALT_OS_REQUEST); + int req_disable = vb2_nv_get(ctx, VB2_NV_DISABLE_ALT_OS_REQUEST); + + /* Reset enable/disable requests right away to prevent cycles. */ + vb2_nv_set(ctx, VB2_NV_ENABLE_ALT_OS_REQUEST, 0); + vb2_nv_set(ctx, VB2_NV_DISABLE_ALT_OS_REQUEST, 0); + + uint8_t kflags; + uint8_t kflags_set; + int rv; + rv = GetAltOSFlags(&kflags); + if (rv) { + VB2_DEBUG("Unable to read Alt OS flags from TPM\n"); + return rv; + } + kflags_set = kflags; + + int need_oprom = 0; + int oprom_loaded = !(shared->flags & VBSD_OPROM_MATTERS) || + shared->flags & VBSD_OPROM_LOADED; + int hotkey_after_sync = vb2ex_get_alt_os_hotkey(); + int hotkey_last_boot = !!(kflags & ALT_OS_HOTKEY); + int enabled = !!(kflags & ALT_OS_ENABLE); + int force_cros = VbAltOSForceChromeOS(); + + + /* Case 1: Disable Alt OS mode. Does not need UI. */ + if (enabled && req_disable) { + VB2_DEBUG("Disabling Alt OS mode...\n"); + /* Disable has priority over enable. */ + req_enable = 0; + enabled = 0; + kflags_set &= ~ALT_OS_ENABLE; + } + + /* Case 2: Enable Alt OS mode. Needs UI. */ + if (!enabled && ((req_enable && hotkey_after_sync && trusted_ec) || + hotkey_last_boot)) { + VB2_DEBUG("Setting flag to show confirm Alt OS mode\n"); + shared->flags |= VBSD_ALT_OS_CONFIRM_ENABLE; + need_oprom = 1; + /* If we need to reboot to load VGA Option ROM, save Alt OS + * hotkey state in TPM for next boot. */ + kflags_set |= ALT_OS_HOTKEY; + } + + /* Case 3: Show Alt OS picker. Needs UI. */ + if (enabled && !force_cros) { + VB2_DEBUG("Setting flag to show Alt OS picker\n"); + shared->flags |= VBSD_ALT_OS_SHOW_PICKER; + need_oprom = 1; + } + + /* If we don't need to store Alt OS hotkey state, then remove it. */ + if (!need_oprom || oprom_loaded) + kflags_set &= ~ALT_OS_HOTKEY; + + if (kflags_set != kflags) { + rv = SetAltOSFlags(kflags_set); + if (rv) { + VB2_DEBUG("Unable to write Alt OS flags to TPM\n"); + return rv; + } + } + + VB2_DEBUG("Alt OS: kflags=%d\n", kflags); + VB2_DEBUG("Alt OS: kflags_set=%d\n", kflags_set); + VB2_DEBUG("Alt OS: hotkey_after_sync=%d\n", hotkey_after_sync); + VB2_DEBUG("Alt OS: hotkey_last_boot=%d\n", hotkey_last_boot); + VB2_DEBUG("Alt OS: need_oprom=%d\n", need_oprom); + VB2_DEBUG("Alt OS: oprom_loaded=%d\n", oprom_loaded); + VB2_DEBUG("Alt OS: enabled=%d\n", enabled); + VB2_DEBUG("Alt OS: force_cros=%d\n", force_cros); + VB2_DEBUG("Alt OS: req_enable=%d\n", req_enable); + VB2_DEBUG("Alt OS: req_disable=%d\n", req_disable); + VB2_DEBUG("Alt OS: trusted_ec=%d\n", trusted_ec); + + if (need_oprom && !oprom_loaded) { + VB2_DEBUG("Reboot to load VGA Option ROM\n"); + vb2_nv_set(ctx, VB2_NV_OPROM_NEEDED, 1); + return VBERROR_VGA_OPROM_MISMATCH; + } + + return VBERROR_SUCCESS; +} + VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, VbSelectAndLoadKernelParams *kparams) { @@ -417,6 +512,12 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, goto VbSelectAndLoadKernel_exit; /* + * Determine whether the EC is in RO or RW. This information + * will be used later on in Alt OS boot flow. + */ + int trusted_ec = VbExTrustEC(0); + + /* * Do EC software sync if necessary. This has UI, but it's just a * single non-interactive WAIT screen. */ @@ -424,6 +525,15 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, if (retval) goto VbSelectAndLoadKernel_exit; + /* + * Check whether confirmation screen or picker screen need to be + * shown for Alt OS. Ignore return value, and in the case of failure, + * continue to a normal boot. + */ + retval = VbCheckAltOS(&ctx, cparams, trusted_ec); + if (retval == VBERROR_VGA_OPROM_MISMATCH) + goto VbSelectAndLoadKernel_exit; + /* Select boot path */ if (shared->recovery_reason) { /* Recovery boot. This has UI. */ @@ -439,6 +549,12 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, else retval = VbBootDeveloper(&ctx, cparams); VbExEcEnteringMode(0, VB_EC_DEVELOPER); + } else if (shared->flags & VBSD_ALT_OS_CONFIRM_ENABLE || + shared->flags & VBSD_ALT_OS_SHOW_PICKER) { + /* Alt OS boot. This has UI. */ + retval = VbBootAltOS(&ctx, cparams); + /* Report as normal mode to the EC. */ + VbExEcEnteringMode(0, VB_EC_NORMAL); } else { /* Normal boot */ retval = VbBootNormal(&ctx, cparams); |