blob: 6a2aba32fa1cde22bfb34c38a454b285902929e3 [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;
Randall Spangler946abf12016-04-15 14:49:40 -070025static struct RollbackSpaceFwmp fwmp;
Randall Spangler1b1998d2011-07-01 16:12:47 -070026
Randall Spangler1b1998d2011-07-01 16:12:47 -070027#ifdef CHROMEOS_ENVIRONMENT
Randall Spangler946abf12016-04-15 14:49:40 -070028/* Global variable accessors for unit tests */
Randall Spangler29accd92013-02-04 14:01:04 -080029
30VbNvContext *VbApiKernelGetVnc(void)
31{
32 return &vnc;
Randall Spangler1b1998d2011-07-01 16:12:47 -070033}
Randall Spangler946abf12016-04-15 14:49:40 -070034
35struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void)
36{
37 return &fwmp;
38}
Randall Spangler1b1998d2011-07-01 16:12:47 -070039#endif
40
Randall Spangler29accd92013-02-04 14:01:04 -080041/**
Randall Spangler7f436692013-02-05 12:42:36 -080042 * Set recovery request (called from vboot_api_kernel.c functions only)
Randall Spangler29accd92013-02-04 14:01:04 -080043 */
44static void VbSetRecoveryRequest(uint32_t recovery_request)
45{
46 VBDEBUG(("VbSetRecoveryRequest(%d)\n", (int)recovery_request));
47 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, recovery_request);
Randall Spangler1b1998d2011-07-01 16:12:47 -070048}
49
Daisuke Nojiri3a631482015-10-20 18:31:10 -070050static void VbSetRecoverySubcode(uint32_t recovery_request)
51{
52 VBDEBUG(("VbSetRecoverySubcode(%d)\n", (int)recovery_request));
53 VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, recovery_request);
54}
55
56static void VbNvCommit(void)
57{
58 VbNvTeardown(&vnc);
59 if (vnc.raw_changed)
60 VbExNvStorageWrite(vnc.raw);
61}
62
Vadim Bendeburyccca6662015-04-06 18:04:44 -070063static void VbAllowUsbBoot(void)
64{
65 VBDEBUG(("%s\n", __func__));
66 VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 1);
67}
68
Randall Spangler29accd92013-02-04 14:01:04 -080069/**
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -080070 * Checks GBB flags against VbExIsShutdownRequested() shutdown request to
71 * determine if a shutdown is required.
72 *
73 * Returns true if a shutdown is required and false if no shutdown is required.
74 */
75static int VbWantShutdown(uint32_t gbb_flags)
76{
77 uint32_t shutdown_request = VbExIsShutdownRequested();
78
79 /* If desired, ignore shutdown request due to lid closure. */
80 if (gbb_flags & GBB_FLAG_DISABLE_LID_SHUTDOWN)
81 shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED;
82
83 return !!shutdown_request;
84}
85
Julius Werner957b4242015-05-08 22:54:14 -070086static void VbTryLegacy(int allowed)
87{
88 if (!allowed)
89 VBDEBUG(("VbBootDeveloper() - Legacy boot is disabled\n"));
90 else if (0 != RollbackKernelLock(0))
91 VBDEBUG(("Error locking kernel versions on legacy boot.\n"));
92 else
93 VbExLegacy(); /* will not return if successful */
94
95 /* If legacy boot fails, beep and return to calling UI loop. */
96 VbExBeep(120, 400);
97 VbExSleepMs(120);
98 VbExBeep(120, 400);
99}
100
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800101/**
Randall Spangler29accd92013-02-04 14:01:04 -0800102 * Attempt loading a kernel from the specified type(s) of disks.
103 *
104 * If successful, sets p->disk_handle to the disk for the kernel and returns
Randall Spangler1cf77cd2011-07-25 09:19:58 -0700105 * VBERROR_SUCCESS.
106 *
107 * Returns VBERROR_NO_DISK_FOUND if no disks of the specified type were found.
108 *
Randall Spangler29accd92013-02-04 14:01:04 -0800109 * May return other VBERROR_ codes for other failures.
110 */
111uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p,
112 uint32_t get_info_flags)
113{
114 VbError_t retval = VBERROR_UNKNOWN;
115 VbDiskInfo* disk_info = NULL;
116 uint32_t disk_count = 0;
117 uint32_t i;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700118
Randall Spangler29accd92013-02-04 14:01:04 -0800119 VBDEBUG(("VbTryLoadKernel() start, get_info_flags=0x%x\n",
120 (unsigned)get_info_flags));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700121
Randall Spangler29accd92013-02-04 14:01:04 -0800122 p->disk_handle = NULL;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700123
Randall Spangler29accd92013-02-04 14:01:04 -0800124 /* Find disks */
125 if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
126 get_info_flags))
127 disk_count = 0;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700128
Randall Spangler29accd92013-02-04 14:01:04 -0800129 VBDEBUG(("VbTryLoadKernel() found %d disks\n", (int)disk_count));
130 if (0 == disk_count) {
131 VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_DISK);
132 return VBERROR_NO_DISK_FOUND;
133 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700134
Randall Spangler29accd92013-02-04 14:01:04 -0800135 /* Loop over disks */
136 for (i = 0; i < disk_count; i++) {
137 VBDEBUG(("VbTryLoadKernel() trying disk %d\n", (int)i));
138 /*
139 * Sanity-check what we can. FWIW, VbTryLoadKernel() is always
140 * called with only a single bit set in get_info_flags.
141 *
142 * Ensure 512-byte sectors and non-trivially sized disk (for
143 * cgptlib) and that we got a partition with only the flags we
144 * asked for.
145 */
146 if (512 != disk_info[i].bytes_per_lba ||
Dan Ehrenbergf47eccf2015-01-05 13:05:58 -0800147 16 > disk_info[i].lba_count ||
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800148 get_info_flags != (disk_info[i].flags & ~VB_DISK_FLAG_EXTERNAL_GPT)) {
Simon Glass981cb2a2013-08-12 15:12:47 -0600149 VBDEBUG((" skipping: bytes_per_lba=%" PRIu64
150 " lba_count=%" PRIu64 " flags=0x%x\n",
Randall Spangler29accd92013-02-04 14:01:04 -0800151 disk_info[i].bytes_per_lba,
152 disk_info[i].lba_count,
153 disk_info[i].flags));
154 continue;
155 }
156 p->disk_handle = disk_info[i].handle;
157 p->bytes_per_lba = disk_info[i].bytes_per_lba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800158 p->gpt_lba_count = disk_info[i].lba_count;
159 p->streaming_lba_count = disk_info[i].streaming_lba_count
160 ?: p->gpt_lba_count;
161 p->boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT
162 ? BOOT_FLAG_EXTERNAL_GPT : 0;
Simon Glass527ba812013-07-25 08:48:47 -0600163 retval = LoadKernel(p, cparams);
Randall Spangler29accd92013-02-04 14:01:04 -0800164 VBDEBUG(("VbTryLoadKernel() LoadKernel() = %d\n", retval));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700165
Randall Spangler29accd92013-02-04 14:01:04 -0800166 /*
167 * Stop now if we found a kernel.
168 *
169 * TODO: If recovery requested, should track the farthest we
170 * get, instead of just returning the value from the last disk
171 * attempted.
172 */
173 if (VBERROR_SUCCESS == retval)
174 break;
175 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700176
Randall Spangler29accd92013-02-04 14:01:04 -0800177 /* If we didn't find any good kernels, don't return a disk handle. */
178 if (VBERROR_SUCCESS != retval) {
179 VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_KERNEL);
180 p->disk_handle = NULL;
181 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700182
Randall Spangler29accd92013-02-04 14:01:04 -0800183 VbExDiskFreeInfo(disk_info, p->disk_handle);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700184
Randall Spangler29accd92013-02-04 14:01:04 -0800185 /*
186 * Pass through return code. Recovery reason (if any) has already been
187 * set by LoadKernel().
188 */
189 return retval;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700190}
191
Mary Ruthven12a55f22015-10-06 10:42:31 -0700192uint32_t VbTryUsb(VbCommonParams *cparams, LoadKernelParams *p)
193{
194 uint32_t retval = VbTryLoadKernel(cparams, p, VB_DISK_FLAG_REMOVABLE);
195 if (VBERROR_SUCCESS == retval) {
196 VBDEBUG(("VbBootDeveloper() - booting USB\n"));
197 } else {
198 VBDEBUG(("VbBootDeveloper() - no kernel found on USB\n"));
199 VbExBeep(250, 200);
200 VbExSleepMs(120);
201 /*
202 * Clear recovery requests from failed
203 * kernel loading, so that powering off
204 * at this point doesn't put us into
205 * recovery mode.
206 */
207 VbSetRecoveryRequest(
208 VBNV_RECOVERY_NOT_REQUESTED);
209 }
210 return retval;
211}
212
Shawn Nematbakhshba7fd8d2012-10-30 15:17:33 -0700213#define CONFIRM_KEY_DELAY 20 /* Check confirm screen keys every 20ms */
214
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800215int VbUserConfirms(VbCommonParams *cparams, uint32_t confirm_flags)
Randall Spangler29accd92013-02-04 14:01:04 -0800216{
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800217 VbSharedDataHeader *shared =
218 (VbSharedDataHeader *)cparams->shared_data_blob;
Randall Spangler29accd92013-02-04 14:01:04 -0800219 uint32_t key;
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800220 uint32_t key_flags;
221 uint32_t button;
222 int rec_button_was_pressed = 0;
Bill Richardson29344752012-08-01 15:02:15 -0700223
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800224 VBDEBUG(("Entering %s(0x%x)\n", __func__, confirm_flags));
Bill Richardson29344752012-08-01 15:02:15 -0700225
Randall Spangler29accd92013-02-04 14:01:04 -0800226 /* Await further instructions */
227 while (1) {
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800228 if (VbWantShutdown(cparams->gbb->flags))
Randall Spangler29accd92013-02-04 14:01:04 -0800229 return -1;
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800230 key = VbExKeyboardReadWithFlags(&key_flags);
231 button = VbExGetSwitches(VB_INIT_FLAG_REC_BUTTON_PRESSED);
Randall Spangler29accd92013-02-04 14:01:04 -0800232 switch (key) {
233 case '\r':
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800234 /* If we require a trusted keyboard for confirmation,
235 * but the keyboard may be faked (for instance, a USB
236 * device), beep and keep waiting.
237 */
238 if (confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD &&
239 !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) {
240 VbExBeep(120, 400);
241 break;
242 }
243
Randall Spangler29accd92013-02-04 14:01:04 -0800244 VBDEBUG(("%s() - Yes (1)\n", __func__));
245 return 1;
246 break;
247 case ' ':
Vadim Bendebury7aa250f2013-08-09 16:02:28 -0700248 VBDEBUG(("%s() - Space (%d)\n", __func__,
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800249 confirm_flags & VB_CONFIRM_SPACE_MEANS_NO));
250 if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO)
Randall Spangler29accd92013-02-04 14:01:04 -0800251 return 0;
252 break;
253 case 0x1b:
254 VBDEBUG(("%s() - No (0)\n", __func__));
255 return 0;
256 break;
257 default:
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800258 /* If the recovery button is physical, and is pressed,
259 * this is also a YES, but must wait for release.
260 */
261 if (!(shared->flags & VBSD_BOOT_REC_SWITCH_VIRTUAL)) {
262 if (button) {
263 VBDEBUG(("%s() - Rec button pressed\n",
264 __func__));
265 rec_button_was_pressed = 1;
266 } else if (rec_button_was_pressed) {
267 VBDEBUG(("%s() - Rec button (1)\n",
268 __func__));
269 return 1;
270 }
271 }
Randall Spangler29accd92013-02-04 14:01:04 -0800272 VbCheckDisplayKey(cparams, key, &vnc);
273 }
274 VbExSleepMs(CONFIRM_KEY_DELAY);
275 }
276
277 /* Not reached, but compiler will complain without it */
278 return -1;
Bill Richardson29344752012-08-01 15:02:15 -0700279}
280
Yunlian Jiang637ff032015-06-09 16:21:56 -0700281VbError_t test_mockable
282VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p)
Randall Spangler29accd92013-02-04 14:01:04 -0800283{
284 /* Boot from fixed disk only */
285 VBDEBUG(("Entering %s()\n", __func__));
286 return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700287}
288
Randall Spangler946abf12016-04-15 14:49:40 -0700289static const char dev_disable_msg[] =
290 "Developer mode is disabled on this device by system policy.\n"
291 "For more information, see http://dev.chromium.org/chromium-os/fwmp\n"
292 "\n";
293
Randall Spangler29accd92013-02-04 14:01:04 -0800294VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p)
295{
Simon Glass527ba812013-07-25 08:48:47 -0600296 GoogleBinaryBlockHeader *gbb = cparams->gbb;
Randall Spangler29accd92013-02-04 14:01:04 -0800297 VbSharedDataHeader *shared =
298 (VbSharedDataHeader *)cparams->shared_data_blob;
Mary Ruthven12a55f22015-10-06 10:42:31 -0700299
300 uint32_t allow_usb = 0;
301 uint32_t allow_legacy = 0;
Randall Spangler946abf12016-04-15 14:49:40 -0700302 uint32_t disable_dev_boot = 0;
Mary Ruthven12a55f22015-10-06 10:42:31 -0700303 uint32_t use_usb = 0;
304 uint32_t use_legacy = 0;
305 uint32_t default_boot = 0;
306 uint32_t ctrl_d_pressed = 0;
307
Randall Spangler29accd92013-02-04 14:01:04 -0800308 VbAudioContext *audio = 0;
Randall Spanglerdaa807c2011-07-11 10:55:18 -0700309
Randall Spangler29accd92013-02-04 14:01:04 -0800310 VBDEBUG(("Entering %s()\n", __func__));
Bill Richardsonec8df162012-06-07 04:21:14 -0700311
Randall Spangler29accd92013-02-04 14:01:04 -0800312 /* Check if USB booting is allowed */
313 VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &allow_usb);
314 VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &allow_legacy);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700315
Mary Ruthven12a55f22015-10-06 10:42:31 -0700316 /* Check if the default is to boot using disk, usb, or legacy */
317 VbNvGet(&vnc, VBNV_DEV_DEFAULT_BOOT, &default_boot);
318
319 if(default_boot == VBNV_DEV_DEFAULT_BOOT_USB)
320 use_usb = 1;
321 if(default_boot == VBNV_DEV_DEFAULT_BOOT_LEGACY)
322 use_legacy = 1;
323
Randall Spangler29accd92013-02-04 14:01:04 -0800324 /* Handle GBB flag override */
325 if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_USB)
326 allow_usb = 1;
327 if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_LEGACY)
328 allow_legacy = 1;
Mary Ruthven12a55f22015-10-06 10:42:31 -0700329 if (gbb->flags & GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) {
330 use_legacy = 1;
331 use_usb = 0;
332 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700333
Randall Spangler946abf12016-04-15 14:49:40 -0700334 /* Handle FWMP override */
335 if (fwmp.flags & FWMP_DEV_ENABLE_USB)
336 allow_usb = 1;
337 if (fwmp.flags & FWMP_DEV_ENABLE_LEGACY)
338 allow_legacy = 1;
339 if (fwmp.flags & FWMP_DEV_DISABLE_BOOT) {
340 if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) {
341 VBDEBUG(("%s() - FWMP_DEV_DISABLE_BOOT rejected by "
342 "FORCE_DEV_SWITCH_ON\n",
343 __func__));
344 } else {
345 disable_dev_boot = 1;
346 }
347 }
348
349 /* If dev mode is disabled, only allow TONORM */
350 while (disable_dev_boot) {
351 VBDEBUG(("%s() - dev_disable_boot is set.\n", __func__));
352 VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_TO_NORM, 0, &vnc);
353 VbExDisplayDebugInfo(dev_disable_msg);
354
355 /* Ignore space in VbUserConfirms()... */
356 switch (VbUserConfirms(cparams, 0)) {
357 case 1:
358 VBDEBUG(("%s() - leaving dev-mode.\n", __func__));
359 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 1);
360 VbDisplayScreen(cparams,
361 VB_SCREEN_TO_NORM_CONFIRMED,
362 0, &vnc);
363 VbExSleepMs(5000);
364 return VBERROR_TPM_REBOOT_REQUIRED;
365 case -1:
366 VBDEBUG(("%s() - shutdown requested\n", __func__));
367 return VBERROR_SHUTDOWN_REQUESTED;
368 default:
369 /* Ignore user attempt to cancel */
370 VBDEBUG(("%s() - ignore cancel TONORM\n", __func__));
371 }
372 }
373
Randall Spangler29accd92013-02-04 14:01:04 -0800374 /* Show the dev mode warning screen */
375 VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_WARNING, 0, &vnc);
Bill Richardson25a3dbc2011-09-23 15:14:49 -0700376
Randall Spangler29accd92013-02-04 14:01:04 -0800377 /* Get audio/delay context */
378 audio = VbAudioOpen(cparams);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700379
Randall Spangler29accd92013-02-04 14:01:04 -0800380 /* We'll loop until we finish the delay or are interrupted */
381 do {
382 uint32_t key;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700383
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800384 if (VbWantShutdown(gbb->flags)) {
Randall Spangler29accd92013-02-04 14:01:04 -0800385 VBDEBUG(("VbBootDeveloper() - shutdown requested!\n"));
386 VbAudioClose(audio);
387 return VBERROR_SHUTDOWN_REQUESTED;
388 }
Stefan Reinauera2326ee2012-08-23 15:06:45 -0700389
Randall Spangler29accd92013-02-04 14:01:04 -0800390 key = VbExKeyboardRead();
391 switch (key) {
392 case 0:
393 /* nothing pressed */
394 break;
395 case '\r':
396 /* Only disable virtual dev switch if allowed by GBB */
397 if (!(gbb->flags & GBB_FLAG_ENTER_TRIGGERS_TONORM))
398 break;
399 case ' ':
400 /* See if we should disable virtual dev-mode switch. */
401 VBDEBUG(("%s shared->flags=0x%x\n",
402 __func__, shared->flags));
403 if (shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
404 shared->flags & VBSD_BOOT_DEV_SWITCH_ON) {
405 /* Stop the countdown while we go ask... */
406 VbAudioClose(audio);
407 if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) {
408 /*
409 * TONORM won't work (only for
410 * non-shipping devices).
411 */
412 VBDEBUG(("%s() - TONORM rejected by "
413 "FORCE_DEV_SWITCH_ON\n",
414 __func__));
415 VbExDisplayDebugInfo(
416 "WARNING: TONORM prohibited by "
417 "GBB FORCE_DEV_SWITCH_ON.\n\n");
418 VbExBeep(120, 400);
419 break;
420 }
421 VbDisplayScreen(cparams,
422 VB_SCREEN_DEVELOPER_TO_NORM,
423 0, &vnc);
424 /* Ignore space in VbUserConfirms()... */
425 switch (VbUserConfirms(cparams, 0)) {
426 case 1:
427 VBDEBUG(("%s() - leaving dev-mode.\n",
428 __func__));
429 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST,
430 1);
431 VbDisplayScreen(
432 cparams,
433 VB_SCREEN_TO_NORM_CONFIRMED,
434 0, &vnc);
435 VbExSleepMs(5000);
436 return VBERROR_TPM_REBOOT_REQUIRED;
437 case -1:
438 VBDEBUG(("%s() - shutdown requested\n",
439 __func__));
440 return VBERROR_SHUTDOWN_REQUESTED;
441 default:
442 /* Stay in dev-mode */
443 VBDEBUG(("%s() - stay in dev-mode\n",
444 __func__));
445 VbDisplayScreen(
446 cparams,
447 VB_SCREEN_DEVELOPER_WARNING,
448 0, &vnc);
449 /* Start new countdown */
450 audio = VbAudioOpen(cparams);
451 }
452 } else {
453 /*
454 * No virtual dev-mode switch, so go directly
455 * to recovery mode.
456 */
457 VBDEBUG(("%s() - going to recovery\n",
458 __func__));
459 VbSetRecoveryRequest(
460 VBNV_RECOVERY_RW_DEV_SCREEN);
461 VbAudioClose(audio);
462 return VBERROR_LOAD_KERNEL_RECOVERY;
463 }
464 break;
465 case 0x04:
466 /* Ctrl+D = dismiss warning; advance to timeout */
467 VBDEBUG(("VbBootDeveloper() - "
468 "user pressed Ctrl+D; skip delay\n"));
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700469 ctrl_d_pressed = 1;
Randall Spangler29accd92013-02-04 14:01:04 -0800470 goto fallout;
471 break;
472 case 0x0c:
473 VBDEBUG(("VbBootDeveloper() - "
474 "user pressed Ctrl+L; Try legacy boot\n"));
Julius Werner957b4242015-05-08 22:54:14 -0700475 VbTryLegacy(allow_legacy);
Randall Spangler29accd92013-02-04 14:01:04 -0800476 break;
477
Randall Spangler7f436692013-02-05 12:42:36 -0800478 case VB_KEY_CTRL_ENTER:
479 /*
480 * The Ctrl-Enter is special for Lumpy test purpose;
481 * fall through to Ctrl+U handler.
482 */
Randall Spangler29accd92013-02-04 14:01:04 -0800483 case 0x15:
484 /* Ctrl+U = try USB boot, or beep if failure */
485 VBDEBUG(("VbBootDeveloper() - "
486 "user pressed Ctrl+U; try USB\n"));
487 if (!allow_usb) {
488 VBDEBUG(("VbBootDeveloper() - "
489 "USB booting is disabled\n"));
490 VbExDisplayDebugInfo(
491 "WARNING: Booting from external media "
492 "(USB/SD) has not been enabled. Refer "
493 "to the developer-mode documentation "
494 "for details.\n");
495 VbExBeep(120, 400);
496 VbExSleepMs(120);
497 VbExBeep(120, 400);
498 } else {
499 /*
500 * Clear the screen to show we get the Ctrl+U
501 * key press.
502 */
503 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0,
504 &vnc);
Mary Ruthven12a55f22015-10-06 10:42:31 -0700505 if (VBERROR_SUCCESS == VbTryUsb(cparams, p)) {
Randall Spangler29accd92013-02-04 14:01:04 -0800506 VbAudioClose(audio);
507 return VBERROR_SUCCESS;
508 } else {
Randall Spangler29accd92013-02-04 14:01:04 -0800509 /* Show dev mode warning screen again */
510 VbDisplayScreen(
511 cparams,
512 VB_SCREEN_DEVELOPER_WARNING,
513 0, &vnc);
514 }
515 }
516 break;
517 default:
518 VBDEBUG(("VbBootDeveloper() - pressed key %d\n", key));
519 VbCheckDisplayKey(cparams, key, &vnc);
520 break;
521 }
522 } while(VbAudioLooping(audio));
Bill Richardson25a3dbc2011-09-23 15:14:49 -0700523
Randall Spangler29accd92013-02-04 14:01:04 -0800524 fallout:
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700525
526 /* If defaulting to legacy boot, try that unless Ctrl+D was pressed */
Mary Ruthven12a55f22015-10-06 10:42:31 -0700527 if (use_legacy && !ctrl_d_pressed) {
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700528 VBDEBUG(("VbBootDeveloper() - defaulting to legacy\n"));
Julius Werner0140cd22015-05-08 23:00:16 -0700529 VbTryLegacy(allow_legacy);
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700530 }
531
Mary Ruthven12a55f22015-10-06 10:42:31 -0700532 if ((use_usb && !ctrl_d_pressed) && allow_usb) {
533 if (VBERROR_SUCCESS == VbTryUsb(cparams, p)) {
534 VbAudioClose(audio);
535 return VBERROR_SUCCESS;
536 }
537 }
538
Randall Spangler29accd92013-02-04 14:01:04 -0800539 /* Timeout or Ctrl+D; attempt loading from fixed disk */
540 VBDEBUG(("VbBootDeveloper() - trying fixed disk\n"));
541 VbAudioClose(audio);
542 return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700543}
544
Simon Glass74fa2072012-09-06 14:55:31 -0700545/* Delay in recovery mode */
Shawn Nematbakhsh04171532013-12-13 14:41:47 -0800546#define REC_DISK_DELAY 1000 /* Check disks every 1s */
547#define REC_KEY_DELAY 20 /* Check keys every 20ms */
548#define REC_MEDIA_INIT_DELAY 500 /* Check removable media every 500ms */
Randall Spangler1b1998d2011-07-01 16:12:47 -0700549
Randall Spangler29accd92013-02-04 14:01:04 -0800550VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p)
551{
552 VbSharedDataHeader *shared =
553 (VbSharedDataHeader *)cparams->shared_data_blob;
554 uint32_t retval;
555 uint32_t key;
556 int i;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700557
Randall Spangler29accd92013-02-04 14:01:04 -0800558 VBDEBUG(("VbBootRecovery() start\n"));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700559
Randall Spangler29accd92013-02-04 14:01:04 -0800560 /*
561 * If the dev-mode switch is off and the user didn't press the recovery
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700562 * button (recovery was triggerred automatically), show 'broken' screen.
563 * The user can either only shutdown to abort or hit esc+refresh+power
564 * to initiate recovery as instructed on the screen.
Randall Spangler29accd92013-02-04 14:01:04 -0800565 */
566 if (!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
567 !(shared->flags & VBSD_BOOT_REC_SWITCH_ON)) {
Daisuke Nojiri3a631482015-10-20 18:31:10 -0700568 /*
569 * We have to save the reason here so that it will survive
570 * coming up three-finger-salute. We're saving it in
571 * VBNV_RECOVERY_SUBCODE to avoid a recovery loop.
572 * If we save the reason in VBNV_RECOVERY_REQUEST, we will come
573 * back here, thus, we won't be able to give a user a chance to
574 * reboot to workaround boot hicups.
575 */
576 VBDEBUG(("VbBootRecovery() saving recovery reason (%#x)\n",
577 shared->recovery_reason));
578 VbSetRecoverySubcode(shared->recovery_reason);
579 VbNvCommit();
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700580 VbDisplayScreen(cparams, VB_SCREEN_OS_BROKEN, 0, &vnc);
Daisuke Nojiri3a631482015-10-20 18:31:10 -0700581 VBDEBUG(("VbBootRecovery() waiting for manual recovery\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800582 while (1) {
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700583 VbCheckDisplayKey(cparams, VbExKeyboardRead(), &vnc);
584 if (VbWantShutdown(cparams->gbb->flags))
585 return VBERROR_SHUTDOWN_REQUESTED;
586 VbExSleepMs(REC_KEY_DELAY);
Randall Spangler29accd92013-02-04 14:01:04 -0800587 }
588 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700589
Randall Spangler29accd92013-02-04 14:01:04 -0800590 /* Loop and wait for a recovery image */
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700591 VBDEBUG(("VbBootRecovery() waiting for a recovery image\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800592 while (1) {
593 VBDEBUG(("VbBootRecovery() attempting to load kernel2\n"));
594 retval = VbTryLoadKernel(cparams, p, VB_DISK_FLAG_REMOVABLE);
Randall Spanglerad334852011-07-19 15:52:43 -0700595
Randall Spangler29accd92013-02-04 14:01:04 -0800596 /*
597 * Clear recovery requests from failed kernel loading, since
598 * we're already in recovery mode. Do this now, so that
599 * powering off after inserting an invalid disk doesn't leave
600 * us stuck in recovery mode.
601 */
602 VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700603
Randall Spangler29accd92013-02-04 14:01:04 -0800604 if (VBERROR_SUCCESS == retval)
605 break; /* Found a recovery kernel */
Randall Spangler1b1998d2011-07-01 16:12:47 -0700606
Randall Spangler29accd92013-02-04 14:01:04 -0800607 VbDisplayScreen(cparams, VBERROR_NO_DISK_FOUND == retval ?
608 VB_SCREEN_RECOVERY_INSERT :
609 VB_SCREEN_RECOVERY_NO_GOOD,
610 0, &vnc);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700611
Randall Spangler29accd92013-02-04 14:01:04 -0800612 /*
613 * Scan keyboard more frequently than media, since x86
614 * platforms don't like to scan USB too rapidly.
615 */
616 for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
617 key = VbExKeyboardRead();
618 /*
619 * We might want to enter dev-mode from the Insert
620 * screen if all of the following are true:
621 * - user pressed Ctrl-D
622 * - we can honor the virtual dev switch
623 * - not already in dev mode
624 * - user forced recovery mode
625 * - EC isn't pwned
626 */
627 if (key == 0x04 &&
628 shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
629 !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
630 (shared->flags & VBSD_BOOT_REC_SWITCH_ON) &&
Randall Spanglere778ada2014-07-15 16:14:21 -0700631 VbExTrustEC(0)) {
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800632 if (!(shared->flags &
633 VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
634 VbExGetSwitches(
635 VB_INIT_FLAG_REC_BUTTON_PRESSED)) {
636 /*
637 * Is the recovery button stuck? In
638 * any case we don't like this. Beep
639 * and ignore.
640 */
641 VBDEBUG(("%s() - ^D but rec switch "
642 "is pressed\n", __func__));
643 VbExBeep(120, 400);
644 continue;
645 }
646
Randall Spangler29accd92013-02-04 14:01:04 -0800647 /* Ask the user to confirm entering dev-mode */
648 VbDisplayScreen(cparams,
649 VB_SCREEN_RECOVERY_TO_DEV,
650 0, &vnc);
651 /* SPACE means no... */
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800652 uint32_t vbc_flags =
653 VB_CONFIRM_SPACE_MEANS_NO |
654 VB_CONFIRM_MUST_TRUST_KEYBOARD;
655 switch (VbUserConfirms(cparams, vbc_flags)) {
Randall Spangler29accd92013-02-04 14:01:04 -0800656 case 1:
657 VBDEBUG(("%s() Enabling dev-mode...\n",
658 __func__));
659 if (TPM_SUCCESS != SetVirtualDevMode(1))
660 return VBERROR_TPM_SET_BOOT_MODE_STATE;
661 VBDEBUG(("%s() Reboot so it will take "
662 "effect\n", __func__));
Vadim Bendeburyccca6662015-04-06 18:04:44 -0700663 if (VbExGetSwitches
664 (VB_INIT_FLAG_ALLOW_USB_BOOT))
665 VbAllowUsbBoot();
Randall Spangler29accd92013-02-04 14:01:04 -0800666 return VBERROR_TPM_REBOOT_REQUIRED;
667 case -1:
668 VBDEBUG(("%s() - Shutdown requested\n",
669 __func__));
670 return VBERROR_SHUTDOWN_REQUESTED;
671 default: /* zero, actually */
672 VBDEBUG(("%s() - Not enabling "
673 "dev-mode\n", __func__));
674 /*
675 * Jump out of the outer loop to
676 * refresh the display quickly.
677 */
678 i = 4;
679 break;
680 }
681 } else {
682 VbCheckDisplayKey(cparams, key, &vnc);
683 }
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800684 if (VbWantShutdown(cparams->gbb->flags))
Randall Spangler29accd92013-02-04 14:01:04 -0800685 return VBERROR_SHUTDOWN_REQUESTED;
686 VbExSleepMs(REC_KEY_DELAY);
687 }
688 }
689
690 return VBERROR_SUCCESS;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700691}
692
Randall Spangler29accd92013-02-04 14:01:04 -0800693/**
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800694 * Wrapper around VbExEcProtect() which sets recovery reason on error.
Randall Spangler29accd92013-02-04 14:01:04 -0800695 */
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800696static VbError_t EcProtect(int devidx, enum VbSelectFirmware_t select)
Randall Spangler29accd92013-02-04 14:01:04 -0800697{
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800698 int rv = VbExEcProtect(devidx, select);
Randall Spangler09d0c2e2012-07-25 15:52:51 -0700699
Randall Spangler29accd92013-02-04 14:01:04 -0800700 if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800701 VBDEBUG(("VbExEcProtect() needs reboot\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800702 } else if (rv != VBERROR_SUCCESS) {
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800703 VBDEBUG(("VbExEcProtect() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800704 VbSetRecoveryRequest(VBNV_RECOVERY_EC_PROTECT);
705 }
706 return rv;
Randall Spangler09d0c2e2012-07-25 15:52:51 -0700707}
Randall Spangler1b1998d2011-07-01 16:12:47 -0700708
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800709static VbError_t EcUpdateImage(int devidx, VbCommonParams *cparams,
710 enum VbSelectFirmware_t select,
711 int *need_update, int in_rw)
712{
713 VbSharedDataHeader *shared =
714 (VbSharedDataHeader *)cparams->shared_data_blob;
715 int rv;
716 int hash_size;
Julius Wernere1867d22016-05-27 13:27:18 -0700717 int ec_hash_size;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800718 const uint8_t *hash = NULL;
719 const uint8_t *expected = NULL;
720 const uint8_t *ec_hash = NULL;
721 int expected_size;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800722 int i;
723 int rw_request = select != VB_SELECT_FIRMWARE_READONLY;
724
725 *need_update = 0;
726 VBDEBUG(("EcUpdateImage() - "
727 "Check for %s update\n", rw_request ? "RW" : "RO"));
728
729 /* Get current EC hash. */
Julius Wernere1867d22016-05-27 13:27:18 -0700730 rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800731 if (rv) {
732 VBDEBUG(("EcUpdateImage() - "
733 "VbExEcHashImage() returned %d\n", rv));
734 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
735 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
736 }
Julius Wernere1867d22016-05-27 13:27:18 -0700737 VBDEBUG(("EC-%s hash: ", rw_request ? "RW" : "RO"));
738 for (i = 0; i < ec_hash_size; i++)
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800739 VBDEBUG(("%02x",ec_hash[i]));
740 VBDEBUG(("\n"));
741
742 /* Get expected EC hash. */
743 rv = VbExEcGetExpectedImageHash(devidx, select, &hash, &hash_size);
Julius Wernere1867d22016-05-27 13:27:18 -0700744 if (rv) {
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800745 VBDEBUG(("EcUpdateImage() - "
746 "VbExEcGetExpectedImageHash() returned %d\n", rv));
747 VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
748 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Julius Wernere1867d22016-05-27 13:27:18 -0700749 }
750 if (ec_hash_size != hash_size) {
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800751 VBDEBUG(("EcUpdateImage() - "
Julius Wernere1867d22016-05-27 13:27:18 -0700752 "EC uses %d-byte hash, but AP-RW contains %d bytes\n",
753 ec_hash_size, hash_size));
754 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800755 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800756 }
757
Julius Wernere1867d22016-05-27 13:27:18 -0700758 VBDEBUG(("Expected hash: "));
759 for (i = 0; i < hash_size; i++)
760 VBDEBUG(("%02x", hash[i]));
761 VBDEBUG(("\n"));
762 *need_update = SafeMemcmp(ec_hash, hash, hash_size);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800763
Julius Wernere1867d22016-05-27 13:27:18 -0700764 if (!*need_update)
765 return VBERROR_SUCCESS;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800766
Julius Wernere1867d22016-05-27 13:27:18 -0700767 /* Get expected EC image */
768 rv = VbExEcGetExpectedImage(devidx, select, &expected, &expected_size);
769 if (rv) {
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800770 VBDEBUG(("EcUpdateImage() - "
771 "VbExEcGetExpectedImage() returned %d\n", rv));
Julius Wernere1867d22016-05-27 13:27:18 -0700772 VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
773 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
774 }
775 VBDEBUG(("EcUpdateImage() - image len = %d\n", expected_size));
776
777 if (in_rw && rw_request) {
778 /*
779 * Check if BIOS should also load VGA Option ROM when
780 * rebooting to save another reboot if possible.
781 */
782 if ((shared->flags & VBSD_EC_SLOW_UPDATE) &&
783 (shared->flags & VBSD_OPROM_MATTERS) &&
784 !(shared->flags & VBSD_OPROM_LOADED)) {
785 VBDEBUG(("EcUpdateImage() - Reboot to "
786 "load VGA Option ROM\n"));
787 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
788 }
789
790 /*
791 * EC is running the wrong RW image. Reboot the EC to
792 * RO so we can update it on the next boot.
793 */
794 VBDEBUG(("EcUpdateImage() - "
795 "in RW, need to update RW, so reboot\n"));
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800796 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
797 }
798
Julius Wernere1867d22016-05-27 13:27:18 -0700799 VBDEBUG(("EcUpdateImage() updating EC-%s...\n",
800 rw_request ? "RW" : "RO"));
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800801
Julius Wernere1867d22016-05-27 13:27:18 -0700802 if (shared->flags & VBSD_EC_SLOW_UPDATE) {
803 VBDEBUG(("EcUpdateImage() - EC is slow. Show WAIT screen.\n"));
804
805 /* Ensure the VGA Option ROM is loaded */
806 if ((shared->flags & VBSD_OPROM_MATTERS) &&
807 !(shared->flags & VBSD_OPROM_LOADED)) {
808 VBDEBUG(("EcUpdateImage() - Reboot to "
809 "load VGA Option ROM\n"));
810 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
811 return VBERROR_VGA_OPROM_MISMATCH;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800812 }
813
Julius Wernere1867d22016-05-27 13:27:18 -0700814 VbDisplayScreen(cparams, VB_SCREEN_WAIT, 0, &vnc);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800815 }
816
Julius Wernere1867d22016-05-27 13:27:18 -0700817 rv = VbExEcUpdateImage(devidx, select, expected, expected_size);
818 if (rv != VBERROR_SUCCESS) {
819 VBDEBUG(("EcUpdateImage() - "
820 "VbExEcUpdateImage() returned %d\n", rv));
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800821
Julius Wernere1867d22016-05-27 13:27:18 -0700822 /*
823 * The EC may know it needs a reboot. It may need to
824 * unprotect the region before updating, or may need to
825 * reboot after updating. Either way, it's not an error
826 * requiring recovery mode.
827 *
828 * If we fail for any other reason, trigger recovery
829 * mode.
830 */
831 if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
832 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800833
Julius Wernere1867d22016-05-27 13:27:18 -0700834 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800835 }
836
837 /* Verify the EC was updated properly */
Julius Wernere1867d22016-05-27 13:27:18 -0700838 rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
839 if (rv) {
840 VBDEBUG(("EcUpdateImage() - "
841 "VbExEcHashImage() returned %d\n", rv));
842 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
843 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800844 }
Julius Wernere1867d22016-05-27 13:27:18 -0700845 if (hash_size != ec_hash_size) {
846 VBDEBUG(("EcUpdateImage() - "
847 "VbExEcHashImage() says size %d, not %d\n",
848 ec_hash_size, hash_size));
849 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
850 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
851 }
852 VBDEBUG(("Updated EC-%s hash: ", rw_request ? "RW" : "RO"));
853 for (i = 0; i < ec_hash_size; i++)
854 VBDEBUG(("%02x",ec_hash[i]));
855 VBDEBUG(("\n"));
856
857 if (SafeMemcmp(ec_hash, hash, hash_size)){
858 VBDEBUG(("EcUpdateImage() - "
859 "Failed to update EC-%s\n", rw_request ?
860 "RW" : "RO"));
861 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
862 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
863 }
864
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800865 return VBERROR_SUCCESS;
866}
867
Randall Spanglere778ada2014-07-15 16:14:21 -0700868VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams)
Randall Spangler29accd92013-02-04 14:01:04 -0800869{
870 VbSharedDataHeader *shared =
871 (VbSharedDataHeader *)cparams->shared_data_blob;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800872 enum VbSelectFirmware_t select_rw =
873 shared->firmware_index ? VB_SELECT_FIRMWARE_B :
874 VB_SELECT_FIRMWARE_A;
875 enum VbSelectFirmware_t select_ro = VB_SELECT_FIRMWARE_READONLY;
Randall Spangler29accd92013-02-04 14:01:04 -0800876 int in_rw = 0;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800877 int ro_try_count = 2;
878 int num_tries = 0;
879 uint32_t try_ro_sync, recovery_request;
880 int rv, updated_rw, updated_ro;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700881
Randall Spangler6014c042014-07-22 14:42:58 -0700882 VBDEBUG(("VbEcSoftwareSync(devidx=%d)\n", devidx));
883
Randall Spangler29accd92013-02-04 14:01:04 -0800884 /* Determine whether the EC is in RO or RW */
Randall Spanglere778ada2014-07-15 16:14:21 -0700885 rv = VbExEcRunningRW(devidx, &in_rw);
Randall Spangler584e0d22012-07-26 10:29:48 -0700886
Randall Spangler29accd92013-02-04 14:01:04 -0800887 if (shared->recovery_reason) {
888 /* Recovery mode; just verify the EC is in RO code */
889 if (rv == VBERROR_SUCCESS && in_rw == 1) {
890 /*
891 * EC is definitely in RW firmware. We want it in
892 * read-only code, so preserve the current recovery
893 * reason and reboot.
894 *
895 * We don't reboot on error or unknown EC code, because
896 * we could end up in an endless reboot loop. If we
897 * had some way to track that we'd already rebooted for
898 * this reason, we could retry only once.
899 */
900 VBDEBUG(("VbEcSoftwareSync() - "
901 "want recovery but got EC-RW\n"));
902 VbSetRecoveryRequest(shared->recovery_reason);
903 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
904 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700905
Randall Spangler29accd92013-02-04 14:01:04 -0800906 VBDEBUG(("VbEcSoftwareSync() in recovery; EC-RO\n"));
907 return VBERROR_SUCCESS;
908 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700909
Randall Spangler29accd92013-02-04 14:01:04 -0800910 /*
911 * Not in recovery. If we couldn't determine where the EC was,
912 * reboot to recovery.
913 */
914 if (rv != VBERROR_SUCCESS) {
915 VBDEBUG(("VbEcSoftwareSync() - "
Vadim Bendebury48b26df2013-06-21 16:28:28 -0700916 "VbExEcRunningRW() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800917 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UNKNOWN_IMAGE);
918 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
919 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700920
Randall Spangler29accd92013-02-04 14:01:04 -0800921 /* If AP is read-only normal, EC should be in its RO code also. */
922 if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
923 /* If EC is in RW code, request reboot back to RO */
924 if (in_rw == 1) {
925 VBDEBUG(("VbEcSoftwareSync() - "
926 "want RO-normal but got EC-RW\n"));
927 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
928 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700929
Randall Spangler29accd92013-02-04 14:01:04 -0800930 /* Protect the RW flash and stay in EC-RO */
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800931 rv = EcProtect(devidx, select_rw);
Randall Spangler29accd92013-02-04 14:01:04 -0800932 if (rv != VBERROR_SUCCESS)
933 return rv;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700934
Randall Spanglere778ada2014-07-15 16:14:21 -0700935 rv = VbExEcDisableJump(devidx);
Randall Spangler29accd92013-02-04 14:01:04 -0800936 if (rv != VBERROR_SUCCESS) {
937 VBDEBUG(("VbEcSoftwareSync() - "
Daisuke Nojiri89121692013-10-10 11:51:45 -0700938 "VbExEcDisableJump() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800939 VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
940 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
941 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700942
Randall Spangler29accd92013-02-04 14:01:04 -0800943 VBDEBUG(("VbEcSoftwareSync() in RO-Normal; EC-RO\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800944 return VBERROR_SUCCESS;
945 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700946
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800947 VBDEBUG(("VbEcSoftwareSync() check for RW update.\n"));
948
949 /* Update the RW Image. */
950 rv = EcUpdateImage(devidx, cparams, select_rw, &updated_rw, in_rw);
951
952 if (rv != VBERROR_SUCCESS) {
Randall Spangler29accd92013-02-04 14:01:04 -0800953 VBDEBUG(("VbEcSoftwareSync() - "
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800954 "EcUpdateImage() returned %d\n", rv));
955 return rv;
Randall Spangler29accd92013-02-04 14:01:04 -0800956 }
Randall Spangler241de332012-07-23 16:24:43 -0700957
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800958 /* Tell EC to jump to its RW image */
959 if (!in_rw) {
960 VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n"));
961 rv = VbExEcJumpToRW(devidx);
Randall Spanglerbbc76062013-09-20 11:18:08 -0700962 if (rv != VBERROR_SUCCESS) {
Randall Spangler29accd92013-02-04 14:01:04 -0800963 VBDEBUG(("VbEcSoftwareSync() - "
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800964 "VbExEcJumpToRW() returned %x\n", rv));
Randall Spanglerbbc76062013-09-20 11:18:08 -0700965
966 /*
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800967 * If the EC booted RO-normal and a previous AP boot
968 * has called VbExEcStayInRO(), we need to reboot the EC
969 * to unlock the ability to jump to the RW firmware.
Randall Spanglerbbc76062013-09-20 11:18:08 -0700970 *
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800971 * All other errors trigger recovery mode.
Randall Spanglerbbc76062013-09-20 11:18:08 -0700972 */
973 if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800974 VbSetRecoveryRequest(VBNV_RECOVERY_EC_JUMP_RW);
Randall Spanglerbbc76062013-09-20 11:18:08 -0700975
Randall Spangler29accd92013-02-04 14:01:04 -0800976 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
977 }
Randall Spangler29accd92013-02-04 14:01:04 -0800978 }
Randall Spangler241de332012-07-23 16:24:43 -0700979
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800980 VbNvGet(&vnc, VBNV_TRY_RO_SYNC, &try_ro_sync);
981
982 if (!devidx && try_ro_sync &&
983 !(shared->flags & VBSD_BOOT_FIRMWARE_WP_ENABLED)) {
984 /* Reset RO Software Sync NV flag */
985 VbNvSet(&vnc, VBNV_TRY_RO_SYNC, 0);
986
987 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery_request);
988
989 /* Update the RO Image. */
990 while (num_tries < ro_try_count) {
991 VBDEBUG(("VbEcSoftwareSync() RO Software Sync\n"));
992
993 /* Get expected EC-RO Image. */
994 rv = EcUpdateImage(devidx, cparams, select_ro,
995 &updated_ro, in_rw);
996 if (rv == VBERROR_SUCCESS) {
997 /*
998 * If the RO update had failed, reset the
999 * recovery request.
1000 */
1001 if (num_tries)
1002 VbSetRecoveryRequest(recovery_request);
1003 break;
1004 } else
1005 VBDEBUG(("VbEcSoftwareSync() - "
1006 "EcUpdateImage() returned %d\n", rv));
1007
1008 num_tries++;
1009 }
1010 }
Randall Spangler29accd92013-02-04 14:01:04 -08001011 if (rv != VBERROR_SUCCESS)
1012 return rv;
Randall Spangler241de332012-07-23 16:24:43 -07001013
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001014 /* Protect RO flash */
1015 rv = EcProtect(devidx, select_ro);
1016 if (rv != VBERROR_SUCCESS)
1017 return rv;
Randall Spanglerbbc76062013-09-20 11:18:08 -07001018
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001019 /* Protect RW flash */
1020 rv = EcProtect(devidx, select_rw);
1021 if (rv != VBERROR_SUCCESS)
1022 return rv;
Daisuke Nojiri89121692013-10-10 11:51:45 -07001023
Randall Spanglere778ada2014-07-15 16:14:21 -07001024 rv = VbExEcDisableJump(devidx);
Daisuke Nojiri89121692013-10-10 11:51:45 -07001025 if (rv != VBERROR_SUCCESS) {
1026 VBDEBUG(("VbEcSoftwareSync() - "
1027 "VbExEcDisableJump() returned %d\n", rv));
1028 VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
1029 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
1030 }
Randall Spangler241de332012-07-23 16:24:43 -07001031
Duncan Laurie731f8e82014-10-16 11:05:13 -07001032 /*
1033 * Reboot to unload VGA Option ROM if:
1034 * - RW update was done
1035 * - the system is NOT in developer mode
1036 * - the system has slow EC update flag set
1037 * - the VGA Option ROM was needed and loaded
1038 */
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001039 if (updated_rw &&
Duncan Laurie731f8e82014-10-16 11:05:13 -07001040 !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
1041 (shared->flags & VBSD_EC_SLOW_UPDATE) &&
1042 (shared->flags & VBSD_OPROM_MATTERS) &&
1043 (shared->flags & VBSD_OPROM_LOADED)) {
1044 VBDEBUG(("VbEcSoftwareSync() - Reboot to "
1045 "unload VGA Option ROM\n"));
Duncan Laurieeea01162016-01-20 12:53:15 -08001046 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0);
Duncan Laurie731f8e82014-10-16 11:05:13 -07001047 return VBERROR_VGA_OPROM_MISMATCH;
1048 }
1049
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001050
1051 return rv;
Randall Spanglerd4faa062012-07-16 16:42:40 -07001052}
1053
Simon Glass527ba812013-07-25 08:48:47 -06001054/* This function is also used by tests */
1055void VbApiKernelFree(VbCommonParams *cparams)
1056{
1057 /* VbSelectAndLoadKernel() always allocates this, tests don't */
1058 if (cparams->gbb) {
1059 VbExFree(cparams->gbb);
1060 cparams->gbb = NULL;
1061 }
1062 if (cparams->bmp) {
1063 VbExFree(cparams->bmp);
1064 cparams->bmp = NULL;
1065 }
1066}
1067
Randall Spangler29accd92013-02-04 14:01:04 -08001068VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
1069 VbSelectAndLoadKernelParams *kparams)
1070{
1071 VbSharedDataHeader *shared =
1072 (VbSharedDataHeader *)cparams->shared_data_blob;
1073 VbError_t retval = VBERROR_SUCCESS;
1074 LoadKernelParams p;
1075 uint32_t tpm_status = 0;
Hung-Te Linaee6bd62016-04-07 12:21:03 +08001076 uint32_t battery_cutoff = 0;
Randall Spanglerd4faa062012-07-16 16:42:40 -07001077
Randall Spangler29accd92013-02-04 14:01:04 -08001078 /* Start timer */
1079 shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer();
Randall Spangler1b1998d2011-07-01 16:12:47 -07001080
Randall Spangler29accd92013-02-04 14:01:04 -08001081 VbExNvStorageRead(vnc.raw);
1082 VbNvSetup(&vnc);
Randall Spangler96191122011-07-08 14:01:54 -07001083
Randall Spangler1589f942016-09-02 12:10:31 -07001084 /* Fill in params for calls to LoadKernel() */
Randall Spangler664096b2016-10-13 16:16:41 -07001085 memset(&p, 0, sizeof(p));
Randall Spangler1589f942016-09-02 12:10:31 -07001086 p.shared_data_blob = cparams->shared_data_blob;
1087 p.shared_data_size = cparams->shared_data_size;
1088 p.gbb_data = cparams->gbb_data;
1089 p.gbb_size = cparams->gbb_size;
1090 p.fwmp = &fwmp;
1091 p.nv_context = &vnc;
1092
1093 /*
1094 * This could be set to NULL, in which case the vboot header
1095 * information about the load address and size will be used.
1096 */
1097 p.kernel_buffer = kparams->kernel_buffer;
1098 p.kernel_buffer_size = kparams->kernel_buffer_size;
1099
Randall Spangler29accd92013-02-04 14:01:04 -08001100 /* Clear output params in case we fail */
1101 kparams->disk_handle = NULL;
1102 kparams->partition_number = 0;
1103 kparams->bootloader_address = 0;
1104 kparams->bootloader_size = 0;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -08001105 kparams->flags = 0;
Randall Spangler664096b2016-10-13 16:16:41 -07001106 memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));
Randall Spangler1b1998d2011-07-01 16:12:47 -07001107
Simon Glass527ba812013-07-25 08:48:47 -06001108 cparams->bmp = NULL;
1109 cparams->gbb = VbExMalloc(sizeof(*cparams->gbb));
1110 retval = VbGbbReadHeader_static(cparams, cparams->gbb);
1111 if (VBERROR_SUCCESS != retval)
1112 goto VbSelectAndLoadKernel_exit;
1113
Randall Spangler29accd92013-02-04 14:01:04 -08001114 /* Do EC software sync if necessary */
Randall Spanglerf2a1dc02013-06-11 16:53:07 -07001115 if ((shared->flags & VBSD_EC_SOFTWARE_SYNC) &&
Simon Glass527ba812013-07-25 08:48:47 -06001116 !(cparams->gbb->flags & GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)) {
Duncan Laurie731f8e82014-10-16 11:05:13 -07001117 int oprom_mismatch = 0;
1118
Randall Spanglere778ada2014-07-15 16:14:21 -07001119 retval = VbEcSoftwareSync(0, cparams);
Duncan Laurie731f8e82014-10-16 11:05:13 -07001120 /* Save reboot requested until after possible PD sync */
1121 if (retval == VBERROR_VGA_OPROM_MISMATCH)
1122 oprom_mismatch = 1;
1123 else if (retval != VBERROR_SUCCESS)
Randall Spangler29accd92013-02-04 14:01:04 -08001124 goto VbSelectAndLoadKernel_exit;
Randall Spangler6014c042014-07-22 14:42:58 -07001125
1126#ifdef PD_SYNC
Duncan Laurie277dc522014-08-11 12:30:04 -07001127 if (!(cparams->gbb->flags &
1128 GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC)) {
1129 retval = VbEcSoftwareSync(1, cparams);
Duncan Laurie731f8e82014-10-16 11:05:13 -07001130 if (retval == VBERROR_VGA_OPROM_MISMATCH)
1131 oprom_mismatch = 1;
1132 else if (retval != VBERROR_SUCCESS)
Duncan Laurie277dc522014-08-11 12:30:04 -07001133 goto VbSelectAndLoadKernel_exit;
1134 }
Randall Spangler6014c042014-07-22 14:42:58 -07001135#endif
Duncan Laurie731f8e82014-10-16 11:05:13 -07001136
1137 /* Request reboot to unload VGA Option ROM */
1138 if (oprom_mismatch) {
1139 retval = VBERROR_VGA_OPROM_MISMATCH;
1140 goto VbSelectAndLoadKernel_exit;
1141 }
Randall Spangler29accd92013-02-04 14:01:04 -08001142 }
Randall Spangler1b1998d2011-07-01 16:12:47 -07001143
Shawn Nematbakhshb491bc82015-10-21 14:31:02 -07001144 /* EC verification (and possibily updating / jumping) is done */
1145 retval = VbExEcVbootDone(!!shared->recovery_reason);
1146 if (retval != VBERROR_SUCCESS)
1147 goto VbSelectAndLoadKernel_exit;
1148
Hung-Te Linaee6bd62016-04-07 12:21:03 +08001149 /* Check if we need to cut-off battery. This must be done after EC
1150 * firmware updating and before kernel started. */
1151 VbNvGet(&vnc, VBNV_BATTERY_CUTOFF_REQUEST, &battery_cutoff);
1152 if (battery_cutoff) {
1153 VBDEBUG(("Request to cut-off battery\n"));
1154 VbNvSet(&vnc, VBNV_BATTERY_CUTOFF_REQUEST, 0);
1155 VbExEcBatteryCutOff();
1156 retval = VBERROR_SHUTDOWN_REQUESTED;
1157 goto VbSelectAndLoadKernel_exit;
1158 }
1159
Randall Spangler29accd92013-02-04 14:01:04 -08001160 /* Read kernel version from the TPM. Ignore errors in recovery mode. */
1161 tpm_status = RollbackKernelRead(&shared->kernel_version_tpm);
1162 if (0 != tpm_status) {
1163 VBDEBUG(("Unable to get kernel versions from TPM\n"));
1164 if (!shared->recovery_reason) {
1165 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_R_ERROR);
1166 retval = VBERROR_TPM_READ_KERNEL;
1167 goto VbSelectAndLoadKernel_exit;
1168 }
1169 }
1170 shared->kernel_version_tpm_start = shared->kernel_version_tpm;
Randall Spanglerd4faa062012-07-16 16:42:40 -07001171
Randall Spangler946abf12016-04-15 14:49:40 -07001172 /* Read FWMP. Ignore errors in recovery mode. */
1173 if (cparams->gbb->flags & GBB_FLAG_DISABLE_FWMP) {
Randall Spangler664096b2016-10-13 16:16:41 -07001174 memset(&fwmp, 0, sizeof(fwmp));
Randall Spangler946abf12016-04-15 14:49:40 -07001175 tpm_status = 0;
1176 } else {
1177 tpm_status = RollbackFwmpRead(&fwmp);
1178 }
1179 if (0 != tpm_status) {
1180 VBDEBUG(("Unable to get FWMP from TPM\n"));
1181 if (!shared->recovery_reason) {
1182 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_R_ERROR);
1183 retval = VBERROR_TPM_READ_FWMP;
1184 goto VbSelectAndLoadKernel_exit;
1185 }
1186 }
1187
Randall Spangler1589f942016-09-02 12:10:31 -07001188 /* Set up boot flags */
Randall Spangler29accd92013-02-04 14:01:04 -08001189 p.boot_flags = 0;
1190 if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON)
1191 p.boot_flags |= BOOT_FLAG_DEVELOPER;
Vadim Bendeburyb321dbb2012-08-01 18:44:05 -07001192
Randall Spangler29accd92013-02-04 14:01:04 -08001193 /* Handle separate normal and developer firmware builds. */
Randall Spangler64ca7882011-07-11 15:46:19 -07001194#if defined(VBOOT_FIRMWARE_TYPE_NORMAL)
Randall Spangler29accd92013-02-04 14:01:04 -08001195 /* Normal-type firmware always acts like the dev switch is off. */
1196 p.boot_flags &= ~BOOT_FLAG_DEVELOPER;
Randall Spangler64ca7882011-07-11 15:46:19 -07001197#elif defined(VBOOT_FIRMWARE_TYPE_DEVELOPER)
Randall Spangler29accd92013-02-04 14:01:04 -08001198 /* Developer-type firmware fails if the dev switch is off. */
1199 if (!(p.boot_flags & BOOT_FLAG_DEVELOPER)) {
1200 /*
1201 * Dev firmware should be signed with a key that only verifies
1202 * when the dev switch is on, so we should never get here.
1203 */
1204 VBDEBUG(("Developer firmware called with dev switch off!\n"));
1205 VbSetRecoveryRequest(VBNV_RECOVERY_RW_DEV_MISMATCH);
1206 retval = VBERROR_DEV_FIRMWARE_SWITCH_MISMATCH;
1207 goto VbSelectAndLoadKernel_exit;
1208 }
Randall Spangler64ca7882011-07-11 15:46:19 -07001209#else
Randall Spangler29accd92013-02-04 14:01:04 -08001210 /*
1211 * Recovery firmware, or merged normal+developer firmware. No need to
1212 * override flags.
1213 */
Randall Spangler64ca7882011-07-11 15:46:19 -07001214#endif
1215
Randall Spangler29accd92013-02-04 14:01:04 -08001216 /* Select boot path */
1217 if (shared->recovery_reason) {
1218 /* Recovery boot */
1219 p.boot_flags |= BOOT_FLAG_RECOVERY;
1220 retval = VbBootRecovery(cparams, &p);
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001221 VbExEcEnteringMode(0, VB_EC_RECOVERY);
Randall Spangler29accd92013-02-04 14:01:04 -08001222 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0, &vnc);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001223
Randall Spangler29accd92013-02-04 14:01:04 -08001224 } else if (p.boot_flags & BOOT_FLAG_DEVELOPER) {
1225 /* Developer boot */
1226 retval = VbBootDeveloper(cparams, &p);
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001227 VbExEcEnteringMode(0, VB_EC_DEVELOPER);
Randall Spangler29accd92013-02-04 14:01:04 -08001228 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0, &vnc);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001229
Randall Spangler29accd92013-02-04 14:01:04 -08001230 } else {
1231 /* Normal boot */
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001232 VbExEcEnteringMode(0, VB_EC_NORMAL);
Randall Spangler29accd92013-02-04 14:01:04 -08001233 retval = VbBootNormal(cparams, &p);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001234
Randall Spangler29accd92013-02-04 14:01:04 -08001235 if ((1 == shared->firmware_index) &&
1236 (shared->flags & VBSD_FWB_TRIED)) {
1237 /*
1238 * Special cases for when we're trying a new firmware
1239 * B. These are needed because firmware updates also
1240 * usually change the kernel key, which means that the
1241 * B firmware can only boot a new kernel, and the old
1242 * firmware in A can only boot the previous kernel.
1243 *
1244 * Don't advance the TPM if we're trying a new firmware
1245 * B, because we don't yet know if the new kernel will
1246 * successfully boot. We still want to be able to fall
1247 * back to the previous firmware+kernel if the new
1248 * firmware+kernel fails.
1249 *
1250 * If we found only invalid kernels, reboot and try
1251 * again. This allows us to fall back to the previous
1252 * firmware+kernel instead of giving up and going to
1253 * recovery mode right away. We'll still go to
1254 * recovery mode if we run out of tries and the old
1255 * firmware can't find a kernel it likes.
1256 */
1257 if (VBERROR_INVALID_KERNEL_FOUND == retval) {
1258 VBDEBUG(("Trying firmware B, "
1259 "and only found invalid kernels.\n"));
1260 VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);
1261 goto VbSelectAndLoadKernel_exit;
1262 }
1263 } else {
1264 /* Not trying a new firmware B. */
Randall Spangler99275122011-07-26 16:26:59 -07001265
Randall Spangler29accd92013-02-04 14:01:04 -08001266 /* See if we need to update the TPM. */
1267 VBDEBUG(("Checking if TPM kernel version needs "
1268 "advancing\n"));
1269 if (shared->kernel_version_tpm >
1270 shared->kernel_version_tpm_start) {
1271 tpm_status = RollbackKernelWrite(
1272 shared->kernel_version_tpm);
1273 if (0 != tpm_status) {
1274 VBDEBUG(("Error writing kernel "
1275 "versions to TPM.\n"));
1276 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_W_ERROR);
1277 retval = VBERROR_TPM_WRITE_KERNEL;
1278 goto VbSelectAndLoadKernel_exit;
1279 }
1280 }
1281 }
1282 }
Randall Spangler99275122011-07-26 16:26:59 -07001283
Randall Spangler29accd92013-02-04 14:01:04 -08001284 if (VBERROR_SUCCESS != retval)
1285 goto VbSelectAndLoadKernel_exit;
Randall Spangler1b1998d2011-07-01 16:12:47 -07001286
Randall Spangler29accd92013-02-04 14:01:04 -08001287 /* Save disk parameters */
1288 kparams->disk_handle = p.disk_handle;
1289 kparams->partition_number = (uint32_t)p.partition_number;
1290 kparams->bootloader_address = p.bootloader_address;
1291 kparams->bootloader_size = (uint32_t)p.bootloader_size;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -08001292 kparams->flags = p.flags;
Randall Spangler664096b2016-10-13 16:16:41 -07001293 memcpy(kparams->partition_guid, p.partition_guid,
Randall Spangler29accd92013-02-04 14:01:04 -08001294 sizeof(kparams->partition_guid));
Randall Spangler22e7bb22011-07-22 14:06:51 -07001295
Randall Spangler29accd92013-02-04 14:01:04 -08001296 /* Lock the kernel versions. Ignore errors in recovery mode. */
Shawn Nematbakhsh964144b2013-07-22 13:33:46 -07001297 tpm_status = RollbackKernelLock(shared->recovery_reason);
Randall Spangler29accd92013-02-04 14:01:04 -08001298 if (0 != tpm_status) {
1299 VBDEBUG(("Error locking kernel versions.\n"));
1300 if (!shared->recovery_reason) {
1301 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_L_ERROR);
1302 retval = VBERROR_TPM_LOCK_KERNEL;
1303 goto VbSelectAndLoadKernel_exit;
1304 }
1305 }
Randall Spangler22e7bb22011-07-22 14:06:51 -07001306
Randall Spangler29accd92013-02-04 14:01:04 -08001307 VbSelectAndLoadKernel_exit:
Randall Spangler1b1998d2011-07-01 16:12:47 -07001308
Simon Glass527ba812013-07-25 08:48:47 -06001309 VbApiKernelFree(cparams);
1310
Daisuke Nojiri3a631482015-10-20 18:31:10 -07001311 VbNvCommit();
Randall Spangler22e7bb22011-07-22 14:06:51 -07001312
Randall Spangler29accd92013-02-04 14:01:04 -08001313 /* Stop timer */
1314 shared->timer_vb_select_and_load_kernel_exit = VbExGetTimer();
Randall Spangler1b1998d2011-07-01 16:12:47 -07001315
Randall Spangler29accd92013-02-04 14:01:04 -08001316 kparams->kernel_buffer = p.kernel_buffer;
1317 kparams->kernel_buffer_size = p.kernel_buffer_size;
Randall Spangler96191122011-07-08 14:01:54 -07001318
Randall Spangler29accd92013-02-04 14:01:04 -08001319 VBDEBUG(("VbSelectAndLoadKernel() returning %d\n", (int)retval));
Vadim Bendeburyb321dbb2012-08-01 18:44:05 -07001320
Randall Spangler29accd92013-02-04 14:01:04 -08001321 /* Pass through return value from boot path */
1322 return retval;
Randall Spangler1b1998d2011-07-01 16:12:47 -07001323}
Furquan Shaikhf2743602015-05-21 14:39:11 -07001324
1325VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams,
1326 VbSelectAndLoadKernelParams *kparams,
1327 void *boot_image,
1328 size_t image_size)
1329{
1330 VbError_t retval;
1331 VbPublicKey* kernel_subkey = NULL;
1332 uint8_t *kbuf;
1333 VbKeyBlockHeader *key_block;
1334 VbSharedDataHeader *shared =
1335 (VbSharedDataHeader *)cparams->shared_data_blob;
1336 RSAPublicKey *data_key = NULL;
1337 VbKernelPreambleHeader *preamble;
1338 uint64_t body_offset;
1339 int hash_only = 0;
1340 int dev_switch;
Furquan Shaikh55484552015-10-28 13:01:27 -07001341 uint32_t allow_fastboot_full_cap = 0;
Furquan Shaikhf2743602015-05-21 14:39:11 -07001342
1343 if ((boot_image == NULL) || (image_size == 0))
1344 return VBERROR_INVALID_PARAMETER;
1345
1346 /* Clear output params in case we fail. */
1347 kparams->disk_handle = NULL;
1348 kparams->partition_number = 0;
1349 kparams->bootloader_address = 0;
1350 kparams->bootloader_size = 0;
1351 kparams->flags = 0;
Randall Spangler664096b2016-10-13 16:16:41 -07001352 memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));
Furquan Shaikhf2743602015-05-21 14:39:11 -07001353
Furquan Shaikhf2743602015-05-21 14:39:11 -07001354 kbuf = boot_image;
Furquan Shaikhf2743602015-05-21 14:39:11 -07001355
1356 /* Read GBB Header */
1357 cparams->bmp = NULL;
1358 cparams->gbb = VbExMalloc(sizeof(*cparams->gbb));
1359 retval = VbGbbReadHeader_static(cparams, cparams->gbb);
1360 if (VBERROR_SUCCESS != retval) {
1361 VBDEBUG(("Gbb read header failed.\n"));
1362 return retval;
1363 }
1364
1365 /*
1366 * We don't care verifying the image if:
1367 * 1. dev-mode switch is on and
Furquan Shaikh55484552015-10-28 13:01:27 -07001368 * 2a. GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP is set, or
1369 * 2b. DEV_BOOT_FASTBOOT_FULL_CAP flag is set in NvStorage
Furquan Shaikhf2743602015-05-21 14:39:11 -07001370 *
1371 * Check only the integrity of the image.
1372 */
1373 dev_switch = shared->flags & VBSD_BOOT_DEV_SWITCH_ON;
Furquan Shaikh55484552015-10-28 13:01:27 -07001374
1375 VbExNvStorageRead(vnc.raw);
1376 VbNvSetup(&vnc);
1377 VbNvGet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP,
1378 &allow_fastboot_full_cap);
1379
1380 if (0 == allow_fastboot_full_cap) {
1381 allow_fastboot_full_cap = !!(cparams->gbb->flags &
1382 GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP);
1383 }
1384
1385 if (dev_switch && allow_fastboot_full_cap) {
Furquan Shaikhf2743602015-05-21 14:39:11 -07001386 VBDEBUG(("Only performing integrity-check.\n"));
1387 hash_only = 1;
1388 } else {
1389 /* Get recovery key. */
1390 retval = VbGbbReadRecoveryKey(cparams, &kernel_subkey);
1391 if (VBERROR_SUCCESS != retval) {
1392 VBDEBUG(("Gbb Read Recovery key failed.\n"));
1393 return retval;
1394 }
1395 }
1396
1397 /* If we fail at any step, retval returned would be invalid kernel. */
1398 retval = VBERROR_INVALID_KERNEL_FOUND;
1399
1400 /* Verify the key block. */
Furquan Shaikh04e23382015-05-29 18:00:46 -07001401 key_block = (VbKeyBlockHeader *)kbuf;
Furquan Shaikhf2743602015-05-21 14:39:11 -07001402 if (0 != KeyBlockVerify(key_block, image_size, kernel_subkey,
1403 hash_only)) {
1404 VBDEBUG(("Verifying key block signature/hash failed.\n"));
1405 goto fail;
1406 }
1407
1408 /* Check the key block flags against the current boot mode. */
1409 if (!(key_block->key_block_flags &
1410 (dev_switch ? KEY_BLOCK_FLAG_DEVELOPER_1 :
1411 KEY_BLOCK_FLAG_DEVELOPER_0))) {
1412 VBDEBUG(("Key block developer flag mismatch.\n"));
1413 if (hash_only == 0)
1414 goto fail;
1415 }
1416
1417 if (!(key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)) {
1418 VBDEBUG(("Key block recovery flag mismatch.\n"));
1419 if (hash_only == 0)
1420 goto fail;
1421 }
1422
1423 /* Get key for preamble/data verification from the key block. */
1424 data_key = PublicKeyToRSA(&key_block->data_key);
1425 if (!data_key) {
1426 VBDEBUG(("Data key bad.\n"));
1427 goto fail;
1428 }
1429
1430 /* Verify the preamble, which follows the key block */
Furquan Shaikh04e23382015-05-29 18:00:46 -07001431 preamble = (VbKernelPreambleHeader *)(kbuf + key_block->key_block_size);
Furquan Shaikhf2743602015-05-21 14:39:11 -07001432 if ((0 != VerifyKernelPreamble(preamble,
1433 image_size -
1434 key_block->key_block_size,
1435 data_key))) {
1436 VBDEBUG(("Preamble verification failed.\n"));
1437 goto fail;
1438 }
1439
1440 VBDEBUG(("Kernel preamble is good.\n"));
1441
1442 /* Verify kernel data */
Furquan Shaikh04e23382015-05-29 18:00:46 -07001443 body_offset = key_block->key_block_size + preamble->preamble_size;
Furquan Shaikhf2743602015-05-21 14:39:11 -07001444 if (0 != VerifyData((const uint8_t *)(kbuf + body_offset),
1445 image_size - body_offset,
1446 &preamble->body_signature, data_key)) {
1447 VBDEBUG(("Kernel data verification failed.\n"));
1448 goto fail;
1449 }
1450
1451 VBDEBUG(("Kernel is good.\n"));
1452
1453 /* Fill in output parameters. */
1454 kparams->kernel_buffer = kbuf + body_offset;
1455 kparams->kernel_buffer_size = image_size - body_offset;
1456 kparams->bootloader_address = preamble->bootloader_address;
1457 kparams->bootloader_size = preamble->bootloader_size;
1458 if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS)
1459 kparams->flags = preamble->flags;
1460
1461 retval = VBERROR_SUCCESS;
1462
1463fail:
1464 VbApiKernelFree(cparams);
1465 if (NULL != data_key)
1466 RSAPublicKeyFree(data_key);
1467 if (NULL != kernel_subkey)
1468 VbExFree(kernel_subkey);
1469 return retval;
1470}
Furquan Shaikh773b5ac2015-05-25 21:49:11 -07001471
1472VbError_t VbUnlockDevice(void)
1473{
1474 VBDEBUG(("%s() Enabling dev-mode...\n", __func__));
1475 if (TPM_SUCCESS != SetVirtualDevMode(1))
1476 return VBERROR_TPM_SET_BOOT_MODE_STATE;
1477
1478 VBDEBUG(("%s() Mode change will take effect on next reboot.\n",
1479 __func__));
1480 return VBERROR_SUCCESS;
1481}
1482
1483VbError_t VbLockDevice(void)
1484{
1485 VbExNvStorageRead(vnc.raw);
1486 VbNvSetup(&vnc);
1487
1488 VBDEBUG(("%s() - Storing request to leave dev-mode.\n",
1489 __func__));
1490 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST,
1491 1);
1492
Daisuke Nojiri3a631482015-10-20 18:31:10 -07001493 VbNvCommit();
Furquan Shaikh773b5ac2015-05-25 21:49:11 -07001494
1495 VBDEBUG(("%s() Mode change will take effect on next reboot.\n",
1496 __func__));
1497
1498 return VBERROR_SUCCESS;
1499}