Home | History | Annotate | Download | only in tests
      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