blob: 08da08cb942d0f4d9e2b8ae1fcd57eede178ea97 [file] [log] [blame]
Shelley Chen8c4b8282017-07-31 14:28:42 -07001/* Copyright 2017 The Chromium OS Authors. All rights reserved.
Shelley Chen71c6c032016-12-22 09:55:47 -08002 * 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 - user interface for RW firmware
6 */
7
Shelley Chen71c6c032016-12-22 09:55:47 -08008#include "2common.h"
9#include "2misc.h"
10#include "2nvstorage.h"
11#include "2rsa.h"
Joel Kitching479f2d62019-08-30 14:31:46 +080012#include "2secdata.h"
Joel Kitching9adf2aa2019-08-20 17:43:50 +080013#include "2sysincludes.h"
Shelley Chen71c6c032016-12-22 09:55:47 -080014#include "load_kernel_fw.h"
Joel Kitching110df5c2019-08-29 13:27:23 +080015#include "secdata_tpm.h"
Shelley Chen71c6c032016-12-22 09:55:47 -080016#include "utility.h"
17#include "vb2_common.h"
18#include "vboot_api.h"
19#include "vboot_audio.h"
20#include "vboot_common.h"
21#include "vboot_display.h"
22#include "vboot_kernel.h"
Simon Glass8ed28872018-10-31 09:53:05 -060023#include "vboot_ui_common.h"
Shelley Chen2d926202017-12-14 15:50:26 -080024#include "vboot_ui_menu_private.h"
Shelley Chen71c6c032016-12-22 09:55:47 -080025
Julius Wernerc76e7362018-01-25 17:41:09 -080026static const char dev_disable_msg[] =
27 "Developer mode is disabled on this device by system policy.\n"
28 "For more information, see http://dev.chromium.org/chromium-os/fwmp\n"
29 "\n";
30
31static VB_MENU current_menu, prev_menu;
Julius Werner70ba5af2019-04-01 15:04:21 -070032static int current_menu_idx, disabled_idx_mask, usb_nogood, force_redraw;
Julius Wernerc76e7362018-01-25 17:41:09 -080033static uint32_t default_boot;
34static uint32_t disable_dev_boot;
Simon Glassebd087a2018-10-16 03:42:56 -060035static uint32_t altfw_allowed;
Julius Wernerc76e7362018-01-25 17:41:09 -080036static struct vb2_menu menus[];
Simon Glassa0ae3182018-10-16 19:36:48 -060037static const char no_legacy[] = "Legacy boot failed. Missing BIOS?\n";
Shelley Chen71c6c032016-12-22 09:55:47 -080038
39/**
40 * Checks GBB flags against VbExIsShutdownRequested() shutdown request to
41 * determine if a shutdown is required.
42 *
43 * Returns true if a shutdown is required and false if no shutdown is required.
44 */
Randall Spangler51421322017-12-14 15:43:17 -080045static int VbWantShutdownMenu(struct vb2_context *ctx)
Shelley Chen71c6c032016-12-22 09:55:47 -080046{
Joel Kitchingde2cae62019-05-21 12:20:38 +080047 struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
Shelley Chen71c6c032016-12-22 09:55:47 -080048 uint32_t shutdown_request = VbExIsShutdownRequested();
49
50 /* If desired, ignore shutdown request due to lid closure. */
Joel Kitchingde2cae62019-05-21 12:20:38 +080051 if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN)
Shelley Chen71c6c032016-12-22 09:55:47 -080052 shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED;
53
Shelley Chen53f82022017-01-11 13:08:51 -080054 /*
55 * In detachables, disabling shutdown due to power button.
56 * We are using it for selection instead.
57 */
58 shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON;
59
Shelley Chen71c6c032016-12-22 09:55:47 -080060 return !!shutdown_request;
61}
62
Julius Wernerc76e7362018-01-25 17:41:09 -080063/* (Re-)Draw the menu identified by current_menu[_idx] to the screen. */
Joel Kitching90671fa2019-07-31 13:17:08 +080064static vb2_error_t vb2_draw_current_screen(struct vb2_context *ctx) {
65 vb2_error_t ret = VbDisplayMenu(ctx, menus[current_menu].screen,
Julius Werner70ba5af2019-04-01 15:04:21 -070066 force_redraw, current_menu_idx, disabled_idx_mask);
67 force_redraw = 0;
68 return ret;
Julius Wernerc76e7362018-01-25 17:41:09 -080069}
Shelley Chen71c6c032016-12-22 09:55:47 -080070
Julius Wernerc76e7362018-01-25 17:41:09 -080071/* Flash the screen to black to catch user awareness, then redraw menu. */
72static void vb2_flash_screen(struct vb2_context *ctx)
73{
Mathew King9d6dc0d2019-02-11 10:27:59 -070074 VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
Julius Wernerc76e7362018-01-25 17:41:09 -080075 VbExSleepMs(50);
76 vb2_draw_current_screen(ctx);
77}
78
Julius Werner99a0f5b2019-01-24 16:35:37 -080079static void vb2_log_menu_change(void)
80{
81 if (menus[current_menu].size)
82 VB2_DEBUG("================ %s Menu ================ [ %s ]\n",
83 menus[current_menu].name,
84 menus[current_menu].items[current_menu_idx].text);
85 else
86 VB2_DEBUG("=============== %s Screen ===============\n",
87 menus[current_menu].name);
88}
89
Shelley Chen84961572017-01-27 15:21:42 -080090/**
Julius Werner6ab5fce2018-01-24 19:47:33 -080091 * Switch to a new menu (but don't draw it yet).
Shelley Chen84961572017-01-27 15:21:42 -080092 *
93 * @param new_current_menu: new menu to set current_menu to
94 * @param new_current_menu_idx: new idx to set current_menu_idx to
Shelley Chen84961572017-01-27 15:21:42 -080095 */
Julius Werner6ab5fce2018-01-24 19:47:33 -080096static void vb2_change_menu(VB_MENU new_current_menu,
97 int new_current_menu_idx)
Shelley Chen0d828532017-01-10 15:22:15 -080098{
99 prev_menu = current_menu;
100 current_menu = new_current_menu;
Julius Werner6ab5fce2018-01-24 19:47:33 -0800101
Julius Werner6ab5fce2018-01-24 19:47:33 -0800102 /* Reconfigure disabled_idx_mask for the new menu */
103 disabled_idx_mask = 0;
104 /* Disable Network Boot Option */
105 if (current_menu == VB_MENU_DEV)
106 disabled_idx_mask |= 1 << VB_DEV_NETWORK;
107 /* Disable cancel option if enterprise disabled dev mode */
108 if (current_menu == VB_MENU_TO_NORM &&
109 disable_dev_boot == 1)
110 disabled_idx_mask |= 1 << VB_TO_NORM_CANCEL;
Simon Glassa0ae3182018-10-16 19:36:48 -0600111
112 /* Enable menu items for the selected bootloaders */
113 if (current_menu == VB_MENU_ALT_FW) {
114 disabled_idx_mask = ~(VbExGetAltFwIdxMask() >> 1);
115
116 /* Make sure 'cancel' is shown even with an invalid mask */
117 disabled_idx_mask &= (1 << VB_ALTFW_COUNT) - 1;
118 }
119 /* We assume that there is at least one enabled item */
120 while ((1 << new_current_menu_idx) & disabled_idx_mask)
121 new_current_menu_idx++;
122 if (new_current_menu_idx < menus[current_menu].size)
123 current_menu_idx = new_current_menu_idx;
Julius Werner99a0f5b2019-01-24 16:35:37 -0800124
125 vb2_log_menu_change();
Shelley Chen0d828532017-01-10 15:22:15 -0800126}
127
Julius Wernerc76e7362018-01-25 17:41:09 -0800128/************************
129 * Menu Actions *
130 ************************/
131
132/* Boot from internal disk if allowed. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800133static vb2_error_t boot_disk_action(struct vb2_context *ctx)
Shelley Chene6e177d2017-11-14 12:35:55 -0800134{
Julius Wernerc76e7362018-01-25 17:41:09 -0800135 if (disable_dev_boot) {
136 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700137 vb2_error_notify("Developer mode disabled\n", NULL,
138 VB_BEEP_NOT_ALLOWED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800139 return VBERROR_KEEP_LOOPING;
140 }
141 VB2_DEBUG("trying fixed disk\n");
142 return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED);
143}
144
145/* Boot legacy BIOS if allowed and available. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800146static vb2_error_t boot_legacy_action(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800147{
Julius Wernerc76e7362018-01-25 17:41:09 -0800148 if (disable_dev_boot) {
149 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700150 vb2_error_notify("Developer mode disabled\n", NULL,
151 VB_BEEP_NOT_ALLOWED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800152 return VBERROR_KEEP_LOOPING;
153 }
154
Simon Glassebd087a2018-10-16 03:42:56 -0600155 if (!altfw_allowed) {
Julius Wernerc76e7362018-01-25 17:41:09 -0800156 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700157 vb2_error_notify("WARNING: Booting legacy BIOS has not "
158 "been enabled. Refer to the developer"
159 "-mode documentation for details.\n",
160 "Legacy boot is disabled\n",
161 VB_BEEP_NOT_ALLOWED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800162 return VBERROR_KEEP_LOOPING;
163 }
164
Joel Kitching7d64b932019-08-30 14:58:27 +0800165 vb2_try_altfw(ctx, 1, VB_ALTFW_DEFAULT);
Julius Wernerc76e7362018-01-25 17:41:09 -0800166 vb2_flash_screen(ctx);
Julius Wernerc76e7362018-01-25 17:41:09 -0800167 return VBERROR_KEEP_LOOPING;
168}
169
170/* Boot from USB or SD card if allowed and available. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800171static vb2_error_t boot_usb_action(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800172{
173 const char no_kernel[] = "No bootable kernel found on USB/SD.\n";
174
175 if (disable_dev_boot) {
176 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700177 vb2_error_notify("Developer mode disabled\n", NULL,
178 VB_BEEP_NOT_ALLOWED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800179 return VBERROR_KEEP_LOOPING;
180 }
181
182 if (!vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB) &&
Joel Kitchingde2cae62019-05-21 12:20:38 +0800183 !(vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) &&
Joel Kitchingadb41832019-09-23 22:53:49 +0800184 !vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_USB)) {
Julius Wernerc76e7362018-01-25 17:41:09 -0800185 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700186 vb2_error_notify("WARNING: Booting from external media "
187 "(USB/SD) has not been enabled. Refer "
188 "to the developer-mode documentation "
189 "for details.\n",
190 "USB booting is disabled\n",
191 VB_BEEP_NOT_ALLOWED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800192 return VBERROR_KEEP_LOOPING;
193 }
194
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800195 if (VB2_SUCCESS == VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE)) {
Julius Wernerc76e7362018-01-25 17:41:09 -0800196 VB2_DEBUG("booting USB\n");
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800197 return VB2_SUCCESS;
Julius Wernerc76e7362018-01-25 17:41:09 -0800198 }
199
Julius Wernerc76e7362018-01-25 17:41:09 -0800200 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700201 vb2_error_notify(no_kernel, NULL, VB_BEEP_FAILED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800202 return VBERROR_KEEP_LOOPING;
203}
204
Joel Kitching90671fa2019-07-31 13:17:08 +0800205static vb2_error_t enter_developer_menu(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800206{
207 int menu_idx;
208 switch(default_boot) {
Martin Rothb5c00db2018-02-01 09:37:01 -0700209 default:
Julius Wernerc76e7362018-01-25 17:41:09 -0800210 case VB2_DEV_DEFAULT_BOOT_DISK:
211 menu_idx = VB_DEV_DISK;
212 break;
213 case VB2_DEV_DEFAULT_BOOT_USB:
214 menu_idx = VB_DEV_USB;
215 break;
216 case VB2_DEV_DEFAULT_BOOT_LEGACY:
217 menu_idx = VB_DEV_LEGACY;
218 break;
219 }
220 vb2_change_menu(VB_MENU_DEV, menu_idx);
221 vb2_draw_current_screen(ctx);
222 return VBERROR_KEEP_LOOPING;
223}
224
Joel Kitching90671fa2019-07-31 13:17:08 +0800225static vb2_error_t enter_dev_warning_menu(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800226{
227 vb2_change_menu(VB_MENU_DEV_WARNING, VB_WARN_POWER_OFF);
228 vb2_draw_current_screen(ctx);
229 return VBERROR_KEEP_LOOPING;
230}
231
Joel Kitching90671fa2019-07-31 13:17:08 +0800232static vb2_error_t enter_language_menu(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800233{
234 vb2_change_menu(VB_MENU_LANGUAGES,
235 vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX));
236 vb2_draw_current_screen(ctx);
237 return VBERROR_KEEP_LOOPING;
238}
239
Joel Kitching90671fa2019-07-31 13:17:08 +0800240static vb2_error_t enter_recovery_base_screen(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800241{
Julius Werner3f896a52018-03-22 14:38:11 -0700242 if (!vb2_allow_recovery(ctx))
Julius Werner45b04f62018-01-29 15:55:51 -0800243 vb2_change_menu(VB_MENU_RECOVERY_BROKEN, 0);
244 else if (usb_nogood)
Julius Werner6ab5fce2018-01-24 19:47:33 -0800245 vb2_change_menu(VB_MENU_RECOVERY_NO_GOOD, 0);
Shelley Chene6e177d2017-11-14 12:35:55 -0800246 else
Julius Werner6ab5fce2018-01-24 19:47:33 -0800247 vb2_change_menu(VB_MENU_RECOVERY_INSERT, 0);
Julius Wernerc76e7362018-01-25 17:41:09 -0800248 vb2_draw_current_screen(ctx);
249 return VBERROR_KEEP_LOOPING;
Shelley Chene6e177d2017-11-14 12:35:55 -0800250}
251
Joel Kitching90671fa2019-07-31 13:17:08 +0800252static vb2_error_t enter_options_menu(struct vb2_context *ctx)
Shelley Chen71c6c032016-12-22 09:55:47 -0800253{
Julius Wernerc76e7362018-01-25 17:41:09 -0800254 vb2_change_menu(VB_MENU_OPTIONS, VB_OPTIONS_CANCEL);
255 vb2_draw_current_screen(ctx);
256 return VBERROR_KEEP_LOOPING;
Shelley Chen71c6c032016-12-22 09:55:47 -0800257}
258
Joel Kitching90671fa2019-07-31 13:17:08 +0800259static vb2_error_t enter_to_dev_menu(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800260{
261 const char dev_already_on[] =
262 "WARNING: TODEV rejected, developer mode is already on.\n";
263 if (vb2_get_sd(ctx)->vbsd->flags & VBSD_BOOT_DEV_SWITCH_ON) {
264 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700265 vb2_error_notify(dev_already_on, NULL, VB_BEEP_NOT_ALLOWED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800266 return VBERROR_KEEP_LOOPING;
Shelley Chen46802fd2017-04-12 15:53:49 -0700267 }
Julius Wernerc76e7362018-01-25 17:41:09 -0800268 vb2_change_menu(VB_MENU_TO_DEV, VB_TO_DEV_CANCEL);
269 vb2_draw_current_screen(ctx);
270 return VBERROR_KEEP_LOOPING;
271}
272
Joel Kitching90671fa2019-07-31 13:17:08 +0800273static vb2_error_t enter_to_norm_menu(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800274{
275 vb2_change_menu(VB_MENU_TO_NORM, VB_TO_NORM_CONFIRM);
276 vb2_draw_current_screen(ctx);
277 return VBERROR_KEEP_LOOPING;
278}
279
Simon Glassa0ae3182018-10-16 19:36:48 -0600280/* Boot alternative bootloader if allowed and available. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800281static vb2_error_t enter_altfw_menu(struct vb2_context *ctx)
Simon Glassa0ae3182018-10-16 19:36:48 -0600282{
283 VB2_DEBUG("enter_altfw_menu()\n");
284 if (disable_dev_boot) {
285 vb2_flash_screen(ctx);
286 vb2_error_beep(VB_BEEP_NOT_ALLOWED);
287 return VBERROR_KEEP_LOOPING;
288 }
289 if (!altfw_allowed) {
290 vb2_flash_screen(ctx);
291 vb2_error_no_altfw();
292 return VBERROR_KEEP_LOOPING;
293 }
294 vb2_change_menu(VB_MENU_ALT_FW, 0);
295 vb2_draw_current_screen(ctx);
296
297 return VBERROR_KEEP_LOOPING;
298}
299
Joel Kitching90671fa2019-07-31 13:17:08 +0800300static vb2_error_t debug_info_action(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800301{
Julius Werner70ba5af2019-04-01 15:04:21 -0700302 force_redraw = 1;
Julius Wernerc76e7362018-01-25 17:41:09 -0800303 VbDisplayDebugInfo(ctx);
304 return VBERROR_KEEP_LOOPING;
305}
306
307/* Action when selecting a language entry in the language menu. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800308static vb2_error_t language_action(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800309{
Julius Werner45b04f62018-01-29 15:55:51 -0800310 /* Write selected language ID back to NVRAM. */
Julius Wernerc76e7362018-01-25 17:41:09 -0800311 vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, current_menu_idx);
312
Julius Werner45b04f62018-01-29 15:55:51 -0800313 /*
Joel Kitchingffa02e82019-10-04 16:18:00 +0800314 * Non-manual recovery mode is meant to be left via three-finger
315 * salute (into manual recovery mode). Need to commit nvdata
Joel Kitchingadb41832019-09-23 22:53:49 +0800316 * changes immediately. Ignore commit errors in recovery mode.
Julius Werner45b04f62018-01-29 15:55:51 -0800317 */
Joel Kitchingffa02e82019-10-04 16:18:00 +0800318 if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) &&
319 !vb2_allow_recovery(ctx))
Joel Kitchingadb41832019-09-23 22:53:49 +0800320 vb2_commit_data(ctx);
Julius Werner45b04f62018-01-29 15:55:51 -0800321
322 /* Return to previous menu. */
Julius Wernerc76e7362018-01-25 17:41:09 -0800323 switch (prev_menu) {
324 case VB_MENU_DEV_WARNING:
325 return enter_dev_warning_menu(ctx);
326 case VB_MENU_DEV:
327 return enter_developer_menu(ctx);
328 case VB_MENU_TO_NORM:
329 return enter_to_norm_menu(ctx);
330 case VB_MENU_TO_DEV:
331 return enter_to_dev_menu(ctx);
332 case VB_MENU_OPTIONS:
333 return enter_options_menu(ctx);
334 default:
335 /* This should never happen. */
336 VB2_DEBUG("ERROR: prev_menu state corrupted, force shutdown\n");
337 return VBERROR_SHUTDOWN_REQUESTED;
338 }
339}
340
Simon Glassa0ae3182018-10-16 19:36:48 -0600341/* Action when selecting a bootloader in the alternative firmware menu. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800342static vb2_error_t altfw_action(struct vb2_context *ctx)
Simon Glassa0ae3182018-10-16 19:36:48 -0600343{
Joel Kitching7d64b932019-08-30 14:58:27 +0800344 vb2_try_altfw(ctx, 1, current_menu_idx + 1);
Simon Glassa0ae3182018-10-16 19:36:48 -0600345 vb2_flash_screen(ctx);
346 VB2_DEBUG(no_legacy);
Julius Werner9e53b922019-03-01 14:23:30 -0800347 VbExDisplayDebugInfo(no_legacy, 0);
Simon Glassa0ae3182018-10-16 19:36:48 -0600348
349 return VBERROR_KEEP_LOOPING;
350}
351
Julius Wernerc76e7362018-01-25 17:41:09 -0800352/* Action that enables developer mode and reboots. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800353static vb2_error_t to_dev_action(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800354{
355 uint32_t vbsd_flags = vb2_get_sd(ctx)->vbsd->flags;
356
357 /* Sanity check, should never happen. */
Joel Kitchinge1761d62019-03-18 16:36:36 +0800358 if ((vbsd_flags & VBSD_BOOT_DEV_SWITCH_ON) ||
Julius Werner3f896a52018-03-22 14:38:11 -0700359 !vb2_allow_recovery(ctx))
Julius Wernerc76e7362018-01-25 17:41:09 -0800360 return VBERROR_KEEP_LOOPING;
361
362 VB2_DEBUG("Enabling dev-mode...\n");
Joel Kitchingadb41832019-09-23 22:53:49 +0800363 if (VB2_SUCCESS != vb2_enable_developer_mode(ctx))
Julius Wernerc76e7362018-01-25 17:41:09 -0800364 return VBERROR_TPM_SET_BOOT_MODE_STATE;
365
366 /* This was meant for headless devices, shouldn't really matter here. */
Matt Delcofa656b62019-02-13 12:31:09 -0800367 if (VbExGetSwitches(VB_SWITCH_FLAG_ALLOW_USB_BOOT))
Julius Wernerc76e7362018-01-25 17:41:09 -0800368 vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1);
369
370 VB2_DEBUG("Reboot so it will take effect\n");
371 return VBERROR_REBOOT_REQUIRED;
372}
373
374/* Action that disables developer mode, shows TO_NORM_CONFIRMED and reboots. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800375static vb2_error_t to_norm_action(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800376{
Joel Kitchingde2cae62019-05-21 12:20:38 +0800377 if (vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
Julius Wernerc76e7362018-01-25 17:41:09 -0800378 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700379 vb2_error_notify("WARNING: TONORM prohibited by "
380 "GBB FORCE_DEV_SWITCH_ON.\n", NULL,
381 VB_BEEP_NOT_ALLOWED);
Julius Wernerc76e7362018-01-25 17:41:09 -0800382 return VBERROR_KEEP_LOOPING;
383 }
384
385 VB2_DEBUG("leaving dev-mode.\n");
386 vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
387 vb2_change_menu(VB_MENU_TO_NORM_CONFIRMED, 0);
388 vb2_draw_current_screen(ctx);
389 VbExSleepMs(5000);
390 return VBERROR_REBOOT_REQUIRED;
391}
392
393/* Action that will power off the system. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800394static vb2_error_t power_off_action(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800395{
Joel Kitching3c477452019-10-04 17:46:29 +0800396 VB2_DEBUG("Power off requested from screen %#x\n",
Julius Wernerc76e7362018-01-25 17:41:09 -0800397 menus[current_menu].screen);
398 return VBERROR_SHUTDOWN_REQUESTED;
399}
400
Simon Glassc61d34f2018-10-15 06:55:06 -0600401/**
402 * Updates current_menu_idx upon an up/down key press, taking into
403 * account disabled indices (from disabled_idx_mask). The cursor
404 * will not wrap, meaning that we block on the 0 or max index when
405 * we hit the ends of the menu.
406 *
407 * @param key VOL_KEY_UP = increase index selection
408 * VOL_KEY_DOWN = decrease index selection.
409 * Every other key has no effect now.
410 */
411static void vb2_update_selection(uint32_t key) {
412 int idx;
413
414 switch (key) {
415 case VB_BUTTON_VOL_UP_SHORT_PRESS:
416 case VB_KEY_UP:
417 idx = current_menu_idx - 1;
418 while (idx >= 0 &&
419 ((1 << idx) & disabled_idx_mask))
420 idx--;
421 /* Only update if idx is valid */
422 if (idx >= 0)
423 current_menu_idx = idx;
424 break;
425 case VB_BUTTON_VOL_DOWN_SHORT_PRESS:
426 case VB_KEY_DOWN:
427 idx = current_menu_idx + 1;
428 while (idx < menus[current_menu].size &&
429 ((1 << idx) & disabled_idx_mask))
430 idx++;
431 /* Only update if idx is valid */
432 if (idx < menus[current_menu].size)
433 current_menu_idx = idx;
434 break;
435 default:
Joel Kitching3c477452019-10-04 17:46:29 +0800436 VB2_DEBUG("ERROR: %s called with key %#x!\n", __func__, key);
Simon Glassc61d34f2018-10-15 06:55:06 -0600437 break;
438 }
Julius Werner99a0f5b2019-01-24 16:35:37 -0800439
440 vb2_log_menu_change();
Simon Glassc61d34f2018-10-15 06:55:06 -0600441}
442
Joel Kitching90671fa2019-07-31 13:17:08 +0800443static vb2_error_t vb2_handle_menu_input(struct vb2_context *ctx,
444 uint32_t key, uint32_t key_flags)
Simon Glassc61d34f2018-10-15 06:55:06 -0600445{
446 switch (key) {
447 case 0:
448 /* nothing pressed */
449 break;
450 case '\t':
451 /* Tab = display debug info */
452 return debug_info_action(ctx);
Julius Werner70ba5af2019-04-01 15:04:21 -0700453 case VB_KEY_ESC:
454 /* Esc = redraw screen (to clear old debug info) */
455 vb2_draw_current_screen(ctx);
456 break;
Simon Glassc61d34f2018-10-15 06:55:06 -0600457 case VB_KEY_UP:
458 case VB_KEY_DOWN:
459 case VB_BUTTON_VOL_UP_SHORT_PRESS:
460 case VB_BUTTON_VOL_DOWN_SHORT_PRESS:
461 /* Untrusted (USB keyboard) input disabled for TO_DEV menu. */
462 if (current_menu == VB_MENU_TO_DEV &&
463 !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) {
464 vb2_flash_screen(ctx);
Nick Crewsf07ea542018-11-09 15:51:17 -0700465 vb2_error_notify("Please use the on-device volume "
466 "buttons to navigate\n",
467 "vb2_handle_menu_input() - Untrusted "
468 "(USB keyboard) input disabled\n",
469 VB_BEEP_NOT_ALLOWED);
Simon Glassc61d34f2018-10-15 06:55:06 -0600470 break;
471 }
472
473 /* Menuless screens enter OPTIONS on volume button press. */
474 if (!menus[current_menu].size) {
475 enter_options_menu(ctx);
476 break;
477 }
478
479 vb2_update_selection(key);
480 vb2_draw_current_screen(ctx);
481 break;
482 case VB_BUTTON_POWER_SHORT_PRESS:
Mathew Kingaf26dc12019-02-19 10:43:32 -0700483 case VB_KEY_ENTER:
Simon Glassc61d34f2018-10-15 06:55:06 -0600484 /* Menuless screens shut down on power button press. */
485 if (!menus[current_menu].size)
486 return VBERROR_SHUTDOWN_REQUESTED;
487
488 return menus[current_menu].items[current_menu_idx].action(ctx);
489 default:
Joel Kitching3c477452019-10-04 17:46:29 +0800490 VB2_DEBUG("pressed key %#x\n", key);
Simon Glassc61d34f2018-10-15 06:55:06 -0600491 break;
492 }
493
494 if (VbWantShutdownMenu(ctx)) {
495 VB2_DEBUG("shutdown requested!\n");
496 return VBERROR_SHUTDOWN_REQUESTED;
497 }
498
499 return VBERROR_KEEP_LOOPING;
500}
501
Julius Wernerc76e7362018-01-25 17:41:09 -0800502/* Master table of all menus. Menus with size == 0 count as menuless screens. */
503static struct vb2_menu menus[VB_MENU_COUNT] = {
504 [VB_MENU_DEV_WARNING] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800505 .name = "Developer Warning",
Julius Wernerc76e7362018-01-25 17:41:09 -0800506 .size = VB_WARN_COUNT,
507 .screen = VB_SCREEN_DEVELOPER_WARNING_MENU,
508 .items = (struct vb2_menu_item[]){
509 [VB_WARN_OPTIONS] = {
510 .text = "Developer Options",
511 .action = enter_developer_menu,
512 },
513 [VB_WARN_DBG_INFO] = {
514 .text = "Show Debug Info",
515 .action = debug_info_action,
516 },
517 [VB_WARN_ENABLE_VER] = {
518 .text = "Enable OS Verification",
519 .action = enter_to_norm_menu,
520 },
521 [VB_WARN_POWER_OFF] = {
522 .text = "Power Off",
523 .action = power_off_action,
524 },
525 [VB_WARN_LANGUAGE] = {
526 .text = "Language",
527 .action = enter_language_menu,
528 },
529 },
530 },
531 [VB_MENU_DEV] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800532 .name = "Developer Boot Options",
Julius Wernerc76e7362018-01-25 17:41:09 -0800533 .size = VB_DEV_COUNT,
534 .screen = VB_SCREEN_DEVELOPER_MENU,
535 .items = (struct vb2_menu_item[]){
536 [VB_DEV_NETWORK] = {
537 .text = "Boot From Network",
538 .action = NULL, /* unimplemented */
539 },
540 [VB_DEV_LEGACY] = {
541 .text = "Boot Legacy BIOS",
Simon Glassa0ae3182018-10-16 19:36:48 -0600542 .action = enter_altfw_menu,
Julius Wernerc76e7362018-01-25 17:41:09 -0800543 },
544 [VB_DEV_USB] = {
545 .text = "Boot From USB or SD Card",
546 .action = boot_usb_action,
547 },
548 [VB_DEV_DISK] = {
549 .text = "Boot From Internal Disk",
550 .action = boot_disk_action,
551 },
552 [VB_DEV_CANCEL] = {
553 .text = "Cancel",
554 .action = enter_dev_warning_menu,
555 },
556 [VB_DEV_POWER_OFF] = {
557 .text = "Power Off",
558 .action = power_off_action,
559 },
560 [VB_DEV_LANGUAGE] = {
561 .text = "Language",
562 .action = enter_language_menu,
563 },
564 },
565 },
566 [VB_MENU_TO_NORM] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800567 .name = "TO_NORM Confirmation",
Julius Wernerc76e7362018-01-25 17:41:09 -0800568 .size = VB_TO_NORM_COUNT,
569 .screen = VB_SCREEN_DEVELOPER_TO_NORM_MENU,
570 .items = (struct vb2_menu_item[]){
571 [VB_TO_NORM_CONFIRM] = {
572 .text = "Confirm Enabling OS Verification",
573 .action = to_norm_action,
574 },
575 [VB_TO_NORM_CANCEL] = {
576 .text = "Cancel",
577 .action = enter_dev_warning_menu,
578 },
579 [VB_TO_NORM_POWER_OFF] = {
580 .text = "Power Off",
581 .action = power_off_action,
582 },
583 [VB_TO_NORM_LANGUAGE] = {
584 .text = "Language",
585 .action = enter_language_menu,
586 },
587 },
588 },
589 [VB_MENU_TO_DEV] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800590 .name = "TO_DEV Confirmation",
Julius Wernerc76e7362018-01-25 17:41:09 -0800591 .size = VB_TO_DEV_COUNT,
592 .screen = VB_SCREEN_RECOVERY_TO_DEV_MENU,
593 .items = (struct vb2_menu_item[]){
594 [VB_TO_DEV_CONFIRM] = {
595 .text = "Confirm Disabling OS Verification",
596 .action = to_dev_action,
597 },
598 [VB_TO_DEV_CANCEL] = {
599 .text = "Cancel",
600 .action = enter_recovery_base_screen,
601 },
602 [VB_TO_DEV_POWER_OFF] = {
603 .text = "Power Off",
604 .action = power_off_action,
605 },
606 [VB_TO_DEV_LANGUAGE] = {
607 .text = "Language",
608 .action = enter_language_menu,
609 },
610 },
611 },
612 [VB_MENU_LANGUAGES] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800613 .name = "Language Selection",
Julius Wernerc76e7362018-01-25 17:41:09 -0800614 .screen = VB_SCREEN_LANGUAGES_MENU,
615 /* Rest is filled out dynamically by vb2_init_menus() */
616 },
617 [VB_MENU_OPTIONS] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800618 .name = "Options",
Julius Wernerc76e7362018-01-25 17:41:09 -0800619 .size = VB_OPTIONS_COUNT,
620 .screen = VB_SCREEN_OPTIONS_MENU,
621 .items = (struct vb2_menu_item[]){
622 [VB_OPTIONS_DBG_INFO] = {
623 .text = "Show Debug Info",
624 .action = debug_info_action,
625 },
626 [VB_OPTIONS_CANCEL] = {
627 .text = "Cancel",
628 .action = enter_recovery_base_screen,
629 },
630 [VB_OPTIONS_POWER_OFF] = {
631 .text = "Power Off",
632 .action = power_off_action,
633 },
634 [VB_OPTIONS_LANGUAGE] = {
635 .text = "Language",
636 .action = enter_language_menu,
637 },
638 },
639 },
640 [VB_MENU_RECOVERY_INSERT] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800641 .name = "Recovery INSERT",
Julius Wernerc76e7362018-01-25 17:41:09 -0800642 .size = 0,
643 .screen = VB_SCREEN_RECOVERY_INSERT,
644 .items = NULL,
645 },
646 [VB_MENU_RECOVERY_NO_GOOD] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800647 .name = "Recovery NO_GOOD",
Julius Wernerc76e7362018-01-25 17:41:09 -0800648 .size = 0,
649 .screen = VB_SCREEN_RECOVERY_NO_GOOD,
650 .items = NULL,
651 },
652 [VB_MENU_RECOVERY_BROKEN] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800653 .name = "Non-manual Recovery (BROKEN)",
Julius Wernerc76e7362018-01-25 17:41:09 -0800654 .size = 0,
655 .screen = VB_SCREEN_OS_BROKEN,
656 .items = NULL,
657 },
658 [VB_MENU_TO_NORM_CONFIRMED] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800659 .name = "TO_NORM Interstitial",
Julius Wernerc76e7362018-01-25 17:41:09 -0800660 .size = 0,
661 .screen = VB_SCREEN_TO_NORM_CONFIRMED,
662 .items = NULL,
663 },
Simon Glassa0ae3182018-10-16 19:36:48 -0600664 [VB_MENU_ALT_FW] = {
Julius Werner99a0f5b2019-01-24 16:35:37 -0800665 .name = "Alternative Firmware Selection",
Simon Glassa0ae3182018-10-16 19:36:48 -0600666 .screen = VB_SCREEN_ALT_FW_MENU,
667 .size = VB_ALTFW_COUNT + 1,
668 .items = (struct vb2_menu_item[]) {{
669 .text = "Bootloader 1",
670 .action = altfw_action,
671 }, {
672 .text = "Bootloader 2",
673 .action = altfw_action,
674 }, {
675 .text = "Bootloader 3",
676 .action = altfw_action,
677 }, {
678 .text = "Bootloader 4",
679 .action = altfw_action,
680 }, {
681 .text = "Bootloader 5",
682 .action = altfw_action,
683 }, {
684 .text = "Bootloader 6",
685 .action = altfw_action,
686 }, {
687 .text = "Bootloader 7",
688 .action = altfw_action,
689 }, {
690 .text = "Bootloader 8",
691 .action = altfw_action,
692 }, {
693 .text = "Bootloader 9",
694 .action = altfw_action,
695 }, {
696 .text = "Cancel",
697 .action = enter_developer_menu,
698 },
699 },
700 },
Julius Wernerc76e7362018-01-25 17:41:09 -0800701};
702
703/* Initialize menu state. Must be called once before displaying any menus. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800704static vb2_error_t vb2_init_menus(struct vb2_context *ctx)
Julius Wernerc76e7362018-01-25 17:41:09 -0800705{
706 struct vb2_menu_item *items;
707 uint32_t count;
708 int i;
709
710 /* Initialize language menu with the correct amount of entries. */
Joel Kitching7ceb2ae2019-08-01 12:45:47 +0800711 if (VB2_SUCCESS != VbExGetLocalizationCount(&count) || count == 0)
712 count = 1; /* Fall back to 1 language entry on failure */
Julius Wernerc76e7362018-01-25 17:41:09 -0800713
714 items = malloc(count * sizeof(struct vb2_menu_item));
715 if (!items)
Joel Kitching9908a9a2019-07-29 18:53:38 +0800716 return VB2_ERROR_UNKNOWN;
Julius Wernerc76e7362018-01-25 17:41:09 -0800717
718 for (i = 0; i < count; i++) {
Simon Glassa0ae3182018-10-16 19:36:48 -0600719 /* The actual language is drawn by the bootloader */
Julius Wernerc76e7362018-01-25 17:41:09 -0800720 items[i].text = "Some Language";
721 items[i].action = language_action;
722 }
723 menus[VB_MENU_LANGUAGES].size = count;
724 menus[VB_MENU_LANGUAGES].items = items;
725
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800726 return VB2_SUCCESS;
Shelley Chen46802fd2017-04-12 15:53:49 -0700727}
728
729/**
Shelley Chen84961572017-01-27 15:21:42 -0800730 * Main function that handles developer warning menu functionality
731 *
732 * @param ctx Vboot2 context
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800733 * @return VB2_SUCCESS, or non-zero error code if error.
Shelley Chen84961572017-01-27 15:21:42 -0800734 */
Joel Kitching90671fa2019-07-31 13:17:08 +0800735static vb2_error_t vb2_developer_menu(struct vb2_context *ctx)
Shelley Chen71c6c032016-12-22 09:55:47 -0800736{
Joel Kitchingde2cae62019-05-21 12:20:38 +0800737 struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
Joel Kitching90671fa2019-07-31 13:17:08 +0800738 vb2_error_t ret;
Shelley Chen78500342017-11-06 15:59:50 -0800739
Shelley Chen71c6c032016-12-22 09:55:47 -0800740 /* Check if the default is to boot using disk, usb, or legacy */
Shelley Chen0d828532017-01-10 15:22:15 -0800741 default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT);
Joel Kitchingde2cae62019-05-21 12:20:38 +0800742 if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY)
Julius Wernerc76e7362018-01-25 17:41:09 -0800743 default_boot = VB2_DEV_DEFAULT_BOOT_LEGACY;
Shelley Chen71c6c032016-12-22 09:55:47 -0800744
Julius Wernerc76e7362018-01-25 17:41:09 -0800745 /* Check if developer mode is disabled by FWMP */
746 disable_dev_boot = 0;
Joel Kitchingadb41832019-09-23 22:53:49 +0800747 if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) {
Joel Kitchingde2cae62019-05-21 12:20:38 +0800748 if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
Shelley Chene6198e72017-02-14 14:35:01 -0800749 VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by"
750 "FORCE_DEV_SWITCH_ON\n");
Shelley Chen71c6c032016-12-22 09:55:47 -0800751 } else {
Shelley Chene6e177d2017-11-14 12:35:55 -0800752 /* If dev mode is disabled, only allow TONORM */
Shelley Chen71c6c032016-12-22 09:55:47 -0800753 disable_dev_boot = 1;
Shelley Chen78500342017-11-06 15:59:50 -0800754 VB2_DEBUG("dev_disable_boot is set.\n");
Shelley Chen71c6c032016-12-22 09:55:47 -0800755 }
756 }
Joel Kitchingadb41832019-09-23 22:53:49 +0800757
Simon Glassebd087a2018-10-16 03:42:56 -0600758 altfw_allowed = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY) ||
Joel Kitchingde2cae62019-05-21 12:20:38 +0800759 (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) ||
Joel Kitchingadb41832019-09-23 22:53:49 +0800760 vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY);
Shelley Chen71c6c032016-12-22 09:55:47 -0800761
Julius Wernerc76e7362018-01-25 17:41:09 -0800762 /* Show appropriate initial menu */
763 if (disable_dev_boot)
764 enter_to_norm_menu(ctx);
765 else
766 enter_dev_warning_menu(ctx);
Shelley Chen71c6c032016-12-22 09:55:47 -0800767
768 /* Get audio/delay context */
Randall Spanglerde818cc2017-12-12 14:05:19 -0800769 vb2_audio_start(ctx);
Shelley Chen71c6c032016-12-22 09:55:47 -0800770
771 /* We'll loop until we finish the delay or are interrupted */
772 do {
Julius Wernerc034c452018-01-29 15:05:12 -0800773 uint32_t key = VbExKeyboardRead();
Shelley Chen71c6c032016-12-22 09:55:47 -0800774
Shelley Chen78500342017-11-06 15:59:50 -0800775 /* Make sure user knows dev mode disabled */
776 if (disable_dev_boot)
Julius Werner9e53b922019-03-01 14:23:30 -0800777 VbExDisplayDebugInfo(dev_disable_msg, 0);
Shelley Chen78500342017-11-06 15:59:50 -0800778
Shelley Chen71c6c032016-12-22 09:55:47 -0800779 switch (key) {
Furquan Shaikhdb794182017-11-07 12:49:17 -0800780 case VB_BUTTON_VOL_DOWN_LONG_PRESS:
Mathew Kingaf26dc12019-02-19 10:43:32 -0700781 case VB_KEY_CTRL('D'):
Julius Wernerc76e7362018-01-25 17:41:09 -0800782 /* Ctrl+D = boot from internal disk */
783 ret = boot_disk_action(ctx);
Shelley Chen19a41182017-02-14 14:50:54 -0800784 break;
Mathew Kingaf26dc12019-02-19 10:43:32 -0700785 case VB_KEY_CTRL('L'):
Simon Glassa0ae3182018-10-16 19:36:48 -0600786 /* Ctrl+L = boot alternative bootloader */
787 ret = enter_altfw_menu(ctx);
Shelley Chen19a41182017-02-14 14:50:54 -0800788 break;
Furquan Shaikhdb794182017-11-07 12:49:17 -0800789 case VB_BUTTON_VOL_UP_LONG_PRESS:
Mathew Kingaf26dc12019-02-19 10:43:32 -0700790 case VB_KEY_CTRL('U'):
Julius Wernerc76e7362018-01-25 17:41:09 -0800791 /* Ctrl+U = boot from USB or SD card */
792 ret = boot_usb_action(ctx);
Shelley Chen71c6c032016-12-22 09:55:47 -0800793 break;
Simon Glassa0ae3182018-10-16 19:36:48 -0600794 /* We allow selection of the default '0' bootloader here */
795 case '0'...'9':
796 VB2_DEBUG("VbBootDeveloper() - "
797 "user pressed key '%c': Boot alternative "
798 "firmware\n", key);
Joel Kitching7d64b932019-08-30 14:58:27 +0800799 vb2_try_altfw(ctx, altfw_allowed, key - '0');
Mathew Kingb720a102019-04-04 13:53:54 -0600800 ret = VBERROR_KEEP_LOOPING;
Simon Glassa0ae3182018-10-16 19:36:48 -0600801 break;
Shelley Chen71c6c032016-12-22 09:55:47 -0800802 default:
Julius Wernerc034c452018-01-29 15:05:12 -0800803 ret = vb2_handle_menu_input(ctx, key, 0);
Shelley Chen71c6c032016-12-22 09:55:47 -0800804 break;
805 }
Randall Spanglerde818cc2017-12-12 14:05:19 -0800806
Julius Wernerc034c452018-01-29 15:05:12 -0800807 /* We may have loaded a kernel or decided to shut down now. */
808 if (ret != VBERROR_KEEP_LOOPING)
809 return ret;
810
Julius Wernerc76e7362018-01-25 17:41:09 -0800811 /* Reset 30 second timer whenever we see a new key. */
812 if (key != 0)
813 vb2_audio_start(ctx);
814
Julius Werner5caaa392019-10-11 15:22:34 -0700815 VbExSleepMs(KEY_DELAY_MS);
Raul E Rangel90ee96f2018-08-20 14:28:55 -0600816
Randall Spanglerde818cc2017-12-12 14:05:19 -0800817 /* If dev mode was disabled, loop forever (never timeout) */
Simon Glassa0ae3182018-10-16 19:36:48 -0600818 } while (disable_dev_boot ? 1 : vb2_audio_looping());
Shelley Chen71c6c032016-12-22 09:55:47 -0800819
Julius Wernerc76e7362018-01-25 17:41:09 -0800820 if (default_boot == VB2_DEV_DEFAULT_BOOT_LEGACY)
821 boot_legacy_action(ctx); /* Doesn't return on success. */
Shelley Chen71c6c032016-12-22 09:55:47 -0800822
Julius Wernerc76e7362018-01-25 17:41:09 -0800823 if (default_boot == VB2_DEV_DEFAULT_BOOT_USB)
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800824 if (VB2_SUCCESS == boot_usb_action(ctx))
825 return VB2_SUCCESS;
Shelley Chen71c6c032016-12-22 09:55:47 -0800826
Julius Wernerc76e7362018-01-25 17:41:09 -0800827 return boot_disk_action(ctx);
Shelley Chen71c6c032016-12-22 09:55:47 -0800828}
829
Julius Wernerc76e7362018-01-25 17:41:09 -0800830/* Developer mode entry point. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800831vb2_error_t VbBootDeveloperMenu(struct vb2_context *ctx)
Shelley Chen71c6c032016-12-22 09:55:47 -0800832{
Joel Kitching90671fa2019-07-31 13:17:08 +0800833 vb2_error_t retval = vb2_init_menus(ctx);
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800834 if (VB2_SUCCESS != retval)
Julius Wernerc76e7362018-01-25 17:41:09 -0800835 return retval;
836 retval = vb2_developer_menu(ctx);
Mathew King9d6dc0d2019-02-11 10:27:59 -0700837 VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
Shelley Chen71c6c032016-12-22 09:55:47 -0800838 return retval;
839}
840
Julius Werner45b04f62018-01-29 15:55:51 -0800841/* Main function that handles non-manual recovery (BROKEN) menu functionality */
Joel Kitching90671fa2019-07-31 13:17:08 +0800842static vb2_error_t broken_ui(struct vb2_context *ctx)
Julius Werner45b04f62018-01-29 15:55:51 -0800843{
844 VbSharedDataHeader *vbsd = vb2_get_sd(ctx)->vbsd;
845
846 /*
847 * Temporarily stash recovery reason in subcode so we'll still know what
848 * to display if the user reboots into manual recovery from here. Commit
849 * immediately since the user may hard-reset out of here.
850 */
851 VB2_DEBUG("saving recovery reason (%#x)\n", vbsd->recovery_reason);
852 vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, vbsd->recovery_reason);
Joel Kitchingadb41832019-09-23 22:53:49 +0800853
854 /* Ignore commit errors in recovery mode. */
855 vb2_commit_data(ctx);
Julius Werner45b04f62018-01-29 15:55:51 -0800856
857 enter_recovery_base_screen(ctx);
858
859 /* Loop and wait for the user to reset or shut down. */
860 VB2_DEBUG("waiting for manual recovery\n");
861 while (1) {
862 uint32_t key = VbExKeyboardRead();
Joel Kitching90671fa2019-07-31 13:17:08 +0800863 vb2_error_t ret = vb2_handle_menu_input(ctx, key, 0);
Julius Werner45b04f62018-01-29 15:55:51 -0800864 if (ret != VBERROR_KEEP_LOOPING)
865 return ret;
866 }
867}
868
Shelley Chen84961572017-01-27 15:21:42 -0800869/**
870 * Main function that handles recovery menu functionality
871 *
872 * @param ctx Vboot2 context
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800873 * @return VB2_SUCCESS, or non-zero error code if error.
Shelley Chen84961572017-01-27 15:21:42 -0800874 */
Joel Kitching90671fa2019-07-31 13:17:08 +0800875static vb2_error_t recovery_ui(struct vb2_context *ctx)
Shelley Chen71c6c032016-12-22 09:55:47 -0800876{
Shelley Chen71c6c032016-12-22 09:55:47 -0800877 uint32_t key;
Shelley Chen12820812017-09-13 10:34:11 -0700878 uint32_t key_flags;
Joel Kitching90671fa2019-07-31 13:17:08 +0800879 vb2_error_t ret;
Shelley Chen71c6c032016-12-22 09:55:47 -0800880
Shelley Chen71c6c032016-12-22 09:55:47 -0800881 /* Loop and wait for a recovery image */
Shelley Chene6198e72017-02-14 14:35:01 -0800882 VB2_DEBUG("waiting for a recovery image\n");
Shelley Chene6e177d2017-11-14 12:35:55 -0800883 usb_nogood = -1;
Shelley Chen71c6c032016-12-22 09:55:47 -0800884 while (1) {
Julius Wernerc76e7362018-01-25 17:41:09 -0800885 ret = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE);
Shelley Chen71c6c032016-12-22 09:55:47 -0800886
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800887 if (VB2_SUCCESS == ret)
Julius Werner45b04f62018-01-29 15:55:51 -0800888 return ret; /* Found a recovery kernel */
Shelley Chen71c6c032016-12-22 09:55:47 -0800889
Julius Wernerc76e7362018-01-25 17:41:09 -0800890 if (usb_nogood != (ret != VBERROR_NO_DISK_FOUND)) {
Shelley Chene6e177d2017-11-14 12:35:55 -0800891 /* USB state changed, force back to base screen */
Julius Wernerc76e7362018-01-25 17:41:09 -0800892 usb_nogood = ret != VBERROR_NO_DISK_FOUND;
893 enter_recovery_base_screen(ctx);
Shelley Chen755bf332016-12-27 14:10:26 -0800894 }
Shelley Chen71c6c032016-12-22 09:55:47 -0800895
Julius Werner5caaa392019-10-11 15:22:34 -0700896 key = VbExKeyboardReadWithFlags(&key_flags);
897 if (key == VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS) {
898 if (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)
899 enter_to_dev_menu(ctx);
900 else
901 VB2_DEBUG("ERROR: untrusted combo?!\n");
902 } else {
903 ret = vb2_handle_menu_input(ctx, key, key_flags);
904 if (ret != VBERROR_KEEP_LOOPING)
905 return ret;
Shelley Chen71c6c032016-12-22 09:55:47 -0800906 }
Julius Werner5caaa392019-10-11 15:22:34 -0700907 VbExSleepMs(KEY_DELAY_MS);
Shelley Chen71c6c032016-12-22 09:55:47 -0800908 }
Shelley Chen71c6c032016-12-22 09:55:47 -0800909}
910
Julius Wernerc76e7362018-01-25 17:41:09 -0800911/* Recovery mode entry point. */
Joel Kitching90671fa2019-07-31 13:17:08 +0800912vb2_error_t VbBootRecoveryMenu(struct vb2_context *ctx)
Shelley Chen71c6c032016-12-22 09:55:47 -0800913{
Joel Kitching90671fa2019-07-31 13:17:08 +0800914 vb2_error_t retval = vb2_init_menus(ctx);
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800915 if (VB2_SUCCESS != retval)
Julius Wernerc76e7362018-01-25 17:41:09 -0800916 return retval;
Julius Werner3f896a52018-03-22 14:38:11 -0700917 if (vb2_allow_recovery(ctx))
Julius Werner45b04f62018-01-29 15:55:51 -0800918 retval = recovery_ui(ctx);
919 else
920 retval = broken_ui(ctx);
Mathew King9d6dc0d2019-02-11 10:27:59 -0700921 VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
Shelley Chen71c6c032016-12-22 09:55:47 -0800922 return retval;
923}