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