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