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_init 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 "rollback_index.h" 15 #include "test_common.h" 16 #include "vboot_common.h" 17 #include "vboot_nvstorage.h" 18 #include "vboot_struct.h" 19 20 /* Mock data */ 21 static VbCommonParams cparams; 22 static VbInitParams iparams; 23 static VbNvContext vnc; 24 static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 25 static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 26 static uint64_t mock_timer; 27 static int rollback_s3_retval; 28 static int nv_write_called; 29 static GoogleBinaryBlockHeader gbb; 30 static int mock_virt_dev_sw; 31 static uint32_t mock_tpm_version; 32 static uint32_t mock_rfs_retval; 33 static int rfs_clear_tpm_request; 34 static int rfs_disable_dev_request; 35 static uint8_t backup_space[BACKUP_NV_SIZE]; 36 static int backup_write_called; 37 static int backup_read_called; 38 39 /* Reset mock data (for use before each test) */ 40 static void ResetMocks(void) 41 { 42 Memset(&cparams, 0, sizeof(cparams)); 43 cparams.shared_data_size = sizeof(shared_data); 44 cparams.shared_data_blob = shared_data; 45 cparams.gbb_data = &gbb; 46 cparams.gbb_size = sizeof(gbb); 47 48 Memset(&gbb, 0, sizeof(gbb)); 49 gbb.major_version = GBB_MAJOR_VER; 50 gbb.minor_version = GBB_MINOR_VER; 51 gbb.flags = 0; 52 53 Memset(&iparams, 0, sizeof(iparams)); 54 55 Memset(&vnc, 0, sizeof(vnc)); 56 VbNvSetup(&vnc); 57 VbNvTeardown(&vnc); /* So CRC gets generated */ 58 59 Memset(backup_space, 0, sizeof(backup_space)); 60 backup_write_called = 0; 61 backup_read_called = 0; 62 63 Memset(&shared_data, 0, sizeof(shared_data)); 64 VbSharedDataInit(shared, sizeof(shared_data)); 65 66 mock_timer = 10; 67 rollback_s3_retval = TPM_SUCCESS; 68 nv_write_called = 0; 69 70 mock_virt_dev_sw = 0; 71 mock_tpm_version = 0x10001; 72 mock_rfs_retval = 0; 73 74 rfs_clear_tpm_request = 0; 75 rfs_disable_dev_request = 0; 76 } 77 78 /****************************************************************************/ 79 /* Mocked verification functions */ 80 81 VbError_t VbExNvStorageRead(uint8_t *buf) 82 { 83 Memcpy(buf, vnc.raw, sizeof(vnc.raw)); 84 return VBERROR_SUCCESS; 85 } 86 87 VbError_t VbExNvStorageWrite(const uint8_t *buf) 88 { 89 nv_write_called++; 90 Memcpy(vnc.raw, buf, sizeof(vnc.raw)); 91 return VBERROR_SUCCESS; 92 } 93 94 uint32_t RollbackBackupRead(uint8_t *raw) 95 { 96 backup_read_called++; 97 Memcpy(raw, backup_space, sizeof(backup_space)); 98 return TPM_SUCCESS; 99 } 100 101 uint32_t RollbackBackupWrite(uint8_t *raw) 102 { 103 backup_write_called++; 104 Memcpy(backup_space, raw, sizeof(backup_space)); 105 return TPM_SUCCESS; 106 } 107 108 uint64_t VbExGetTimer(void) 109 { 110 /* 111 * Exponential-ish rather than linear time, so that subtracting any 112 * two mock values will yield a unique result. 113 */ 114 uint64_t new_timer = mock_timer * 2 + 1; 115 VbAssert(new_timer > mock_timer); /* Make sure we don't overflow */ 116 mock_timer = new_timer; 117 return mock_timer; 118 } 119 120 uint32_t RollbackS3Resume(void) 121 { 122 return rollback_s3_retval; 123 } 124 125 uint32_t RollbackFirmwareSetup(int is_hw_dev, 126 int disable_dev_request, 127 int clear_tpm_owner_request, 128 /* two outputs on success */ 129 int *is_virt_dev, uint32_t *version) 130 { 131 rfs_clear_tpm_request = clear_tpm_owner_request; 132 rfs_disable_dev_request = disable_dev_request; 133 134 *is_virt_dev = mock_virt_dev_sw; 135 *version = mock_tpm_version; 136 return mock_rfs_retval; 137 } 138 139 /****************************************************************************/ 140 /* Test VbInit() and check expected return value and recovery reason */ 141 142 static void TestVbInit(VbError_t expected_retval, 143 uint8_t expected_recovery, const char *desc) 144 { 145 uint32_t rr = 256; 146 147 TEST_EQ(VbInit(&cparams, &iparams), expected_retval, desc); 148 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &rr); 149 TEST_EQ(rr, expected_recovery, " (recovery request)"); 150 } 151 152 /****************************************************************************/ 153 154 static void VbInitTest(void) 155 { 156 uint32_t u; 157 158 /* Test passing in too small a shared data area */ 159 ResetMocks(); 160 cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE - 1; 161 TestVbInit(VBERROR_INIT_SHARED_DATA, 0, "Shared data too small"); 162 163 /* Normal call; dev=0 rec=0 */ 164 ResetMocks(); 165 TestVbInit(0, 0, "Normal call"); 166 TEST_EQ(shared->timer_vb_init_enter, 21, " time enter"); 167 TEST_EQ(shared->timer_vb_init_exit, 43, " time exit"); 168 TEST_EQ(shared->flags, 0, " shared flags"); 169 TEST_EQ(iparams.out_flags, 0, " out flags"); 170 TEST_EQ(nv_write_called, 0, 171 " NV write not called since nothing changed"); 172 173 /* If NV data is trashed, we initialize it */ 174 ResetMocks(); 175 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); 176 /* 177 * Note that we're not doing a VbNvTeardown(), so the CRC hasn't been 178 * regenerated yet. So VbInit() should ignore the corrupted recovery 179 * value and boot normally. 180 */ 181 TestVbInit(0, 0, "NV data trashed"); 182 TEST_EQ(nv_write_called, 1, " NV write called"); 183 184 /* 185 * Test boot switch flags which are just passed through to shared 186 * flags, and don't have an effect on VbInit(). 187 */ 188 ResetMocks(); 189 iparams.flags = VB_INIT_FLAG_WP_ENABLED; 190 TestVbInit(0, 0, "Flags test WP"); 191 TEST_EQ(shared->flags, VBSD_BOOT_FIRMWARE_WP_ENABLED, 192 " shared flags"); 193 194 ResetMocks(); 195 iparams.flags = VB_INIT_FLAG_SW_WP_ENABLED; 196 TestVbInit(0, 0, "Flags test SW WP"); 197 TEST_EQ(shared->flags, VBSD_BOOT_FIRMWARE_SW_WP_ENABLED, 198 " shared flags"); 199 200 ResetMocks(); 201 iparams.flags = VB_INIT_FLAG_RO_NORMAL_SUPPORT; 202 TestVbInit(0, 0, " flags test RO normal"); 203 TEST_EQ(shared->flags, VBSD_BOOT_RO_NORMAL_SUPPORT, 204 " shared flags"); 205 206 ResetMocks(); 207 iparams.flags = VB_INIT_FLAG_EC_SOFTWARE_SYNC; 208 TestVbInit(0, 0, " flags test EC software sync"); 209 TEST_EQ(shared->flags, VBSD_EC_SOFTWARE_SYNC, " shared flags"); 210 211 ResetMocks(); 212 iparams.flags = VB_INIT_FLAG_EC_SLOW_UPDATE; 213 TestVbInit(0, 0, " flags test EC slow update"); 214 TEST_EQ(shared->flags, VBSD_EC_SLOW_UPDATE, " shared flags"); 215 216 /* S3 resume */ 217 ResetMocks(); 218 iparams.flags = VB_INIT_FLAG_S3_RESUME; 219 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); 220 VbNvTeardown(&vnc); 221 /* S3 resume doesn't clear the recovery request (or act on it) */ 222 TestVbInit(0, 123, "S3 resume"); 223 TEST_EQ(shared->flags, VBSD_BOOT_S3_RESUME, " shared flags S3"); 224 TEST_EQ(iparams.out_flags, 0, " out flags"); 225 TEST_EQ(shared->recovery_reason, 0, 226 " S3 doesn't look at recovery request"); 227 228 /* S3 resume with TPM resume error */ 229 ResetMocks(); 230 iparams.flags = VB_INIT_FLAG_S3_RESUME; 231 rollback_s3_retval = 1; 232 /* S3 resume doesn't clear the recovery request (or act on it) */ 233 TestVbInit(VBERROR_TPM_S3_RESUME, 0, "S3 resume rollback error"); 234 235 /* 236 * Normal boot doesn't care about TPM resume error because it doesn't 237 * call RollbackS3Resume(). 238 */ 239 ResetMocks(); 240 rollback_s3_retval = 1; 241 TestVbInit(0, 0, "Normal doesn't S3 resume"); 242 243 /* S3 resume with debug reset */ 244 ResetMocks(); 245 iparams.flags = VB_INIT_FLAG_S3_RESUME; 246 VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1); 247 VbNvTeardown(&vnc); 248 TestVbInit(0, 0, "S3 debug reset"); 249 TEST_EQ(iparams.out_flags, VB_INIT_OUT_S3_DEBUG_BOOT, " out flags"); 250 VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &u); 251 TEST_EQ(u, 0, " S3 clears nv debug reset mode"); 252 253 /* Normal boot clears S3 debug reset mode; doesn't set output flag */ 254 ResetMocks(); 255 VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1); 256 VbNvTeardown(&vnc); 257 TestVbInit(0, 0, "Normal with debug reset mode"); 258 TEST_EQ(iparams.out_flags, 0, " out flags"); 259 VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &u); 260 TEST_EQ(u, 0, " normal clears nv debug reset mode"); 261 262 /* 263 * S3 resume with debug reset is a normal boot, so doesn't resume the 264 * TPM. 265 */ 266 ResetMocks(); 267 iparams.flags = VB_INIT_FLAG_S3_RESUME; 268 rollback_s3_retval = 1; 269 VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1); 270 VbNvTeardown(&vnc); 271 TestVbInit(0, 0, "S3 debug reset rollback error"); 272 273 /* Developer mode */ 274 ResetMocks(); 275 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON; 276 TestVbInit(0, 0, "Dev mode on"); 277 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 278 TEST_EQ(iparams.out_flags, 279 VB_INIT_OUT_CLEAR_RAM | 280 VB_INIT_OUT_ENABLE_DISPLAY | 281 VB_INIT_OUT_ENABLE_USB_STORAGE | 282 VB_INIT_OUT_ENABLE_DEVELOPER | 283 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); 284 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); 285 286 /* Developer mode forced by GBB flag */ 287 ResetMocks(); 288 iparams.flags = 0; 289 gbb.flags = GBB_FLAG_FORCE_DEV_SWITCH_ON; 290 TestVbInit(0, 0, "Dev mode via GBB"); 291 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 292 TEST_EQ(iparams.out_flags, 293 VB_INIT_OUT_CLEAR_RAM | 294 VB_INIT_OUT_ENABLE_DISPLAY | 295 VB_INIT_OUT_ENABLE_USB_STORAGE | 296 VB_INIT_OUT_ENABLE_DEVELOPER | 297 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); 298 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); 299 300 /* Developer mode when option ROM matters and isn't loaded */ 301 ResetMocks(); 302 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON | 303 VB_INIT_FLAG_OPROM_MATTERS; 304 TestVbInit(VBERROR_VGA_OPROM_MISMATCH, 0, "Dev mode need oprom"); 305 VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u); 306 TEST_EQ(u, 1, " oprom requested"); 307 308 /* Developer mode when option ROM matters and is already loaded */ 309 ResetMocks(); 310 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON | 311 VB_INIT_FLAG_OPROM_MATTERS | VB_INIT_FLAG_OPROM_LOADED; 312 TestVbInit(0, 0, "Dev mode has oprom"); 313 314 /* Normal mode when option ROM matters and is loaded */ 315 ResetMocks(); 316 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1); 317 VbNvTeardown(&vnc); 318 iparams.flags = VB_INIT_FLAG_OPROM_MATTERS | VB_INIT_FLAG_OPROM_LOADED; 319 TestVbInit(VBERROR_VGA_OPROM_MISMATCH, 0, "Normal mode with oprom"); 320 VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u); 321 TEST_EQ(u, 0, " oprom not requested"); 322 323 /* Option ROMs can be forced by GBB flag */ 324 ResetMocks(); 325 gbb.flags = GBB_FLAG_LOAD_OPTION_ROMS; 326 TestVbInit(0, 0, "GBB load option ROMs"); 327 TEST_EQ(iparams.out_flags, VB_INIT_OUT_ENABLE_OPROM, " out flags"); 328 329 /* If requiring signed only, don't enable alternate OS by default */ 330 ResetMocks(); 331 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1); 332 VbNvTeardown(&vnc); 333 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON; 334 TestVbInit(0, 0, "Dev signed only"); 335 TEST_EQ(iparams.out_flags, 336 VB_INIT_OUT_CLEAR_RAM | 337 VB_INIT_OUT_ENABLE_DISPLAY | 338 VB_INIT_OUT_ENABLE_USB_STORAGE | 339 VB_INIT_OUT_ENABLE_DEVELOPER, " out flags"); 340 341 /* But that can be overridden by the GBB */ 342 ResetMocks(); 343 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1); 344 VbNvTeardown(&vnc); 345 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON; 346 gbb.flags = GBB_FLAG_ENABLE_ALTERNATE_OS; 347 TestVbInit(0, 0, "Force option ROMs via GBB"); 348 TEST_EQ(iparams.out_flags, 349 VB_INIT_OUT_CLEAR_RAM | 350 VB_INIT_OUT_ENABLE_DISPLAY | 351 VB_INIT_OUT_ENABLE_USB_STORAGE | 352 VB_INIT_OUT_ENABLE_DEVELOPER | 353 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); 354 355 /* The GBB override is ignored in normal mode */ 356 ResetMocks(); 357 gbb.flags = GBB_FLAG_ENABLE_ALTERNATE_OS; 358 TestVbInit(0, 0, "Normal mode ignores forcing option ROMs via GBB"); 359 TEST_EQ(iparams.out_flags, 0, " out flags"); 360 361 /* Recovery mode from NV storage */ 362 ResetMocks(); 363 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); 364 VbNvTeardown(&vnc); 365 TestVbInit(0, 0, "Recovery mode - from nv"); 366 TEST_EQ(shared->recovery_reason, 123, " recovery reason"); 367 TEST_EQ(iparams.out_flags, 368 VB_INIT_OUT_ENABLE_RECOVERY | 369 VB_INIT_OUT_CLEAR_RAM | 370 VB_INIT_OUT_ENABLE_DISPLAY | 371 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags"); 372 TEST_EQ(shared->flags, 0, " shared flags"); 373 374 /* Recovery mode from recovery button */ 375 ResetMocks(); 376 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED; 377 TestVbInit(0, 0, "Recovery mode - button"); 378 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL, 379 " recovery reason"); 380 TEST_EQ(iparams.out_flags, 381 VB_INIT_OUT_ENABLE_RECOVERY | 382 VB_INIT_OUT_CLEAR_RAM | 383 VB_INIT_OUT_ENABLE_DISPLAY | 384 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags"); 385 TEST_EQ(shared->flags, VBSD_BOOT_REC_SWITCH_ON, " shared flags"); 386 387 /* Recovery button reason supersedes NV reason */ 388 ResetMocks(); 389 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED; 390 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); 391 VbNvTeardown(&vnc); 392 TestVbInit(0, 0, "Recovery mode - button AND nv"); 393 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL, 394 " recovery reason"); 395 396 /* Recovery mode from previous boot fail */ 397 ResetMocks(); 398 iparams.flags = VB_INIT_FLAG_PREVIOUS_BOOT_FAIL; 399 TestVbInit(0, 0, "Recovery mode - previous boot fail"); 400 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_FIRMWARE, 401 " recovery reason"); 402 TEST_EQ(iparams.out_flags, 403 VB_INIT_OUT_ENABLE_RECOVERY | 404 VB_INIT_OUT_CLEAR_RAM | 405 VB_INIT_OUT_ENABLE_DISPLAY | 406 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags"); 407 TEST_EQ(shared->flags, 0, " shared flags"); 408 409 /* Recovery mode from NV supersedes previous boot fail */ 410 ResetMocks(); 411 iparams.flags = VB_INIT_FLAG_PREVIOUS_BOOT_FAIL; 412 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); 413 VbNvTeardown(&vnc); 414 TestVbInit(0, 0, "Recovery mode - previous boot fail AND nv"); 415 TEST_EQ(shared->recovery_reason, 123, " recovery reason"); 416 417 /* Dev + recovery = recovery */ 418 ResetMocks(); 419 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED | 420 VB_INIT_FLAG_DEV_SWITCH_ON; 421 TestVbInit(0, 0, "Recovery mode - button"); 422 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL, 423 " recovery reason"); 424 TEST_EQ(iparams.out_flags, 425 VB_INIT_OUT_ENABLE_RECOVERY | 426 VB_INIT_OUT_CLEAR_RAM | 427 VB_INIT_OUT_ENABLE_DISPLAY | 428 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags"); 429 TEST_EQ(shared->flags, 430 VBSD_BOOT_REC_SWITCH_ON | VBSD_BOOT_DEV_SWITCH_ON, 431 " shared flags"); 432 } 433 434 static void VbInitTestTPM(void) 435 { 436 uint32_t u; 437 438 /* Rollback setup needs to reboot */ 439 ResetMocks(); 440 mock_rfs_retval = TPM_E_MUST_REBOOT; 441 TestVbInit(VBERROR_TPM_REBOOT_REQUIRED, 0, 442 "Rollback TPM reboot (rec=0)"); 443 ResetMocks(); 444 mock_rfs_retval = TPM_E_MUST_REBOOT; 445 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED; 446 TestVbInit(VBERROR_TPM_REBOOT_REQUIRED, VBNV_RECOVERY_RO_TPM_REBOOT, 447 "Rollback TPM reboot, in recovery, first time"); 448 /* Ignore if we already tried rebooting */ 449 ResetMocks(); 450 mock_rfs_retval = TPM_E_MUST_REBOOT; 451 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_REBOOT); 452 VbNvTeardown(&vnc); 453 TestVbInit(0, 0, "Rollback TPM reboot, in recovery, already retried"); 454 TEST_EQ(shared->fw_version_tpm, 0x10001, " shared fw_version_tpm"); 455 456 /* Other rollback setup errors */ 457 ResetMocks(); 458 mock_rfs_retval = TPM_E_IOERROR; 459 mock_tpm_version = 0x20002; 460 TestVbInit(VBERROR_TPM_FIRMWARE_SETUP, VBNV_RECOVERY_RO_TPM_S_ERROR, 461 "Rollback TPM setup error - not in recovery"); 462 TEST_EQ(shared->fw_version_tpm, 0, " shared fw_version_tpm not set"); 463 ResetMocks(); 464 mock_rfs_retval = TPM_E_IOERROR; 465 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_US_TEST); 466 VbNvTeardown(&vnc); 467 TestVbInit(0, 0, "Rollback TPM setup error ignored in recovery"); 468 TEST_EQ(shared->fw_version_tpm, 0x10001, " shared fw_version_tpm"); 469 470 /* Virtual developer switch, but not enabled. */ 471 ResetMocks(); 472 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 1); 473 VbNvTeardown(&vnc); 474 iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH; 475 TestVbInit(0, 0, "TPM Dev mode off"); 476 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 477 TEST_EQ(iparams.out_flags, 0, " out flags"); 478 TEST_EQ(shared->flags, VBSD_HONOR_VIRT_DEV_SWITCH, " shared flags"); 479 VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &u); 480 TEST_EQ(u, 0, " disable dev request"); 481 482 /* Virtual developer switch, enabled. */ 483 ResetMocks(); 484 VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 1); 485 VbNvTeardown(&vnc); 486 iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH; 487 mock_virt_dev_sw = 1; 488 TestVbInit(0, 0, "TPM Dev mode on"); 489 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 490 TEST_EQ(iparams.out_flags, 491 VB_INIT_OUT_CLEAR_RAM | 492 VB_INIT_OUT_ENABLE_DISPLAY | 493 VB_INIT_OUT_ENABLE_USB_STORAGE | 494 VB_INIT_OUT_ENABLE_DEVELOPER | 495 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); 496 TEST_EQ(shared->flags, 497 VBSD_BOOT_DEV_SWITCH_ON | VBSD_HONOR_VIRT_DEV_SWITCH, 498 " shared flags"); 499 /* Disable-request doesn't get cleared because dev mode is still on */ 500 VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &u); 501 TEST_EQ(u, 1, " disable dev request"); 502 /* Disable request was passed on to RollbackFirmwareSetup() */ 503 TEST_EQ(rfs_disable_dev_request, 1, " rfs disable dev"); 504 505 /* Ignore virtual developer switch, even though enabled. */ 506 ResetMocks(); 507 mock_virt_dev_sw = 1; 508 TestVbInit(0, 0, "TPM Dev mode on but ignored"); 509 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 510 TEST_EQ(iparams.out_flags, 0, " out flags"); 511 TEST_EQ(shared->flags, 0, " shared flags"); 512 513 /* HW dev switch on, no virtual developer switch */ 514 ResetMocks(); 515 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON; 516 TestVbInit(0, 0, "HW Dev mode on"); 517 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 518 TEST_EQ(iparams.out_flags, 519 VB_INIT_OUT_CLEAR_RAM | 520 VB_INIT_OUT_ENABLE_DISPLAY | 521 VB_INIT_OUT_ENABLE_USB_STORAGE | 522 VB_INIT_OUT_ENABLE_DEVELOPER | 523 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); 524 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); 525 526 /* Check TPM owner clear request */ 527 ResetMocks(); 528 VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 1); 529 VbNvTeardown(&vnc); 530 TestVbInit(0, 0, "TPM clear owner"); 531 VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, &u); 532 TEST_EQ(u, 0, " tpm clear request"); 533 VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_DONE, &u); 534 TEST_EQ(u, 1, " tpm clear request"); 535 TEST_EQ(rfs_clear_tpm_request, 1, "rfs tpm clear request"); 536 } 537 538 static void VbInitTestBackup(void) 539 { 540 VbNvContext tmp_vnc; 541 uint32_t u, nv_w, bu_r; 542 543 ResetMocks(); 544 /* Normal mode call */ 545 TestVbInit(0, 0, "normal mode, no backup"); 546 TEST_EQ(shared->flags, 0, " shared flags"); 547 TEST_EQ(iparams.out_flags, 0, " out flags"); 548 TEST_EQ(nv_write_called, 0, 549 " NV write not called since nothing changed"); 550 551 ResetMocks(); 552 /* Now set some params that should be backed up. */ 553 VbNvSet(&vnc, VBNV_KERNEL_FIELD, 0xaabbccdd); 554 VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0xa5); 555 VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 1); 556 VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 1); 557 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1); 558 /* and some that don't */ 559 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1); 560 VbNvSet(&vnc, VBNV_TRY_B_COUNT, 3); 561 /* Make sure they're clean */ 562 VbNvTeardown(&vnc); 563 /* Normal mode call */ 564 TestVbInit(0, 0, "normal mode, some backup"); 565 TEST_EQ(shared->flags, 0, " shared flags"); 566 TEST_EQ(iparams.out_flags, 0, " out flags"); 567 TEST_EQ(nv_write_called, 1, 568 " Write NV because things have changed"); 569 /* Some fields should be unchanged */ 570 VbNvGet(&vnc, VBNV_KERNEL_FIELD, &u); 571 TEST_EQ(u, 0xaabbccdd, " NV kernel field"); 572 VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); 573 TEST_EQ(u, 0xa5, " NV localization index"); 574 VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u); 575 TEST_EQ(u, 1, " NV oprom_needed"); 576 VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u); 577 TEST_EQ(u, 3, " NV try_b_count"); 578 /* But normal mode should have cleared the DEV_BOOT flags */ 579 VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &u); 580 TEST_EQ(u, 0, " NV dev_boot_usb"); 581 VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &u); 582 TEST_EQ(u, 0, " NV dev_boot_legacy"); 583 VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u); 584 TEST_EQ(u, 0, " NV dev_boot_signed_only"); 585 /* So we should have written the backup */ 586 TEST_EQ(backup_write_called, 1, " Backup written once"); 587 /* And the backup should reflect the persisent flags. */ 588 Memset(&tmp_vnc, 0, sizeof(tmp_vnc)); 589 TEST_EQ(0, RestoreNvFromBackup(&tmp_vnc), "read from backup"); 590 VbNvGet(&tmp_vnc, VBNV_KERNEL_FIELD, &u); 591 TEST_EQ(u, 0xaabbccdd, " BU kernel field"); 592 VbNvGet(&tmp_vnc, VBNV_LOCALIZATION_INDEX, &u); 593 TEST_EQ(u, 0xa5, " BU localization index"); 594 VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_USB, &u); 595 TEST_EQ(u, 0, " BU dev_boot_usb"); 596 VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_LEGACY, &u); 597 TEST_EQ(u, 0, " BU dev_boot_legacy"); 598 VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u); 599 TEST_EQ(u, 0, " BU dev_boot_signed_only"); 600 /* but not the others */ 601 VbNvGet(&tmp_vnc, VBNV_OPROM_NEEDED, &u); 602 TEST_EQ(u, 0, " BU oprom_needed"); 603 VbNvGet(&tmp_vnc, VBNV_TRY_B_COUNT, &u); 604 TEST_EQ(u, 0, " BU try_b_count"); 605 606 /* 607 * If we change one of the non-backed-up NVRAM params and try 608 * again, we shouldn't need to backup again. 609 */ 610 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0); 611 VbNvSet(&vnc, VBNV_TRY_B_COUNT, 2); 612 /* Make sure they're clean */ 613 VbNvTeardown(&vnc); 614 /* Normal mode call */ 615 TestVbInit(0, 0, "normal mode, expect no backup"); 616 TEST_EQ(shared->flags, 0, " shared flags"); 617 TEST_EQ(iparams.out_flags, 0, " out flags"); 618 TEST_EQ(backup_write_called, 1, " Backup still only written once"); 619 620 /* Now switch to dev-mode. */ 621 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON; 622 TestVbInit(0, 0, "Dev mode on"); 623 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 624 TEST_EQ(iparams.out_flags, 625 VB_INIT_OUT_CLEAR_RAM | 626 VB_INIT_OUT_ENABLE_DISPLAY | 627 VB_INIT_OUT_ENABLE_USB_STORAGE | 628 VB_INIT_OUT_ENABLE_DEVELOPER | 629 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags"); 630 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); 631 TEST_EQ(backup_write_called, 1, " Still only one backup"); 632 633 /* Now change some params that should be backed up. */ 634 VbNvSet(&vnc, VBNV_KERNEL_FIELD, 0xdeadbeef); 635 VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0x5a); 636 VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 1); 637 VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 1); 638 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1); 639 /* and some that don't */ 640 VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1); 641 VbNvSet(&vnc, VBNV_TRY_B_COUNT, 4); 642 /* Make sure they're clean */ 643 VbNvTeardown(&vnc); 644 TestVbInit(0, 0, "Dev mode on"); 645 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 646 TEST_EQ(iparams.out_flags, 647 VB_INIT_OUT_CLEAR_RAM | 648 VB_INIT_OUT_ENABLE_DISPLAY | 649 VB_INIT_OUT_ENABLE_USB_STORAGE | 650 VB_INIT_OUT_ENABLE_DEVELOPER, " out flags"); 651 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); 652 TEST_EQ(backup_write_called, 1, " Once more, one backup"); 653 654 /* But if we explictly request a backup, they'll get saved. */ 655 VbNvSet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, 1); 656 VbNvTeardown(&vnc); 657 TestVbInit(0, 0, "Dev mode on"); 658 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 659 TEST_EQ(iparams.out_flags, 660 VB_INIT_OUT_CLEAR_RAM | 661 VB_INIT_OUT_ENABLE_DISPLAY | 662 VB_INIT_OUT_ENABLE_USB_STORAGE | 663 VB_INIT_OUT_ENABLE_DEVELOPER, " out flags"); 664 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); 665 TEST_EQ(backup_write_called, 2, " Two backups now"); 666 VbNvGet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, &u); 667 TEST_EQ(u, 0, " backup_request cleared"); 668 /* Quick check that the non-backed-up stuff is still valid */ 669 VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u); 670 TEST_EQ(u, 1, " NV oprom_needed"); 671 VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u); 672 TEST_EQ(u, 4, " NV try_b_count"); 673 /* But only the stuff we care about was backed up */ 674 Memset(&tmp_vnc, 0, sizeof(tmp_vnc)); 675 TEST_EQ(0, RestoreNvFromBackup(&tmp_vnc), "read from backup"); 676 VbNvGet(&tmp_vnc, VBNV_KERNEL_FIELD, &u); 677 TEST_EQ(u, 0xdeadbeef, " BU kernel field"); 678 VbNvGet(&tmp_vnc, VBNV_LOCALIZATION_INDEX, &u); 679 TEST_EQ(u, 0x5a, " BU localization index"); 680 VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_USB, &u); 681 TEST_EQ(u, 1, " BU dev_boot_usb"); 682 VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_LEGACY, &u); 683 TEST_EQ(u, 1, " BU dev_boot_legacy"); 684 VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u); 685 TEST_EQ(u, 1, " BU dev_boot_signed_only"); 686 /* but not the others */ 687 VbNvGet(&tmp_vnc, VBNV_OPROM_NEEDED, &u); 688 TEST_EQ(u, 0, " BU oprom_needed"); 689 VbNvGet(&tmp_vnc, VBNV_TRY_B_COUNT, &u); 690 TEST_EQ(u, 0, " BU try_b_count"); 691 692 /* If we lose the NV storage, the backup bits will be restored */ 693 vnc.raw[0] = 0; 694 bu_r = backup_read_called; 695 nv_w = nv_write_called; 696 TestVbInit(0, 0, "Dev mode on"); 697 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 698 TEST_EQ(iparams.out_flags, 699 VB_INIT_OUT_CLEAR_RAM | 700 VB_INIT_OUT_ENABLE_DISPLAY | 701 VB_INIT_OUT_ENABLE_USB_STORAGE | 702 VB_INIT_OUT_ENABLE_DEVELOPER, " out flags"); 703 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags"); 704 TEST_EQ(backup_write_called, 2, " Still just two backups now"); 705 TEST_EQ(backup_read_called, bu_r + 1, " One more backup read"); 706 TEST_EQ(nv_write_called, nv_w + 1, " One more NV write"); 707 /* The non-backed-up stuff is reset to defaults */ 708 VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u); 709 TEST_EQ(u, 0, " NV oprom_needed"); 710 VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u); 711 TEST_EQ(u, 0, " NV try_b_count"); 712 /* And the backed up stuff is restored */ 713 VbNvGet(&vnc, VBNV_KERNEL_FIELD, &u); 714 TEST_EQ(u, 0xdeadbeef, " BU kernel field"); 715 VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); 716 TEST_EQ(u, 0x5a, " BU localization index"); 717 VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &u); 718 TEST_EQ(u, 1, " BU dev_boot_usb"); 719 VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &u); 720 TEST_EQ(u, 1, " BU dev_boot_legacy"); 721 VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u); 722 TEST_EQ(u, 1, " BU dev_boot_signed_only"); 723 724 /* 725 * But if we lose the NV storage and go back to normal mode at the same 726 * time, then the DEV_BOOT_* flags will be cleared. 727 */ 728 vnc.raw[0] = 0; 729 bu_r = backup_read_called; 730 nv_w = nv_write_called; 731 iparams.flags = 0; 732 TestVbInit(0, 0, "Back to normal mode"); 733 TEST_EQ(shared->recovery_reason, 0, " recovery reason"); 734 TEST_EQ(iparams.out_flags, 0, " out flags"); 735 TEST_EQ(shared->flags, 0, " shared flags"); 736 /* We read twice: once to restore, once for read-prior-to-write */ 737 TEST_EQ(backup_read_called, bu_r + 2, " Two more backup reads"); 738 TEST_EQ(backup_write_called, 3, " Backup write due clearing DEV_*"); 739 TEST_EQ(nv_write_called, nv_w + 1, " One more NV write"); 740 /* The non-backed-up stuff is reset to defaults */ 741 VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u); 742 TEST_EQ(u, 0, " NV oprom_needed"); 743 VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u); 744 TEST_EQ(u, 0, " NV try_b_count"); 745 /* And the backed up stuff is restored */ 746 VbNvGet(&vnc, VBNV_KERNEL_FIELD, &u); 747 TEST_EQ(u, 0xdeadbeef, " BU kernel field"); 748 VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); 749 TEST_EQ(u, 0x5a, " BU localization index"); 750 /* But not the DEV_BOOT_* flags */ 751 VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &u); 752 TEST_EQ(u, 0, " BU dev_boot_usb"); 753 VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &u); 754 TEST_EQ(u, 0, " BU dev_boot_legacy"); 755 VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u); 756 TEST_EQ(u, 0, " BU dev_boot_signed_only"); 757 } 758 759 760 int main(int argc, char *argv[]) 761 { 762 VbInitTest(); 763 VbInitTestTPM(); 764 VbInitTestBackup(); 765 766 return gTestSuccess ? 0 : 255; 767 } 768