• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) */
ResetMocks(void)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 
VbExNvStorageRead(uint8_t * buf)81 VbError_t VbExNvStorageRead(uint8_t *buf)
82 {
83 	Memcpy(buf, vnc.raw, sizeof(vnc.raw));
84 	return VBERROR_SUCCESS;
85 }
86 
VbExNvStorageWrite(const uint8_t * buf)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 
RollbackBackupRead(uint8_t * raw)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 
RollbackBackupWrite(uint8_t * raw)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 
VbExGetTimer(void)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 
RollbackS3Resume(void)120 uint32_t RollbackS3Resume(void)
121 {
122 	return rollback_s3_retval;
123 }
124 
RollbackFirmwareSetup(int is_hw_dev,int disable_dev_request,int clear_tpm_owner_request,int * is_virt_dev,uint32_t * version)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 
TestVbInit(VbError_t expected_retval,uint8_t expected_recovery,const char * desc)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 
VbInitTest(void)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 
VbInitTestTPM(void)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 
VbInitTestBackup(void)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 
main(int argc,char * argv[])760 int main(int argc, char *argv[])
761 {
762 	VbInitTest();
763 	VbInitTestTPM();
764 	VbInitTestBackup();
765 
766 	return gTestSuccess ? 0 : 255;
767 }
768