vboot_api_init.c revision 472d93c146403c0f95b656e182b972e15ff11835
17993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 21b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler * Use of this source code is governed by a BSD-style license that can be 31b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler * found in the LICENSE file. 41b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler * 51b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler * High-level firmware wrapper API - entry points for init, firmware selection 61b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler */ 71b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler 80c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "sysincludes.h" 90c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson 101b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "gbb_header.h" 111b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "load_firmware_fw.h" 121b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "rollback_index.h" 131b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "utility.h" 141b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "vboot_api.h" 151b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "vboot_common.h" 161b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "vboot_nvstorage.h" 171b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler 187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall SpanglerVbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams) 197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler{ 207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbSharedDataHeader *shared = 217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler (VbSharedDataHeader *)cparams->shared_data_blob; 227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler GoogleBinaryBlockHeader *gbb = 237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler (GoogleBinaryBlockHeader *)cparams->gbb_data; 247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvContext vnc; 257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbError_t retval = VBERROR_SUCCESS; 267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED; 277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_s3_resume = 0; 287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t s3_debug_boot = 0; 297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t require_official_os = 0; 307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t tpm_version = 0; 317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t tpm_status = 0; 327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int has_virt_dev_switch = 0; 337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_hw_dev = 0; 347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_virt_dev = 0; 357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t disable_dev_request = 0; 367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t clear_tpm_owner_request = 0; 377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_dev = 0; 387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() input flags 0x%x\n", iparams->flags)); 407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Initialize output flags */ 427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags = 0; 437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Set up NV storage */ 457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbExNvStorageRead(vnc.raw); 467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSetup(&vnc); 477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Initialize shared data structure */ 497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (0 != VbSharedDataInit(shared, cparams->shared_data_size)) { 507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("Shared data init error\n")); 517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler return VBERROR_INIT_SHARED_DATA; 527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->timer_vb_init_enter = VbExGetTimer(); 557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Copy some boot switch flags */ 577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* TODO: in next refactor, just save in/out flags in VbSharedData */ 587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags = 0; 597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED) 607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_REC_SWITCH_ON; 617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_WP_ENABLED) 627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED; 637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_SW_WP_ENABLED) 647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_FIRMWARE_SW_WP_ENABLED; 657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_S3_RESUME) 667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_S3_RESUME; 677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_RO_NORMAL_SUPPORT) 687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT; 697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_EC_SOFTWARE_SYNC) 707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_EC_SOFTWARE_SYNC; 717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_EC_SLOW_UPDATE) 727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_EC_SLOW_UPDATE; 737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_s3_resume = (iparams->flags & VB_INIT_FLAG_S3_RESUME ? 1 : 0); 757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Check if the OS is requesting a debug S3 reset */ 777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &s3_debug_boot); 787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (s3_debug_boot) { 797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (is_s3_resume) { 807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() requesting S3 debug boot\n")); 817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT; 827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_s3_resume = 0; /* Proceed as if normal boot */ 837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Clear the request even if this is a normal boot, since we 877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * don't want the NEXT S3 resume to be a debug reset unless the 887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * OS asserts the request again. 897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 0); 917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If this isn't a S3 resume, read the current recovery request, then 957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * clear it so we don't get stuck in recovery mode. 967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!is_s3_resume) { 987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery); 997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit sees recovery request = %d\n", recovery)); 1007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (VBNV_RECOVERY_NOT_REQUESTED != recovery) 1017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 1027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBNV_RECOVERY_NOT_REQUESTED); 1037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If the previous boot failed in the firmware somewhere outside of 1077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * verified boot, and recovery is not requested for our own reasons, 1087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * request recovery mode. This gives the calling firmware a way to 1097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * request recovery if it finds something terribly wrong. 1107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (VBNV_RECOVERY_NOT_REQUESTED == recovery && 1127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->flags & VB_INIT_FLAG_PREVIOUS_BOOT_FAIL) { 1137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler recovery = VBNV_RECOVERY_RO_FIRMWARE; 1147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If recovery button is pressed, override recovery reason. Note that 1187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * we do this in the S3 resume path also. 1197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED) 1217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler recovery = VBNV_RECOVERY_RO_MANUAL; 1227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Copy current recovery reason to shared data. If we fail later on, it 1257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * won't matter, since we'll just reboot. 1267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->recovery_reason = (uint8_t)recovery; 1287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", recovery)); 1297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If this is a S3 resume, resume the TPM. 1327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * 1337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * FIXME: I think U-Boot won't ever ask us to do this. Can we remove 1347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * it? 1357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (is_s3_resume) { 1377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (TPM_SUCCESS != RollbackS3Resume()) { 1387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If we can't resume, just do a full reboot. No need 1407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * to go to recovery mode here, since if the TPM is 1417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * really broken we'll catch it on the next boot. 1427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_S3_RESUME; 1447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else { 1467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Should we pay attention to the TPM's virtual dev-switch? */ 1477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH) { 1487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH; 1497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler has_virt_dev_switch = 1; 1507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * We always believe the HW dev-switch, since there's one 1547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * attached to servo which may be active even on systems 1557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * without a physical switch. The EC may also implement a fake 1567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * dev-switch for testing. 1577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON) 1597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_hw_dev = 1; 1607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* We may be asked to clear the virtual dev-switch at boot. */ 1627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request); 1637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Allow GBB flag to override dev switch */ 1657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) 1667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_hw_dev = 1; 1677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Have we been explicitly asked to clear the TPM owner? */ 1697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 1707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler &clear_tpm_owner_request); 1717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Initialize the TPM. If the developer mode state has changed 1747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * since the last boot, we need to clear TPM ownership. If the 1757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * TPM space is initialized by this call, the virtual 1767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * dev-switch will be disabled by default) 1777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 178472d93c146403c0f95b656e182b972e15ff11835Shawn Nematbakhsh VBDEBUG(("TPM: Call RollbackFirmwareSetup(r%d, d%d)\n", 179472d93c146403c0f95b656e182b972e15ff11835Shawn Nematbakhsh recovery, is_hw_dev)); 180472d93c146403c0f95b656e182b972e15ff11835Shawn Nematbakhsh tpm_status = RollbackFirmwareSetup(is_hw_dev, 1817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler disable_dev_request, 1827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler clear_tpm_owner_request, 1837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* two outputs on success */ 1847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler &is_virt_dev, &tpm_version); 1857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (0 != tpm_status) { 1877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("Unable to setup TPM and read " 1887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler "firmware version (0x%x)\n", tpm_status)); 1897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (TPM_E_MUST_REBOOT == tpm_status) { 1917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * TPM wants to reboot into the same mode we're 1937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * in now 1947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("TPM requires a reboot.\n")); 1967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!recovery) { 1977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Not recovery mode. Just reboot (not 1997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * into recovery). 2007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_REBOOT_REQUIRED; 2027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler goto VbInit_exit; 2037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else if (VBNV_RECOVERY_RO_TPM_REBOOT != 2047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->recovery_reason) { 2057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * In recovery mode now, and we haven't 2077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * requested a TPM reboot yet, so 2087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * request one. 2097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 2117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBNV_RECOVERY_RO_TPM_REBOOT); 2127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_REBOOT_REQUIRED; 2137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler goto VbInit_exit; 2147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!recovery) { 2187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 2197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBNV_RECOVERY_RO_TPM_S_ERROR); 2207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, 2217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler tpm_status); 2227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_FIRMWARE_SETUP; 2237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler goto VbInit_exit; 2247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 227339b0ac9a0589c8287b0f9be6221934e8df268c6Randall Spangler /* TPM setup succeeded, or we're in recovery mode and ignoring 228339b0ac9a0589c8287b0f9be6221934e8df268c6Randall Spangler * errors. What did we learn? */ 2297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->fw_version_tpm_start = tpm_version; 2307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->fw_version_tpm = tpm_version; 2317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (is_hw_dev || (has_virt_dev_switch && is_virt_dev)) { 2327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_dev = 1; 2337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; 2347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (disable_dev_request && !is_virt_dev) 2367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 0); 2377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (clear_tpm_owner_request) { 2387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 0); 2397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_DONE, 1); 2407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Allow BIOS to load arbitrary option ROMs? */ 2447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (gbb->flags & GBB_FLAG_LOAD_OPTION_ROMS) 2457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM; 2467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Factory may need to boot custom OSes when the dev-switch is on */ 2487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (is_dev && (gbb->flags & GBB_FLAG_ENABLE_ALTERNATE_OS)) 2497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; 2507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Set output flags */ 2527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (VBNV_RECOVERY_NOT_REQUESTED != recovery) { 2537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Requesting recovery mode */ 2547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= (VB_INIT_OUT_ENABLE_RECOVERY | 2557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_CLEAR_RAM | 2567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_DISPLAY | 2577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_USB_STORAGE); 2587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else if (is_dev) { 2597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Developer switch is on, so need to support dev mode */ 2607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= (VB_INIT_OUT_ENABLE_DEVELOPER | 2617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_CLEAR_RAM | 2627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_DISPLAY | 2637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_USB_STORAGE); 2647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* ... which may or may not include custom OSes */ 2657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os); 2667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!require_official_os) 2677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; 2687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Dev-mode needs the VGA option ROM to be loaded so it can 2717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * display the scary boot screen. If we don't have it, we need 2727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * to request it and reboot so it can be loaded. 2737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && 2757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler !(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { 2767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1); 2777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_VGA_OPROM_MISMATCH; 2787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() needs oprom, doesn't have it\n")); 2797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else { 2827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Normal mode, so disable dev_boot_* flags. This ensures they 2847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * will be initially disabled if the user later transitions 2857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * back into developer mode. 2867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0); 2887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 0); 2897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0); 2907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If we don't need the VGA option ROM but got it anyway, stop 2937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * asking for it and reboot in case there's some vulnerability 2947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * in using it. 2957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && 2977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { 2987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0); 2997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_VGA_OPROM_MISMATCH; 3007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() has oprom, doesn't need it\n")); 3017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 3027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 3037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbInit_exit: 3057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Tear down NV storage */ 3077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvTeardown(&vnc); 3087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (vnc.raw_changed) 3097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbExNvStorageWrite(vnc.raw); 3107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() output flags 0x%x\n", iparams->out_flags)); 3127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->timer_vb_init_exit = VbExGetTimer(); 3147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() returning 0x%x\n", retval)); 3167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler return retval; 3181b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler} 319