/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * High-level firmware wrapper API - entry points for init, firmware selection
 */

#include "sysincludes.h"

#include "region.h"
#include "gbb_access.h"
#include "gbb_header.h"
#include "load_firmware_fw.h"
#include "rollback_index.h"
#include "utility.h"
#include "vboot_api.h"
#include "vboot_common.h"
#include "vboot_nvstorage.h"

VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams)
{
	VbSharedDataHeader *shared =
		(VbSharedDataHeader *)cparams->shared_data_blob;
	GoogleBinaryBlockHeader gbb;
	VbNvContext vnc;
	VbError_t retval = VBERROR_SUCCESS;
	uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED;
	int is_s3_resume = 0;
	uint32_t s3_debug_boot = 0;
	uint32_t require_official_os = 0;
	uint32_t tpm_version = 0;
	uint32_t tpm_status = 0;
	int has_virt_dev_switch = 0;
	int is_hw_dev = 0;
	int is_virt_dev = 0;
	uint32_t disable_dev_request = 0;
	uint32_t clear_tpm_owner_request = 0;
	int is_dev = 0;
	uint32_t backup_requested = 0;
	uint32_t backup_for_safety = 0;
	int lost_nvram;

	/* Initialize output flags */
	iparams->out_flags = 0;

	retval = VbGbbReadHeader_static(cparams, &gbb);
	if (retval)
		return retval;

	VBDEBUG(("VbInit() input flags 0x%x gbb flags 0x%x\n", iparams->flags,
		 gbb.flags));

	/* Set up NV storage */
	VbExNvStorageRead(vnc.raw);
	VbNvSetup(&vnc);
	lost_nvram = vnc.regenerate_crc;

	/* Initialize shared data structure */
	if (0 != VbSharedDataInit(shared, cparams->shared_data_size)) {
		VBDEBUG(("Shared data init error\n"));
		return VBERROR_INIT_SHARED_DATA;
	}

	shared->timer_vb_init_enter = VbExGetTimer();

	/* Copy some boot switch flags */
	/* TODO: in next refactor, just save in/out flags in VbSharedData */
	shared->flags = 0;
	if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED)
		shared->flags |= VBSD_BOOT_REC_SWITCH_ON;
	if (iparams->flags & VB_INIT_FLAG_WP_ENABLED)
		shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
	if (iparams->flags & VB_INIT_FLAG_SW_WP_ENABLED)
		shared->flags |= VBSD_BOOT_FIRMWARE_SW_WP_ENABLED;
	if (iparams->flags & VB_INIT_FLAG_S3_RESUME)
		shared->flags |= VBSD_BOOT_S3_RESUME;
	if (iparams->flags & VB_INIT_FLAG_RO_NORMAL_SUPPORT)
		shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
	if (iparams->flags & VB_INIT_FLAG_NOFAIL_BOOT)
		shared->flags |= VBSD_NOFAIL_BOOT;
	if (iparams->flags & VB_INIT_FLAG_EC_SOFTWARE_SYNC)
		shared->flags |= VBSD_EC_SOFTWARE_SYNC;
	if (iparams->flags & VB_INIT_FLAG_EC_SLOW_UPDATE)
		shared->flags |= VBSD_EC_SLOW_UPDATE;
	if (iparams->flags & VB_INIT_FLAG_VIRTUAL_REC_SWITCH)
		shared->flags |= VBSD_BOOT_REC_SWITCH_VIRTUAL;
	if (iparams->flags & VB_INIT_FLAG_OPROM_MATTERS)
		shared->flags |= VBSD_OPROM_MATTERS;
	if (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)
		shared->flags |= VBSD_OPROM_LOADED;

	is_s3_resume = (iparams->flags & VB_INIT_FLAG_S3_RESUME ? 1 : 0);

	/* Check if the OS is requesting a debug S3 reset */
	VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &s3_debug_boot);
	if (s3_debug_boot) {
		if (is_s3_resume) {
			VBDEBUG(("VbInit() requesting S3 debug boot\n"));
			iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT;
			is_s3_resume = 0;  /* Proceed as if normal boot */
		}

		/*
		 * Clear the request even if this is a normal boot, since we
		 * don't want the NEXT S3 resume to be a debug reset unless the
		 * OS asserts the request again.
		 */
		VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 0);
	}

	/*
	 * If this isn't a S3 resume, read the current recovery request, then
	 * clear it so we don't get stuck in recovery mode.
	 */
	if (!is_s3_resume) {
		VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery);
		VBDEBUG(("VbInit sees recovery request = %d\n", recovery));
		if (VBNV_RECOVERY_NOT_REQUESTED != recovery)
			VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
				VBNV_RECOVERY_NOT_REQUESTED);
	}

	/*
	 * If the previous boot failed in the firmware somewhere outside of
	 * verified boot, and recovery is not requested for our own reasons,
	 * request recovery mode.  This gives the calling firmware a way to
	 * request recovery if it finds something terribly wrong.
	 */
	if (VBNV_RECOVERY_NOT_REQUESTED == recovery &&
	    iparams->flags & VB_INIT_FLAG_PREVIOUS_BOOT_FAIL) {
		recovery = VBNV_RECOVERY_RO_FIRMWARE;
	}

	/*
	 * If recovery button is pressed, override recovery reason.  Note that
	 * we do this in the S3 resume path also.
	 */
	if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED)
		recovery = VBNV_RECOVERY_RO_MANUAL;

	/*
	 * Copy current recovery reason to shared data. If we fail later on, it
	 * won't matter, since we'll just reboot.
	 */
	shared->recovery_reason = (uint8_t)recovery;
	VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", recovery));

	/*
	 * If this is a S3 resume, resume the TPM.
	 *
	 * FIXME: I think U-Boot won't ever ask us to do this. Can we remove
	 * it?
	 */
	if (is_s3_resume) {
		if (TPM_SUCCESS != RollbackS3Resume()) {
			/*
			 * If we can't resume, just do a full reboot.  No need
			 * to go to recovery mode here, since if the TPM is
			 * really broken we'll catch it on the next boot.
			 */
			retval = VBERROR_TPM_S3_RESUME;
		}
	} else {
		/* Should we pay attention to the TPM's virtual dev-switch? */
		if (iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH) {
			shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH;
			has_virt_dev_switch = 1;
		}

		/*
		 * We always believe the HW dev-switch, since there's one
		 * attached to servo which may be active even on systems
		 * without a physical switch. The EC may also implement a fake
		 * dev-switch for testing.
		 */
		if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON)
			is_hw_dev = 1;

		/* We may be asked to clear the virtual dev-switch at boot. */
		VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request);

		/* Allow GBB flag to override dev switch */
		if (gbb.flags & GBB_FLAG_FORCE_DEV_SWITCH_ON)
			is_hw_dev = 1;

		/* Have we been explicitly asked to clear the TPM owner? */
		VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST,
			&clear_tpm_owner_request);

		/*
		 * Initialize the TPM. If the developer mode state has changed
		 * since the last boot, we need to clear TPM ownership. If the
		 * TPM space is initialized by this call, the virtual
		 * dev-switch will be disabled by default)
		 */
		VBDEBUG(("TPM: Call RollbackFirmwareSetup(r%d, d%d)\n",
			 recovery, is_hw_dev));
		tpm_status = RollbackFirmwareSetup(is_hw_dev,
						   disable_dev_request,
						   clear_tpm_owner_request,
						   /* two outputs on success */
						   &is_virt_dev, &tpm_version);

		if (0 != tpm_status) {
			VBDEBUG(("Unable to setup TPM and read "
				 "firmware version (0x%x)\n", tpm_status));

			if (TPM_E_MUST_REBOOT == tpm_status) {
				/*
				 * TPM wants to reboot into the same mode we're
				 * in now
				 */
				VBDEBUG(("TPM requires a reboot.\n"));
				if (!recovery) {
					/*
					 * Not recovery mode.  Just reboot (not
					 * into recovery).
					 */
					retval = VBERROR_TPM_REBOOT_REQUIRED;
					goto VbInit_exit;
				} else if (VBNV_RECOVERY_RO_TPM_REBOOT !=
					   shared->recovery_reason) {
					/*
					 * In recovery mode now, and we haven't
					 * requested a TPM reboot yet, so
					 * request one.
					 */
					VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
						VBNV_RECOVERY_RO_TPM_REBOOT);
					retval = VBERROR_TPM_REBOOT_REQUIRED;
					goto VbInit_exit;
				}
			}

			if (!recovery) {
				VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
					VBNV_RECOVERY_RO_TPM_S_ERROR);
				VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE,
					tpm_status);
				retval = VBERROR_TPM_FIRMWARE_SETUP;
				goto VbInit_exit;
			}
		}

		/* TPM setup succeeded, or we're in recovery mode and ignoring
		 * errors. What did we learn? */
		shared->fw_version_tpm_start = tpm_version;
		shared->fw_version_tpm = tpm_version;
		if (is_hw_dev || (has_virt_dev_switch && is_virt_dev)) {
			is_dev = 1;
			shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
		}
		if (disable_dev_request && !is_virt_dev)
			VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 0);
		if (clear_tpm_owner_request) {
			VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 0);
			VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_DONE, 1);
		}
	}

	/*
	 * If the nvram state was lost, try to restore the bits we care about
	 * from the backup in the TPM. It's okay if we can't, though.
	 * Note: None of the bits that we back up should have been referenced
	 * before this point. Otherwise, they'll just be overwritten here.
	 * All the other bits will be unchanged from whatever has happened to
	 * them since VbNvSetup() reinitialized the VbNvContext.
	 */
	if (lost_nvram)
		RestoreNvFromBackup(&vnc);

	/* Allow BIOS to load arbitrary option ROMs? */
	if (gbb.flags & GBB_FLAG_LOAD_OPTION_ROMS)
		iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM;

	/* Factory may need to boot custom OSes when the dev-switch is on */
	if (is_dev && (gbb.flags & GBB_FLAG_ENABLE_ALTERNATE_OS))
		iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;

	/* Set output flags */
	if (VBNV_RECOVERY_NOT_REQUESTED != recovery) {
		/* Requesting recovery mode */
		iparams->out_flags |= (VB_INIT_OUT_ENABLE_RECOVERY |
				       VB_INIT_OUT_CLEAR_RAM |
				       VB_INIT_OUT_ENABLE_DISPLAY |
				       VB_INIT_OUT_ENABLE_USB_STORAGE);
	} else if (is_dev) {
		/* Developer switch is on, so need to support dev mode */
		iparams->out_flags |= (VB_INIT_OUT_ENABLE_DEVELOPER |
				       VB_INIT_OUT_CLEAR_RAM |
				       VB_INIT_OUT_ENABLE_DISPLAY |
				       VB_INIT_OUT_ENABLE_USB_STORAGE);
		/* ... which may or may not include custom OSes */
		VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os);
		if (!require_official_os)
			iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;

		/*
		 * Dev-mode needs the VGA option ROM to be loaded so it can
		 * display the scary boot screen. If we don't have it, we need
		 * to request it and reboot so it can be loaded.
		 */
		if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) &&
		    !(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) {
			VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
			/*
			 * If VbInit() is run before Option ROMs are run it
			 * can still respond to the VbNv flag and does not
			 * need to reboot here.
			 */
			if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD))
				retval = VBERROR_VGA_OPROM_MISMATCH;
			VBDEBUG(("VbInit() needs oprom, doesn't have it\n"));
		}

	} else {
		/*
		 * Normal mode, so disable dev_boot_* flags.  This ensures they
		 * will be initially disabled if the user later transitions
		 * back into developer mode.
		 */
		VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0);
		VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 0);
		VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0);
		VbNvSet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, 0);
		VbNvSet(&vnc, VBNV_DEV_DEFAULT_BOOT, 0);
		VbNvSet(&vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, 0);
		/*
		 * Back up any changes now, so these values can't be forgotten
		 * by draining the battery. We really only care about these
		 * three fields, but it's uncommon for any others to change so
		 * this is an easier test than checking each one.
		 */
		if (vnc.regenerate_crc)
			backup_for_safety = 1;

		/*
		 * If we don't need the VGA option ROM but got it anyway, stop
		 * asking for it and reboot in case there's some vulnerability
		 * in using it.
		 */
		if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) &&
		    (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) {
			VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0);
			/*
			 * If VbInit() is run before Option ROMs are run it
			 * can still respond to the VbNv flag and does not
			 * need to reboot here.
			 */
			if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD))
				retval = VBERROR_VGA_OPROM_MISMATCH;
			VBDEBUG(("VbInit() has oprom, doesn't need it\n"));
		}
	}

VbInit_exit:
	/*
	 * If we successfully backup the NV storage, it will clear the
	 * VBNV_BACKUP_NVRAM_REQUEST field, so we want to do it before
	 * calling VbNvTeardown(). It's okay if we can't backup, though.
	 */
	VbNvGet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, &backup_requested);
	if (backup_requested || backup_for_safety)
		SaveNvToBackup(&vnc);

	/* Tear down NV storage */
	VbNvTeardown(&vnc);
	if (vnc.raw_changed)
		VbExNvStorageWrite(vnc.raw);

	VBDEBUG(("VbInit() output flags 0x%x\n", iparams->out_flags));

	shared->timer_vb_init_exit = VbExGetTimer();

	VBDEBUG(("VbInit() returning 0x%x\n", retval));

	return retval;
}
