blob: f264fb7f5f0fb951a4a3fa080d33def2a3c116aa [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
Randall Spangler49e517d2016-10-14 10:41:44 -070010#include "2sysincludes.h"
11#include "2common.h"
Randall Spangler13b10972016-10-14 11:04:27 -070012#include "2rsa.h"
Simon Glass527ba812013-07-25 08:48:47 -060013#include "gbb_access.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070014#include "gbb_header.h"
15#include "load_kernel_fw.h"
Simon Glass527ba812013-07-25 08:48:47 -060016#include "region.h"
Randall Spangler22e7bb22011-07-22 14:06:51 -070017#include "rollback_index.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070018#include "utility.h"
Randall Spangler13b10972016-10-14 11:04:27 -070019#include "vb2_common.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070020#include "vboot_api.h"
Bill Richardson253a58e2011-10-03 14:00:58 -070021#include "vboot_audio.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070022#include "vboot_common.h"
Bill Richardson822eca62011-08-22 14:06:38 -070023#include "vboot_display.h"
Aaron Durbin612797e2013-02-26 09:40:55 -060024#include "vboot_kernel.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070025#include "vboot_nvstorage.h"
26
Randall Spangler1b1998d2011-07-01 16:12:47 -070027/* Global variables */
Randall Spangler1b1998d2011-07-01 16:12:47 -070028static VbNvContext vnc;
Randall Spangler946abf12016-04-15 14:49:40 -070029static struct RollbackSpaceFwmp fwmp;
Randall Spangler1b1998d2011-07-01 16:12:47 -070030
Randall Spangler1b1998d2011-07-01 16:12:47 -070031#ifdef CHROMEOS_ENVIRONMENT
Randall Spangler946abf12016-04-15 14:49:40 -070032/* Global variable accessors for unit tests */
Randall Spangler29accd92013-02-04 14:01:04 -080033
34VbNvContext *VbApiKernelGetVnc(void)
35{
36 return &vnc;
Randall Spangler1b1998d2011-07-01 16:12:47 -070037}
Randall Spangler946abf12016-04-15 14:49:40 -070038
39struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void)
40{
41 return &fwmp;
42}
Randall Spangler1b1998d2011-07-01 16:12:47 -070043#endif
44
Randall Spangler29accd92013-02-04 14:01:04 -080045/**
Randall Spangler7f436692013-02-05 12:42:36 -080046 * Set recovery request (called from vboot_api_kernel.c functions only)
Randall Spangler29accd92013-02-04 14:01:04 -080047 */
48static void VbSetRecoveryRequest(uint32_t recovery_request)
49{
50 VBDEBUG(("VbSetRecoveryRequest(%d)\n", (int)recovery_request));
51 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, recovery_request);
Randall Spangler1b1998d2011-07-01 16:12:47 -070052}
53
Daisuke Nojiri3a631482015-10-20 18:31:10 -070054static void VbSetRecoverySubcode(uint32_t recovery_request)
55{
56 VBDEBUG(("VbSetRecoverySubcode(%d)\n", (int)recovery_request));
57 VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, recovery_request);
58}
59
60static void VbNvCommit(void)
61{
62 VbNvTeardown(&vnc);
63 if (vnc.raw_changed)
64 VbExNvStorageWrite(vnc.raw);
65}
66
Vadim Bendeburyccca6662015-04-06 18:04:44 -070067static void VbAllowUsbBoot(void)
68{
69 VBDEBUG(("%s\n", __func__));
70 VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 1);
71}
72
Randall Spangler29accd92013-02-04 14:01:04 -080073/**
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -080074 * Checks GBB flags against VbExIsShutdownRequested() shutdown request to
75 * determine if a shutdown is required.
76 *
77 * Returns true if a shutdown is required and false if no shutdown is required.
78 */
79static int VbWantShutdown(uint32_t gbb_flags)
80{
81 uint32_t shutdown_request = VbExIsShutdownRequested();
82
83 /* If desired, ignore shutdown request due to lid closure. */
84 if (gbb_flags & GBB_FLAG_DISABLE_LID_SHUTDOWN)
85 shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED;
86
87 return !!shutdown_request;
88}
89
Julius Werner957b4242015-05-08 22:54:14 -070090static void VbTryLegacy(int allowed)
91{
92 if (!allowed)
93 VBDEBUG(("VbBootDeveloper() - Legacy boot is disabled\n"));
94 else if (0 != RollbackKernelLock(0))
95 VBDEBUG(("Error locking kernel versions on legacy boot.\n"));
96 else
97 VbExLegacy(); /* will not return if successful */
98
99 /* If legacy boot fails, beep and return to calling UI loop. */
100 VbExBeep(120, 400);
101 VbExSleepMs(120);
102 VbExBeep(120, 400);
103}
104
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800105/**
Randall Spangler29accd92013-02-04 14:01:04 -0800106 * Attempt loading a kernel from the specified type(s) of disks.
107 *
108 * If successful, sets p->disk_handle to the disk for the kernel and returns
Randall Spangler1cf77cd2011-07-25 09:19:58 -0700109 * VBERROR_SUCCESS.
110 *
111 * Returns VBERROR_NO_DISK_FOUND if no disks of the specified type were found.
112 *
Randall Spangler29accd92013-02-04 14:01:04 -0800113 * May return other VBERROR_ codes for other failures.
114 */
115uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p,
116 uint32_t get_info_flags)
117{
118 VbError_t retval = VBERROR_UNKNOWN;
119 VbDiskInfo* disk_info = NULL;
120 uint32_t disk_count = 0;
121 uint32_t i;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700122
Randall Spangler29accd92013-02-04 14:01:04 -0800123 VBDEBUG(("VbTryLoadKernel() start, get_info_flags=0x%x\n",
124 (unsigned)get_info_flags));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700125
Randall Spangler29accd92013-02-04 14:01:04 -0800126 p->disk_handle = NULL;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700127
Randall Spangler29accd92013-02-04 14:01:04 -0800128 /* Find disks */
129 if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
130 get_info_flags))
131 disk_count = 0;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700132
Randall Spangler29accd92013-02-04 14:01:04 -0800133 VBDEBUG(("VbTryLoadKernel() found %d disks\n", (int)disk_count));
134 if (0 == disk_count) {
135 VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_DISK);
136 return VBERROR_NO_DISK_FOUND;
137 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700138
Randall Spangler29accd92013-02-04 14:01:04 -0800139 /* Loop over disks */
140 for (i = 0; i < disk_count; i++) {
141 VBDEBUG(("VbTryLoadKernel() trying disk %d\n", (int)i));
142 /*
143 * Sanity-check what we can. FWIW, VbTryLoadKernel() is always
144 * called with only a single bit set in get_info_flags.
145 *
146 * Ensure 512-byte sectors and non-trivially sized disk (for
147 * cgptlib) and that we got a partition with only the flags we
148 * asked for.
149 */
150 if (512 != disk_info[i].bytes_per_lba ||
Dan Ehrenbergf47eccf2015-01-05 13:05:58 -0800151 16 > disk_info[i].lba_count ||
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800152 get_info_flags != (disk_info[i].flags & ~VB_DISK_FLAG_EXTERNAL_GPT)) {
Simon Glass981cb2a2013-08-12 15:12:47 -0600153 VBDEBUG((" skipping: bytes_per_lba=%" PRIu64
154 " lba_count=%" PRIu64 " flags=0x%x\n",
Randall Spangler29accd92013-02-04 14:01:04 -0800155 disk_info[i].bytes_per_lba,
156 disk_info[i].lba_count,
157 disk_info[i].flags));
158 continue;
159 }
160 p->disk_handle = disk_info[i].handle;
161 p->bytes_per_lba = disk_info[i].bytes_per_lba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800162 p->gpt_lba_count = disk_info[i].lba_count;
163 p->streaming_lba_count = disk_info[i].streaming_lba_count
164 ?: p->gpt_lba_count;
165 p->boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT
166 ? BOOT_FLAG_EXTERNAL_GPT : 0;
Simon Glass527ba812013-07-25 08:48:47 -0600167 retval = LoadKernel(p, cparams);
Randall Spangler29accd92013-02-04 14:01:04 -0800168 VBDEBUG(("VbTryLoadKernel() LoadKernel() = %d\n", retval));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700169
Randall Spangler29accd92013-02-04 14:01:04 -0800170 /*
171 * Stop now if we found a kernel.
172 *
173 * TODO: If recovery requested, should track the farthest we
174 * get, instead of just returning the value from the last disk
175 * attempted.
176 */
177 if (VBERROR_SUCCESS == retval)
178 break;
179 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700180
Randall Spangler29accd92013-02-04 14:01:04 -0800181 /* If we didn't find any good kernels, don't return a disk handle. */
182 if (VBERROR_SUCCESS != retval) {
183 VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_KERNEL);
184 p->disk_handle = NULL;
185 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700186
Randall Spangler29accd92013-02-04 14:01:04 -0800187 VbExDiskFreeInfo(disk_info, p->disk_handle);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700188
Randall Spangler29accd92013-02-04 14:01:04 -0800189 /*
190 * Pass through return code. Recovery reason (if any) has already been
191 * set by LoadKernel().
192 */
193 return retval;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700194}
195
Mary Ruthven12a55f22015-10-06 10:42:31 -0700196uint32_t VbTryUsb(VbCommonParams *cparams, LoadKernelParams *p)
197{
198 uint32_t retval = VbTryLoadKernel(cparams, p, VB_DISK_FLAG_REMOVABLE);
199 if (VBERROR_SUCCESS == retval) {
200 VBDEBUG(("VbBootDeveloper() - booting USB\n"));
201 } else {
202 VBDEBUG(("VbBootDeveloper() - no kernel found on USB\n"));
203 VbExBeep(250, 200);
204 VbExSleepMs(120);
205 /*
206 * Clear recovery requests from failed
207 * kernel loading, so that powering off
208 * at this point doesn't put us into
209 * recovery mode.
210 */
211 VbSetRecoveryRequest(
212 VBNV_RECOVERY_NOT_REQUESTED);
213 }
214 return retval;
215}
216
Shawn Nematbakhshba7fd8d2012-10-30 15:17:33 -0700217#define CONFIRM_KEY_DELAY 20 /* Check confirm screen keys every 20ms */
218
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800219int VbUserConfirms(VbCommonParams *cparams, uint32_t confirm_flags)
Randall Spangler29accd92013-02-04 14:01:04 -0800220{
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800221 VbSharedDataHeader *shared =
222 (VbSharedDataHeader *)cparams->shared_data_blob;
Randall Spangler29accd92013-02-04 14:01:04 -0800223 uint32_t key;
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800224 uint32_t key_flags;
225 uint32_t button;
226 int rec_button_was_pressed = 0;
Bill Richardson29344752012-08-01 15:02:15 -0700227
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800228 VBDEBUG(("Entering %s(0x%x)\n", __func__, confirm_flags));
Bill Richardson29344752012-08-01 15:02:15 -0700229
Randall Spangler29accd92013-02-04 14:01:04 -0800230 /* Await further instructions */
231 while (1) {
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800232 if (VbWantShutdown(cparams->gbb->flags))
Randall Spangler29accd92013-02-04 14:01:04 -0800233 return -1;
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800234 key = VbExKeyboardReadWithFlags(&key_flags);
235 button = VbExGetSwitches(VB_INIT_FLAG_REC_BUTTON_PRESSED);
Randall Spangler29accd92013-02-04 14:01:04 -0800236 switch (key) {
237 case '\r':
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800238 /* If we require a trusted keyboard for confirmation,
239 * but the keyboard may be faked (for instance, a USB
240 * device), beep and keep waiting.
241 */
242 if (confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD &&
243 !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) {
244 VbExBeep(120, 400);
245 break;
246 }
247
Randall Spangler29accd92013-02-04 14:01:04 -0800248 VBDEBUG(("%s() - Yes (1)\n", __func__));
249 return 1;
250 break;
251 case ' ':
Vadim Bendebury7aa250f2013-08-09 16:02:28 -0700252 VBDEBUG(("%s() - Space (%d)\n", __func__,
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800253 confirm_flags & VB_CONFIRM_SPACE_MEANS_NO));
254 if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO)
Randall Spangler29accd92013-02-04 14:01:04 -0800255 return 0;
256 break;
257 case 0x1b:
258 VBDEBUG(("%s() - No (0)\n", __func__));
259 return 0;
260 break;
261 default:
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800262 /* If the recovery button is physical, and is pressed,
263 * this is also a YES, but must wait for release.
264 */
265 if (!(shared->flags & VBSD_BOOT_REC_SWITCH_VIRTUAL)) {
266 if (button) {
267 VBDEBUG(("%s() - Rec button pressed\n",
268 __func__));
269 rec_button_was_pressed = 1;
270 } else if (rec_button_was_pressed) {
271 VBDEBUG(("%s() - Rec button (1)\n",
272 __func__));
273 return 1;
274 }
275 }
Randall Spangler29accd92013-02-04 14:01:04 -0800276 VbCheckDisplayKey(cparams, key, &vnc);
277 }
278 VbExSleepMs(CONFIRM_KEY_DELAY);
279 }
280
281 /* Not reached, but compiler will complain without it */
282 return -1;
Bill Richardson29344752012-08-01 15:02:15 -0700283}
284
Yunlian Jiang637ff032015-06-09 16:21:56 -0700285VbError_t test_mockable
286VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p)
Randall Spangler29accd92013-02-04 14:01:04 -0800287{
288 /* Boot from fixed disk only */
289 VBDEBUG(("Entering %s()\n", __func__));
290 return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700291}
292
Randall Spangler946abf12016-04-15 14:49:40 -0700293static const char dev_disable_msg[] =
294 "Developer mode is disabled on this device by system policy.\n"
295 "For more information, see http://dev.chromium.org/chromium-os/fwmp\n"
296 "\n";
297
Randall Spangler29accd92013-02-04 14:01:04 -0800298VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p)
299{
Simon Glass527ba812013-07-25 08:48:47 -0600300 GoogleBinaryBlockHeader *gbb = cparams->gbb;
Randall Spangler29accd92013-02-04 14:01:04 -0800301 VbSharedDataHeader *shared =
302 (VbSharedDataHeader *)cparams->shared_data_blob;
Mary Ruthven12a55f22015-10-06 10:42:31 -0700303
304 uint32_t allow_usb = 0;
305 uint32_t allow_legacy = 0;
Randall Spangler946abf12016-04-15 14:49:40 -0700306 uint32_t disable_dev_boot = 0;
Mary Ruthven12a55f22015-10-06 10:42:31 -0700307 uint32_t use_usb = 0;
308 uint32_t use_legacy = 0;
309 uint32_t default_boot = 0;
310 uint32_t ctrl_d_pressed = 0;
311
Randall Spangler29accd92013-02-04 14:01:04 -0800312 VbAudioContext *audio = 0;
Randall Spanglerdaa807c2011-07-11 10:55:18 -0700313
Randall Spangler29accd92013-02-04 14:01:04 -0800314 VBDEBUG(("Entering %s()\n", __func__));
Bill Richardsonec8df162012-06-07 04:21:14 -0700315
Randall Spangler29accd92013-02-04 14:01:04 -0800316 /* Check if USB booting is allowed */
317 VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &allow_usb);
318 VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &allow_legacy);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700319
Mary Ruthven12a55f22015-10-06 10:42:31 -0700320 /* Check if the default is to boot using disk, usb, or legacy */
321 VbNvGet(&vnc, VBNV_DEV_DEFAULT_BOOT, &default_boot);
322
323 if(default_boot == VBNV_DEV_DEFAULT_BOOT_USB)
324 use_usb = 1;
325 if(default_boot == VBNV_DEV_DEFAULT_BOOT_LEGACY)
326 use_legacy = 1;
327
Randall Spangler29accd92013-02-04 14:01:04 -0800328 /* Handle GBB flag override */
329 if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_USB)
330 allow_usb = 1;
331 if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_LEGACY)
332 allow_legacy = 1;
Mary Ruthven12a55f22015-10-06 10:42:31 -0700333 if (gbb->flags & GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) {
334 use_legacy = 1;
335 use_usb = 0;
336 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700337
Randall Spangler946abf12016-04-15 14:49:40 -0700338 /* Handle FWMP override */
339 if (fwmp.flags & FWMP_DEV_ENABLE_USB)
340 allow_usb = 1;
341 if (fwmp.flags & FWMP_DEV_ENABLE_LEGACY)
342 allow_legacy = 1;
343 if (fwmp.flags & FWMP_DEV_DISABLE_BOOT) {
344 if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) {
345 VBDEBUG(("%s() - FWMP_DEV_DISABLE_BOOT rejected by "
346 "FORCE_DEV_SWITCH_ON\n",
347 __func__));
348 } else {
349 disable_dev_boot = 1;
350 }
351 }
352
353 /* If dev mode is disabled, only allow TONORM */
354 while (disable_dev_boot) {
355 VBDEBUG(("%s() - dev_disable_boot is set.\n", __func__));
356 VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_TO_NORM, 0, &vnc);
357 VbExDisplayDebugInfo(dev_disable_msg);
358
359 /* Ignore space in VbUserConfirms()... */
360 switch (VbUserConfirms(cparams, 0)) {
361 case 1:
362 VBDEBUG(("%s() - leaving dev-mode.\n", __func__));
363 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 1);
364 VbDisplayScreen(cparams,
365 VB_SCREEN_TO_NORM_CONFIRMED,
366 0, &vnc);
367 VbExSleepMs(5000);
368 return VBERROR_TPM_REBOOT_REQUIRED;
369 case -1:
370 VBDEBUG(("%s() - shutdown requested\n", __func__));
371 return VBERROR_SHUTDOWN_REQUESTED;
372 default:
373 /* Ignore user attempt to cancel */
374 VBDEBUG(("%s() - ignore cancel TONORM\n", __func__));
375 }
376 }
377
Randall Spangler29accd92013-02-04 14:01:04 -0800378 /* Show the dev mode warning screen */
379 VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_WARNING, 0, &vnc);
Bill Richardson25a3dbc2011-09-23 15:14:49 -0700380
Randall Spangler29accd92013-02-04 14:01:04 -0800381 /* Get audio/delay context */
382 audio = VbAudioOpen(cparams);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700383
Randall Spangler29accd92013-02-04 14:01:04 -0800384 /* We'll loop until we finish the delay or are interrupted */
385 do {
386 uint32_t key;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700387
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800388 if (VbWantShutdown(gbb->flags)) {
Randall Spangler29accd92013-02-04 14:01:04 -0800389 VBDEBUG(("VbBootDeveloper() - shutdown requested!\n"));
390 VbAudioClose(audio);
391 return VBERROR_SHUTDOWN_REQUESTED;
392 }
Stefan Reinauera2326ee2012-08-23 15:06:45 -0700393
Randall Spangler29accd92013-02-04 14:01:04 -0800394 key = VbExKeyboardRead();
395 switch (key) {
396 case 0:
397 /* nothing pressed */
398 break;
399 case '\r':
400 /* Only disable virtual dev switch if allowed by GBB */
401 if (!(gbb->flags & GBB_FLAG_ENTER_TRIGGERS_TONORM))
402 break;
403 case ' ':
404 /* See if we should disable virtual dev-mode switch. */
405 VBDEBUG(("%s shared->flags=0x%x\n",
406 __func__, shared->flags));
407 if (shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
408 shared->flags & VBSD_BOOT_DEV_SWITCH_ON) {
409 /* Stop the countdown while we go ask... */
410 VbAudioClose(audio);
411 if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) {
412 /*
413 * TONORM won't work (only for
414 * non-shipping devices).
415 */
416 VBDEBUG(("%s() - TONORM rejected by "
417 "FORCE_DEV_SWITCH_ON\n",
418 __func__));
419 VbExDisplayDebugInfo(
420 "WARNING: TONORM prohibited by "
421 "GBB FORCE_DEV_SWITCH_ON.\n\n");
422 VbExBeep(120, 400);
423 break;
424 }
425 VbDisplayScreen(cparams,
426 VB_SCREEN_DEVELOPER_TO_NORM,
427 0, &vnc);
428 /* Ignore space in VbUserConfirms()... */
429 switch (VbUserConfirms(cparams, 0)) {
430 case 1:
431 VBDEBUG(("%s() - leaving dev-mode.\n",
432 __func__));
433 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST,
434 1);
435 VbDisplayScreen(
436 cparams,
437 VB_SCREEN_TO_NORM_CONFIRMED,
438 0, &vnc);
439 VbExSleepMs(5000);
440 return VBERROR_TPM_REBOOT_REQUIRED;
441 case -1:
442 VBDEBUG(("%s() - shutdown requested\n",
443 __func__));
444 return VBERROR_SHUTDOWN_REQUESTED;
445 default:
446 /* Stay in dev-mode */
447 VBDEBUG(("%s() - stay in dev-mode\n",
448 __func__));
449 VbDisplayScreen(
450 cparams,
451 VB_SCREEN_DEVELOPER_WARNING,
452 0, &vnc);
453 /* Start new countdown */
454 audio = VbAudioOpen(cparams);
455 }
456 } else {
457 /*
458 * No virtual dev-mode switch, so go directly
459 * to recovery mode.
460 */
461 VBDEBUG(("%s() - going to recovery\n",
462 __func__));
463 VbSetRecoveryRequest(
464 VBNV_RECOVERY_RW_DEV_SCREEN);
465 VbAudioClose(audio);
466 return VBERROR_LOAD_KERNEL_RECOVERY;
467 }
468 break;
469 case 0x04:
470 /* Ctrl+D = dismiss warning; advance to timeout */
471 VBDEBUG(("VbBootDeveloper() - "
472 "user pressed Ctrl+D; skip delay\n"));
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700473 ctrl_d_pressed = 1;
Randall Spangler29accd92013-02-04 14:01:04 -0800474 goto fallout;
475 break;
476 case 0x0c:
477 VBDEBUG(("VbBootDeveloper() - "
478 "user pressed Ctrl+L; Try legacy boot\n"));
Julius Werner957b4242015-05-08 22:54:14 -0700479 VbTryLegacy(allow_legacy);
Randall Spangler29accd92013-02-04 14:01:04 -0800480 break;
481
Randall Spangler7f436692013-02-05 12:42:36 -0800482 case VB_KEY_CTRL_ENTER:
483 /*
484 * The Ctrl-Enter is special for Lumpy test purpose;
485 * fall through to Ctrl+U handler.
486 */
Randall Spangler29accd92013-02-04 14:01:04 -0800487 case 0x15:
488 /* Ctrl+U = try USB boot, or beep if failure */
489 VBDEBUG(("VbBootDeveloper() - "
490 "user pressed Ctrl+U; try USB\n"));
491 if (!allow_usb) {
492 VBDEBUG(("VbBootDeveloper() - "
493 "USB booting is disabled\n"));
494 VbExDisplayDebugInfo(
495 "WARNING: Booting from external media "
496 "(USB/SD) has not been enabled. Refer "
497 "to the developer-mode documentation "
498 "for details.\n");
499 VbExBeep(120, 400);
500 VbExSleepMs(120);
501 VbExBeep(120, 400);
502 } else {
503 /*
504 * Clear the screen to show we get the Ctrl+U
505 * key press.
506 */
507 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0,
508 &vnc);
Mary Ruthven12a55f22015-10-06 10:42:31 -0700509 if (VBERROR_SUCCESS == VbTryUsb(cparams, p)) {
Randall Spangler29accd92013-02-04 14:01:04 -0800510 VbAudioClose(audio);
511 return VBERROR_SUCCESS;
512 } else {
Randall Spangler29accd92013-02-04 14:01:04 -0800513 /* Show dev mode warning screen again */
514 VbDisplayScreen(
515 cparams,
516 VB_SCREEN_DEVELOPER_WARNING,
517 0, &vnc);
518 }
519 }
520 break;
521 default:
522 VBDEBUG(("VbBootDeveloper() - pressed key %d\n", key));
523 VbCheckDisplayKey(cparams, key, &vnc);
524 break;
525 }
526 } while(VbAudioLooping(audio));
Bill Richardson25a3dbc2011-09-23 15:14:49 -0700527
Randall Spangler29accd92013-02-04 14:01:04 -0800528 fallout:
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700529
530 /* If defaulting to legacy boot, try that unless Ctrl+D was pressed */
Mary Ruthven12a55f22015-10-06 10:42:31 -0700531 if (use_legacy && !ctrl_d_pressed) {
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700532 VBDEBUG(("VbBootDeveloper() - defaulting to legacy\n"));
Julius Werner0140cd22015-05-08 23:00:16 -0700533 VbTryLegacy(allow_legacy);
Randall Spanglerf2a1dc02013-06-11 16:53:07 -0700534 }
535
Mary Ruthven12a55f22015-10-06 10:42:31 -0700536 if ((use_usb && !ctrl_d_pressed) && allow_usb) {
537 if (VBERROR_SUCCESS == VbTryUsb(cparams, p)) {
538 VbAudioClose(audio);
539 return VBERROR_SUCCESS;
540 }
541 }
542
Randall Spangler29accd92013-02-04 14:01:04 -0800543 /* Timeout or Ctrl+D; attempt loading from fixed disk */
544 VBDEBUG(("VbBootDeveloper() - trying fixed disk\n"));
545 VbAudioClose(audio);
546 return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700547}
548
Simon Glass74fa2072012-09-06 14:55:31 -0700549/* Delay in recovery mode */
Shawn Nematbakhsh04171532013-12-13 14:41:47 -0800550#define REC_DISK_DELAY 1000 /* Check disks every 1s */
551#define REC_KEY_DELAY 20 /* Check keys every 20ms */
552#define REC_MEDIA_INIT_DELAY 500 /* Check removable media every 500ms */
Randall Spangler1b1998d2011-07-01 16:12:47 -0700553
Randall Spangler29accd92013-02-04 14:01:04 -0800554VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p)
555{
556 VbSharedDataHeader *shared =
557 (VbSharedDataHeader *)cparams->shared_data_blob;
558 uint32_t retval;
559 uint32_t key;
560 int i;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700561
Randall Spangler29accd92013-02-04 14:01:04 -0800562 VBDEBUG(("VbBootRecovery() start\n"));
Randall Spangler1b1998d2011-07-01 16:12:47 -0700563
Randall Spangler29accd92013-02-04 14:01:04 -0800564 /*
565 * If the dev-mode switch is off and the user didn't press the recovery
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700566 * button (recovery was triggerred automatically), show 'broken' screen.
567 * The user can either only shutdown to abort or hit esc+refresh+power
568 * to initiate recovery as instructed on the screen.
Randall Spangler29accd92013-02-04 14:01:04 -0800569 */
570 if (!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
571 !(shared->flags & VBSD_BOOT_REC_SWITCH_ON)) {
Daisuke Nojiri3a631482015-10-20 18:31:10 -0700572 /*
573 * We have to save the reason here so that it will survive
574 * coming up three-finger-salute. We're saving it in
575 * VBNV_RECOVERY_SUBCODE to avoid a recovery loop.
576 * If we save the reason in VBNV_RECOVERY_REQUEST, we will come
577 * back here, thus, we won't be able to give a user a chance to
578 * reboot to workaround boot hicups.
579 */
580 VBDEBUG(("VbBootRecovery() saving recovery reason (%#x)\n",
581 shared->recovery_reason));
582 VbSetRecoverySubcode(shared->recovery_reason);
583 VbNvCommit();
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700584 VbDisplayScreen(cparams, VB_SCREEN_OS_BROKEN, 0, &vnc);
Daisuke Nojiri3a631482015-10-20 18:31:10 -0700585 VBDEBUG(("VbBootRecovery() waiting for manual recovery\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800586 while (1) {
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700587 VbCheckDisplayKey(cparams, VbExKeyboardRead(), &vnc);
588 if (VbWantShutdown(cparams->gbb->flags))
589 return VBERROR_SHUTDOWN_REQUESTED;
590 VbExSleepMs(REC_KEY_DELAY);
Randall Spangler29accd92013-02-04 14:01:04 -0800591 }
592 }
Randall Spangler1b1998d2011-07-01 16:12:47 -0700593
Randall Spangler29accd92013-02-04 14:01:04 -0800594 /* Loop and wait for a recovery image */
Daisuke Nojiri73a63722015-04-30 12:41:24 -0700595 VBDEBUG(("VbBootRecovery() waiting for a recovery image\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800596 while (1) {
597 VBDEBUG(("VbBootRecovery() attempting to load kernel2\n"));
598 retval = VbTryLoadKernel(cparams, p, VB_DISK_FLAG_REMOVABLE);
Randall Spanglerad334852011-07-19 15:52:43 -0700599
Randall Spangler29accd92013-02-04 14:01:04 -0800600 /*
601 * Clear recovery requests from failed kernel loading, since
602 * we're already in recovery mode. Do this now, so that
603 * powering off after inserting an invalid disk doesn't leave
604 * us stuck in recovery mode.
605 */
606 VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700607
Randall Spangler29accd92013-02-04 14:01:04 -0800608 if (VBERROR_SUCCESS == retval)
609 break; /* Found a recovery kernel */
Randall Spangler1b1998d2011-07-01 16:12:47 -0700610
Randall Spangler29accd92013-02-04 14:01:04 -0800611 VbDisplayScreen(cparams, VBERROR_NO_DISK_FOUND == retval ?
612 VB_SCREEN_RECOVERY_INSERT :
613 VB_SCREEN_RECOVERY_NO_GOOD,
614 0, &vnc);
Randall Spangler1b1998d2011-07-01 16:12:47 -0700615
Randall Spangler29accd92013-02-04 14:01:04 -0800616 /*
617 * Scan keyboard more frequently than media, since x86
618 * platforms don't like to scan USB too rapidly.
619 */
620 for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
621 key = VbExKeyboardRead();
622 /*
623 * We might want to enter dev-mode from the Insert
624 * screen if all of the following are true:
625 * - user pressed Ctrl-D
626 * - we can honor the virtual dev switch
627 * - not already in dev mode
628 * - user forced recovery mode
629 * - EC isn't pwned
630 */
631 if (key == 0x04 &&
632 shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
633 !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
634 (shared->flags & VBSD_BOOT_REC_SWITCH_ON) &&
Randall Spanglere778ada2014-07-15 16:14:21 -0700635 VbExTrustEC(0)) {
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800636 if (!(shared->flags &
637 VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
638 VbExGetSwitches(
639 VB_INIT_FLAG_REC_BUTTON_PRESSED)) {
640 /*
641 * Is the recovery button stuck? In
642 * any case we don't like this. Beep
643 * and ignore.
644 */
645 VBDEBUG(("%s() - ^D but rec switch "
646 "is pressed\n", __func__));
647 VbExBeep(120, 400);
648 continue;
649 }
650
Randall Spangler29accd92013-02-04 14:01:04 -0800651 /* Ask the user to confirm entering dev-mode */
652 VbDisplayScreen(cparams,
653 VB_SCREEN_RECOVERY_TO_DEV,
654 0, &vnc);
655 /* SPACE means no... */
Luigi Semenzatoa53a0b02014-01-10 16:26:08 -0800656 uint32_t vbc_flags =
657 VB_CONFIRM_SPACE_MEANS_NO |
658 VB_CONFIRM_MUST_TRUST_KEYBOARD;
659 switch (VbUserConfirms(cparams, vbc_flags)) {
Randall Spangler29accd92013-02-04 14:01:04 -0800660 case 1:
661 VBDEBUG(("%s() Enabling dev-mode...\n",
662 __func__));
663 if (TPM_SUCCESS != SetVirtualDevMode(1))
664 return VBERROR_TPM_SET_BOOT_MODE_STATE;
665 VBDEBUG(("%s() Reboot so it will take "
666 "effect\n", __func__));
Vadim Bendeburyccca6662015-04-06 18:04:44 -0700667 if (VbExGetSwitches
668 (VB_INIT_FLAG_ALLOW_USB_BOOT))
669 VbAllowUsbBoot();
Randall Spangler29accd92013-02-04 14:01:04 -0800670 return VBERROR_TPM_REBOOT_REQUIRED;
671 case -1:
672 VBDEBUG(("%s() - Shutdown requested\n",
673 __func__));
674 return VBERROR_SHUTDOWN_REQUESTED;
675 default: /* zero, actually */
676 VBDEBUG(("%s() - Not enabling "
677 "dev-mode\n", __func__));
678 /*
679 * Jump out of the outer loop to
680 * refresh the display quickly.
681 */
682 i = 4;
683 break;
684 }
685 } else {
686 VbCheckDisplayKey(cparams, key, &vnc);
687 }
Shawn Nematbakhsh5d652cd2014-12-12 09:40:42 -0800688 if (VbWantShutdown(cparams->gbb->flags))
Randall Spangler29accd92013-02-04 14:01:04 -0800689 return VBERROR_SHUTDOWN_REQUESTED;
690 VbExSleepMs(REC_KEY_DELAY);
691 }
692 }
693
694 return VBERROR_SUCCESS;
Randall Spangler1b1998d2011-07-01 16:12:47 -0700695}
696
Randall Spangler29accd92013-02-04 14:01:04 -0800697/**
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800698 * Wrapper around VbExEcProtect() which sets recovery reason on error.
Randall Spangler29accd92013-02-04 14:01:04 -0800699 */
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800700static VbError_t EcProtect(int devidx, enum VbSelectFirmware_t select)
Randall Spangler29accd92013-02-04 14:01:04 -0800701{
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800702 int rv = VbExEcProtect(devidx, select);
Randall Spangler09d0c2e2012-07-25 15:52:51 -0700703
Randall Spangler29accd92013-02-04 14:01:04 -0800704 if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800705 VBDEBUG(("VbExEcProtect() needs reboot\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800706 } else if (rv != VBERROR_SUCCESS) {
Mary Ruthven7e0728d2015-12-18 11:16:02 -0800707 VBDEBUG(("VbExEcProtect() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800708 VbSetRecoveryRequest(VBNV_RECOVERY_EC_PROTECT);
709 }
710 return rv;
Randall Spangler09d0c2e2012-07-25 15:52:51 -0700711}
Randall Spangler1b1998d2011-07-01 16:12:47 -0700712
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800713static VbError_t EcUpdateImage(int devidx, VbCommonParams *cparams,
714 enum VbSelectFirmware_t select,
715 int *need_update, int in_rw)
716{
717 VbSharedDataHeader *shared =
718 (VbSharedDataHeader *)cparams->shared_data_blob;
719 int rv;
720 int hash_size;
Julius Wernere1867d22016-05-27 13:27:18 -0700721 int ec_hash_size;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800722 const uint8_t *hash = NULL;
723 const uint8_t *expected = NULL;
724 const uint8_t *ec_hash = NULL;
725 int expected_size;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800726 int i;
727 int rw_request = select != VB_SELECT_FIRMWARE_READONLY;
728
729 *need_update = 0;
730 VBDEBUG(("EcUpdateImage() - "
731 "Check for %s update\n", rw_request ? "RW" : "RO"));
732
733 /* Get current EC hash. */
Julius Wernere1867d22016-05-27 13:27:18 -0700734 rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800735 if (rv) {
736 VBDEBUG(("EcUpdateImage() - "
737 "VbExEcHashImage() returned %d\n", rv));
738 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
739 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
740 }
Julius Wernere1867d22016-05-27 13:27:18 -0700741 VBDEBUG(("EC-%s hash: ", rw_request ? "RW" : "RO"));
742 for (i = 0; i < ec_hash_size; i++)
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800743 VBDEBUG(("%02x",ec_hash[i]));
744 VBDEBUG(("\n"));
745
746 /* Get expected EC hash. */
747 rv = VbExEcGetExpectedImageHash(devidx, select, &hash, &hash_size);
Julius Wernere1867d22016-05-27 13:27:18 -0700748 if (rv) {
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800749 VBDEBUG(("EcUpdateImage() - "
750 "VbExEcGetExpectedImageHash() returned %d\n", rv));
751 VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
752 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Julius Wernere1867d22016-05-27 13:27:18 -0700753 }
754 if (ec_hash_size != hash_size) {
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800755 VBDEBUG(("EcUpdateImage() - "
Julius Wernere1867d22016-05-27 13:27:18 -0700756 "EC uses %d-byte hash, but AP-RW contains %d bytes\n",
757 ec_hash_size, hash_size));
758 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800759 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800760 }
761
Julius Wernere1867d22016-05-27 13:27:18 -0700762 VBDEBUG(("Expected hash: "));
763 for (i = 0; i < hash_size; i++)
764 VBDEBUG(("%02x", hash[i]));
765 VBDEBUG(("\n"));
Randall Spangler49e517d2016-10-14 10:41:44 -0700766 *need_update = vb2_safe_memcmp(ec_hash, hash, hash_size);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800767
Julius Wernere1867d22016-05-27 13:27:18 -0700768 if (!*need_update)
769 return VBERROR_SUCCESS;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800770
Julius Wernere1867d22016-05-27 13:27:18 -0700771 /* Get expected EC image */
772 rv = VbExEcGetExpectedImage(devidx, select, &expected, &expected_size);
773 if (rv) {
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800774 VBDEBUG(("EcUpdateImage() - "
775 "VbExEcGetExpectedImage() returned %d\n", rv));
Julius Wernere1867d22016-05-27 13:27:18 -0700776 VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
777 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
778 }
779 VBDEBUG(("EcUpdateImage() - image len = %d\n", expected_size));
780
781 if (in_rw && rw_request) {
782 /*
783 * Check if BIOS should also load VGA Option ROM when
784 * rebooting to save another reboot if possible.
785 */
786 if ((shared->flags & VBSD_EC_SLOW_UPDATE) &&
787 (shared->flags & VBSD_OPROM_MATTERS) &&
788 !(shared->flags & VBSD_OPROM_LOADED)) {
789 VBDEBUG(("EcUpdateImage() - Reboot to "
790 "load VGA Option ROM\n"));
791 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
792 }
793
794 /*
795 * EC is running the wrong RW image. Reboot the EC to
796 * RO so we can update it on the next boot.
797 */
798 VBDEBUG(("EcUpdateImage() - "
799 "in RW, need to update RW, so reboot\n"));
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800800 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
801 }
802
Julius Wernere1867d22016-05-27 13:27:18 -0700803 VBDEBUG(("EcUpdateImage() updating EC-%s...\n",
804 rw_request ? "RW" : "RO"));
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800805
Julius Wernere1867d22016-05-27 13:27:18 -0700806 if (shared->flags & VBSD_EC_SLOW_UPDATE) {
807 VBDEBUG(("EcUpdateImage() - EC is slow. Show WAIT screen.\n"));
808
809 /* Ensure the VGA Option ROM is loaded */
810 if ((shared->flags & VBSD_OPROM_MATTERS) &&
811 !(shared->flags & VBSD_OPROM_LOADED)) {
812 VBDEBUG(("EcUpdateImage() - Reboot to "
813 "load VGA Option ROM\n"));
814 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
815 return VBERROR_VGA_OPROM_MISMATCH;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800816 }
817
Julius Wernere1867d22016-05-27 13:27:18 -0700818 VbDisplayScreen(cparams, VB_SCREEN_WAIT, 0, &vnc);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800819 }
820
Julius Wernere1867d22016-05-27 13:27:18 -0700821 rv = VbExEcUpdateImage(devidx, select, expected, expected_size);
822 if (rv != VBERROR_SUCCESS) {
823 VBDEBUG(("EcUpdateImage() - "
824 "VbExEcUpdateImage() returned %d\n", rv));
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800825
Julius Wernere1867d22016-05-27 13:27:18 -0700826 /*
827 * The EC may know it needs a reboot. It may need to
828 * unprotect the region before updating, or may need to
829 * reboot after updating. Either way, it's not an error
830 * requiring recovery mode.
831 *
832 * If we fail for any other reason, trigger recovery
833 * mode.
834 */
835 if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
836 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800837
Julius Wernere1867d22016-05-27 13:27:18 -0700838 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800839 }
840
841 /* Verify the EC was updated properly */
Julius Wernere1867d22016-05-27 13:27:18 -0700842 rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
843 if (rv) {
844 VBDEBUG(("EcUpdateImage() - "
845 "VbExEcHashImage() returned %d\n", rv));
846 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
847 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800848 }
Julius Wernere1867d22016-05-27 13:27:18 -0700849 if (hash_size != ec_hash_size) {
850 VBDEBUG(("EcUpdateImage() - "
851 "VbExEcHashImage() says size %d, not %d\n",
852 ec_hash_size, hash_size));
853 VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
854 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
855 }
856 VBDEBUG(("Updated EC-%s hash: ", rw_request ? "RW" : "RO"));
857 for (i = 0; i < ec_hash_size; i++)
858 VBDEBUG(("%02x",ec_hash[i]));
859 VBDEBUG(("\n"));
860
Randall Spangler49e517d2016-10-14 10:41:44 -0700861 if (vb2_safe_memcmp(ec_hash, hash, hash_size)){
Julius Wernere1867d22016-05-27 13:27:18 -0700862 VBDEBUG(("EcUpdateImage() - "
863 "Failed to update EC-%s\n", rw_request ?
864 "RW" : "RO"));
865 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
866 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
867 }
868
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800869 return VBERROR_SUCCESS;
870}
871
Randall Spanglere778ada2014-07-15 16:14:21 -0700872VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams)
Randall Spangler29accd92013-02-04 14:01:04 -0800873{
874 VbSharedDataHeader *shared =
875 (VbSharedDataHeader *)cparams->shared_data_blob;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800876 enum VbSelectFirmware_t select_rw =
877 shared->firmware_index ? VB_SELECT_FIRMWARE_B :
878 VB_SELECT_FIRMWARE_A;
879 enum VbSelectFirmware_t select_ro = VB_SELECT_FIRMWARE_READONLY;
Randall Spangler29accd92013-02-04 14:01:04 -0800880 int in_rw = 0;
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800881 int ro_try_count = 2;
882 int num_tries = 0;
883 uint32_t try_ro_sync, recovery_request;
884 int rv, updated_rw, updated_ro;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700885
Randall Spangler6014c042014-07-22 14:42:58 -0700886 VBDEBUG(("VbEcSoftwareSync(devidx=%d)\n", devidx));
887
Randall Spangler29accd92013-02-04 14:01:04 -0800888 /* Determine whether the EC is in RO or RW */
Randall Spanglere778ada2014-07-15 16:14:21 -0700889 rv = VbExEcRunningRW(devidx, &in_rw);
Randall Spangler584e0d22012-07-26 10:29:48 -0700890
Randall Spangler29accd92013-02-04 14:01:04 -0800891 if (shared->recovery_reason) {
892 /* Recovery mode; just verify the EC is in RO code */
893 if (rv == VBERROR_SUCCESS && in_rw == 1) {
894 /*
895 * EC is definitely in RW firmware. We want it in
896 * read-only code, so preserve the current recovery
897 * reason and reboot.
898 *
899 * We don't reboot on error or unknown EC code, because
900 * we could end up in an endless reboot loop. If we
901 * had some way to track that we'd already rebooted for
902 * this reason, we could retry only once.
903 */
904 VBDEBUG(("VbEcSoftwareSync() - "
905 "want recovery but got EC-RW\n"));
906 VbSetRecoveryRequest(shared->recovery_reason);
907 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
908 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700909
Randall Spangler29accd92013-02-04 14:01:04 -0800910 VBDEBUG(("VbEcSoftwareSync() in recovery; EC-RO\n"));
911 return VBERROR_SUCCESS;
912 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700913
Randall Spangler29accd92013-02-04 14:01:04 -0800914 /*
915 * Not in recovery. If we couldn't determine where the EC was,
916 * reboot to recovery.
917 */
918 if (rv != VBERROR_SUCCESS) {
919 VBDEBUG(("VbEcSoftwareSync() - "
Vadim Bendebury48b26df2013-06-21 16:28:28 -0700920 "VbExEcRunningRW() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800921 VbSetRecoveryRequest(VBNV_RECOVERY_EC_UNKNOWN_IMAGE);
922 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
923 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700924
Randall Spangler29accd92013-02-04 14:01:04 -0800925 /* If AP is read-only normal, EC should be in its RO code also. */
926 if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
927 /* If EC is in RW code, request reboot back to RO */
928 if (in_rw == 1) {
929 VBDEBUG(("VbEcSoftwareSync() - "
930 "want RO-normal but got EC-RW\n"));
931 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
932 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700933
Randall Spangler29accd92013-02-04 14:01:04 -0800934 /* Protect the RW flash and stay in EC-RO */
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800935 rv = EcProtect(devidx, select_rw);
Randall Spangler29accd92013-02-04 14:01:04 -0800936 if (rv != VBERROR_SUCCESS)
937 return rv;
Randall Spanglerd4faa062012-07-16 16:42:40 -0700938
Randall Spanglere778ada2014-07-15 16:14:21 -0700939 rv = VbExEcDisableJump(devidx);
Randall Spangler29accd92013-02-04 14:01:04 -0800940 if (rv != VBERROR_SUCCESS) {
941 VBDEBUG(("VbEcSoftwareSync() - "
Daisuke Nojiri89121692013-10-10 11:51:45 -0700942 "VbExEcDisableJump() returned %d\n", rv));
Randall Spangler29accd92013-02-04 14:01:04 -0800943 VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
944 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
945 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700946
Randall Spangler29accd92013-02-04 14:01:04 -0800947 VBDEBUG(("VbEcSoftwareSync() in RO-Normal; EC-RO\n"));
Randall Spangler29accd92013-02-04 14:01:04 -0800948 return VBERROR_SUCCESS;
949 }
Randall Spanglerd4faa062012-07-16 16:42:40 -0700950
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800951 VBDEBUG(("VbEcSoftwareSync() check for RW update.\n"));
952
953 /* Update the RW Image. */
954 rv = EcUpdateImage(devidx, cparams, select_rw, &updated_rw, in_rw);
955
956 if (rv != VBERROR_SUCCESS) {
Randall Spangler29accd92013-02-04 14:01:04 -0800957 VBDEBUG(("VbEcSoftwareSync() - "
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800958 "EcUpdateImage() returned %d\n", rv));
959 return rv;
Randall Spangler29accd92013-02-04 14:01:04 -0800960 }
Randall Spangler241de332012-07-23 16:24:43 -0700961
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800962 /* Tell EC to jump to its RW image */
963 if (!in_rw) {
964 VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n"));
965 rv = VbExEcJumpToRW(devidx);
Randall Spanglerbbc76062013-09-20 11:18:08 -0700966 if (rv != VBERROR_SUCCESS) {
Randall Spangler29accd92013-02-04 14:01:04 -0800967 VBDEBUG(("VbEcSoftwareSync() - "
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800968 "VbExEcJumpToRW() returned %x\n", rv));
Randall Spanglerbbc76062013-09-20 11:18:08 -0700969
970 /*
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800971 * If the EC booted RO-normal and a previous AP boot
972 * has called VbExEcStayInRO(), we need to reboot the EC
973 * to unlock the ability to jump to the RW firmware.
Randall Spanglerbbc76062013-09-20 11:18:08 -0700974 *
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800975 * All other errors trigger recovery mode.
Randall Spanglerbbc76062013-09-20 11:18:08 -0700976 */
977 if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800978 VbSetRecoveryRequest(VBNV_RECOVERY_EC_JUMP_RW);
Randall Spanglerbbc76062013-09-20 11:18:08 -0700979
Randall Spangler29accd92013-02-04 14:01:04 -0800980 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
981 }
Randall Spangler29accd92013-02-04 14:01:04 -0800982 }
Randall Spangler241de332012-07-23 16:24:43 -0700983
Mary Ruthvenbcf83892016-01-06 11:30:55 -0800984 VbNvGet(&vnc, VBNV_TRY_RO_SYNC, &try_ro_sync);
985
986 if (!devidx && try_ro_sync &&
987 !(shared->flags & VBSD_BOOT_FIRMWARE_WP_ENABLED)) {
988 /* Reset RO Software Sync NV flag */
989 VbNvSet(&vnc, VBNV_TRY_RO_SYNC, 0);
990
991 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery_request);
992
993 /* Update the RO Image. */
994 while (num_tries < ro_try_count) {
995 VBDEBUG(("VbEcSoftwareSync() RO Software Sync\n"));
996
997 /* Get expected EC-RO Image. */
998 rv = EcUpdateImage(devidx, cparams, select_ro,
999 &updated_ro, in_rw);
1000 if (rv == VBERROR_SUCCESS) {
1001 /*
1002 * If the RO update had failed, reset the
1003 * recovery request.
1004 */
1005 if (num_tries)
1006 VbSetRecoveryRequest(recovery_request);
1007 break;
1008 } else
1009 VBDEBUG(("VbEcSoftwareSync() - "
1010 "EcUpdateImage() returned %d\n", rv));
1011
1012 num_tries++;
1013 }
1014 }
Randall Spangler29accd92013-02-04 14:01:04 -08001015 if (rv != VBERROR_SUCCESS)
1016 return rv;
Randall Spangler241de332012-07-23 16:24:43 -07001017
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001018 /* Protect RO flash */
1019 rv = EcProtect(devidx, select_ro);
1020 if (rv != VBERROR_SUCCESS)
1021 return rv;
Randall Spanglerbbc76062013-09-20 11:18:08 -07001022
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001023 /* Protect RW flash */
1024 rv = EcProtect(devidx, select_rw);
1025 if (rv != VBERROR_SUCCESS)
1026 return rv;
Daisuke Nojiri89121692013-10-10 11:51:45 -07001027
Randall Spanglere778ada2014-07-15 16:14:21 -07001028 rv = VbExEcDisableJump(devidx);
Daisuke Nojiri89121692013-10-10 11:51:45 -07001029 if (rv != VBERROR_SUCCESS) {
1030 VBDEBUG(("VbEcSoftwareSync() - "
1031 "VbExEcDisableJump() returned %d\n", rv));
1032 VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
1033 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
1034 }
Randall Spangler241de332012-07-23 16:24:43 -07001035
Duncan Laurie731f8e82014-10-16 11:05:13 -07001036 /*
1037 * Reboot to unload VGA Option ROM if:
1038 * - RW update was done
1039 * - the system is NOT in developer mode
1040 * - the system has slow EC update flag set
1041 * - the VGA Option ROM was needed and loaded
1042 */
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001043 if (updated_rw &&
Duncan Laurie731f8e82014-10-16 11:05:13 -07001044 !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
1045 (shared->flags & VBSD_EC_SLOW_UPDATE) &&
1046 (shared->flags & VBSD_OPROM_MATTERS) &&
1047 (shared->flags & VBSD_OPROM_LOADED)) {
1048 VBDEBUG(("VbEcSoftwareSync() - Reboot to "
1049 "unload VGA Option ROM\n"));
Duncan Laurieeea01162016-01-20 12:53:15 -08001050 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0);
Duncan Laurie731f8e82014-10-16 11:05:13 -07001051 return VBERROR_VGA_OPROM_MISMATCH;
1052 }
1053
Mary Ruthvenbcf83892016-01-06 11:30:55 -08001054
1055 return rv;
Randall Spanglerd4faa062012-07-16 16:42:40 -07001056}
1057
Simon Glass527ba812013-07-25 08:48:47 -06001058/* This function is also used by tests */
1059void VbApiKernelFree(VbCommonParams *cparams)
1060{
1061 /* VbSelectAndLoadKernel() always allocates this, tests don't */
1062 if (cparams->gbb) {
Randall Spangler559a1102016-10-18 14:41:22 -07001063 free(cparams->gbb);
Simon Glass527ba812013-07-25 08:48:47 -06001064 cparams->gbb = NULL;
1065 }
1066 if (cparams->bmp) {
Randall Spangler559a1102016-10-18 14:41:22 -07001067 free(cparams->bmp);
Simon Glass527ba812013-07-25 08:48:47 -06001068 cparams->bmp = NULL;
1069 }
1070}
1071
Randall Spangler29accd92013-02-04 14:01:04 -08001072VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
1073 VbSelectAndLoadKernelParams *kparams)
1074{
1075 VbSharedDataHeader *shared =
1076 (VbSharedDataHeader *)cparams->shared_data_blob;
1077 VbError_t retval = VBERROR_SUCCESS;
1078 LoadKernelParams p;
1079 uint32_t tpm_status = 0;
Hung-Te Linaee6bd62016-04-07 12:21:03 +08001080 uint32_t battery_cutoff = 0;
Randall Spanglerd4faa062012-07-16 16:42:40 -07001081
Randall Spangler29accd92013-02-04 14:01:04 -08001082 /* Start timer */
1083 shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer();
Randall Spangler1b1998d2011-07-01 16:12:47 -07001084
Randall Spangler29accd92013-02-04 14:01:04 -08001085 VbExNvStorageRead(vnc.raw);
1086 VbNvSetup(&vnc);
Randall Spangler96191122011-07-08 14:01:54 -07001087
Randall Spangler1589f942016-09-02 12:10:31 -07001088 /* Fill in params for calls to LoadKernel() */
Randall Spangler664096b2016-10-13 16:16:41 -07001089 memset(&p, 0, sizeof(p));
Randall Spangler1589f942016-09-02 12:10:31 -07001090 p.shared_data_blob = cparams->shared_data_blob;
1091 p.shared_data_size = cparams->shared_data_size;
1092 p.gbb_data = cparams->gbb_data;
1093 p.gbb_size = cparams->gbb_size;
1094 p.fwmp = &fwmp;
1095 p.nv_context = &vnc;
1096
1097 /*
1098 * This could be set to NULL, in which case the vboot header
1099 * information about the load address and size will be used.
1100 */
1101 p.kernel_buffer = kparams->kernel_buffer;
1102 p.kernel_buffer_size = kparams->kernel_buffer_size;
1103
Randall Spangler29accd92013-02-04 14:01:04 -08001104 /* Clear output params in case we fail */
1105 kparams->disk_handle = NULL;
1106 kparams->partition_number = 0;
1107 kparams->bootloader_address = 0;
1108 kparams->bootloader_size = 0;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -08001109 kparams->flags = 0;
Randall Spangler664096b2016-10-13 16:16:41 -07001110 memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));
Randall Spangler1b1998d2011-07-01 16:12:47 -07001111
Simon Glass527ba812013-07-25 08:48:47 -06001112 cparams->bmp = NULL;
Randall Spangler559a1102016-10-18 14:41:22 -07001113 cparams->gbb = malloc(sizeof(*cparams->gbb));
Simon Glass527ba812013-07-25 08:48:47 -06001114 retval = VbGbbReadHeader_static(cparams, cparams->gbb);
1115 if (VBERROR_SUCCESS != retval)
1116 goto VbSelectAndLoadKernel_exit;
1117
Randall Spangler29accd92013-02-04 14:01:04 -08001118 /* Do EC software sync if necessary */
Randall Spanglerf2a1dc02013-06-11 16:53:07 -07001119 if ((shared->flags & VBSD_EC_SOFTWARE_SYNC) &&
Simon Glass527ba812013-07-25 08:48:47 -06001120 !(cparams->gbb->flags & GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)) {
Duncan Laurie731f8e82014-10-16 11:05:13 -07001121 int oprom_mismatch = 0;
1122
Randall Spanglere778ada2014-07-15 16:14:21 -07001123 retval = VbEcSoftwareSync(0, cparams);
Duncan Laurie731f8e82014-10-16 11:05:13 -07001124 /* Save reboot requested until after possible PD sync */
1125 if (retval == VBERROR_VGA_OPROM_MISMATCH)
1126 oprom_mismatch = 1;
1127 else if (retval != VBERROR_SUCCESS)
Randall Spangler29accd92013-02-04 14:01:04 -08001128 goto VbSelectAndLoadKernel_exit;
Randall Spangler6014c042014-07-22 14:42:58 -07001129
1130#ifdef PD_SYNC
Duncan Laurie277dc522014-08-11 12:30:04 -07001131 if (!(cparams->gbb->flags &
1132 GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC)) {
1133 retval = VbEcSoftwareSync(1, cparams);
Duncan Laurie731f8e82014-10-16 11:05:13 -07001134 if (retval == VBERROR_VGA_OPROM_MISMATCH)
1135 oprom_mismatch = 1;
1136 else if (retval != VBERROR_SUCCESS)
Duncan Laurie277dc522014-08-11 12:30:04 -07001137 goto VbSelectAndLoadKernel_exit;
1138 }
Randall Spangler6014c042014-07-22 14:42:58 -07001139#endif
Duncan Laurie731f8e82014-10-16 11:05:13 -07001140
1141 /* Request reboot to unload VGA Option ROM */
1142 if (oprom_mismatch) {
1143 retval = VBERROR_VGA_OPROM_MISMATCH;
1144 goto VbSelectAndLoadKernel_exit;
1145 }
Randall Spangler29accd92013-02-04 14:01:04 -08001146 }
Randall Spangler1b1998d2011-07-01 16:12:47 -07001147
Shawn Nematbakhshb491bc82015-10-21 14:31:02 -07001148 /* EC verification (and possibily updating / jumping) is done */
1149 retval = VbExEcVbootDone(!!shared->recovery_reason);
1150 if (retval != VBERROR_SUCCESS)
1151 goto VbSelectAndLoadKernel_exit;
1152
Hung-Te Linaee6bd62016-04-07 12:21:03 +08001153 /* Check if we need to cut-off battery. This must be done after EC
1154 * firmware updating and before kernel started. */
1155 VbNvGet(&vnc, VBNV_BATTERY_CUTOFF_REQUEST, &battery_cutoff);
1156 if (battery_cutoff) {
1157 VBDEBUG(("Request to cut-off battery\n"));
1158 VbNvSet(&vnc, VBNV_BATTERY_CUTOFF_REQUEST, 0);
1159 VbExEcBatteryCutOff();
1160 retval = VBERROR_SHUTDOWN_REQUESTED;
1161 goto VbSelectAndLoadKernel_exit;
1162 }
1163
Randall Spangler29accd92013-02-04 14:01:04 -08001164 /* Read kernel version from the TPM. Ignore errors in recovery mode. */
1165 tpm_status = RollbackKernelRead(&shared->kernel_version_tpm);
1166 if (0 != tpm_status) {
1167 VBDEBUG(("Unable to get kernel versions from TPM\n"));
1168 if (!shared->recovery_reason) {
1169 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_R_ERROR);
1170 retval = VBERROR_TPM_READ_KERNEL;
1171 goto VbSelectAndLoadKernel_exit;
1172 }
1173 }
1174 shared->kernel_version_tpm_start = shared->kernel_version_tpm;
Randall Spanglerd4faa062012-07-16 16:42:40 -07001175
Randall Spangler946abf12016-04-15 14:49:40 -07001176 /* Read FWMP. Ignore errors in recovery mode. */
1177 if (cparams->gbb->flags & GBB_FLAG_DISABLE_FWMP) {
Randall Spangler664096b2016-10-13 16:16:41 -07001178 memset(&fwmp, 0, sizeof(fwmp));
Randall Spangler946abf12016-04-15 14:49:40 -07001179 tpm_status = 0;
1180 } else {
1181 tpm_status = RollbackFwmpRead(&fwmp);
1182 }
1183 if (0 != tpm_status) {
1184 VBDEBUG(("Unable to get FWMP from TPM\n"));
1185 if (!shared->recovery_reason) {
1186 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_R_ERROR);
1187 retval = VBERROR_TPM_READ_FWMP;
1188 goto VbSelectAndLoadKernel_exit;
1189 }
1190 }
1191
Randall Spangler1589f942016-09-02 12:10:31 -07001192 /* Set up boot flags */
Randall Spangler29accd92013-02-04 14:01:04 -08001193 p.boot_flags = 0;
1194 if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON)
1195 p.boot_flags |= BOOT_FLAG_DEVELOPER;
Vadim Bendeburyb321dbb2012-08-01 18:44:05 -07001196
Randall Spangler29accd92013-02-04 14:01:04 -08001197 /* Handle separate normal and developer firmware builds. */
Randall Spangler64ca7882011-07-11 15:46:19 -07001198#if defined(VBOOT_FIRMWARE_TYPE_NORMAL)
Randall Spangler29accd92013-02-04 14:01:04 -08001199 /* Normal-type firmware always acts like the dev switch is off. */
1200 p.boot_flags &= ~BOOT_FLAG_DEVELOPER;
Randall Spangler64ca7882011-07-11 15:46:19 -07001201#elif defined(VBOOT_FIRMWARE_TYPE_DEVELOPER)
Randall Spangler29accd92013-02-04 14:01:04 -08001202 /* Developer-type firmware fails if the dev switch is off. */
1203 if (!(p.boot_flags & BOOT_FLAG_DEVELOPER)) {
1204 /*
1205 * Dev firmware should be signed with a key that only verifies
1206 * when the dev switch is on, so we should never get here.
1207 */
1208 VBDEBUG(("Developer firmware called with dev switch off!\n"));
1209 VbSetRecoveryRequest(VBNV_RECOVERY_RW_DEV_MISMATCH);
1210 retval = VBERROR_DEV_FIRMWARE_SWITCH_MISMATCH;
1211 goto VbSelectAndLoadKernel_exit;
1212 }
Randall Spangler64ca7882011-07-11 15:46:19 -07001213#else
Randall Spangler29accd92013-02-04 14:01:04 -08001214 /*
1215 * Recovery firmware, or merged normal+developer firmware. No need to
1216 * override flags.
1217 */
Randall Spangler64ca7882011-07-11 15:46:19 -07001218#endif
1219
Randall Spangler29accd92013-02-04 14:01:04 -08001220 /* Select boot path */
1221 if (shared->recovery_reason) {
1222 /* Recovery boot */
1223 p.boot_flags |= BOOT_FLAG_RECOVERY;
1224 retval = VbBootRecovery(cparams, &p);
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001225 VbExEcEnteringMode(0, VB_EC_RECOVERY);
Randall Spangler29accd92013-02-04 14:01:04 -08001226 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0, &vnc);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001227
Randall Spangler29accd92013-02-04 14:01:04 -08001228 } else if (p.boot_flags & BOOT_FLAG_DEVELOPER) {
1229 /* Developer boot */
1230 retval = VbBootDeveloper(cparams, &p);
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001231 VbExEcEnteringMode(0, VB_EC_DEVELOPER);
Randall Spangler29accd92013-02-04 14:01:04 -08001232 VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0, &vnc);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001233
Randall Spangler29accd92013-02-04 14:01:04 -08001234 } else {
1235 /* Normal boot */
Sheng-Liang Song487a54b2014-07-26 21:34:28 -07001236 VbExEcEnteringMode(0, VB_EC_NORMAL);
Randall Spangler29accd92013-02-04 14:01:04 -08001237 retval = VbBootNormal(cparams, &p);
Randall Spangler22e7bb22011-07-22 14:06:51 -07001238
Randall Spangler29accd92013-02-04 14:01:04 -08001239 if ((1 == shared->firmware_index) &&
1240 (shared->flags & VBSD_FWB_TRIED)) {
1241 /*
1242 * Special cases for when we're trying a new firmware
1243 * B. These are needed because firmware updates also
1244 * usually change the kernel key, which means that the
1245 * B firmware can only boot a new kernel, and the old
1246 * firmware in A can only boot the previous kernel.
1247 *
1248 * Don't advance the TPM if we're trying a new firmware
1249 * B, because we don't yet know if the new kernel will
1250 * successfully boot. We still want to be able to fall
1251 * back to the previous firmware+kernel if the new
1252 * firmware+kernel fails.
1253 *
1254 * If we found only invalid kernels, reboot and try
1255 * again. This allows us to fall back to the previous
1256 * firmware+kernel instead of giving up and going to
1257 * recovery mode right away. We'll still go to
1258 * recovery mode if we run out of tries and the old
1259 * firmware can't find a kernel it likes.
1260 */
1261 if (VBERROR_INVALID_KERNEL_FOUND == retval) {
1262 VBDEBUG(("Trying firmware B, "
1263 "and only found invalid kernels.\n"));
1264 VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);
1265 goto VbSelectAndLoadKernel_exit;
1266 }
1267 } else {
1268 /* Not trying a new firmware B. */
Randall Spangler99275122011-07-26 16:26:59 -07001269
Randall Spangler29accd92013-02-04 14:01:04 -08001270 /* See if we need to update the TPM. */
1271 VBDEBUG(("Checking if TPM kernel version needs "
1272 "advancing\n"));
1273 if (shared->kernel_version_tpm >
1274 shared->kernel_version_tpm_start) {
1275 tpm_status = RollbackKernelWrite(
1276 shared->kernel_version_tpm);
1277 if (0 != tpm_status) {
1278 VBDEBUG(("Error writing kernel "
1279 "versions to TPM.\n"));
1280 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_W_ERROR);
1281 retval = VBERROR_TPM_WRITE_KERNEL;
1282 goto VbSelectAndLoadKernel_exit;
1283 }
1284 }
1285 }
1286 }
Randall Spangler99275122011-07-26 16:26:59 -07001287
Randall Spangler29accd92013-02-04 14:01:04 -08001288 if (VBERROR_SUCCESS != retval)
1289 goto VbSelectAndLoadKernel_exit;
Randall Spangler1b1998d2011-07-01 16:12:47 -07001290
Randall Spangler29accd92013-02-04 14:01:04 -08001291 /* Save disk parameters */
1292 kparams->disk_handle = p.disk_handle;
1293 kparams->partition_number = (uint32_t)p.partition_number;
1294 kparams->bootloader_address = p.bootloader_address;
1295 kparams->bootloader_size = (uint32_t)p.bootloader_size;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -08001296 kparams->flags = p.flags;
Randall Spangler664096b2016-10-13 16:16:41 -07001297 memcpy(kparams->partition_guid, p.partition_guid,
Randall Spangler29accd92013-02-04 14:01:04 -08001298 sizeof(kparams->partition_guid));
Randall Spangler22e7bb22011-07-22 14:06:51 -07001299
Randall Spangler29accd92013-02-04 14:01:04 -08001300 /* Lock the kernel versions. Ignore errors in recovery mode. */
Shawn Nematbakhsh964144b2013-07-22 13:33:46 -07001301 tpm_status = RollbackKernelLock(shared->recovery_reason);
Randall Spangler29accd92013-02-04 14:01:04 -08001302 if (0 != tpm_status) {
1303 VBDEBUG(("Error locking kernel versions.\n"));
1304 if (!shared->recovery_reason) {
1305 VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_L_ERROR);
1306 retval = VBERROR_TPM_LOCK_KERNEL;
1307 goto VbSelectAndLoadKernel_exit;
1308 }
1309 }
Randall Spangler22e7bb22011-07-22 14:06:51 -07001310
Randall Spangler29accd92013-02-04 14:01:04 -08001311 VbSelectAndLoadKernel_exit:
Randall Spangler1b1998d2011-07-01 16:12:47 -07001312
Simon Glass527ba812013-07-25 08:48:47 -06001313 VbApiKernelFree(cparams);
1314
Daisuke Nojiri3a631482015-10-20 18:31:10 -07001315 VbNvCommit();
Randall Spangler22e7bb22011-07-22 14:06:51 -07001316
Randall Spangler29accd92013-02-04 14:01:04 -08001317 /* Stop timer */
1318 shared->timer_vb_select_and_load_kernel_exit = VbExGetTimer();
Randall Spangler1b1998d2011-07-01 16:12:47 -07001319
Randall Spangler29accd92013-02-04 14:01:04 -08001320 kparams->kernel_buffer = p.kernel_buffer;
1321 kparams->kernel_buffer_size = p.kernel_buffer_size;
Randall Spangler96191122011-07-08 14:01:54 -07001322
Randall Spangler29accd92013-02-04 14:01:04 -08001323 VBDEBUG(("VbSelectAndLoadKernel() returning %d\n", (int)retval));
Vadim Bendeburyb321dbb2012-08-01 18:44:05 -07001324
Randall Spangler29accd92013-02-04 14:01:04 -08001325 /* Pass through return value from boot path */
1326 return retval;
Randall Spangler1b1998d2011-07-01 16:12:47 -07001327}
Furquan Shaikhf2743602015-05-21 14:39:11 -07001328
1329VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams,
1330 VbSelectAndLoadKernelParams *kparams,
1331 void *boot_image,
1332 size_t image_size)
1333{
1334 VbError_t retval;
1335 VbPublicKey* kernel_subkey = NULL;
1336 uint8_t *kbuf;
1337 VbKeyBlockHeader *key_block;
1338 VbSharedDataHeader *shared =
1339 (VbSharedDataHeader *)cparams->shared_data_blob;
Furquan Shaikhf2743602015-05-21 14:39:11 -07001340 VbKernelPreambleHeader *preamble;
1341 uint64_t body_offset;
1342 int hash_only = 0;
1343 int dev_switch;
Furquan Shaikh55484552015-10-28 13:01:27 -07001344 uint32_t allow_fastboot_full_cap = 0;
Randall Spangler13b10972016-10-14 11:04:27 -07001345 uint8_t *workbuf = NULL;
1346 struct vb2_workbuf wb;
Furquan Shaikhf2743602015-05-21 14:39:11 -07001347
1348 if ((boot_image == NULL) || (image_size == 0))
1349 return VBERROR_INVALID_PARAMETER;
1350
1351 /* Clear output params in case we fail. */
1352 kparams->disk_handle = NULL;
1353 kparams->partition_number = 0;
1354 kparams->bootloader_address = 0;
1355 kparams->bootloader_size = 0;
1356 kparams->flags = 0;
Randall Spangler664096b2016-10-13 16:16:41 -07001357 memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));
Furquan Shaikhf2743602015-05-21 14:39:11 -07001358
Furquan Shaikhf2743602015-05-21 14:39:11 -07001359 kbuf = boot_image;
Furquan Shaikhf2743602015-05-21 14:39:11 -07001360
1361 /* Read GBB Header */
1362 cparams->bmp = NULL;
Randall Spangler559a1102016-10-18 14:41:22 -07001363 cparams->gbb = malloc(sizeof(*cparams->gbb));
Furquan Shaikhf2743602015-05-21 14:39:11 -07001364 retval = VbGbbReadHeader_static(cparams, cparams->gbb);
1365 if (VBERROR_SUCCESS != retval) {
1366 VBDEBUG(("Gbb read header failed.\n"));
1367 return retval;
1368 }
1369
1370 /*
1371 * We don't care verifying the image if:
1372 * 1. dev-mode switch is on and
Furquan Shaikh55484552015-10-28 13:01:27 -07001373 * 2a. GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP is set, or
1374 * 2b. DEV_BOOT_FASTBOOT_FULL_CAP flag is set in NvStorage
Furquan Shaikhf2743602015-05-21 14:39:11 -07001375 *
1376 * Check only the integrity of the image.
1377 */
1378 dev_switch = shared->flags & VBSD_BOOT_DEV_SWITCH_ON;
Furquan Shaikh55484552015-10-28 13:01:27 -07001379
1380 VbExNvStorageRead(vnc.raw);
1381 VbNvSetup(&vnc);
1382 VbNvGet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP,
1383 &allow_fastboot_full_cap);
1384
1385 if (0 == allow_fastboot_full_cap) {
1386 allow_fastboot_full_cap = !!(cparams->gbb->flags &
1387 GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP);
1388 }
1389
1390 if (dev_switch && allow_fastboot_full_cap) {
Furquan Shaikhf2743602015-05-21 14:39:11 -07001391 VBDEBUG(("Only performing integrity-check.\n"));
1392 hash_only = 1;
1393 } else {
1394 /* Get recovery key. */
1395 retval = VbGbbReadRecoveryKey(cparams, &kernel_subkey);
1396 if (VBERROR_SUCCESS != retval) {
1397 VBDEBUG(("Gbb Read Recovery key failed.\n"));
1398 return retval;
1399 }
1400 }
1401
1402 /* If we fail at any step, retval returned would be invalid kernel. */
1403 retval = VBERROR_INVALID_KERNEL_FOUND;
1404
Randall Spangler13b10972016-10-14 11:04:27 -07001405 /* Allocate work buffer */
Randall Spangler559a1102016-10-18 14:41:22 -07001406 workbuf = (uint8_t *)malloc(VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE);
Randall Spangler13b10972016-10-14 11:04:27 -07001407 if (!workbuf)
1408 goto fail;
Randall Spanglera03a1642016-11-03 10:12:16 -07001409 vb2_workbuf_init(&wb, workbuf, VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE);
Randall Spangler13b10972016-10-14 11:04:27 -07001410
Furquan Shaikhf2743602015-05-21 14:39:11 -07001411 /* Verify the key block. */
Furquan Shaikh04e23382015-05-29 18:00:46 -07001412 key_block = (VbKeyBlockHeader *)kbuf;
Randall Spangler13b10972016-10-14 11:04:27 -07001413 struct vb2_keyblock *keyblock2 = (struct vb2_keyblock *)kbuf;
1414 int rv;
1415 if (hash_only) {
1416 rv = vb2_verify_keyblock_hash(keyblock2, image_size, &wb);
1417 } else {
1418 /* Unpack kernel subkey */
1419 struct vb2_public_key kernel_subkey2;
1420 if (VB2_SUCCESS != vb2_unpack_key(&kernel_subkey2,
1421 (const uint8_t *)kernel_subkey,
1422 kernel_subkey->key_offset +
1423 kernel_subkey->key_size)) {
1424 VBDEBUG(("Unable to unpack kernel subkey\n"));
1425 goto fail;
1426 }
1427 rv = vb2_verify_keyblock(keyblock2, image_size,
1428 &kernel_subkey2, &wb);
1429 }
1430
1431 if (VB2_SUCCESS != rv) {
Furquan Shaikhf2743602015-05-21 14:39:11 -07001432 VBDEBUG(("Verifying key block signature/hash failed.\n"));
1433 goto fail;
1434 }
1435
1436 /* Check the key block flags against the current boot mode. */
1437 if (!(key_block->key_block_flags &
1438 (dev_switch ? KEY_BLOCK_FLAG_DEVELOPER_1 :
1439 KEY_BLOCK_FLAG_DEVELOPER_0))) {
1440 VBDEBUG(("Key block developer flag mismatch.\n"));
1441 if (hash_only == 0)
1442 goto fail;
1443 }
1444
1445 if (!(key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)) {
1446 VBDEBUG(("Key block recovery flag mismatch.\n"));
1447 if (hash_only == 0)
1448 goto fail;
1449 }
1450
1451 /* Get key for preamble/data verification from the key block. */
Randall Spangler13b10972016-10-14 11:04:27 -07001452 struct vb2_public_key data_key2;
1453 if (VB2_SUCCESS !=
1454 vb2_unpack_key(&data_key2,
1455 (const uint8_t *)&keyblock2->data_key,
1456 keyblock2->data_key.key_offset +
1457 keyblock2->data_key.key_size)) {
1458 VBDEBUG(("Unable to unpack kernel data key\n"));
Furquan Shaikhf2743602015-05-21 14:39:11 -07001459 goto fail;
1460 }
1461
1462 /* Verify the preamble, which follows the key block */
Furquan Shaikh04e23382015-05-29 18:00:46 -07001463 preamble = (VbKernelPreambleHeader *)(kbuf + key_block->key_block_size);
Randall Spangler13b10972016-10-14 11:04:27 -07001464 struct vb2_kernel_preamble *preamble2 =
1465 (struct vb2_kernel_preamble *)
1466 (kbuf + key_block->key_block_size);
1467
1468 if (VB2_SUCCESS != vb2_verify_kernel_preamble(
1469 preamble2,
1470 image_size - key_block->key_block_size,
1471 &data_key2,
1472 &wb)) {
Furquan Shaikhf2743602015-05-21 14:39:11 -07001473 VBDEBUG(("Preamble verification failed.\n"));
1474 goto fail;
1475 }
1476
1477 VBDEBUG(("Kernel preamble is good.\n"));
1478
1479 /* Verify kernel data */
Furquan Shaikh04e23382015-05-29 18:00:46 -07001480 body_offset = key_block->key_block_size + preamble->preamble_size;
Randall Spangler13b10972016-10-14 11:04:27 -07001481 if (VB2_SUCCESS != vb2_verify_data(
1482 (const uint8_t *)(kbuf + body_offset),
1483 image_size - body_offset,
1484 (struct vb2_signature *)&preamble->body_signature,
1485 &data_key2, &wb)) {
Furquan Shaikhf2743602015-05-21 14:39:11 -07001486 VBDEBUG(("Kernel data verification failed.\n"));
1487 goto fail;
1488 }
1489
1490 VBDEBUG(("Kernel is good.\n"));
1491
1492 /* Fill in output parameters. */
1493 kparams->kernel_buffer = kbuf + body_offset;
1494 kparams->kernel_buffer_size = image_size - body_offset;
1495 kparams->bootloader_address = preamble->bootloader_address;
1496 kparams->bootloader_size = preamble->bootloader_size;
1497 if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS)
1498 kparams->flags = preamble->flags;
1499
1500 retval = VBERROR_SUCCESS;
1501
1502fail:
1503 VbApiKernelFree(cparams);
Furquan Shaikhf2743602015-05-21 14:39:11 -07001504 if (NULL != kernel_subkey)
Randall Spangler559a1102016-10-18 14:41:22 -07001505 free(kernel_subkey);
Randall Spangler13b10972016-10-14 11:04:27 -07001506 if (NULL != workbuf)
Randall Spangler559a1102016-10-18 14:41:22 -07001507 free(workbuf);
Furquan Shaikhf2743602015-05-21 14:39:11 -07001508 return retval;
1509}
Furquan Shaikh773b5ac2015-05-25 21:49:11 -07001510
1511VbError_t VbUnlockDevice(void)
1512{
1513 VBDEBUG(("%s() Enabling dev-mode...\n", __func__));
1514 if (TPM_SUCCESS != SetVirtualDevMode(1))
1515 return VBERROR_TPM_SET_BOOT_MODE_STATE;
1516
1517 VBDEBUG(("%s() Mode change will take effect on next reboot.\n",
1518 __func__));
1519 return VBERROR_SUCCESS;
1520}
1521
1522VbError_t VbLockDevice(void)
1523{
1524 VbExNvStorageRead(vnc.raw);
1525 VbNvSetup(&vnc);
1526
1527 VBDEBUG(("%s() - Storing request to leave dev-mode.\n",
1528 __func__));
1529 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST,
1530 1);
1531
Daisuke Nojiri3a631482015-10-20 18:31:10 -07001532 VbNvCommit();
Furquan Shaikh773b5ac2015-05-25 21:49:11 -07001533
1534 VBDEBUG(("%s() Mode change will take effect on next reboot.\n",
1535 __func__));
1536
1537 return VBERROR_SUCCESS;
1538}