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 10527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "region.h" 11527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "gbb_access.h" 121b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "gbb_header.h" 131b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "load_firmware_fw.h" 141b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "rollback_index.h" 151b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "utility.h" 161b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "vboot_api.h" 171b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "vboot_common.h" 181b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler#include "vboot_nvstorage.h" 191b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler 207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall SpanglerVbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams) 217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler{ 227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbSharedDataHeader *shared = 237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler (VbSharedDataHeader *)cparams->shared_data_blob; 24527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass GoogleBinaryBlockHeader gbb; 257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvContext vnc; 267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbError_t retval = VBERROR_SUCCESS; 277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED; 287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_s3_resume = 0; 297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t s3_debug_boot = 0; 307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t require_official_os = 0; 317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t tpm_version = 0; 327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t tpm_status = 0; 337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int has_virt_dev_switch = 0; 347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_hw_dev = 0; 357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_virt_dev = 0; 367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t disable_dev_request = 0; 377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler uint32_t clear_tpm_owner_request = 0; 387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler int is_dev = 0; 39b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson uint32_t backup_requested = 0; 40b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson uint32_t backup_for_safety = 0; 41b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson int lost_nvram; 427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Initialize output flags */ 447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags = 0; 457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 46527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass retval = VbGbbReadHeader_static(cparams, &gbb); 47527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (retval) 48527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return retval; 49527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 50527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VBDEBUG(("VbInit() input flags 0x%x gbb flags 0x%x\n", iparams->flags, 51b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson gbb.flags)); 52527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Set up NV storage */ 547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbExNvStorageRead(vnc.raw); 557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSetup(&vnc); 56b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson lost_nvram = vnc.regenerate_crc; 577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Initialize shared data structure */ 597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (0 != VbSharedDataInit(shared, cparams->shared_data_size)) { 607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("Shared data init error\n")); 617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler return VBERROR_INIT_SHARED_DATA; 627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->timer_vb_init_enter = VbExGetTimer(); 657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Copy some boot switch flags */ 677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* TODO: in next refactor, just save in/out flags in VbSharedData */ 687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags = 0; 697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED) 707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_REC_SWITCH_ON; 717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_WP_ENABLED) 727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED; 737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_SW_WP_ENABLED) 747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_FIRMWARE_SW_WP_ENABLED; 757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_S3_RESUME) 767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_S3_RESUME; 777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_RO_NORMAL_SUPPORT) 787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT; 797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_EC_SOFTWARE_SYNC) 807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_EC_SOFTWARE_SYNC; 817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_EC_SLOW_UPDATE) 827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_EC_SLOW_UPDATE; 83a53a0b040f45a1086515e7a5c8a8326c0b1d1f74Luigi Semenzato if (iparams->flags & VB_INIT_FLAG_VIRTUAL_REC_SWITCH) 84a53a0b040f45a1086515e7a5c8a8326c0b1d1f74Luigi Semenzato shared->flags |= VBSD_BOOT_REC_SWITCH_VIRTUAL; 85731f8e8a1df73a00f4840120171b07a259a6304aDuncan Laurie if (iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) 86731f8e8a1df73a00f4840120171b07a259a6304aDuncan Laurie shared->flags |= VBSD_OPROM_MATTERS; 87731f8e8a1df73a00f4840120171b07a259a6304aDuncan Laurie if (iparams->flags & VB_INIT_FLAG_OPROM_LOADED) 88731f8e8a1df73a00f4840120171b07a259a6304aDuncan Laurie shared->flags |= VBSD_OPROM_LOADED; 897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_s3_resume = (iparams->flags & VB_INIT_FLAG_S3_RESUME ? 1 : 0); 917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Check if the OS is requesting a debug S3 reset */ 937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &s3_debug_boot); 947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (s3_debug_boot) { 957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (is_s3_resume) { 967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() requesting S3 debug boot\n")); 977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT; 987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_s3_resume = 0; /* Proceed as if normal boot */ 997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Clear the request even if this is a normal boot, since we 1037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * don't want the NEXT S3 resume to be a debug reset unless the 1047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * OS asserts the request again. 1057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 0); 1077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If this isn't a S3 resume, read the current recovery request, then 1117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * clear it so we don't get stuck in recovery mode. 1127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!is_s3_resume) { 1147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery); 1157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit sees recovery request = %d\n", recovery)); 1167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (VBNV_RECOVERY_NOT_REQUESTED != recovery) 1177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 1187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBNV_RECOVERY_NOT_REQUESTED); 1197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If the previous boot failed in the firmware somewhere outside of 1237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * verified boot, and recovery is not requested for our own reasons, 1247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * request recovery mode. This gives the calling firmware a way to 1257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * request recovery if it finds something terribly wrong. 1267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (VBNV_RECOVERY_NOT_REQUESTED == recovery && 1287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->flags & VB_INIT_FLAG_PREVIOUS_BOOT_FAIL) { 1297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler recovery = VBNV_RECOVERY_RO_FIRMWARE; 1307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If recovery button is pressed, override recovery reason. Note that 1347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * we do this in the S3 resume path also. 1357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED) 1377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler recovery = VBNV_RECOVERY_RO_MANUAL; 1387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Copy current recovery reason to shared data. If we fail later on, it 1417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * won't matter, since we'll just reboot. 1427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1437993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->recovery_reason = (uint8_t)recovery; 1447993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", recovery)); 1457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If this is a S3 resume, resume the TPM. 1487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * 1497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * FIXME: I think U-Boot won't ever ask us to do this. Can we remove 1507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * it? 1517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (is_s3_resume) { 1537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (TPM_SUCCESS != RollbackS3Resume()) { 1547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If we can't resume, just do a full reboot. No need 1567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * to go to recovery mode here, since if the TPM is 1577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * really broken we'll catch it on the next boot. 1587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1597993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_S3_RESUME; 1607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else { 1627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Should we pay attention to the TPM's virtual dev-switch? */ 1637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH) { 1647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH; 1657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler has_virt_dev_switch = 1; 1667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 1677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * We always believe the HW dev-switch, since there's one 1707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * attached to servo which may be active even on systems 1717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * without a physical switch. The EC may also implement a fake 1727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * dev-switch for testing. 1737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 1747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON) 1757993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_hw_dev = 1; 1767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* We may be asked to clear the virtual dev-switch at boot. */ 1787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request); 1797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Allow GBB flag to override dev switch */ 181527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (gbb.flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) 1827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_hw_dev = 1; 1837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Have we been explicitly asked to clear the TPM owner? */ 1857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 1867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler &clear_tpm_owner_request); 1877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 1887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 1897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Initialize the TPM. If the developer mode state has changed 1907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * since the last boot, we need to clear TPM ownership. If the 1917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * TPM space is initialized by this call, the virtual 1927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * dev-switch will be disabled by default) 1937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 194472d93c146403c0f95b656e182b972e15ff11835Shawn Nematbakhsh VBDEBUG(("TPM: Call RollbackFirmwareSetup(r%d, d%d)\n", 195b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson recovery, is_hw_dev)); 196472d93c146403c0f95b656e182b972e15ff11835Shawn Nematbakhsh tpm_status = RollbackFirmwareSetup(is_hw_dev, 1977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler disable_dev_request, 1987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler clear_tpm_owner_request, 1997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* two outputs on success */ 2007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler &is_virt_dev, &tpm_version); 2017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (0 != tpm_status) { 2037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("Unable to setup TPM and read " 2047993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler "firmware version (0x%x)\n", tpm_status)); 2057993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2067993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (TPM_E_MUST_REBOOT == tpm_status) { 2077993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2087993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * TPM wants to reboot into the same mode we're 2097993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * in now 2107993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("TPM requires a reboot.\n")); 2127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!recovery) { 2137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Not recovery mode. Just reboot (not 2157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * into recovery). 2167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_REBOOT_REQUIRED; 2187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler goto VbInit_exit; 2197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else if (VBNV_RECOVERY_RO_TPM_REBOOT != 2207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->recovery_reason) { 2217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * In recovery mode now, and we haven't 2237993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * requested a TPM reboot yet, so 2247993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * request one. 2257993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 2267993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 2277993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBNV_RECOVERY_RO_TPM_REBOOT); 2287993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_REBOOT_REQUIRED; 2297993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler goto VbInit_exit; 2307993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!recovery) { 2347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 2357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBNV_RECOVERY_RO_TPM_S_ERROR); 2367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, 2377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler tpm_status); 2387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler retval = VBERROR_TPM_FIRMWARE_SETUP; 2397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler goto VbInit_exit; 2407993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2417993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2427993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 243339b0ac9a0589c8287b0f9be6221934e8df268c6Randall Spangler /* TPM setup succeeded, or we're in recovery mode and ignoring 244339b0ac9a0589c8287b0f9be6221934e8df268c6Randall Spangler * errors. What did we learn? */ 2457993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->fw_version_tpm_start = tpm_version; 2467993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->fw_version_tpm = tpm_version; 2477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (is_hw_dev || (has_virt_dev_switch && is_virt_dev)) { 2487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler is_dev = 1; 2497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; 2507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2517993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (disable_dev_request && !is_virt_dev) 2527993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 0); 2537993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (clear_tpm_owner_request) { 2547993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 0); 2557993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_DONE, 1); 2567993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2577993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 2587993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 259b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson /* 260b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * If the nvram state was lost, try to restore the bits we care about 261b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * from the backup in the TPM. It's okay if we can't, though. 262b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * Note: None of the bits that we back up should have been referenced 263b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * before this point. Otherwise, they'll just be overwritten here. 264b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * All the other bits will be unchanged from whatever has happened to 265b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * them since VbNvSetup() reinitialized the VbNvContext. 266b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson */ 267b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson if (lost_nvram) 268b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson RestoreNvFromBackup(&vnc); 269b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson 2707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Allow BIOS to load arbitrary option ROMs? */ 271527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (gbb.flags & GBB_FLAG_LOAD_OPTION_ROMS) 2727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM; 2737993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2747993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Factory may need to boot custom OSes when the dev-switch is on */ 275527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (is_dev && (gbb.flags & GBB_FLAG_ENABLE_ALTERNATE_OS)) 2767993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; 2777993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2787993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Set output flags */ 2797993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (VBNV_RECOVERY_NOT_REQUESTED != recovery) { 2807993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Requesting recovery mode */ 2817993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= (VB_INIT_OUT_ENABLE_RECOVERY | 2827993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_CLEAR_RAM | 2837993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_DISPLAY | 2847993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_USB_STORAGE); 2857993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else if (is_dev) { 2867993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Developer switch is on, so need to support dev mode */ 2877993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= (VB_INIT_OUT_ENABLE_DEVELOPER | 2887993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_CLEAR_RAM | 2897993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_DISPLAY | 2907993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VB_INIT_OUT_ENABLE_USB_STORAGE); 2917993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* ... which may or may not include custom OSes */ 2927993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os); 2937993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (!require_official_os) 2947993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; 2957993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 2967993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 2977993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Dev-mode needs the VGA option ROM to be loaded so it can 2987993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * display the scary boot screen. If we don't have it, we need 2997993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * to request it and reboot so it can be loaded. 3007993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 3017993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && 3027993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler !(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { 3037993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1); 3042596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie /* 3052596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie * If VbInit() is run before Option ROMs are run it 3062596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie * can still respond to the VbNv flag and does not 3072596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie * need to reboot here. 3082596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie */ 3092596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD)) 3102596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie retval = VBERROR_VGA_OPROM_MISMATCH; 3117993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() needs oprom, doesn't have it\n")); 3127993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 3137993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3147993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } else { 3157993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 3167993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * Normal mode, so disable dev_boot_* flags. This ensures they 3177993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * will be initially disabled if the user later transitions 3187993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * back into developer mode. 3197993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 3207993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0); 3217993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 0); 3227993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0); 323b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson /* 324b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * Back up any changes now, so these values can't be forgotten 325b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * by draining the battery. We really only care about these 326b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * three fields, but it's uncommon for any others to change so 327b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * this is an easier test than checking each one. 328b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson */ 329b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson if (vnc.regenerate_crc) 330b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson backup_for_safety = 1; 3317993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3327993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* 3337993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * If we don't need the VGA option ROM but got it anyway, stop 3347993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * asking for it and reboot in case there's some vulnerability 3357993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler * in using it. 3367993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler */ 3377993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && 3387993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { 3397993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0); 340731f8e8a1df73a00f4840120171b07a259a6304aDuncan Laurie /* 3412596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie * If VbInit() is run before Option ROMs are run it 3422596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie * can still respond to the VbNv flag and does not 3432596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie * need to reboot here. 344731f8e8a1df73a00f4840120171b07a259a6304aDuncan Laurie */ 3452596c657958477b06d1613902dfe4d47a2ad0ae0Duncan Laurie if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD)) 346731f8e8a1df73a00f4840120171b07a259a6304aDuncan Laurie retval = VBERROR_VGA_OPROM_MISMATCH; 3477993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() has oprom, doesn't need it\n")); 3487993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 3497993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler } 3507993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 351b64f097891e697eaf3b2794baae934f8b4d82d14Bill RichardsonVbInit_exit: 352b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson /* 353b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * If we successfully backup the NV storage, it will clear the 354b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * VBNV_BACKUP_NVRAM_REQUEST field, so we want to do it before 355b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson * calling VbNvTeardown(). It's okay if we can't backup, though. 356b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson */ 357b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson VbNvGet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, &backup_requested); 358b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson if (backup_requested || backup_for_safety) 359b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson SaveNvToBackup(&vnc); 3607993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3617993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler /* Tear down NV storage */ 3627993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbNvTeardown(&vnc); 3637993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler if (vnc.raw_changed) 3647993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VbExNvStorageWrite(vnc.raw); 3657993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3667993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() output flags 0x%x\n", iparams->out_flags)); 3677993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3687993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler shared->timer_vb_init_exit = VbExGetTimer(); 3697993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3707993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler VBDEBUG(("VbInit() returning 0x%x\n", retval)); 3717993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler 3727993f257af87c7c38cdc71b76bc67cde6c3cdbcaRandall Spangler return retval; 3731b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler} 374