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