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