blob: 0609b55b4f121580777b16695c0728502e816e00 [file] [log] [blame]
Randall Spangler29accd92013-02-04 14:01:04 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Randall Spangler1b1998d2011-07-01 16:12:47 -07002 * 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 kernel selection
6 */
7
Bill Richardson0c3ba242013-03-29 11:09:30 -07008#include "sysincludes.h"
9
Simon Glass527ba812013-07-25 08:48:47 -060010#include "gbb_access.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070011#include "gbb_header.h"
12#include "load_kernel_fw.h"
Simon Glass527ba812013-07-25 08:48:47 -060013#include "region.h"
Randall Spangler22e7bb22011-07-22 14:06:51 -070014#include "rollback_index.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070015#include "utility.h"
16#include "vboot_api.h"
Bill Richardson253a58e2011-10-03 14:00:58 -070017#include "vboot_audio.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070018#include "vboot_common.h"
Bill Richardson822eca62011-08-22 14:06:38 -070019#include "vboot_display.h"
Aaron Durbin612797e2013-02-26 09:40:55 -060020#include "vboot_kernel.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070021#include "vboot_nvstorage.h"
22
Randall Spangler1b1998d2011-07-01 16:12:47 -070023/* Global variables */
Randall Spangler1b1998d2011-07-01 16:12:47 -070024static VbNvContext vnc;
25
Randall Spangler1b1998d2011-07-01 16:12:47 -070026#ifdef CHROMEOS_ENVIRONMENT
Randall Spangler29accd92013-02-04 14:01:04 -080027/* Global variable accessor for unit tests */
28
29VbNvContext *VbApiKernelGetVnc(void)
30{
31 return &vnc;
Randall Spangler1b1998d2011-07-01 16:12:47 -070032}
33#endif
34
Randall Spangler29accd92013-02-04 14:01:04 -080035/**
Randall Spangler7f436692013-02-05 12:42:36 -080036 * Set recovery request (called from vboot_api_kernel.c functions only)
Randall Spangler29accd92013-02-04 14:01:04 -080037 */
38static void VbSetRecoveryRequest(uint32_t recovery_request)
39{
40 VBDEBUG(("VbSetRecoveryRequest(%d)\n", (int)recovery_request));
41 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, recovery_request);
Randall Spangler1b1998d2011-07-01 16:12:47 -070042}
43
Randall Spangler29accd92013-02-04 14:01:04 -080044/**
45 * Attempt loading a kernel from the specified type(s) of disks.
46 *
47 * If successful, sets p->disk_handle to the disk for the kernel and returns
Randall Spangler1cf77cd2011-07-25 09:19:58 -070048 * VBERROR_SUCCESS.
49 *
50 * Returns VBERROR_NO_DISK_FOUND if no disks of the specified type were found.
51 *
Randall Spangler29accd92013-02-04 14:01:04 -080052 * May return other VBERROR_ codes for other failures.
53 */
54uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p,
55 uint32_t get_info_flags)
56{
57 VbError_t retval = VBERROR_UNKNOWN;
58 VbDiskInfo* disk_info = NULL;
59 uint32_t disk_count = 0;
60 uint32_t i;
Randall Spangler1b1998d2011-07-01 16:12:47 -070061
Randall Spangler29accd92013-02-04 14:01:04 -080062 VBDEBUG(("VbTryLoadKernel() start, get_info_flags=0x%x\n",
63 (unsigned)get_info_flags));
Randall Spangler1b1998d2011-07-01 16:12:47 -070064
Randall Spangler29accd92013-02-04 14:01:04 -080065 p->disk_handle = NULL;
Randall Spangler1b1998d2011-07-01 16:12:47 -070066
Randall Spangler29accd92013-02-04 14:01:04 -080067 /* Find disks */
68 if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
69 get_info_flags))
70 disk_count = 0;
Randall Spangler1b1998d2011-07-01 16:12:47 -070071
Randall Spangler29accd92013-02-04 14:01:04 -080072 VBDEBUG(("VbTryLoadKernel() found %d disks\n", (int)disk_count));
73 if (0 == disk_count) {
74 VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_DISK);
75 return VBERROR_NO_DISK_FOUND;
76 }
Randall Spangler1b1998d2011-07-01 16:12:47 -070077
Randall Spangler29accd92013-02-04 14:01:04 -080078 /* Loop over disks */
79 for (i = 0; i < disk_count; i++) {
80 VBDEBUG(("VbTryLoadKernel() trying disk %d\n", (int)i));
81 /*
82 * Sanity-check what we can. FWIW, VbTryLoadKernel() is always
83 * called with only a single bit set in get_info_flags.
84 *
85 * Ensure 512-byte sectors and non-trivially sized disk (for
86 * cgptlib) and that we got a partition with only the flags we
87 * asked for.
88 */
89 if (512 != disk_info[i].bytes_per_lba ||
90 32 > disk_info[i].lba_count ||
91 get_info_flags != disk_info[i].flags) {
Simon Glass981cb2a2013-08-12 15:12:47 -060092 VBDEBUG((" skipping: bytes_per_lba=%" PRIu64
93 " lba_count=%" PRIu64 " flags=0x%x\n",
Randall Spangler29accd92013-02-04 14:01:04 -080094 disk_info[i].bytes_per_lba,
95 disk_info[i].lba_count,
96 disk_info[i].flags));
97 continue;
98 }
99 p->disk_handle = disk_info[i].handle;
100 p->bytes_per_lba = disk_info[i].bytes_per_lba;
101 p->ending_lba = disk_info[i].lba_count - 1;
Simon Glass527ba812013-07-25 08:48:47 -0600102 retval = LoadKernel(p, cparams);
Randall Spangler29accd92013-02-04 14:01:04 -0800103 VBDEBUG(("VbTryLoadKernel() LoadKernel() = %d\n", retval));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700104
Randall Spangler29accd92013-02-04 14:01:04 -0800105 /*
106 * Stop now if we found a kernel.
107 *
108 * TODO: If recovery requested, should track the farthest we
109 * get, instead of just returning the value from the last disk
110 * attempted.
111 */
112 if (VBERROR_SUCCESS == retval)
113 break;
114 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700115
Randall Spangler29accd92013-02-04 14:01:04 -0800116 /* If we didn't find any good kernels, don't return a disk handle. */
117 if (VBERROR_SUCCESS != retval) {
118 VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_KERNEL);
119 p->disk_handle = NULL;
120 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700121
Randall Spangler29accd92013-02-04 14:01:04 -0800122 VbExDiskFreeInfo(disk_info, p->disk_handle);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700123
Randall Spangler29accd92013-02-04 14:01:04 -0800124 /*
125 * Pass through return code. Recovery reason (if any) has already been
126 * set by LoadKernel().
127 */
128 return retval;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700129}
130
Shawn Nematbakhshba7fd8d2012-10-30 15:17:33 -0700131#define CONFIRM_KEY_DELAY 20 /* Check confirm screen keys every 20ms */
132
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800133int VbUserConfirms(VbCommonParams *cparams, uint32_t confirm_flags)
Randall Spangler29accd92013-02-04 14:01:04 -0800134{
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800135 VbSharedDataHeader *shared =
136 (VbSharedDataHeader *)cparams->shared_data_blob;
Randall Spangler29accd92013-02-04 14:01:04 -0800137 uint32_t key;
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800138 uint32_t key_flags;
139 uint32_t button;
140 int rec_button_was_pressed = 0;
Bill Richardson29344752012-08-01 15:02:15 -0700141
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800142 VBDEBUG(("Entering %s(0x%x)\n", __func__, confirm_flags));
Bill Richardson29344752012-08-01 15:02:15 -0700143
Randall Spangler29accd92013-02-04 14:01:04 -0800144 /* Await further instructions */
145 while (1) {
146 if (VbExIsShutdownRequested())
147 return -1;
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800148 key = VbExKeyboardReadWithFlags(&key_flags);
149 button = VbExGetSwitches(VB_INIT_FLAG_REC_BUTTON_PRESSED);
Randall Spangler29accd92013-02-04 14:01:04 -0800150 switch (key) {
151 case '\r':
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800152 /* If we require a trusted keyboard for confirmation,
153 * but the keyboard may be faked (for instance, a USB
154 * device), beep and keep waiting.
155 */
156 if (confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD &&
157 !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) {
158 VbExBeep(120, 400);
159 break;
160 }
161
Randall Spangler29accd92013-02-04 14:01:04 -0800162 VBDEBUG(("%s() - Yes (1)\n", __func__));
163 return 1;
164 break;
165 case ' ':
Vadim Bendebury7aa250f2013-08-09 16:02:28 -0700166 VBDEBUG(("%s() - Space (%d)\n", __func__,
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800167 confirm_flags & VB_CONFIRM_SPACE_MEANS_NO));
168 if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO)
Randall Spangler29accd92013-02-04 14:01:04 -0800169 return 0;
170 break;
171 case 0x1b:
172 VBDEBUG(("%s() - No (0)\n", __func__));
173 return 0;
174 break;
175 default:
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800176 /* If the recovery button is physical, and is pressed,
177 * this is also a YES, but must wait for release.
178 */
179 if (!(shared->flags & VBSD_BOOT_REC_SWITCH_VIRTUAL)) {
180 if (button) {
181 VBDEBUG(("%s() - Rec button pressed\n",
182 __func__));
183 rec_button_was_pressed = 1;
184 } else if (rec_button_was_pressed) {
185 VBDEBUG(("%s() - Rec button (1)\n",
186 __func__));
187 return 1;
188 }
189 }
Randall Spangler29accd92013-02-04 14:01:04 -0800190 VbCheckDisplayKey(cparams, key, &vnc);
191 }
192 VbExSleepMs(CONFIRM_KEY_DELAY);
193 }
194
195 /* Not reached, but compiler will complain without it */
196 return -1;
Bill Richardson29344752012-08-01 15:02:15 -0700197}
198
Randall Spangler29accd92013-02-04 14:01:04 -0800199VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p)
200{
201 /* Boot from fixed disk only */
202 VBDEBUG(("Entering %s()\n", __func__));
203 return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700204}
205
Randall Spangler29accd92013-02-04 14:01:04 -0800206VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p)
207{
Simon Glass527ba812013-07-25 08:48:47 -0600208 GoogleBinaryBlockHeader *gbb = cparams->gbb;
Randall Spangler29accd92013-02-04 14:01:04 -0800209 VbSharedDataHeader *shared =
210 (VbSharedDataHeader *)cparams->shared_data_blob;
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700211 uint32_t allow_usb = 0, allow_legacy = 0, ctrl_d_pressed = 0;
Randall Spangler29accd92013-02-04 14:01:04 -0800212 VbAudioContext *audio = 0;
Randall Spanglerdaa807c2011-07-11 10:55:18 -0700213
Randall Spangler29accd92013-02-04 14:01:04 -0800214 VBDEBUG(("Entering %s()\n", __func__));
Bill Richardsonec8df162012-06-07 04:21:14 -0700215
Randall Spangler29accd92013-02-04 14:01:04 -0800216 /* Check if USB booting is allowed */
217 VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &allow_usb);
218 VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &allow_legacy);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700219
Randall Spangler29accd92013-02-04 14:01:04 -0800220 /* Handle GBB flag override */
221 if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_USB)
222 allow_usb = 1;
223 if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_LEGACY)
224 allow_legacy = 1;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700225
Randall Spangler29accd92013-02-04 14:01:04 -0800226 /* Show the dev mode warning screen */
227 VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_WARNING, 0, &vnc);
Bill Richardson25a3dbc2011-09-23 15:14:49 -0700228
Randall Spangler29accd92013-02-04 14:01:04 -0800229 /* Get audio/delay context */
230 audio = VbAudioOpen(cparams);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700231
Randall Spangler29accd92013-02-04 14:01:04 -0800232 /* We'll loop until we finish the delay or are interrupted */
233 do {
234 uint32_t key;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700235
Randall Spangler29accd92013-02-04 14:01:04 -0800236 if (VbExIsShutdownRequested()) {
237 VBDEBUG(("VbBootDeveloper() - shutdown requested!\n"));
238 VbAudioClose(audio);
239 return VBERROR_SHUTDOWN_REQUESTED;
240 }
Stefan Reinauera2326ee2012-08-23 15:06:45 -0700241
Randall Spangler29accd92013-02-04 14:01:04 -0800242 key = VbExKeyboardRead();
243 switch (key) {
244 case 0:
245 /* nothing pressed */
246 break;
247 case '\r':
248 /* Only disable virtual dev switch if allowed by GBB */
249 if (!(gbb->flags & GBB_FLAG_ENTER_TRIGGERS_TONORM))
250 break;
251 case ' ':
252 /* See if we should disable virtual dev-mode switch. */
253 VBDEBUG(("%s shared->flags=0x%x\n",
254 __func__, shared->flags));
255 if (shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
256 shared->flags & VBSD_BOOT_DEV_SWITCH_ON) {
257 /* Stop the countdown while we go ask... */
258 VbAudioClose(audio);
259 if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) {
260 /*
261 * TONORM won't work (only for
262 * non-shipping devices).
263 */
264 VBDEBUG(("%s() - TONORM rejected by "
265 "FORCE_DEV_SWITCH_ON\n",
266 __func__));
267 VbExDisplayDebugInfo(
268 "WARNING: TONORM prohibited by "
269 "GBB FORCE_DEV_SWITCH_ON.\n\n");
270 VbExBeep(120, 400);
271 break;
272 }
273 VbDisplayScreen(cparams,
274 VB_SCREEN_DEVELOPER_TO_NORM,
275 0, &vnc);
276 /* Ignore space in VbUserConfirms()... */
277 switch (VbUserConfirms(cparams, 0)) {
278 case 1:
279 VBDEBUG(("%s() - leaving dev-mode.\n",
280 __func__));
281 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST,
282 1);
283 VbDisplayScreen(
284 cparams,
285 VB_SCREEN_TO_NORM_CONFIRMED,
286 0, &vnc);
287 VbExSleepMs(5000);
288 return VBERROR_TPM_REBOOT_REQUIRED;
289 case -1:
290 VBDEBUG(("%s() - shutdown requested\n",
291 __func__));
292 return VBERROR_SHUTDOWN_REQUESTED;
293 default:
294 /* Stay in dev-mode */
295 VBDEBUG(("%s() - stay in dev-mode\n",
296 __func__));
297 VbDisplayScreen(
298 cparams,
299 VB_SCREEN_DEVELOPER_WARNING,
300 0, &vnc);
301 /* Start new countdown */
302 audio = VbAudioOpen(cparams);
303 }
304 } else {
305 /*
306 * No virtual dev-mode switch, so go directly
307 * to recovery mode.
308 */
309 VBDEBUG(("%s() - going to recovery\n",
310 __func__));
311 VbSetRecoveryRequest(
312 VBNV_RECOVERY_RW_DEV_SCREEN);
313 VbAudioClose(audio);
314 return VBERROR_LOAD_KERNEL_RECOVERY;
315 }
316 break;
317 case 0x04:
318 /* Ctrl+D = dismiss warning; advance to timeout */
319 VBDEBUG(("VbBootDeveloper() - "
320 "user pressed Ctrl+D; skip delay\n"));
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700321 ctrl_d_pressed = 1;
Randall Spangler29accd92013-02-04 14:01:04 -0800322 goto fallout;
323 break;
324 case 0x0c:
325 VBDEBUG(("VbBootDeveloper() - "
326 "user pressed Ctrl+L; Try legacy boot\n"));
327 /*
328 * If VbExLegacy() succeeds, it will never return. If
329 * it returns, beep.
330 */
331 if (allow_legacy)
332 VbExLegacy();
333 else
334 VBDEBUG(("VbBootDeveloper() - "
335 "Legacy boot is disabled\n"));
336
337 VbExBeep(120, 400);
338 VbExSleepMs(120);
339 VbExBeep(120, 400);
340 break;
341
Randall Spangler7f436692013-02-05 12:42:36 -0800342 case VB_KEY_CTRL_ENTER:
343 /*
344 * The Ctrl-Enter is special for Lumpy test purpose;
345 * fall through to Ctrl+U handler.
346 */
Randall Spangler29accd92013-02-04 14:01:04 -0800347 case 0x15:
348 /* Ctrl+U = try USB boot, or beep if failure */
349 VBDEBUG(("VbBootDeveloper() - "
350 "user pressed Ctrl+U; try USB\n"));
351 if (!allow_usb) {
352 VBDEBUG(("VbBootDeveloper() - "
353 "USB booting is disabled\n"));
354 VbExDisplayDebugInfo(
355 "WARNING: Booting from external media "
356 "(USB/SD) has not been enabled. Refer "
357 "to the developer-mode documentation "
358 "for details.\n");
359 VbExBeep(120, 400);
360 VbExSleepMs(120);
361 VbExBeep(120, 400);
362 } else {
363 /*
364 * Clear the screen to show we get the Ctrl+U
365 * key press.
366 */
367 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0,
368 &vnc);
369 if (VBERROR_SUCCESS ==
370 VbTryLoadKernel(cparams, p,
371 VB_DISK_FLAG_REMOVABLE)) {
372 VBDEBUG(("VbBootDeveloper() - "
373 "booting USB\n"));
374 VbAudioClose(audio);
375 return VBERROR_SUCCESS;
376 } else {
377 VBDEBUG(("VbBootDeveloper() - "
378 "no kernel found on USB\n"));
379 VbExBeep(250, 200);
380 VbExSleepMs(120);
381 /*
382 * Clear recovery requests from failed
383 * kernel loading, so that powering off
384 * at this point doesn't put us into
385 * recovery mode.
386 */
387 VbSetRecoveryRequest(
388 VBNV_RECOVERY_NOT_REQUESTED);
389 /* Show dev mode warning screen again */
390 VbDisplayScreen(
391 cparams,
392 VB_SCREEN_DEVELOPER_WARNING,
393 0, &vnc);
394 }
395 }
396 break;
397 default:
398 VBDEBUG(("VbBootDeveloper() - pressed key %d\n", key));
399 VbCheckDisplayKey(cparams, key, &vnc);
400 break;
401 }
402 } while(VbAudioLooping(audio));
Bill Richardson25a3dbc2011-09-23 15:14:49 -0700403
Randall Spangler29accd92013-02-04 14:01:04 -0800404 fallout:
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700405
406 /* If defaulting to legacy boot, try that unless Ctrl+D was pressed */
407 if ((gbb->flags & GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) &&
408 !ctrl_d_pressed) {
409 VBDEBUG(("VbBootDeveloper() - defaulting to legacy\n"));
410 VbExLegacy();
411
412 /* If that fails, beep and fall through to fixed disk */
413 VbExBeep(120, 400);
414 VbExSleepMs(120);
415 VbExBeep(120, 400);
416 }
417
Randall Spangler29accd92013-02-04 14:01:04 -0800418 /* Timeout or Ctrl+D; attempt loading from fixed disk */
419 VBDEBUG(("VbBootDeveloper() - trying fixed disk\n"));
420 VbAudioClose(audio);
421 return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700422}
423
Simon Glass74fa2072012-09-06 14:55:31 -0700424/* Delay in recovery mode */
Shawn Nematbakhsh04171532013-12-13 14:41:47 -0800425#define REC_DISK_DELAY 1000 /* Check disks every 1s */
426#define REC_KEY_DELAY 20 /* Check keys every 20ms */
427#define REC_MEDIA_INIT_DELAY 500 /* Check removable media every 500ms */
Randall Spangler1b1998d2011-07-01 16:12:47 -0700428
Randall Spangler29accd92013-02-04 14:01:04 -0800429VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p)
430{
431 VbSharedDataHeader *shared =
432 (VbSharedDataHeader *)cparams->shared_data_blob;
433 uint32_t retval;
434 uint32_t key;
435 int i;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700436
Randall Spangler29accd92013-02-04 14:01:04 -0800437 VBDEBUG(("VbBootRecovery() start\n"));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700438
Randall Spangler29accd92013-02-04 14:01:04 -0800439 /*
440 * If the dev-mode switch is off and the user didn't press the recovery
441 * button, require removal of all external media.
442 */
443 if (!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
444 !(shared->flags & VBSD_BOOT_REC_SWITCH_ON)) {
445 VbDiskInfo *disk_info = NULL;
446 uint32_t disk_count = 0;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700447
Randall Spangler29accd92013-02-04 14:01:04 -0800448 VBDEBUG(("VbBootRecovery() forcing device removal\n"));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700449
Shawn Nematbakhsh04171532013-12-13 14:41:47 -0800450 /* If no media is detected initially, delay and make one extra
451 * attempt, in case devices appear later than expected. */
452 if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
453 VB_DISK_FLAG_REMOVABLE))
454 disk_count = 0;
455
456 VbExDiskFreeInfo(disk_info, NULL);
457 if (0 == disk_count)
458 VbExSleepMs(REC_MEDIA_INIT_DELAY);
459
Randall Spangler29accd92013-02-04 14:01:04 -0800460 while (1) {
Shawn Nematbakhsh04171532013-12-13 14:41:47 -0800461 disk_info = NULL;
462 disk_count = 0;
Randall Spangler29accd92013-02-04 14:01:04 -0800463 if (VBERROR_SUCCESS !=
464 VbExDiskGetInfo(&disk_info, &disk_count,
465 VB_DISK_FLAG_REMOVABLE))
466 disk_count = 0;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700467
Randall Spangler29accd92013-02-04 14:01:04 -0800468 VbExDiskFreeInfo(disk_info, NULL);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700469
Randall Spangler29accd92013-02-04 14:01:04 -0800470 if (0 == disk_count) {
471 VbDisplayScreen(cparams, VB_SCREEN_BLANK,
472 0, &vnc);
473 break;
474 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700475
Randall Spangler29accd92013-02-04 14:01:04 -0800476 VBDEBUG(("VbBootRecovery() "
477 "waiting for %d disks to be removed\n",
478 (int)disk_count));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700479
Randall Spangler29accd92013-02-04 14:01:04 -0800480 VbDisplayScreen(cparams, VB_SCREEN_RECOVERY_REMOVE,
481 0, &vnc);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700482
Randall Spangler29accd92013-02-04 14:01:04 -0800483 /*
484 * Scan keyboard more frequently than media, since x86
485 * platforms don't like to scan USB too rapidly.
486 */
487 for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
488 VbCheckDisplayKey(cparams, VbExKeyboardRead(),
489 &vnc);
490 if (VbExIsShutdownRequested())
491 return VBERROR_SHUTDOWN_REQUESTED;
492 VbExSleepMs(REC_KEY_DELAY);
493 }
494 }
495 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700496
Randall Spangler29accd92013-02-04 14:01:04 -0800497 /* Loop and wait for a recovery image */
498 while (1) {
499 VBDEBUG(("VbBootRecovery() attempting to load kernel2\n"));
500 retval = VbTryLoadKernel(cparams, p, VB_DISK_FLAG_REMOVABLE);
Randall Spanglerad334852011-07-19 15:52:43 -0700501
Randall Spangler29accd92013-02-04 14:01:04 -0800502 /*
503 * Clear recovery requests from failed kernel loading, since
504 * we're already in recovery mode. Do this now, so that
505 * powering off after inserting an invalid disk doesn't leave
506 * us stuck in recovery mode.
507 */
508 VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700509
Randall Spangler29accd92013-02-04 14:01:04 -0800510 if (VBERROR_SUCCESS == retval)
511 break; /* Found a recovery kernel */
Randall Spangler1b1998d2011-07-01 16:12:47 -0700512
Randall Spangler29accd92013-02-04 14:01:04 -0800513 VbDisplayScreen(cparams, VBERROR_NO_DISK_FOUND == retval ?
514 VB_SCREEN_RECOVERY_INSERT :
515 VB_SCREEN_RECOVERY_NO_GOOD,
516 0, &vnc);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700517
Randall Spangler29accd92013-02-04 14:01:04 -0800518 /*
519 * Scan keyboard more frequently than media, since x86
520 * platforms don't like to scan USB too rapidly.
521 */
522 for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
523 key = VbExKeyboardRead();
524 /*
525 * We might want to enter dev-mode from the Insert
526 * screen if all of the following are true:
527 * - user pressed Ctrl-D
528 * - we can honor the virtual dev switch
529 * - not already in dev mode
530 * - user forced recovery mode
531 * - EC isn't pwned
532 */
533 if (key == 0x04 &&
534 shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
535 !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
536 (shared->flags & VBSD_BOOT_REC_SWITCH_ON) &&
Randall Spanglere778ada2014-07-15 16:14:21 -0700537 VbExTrustEC(0)) {
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800538 if (!(shared->flags &
539 VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
540 VbExGetSwitches(
541 VB_INIT_FLAG_REC_BUTTON_PRESSED)) {
542 /*
543 * Is the recovery button stuck? In
544 * any case we don't like this. Beep
545 * and ignore.
546 */
547 VBDEBUG(("%s() - ^D but rec switch "
548 "is pressed\n", __func__));
549 VbExBeep(120, 400);
550 continue;
551 }
552
Randall Spangler29accd92013-02-04 14:01:04 -0800553 /* Ask the user to confirm entering dev-mode */
554 VbDisplayScreen(cparams,
555 VB_SCREEN_RECOVERY_TO_DEV,
556 0, &vnc);
557 /* SPACE means no... */
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800558 uint32_t vbc_flags =
559 VB_CONFIRM_SPACE_MEANS_NO |
560 VB_CONFIRM_MUST_TRUST_KEYBOARD;
561 switch (VbUserConfirms(cparams, vbc_flags)) {
Randall Spangler29accd92013-02-04 14:01:04 -0800562 case 1:
563 VBDEBUG(("%s() Enabling dev-mode...\n",
564 __func__));
565 if (TPM_SUCCESS != SetVirtualDevMode(1))
566 return VBERROR_TPM_SET_BOOT_MODE_STATE;
567 VBDEBUG(("%s() Reboot so it will take "
568 "effect\n", __func__));
569 return VBERROR_TPM_REBOOT_REQUIRED;
570 case -1:
571 VBDEBUG(("%s() - Shutdown requested\n",
572 __func__));
573 return VBERROR_SHUTDOWN_REQUESTED;
574 default: /* zero, actually */
575 VBDEBUG(("%s() - Not enabling "
576 "dev-mode\n", __func__));
577 /*
578 * Jump out of the outer loop to
579 * refresh the display quickly.
580 */
581 i = 4;
582 break;
583 }
584 } else {
585 VbCheckDisplayKey(cparams, key, &vnc);
586 }
587 if (VbExIsShutdownRequested())
588 return VBERROR_SHUTDOWN_REQUESTED;
589 VbExSleepMs(REC_KEY_DELAY);
590 }
591 }
592
593 return VBERROR_SUCCESS;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700594}
595
Randall Spangler29accd92013-02-04 14:01:04 -0800596/**
597 * Wrapper around VbExEcProtectRW() which sets recovery reason on error.
598 */
Randall Spanglere778ada2014-07-15 16:14:21 -0700599static VbError_t EcProtectRW(int devidx)
Randall Spangler29accd92013-02-04 14:01:04 -0800600{
Randall Spanglere778ada2014-07-15 16:14:21 -0700601 int rv = VbExEcProtectRW(devidx);
Randall Spangler09d0c2e2012-07-25 15:52:51 -0700602
Randall Spangler29accd92013-02-04 14:01:04 -0800603 if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
604 VBDEBUG(("VbExEcProtectRW() needs reboot\n"));
605 } else if (rv != VBERROR_SUCCESS) {
606 VBDEBUG(("VbExEcProtectRW() returned %d\n", rv));
607 VbSetRecoveryRequest(VBNV_RECOVERY_EC_PROTECT);
608 }
609 return rv;
Randall Spangler09d0c2e2012-07-25 15:52:51 -0700610}
Randall Spangler1b1998d2011-07-01 16:12:47 -0700611
Randall Spanglere778ada2014-07-15 16:14:21 -0700612VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams)
Randall Spangler29accd92013-02-04 14:01:04 -0800613{
614 VbSharedDataHeader *shared =
615 (VbSharedDataHeader *)cparams->shared_data_blob;
616 int in_rw = 0;
617 int rv;
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800618 const uint8_t *ec_hash = NULL;
Randall Spangler29accd92013-02-04 14:01:04 -0800619 int ec_hash_size;
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800620 const uint8_t *rw_hash = NULL;
621 int rw_hash_size;
622 const uint8_t *expected = NULL;
Randall Spangler29accd92013-02-04 14:01:04 -0800623 int expected_size;
624 uint8_t expected_hash[SHA256_DIGEST_SIZE];
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800625 int need_update = 0;
Randall Spangler29accd92013-02-04 14:01:04 -0800626 int i;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700627
Randall Spangler6014c042014-07-22 14:42:58 -0700628 VBDEBUG(("VbEcSoftwareSync(devidx=%d)\n", devidx));
629
Randall Spangler29accd92013-02-04 14:01:04 -0800630 /* Determine whether the EC is in RO or RW */
Randall Spanglere778ada2014-07-15 16:14:21 -0700631 rv = VbExEcRunningRW(devidx, &in_rw);
Randall Spangler584e0d22012-07-26 10:29:48 -0700632
Randall Spangler29accd92013-02-04 14:01:04 -0800633 if (shared->recovery_reason) {
634 /* Recovery mode; just verify the EC is in RO code */
635 if (rv == VBERROR_SUCCESS && in_rw == 1) {
636 /*
637 * EC is definitely in RW firmware. We want it in
638 * read-only code, so preserve the current recovery
639 * reason and reboot.
640 *
641 * We don't reboot on error or unknown EC code, because
642 * we could end up in an endless reboot loop. If we
643 * had some way to track that we'd already rebooted for
644 * this reason, we could retry only once.
645 */
646 VBDEBUG(("VbEcSoftwareSync() - "
647 "want recovery but got EC-RW\n"));
648 VbSetRecoveryRequest(shared->recovery_reason);
649 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
650 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700651
Randall Spangler29accd92013-02-04 14:01:04 -0800652 VBDEBUG(("VbEcSoftwareSync() in recovery; EC-RO\n"));
653 return VBERROR_SUCCESS;
654 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700655
Randall Spangler29accd92013-02-04 14:01:04 -0800656 /*
657 * Not in recovery. If we couldn't determine where the EC was,
658 * reboot to recovery.
659 */
660 if (rv != VBERROR_SUCCESS) {
661 VBDEBUG(("VbEcSoftwareSync() - "
Vadim Bendebury48b26df2013-06-21 16:28:28 -0700662 "VbExEcRunningRW() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800663 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UNKNOWN_IMAGE);
664 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
665 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700666
Randall Spangler29accd92013-02-04 14:01:04 -0800667 /* If AP is read-only normal, EC should be in its RO code also. */
668 if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
669 /* If EC is in RW code, request reboot back to RO */
670 if (in_rw == 1) {
671 VBDEBUG(("VbEcSoftwareSync() - "
672 "want RO-normal but got EC-RW\n"));
673 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
674 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700675
Randall Spangler29accd92013-02-04 14:01:04 -0800676 /* Protect the RW flash and stay in EC-RO */
Randall Spanglere778ada2014-07-15 16:14:21 -0700677 rv = EcProtectRW(devidx);
Randall Spangler29accd92013-02-04 14:01:04 -0800678 if (rv != VBERROR_SUCCESS)
679 return rv;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700680
Randall Spanglere778ada2014-07-15 16:14:21 -0700681 rv = VbExEcDisableJump(devidx);
Randall Spangler29accd92013-02-04 14:01:04 -0800682 if (rv != VBERROR_SUCCESS) {
683 VBDEBUG(("VbEcSoftwareSync() - "
Daisuke Nojiri89121692013-10-10 11:51:45 -0700684 "VbExEcDisableJump() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800685 VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
686 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
687 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700688
Randall Spangler29accd92013-02-04 14:01:04 -0800689 VBDEBUG(("VbEcSoftwareSync() in RO-Normal; EC-RO\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800690 return VBERROR_SUCCESS;
691 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700692
Randall Spangler29accd92013-02-04 14:01:04 -0800693 /* Get hash of EC-RW */
Randall Spanglere778ada2014-07-15 16:14:21 -0700694 rv = VbExEcHashRW(devidx, &ec_hash, &ec_hash_size);
Randall Spangler29accd92013-02-04 14:01:04 -0800695 if (rv) {
696 VBDEBUG(("VbEcSoftwareSync() - "
697 "VbExEcHashRW() returned %d\n", rv));
698 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
699 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
700 }
701 if (ec_hash_size != SHA256_DIGEST_SIZE) {
702 VBDEBUG(("VbEcSoftwareSync() - "
703 "VbExEcHashRW() says size %d, not %d\n",
704 ec_hash_size, SHA256_DIGEST_SIZE));
705 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
706 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
707 }
Randall Spangler241de332012-07-23 16:24:43 -0700708
Randall Spangler29accd92013-02-04 14:01:04 -0800709 VBDEBUG(("EC hash:"));
710 for (i = 0; i < SHA256_DIGEST_SIZE; i++)
711 VBDEBUG(("%02x", ec_hash[i]));
712 VBDEBUG(("\n"));
Randall Spangler029ae652012-07-22 17:47:36 -0700713
Randall Spangler29accd92013-02-04 14:01:04 -0800714 /*
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800715 * Get expected EC-RW hash. Note that we've already checked for
Randall Spangler29accd92013-02-04 14:01:04 -0800716 * RO_NORMAL, so we know that the BIOS must be RW-A or RW-B, and
717 * therefore the EC must match.
718 */
Randall Spanglere778ada2014-07-15 16:14:21 -0700719 rv = VbExEcGetExpectedRWHash(devidx, shared->firmware_index ?
Randall Spangler29accd92013-02-04 14:01:04 -0800720 VB_SELECT_FIRMWARE_B : VB_SELECT_FIRMWARE_A,
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800721 &rw_hash, &rw_hash_size);
722
723 if (rv == VBERROR_EC_GET_EXPECTED_HASH_FROM_IMAGE) {
724 /*
725 * BIOS has verified EC image but doesn't have a precomputed
726 * hash for it, so we must compute the hash ourselves.
727 */
728 rw_hash = NULL;
729 } else if (rv) {
730 VBDEBUG(("VbEcSoftwareSync() - "
731 "VbExEcGetExpectedRWHash() returned %d\n", rv));
732 VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
733 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
734 } else if (rw_hash_size != SHA256_DIGEST_SIZE) {
735 VBDEBUG(("VbEcSoftwareSync() - "
736 "VbExEcGetExpectedRWHash() says size %d, not %d\n",
737 rw_hash_size, SHA256_DIGEST_SIZE));
738 VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
739 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
740 } else {
741 VBDEBUG(("Expected hash:"));
742 for (i = 0; i < SHA256_DIGEST_SIZE; i++)
743 VBDEBUG(("%02x", rw_hash[i]));
744 VBDEBUG(("\n"));
745
746 need_update = SafeMemcmp(ec_hash, rw_hash, SHA256_DIGEST_SIZE);
747 }
748
749 /*
750 * Get expected EC-RW image if we're sure we need to update (because the
751 * expected hash didn't match the EC) or we still don't know (because
752 * there was no expected hash and we need the image to compute one
753 * ourselves).
754 */
755 if (need_update || !rw_hash) {
756 /* Get expected EC-RW image */
Randall Spanglere778ada2014-07-15 16:14:21 -0700757 rv = VbExEcGetExpectedRW(devidx, shared->firmware_index ?
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800758 VB_SELECT_FIRMWARE_B :
759 VB_SELECT_FIRMWARE_A,
760 &expected, &expected_size);
761 if (rv) {
762 VBDEBUG(("VbEcSoftwareSync() - "
763 "VbExEcGetExpectedRW() returned %d\n", rv));
764 VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
765 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
766 }
767 VBDEBUG(("VbEcSoftwareSync() - expected len = %d\n",
768 expected_size));
769
770 /* Hash expected image */
771 internal_SHA256(expected, expected_size, expected_hash);
772 VBDEBUG(("Computed hash of expected image:"));
773 for (i = 0; i < SHA256_DIGEST_SIZE; i++)
774 VBDEBUG(("%02x", expected_hash[i]));
775 VBDEBUG(("\n"));
776 }
777
778 if (!rw_hash) {
779 /*
780 * BIOS didn't have expected EC hash, so check if we need
781 * update by comparing EC hash to the one we just computed.
782 */
783 need_update = SafeMemcmp(ec_hash, expected_hash,
784 SHA256_DIGEST_SIZE);
785 } else if (need_update &&
786 SafeMemcmp(rw_hash, expected_hash, SHA256_DIGEST_SIZE)) {
787 /*
788 * We need to update, but the expected EC image doesn't match
789 * the expected EC hash we were given.
790 */
Randall Spangler29accd92013-02-04 14:01:04 -0800791 VBDEBUG(("VbEcSoftwareSync() - "
792 "VbExEcGetExpectedRW() returned %d\n", rv));
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800793 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_MISMATCH);
Randall Spangler29accd92013-02-04 14:01:04 -0800794 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
795 }
Randall Spangler241de332012-07-23 16:24:43 -0700796
Randall Spangler29accd92013-02-04 14:01:04 -0800797 /*
798 * TODO: GBB flag to override whether we need update; needed for EC
799 * development.
800 */
Randall Spanglerd4faa062012-07-16 16:42:40 -0700801
Randall Spangler29accd92013-02-04 14:01:04 -0800802 if (in_rw) {
803 if (need_update) {
804 /*
Duncan Laurie731f8e82014-10-16 11:05:13 -0700805 * Check if BIOS should also load VGA Option ROM when
806 * rebooting to save another reboot if possible.
807 */
808 if ((shared->flags & VBSD_EC_SLOW_UPDATE) &&
809 (shared->flags & VBSD_OPROM_MATTERS) &&
810 !(shared->flags & VBSD_OPROM_LOADED)) {
811 VBDEBUG(("VbEcSoftwareSync() - Reboot to "
812 "load VGA Option ROM\n"));
813 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
814 }
815
816 /*
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800817 * EC is running the wrong RW image. Reboot the EC to
Randall Spangler29accd92013-02-04 14:01:04 -0800818 * RO so we can update it on the next boot.
819 */
820 VBDEBUG(("VbEcSoftwareSync() - "
821 "in RW, need to update RW, so reboot\n"));
822 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
823 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700824
Randall Spangler29accd92013-02-04 14:01:04 -0800825 VBDEBUG(("VbEcSoftwareSync() in EC-RW and it matches\n"));
826 return VBERROR_SUCCESS;
827 }
Randall Spangler241de332012-07-23 16:24:43 -0700828
Randall Spangler29accd92013-02-04 14:01:04 -0800829 /* Update EC if necessary */
830 if (need_update) {
831 VBDEBUG(("VbEcSoftwareSync() updating EC-RW...\n"));
Randall Spangler241de332012-07-23 16:24:43 -0700832
Randall Spangler29accd92013-02-04 14:01:04 -0800833 if (shared->flags & VBSD_EC_SLOW_UPDATE) {
834 VBDEBUG(("VbEcSoftwareSync() - "
835 "EC is slow. Show WAIT screen.\n"));
Duncan Laurie731f8e82014-10-16 11:05:13 -0700836
837 /* Ensure the VGA Option ROM is loaded */
838 if ((shared->flags & VBSD_OPROM_MATTERS) &&
839 !(shared->flags & VBSD_OPROM_LOADED)) {
840 VBDEBUG(("VbEcSoftwareSync() - Reboot to "
841 "load VGA Option ROM\n"));
842 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
843 return VBERROR_VGA_OPROM_MISMATCH;
844 }
845
Randall Spangler29accd92013-02-04 14:01:04 -0800846 VbDisplayScreen(cparams, VB_SCREEN_WAIT, 0, &vnc);
847 }
Randall Spangler241de332012-07-23 16:24:43 -0700848
Randall Spanglere778ada2014-07-15 16:14:21 -0700849 rv = VbExEcUpdateRW(devidx, expected, expected_size);
Randall Spanglerbbc76062013-09-20 11:18:08 -0700850
851 if (rv != VBERROR_SUCCESS) {
Randall Spangler29accd92013-02-04 14:01:04 -0800852 VBDEBUG(("VbEcSoftwareSync() - "
853 "VbExEcUpdateRW() returned %d\n", rv));
Randall Spanglerbbc76062013-09-20 11:18:08 -0700854
855 /*
856 * The EC may know it needs a reboot. It may need to
857 * unprotect RW before updating, or may need to reboot
858 * after RW updated. Either way, it's not an error
859 * requiring recovery mode.
860 *
861 * If we fail for any other reason, trigger recovery
862 * mode.
863 */
864 if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
865 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
866
Randall Spangler29accd92013-02-04 14:01:04 -0800867 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
868 }
Randall Spangler241de332012-07-23 16:24:43 -0700869
Randall Spangler29accd92013-02-04 14:01:04 -0800870 /*
871 * TODO: should ask EC to recompute its hash to verify it's
872 * correct before continuing?
873 */
874 }
Randall Spangler241de332012-07-23 16:24:43 -0700875
Randall Spangler29accd92013-02-04 14:01:04 -0800876 /* Protect EC-RW flash */
Randall Spanglere778ada2014-07-15 16:14:21 -0700877 rv = EcProtectRW(devidx);
Randall Spangler29accd92013-02-04 14:01:04 -0800878 if (rv != VBERROR_SUCCESS)
879 return rv;
Randall Spangler241de332012-07-23 16:24:43 -0700880
Randall Spangler5ca4ea02013-02-04 15:00:09 -0800881 /* Tell EC to jump to its RW image */
Randall Spangler29accd92013-02-04 14:01:04 -0800882 VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n"));
Randall Spanglere778ada2014-07-15 16:14:21 -0700883 rv = VbExEcJumpToRW(devidx);
Randall Spangler29accd92013-02-04 14:01:04 -0800884 if (rv != VBERROR_SUCCESS) {
885 VBDEBUG(("VbEcSoftwareSync() - "
886 "VbExEcJumpToRW() returned %d\n", rv));
Randall Spanglerbbc76062013-09-20 11:18:08 -0700887
888 /*
889 * If the EC booted RO-normal and a previous AP boot has called
890 * VbExEcStayInRO(), we need to reboot the EC to unlock the
891 * ability to jump to the RW firmware.
892 *
893 * All other errors trigger recovery mode.
894 */
895 if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
896 VbSetRecoveryRequest(VBNV_RECOVERY_EC_JUMP_RW);
897
Randall Spangler29accd92013-02-04 14:01:04 -0800898 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
899 }
Randall Spanglerbbc76062013-09-20 11:18:08 -0700900
Daisuke Nojiri89121692013-10-10 11:51:45 -0700901 VBDEBUG(("VbEcSoftwareSync() jumped to EC-RW\n"));
902
Randall Spanglere778ada2014-07-15 16:14:21 -0700903 rv = VbExEcDisableJump(devidx);
Daisuke Nojiri89121692013-10-10 11:51:45 -0700904 if (rv != VBERROR_SUCCESS) {
905 VBDEBUG(("VbEcSoftwareSync() - "
906 "VbExEcDisableJump() returned %d\n", rv));
907 VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
908 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
909 }
Randall Spangler241de332012-07-23 16:24:43 -0700910
Duncan Laurie731f8e82014-10-16 11:05:13 -0700911 /*
912 * Reboot to unload VGA Option ROM if:
913 * - RW update was done
914 * - the system is NOT in developer mode
915 * - the system has slow EC update flag set
916 * - the VGA Option ROM was needed and loaded
917 */
918 if (need_update &&
919 !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
920 (shared->flags & VBSD_EC_SLOW_UPDATE) &&
921 (shared->flags & VBSD_OPROM_MATTERS) &&
922 (shared->flags & VBSD_OPROM_LOADED)) {
923 VBDEBUG(("VbEcSoftwareSync() - Reboot to "
924 "unload VGA Option ROM\n"));
925 return VBERROR_VGA_OPROM_MISMATCH;
926 }
927
Randall Spangler29accd92013-02-04 14:01:04 -0800928 VBDEBUG(("VbEcSoftwareSync() in RW; done\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800929 return VBERROR_SUCCESS;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700930}
931
Simon Glass527ba812013-07-25 08:48:47 -0600932/* This function is also used by tests */
933void VbApiKernelFree(VbCommonParams *cparams)
934{
935 /* VbSelectAndLoadKernel() always allocates this, tests don't */
936 if (cparams->gbb) {
937 VbExFree(cparams->gbb);
938 cparams->gbb = NULL;
939 }
940 if (cparams->bmp) {
941 VbExFree(cparams->bmp);
942 cparams->bmp = NULL;
943 }
944}
945
Randall Spangler29accd92013-02-04 14:01:04 -0800946VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
947 VbSelectAndLoadKernelParams *kparams)
948{
949 VbSharedDataHeader *shared =
950 (VbSharedDataHeader *)cparams->shared_data_blob;
951 VbError_t retval = VBERROR_SUCCESS;
952 LoadKernelParams p;
953 uint32_t tpm_status = 0;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700954
Randall Spangler29accd92013-02-04 14:01:04 -0800955 /* Start timer */
956 shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer();
Randall Spangler1b1998d2011-07-01 16:12:47 -0700957
Randall Spangler29accd92013-02-04 14:01:04 -0800958 VbExNvStorageRead(vnc.raw);
959 VbNvSetup(&vnc);
Randall Spangler96191122011-07-08 14:01:54 -0700960
Randall Spangler29accd92013-02-04 14:01:04 -0800961 /* Clear output params in case we fail */
962 kparams->disk_handle = NULL;
963 kparams->partition_number = 0;
964 kparams->bootloader_address = 0;
965 kparams->bootloader_size = 0;
966 Memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700967
Simon Glass527ba812013-07-25 08:48:47 -0600968 cparams->bmp = NULL;
969 cparams->gbb = VbExMalloc(sizeof(*cparams->gbb));
970 retval = VbGbbReadHeader_static(cparams, cparams->gbb);
971 if (VBERROR_SUCCESS != retval)
972 goto VbSelectAndLoadKernel_exit;
973
Randall Spangler29accd92013-02-04 14:01:04 -0800974 /* Do EC software sync if necessary */
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700975 if ((shared->flags & VBSD_EC_SOFTWARE_SYNC) &&
Simon Glass527ba812013-07-25 08:48:47 -0600976 !(cparams->gbb->flags & GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)) {
Duncan Laurie731f8e82014-10-16 11:05:13 -0700977 int oprom_mismatch = 0;
978
Randall Spanglere778ada2014-07-15 16:14:21 -0700979 retval = VbEcSoftwareSync(0, cparams);
Duncan Laurie731f8e82014-10-16 11:05:13 -0700980 /* Save reboot requested until after possible PD sync */
981 if (retval == VBERROR_VGA_OPROM_MISMATCH)
982 oprom_mismatch = 1;
983 else if (retval != VBERROR_SUCCESS)
Randall Spangler29accd92013-02-04 14:01:04 -0800984 goto VbSelectAndLoadKernel_exit;
Randall Spangler6014c042014-07-22 14:42:58 -0700985
986#ifdef PD_SYNC
Duncan Laurie277dc522014-08-11 12:30:04 -0700987 if (!(cparams->gbb->flags &
988 GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC)) {
989 retval = VbEcSoftwareSync(1, cparams);
Duncan Laurie731f8e82014-10-16 11:05:13 -0700990 if (retval == VBERROR_VGA_OPROM_MISMATCH)
991 oprom_mismatch = 1;
992 else if (retval != VBERROR_SUCCESS)
Duncan Laurie277dc522014-08-11 12:30:04 -0700993 goto VbSelectAndLoadKernel_exit;
994 }
Randall Spangler6014c042014-07-22 14:42:58 -0700995#endif
Duncan Laurie731f8e82014-10-16 11:05:13 -0700996
997 /* Request reboot to unload VGA Option ROM */
998 if (oprom_mismatch) {
999 retval = VBERROR_VGA_OPROM_MISMATCH;
1000 goto VbSelectAndLoadKernel_exit;
1001 }
Randall Spangler29accd92013-02-04 14:01:04 -08001002 }
Randall Spangler1b1998d2011-07-01 16:12:47 -07001003
Randall Spangler29accd92013-02-04 14:01:04 -08001004 /* Read kernel version from the TPM. Ignore errors in recovery mode. */
1005 tpm_status = RollbackKernelRead(&shared->kernel_version_tpm);
1006 if (0 != tpm_status) {
1007 VBDEBUG(("Unable to get kernel versions from TPM\n"));
1008 if (!shared->recovery_reason) {
1009 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_R_ERROR);
1010 retval = VBERROR_TPM_READ_KERNEL;
1011 goto VbSelectAndLoadKernel_exit;
1012 }
1013 }
1014 shared->kernel_version_tpm_start = shared->kernel_version_tpm;
Randall Spanglerd4faa062012-07-16 16:42:40 -07001015
Randall Spangler29accd92013-02-04 14:01:04 -08001016 /* Fill in params for calls to LoadKernel() */
1017 Memset(&p, 0, sizeof(p));
1018 p.shared_data_blob = cparams->shared_data_blob;
1019 p.shared_data_size = cparams->shared_data_size;
1020 p.gbb_data = cparams->gbb_data;
1021 p.gbb_size = cparams->gbb_size;
Randall Spangler22e7bb22011-07-22 14:06:51 -07001022
Randall Spangler29accd92013-02-04 14:01:04 -08001023 /*
1024 * This could be set to NULL, in which case the vboot header
1025 * information about the load address and size will be used.
1026 */
1027 p.kernel_buffer = kparams->kernel_buffer;
1028 p.kernel_buffer_size = kparams->kernel_buffer_size;
Vadim Bendeburyb321dbb2012-08-01 18:44:05 -07001029
Randall Spangler29accd92013-02-04 14:01:04 -08001030 p.nv_context = &vnc;
1031 p.boot_flags = 0;
1032 if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON)
1033 p.boot_flags |= BOOT_FLAG_DEVELOPER;
Vadim Bendeburyb321dbb2012-08-01 18:44:05 -07001034
Randall Spangler29accd92013-02-04 14:01:04 -08001035 /* Handle separate normal and developer firmware builds. */
Randall Spangler64ca7882011-07-11 15:46:19 -07001036#if defined(VBOOT_FIRMWARE_TYPE_NORMAL)
Randall Spangler29accd92013-02-04 14:01:04 -08001037 /* Normal-type firmware always acts like the dev switch is off. */
1038 p.boot_flags &= ~BOOT_FLAG_DEVELOPER;
Randall Spangler64ca7882011-07-11 15:46:19 -07001039#elif defined(VBOOT_FIRMWARE_TYPE_DEVELOPER)
Randall Spangler29accd92013-02-04 14:01:04 -08001040 /* Developer-type firmware fails if the dev switch is off. */
1041 if (!(p.boot_flags & BOOT_FLAG_DEVELOPER)) {
1042 /*
1043 * Dev firmware should be signed with a key that only verifies
1044 * when the dev switch is on, so we should never get here.
1045 */
1046 VBDEBUG(("Developer firmware called with dev switch off!\n"));
1047 VbSetRecoveryRequest(VBNV_RECOVERY_RW_DEV_MISMATCH);
1048 retval = VBERROR_DEV_FIRMWARE_SWITCH_MISMATCH;
1049 goto VbSelectAndLoadKernel_exit;
1050 }
Randall Spangler64ca7882011-07-11 15:46:19 -07001051#else
Randall Spangler29accd92013-02-04 14:01:04 -08001052 /*
1053 * Recovery firmware, or merged normal+developer firmware. No need to
1054 * override flags.
1055 */
Randall Spangler64ca7882011-07-11 15:46:19 -07001056#endif
1057
Randall Spangler29accd92013-02-04 14:01:04 -08001058 /* Select boot path */
1059 if (shared->recovery_reason) {
1060 /* Recovery boot */
1061 p.boot_flags |= BOOT_FLAG_RECOVERY;
1062 retval = VbBootRecovery(cparams, &p);
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001063 VbExEcEnteringMode(0, VB_EC_RECOVERY);
Randall Spangler29accd92013-02-04 14:01:04 -08001064 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0, &vnc);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001065
Randall Spangler29accd92013-02-04 14:01:04 -08001066 } else if (p.boot_flags & BOOT_FLAG_DEVELOPER) {
1067 /* Developer boot */
1068 retval = VbBootDeveloper(cparams, &p);
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001069 VbExEcEnteringMode(0, VB_EC_DEVELOPER);
Randall Spangler29accd92013-02-04 14:01:04 -08001070 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0, &vnc);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001071
Randall Spangler29accd92013-02-04 14:01:04 -08001072 } else {
1073 /* Normal boot */
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001074 VbExEcEnteringMode(0, VB_EC_NORMAL);
Randall Spangler29accd92013-02-04 14:01:04 -08001075 retval = VbBootNormal(cparams, &p);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001076
Randall Spangler29accd92013-02-04 14:01:04 -08001077 if ((1 == shared->firmware_index) &&
1078 (shared->flags & VBSD_FWB_TRIED)) {
1079 /*
1080 * Special cases for when we're trying a new firmware
1081 * B. These are needed because firmware updates also
1082 * usually change the kernel key, which means that the
1083 * B firmware can only boot a new kernel, and the old
1084 * firmware in A can only boot the previous kernel.
1085 *
1086 * Don't advance the TPM if we're trying a new firmware
1087 * B, because we don't yet know if the new kernel will
1088 * successfully boot. We still want to be able to fall
1089 * back to the previous firmware+kernel if the new
1090 * firmware+kernel fails.
1091 *
1092 * If we found only invalid kernels, reboot and try
1093 * again. This allows us to fall back to the previous
1094 * firmware+kernel instead of giving up and going to
1095 * recovery mode right away. We'll still go to
1096 * recovery mode if we run out of tries and the old
1097 * firmware can't find a kernel it likes.
1098 */
1099 if (VBERROR_INVALID_KERNEL_FOUND == retval) {
1100 VBDEBUG(("Trying firmware B, "
1101 "and only found invalid kernels.\n"));
1102 VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);
1103 goto VbSelectAndLoadKernel_exit;
1104 }
1105 } else {
1106 /* Not trying a new firmware B. */
Randall Spangler99275122011-07-26 16:26:59 -07001107
Randall Spangler29accd92013-02-04 14:01:04 -08001108 /* See if we need to update the TPM. */
1109 VBDEBUG(("Checking if TPM kernel version needs "
1110 "advancing\n"));
1111 if (shared->kernel_version_tpm >
1112 shared->kernel_version_tpm_start) {
1113 tpm_status = RollbackKernelWrite(
1114 shared->kernel_version_tpm);
1115 if (0 != tpm_status) {
1116 VBDEBUG(("Error writing kernel "
1117 "versions to TPM.\n"));
1118 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_W_ERROR);
1119 retval = VBERROR_TPM_WRITE_KERNEL;
1120 goto VbSelectAndLoadKernel_exit;
1121 }
1122 }
1123 }
1124 }
Randall Spangler99275122011-07-26 16:26:59 -07001125
Randall Spangler29accd92013-02-04 14:01:04 -08001126 if (VBERROR_SUCCESS != retval)
1127 goto VbSelectAndLoadKernel_exit;
Randall Spangler1b1998d2011-07-01 16:12:47 -07001128
Randall Spangler29accd92013-02-04 14:01:04 -08001129 /* Save disk parameters */
1130 kparams->disk_handle = p.disk_handle;
1131 kparams->partition_number = (uint32_t)p.partition_number;
1132 kparams->bootloader_address = p.bootloader_address;
1133 kparams->bootloader_size = (uint32_t)p.bootloader_size;
1134 Memcpy(kparams->partition_guid, p.partition_guid,
1135 sizeof(kparams->partition_guid));
Randall Spangler22e7bb22011-07-22 14:06:51 -07001136
Randall Spangler29accd92013-02-04 14:01:04 -08001137 /* Lock the kernel versions. Ignore errors in recovery mode. */
Shawn Nematbakhsh964144b2013-07-22 13:33:46 -07001138 tpm_status = RollbackKernelLock(shared->recovery_reason);
Randall Spangler29accd92013-02-04 14:01:04 -08001139 if (0 != tpm_status) {
1140 VBDEBUG(("Error locking kernel versions.\n"));
1141 if (!shared->recovery_reason) {
1142 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_L_ERROR);
1143 retval = VBERROR_TPM_LOCK_KERNEL;
1144 goto VbSelectAndLoadKernel_exit;
1145 }
1146 }
Randall Spangler22e7bb22011-07-22 14:06:51 -07001147
Randall Spangler29accd92013-02-04 14:01:04 -08001148 VbSelectAndLoadKernel_exit:
Randall Spangler1b1998d2011-07-01 16:12:47 -07001149
Simon Glass527ba812013-07-25 08:48:47 -06001150 VbApiKernelFree(cparams);
1151
Randall Spangler29accd92013-02-04 14:01:04 -08001152 VbNvTeardown(&vnc);
1153 if (vnc.raw_changed)
1154 VbExNvStorageWrite(vnc.raw);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001155
Randall Spangler29accd92013-02-04 14:01:04 -08001156 /* Stop timer */
1157 shared->timer_vb_select_and_load_kernel_exit = VbExGetTimer();
Randall Spangler1b1998d2011-07-01 16:12:47 -07001158
Randall Spangler29accd92013-02-04 14:01:04 -08001159 kparams->kernel_buffer = p.kernel_buffer;
1160 kparams->kernel_buffer_size = p.kernel_buffer_size;
Randall Spangler96191122011-07-08 14:01:54 -07001161
Randall Spangler29accd92013-02-04 14:01:04 -08001162 VBDEBUG(("VbSelectAndLoadKernel() returning %d\n", (int)retval));
Vadim Bendeburyb321dbb2012-08-01 18:44:05 -07001163
Randall Spangler29accd92013-02-04 14:01:04 -08001164 /* Pass through return value from boot path */
1165 return retval;
Randall Spangler1b1998d2011-07-01 16:12:47 -07001166}