vboot_api_kernel2_tests.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  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. * Tests for vboot_api_kernel, part 2
  6. */
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "2sysincludes.h"
  11. #include "2api.h"
  12. #include "2misc.h"
  13. #include "2nvstorage.h"
  14. #include "gbb_header.h"
  15. #include "host_common.h"
  16. #include "load_kernel_fw.h"
  17. #include "rollback_index.h"
  18. #include "test_common.h"
  19. #include "vboot_audio.h"
  20. #include "vboot_common.h"
  21. #include "vboot_display.h"
  22. #include "vboot_kernel.h"
  23. #include "vboot_nvstorage.h"
  24. #include "vboot_struct.h"
  25. /* Mock data */
  26. static VbCommonParams cparams;
  27. static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
  28. static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
  29. static GoogleBinaryBlockHeader gbb;
  30. static LoadKernelParams lkp;
  31. static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE];
  32. static struct vb2_context ctx;
  33. static int shutdown_request_calls_left;
  34. static int audio_looping_calls_left;
  35. static uint32_t vbtlk_retval;
  36. static int vbexlegacy_called;
  37. static int trust_ec;
  38. static int virtdev_set;
  39. static uint32_t virtdev_retval;
  40. static uint32_t mock_keypress[8];
  41. static uint32_t mock_keyflags[8];
  42. static uint32_t mock_keypress_count;
  43. static uint32_t mock_switches[8];
  44. static uint32_t mock_switches_count;
  45. static int mock_switches_are_stuck;
  46. static uint32_t screens_displayed[8];
  47. static uint32_t screens_count = 0;
  48. static uint32_t mock_num_disks[8];
  49. static uint32_t mock_num_disks_count;
  50. extern enum VbEcBootMode_t VbGetMode(void);
  51. extern struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void);
  52. /* Reset mock data (for use before each test) */
  53. static void ResetMocks(void)
  54. {
  55. memset(&cparams, 0, sizeof(cparams));
  56. cparams.shared_data_size = sizeof(shared_data);
  57. cparams.shared_data_blob = shared_data;
  58. cparams.gbb_data = &gbb;
  59. cparams.gbb = &gbb;
  60. memset(&gbb, 0, sizeof(gbb));
  61. gbb.major_version = GBB_MAJOR_VER;
  62. gbb.minor_version = GBB_MINOR_VER;
  63. gbb.flags = 0;
  64. memset(VbApiKernelGetFwmp(), 0, sizeof(struct RollbackSpaceFwmp));
  65. memset(&shared_data, 0, sizeof(shared_data));
  66. VbSharedDataInit(shared, sizeof(shared_data));
  67. memset(&lkp, 0, sizeof(lkp));
  68. memset(&ctx, 0, sizeof(ctx));
  69. ctx.workbuf = workbuf;
  70. ctx.workbuf_size = sizeof(workbuf);
  71. vb2_init_context(&ctx);
  72. vb2_nv_init(&ctx);
  73. shutdown_request_calls_left = -1;
  74. audio_looping_calls_left = 30;
  75. vbtlk_retval = 1000;
  76. vbexlegacy_called = 0;
  77. trust_ec = 0;
  78. virtdev_set = 0;
  79. virtdev_retval = 0;
  80. memset(screens_displayed, 0, sizeof(screens_displayed));
  81. screens_count = 0;
  82. memset(mock_keypress, 0, sizeof(mock_keypress));
  83. memset(mock_keyflags, 0, sizeof(mock_keyflags));
  84. mock_keypress_count = 0;
  85. memset(mock_switches, 0, sizeof(mock_switches));
  86. mock_switches_count = 0;
  87. mock_switches_are_stuck = 0;
  88. memset(mock_num_disks, 0, sizeof(mock_num_disks));
  89. mock_num_disks_count = 0;
  90. }
  91. /* Mock functions */
  92. uint32_t VbExIsShutdownRequested(void)
  93. {
  94. if (shutdown_request_calls_left == 0)
  95. return 1;
  96. else if (shutdown_request_calls_left > 0)
  97. shutdown_request_calls_left--;
  98. return 0;
  99. }
  100. uint32_t VbExKeyboardRead(void)
  101. {
  102. return VbExKeyboardReadWithFlags(NULL);
  103. }
  104. uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags)
  105. {
  106. if (mock_keypress_count < ARRAY_SIZE(mock_keypress)) {
  107. if (key_flags != NULL)
  108. *key_flags = mock_keyflags[mock_keypress_count];
  109. return mock_keypress[mock_keypress_count++];
  110. } else
  111. return 0;
  112. }
  113. uint32_t VbExGetSwitches(uint32_t request_mask)
  114. {
  115. if (mock_switches_are_stuck)
  116. return mock_switches[0] & request_mask;
  117. if (mock_switches_count < ARRAY_SIZE(mock_switches))
  118. return mock_switches[mock_switches_count++] & request_mask;
  119. else
  120. return 0;
  121. }
  122. int VbExLegacy(void)
  123. {
  124. vbexlegacy_called++;
  125. return 0;
  126. }
  127. VbError_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count,
  128. uint32_t disk_flags)
  129. {
  130. if (mock_num_disks_count < ARRAY_SIZE(mock_num_disks)) {
  131. if (mock_num_disks[mock_num_disks_count] == -1)
  132. return VBERROR_SIMULATED;
  133. else
  134. *count = mock_num_disks[mock_num_disks_count++];
  135. } else {
  136. *count = 0;
  137. }
  138. return VBERROR_SUCCESS;
  139. }
  140. VbError_t VbExDiskFreeInfo(VbDiskInfo *infos,
  141. VbExDiskHandle_t preserve_handle)
  142. {
  143. return VBERROR_SUCCESS;
  144. }
  145. int VbExTrustEC(int devidx)
  146. {
  147. return trust_ec;
  148. }
  149. int VbAudioLooping(VbAudioContext *audio)
  150. {
  151. if (audio_looping_calls_left == 0)
  152. return 0;
  153. else if (audio_looping_calls_left > 0)
  154. audio_looping_calls_left--;
  155. return 1;
  156. }
  157. uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams,
  158. uint32_t get_info_flags)
  159. {
  160. return vbtlk_retval + get_info_flags;
  161. }
  162. VbError_t VbDisplayScreen(struct vb2_context *ctx, VbCommonParams *cparams,
  163. uint32_t screen, int force)
  164. {
  165. if (screens_count < ARRAY_SIZE(screens_displayed))
  166. screens_displayed[screens_count++] = screen;
  167. return VBERROR_SUCCESS;
  168. }
  169. uint32_t SetVirtualDevMode(int val)
  170. {
  171. virtdev_set = val;
  172. return virtdev_retval;
  173. }
  174. /* Tests */
  175. static void VbUserConfirmsTest(void)
  176. {
  177. printf("Testing VbUserConfirms()...\n");
  178. ResetMocks();
  179. shutdown_request_calls_left = 1;
  180. TEST_EQ(VbUserConfirms(&ctx, &cparams, 0), -1, "Shutdown requested");
  181. ResetMocks();
  182. mock_keypress[0] = '\r';
  183. TEST_EQ(VbUserConfirms(&ctx, &cparams, 0), 1, "Enter");
  184. ResetMocks();
  185. mock_keypress[0] = 0x1b;
  186. TEST_EQ(VbUserConfirms(&ctx, &cparams, 0), 0, "Esc");
  187. ResetMocks();
  188. mock_keypress[0] = ' ';
  189. shutdown_request_calls_left = 1;
  190. TEST_EQ(VbUserConfirms(&ctx, &cparams, VB_CONFIRM_SPACE_MEANS_NO), 0,
  191. "Space means no");
  192. ResetMocks();
  193. mock_keypress[0] = ' ';
  194. shutdown_request_calls_left = 1;
  195. TEST_EQ(VbUserConfirms(&ctx, &cparams, 0), -1, "Space ignored");
  196. ResetMocks();
  197. mock_keypress[0] = '\r';
  198. mock_keyflags[0] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
  199. TEST_EQ(VbUserConfirms(&ctx, &cparams, VB_CONFIRM_MUST_TRUST_KEYBOARD),
  200. 1, "Enter with trusted keyboard");
  201. ResetMocks();
  202. mock_keypress[0] = '\r'; /* untrusted */
  203. mock_keypress[1] = ' ';
  204. TEST_EQ(VbUserConfirms(&ctx, &cparams,
  205. VB_CONFIRM_SPACE_MEANS_NO |
  206. VB_CONFIRM_MUST_TRUST_KEYBOARD),
  207. 0, "Untrusted keyboard");
  208. ResetMocks();
  209. mock_switches[0] = VB_INIT_FLAG_REC_BUTTON_PRESSED;
  210. TEST_EQ(VbUserConfirms(&ctx, &cparams,
  211. VB_CONFIRM_SPACE_MEANS_NO |
  212. VB_CONFIRM_MUST_TRUST_KEYBOARD),
  213. 1, "Recovery button");
  214. ResetMocks();
  215. mock_keypress[0] = '\r';
  216. mock_keypress[1] = 'y';
  217. mock_keypress[2] = 'z';
  218. mock_keypress[3] = ' ';
  219. mock_switches[0] = VB_INIT_FLAG_REC_BUTTON_PRESSED;
  220. mock_switches_are_stuck = 1;
  221. TEST_EQ(VbUserConfirms(&ctx, &cparams,
  222. VB_CONFIRM_SPACE_MEANS_NO |
  223. VB_CONFIRM_MUST_TRUST_KEYBOARD),
  224. 0, "Recovery button stuck");
  225. printf("...done.\n");
  226. }
  227. static void VbBootTest(void)
  228. {
  229. ResetMocks();
  230. VbExEcEnteringMode(0, VB_EC_NORMAL);
  231. TEST_EQ(VbBootNormal(&ctx, &cparams), 1002, "VbBootNormal()");
  232. TEST_EQ(VbGetMode(), VB_EC_NORMAL, "vboot_mode normal");
  233. }
  234. static void VbBootDevTest(void)
  235. {
  236. printf("Testing VbBootDeveloper()...\n");
  237. /* Proceed after timeout */
  238. ResetMocks();
  239. VbExEcEnteringMode(0, VB_EC_DEVELOPER);
  240. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
  241. TEST_EQ(VbGetMode(), VB_EC_DEVELOPER, "vboot_mode developer");
  242. TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
  243. " warning screen");
  244. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0,
  245. " recovery reason");
  246. TEST_EQ(audio_looping_calls_left, 0, " used up audio");
  247. /* Proceed to legacy after timeout if GBB flag set */
  248. ResetMocks();
  249. gbb.flags |= GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY |
  250. GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
  251. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
  252. TEST_EQ(vbexlegacy_called, 1, " try legacy");
  253. /* Proceed to legacy after timeout if boot legacy and default boot
  254. * legacy are set */
  255. ResetMocks();
  256. vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
  257. VBNV_DEV_DEFAULT_BOOT_LEGACY);
  258. vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
  259. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
  260. TEST_EQ(vbexlegacy_called, 1, " try legacy");
  261. /* Proceed to legacy boot mode only if enabled */
  262. ResetMocks();
  263. vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
  264. VBNV_DEV_DEFAULT_BOOT_LEGACY);
  265. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
  266. TEST_EQ(vbexlegacy_called, 0, " not legacy");
  267. /* Proceed to usb after timeout if boot usb and default boot
  268. * usb are set */
  269. ResetMocks();
  270. vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
  271. VBNV_DEV_DEFAULT_BOOT_USB);
  272. vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
  273. vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
  274. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U USB");
  275. /* Proceed to usb boot mode only if enabled */
  276. ResetMocks();
  277. vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
  278. VBNV_DEV_DEFAULT_BOOT_USB);
  279. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
  280. /* If no USB tries fixed disk */
  281. ResetMocks();
  282. vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
  283. vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
  284. VBNV_DEV_DEFAULT_BOOT_USB);
  285. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U enabled");
  286. TEST_EQ(vbexlegacy_called, 0, " not legacy");
  287. /* Up arrow is uninteresting / passed to VbCheckDisplayKey() */
  288. ResetMocks();
  289. mock_keypress[0] = VB_KEY_UP;
  290. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Up arrow");
  291. /* Shutdown requested in loop */
  292. ResetMocks();
  293. shutdown_request_calls_left = 2;
  294. TEST_EQ(VbBootDeveloper(&ctx, &cparams),
  295. VBERROR_SHUTDOWN_REQUESTED,
  296. "Shutdown requested");
  297. TEST_NEQ(audio_looping_calls_left, 0, " aborts audio");
  298. /* Space goes straight to recovery if no virtual dev switch */
  299. ResetMocks();
  300. mock_keypress[0] = ' ';
  301. TEST_EQ(VbBootDeveloper(&ctx, &cparams),
  302. VBERROR_LOAD_KERNEL_RECOVERY,
  303. "Space = recovery");
  304. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST),
  305. VBNV_RECOVERY_RW_DEV_SCREEN, " recovery reason");
  306. /* Space asks to disable virtual dev switch */
  307. ResetMocks();
  308. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
  309. mock_keypress[0] = ' ';
  310. mock_keypress[1] = '\r';
  311. TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
  312. "Space = tonorm");
  313. TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
  314. " warning screen");
  315. TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM,
  316. " tonorm screen");
  317. TEST_EQ(screens_displayed[2], VB_SCREEN_TO_NORM_CONFIRMED,
  318. " confirm screen");
  319. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_DISABLE_DEV_REQUEST), 1,
  320. " disable dev request");
  321. /* Space-space doesn't disable it */
  322. ResetMocks();
  323. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
  324. mock_keypress[0] = ' ';
  325. mock_keypress[1] = ' ';
  326. mock_keypress[2] = 0x1b;
  327. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Space-space");
  328. TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
  329. " warning screen");
  330. TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM,
  331. " tonorm screen");
  332. TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING,
  333. " warning screen");
  334. /* Enter doesn't by default */
  335. ResetMocks();
  336. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
  337. mock_keypress[0] = '\r';
  338. mock_keypress[1] = '\r';
  339. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Enter ignored");
  340. /* Enter does if GBB flag set */
  341. ResetMocks();
  342. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
  343. gbb.flags |= GBB_FLAG_ENTER_TRIGGERS_TONORM;
  344. mock_keypress[0] = '\r';
  345. mock_keypress[1] = '\r';
  346. TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
  347. "Enter = tonorm");
  348. /* Tonorm ignored if GBB forces dev switch on */
  349. ResetMocks();
  350. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
  351. gbb.flags |= GBB_FLAG_FORCE_DEV_SWITCH_ON;
  352. mock_keypress[0] = ' ';
  353. mock_keypress[1] = '\r';
  354. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
  355. "Can't tonorm gbb-dev");
  356. /* Shutdown requested at tonorm screen */
  357. ResetMocks();
  358. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
  359. mock_keypress[0] = ' ';
  360. shutdown_request_calls_left = 2;
  361. TEST_EQ(VbBootDeveloper(&ctx, &cparams),
  362. VBERROR_SHUTDOWN_REQUESTED,
  363. "Shutdown requested at tonorm");
  364. TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
  365. " warning screen");
  366. TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM,
  367. " tonorm screen");
  368. /* Ctrl+D dismisses warning */
  369. ResetMocks();
  370. mock_keypress[0] = 0x04;
  371. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+D");
  372. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0,
  373. " recovery reason");
  374. TEST_NEQ(audio_looping_calls_left, 0, " aborts audio");
  375. TEST_EQ(vbexlegacy_called, 0, " not legacy");
  376. /* Ctrl+D doesn't boot legacy even if GBB flag is set */
  377. ResetMocks();
  378. mock_keypress[0] = 0x04;
  379. gbb.flags |= GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY;
  380. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+D");
  381. TEST_EQ(vbexlegacy_called, 0, " not legacy");
  382. /* Ctrl+L tries legacy boot mode only if enabled */
  383. ResetMocks();
  384. mock_keypress[0] = 0x0c;
  385. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+L normal");
  386. TEST_EQ(vbexlegacy_called, 0, " not legacy");
  387. ResetMocks();
  388. gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
  389. mock_keypress[0] = 0x0c;
  390. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
  391. "Ctrl+L force legacy");
  392. TEST_EQ(vbexlegacy_called, 1, " try legacy");
  393. ResetMocks();
  394. vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
  395. mock_keypress[0] = 0x0c;
  396. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
  397. "Ctrl+L nv legacy");
  398. TEST_EQ(vbexlegacy_called, 1, " try legacy");
  399. ResetMocks();
  400. VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_LEGACY;
  401. mock_keypress[0] = 0x0c;
  402. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
  403. "Ctrl+L fwmp legacy");
  404. TEST_EQ(vbexlegacy_called, 1, " fwmp legacy");
  405. /* Ctrl+U boots USB only if enabled */
  406. ResetMocks();
  407. mock_keypress[0] = 0x15;
  408. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U normal");
  409. /* Ctrl+U enabled, with good USB boot */
  410. ResetMocks();
  411. vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
  412. mock_keypress[0] = 0x15;
  413. vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
  414. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U USB");
  415. /* Ctrl+U enabled via GBB */
  416. ResetMocks();
  417. gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_USB;
  418. mock_keypress[0] = 0x15;
  419. vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
  420. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U force USB");
  421. /* Ctrl+U enabled via FWMP */
  422. ResetMocks();
  423. VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_USB;
  424. mock_keypress[0] = 0x15;
  425. vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
  426. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U force USB");
  427. /* If no USB, eventually times out and tries fixed disk */
  428. ResetMocks();
  429. vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
  430. mock_keypress[0] = 0x15;
  431. TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U enabled");
  432. TEST_EQ(vbexlegacy_called, 0, " not legacy");
  433. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0,
  434. " recovery reason");
  435. TEST_EQ(audio_looping_calls_left, 0, " used up audio");
  436. /* If dev mode is disabled, goes to TONORM screen repeatedly */
  437. ResetMocks();
  438. VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT;
  439. mock_keypress[0] = '\x1b'; /* Just causes TONORM again */
  440. mock_keypress[1] = '\r';
  441. TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
  442. "FWMP dev disabled");
  443. TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
  444. " tonorm screen");
  445. TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM,
  446. " tonorm screen");
  447. TEST_EQ(screens_displayed[2], VB_SCREEN_TO_NORM_CONFIRMED,
  448. " confirm screen");
  449. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_DISABLE_DEV_REQUEST), 1,
  450. " disable dev request");
  451. /* Shutdown requested when dev disabled */
  452. ResetMocks();
  453. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
  454. VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT;
  455. shutdown_request_calls_left = 1;
  456. TEST_EQ(VbBootDeveloper(&ctx, &cparams),
  457. VBERROR_SHUTDOWN_REQUESTED,
  458. "Shutdown requested when dev disabled");
  459. TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
  460. " tonorm screen");
  461. printf("...done.\n");
  462. }
  463. static void VbBootRecTest(void)
  464. {
  465. printf("Testing VbBootRecovery()...\n");
  466. /* Shutdown requested in loop */
  467. ResetMocks();
  468. shutdown_request_calls_left = 10;
  469. VbExEcEnteringMode(0, VB_EC_RECOVERY);
  470. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  471. VBERROR_SHUTDOWN_REQUESTED,
  472. "Shutdown requested");
  473. TEST_EQ(VbGetMode(), VB_EC_RECOVERY, "vboot_mode recovery");
  474. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0,
  475. " recovery reason");
  476. TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
  477. " broken screen");
  478. /* Remove disks */
  479. ResetMocks();
  480. shutdown_request_calls_left = 100;
  481. mock_num_disks[0] = 1;
  482. mock_num_disks[1] = 1;
  483. mock_num_disks[2] = 1;
  484. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  485. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  486. VBERROR_SHUTDOWN_REQUESTED,
  487. "Remove");
  488. TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
  489. " broken screen");
  490. /* No removal if dev switch is on */
  491. ResetMocks();
  492. shutdown_request_calls_left = 100;
  493. mock_num_disks[0] = 1;
  494. mock_num_disks[1] = 1;
  495. shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
  496. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  497. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  498. VBERROR_SHUTDOWN_REQUESTED,
  499. "No remove in dev");
  500. TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
  501. " insert screen");
  502. /* No removal if recovery button physically pressed */
  503. ResetMocks();
  504. shutdown_request_calls_left = 100;
  505. mock_num_disks[0] = 1;
  506. mock_num_disks[1] = 1;
  507. shared->flags |= VBSD_BOOT_REC_SWITCH_ON;
  508. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  509. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  510. VBERROR_SHUTDOWN_REQUESTED,
  511. "No remove in rec");
  512. TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
  513. " insert screen");
  514. /* Removal if no disk initially found, but found on second attempt */
  515. ResetMocks();
  516. shutdown_request_calls_left = 100;
  517. mock_num_disks[0] = 0;
  518. mock_num_disks[1] = 1;
  519. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  520. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  521. VBERROR_SHUTDOWN_REQUESTED,
  522. "Remove");
  523. TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
  524. " broken screen");
  525. /* Bad disk count doesn't require removal */
  526. ResetMocks();
  527. shutdown_request_calls_left = 100;
  528. mock_num_disks[0] = -1;
  529. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  530. shutdown_request_calls_left = 10;
  531. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  532. VBERROR_SHUTDOWN_REQUESTED,
  533. "Bad disk count");
  534. TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
  535. " broken screen");
  536. /* Ctrl+D ignored for many reasons... */
  537. ResetMocks();
  538. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON;
  539. shutdown_request_calls_left = 100;
  540. mock_keypress[0] = 0x04;
  541. trust_ec = 0;
  542. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  543. VBERROR_SHUTDOWN_REQUESTED,
  544. "Ctrl+D ignored if EC not trusted");
  545. TEST_EQ(virtdev_set, 0, " virtual dev mode off");
  546. TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
  547. " todev screen");
  548. ResetMocks();
  549. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON |
  550. VBSD_BOOT_DEV_SWITCH_ON;
  551. trust_ec = 1;
  552. shutdown_request_calls_left = 100;
  553. mock_keypress[0] = 0x04;
  554. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  555. VBERROR_SHUTDOWN_REQUESTED,
  556. "Ctrl+D ignored if already in dev mode");
  557. TEST_EQ(virtdev_set, 0, " virtual dev mode off");
  558. TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
  559. " todev screen");
  560. ResetMocks();
  561. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH;
  562. trust_ec = 1;
  563. shutdown_request_calls_left = 100;
  564. mock_keypress[0] = 0x04;
  565. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  566. VBERROR_SHUTDOWN_REQUESTED,
  567. "Ctrl+D ignored if recovery not manually triggered");
  568. TEST_EQ(virtdev_set, 0, " virtual dev mode off");
  569. TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
  570. " todev screen");
  571. ResetMocks();
  572. shared->flags = VBSD_BOOT_REC_SWITCH_ON;
  573. trust_ec = 1;
  574. shutdown_request_calls_left = 100;
  575. mock_keypress[0] = 0x04;
  576. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  577. VBERROR_SHUTDOWN_REQUESTED,
  578. "Ctrl+D ignored if no virtual dev switch");
  579. TEST_EQ(virtdev_set, 0, " virtual dev mode off");
  580. TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
  581. " todev screen");
  582. /* Ctrl+D ignored because the physical recovery switch is still pressed
  583. * and we don't like that.
  584. */
  585. ResetMocks();
  586. shared->flags = VBSD_BOOT_REC_SWITCH_ON;
  587. trust_ec = 1;
  588. shutdown_request_calls_left = 100;
  589. mock_keypress[0] = 0x04;
  590. mock_switches[0] = VB_INIT_FLAG_REC_BUTTON_PRESSED;
  591. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  592. VBERROR_SHUTDOWN_REQUESTED,
  593. "Ctrl+D ignored if phys rec button is still pressed");
  594. TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
  595. " todev screen");
  596. /* Ctrl+D then space means don't enable */
  597. ResetMocks();
  598. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON;
  599. shutdown_request_calls_left = 100;
  600. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  601. trust_ec = 1;
  602. mock_keypress[0] = 0x04;
  603. mock_keypress[1] = ' ';
  604. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  605. VBERROR_SHUTDOWN_REQUESTED,
  606. "Ctrl+D todev abort");
  607. TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
  608. " insert screen");
  609. TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
  610. " todev screen");
  611. TEST_EQ(screens_displayed[2], VB_SCREEN_RECOVERY_INSERT,
  612. " insert screen");
  613. TEST_EQ(virtdev_set, 0, " virtual dev mode off");
  614. /* Ctrl+D then enter means enable */
  615. ResetMocks();
  616. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON;
  617. shutdown_request_calls_left = 100;
  618. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  619. trust_ec = 1;
  620. mock_keypress[0] = 0x04;
  621. mock_keypress[1] = '\r';
  622. mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
  623. TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
  624. "Ctrl+D todev confirm");
  625. TEST_EQ(virtdev_set, 1, " virtual dev mode on");
  626. /* Handle TPM error in enabling dev mode */
  627. ResetMocks();
  628. shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_REC_SWITCH_ON;
  629. shutdown_request_calls_left = 100;
  630. vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
  631. trust_ec = 1;
  632. mock_keypress[0] = 0x04;
  633. mock_keypress[1] = '\r';
  634. mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
  635. virtdev_retval = VBERROR_SIMULATED;
  636. TEST_EQ(VbBootRecovery(&ctx, &cparams),
  637. VBERROR_TPM_SET_BOOT_MODE_STATE,
  638. "Ctrl+D todev failure");
  639. printf("...done.\n");
  640. }
  641. int main(void)
  642. {
  643. VbUserConfirmsTest();
  644. VbBootTest();
  645. VbBootDevTest();
  646. VbBootRecTest();
  647. return gTestSuccess ? 0 : 255;
  648. }