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
VbInit(VbCommonParams * cparams,VbInitParams * iparams)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