vboot_ui_menu.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. *
  5. * High-level firmware wrapper API - user interface for RW firmware
  6. */
  7. #include "2sysincludes.h"
  8. #include "2common.h"
  9. #include "2misc.h"
  10. #include "2nvstorage.h"
  11. #include "2rsa.h"
  12. #include "ec_sync.h"
  13. #include "gbb_access.h"
  14. #include "gbb_header.h"
  15. #include "load_kernel_fw.h"
  16. #include "region.h"
  17. #include "rollback_index.h"
  18. #include "utility.h"
  19. #include "vb2_common.h"
  20. #include "vboot_api.h"
  21. #include "vboot_audio.h"
  22. #include "vboot_common.h"
  23. #include "vboot_display.h"
  24. #include "vboot_kernel.h"
  25. #include "vboot_nvstorage.h"
  26. static void VbAllowUsbBootMenu(struct vb2_context *ctx)
  27. {
  28. VB2_DEBUG("%s\n", __func__);
  29. vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 1);
  30. }
  31. /**
  32. * Checks GBB flags against VbExIsShutdownRequested() shutdown request to
  33. * determine if a shutdown is required.
  34. *
  35. * Returns true if a shutdown is required and false if no shutdown is required.
  36. */
  37. static int VbWantShutdownMenu(uint32_t gbb_flags)
  38. {
  39. uint32_t shutdown_request = VbExIsShutdownRequested();
  40. /* If desired, ignore shutdown request due to lid closure. */
  41. if (gbb_flags & GBB_FLAG_DISABLE_LID_SHUTDOWN)
  42. shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED;
  43. return !!shutdown_request;
  44. }
  45. static void VbTryLegacyMenu(int allowed)
  46. {
  47. if (!allowed)
  48. VB2_DEBUG("VbBootDeveloperMenu() - Legacy boot is disabled\n");
  49. else if (0 != RollbackKernelLock(0))
  50. VB2_DEBUG("Error locking kernel versions on legacy boot.\n");
  51. else
  52. VbExLegacy(); /* will not return if successful */
  53. /* If legacy boot fails, beep and return to calling UI loop. */
  54. VbExBeep(120, 400);
  55. VbExSleepMs(120);
  56. VbExBeep(120, 400);
  57. }
  58. uint32_t VbTryUsbMenu(struct vb2_context *ctx, VbCommonParams *cparams)
  59. {
  60. uint32_t retval = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_REMOVABLE);
  61. if (VBERROR_SUCCESS == retval) {
  62. VB2_DEBUG("VbBootDeveloperMenu() - booting USB\n");
  63. } else {
  64. VB2_DEBUG("VbBootDeveloperMenu() - no kernel found on USB\n");
  65. VbExBeep(250, 200);
  66. VbExSleepMs(120);
  67. /*
  68. * Clear recovery requests from failed
  69. * kernel loading, so that powering off
  70. * at this point doesn't put us into
  71. * recovery mode.
  72. */
  73. vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST,
  74. VBNV_RECOVERY_NOT_REQUESTED);
  75. }
  76. return retval;
  77. }
  78. #define CONFIRM_KEY_DELAY 20 /* Check confirm screen keys every 20ms */
  79. int VbUserConfirmsMenu(struct vb2_context *ctx, VbCommonParams *cparams,
  80. uint32_t confirm_flags)
  81. {
  82. VbSharedDataHeader *shared =
  83. (VbSharedDataHeader *)cparams->shared_data_blob;
  84. uint32_t key;
  85. uint32_t key_flags;
  86. uint32_t button;
  87. int rec_button_was_pressed = 0;
  88. VB2_DEBUG("Entering %s(0x%x)\n", __func__, confirm_flags);
  89. /* Await further instructions */
  90. while (1) {
  91. if (VbWantShutdownMenu(cparams->gbb->flags))
  92. return -1;
  93. key = VbExKeyboardReadWithFlags(&key_flags);
  94. button = VbExGetSwitches(VB_INIT_FLAG_REC_BUTTON_PRESSED);
  95. switch (key) {
  96. case '\r':
  97. /* If we require a trusted keyboard for confirmation,
  98. * but the keyboard may be faked (for instance, a USB
  99. * device), beep and keep waiting.
  100. */
  101. if (confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD &&
  102. !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) {
  103. VbExBeep(120, 400);
  104. break;
  105. }
  106. VB2_DEBUG("%s() - Yes (1)\n", __func__);
  107. return 1;
  108. break;
  109. case ' ':
  110. VB2_DEBUG("%s() - Space (%d)\n", __func__,
  111. confirm_flags & VB_CONFIRM_SPACE_MEANS_NO);
  112. if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO)
  113. return 0;
  114. break;
  115. case 0x1b:
  116. VB2_DEBUG("%s() - No (0)\n", __func__);
  117. return 0;
  118. break;
  119. default:
  120. /* If the recovery button is physical, and is pressed,
  121. * this is also a YES, but must wait for release.
  122. */
  123. if (!(shared->flags & VBSD_BOOT_REC_SWITCH_VIRTUAL)) {
  124. if (button) {
  125. VB2_DEBUG("%s() - Rec button pressed\n",
  126. __func__);
  127. rec_button_was_pressed = 1;
  128. } else if (rec_button_was_pressed) {
  129. VB2_DEBUG("%s() - Rec button (1)\n",
  130. __func__);
  131. return 1;
  132. }
  133. }
  134. VbCheckDisplayKey(ctx, cparams, key);
  135. }
  136. VbExSleepMs(CONFIRM_KEY_DELAY);
  137. }
  138. /* Not reached, but compiler will complain without it */
  139. return -1;
  140. }
  141. static const char dev_disable_msg[] =
  142. "Developer mode is disabled on this device by system policy.\n"
  143. "For more information, see http://dev.chromium.org/chromium-os/fwmp\n"
  144. "\n";
  145. typedef enum _VB_MENU {
  146. VB_MENU_DEV_WARNING,
  147. VB_MENU_DEV,
  148. VB_MENU_TO_NORM,
  149. VB_MENU_RECOVERY,
  150. VB_MENU_TO_DEV,
  151. VB_MENU_LANGUAGES,
  152. VB_MENU_COUNT,
  153. } VB_MENU;
  154. typedef enum _VB_DEV_WARNING_MENU {
  155. VB_WARN_OPTIONS,
  156. VB_WARN_DBG_INFO,
  157. VB_WARN_ENABLE_VER,
  158. VB_WARN_POWER_OFF,
  159. VB_WARN_LANGUAGE,
  160. VB_WARN_COUNT,
  161. } VB_DEV_WARNING_MENU;
  162. typedef enum _VB_DEV_MENU {
  163. VB_DEV_NETWORK,
  164. VB_DEV_LEGACY,
  165. VB_DEV_USB,
  166. VB_DEV_DISK,
  167. VB_DEV_CANCEL,
  168. VB_DEV_POWER_OFF,
  169. VB_DEV_LANGUAGE,
  170. VB_DEV_COUNT,
  171. } VB_DEV_MENU;
  172. typedef enum _VB_TO_NORM_MENU {
  173. VB_TO_NORM_CONFIRM,
  174. VB_TO_NORM_CANCEL,
  175. VB_TO_NORM_POWER_OFF,
  176. VB_TO_NORM_LANGUAGE,
  177. VB_TO_NORM_COUNT,
  178. } VB_TO_NORM_MENU;
  179. typedef enum _VB_RECOVERY_MENU {
  180. VB_RECOVERY_TO_DEV,
  181. VB_RECOVERY_DBG_INFO,
  182. VB_RECOVERY_POWER_OFF,
  183. VB_RECOVERY_LANGUAGE,
  184. VB_RECOVERY_COUNT,
  185. } VB_RECOVERY_MENU;
  186. typedef enum _VB_TO_DEV_MENU {
  187. VB_TO_DEV_CONFIRM,
  188. VB_TO_DEV_CANCEL,
  189. VB_TO_DEV_POWER_OFF,
  190. VB_TO_DEV_LANGUAGE,
  191. VB_TO_DEV_COUNT,
  192. } VB_TO_DEV_MENU;
  193. // currently we're only supporting
  194. // english. Will need to somehow find mapping
  195. // from language to localization index.
  196. typedef enum _VB_LANGUAGES_MENU {
  197. VB_LANGUAGES_EN_US,
  198. VB_LANGUAGES_COUNT,
  199. } VB_LANGUAGES_MENU;
  200. static VB_MENU current_menu = VB_MENU_DEV_WARNING;
  201. static VB_MENU prev_menu = VB_MENU_DEV_WARNING;
  202. static int current_menu_idx = 0;
  203. static int selected = 0;
  204. // TODO: add in consts
  205. static char *dev_warning_menu[] = {
  206. "Developer Options\n",
  207. "Show Debug Info\n",
  208. "Enable Root Verification\n",
  209. "Power Off\n",
  210. "Language\n"
  211. };
  212. static char *dev_menu[] = {
  213. "Boot Network Image (not working yet)\n",
  214. "Boot Legacy BIOS\n",
  215. "Boot USB Image\n",
  216. "Boot Developer Image\n",
  217. "Cancel\n",
  218. "Power Off\n",
  219. "Language\n"
  220. };
  221. static char *to_normal_menu[] = {
  222. "Confirm Enabling Verified Boot\n",
  223. "Cancel\n",
  224. "Power Off\n",
  225. "Language\n"
  226. };
  227. static char *recovery_menu[] = {
  228. "Enable developer mode\n",
  229. "Show Debug Info\n",
  230. "Power Off\n",
  231. "Language\n"
  232. };
  233. static char *to_dev_menu[] = {
  234. "Confirm enabling developer mode\n",
  235. "Cancel\n",
  236. "Power Off\n",
  237. "Language\n"
  238. };
  239. static char *languages_menu[] = {
  240. "US English\n",
  241. };
  242. // function that gets the current menu string array and size.
  243. // can set menu_array to NULL and only return string size.
  244. VbError_t vb2_get_current_menu_size(VB_MENU menu, char ***menu_array, int *size)
  245. {
  246. char **temp_menu;
  247. switch(menu) {
  248. case VB_MENU_DEV_WARNING:
  249. *size = VB_WARN_COUNT;
  250. temp_menu = dev_warning_menu;
  251. break;
  252. case VB_MENU_DEV:
  253. *size = VB_DEV_COUNT;
  254. temp_menu = dev_menu;
  255. break;
  256. case VB_MENU_TO_NORM:
  257. *size = VB_TO_NORM_COUNT;
  258. temp_menu = to_normal_menu;
  259. break;
  260. case VB_MENU_RECOVERY:
  261. *size = VB_RECOVERY_COUNT;
  262. temp_menu = recovery_menu;
  263. break;
  264. case VB_MENU_TO_DEV:
  265. *size = VB_TO_DEV_COUNT;
  266. temp_menu = to_dev_menu;
  267. break;
  268. case VB_MENU_LANGUAGES:
  269. *size = VB_LANGUAGES_COUNT;
  270. temp_menu = languages_menu;
  271. break;
  272. default:
  273. *size = 0;
  274. return VBERROR_UNKNOWN;
  275. }
  276. *menu_array = temp_menu;
  277. return VBERROR_SUCCESS;
  278. }
  279. // TODO: will probably have to print menu a
  280. // line at a time to center the text at X.
  281. // Otherwise, only the first line will be lined up
  282. // vertically properly.
  283. // which is why x is currently 0.
  284. // also, want to calculate what center is eventually instead of
  285. // hard-coding it.
  286. // at least right now there's no overlapping with the debug
  287. // printouts.
  288. VbError_t vb2_print_current_menu()
  289. {
  290. // create menu string
  291. char m_str[1024];
  292. const char *selected = "==> ";
  293. const char *deselected = " ";
  294. int size = 0;
  295. int i = 0;
  296. static char **m = NULL;
  297. memset(m_str, 0, strlen(m_str));
  298. // TODO: need to check for error code.
  299. vb2_get_current_menu_size(current_menu, &m, &size);
  300. VB2_DEBUG("vb2_print_current_menu:\n");
  301. for (i = 0; i < size; i++) {
  302. if (current_menu_idx == i) {
  303. // add selection to indicate current selection
  304. strncat(m_str, selected, strlen(selected));
  305. } else {
  306. strncat(m_str, deselected, strlen(deselected));
  307. }
  308. strncat(m_str, m[i], strlen(m[i]));
  309. }
  310. VB2_DEBUG("%s", m_str);
  311. return VbExDisplayText(0,50,m_str);
  312. }
  313. // This updates current_menu and current_menu_idx,
  314. // (as necessary)
  315. // which are used to determine what to do.
  316. VbError_t vb2_update_menu()
  317. {
  318. VbError_t ret = VBERROR_SUCCESS;
  319. switch(current_menu) {
  320. case VB_MENU_DEV_WARNING:
  321. switch(current_menu_idx) {
  322. case VB_WARN_OPTIONS:
  323. // select dev menu
  324. prev_menu = current_menu;
  325. current_menu = VB_MENU_DEV;
  326. current_menu_idx = 0;
  327. selected = 0;
  328. break;
  329. case VB_WARN_DBG_INFO:
  330. // show debug info
  331. break;
  332. case VB_WARN_ENABLE_VER:
  333. // enable boot verification
  334. prev_menu = current_menu;
  335. current_menu = VB_MENU_TO_NORM;
  336. current_menu_idx = 0;
  337. selected = 0;
  338. break;
  339. case VB_WARN_POWER_OFF:
  340. // power off machine
  341. ret = VBERROR_SHUTDOWN_REQUESTED;
  342. break;
  343. case VB_WARN_LANGUAGE:
  344. // Languages
  345. // we'll have to figure out how to display this
  346. prev_menu = current_menu;
  347. current_menu = VB_MENU_LANGUAGES;
  348. current_menu_idx = 0;
  349. selected = 0;
  350. break;
  351. default:
  352. // invalid menu item. Don't update anything.
  353. break;
  354. }
  355. break;
  356. case VB_MENU_DEV:
  357. switch(current_menu_idx) {
  358. case VB_DEV_NETWORK:
  359. // boot network image
  360. break;
  361. case VB_DEV_LEGACY:
  362. // boot legacy BIOS
  363. break;
  364. case VB_DEV_USB:
  365. // book USB image
  366. break;
  367. case VB_DEV_DISK:
  368. // boot developer image
  369. break;
  370. case VB_DEV_CANCEL:
  371. // cancel (go back to developer warning menu)
  372. prev_menu = current_menu;
  373. current_menu = VB_MENU_DEV_WARNING;
  374. current_menu_idx = 0;
  375. selected = 0;
  376. break;
  377. case VB_DEV_POWER_OFF:
  378. // power off
  379. ret = VBERROR_SHUTDOWN_REQUESTED;
  380. break;
  381. case VB_DEV_LANGUAGE:
  382. // Language
  383. prev_menu = current_menu;
  384. current_menu = VB_MENU_LANGUAGES;
  385. current_menu_idx = 0;
  386. selected = 0;
  387. break;
  388. default:
  389. // invalid menu item. don't update anything.
  390. break;
  391. }
  392. break;
  393. case VB_MENU_TO_NORM:
  394. switch(current_menu_idx) {
  395. case VB_TO_NORM_CONFIRM:
  396. // confirm enabling verified boot
  397. break;
  398. case VB_TO_NORM_CANCEL:
  399. // cancel (go back to developer warning menu)
  400. prev_menu = current_menu;
  401. current_menu = VB_MENU_DEV_WARNING;
  402. current_menu_idx = 0;
  403. selected = 0;
  404. break;
  405. case VB_TO_NORM_POWER_OFF:
  406. // power off
  407. ret = VBERROR_SHUTDOWN_REQUESTED;
  408. break;
  409. case VB_TO_NORM_LANGUAGE:
  410. // Language
  411. prev_menu = current_menu;
  412. current_menu = VB_MENU_LANGUAGES;
  413. current_menu_idx = 0;
  414. selected = 0;
  415. break;
  416. default:
  417. // invalid menu item. don't update anything
  418. break;
  419. }
  420. break;
  421. case VB_MENU_RECOVERY:
  422. switch(current_menu_idx) {
  423. case VB_RECOVERY_TO_DEV:
  424. // switch to TO_DEV menu
  425. prev_menu = current_menu;
  426. current_menu = VB_MENU_TO_DEV;
  427. current_menu_idx = 0;
  428. selected = 0;
  429. break;
  430. case VB_RECOVERY_DBG_INFO:
  431. break;
  432. case VB_RECOVERY_POWER_OFF:
  433. ret = VBERROR_SHUTDOWN_REQUESTED;
  434. break;
  435. case VB_RECOVERY_LANGUAGE:
  436. prev_menu = current_menu;
  437. current_menu = VB_MENU_LANGUAGES;
  438. current_menu_idx = 0;
  439. selected = 0;
  440. break;
  441. default:
  442. // invalid menu item. don't update anything
  443. break;
  444. }
  445. break;
  446. case VB_MENU_TO_DEV:
  447. switch(current_menu_idx) {
  448. case VB_TO_DEV_CONFIRM:
  449. // confirm enabling dev mode
  450. break;
  451. case VB_TO_DEV_CANCEL:
  452. prev_menu = current_menu;
  453. current_menu = VB_MENU_RECOVERY;
  454. current_menu_idx = 0;
  455. selected = 0;
  456. break;
  457. case VB_TO_DEV_POWER_OFF:
  458. ret = VBERROR_SHUTDOWN_REQUESTED;
  459. break;
  460. case VB_TO_DEV_LANGUAGE:
  461. prev_menu = current_menu;
  462. current_menu = VB_MENU_LANGUAGES;
  463. current_menu_idx = 0;
  464. selected = 0;
  465. break;
  466. default:
  467. // invalid menu item. don't update anything.
  468. break;
  469. }
  470. break;
  471. case VB_MENU_LANGUAGES:
  472. switch(current_menu_idx) {
  473. default:
  474. // assume that we select a language.
  475. // go to previous menu.
  476. // assume that there will be come action here.
  477. current_menu = prev_menu;
  478. current_menu_idx = 0;
  479. prev_menu = VB_MENU_LANGUAGES;
  480. selected = 0;
  481. break;
  482. }
  483. default:
  484. VB2_DEBUG("Current Menu Invalid!");
  485. }
  486. return ret;
  487. }
  488. VbError_t vb2_developer_menu(struct vb2_context *ctx, VbCommonParams *cparams)
  489. {
  490. GoogleBinaryBlockHeader *gbb = cparams->gbb;
  491. #if defined(VBOOT_DEBUG)
  492. VbSharedDataHeader *shared =
  493. (VbSharedDataHeader *)cparams->shared_data_blob;
  494. #endif
  495. uint32_t disable_dev_boot = 0;
  496. uint32_t use_usb = 0;
  497. uint32_t use_legacy = 0;
  498. uint32_t ctrl_d_pressed = 0;
  499. VbAudioContext *audio = 0;
  500. VbError_t ret;
  501. VB2_DEBUG("Entering %s()\n", __func__);
  502. /* Check if USB booting is allowed */
  503. uint32_t allow_usb = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB);
  504. uint32_t allow_legacy = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY);
  505. /* Check if the default is to boot using disk, usb, or legacy */
  506. uint32_t default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT);
  507. if(default_boot == VBNV_DEV_DEFAULT_BOOT_USB)
  508. use_usb = 1;
  509. if(default_boot == VBNV_DEV_DEFAULT_BOOT_LEGACY)
  510. use_legacy = 1;
  511. /* Handle GBB flag override */
  512. if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_USB)
  513. allow_usb = 1;
  514. if (gbb->flags & GBB_FLAG_FORCE_DEV_BOOT_LEGACY)
  515. allow_legacy = 1;
  516. if (gbb->flags & GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) {
  517. use_legacy = 1;
  518. use_usb = 0;
  519. }
  520. /* Handle FWMP override */
  521. uint32_t fwmp_flags = vb2_get_fwmp_flags();
  522. if (fwmp_flags & FWMP_DEV_ENABLE_USB)
  523. allow_usb = 1;
  524. if (fwmp_flags & FWMP_DEV_ENABLE_LEGACY)
  525. allow_legacy = 1;
  526. if (fwmp_flags & FWMP_DEV_DISABLE_BOOT) {
  527. if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) {
  528. VB2_DEBUG("%s() - FWMP_DEV_DISABLE_BOOT rejected by"
  529. "FORCE_DEV_SWITCH_ON\n",
  530. __func__);
  531. } else {
  532. disable_dev_boot = 1;
  533. }
  534. }
  535. /* If dev mode is disabled, only allow TONORM */
  536. while (disable_dev_boot) {
  537. VB2_DEBUG("%s() - dev_disable_boot is set.\n", __func__);
  538. VbDisplayScreen(ctx, cparams, VB_SCREEN_DEVELOPER_TO_NORM, 0);
  539. VbExDisplayDebugInfo(dev_disable_msg);
  540. /* Ignore space in VbUserConfirmsMenu()... */
  541. switch (VbUserConfirmsMenu(ctx, cparams, 0)) {
  542. case 1:
  543. VB2_DEBUG("%s() - leaving dev-mode.\n", __func__);
  544. vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
  545. VbDisplayScreen(ctx, cparams,
  546. VB_SCREEN_TO_NORM_CONFIRMED,
  547. 0);
  548. VbExSleepMs(5000);
  549. return VBERROR_REBOOT_REQUIRED;
  550. case -1:
  551. VB2_DEBUG("%s() - shutdown requested\n", __func__);
  552. return VBERROR_SHUTDOWN_REQUESTED;
  553. default:
  554. /* Ignore user attempt to cancel */
  555. VB2_DEBUG("%s() - ignore cancel TONORM\n", __func__);
  556. }
  557. }
  558. /* Show the dev mode warning screen */
  559. /* TODO: change this to blank screen? */
  560. VbDisplayScreen(ctx, cparams, VB_SCREEN_DEVELOPER_WARNING, 0);
  561. vb2_print_current_menu();
  562. /* Get audio/delay context */
  563. audio = VbAudioOpen(cparams);
  564. /* We'll loop until we finish the delay or are interrupted */
  565. do {
  566. uint32_t key;
  567. int menu_size;
  568. if (VbWantShutdownMenu(gbb->flags)) {
  569. VB2_DEBUG("shutdown requested!\n");
  570. VbAudioClose(audio);
  571. return VBERROR_SHUTDOWN_REQUESTED;
  572. }
  573. key = VbExKeyboardRead();
  574. switch (key) {
  575. case 0:
  576. /* nothing pressed */
  577. break;
  578. case '\r':
  579. /* Only disable virtual dev switch if allowed by GBB */
  580. if (!(gbb->flags & GBB_FLAG_ENTER_TRIGGERS_TONORM))
  581. break;
  582. case VB_KEY_UP:
  583. vb2_get_current_menu_size(current_menu,
  584. NULL, &menu_size);
  585. current_menu_idx = (current_menu_idx+menu_size-1) %
  586. menu_size;
  587. vb2_print_current_menu();
  588. break;
  589. case VB_KEY_DOWN:
  590. vb2_get_current_menu_size(current_menu,
  591. NULL, &menu_size);
  592. current_menu_idx = (current_menu_idx+1) % menu_size;
  593. vb2_print_current_menu();
  594. break;
  595. case VB_KEY_RIGHT:
  596. // temporarily using this as a stand in for power button
  597. // until get power button bypassed
  598. selected = 1;
  599. ret = vb2_update_menu();
  600. // unfortunately, we need the blanking to get rid of
  601. // artifacts from previous menu printing.
  602. VbDisplayScreen(ctx, cparams, VB_SCREEN_BLANK, 0);
  603. VbDisplayScreen(ctx, cparams,
  604. VB_SCREEN_DEVELOPER_WARNING, 0);
  605. vb2_print_current_menu();
  606. // probably shutting down
  607. if (ret != VBERROR_SUCCESS) {
  608. VB2_DEBUG("VbBootDeveloperMenu() - shutting down!\n");
  609. return ret;
  610. }
  611. // nothing selected, skip everything else.
  612. if (selected == 0)
  613. break;
  614. // below is all the selection actions
  615. // Display debug information = tab on most chromebooks
  616. if (current_menu == VB_MENU_DEV_WARNING &&
  617. current_menu_idx == VB_WARN_DBG_INFO) {
  618. VbDisplayDebugInfo(ctx, cparams);
  619. }
  620. // Ctrl+L = legacy mode
  621. if (current_menu == VB_MENU_DEV &&
  622. current_menu_idx == VB_DEV_LEGACY) {
  623. VB2_DEBUG("VbBootDeveloperMenu() - "
  624. "user pressed Ctrl+L; "
  625. "Try legacy boot\n");
  626. VbTryLegacyMenu(allow_legacy);
  627. }
  628. // Ctrl+U = try USB boot, or beep if failure
  629. if (current_menu == VB_MENU_DEV &&
  630. current_menu_idx == VB_DEV_USB) {
  631. VB2_DEBUG("VbBootDeveloperMenu() - "
  632. "user pressed Ctrl+U; try USB\n");
  633. if (!allow_usb) {
  634. VB2_DEBUG("VbBootDeveloperMenu() - "
  635. "USB booting is disabled\n");
  636. VbExDisplayDebugInfo(
  637. "WARNING: Booting from external media "
  638. "(USB/SD) has not been enabled. Refer "
  639. "to the developer-mode documentation "
  640. "for details.\n");
  641. VbExBeep(120, 400);
  642. VbExSleepMs(120);
  643. VbExBeep(120, 400);
  644. } else {
  645. // Clear the screen to show we get the
  646. // Ctrl+U key press.
  647. VbDisplayScreen(ctx,
  648. cparams, VB_SCREEN_BLANK, 0);
  649. if (VBERROR_SUCCESS ==
  650. VbTryUsbMenu(ctx, cparams)) {
  651. VbAudioClose(audio);
  652. return VBERROR_SUCCESS;
  653. } else {
  654. // Show dev mode warning screen
  655. // again
  656. VbDisplayScreen(ctx,
  657. cparams,
  658. VB_SCREEN_DEVELOPER_WARNING,
  659. 0);
  660. }
  661. }
  662. }
  663. /* Ctrl+D = dismiss warning; advance to timeout */
  664. if (current_menu == VB_MENU_DEV &&
  665. current_menu_idx == VB_DEV_DISK) {
  666. VB2_DEBUG("VbBootDeveloperMenu() - "
  667. "user pressed Ctrl+D; skip delay\n");
  668. ctrl_d_pressed = 1;
  669. goto fallout;
  670. }
  671. /* enabling verified boot */
  672. if (current_menu == VB_MENU_TO_NORM &&
  673. current_menu_idx == VB_TO_NORM_CONFIRM) {
  674. // See if we should disable virtual dev-mode
  675. // switch.
  676. VB2_DEBUG("%s shared->flags=0x%x\n",
  677. __func__, shared->flags);
  678. // Ignore space in VbUserConfirmsMenu()...
  679. VB2_DEBUG("%s() - leaving dev-mode.\n",
  680. __func__);
  681. vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST,
  682. 1);
  683. VbDisplayScreen(ctx,
  684. cparams,
  685. VB_SCREEN_TO_NORM_CONFIRMED,
  686. 0);
  687. VbExSleepMs(5000);
  688. return VBERROR_REBOOT_REQUIRED;
  689. }
  690. break;
  691. default:
  692. VB2_DEBUG("VbBootDeveloperMenu() - pressed key %d\n",
  693. key);
  694. VbCheckDisplayKey(ctx, cparams, key);
  695. break;
  696. }
  697. } while(VbAudioLooping(audio));
  698. fallout:
  699. /* If defaulting to legacy boot, try that unless Ctrl+D was pressed */
  700. if (use_legacy && !ctrl_d_pressed) {
  701. VB2_DEBUG("VbBootDeveloperMenu() - defaulting to legacy\n");
  702. VbTryLegacyMenu(allow_legacy);
  703. }
  704. if ((use_usb && !ctrl_d_pressed) && allow_usb) {
  705. if (VBERROR_SUCCESS == VbTryUsbMenu(ctx, cparams)) {
  706. VbAudioClose(audio);
  707. return VBERROR_SUCCESS;
  708. }
  709. }
  710. /* Timeout or Ctrl+D; attempt loading from fixed disk */
  711. VB2_DEBUG("VbBootDeveloperMenu() - trying fixed disk\n");
  712. VbAudioClose(audio);
  713. return VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_FIXED);
  714. }
  715. VbError_t VbBootDeveloperMenu(struct vb2_context *ctx, VbCommonParams *cparams)
  716. {
  717. VbError_t retval = vb2_developer_menu(ctx, cparams);
  718. VbDisplayScreen(ctx, cparams, VB_SCREEN_BLANK, 0);
  719. return retval;
  720. }
  721. /* Delay in recovery mode */
  722. #define REC_DISK_DELAY 1000 /* Check disks every 1s */
  723. #define REC_KEY_DELAY 20 /* Check keys every 20ms */
  724. #define REC_MEDIA_INIT_DELAY 500 /* Check removable media every 500ms */
  725. VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams)
  726. {
  727. VbSharedDataHeader *shared =
  728. (VbSharedDataHeader *)cparams->shared_data_blob;
  729. uint32_t retval;
  730. uint32_t key;
  731. int i;
  732. VbError_t ret;
  733. int menu_size;
  734. VB2_DEBUG("VbBootRecoveryMenu() start\n");
  735. /*
  736. * If the dev-mode switch is off and the user didn't press the recovery
  737. * button (recovery was triggerred automatically), show 'broken' screen.
  738. * The user can either only shutdown to abort or hit esc+refresh+power
  739. * to initiate recovery as instructed on the screen.
  740. */
  741. if (!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
  742. !(shared->flags & VBSD_BOOT_REC_SWITCH_ON)) {
  743. /*
  744. * We have to save the reason here so that it will survive
  745. * coming up three-finger-salute. We're saving it in
  746. * VBNV_RECOVERY_SUBCODE to avoid a recovery loop.
  747. * If we save the reason in VBNV_RECOVERY_REQUEST, we will come
  748. * back here, thus, we won't be able to give a user a chance to
  749. * reboot to workaround boot hicups.
  750. */
  751. VB2_DEBUG("VbBootRecoveryMenu() saving recovery reason (%#x)\n",
  752. shared->recovery_reason);
  753. vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE,
  754. shared->recovery_reason);
  755. /*
  756. * Commit NV now, because it won't get saved if the user forces
  757. * manual recovery via the three-finger salute.
  758. */
  759. vb2_nv_commit(ctx);
  760. VbDisplayScreen(ctx, cparams, VB_SCREEN_OS_BROKEN, 0);
  761. VB2_DEBUG("VbBootRecoveryMenu() waiting for manual recovery\n");
  762. while (1) {
  763. VbCheckDisplayKey(ctx, cparams, VbExKeyboardRead());
  764. if (VbWantShutdownMenu(cparams->gbb->flags))
  765. return VBERROR_SHUTDOWN_REQUESTED;
  766. VbExSleepMs(REC_KEY_DELAY);
  767. }
  768. }
  769. /* Loop and wait for a recovery image */
  770. VB2_DEBUG("VbBootRecoveryMenu() waiting for a recovery image\n");
  771. // initialize menu to recovery menu.
  772. current_menu = VB_MENU_RECOVERY;
  773. prev_menu = VB_MENU_RECOVERY;
  774. current_menu_idx = 0;
  775. while (1) {
  776. VB2_DEBUG("VbBootRecoveryMenu() attempting to load kernel2\n");
  777. retval = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_REMOVABLE);
  778. /*
  779. * Clear recovery requests from failed kernel loading, since
  780. * we're already in recovery mode. Do this now, so that
  781. * powering off after inserting an invalid disk doesn't leave
  782. * us stuck in recovery mode.
  783. */
  784. vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST,
  785. VBNV_RECOVERY_NOT_REQUESTED);
  786. if (VBERROR_SUCCESS == retval)
  787. break; /* Found a recovery kernel */
  788. VbDisplayScreen(ctx, cparams, VBERROR_NO_DISK_FOUND == retval ?
  789. VB_SCREEN_RECOVERY_INSERT :
  790. VB_SCREEN_RECOVERY_NO_GOOD,
  791. 0);
  792. if (current_menu != VB_MENU_RECOVERY ||
  793. current_menu_idx != VB_RECOVERY_DBG_INFO) {
  794. vb2_print_current_menu();
  795. }
  796. /*
  797. * Scan keyboard more frequently than media, since x86
  798. * platforms don't like to scan USB too rapidly.
  799. */
  800. for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
  801. key = VbExKeyboardRead();
  802. switch (key) {
  803. case 0:
  804. /* nothing pressed */
  805. break;
  806. case VB_KEY_UP:
  807. VB2_DEBUG("VbBootRecoveryMenu() - pressed key VB_KEY_UP\n");
  808. vb2_get_current_menu_size(current_menu, NULL, &menu_size);
  809. current_menu_idx = (current_menu_idx+menu_size-1) % menu_size;
  810. vb2_print_current_menu();
  811. break;
  812. case VB_KEY_DOWN:
  813. VB2_DEBUG("VbBootRecoveryMenu() - pressed key VB_KEY_DOWN\n");
  814. vb2_get_current_menu_size(current_menu, NULL, &menu_size);
  815. current_menu_idx = (current_menu_idx+1) % menu_size;
  816. vb2_print_current_menu();
  817. break;
  818. case VB_KEY_RIGHT:
  819. // temporarily using this as a stand in for
  820. // power button until get power button bypassed
  821. VB2_DEBUG("VbBootRecoveryMenu() - pressed key VB_KEY_RIGHT (SELECT)\n");
  822. selected = 1;
  823. ret = vb2_update_menu();
  824. if (current_menu != VB_MENU_RECOVERY ||
  825. current_menu_idx != VB_RECOVERY_DBG_INFO) {
  826. // unfortunately we need this screen
  827. // blanking to clear previous menus
  828. // printed.
  829. VbDisplayScreen(ctx, cparams, VB_SCREEN_BLANK, 0);
  830. VbDisplayScreen(ctx, cparams, VBERROR_NO_DISK_FOUND == retval ?
  831. VB_SCREEN_RECOVERY_INSERT :
  832. VB_SCREEN_RECOVERY_NO_GOOD,
  833. 0);
  834. vb2_print_current_menu();
  835. }
  836. // probably shutting down
  837. if (ret != VBERROR_SUCCESS) {
  838. VB2_DEBUG("VbBootRecoveryMenu() - update_menu - shutting down!\n");
  839. return ret;
  840. }
  841. // nothing selected, skip everything else.
  842. if (selected == 0)
  843. break;
  844. /* Display debug information */
  845. if (current_menu == VB_MENU_RECOVERY &&
  846. current_menu_idx == VB_RECOVERY_DBG_INFO) {
  847. VbDisplayDebugInfo(ctx, cparams);
  848. }
  849. /* Confirm going into developer mode */
  850. /*
  851. * We might want to enter dev-mode from the Insert
  852. * screen if all of the following are true:
  853. * - user pressed Ctrl-D
  854. * - we can honor the virtual dev switch
  855. * - not already in dev mode
  856. * - user forced recovery mode
  857. * - EC isn't pwned
  858. */
  859. // TODO: let's put an error here if we're
  860. // already in dev mode.
  861. if (current_menu == VB_MENU_TO_DEV &&
  862. current_menu_idx == 0 &&
  863. shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
  864. !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
  865. (shared->flags & VBSD_BOOT_REC_SWITCH_ON) &&
  866. VbExTrustEC(0)) {
  867. if (!(shared->flags &
  868. VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
  869. VbExGetSwitches(
  870. VB_INIT_FLAG_REC_BUTTON_PRESSED)) {
  871. /*
  872. * Is the recovery button stuck? In
  873. * any case we don't like this. Beep
  874. * and ignore.
  875. */
  876. VB2_DEBUG("%s() - ^D but rec switch "
  877. "is pressed\n", __func__);
  878. VbExBeep(120, 400);
  879. continue;
  880. }
  881. VB2_DEBUG("%s() Enabling dev-mode...\n",
  882. __func__);
  883. if (TPM_SUCCESS != SetVirtualDevMode(1))
  884. return VBERROR_TPM_SET_BOOT_MODE_STATE;
  885. VB2_DEBUG("%s() Reboot so it will take "
  886. "effect\n", __func__);
  887. if (VbExGetSwitches
  888. (VB_INIT_FLAG_ALLOW_USB_BOOT))
  889. VbAllowUsbBootMenu(ctx);
  890. return VBERROR_REBOOT_REQUIRED;
  891. }
  892. }
  893. if (VbWantShutdownMenu(cparams->gbb->flags))
  894. return VBERROR_SHUTDOWN_REQUESTED;
  895. VbExSleepMs(REC_KEY_DELAY);
  896. }
  897. }
  898. return VBERROR_SUCCESS;
  899. }
  900. VbError_t VbBootRecoveryMenu(struct vb2_context *ctx, VbCommonParams *cparams)
  901. {
  902. VbError_t retval = vb2_recovery_menu(ctx, cparams);
  903. VbDisplayScreen(ctx, cparams, VB_SCREEN_BLANK, 0);
  904. return retval;
  905. }