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 */ 24static VbCommonParams cparams; 25static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 26static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 27static GoogleBinaryBlockHeader gbb; 28static LoadKernelParams lkp; 29 30static int shutdown_request_calls_left; 31static int audio_looping_calls_left; 32static uint32_t vbtlk_retval; 33static int vbexlegacy_called; 34static int trust_ec; 35static int virtdev_set; 36static uint32_t virtdev_retval; 37static uint32_t mock_keypress[8]; 38static uint32_t mock_keyflags[8]; 39static uint32_t mock_keypress_count; 40static uint32_t mock_switches[8]; 41static uint32_t mock_switches_count; 42static int mock_switches_are_stuck; 43static uint32_t screens_displayed[8]; 44static uint32_t screens_count = 0; 45static uint32_t mock_num_disks[8]; 46static uint32_t mock_num_disks_count; 47 48extern enum VbEcBootMode_t VbGetMode(void); 49 50/* Reset mock data (for use before each test) */ 51static 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 102uint32_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 112uint32_t VbExKeyboardRead(void) 113{ 114 return VbExKeyboardReadWithFlags(NULL); 115} 116 117uint32_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 127uint32_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 137int VbExLegacy(void) 138{ 139 vbexlegacy_called++; 140 return 0; 141} 142 143VbError_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 157VbError_t VbExDiskFreeInfo(VbDiskInfo *infos, 158 VbExDiskHandle_t preserve_handle) 159{ 160 return VBERROR_SUCCESS; 161} 162 163int VbExTrustEC(int devidx) 164{ 165 return trust_ec; 166} 167 168int 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 178uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p, 179 uint32_t get_info_flags) 180{ 181 return vbtlk_retval + get_info_flags; 182} 183 184VbError_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 193uint32_t SetVirtualDevMode(int val) 194{ 195 virtdev_set = val; 196 return virtdev_retval; 197} 198 199/* Tests */ 200 201static 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 264static 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 272static 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 448static 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 662int 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