Home | History | Annotate | Download | only in lib
      1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  *
      5  * High-level firmware wrapper API - entry points for init, firmware selection
      6  */
      7 
      8 #include "sysincludes.h"
      9 
     10 #include "region.h"
     11 #include "gbb_access.h"
     12 #include "gbb_header.h"
     13 #include "load_firmware_fw.h"
     14 #include "rollback_index.h"
     15 #include "utility.h"
     16 #include "vboot_api.h"
     17 #include "vboot_common.h"
     18 #include "vboot_nvstorage.h"
     19 
     20 VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams)
     21 {
     22 	VbSharedDataHeader *shared =
     23 		(VbSharedDataHeader *)cparams->shared_data_blob;
     24 	GoogleBinaryBlockHeader gbb;
     25 	VbNvContext vnc;
     26 	VbError_t retval = VBERROR_SUCCESS;
     27 	uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED;
     28 	int is_s3_resume = 0;
     29 	uint32_t s3_debug_boot = 0;
     30 	uint32_t require_official_os = 0;
     31 	uint32_t tpm_version = 0;
     32 	uint32_t tpm_status = 0;
     33 	int has_virt_dev_switch = 0;
     34 	int is_hw_dev = 0;
     35 	int is_virt_dev = 0;
     36 	uint32_t disable_dev_request = 0;
     37 	uint32_t clear_tpm_owner_request = 0;
     38 	int is_dev = 0;
     39 	uint32_t backup_requested = 0;
     40 	uint32_t backup_for_safety = 0;
     41 	int lost_nvram;
     42 
     43 	/* Initialize output flags */
     44 	iparams->out_flags = 0;
     45 
     46 	retval = VbGbbReadHeader_static(cparams, &gbb);
     47 	if (retval)
     48 		return retval;
     49 
     50 	VBDEBUG(("VbInit() input flags 0x%x gbb flags 0x%x\n", iparams->flags,
     51 		 gbb.flags));
     52 
     53 	/* Set up NV storage */
     54 	VbExNvStorageRead(vnc.raw);
     55 	VbNvSetup(&vnc);
     56 	lost_nvram = vnc.regenerate_crc;
     57 
     58 	/* Initialize shared data structure */
     59 	if (0 != VbSharedDataInit(shared, cparams->shared_data_size)) {
     60 		VBDEBUG(("Shared data init error\n"));
     61 		return VBERROR_INIT_SHARED_DATA;
     62 	}
     63 
     64 	shared->timer_vb_init_enter = VbExGetTimer();
     65 
     66 	/* Copy some boot switch flags */
     67 	/* TODO: in next refactor, just save in/out flags in VbSharedData */
     68 	shared->flags = 0;
     69 	if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED)
     70 		shared->flags |= VBSD_BOOT_REC_SWITCH_ON;
     71 	if (iparams->flags & VB_INIT_FLAG_WP_ENABLED)
     72 		shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
     73 	if (iparams->flags & VB_INIT_FLAG_SW_WP_ENABLED)
     74 		shared->flags |= VBSD_BOOT_FIRMWARE_SW_WP_ENABLED;
     75 	if (iparams->flags & VB_INIT_FLAG_S3_RESUME)
     76 		shared->flags |= VBSD_BOOT_S3_RESUME;
     77 	if (iparams->flags & VB_INIT_FLAG_RO_NORMAL_SUPPORT)
     78 		shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
     79 	if (iparams->flags & VB_INIT_FLAG_EC_SOFTWARE_SYNC)
     80 		shared->flags |= VBSD_EC_SOFTWARE_SYNC;
     81 	if (iparams->flags & VB_INIT_FLAG_EC_SLOW_UPDATE)
     82 		shared->flags |= VBSD_EC_SLOW_UPDATE;
     83 	if (iparams->flags & VB_INIT_FLAG_VIRTUAL_REC_SWITCH)
     84 		shared->flags |= VBSD_BOOT_REC_SWITCH_VIRTUAL;
     85 	if (iparams->flags & VB_INIT_FLAG_OPROM_MATTERS)
     86 		shared->flags |= VBSD_OPROM_MATTERS;
     87 	if (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)
     88 		shared->flags |= VBSD_OPROM_LOADED;
     89 
     90 	is_s3_resume = (iparams->flags & VB_INIT_FLAG_S3_RESUME ? 1 : 0);
     91 
     92 	/* Check if the OS is requesting a debug S3 reset */
     93 	VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &s3_debug_boot);
     94 	if (s3_debug_boot) {
     95 		if (is_s3_resume) {
     96 			VBDEBUG(("VbInit() requesting S3 debug boot\n"));
     97 			iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT;
     98 			is_s3_resume = 0;  /* Proceed as if normal boot */
     99 		}
    100 
    101 		/*
    102 		 * Clear the request even if this is a normal boot, since we
    103 		 * don't want the NEXT S3 resume to be a debug reset unless the
    104 		 * OS asserts the request again.
    105 		 */
    106 		VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 0);
    107 	}
    108 
    109 	/*
    110 	 * If this isn't a S3 resume, read the current recovery request, then
    111 	 * clear it so we don't get stuck in recovery mode.
    112 	 */
    113 	if (!is_s3_resume) {
    114 		VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery);
    115 		VBDEBUG(("VbInit sees recovery request = %d\n", recovery));
    116 		if (VBNV_RECOVERY_NOT_REQUESTED != recovery)
    117 			VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
    118 				VBNV_RECOVERY_NOT_REQUESTED);
    119 	}
    120 
    121 	/*
    122 	 * If the previous boot failed in the firmware somewhere outside of
    123 	 * verified boot, and recovery is not requested for our own reasons,
    124 	 * request recovery mode.  This gives the calling firmware a way to
    125 	 * request recovery if it finds something terribly wrong.
    126 	 */
    127 	if (VBNV_RECOVERY_NOT_REQUESTED == recovery &&
    128 	    iparams->flags & VB_INIT_FLAG_PREVIOUS_BOOT_FAIL) {
    129 		recovery = VBNV_RECOVERY_RO_FIRMWARE;
    130 	}
    131 
    132 	/*
    133 	 * If recovery button is pressed, override recovery reason.  Note that
    134 	 * we do this in the S3 resume path also.
    135 	 */
    136 	if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED)
    137 		recovery = VBNV_RECOVERY_RO_MANUAL;
    138 
    139 	/*
    140 	 * Copy current recovery reason to shared data. If we fail later on, it
    141 	 * won't matter, since we'll just reboot.
    142 	 */
    143 	shared->recovery_reason = (uint8_t)recovery;
    144 	VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", recovery));
    145 
    146 	/*
    147 	 * If this is a S3 resume, resume the TPM.
    148 	 *
    149 	 * FIXME: I think U-Boot won't ever ask us to do this. Can we remove
    150 	 * it?
    151 	 */
    152 	if (is_s3_resume) {
    153 		if (TPM_SUCCESS != RollbackS3Resume()) {
    154 			/*
    155 			 * If we can't resume, just do a full reboot.  No need
    156 			 * to go to recovery mode here, since if the TPM is
    157 			 * really broken we'll catch it on the next boot.
    158 			 */
    159 			retval = VBERROR_TPM_S3_RESUME;
    160 		}
    161 	} else {
    162 		/* Should we pay attention to the TPM's virtual dev-switch? */
    163 		if (iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH) {
    164 			shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH;
    165 			has_virt_dev_switch = 1;
    166 		}
    167 
    168 		/*
    169 		 * We always believe the HW dev-switch, since there's one
    170 		 * attached to servo which may be active even on systems
    171 		 * without a physical switch. The EC may also implement a fake
    172 		 * dev-switch for testing.
    173 		 */
    174 		if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON)
    175 			is_hw_dev = 1;
    176 
    177 		/* We may be asked to clear the virtual dev-switch at boot. */
    178 		VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request);
    179 
    180 		/* Allow GBB flag to override dev switch */
    181 		if (gbb.flags & GBB_FLAG_FORCE_DEV_SWITCH_ON)
    182 			is_hw_dev = 1;
    183 
    184 		/* Have we been explicitly asked to clear the TPM owner? */
    185 		VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST,
    186 			&clear_tpm_owner_request);
    187 
    188 		/*
    189 		 * Initialize the TPM. If the developer mode state has changed
    190 		 * since the last boot, we need to clear TPM ownership. If the
    191 		 * TPM space is initialized by this call, the virtual
    192 		 * dev-switch will be disabled by default)
    193 		 */
    194 		VBDEBUG(("TPM: Call RollbackFirmwareSetup(r%d, d%d)\n",
    195 			 recovery, is_hw_dev));
    196 		tpm_status = RollbackFirmwareSetup(is_hw_dev,
    197 						   disable_dev_request,
    198 						   clear_tpm_owner_request,
    199 						   /* two outputs on success */
    200 						   &is_virt_dev, &tpm_version);
    201 
    202 		if (0 != tpm_status) {
    203 			VBDEBUG(("Unable to setup TPM and read "
    204 				 "firmware version (0x%x)\n", tpm_status));
    205 
    206 			if (TPM_E_MUST_REBOOT == tpm_status) {
    207 				/*
    208 				 * TPM wants to reboot into the same mode we're
    209 				 * in now
    210 				 */
    211 				VBDEBUG(("TPM requires a reboot.\n"));
    212 				if (!recovery) {
    213 					/*
    214 					 * Not recovery mode.  Just reboot (not
    215 					 * into recovery).
    216 					 */
    217 					retval = VBERROR_TPM_REBOOT_REQUIRED;
    218 					goto VbInit_exit;
    219 				} else if (VBNV_RECOVERY_RO_TPM_REBOOT !=
    220 					   shared->recovery_reason) {
    221 					/*
    222 					 * In recovery mode now, and we haven't
    223 					 * requested a TPM reboot yet, so
    224 					 * request one.
    225 					 */
    226 					VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
    227 						VBNV_RECOVERY_RO_TPM_REBOOT);
    228 					retval = VBERROR_TPM_REBOOT_REQUIRED;
    229 					goto VbInit_exit;
    230 				}
    231 			}
    232 
    233 			if (!recovery) {
    234 				VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
    235 					VBNV_RECOVERY_RO_TPM_S_ERROR);
    236 				VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE,
    237 					tpm_status);
    238 				retval = VBERROR_TPM_FIRMWARE_SETUP;
    239 				goto VbInit_exit;
    240 			}
    241 		}
    242 
    243 		/* TPM setup succeeded, or we're in recovery mode and ignoring
    244 		 * errors. What did we learn? */
    245 		shared->fw_version_tpm_start = tpm_version;
    246 		shared->fw_version_tpm = tpm_version;
    247 		if (is_hw_dev || (has_virt_dev_switch && is_virt_dev)) {
    248 			is_dev = 1;
    249 			shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
    250 		}
    251 		if (disable_dev_request && !is_virt_dev)
    252 			VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 0);
    253 		if (clear_tpm_owner_request) {
    254 			VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 0);
    255 			VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_DONE, 1);
    256 		}
    257 	}
    258 
    259 	/*
    260 	 * If the nvram state was lost, try to restore the bits we care about
    261 	 * from the backup in the TPM. It's okay if we can't, though.
    262 	 * Note: None of the bits that we back up should have been referenced
    263 	 * before this point. Otherwise, they'll just be overwritten here.
    264 	 * All the other bits will be unchanged from whatever has happened to
    265 	 * them since VbNvSetup() reinitialized the VbNvContext.
    266 	 */
    267 	if (lost_nvram)
    268 		RestoreNvFromBackup(&vnc);
    269 
    270 	/* Allow BIOS to load arbitrary option ROMs? */
    271 	if (gbb.flags & GBB_FLAG_LOAD_OPTION_ROMS)
    272 		iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM;
    273 
    274 	/* Factory may need to boot custom OSes when the dev-switch is on */
    275 	if (is_dev && (gbb.flags & GBB_FLAG_ENABLE_ALTERNATE_OS))
    276 		iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;
    277 
    278 	/* Set output flags */
    279 	if (VBNV_RECOVERY_NOT_REQUESTED != recovery) {
    280 		/* Requesting recovery mode */
    281 		iparams->out_flags |= (VB_INIT_OUT_ENABLE_RECOVERY |
    282 				       VB_INIT_OUT_CLEAR_RAM |
    283 				       VB_INIT_OUT_ENABLE_DISPLAY |
    284 				       VB_INIT_OUT_ENABLE_USB_STORAGE);
    285 	} else if (is_dev) {
    286 		/* Developer switch is on, so need to support dev mode */
    287 		iparams->out_flags |= (VB_INIT_OUT_ENABLE_DEVELOPER |
    288 				       VB_INIT_OUT_CLEAR_RAM |
    289 				       VB_INIT_OUT_ENABLE_DISPLAY |
    290 				       VB_INIT_OUT_ENABLE_USB_STORAGE);
    291 		/* ... which may or may not include custom OSes */
    292 		VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os);
    293 		if (!require_official_os)
    294 			iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;
    295 
    296 		/*
    297 		 * Dev-mode needs the VGA option ROM to be loaded so it can
    298 		 * display the scary boot screen. If we don't have it, we need
    299 		 * to request it and reboot so it can be loaded.
    300 		 */
    301 		if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) &&
    302 		    !(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) {
    303 			VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
    304 			/*
    305 			 * If VbInit() is run before Option ROMs are run it
    306 			 * can still respond to the VbNv flag and does not
    307 			 * need to reboot here.
    308 			 */
    309 			if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD))
    310 				retval = VBERROR_VGA_OPROM_MISMATCH;
    311 			VBDEBUG(("VbInit() needs oprom, doesn't have it\n"));
    312 		}
    313 
    314 	} else {
    315 		/*
    316 		 * Normal mode, so disable dev_boot_* flags.  This ensures they
    317 		 * will be initially disabled if the user later transitions
    318 		 * back into developer mode.
    319 		 */
    320 		VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0);
    321 		VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 0);
    322 		VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0);
    323 		/*
    324 		 * Back up any changes now, so these values can't be forgotten
    325 		 * by draining the battery. We really only care about these
    326 		 * three fields, but it's uncommon for any others to change so
    327 		 * this is an easier test than checking each one.
    328 		 */
    329 		if (vnc.regenerate_crc)
    330 			backup_for_safety = 1;
    331 
    332 		/*
    333 		 * If we don't need the VGA option ROM but got it anyway, stop
    334 		 * asking for it and reboot in case there's some vulnerability
    335 		 * in using it.
    336 		 */
    337 		if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) &&
    338 		    (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) {
    339 			VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0);
    340 			/*
    341 			 * If VbInit() is run before Option ROMs are run it
    342 			 * can still respond to the VbNv flag and does not
    343 			 * need to reboot here.
    344 			 */
    345 			if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD))
    346 				retval = VBERROR_VGA_OPROM_MISMATCH;
    347 			VBDEBUG(("VbInit() has oprom, doesn't need it\n"));
    348 		}
    349 	}
    350 
    351 VbInit_exit:
    352 	/*
    353 	 * If we successfully backup the NV storage, it will clear the
    354 	 * VBNV_BACKUP_NVRAM_REQUEST field, so we want to do it before
    355 	 * calling VbNvTeardown(). It's okay if we can't backup, though.
    356 	 */
    357 	VbNvGet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, &backup_requested);
    358 	if (backup_requested || backup_for_safety)
    359 		SaveNvToBackup(&vnc);
    360 
    361 	/* Tear down NV storage */
    362 	VbNvTeardown(&vnc);
    363 	if (vnc.raw_changed)
    364 		VbExNvStorageWrite(vnc.raw);
    365 
    366 	VBDEBUG(("VbInit() output flags 0x%x\n", iparams->out_flags));
    367 
    368 	shared->timer_vb_init_exit = VbExGetTimer();
    369 
    370 	VBDEBUG(("VbInit() returning 0x%x\n", retval));
    371 
    372 	return retval;
    373 }
    374