blob: dd6daee4b08f0d18e3be89a520aaa0bf45e29412 [file] [log] [blame]
Randall Spangleracd6f462012-06-13 16:43:59 -07001/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Randall Spangler391b3102011-09-02 11:28:24 -07002 * 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 <stdio.h>
9#include <stdlib.h>
10
Bill Richardsonc8e4ff72011-11-10 13:31:39 -080011#include "gbb_header.h"
Randall Spangler391b3102011-09-02 11:28:24 -070012#include "host_common.h"
13#include "rollback_index.h"
14#include "test_common.h"
15#include "vboot_common.h"
16#include "vboot_nvstorage.h"
17#include "vboot_struct.h"
18
19/* Mock data */
20static VbCommonParams cparams;
21static VbInitParams iparams;
22static VbNvContext vnc;
23static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
24static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data;
25static uint64_t mock_timer;
26static int rollback_s3_retval;
27static int nv_write_called;
Bill Richardsonc8e4ff72011-11-10 13:31:39 -080028static GoogleBinaryBlockHeader gbb;
Bill Richardsonec8df162012-06-07 04:21:14 -070029static int mock_virt_dev_sw;
Bill Richardsonb75d8ad2012-05-17 13:26:05 -070030static uint32_t mock_tpm_version;
31static uint32_t mock_rfs_retval;
Randall Spangler391b3102011-09-02 11:28:24 -070032
33/* Reset mock data (for use before each test) */
34static void ResetMocks(void) {
35 Memset(&cparams, 0, sizeof(cparams));
36 cparams.shared_data_size = sizeof(shared_data);
37 cparams.shared_data_blob = shared_data;
Bill Richardsonc8e4ff72011-11-10 13:31:39 -080038 cparams.gbb_data = &gbb;
39
40 Memset(&gbb, 0, sizeof(gbb));
41 gbb.major_version = GBB_MAJOR_VER;
42 gbb.minor_version = GBB_MINOR_VER;
43 gbb.flags = 0;
Randall Spangler391b3102011-09-02 11:28:24 -070044
45 Memset(&iparams, 0, sizeof(iparams));
46
47 Memset(&vnc, 0, sizeof(vnc));
48 VbNvSetup(&vnc);
Bill Richardsonb75d8ad2012-05-17 13:26:05 -070049 VbNvTeardown(&vnc); /* So CRC gets generated */
Randall Spangler391b3102011-09-02 11:28:24 -070050
51 Memset(&shared_data, 0, sizeof(shared_data));
52 VbSharedDataInit(shared, sizeof(shared_data));
53
54 mock_timer = 10;
55 rollback_s3_retval = TPM_SUCCESS;
56 nv_write_called = 0;
Bill Richardsonb75d8ad2012-05-17 13:26:05 -070057
Bill Richardsonec8df162012-06-07 04:21:14 -070058 mock_virt_dev_sw = 0;
Bill Richardsonb75d8ad2012-05-17 13:26:05 -070059 mock_tpm_version = 0x10001;
60 mock_rfs_retval = 0;
Randall Spangler391b3102011-09-02 11:28:24 -070061}
62
63/****************************************************************************/
64/* Mocked verification functions */
65
66VbError_t VbExNvStorageRead(uint8_t* buf) {
67 Memcpy(buf, vnc.raw, sizeof(vnc.raw));
68 return VBERROR_SUCCESS;
69}
70
71VbError_t VbExNvStorageWrite(const uint8_t* buf) {
72 nv_write_called = 1;
73 Memcpy(vnc.raw, buf, sizeof(vnc.raw));
74 return VBERROR_SUCCESS;
75}
76
77uint64_t VbExGetTimer(void) {
78 /* Exponential-ish rather than linear time, so that subtracting any
79 * two mock values will yield a unique result. */
80 uint64_t new_timer = mock_timer * 2 + 1;
81 VbAssert(new_timer > mock_timer); /* Make sure we don't overflow */
82 mock_timer = new_timer;
83 return mock_timer;
84}
85
86uint32_t RollbackS3Resume(void) {
87 return rollback_s3_retval;
88}
89
Bill Richardsonec8df162012-06-07 04:21:14 -070090uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev,
91 int disable_dev_request,
Randall Spangler29e88072012-06-19 10:03:53 -070092 int clear_tpm_owner_request,
Bill Richardsonec8df162012-06-07 04:21:14 -070093 /* two outputs on success */
94 int *is_virt_dev, uint32_t *version) {
95 *is_virt_dev = mock_virt_dev_sw;
Bill Richardsonb75d8ad2012-05-17 13:26:05 -070096 *version = mock_tpm_version;
97 return mock_rfs_retval;
98}
99
Randall Spangler391b3102011-09-02 11:28:24 -0700100/****************************************************************************/
101/* Test VbInit() and check expected return value and recovery reason */
102static void TestVbInit(VbError_t expected_retval,
103 uint8_t expected_recovery, const char* desc) {
104 uint32_t rr = 256;
105
106 TEST_EQ(VbInit(&cparams, &iparams), expected_retval, desc);
107 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &rr);
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700108 TEST_EQ(rr, expected_recovery, " (recovery request)");
Randall Spangler391b3102011-09-02 11:28:24 -0700109}
110
111/****************************************************************************/
112
113static void VbInitTest(void) {
114 uint32_t u;
115
116 /* Test passing in too small a shared data area */
117 ResetMocks();
118 cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE - 1;
119 TestVbInit(VBERROR_INIT_SHARED_DATA, 0, "Shared data too small");
120
121 /* Normal call; dev=0 rec=0 */
122 ResetMocks();
123 TestVbInit(0, 0, "Normal call");
124 TEST_EQ(shared->timer_vb_init_enter, 21, " time enter");
125 TEST_EQ(shared->timer_vb_init_exit, 43, " time exit");
126 TEST_EQ(shared->flags, 0, " shared flags");
127 TEST_EQ(iparams.out_flags, 0, " out flags");
128 TEST_EQ(nv_write_called, 0, " NV write not called since nothing changed");
129
130 /* If NV data is trashed, we initialize it */
131 ResetMocks();
132 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
133 /* Note that we're not doing a VbNvTeardown(), so the CRC hasn't
134 * been regenerated yet. So VbInit() should ignore the corrupted
135 * recovery value and boot normally. */
136 TestVbInit(0, 0, "NV data trashed");
137 TEST_EQ(nv_write_called, 1, " NV write called");
138
139 /* Test boot switch flags which are just passed through to shared
140 * flags, and don't have an effect on VbInit(). */
141 ResetMocks();
142 iparams.flags = VB_INIT_FLAG_WP_ENABLED;
143 TestVbInit(0, 0, "Flags test WP");
144 TEST_EQ(shared->flags, VBSD_BOOT_FIRMWARE_WP_ENABLED, " shared flags WP");
145
146 ResetMocks();
Bill Richardson9dc62172012-08-28 15:00:51 -0700147 iparams.flags = VB_INIT_FLAG_SW_WP_ENABLED;
148 TestVbInit(0, 0, "Flags test SW WP");
149 TEST_EQ(shared->flags, VBSD_BOOT_FIRMWARE_SW_WP_ENABLED,
150 " shared flags SW WP");
151
152 ResetMocks();
Randall Spangler391b3102011-09-02 11:28:24 -0700153 iparams.flags = VB_INIT_FLAG_RO_NORMAL_SUPPORT;
154 TestVbInit(0, 0, " flags test RO normal");
155 TEST_EQ(shared->flags, VBSD_BOOT_RO_NORMAL_SUPPORT,
156 " shared flags RO normal");
157
158 /* S3 resume */
159 ResetMocks();
160 iparams.flags = VB_INIT_FLAG_S3_RESUME;
161 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
162 VbNvTeardown(&vnc);
163 /* S3 resume doesn't clear the recovery request (or act on it) */
164 TestVbInit(0, 123, "S3 resume");
165 TEST_EQ(shared->flags, VBSD_BOOT_S3_RESUME, " shared flags S3");
166 TEST_EQ(iparams.out_flags, 0, " out flags");
167 TEST_EQ(shared->recovery_reason, 0, " S3 doesn't look at recovery request");
168
169 /* S3 resume with TPM resume error */
170 ResetMocks();
171 iparams.flags = VB_INIT_FLAG_S3_RESUME;
172 rollback_s3_retval = 1;
173 /* S3 resume doesn't clear the recovery request (or act on it) */
174 TestVbInit(VBERROR_TPM_S3_RESUME, 0, "S3 resume rollback error");
175
176 /* Normal boot doesn't care about TPM resume error because it
177 * doesn't call RollbackS3Resume() */
178 ResetMocks();
179 rollback_s3_retval = 1;
180 TestVbInit(0, 0, "Normal doesn't S3 resume");
181
182 /* S3 resume with debug reset */
183 ResetMocks();
184 iparams.flags = VB_INIT_FLAG_S3_RESUME;
185 VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1);
186 VbNvTeardown(&vnc);
187 TestVbInit(0, 0, "S3 debug reset");
188 TEST_EQ(iparams.out_flags, VB_INIT_OUT_S3_DEBUG_BOOT, " out flags");
189 VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &u);
190 TEST_EQ(u, 0, " S3 clears nv debug reset mode");
191
192 /* Normal boot clears S3 debug reset mode, but doesn't set output flag */
193 ResetMocks();
194 VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1);
195 VbNvTeardown(&vnc);
196 TestVbInit(0, 0, "Normal with debug reset mode");
197 TEST_EQ(iparams.out_flags, 0, " out flags");
198 VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &u);
199 TEST_EQ(u, 0, " normal clears nv debug reset mode");
200
201 /* S3 resume with debug reset is a normal boot, so doesn't resume the TPM */
202 ResetMocks();
203 iparams.flags = VB_INIT_FLAG_S3_RESUME;
204 rollback_s3_retval = 1;
205 VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1);
206 VbNvTeardown(&vnc);
207 TestVbInit(0, 0, "S3 debug reset rollback error");
208
209 /* Developer mode */
210 ResetMocks();
211 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON;
212 TestVbInit(0, 0, "Dev mode on");
213 TEST_EQ(shared->recovery_reason, 0, " recovery reason");
214 TEST_EQ(iparams.out_flags,
215 VB_INIT_OUT_CLEAR_RAM |
216 VB_INIT_OUT_ENABLE_DISPLAY |
Bill Richardson7272a692011-11-17 10:48:59 -0800217 VB_INIT_OUT_ENABLE_USB_STORAGE |
Bill Richardson45de9c92012-07-10 20:08:13 -0700218 VB_INIT_OUT_ENABLE_DEVELOPER |
Bill Richardson7272a692011-11-17 10:48:59 -0800219 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
Randall Spangler391b3102011-09-02 11:28:24 -0700220 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
221
Randall Spangleracd6f462012-06-13 16:43:59 -0700222 /* Developer mode forced by GBB flag */
223 ResetMocks();
224 iparams.flags = 0;
225 gbb.flags = GBB_FLAG_FORCE_DEV_SWITCH_ON;
226 TestVbInit(0, 0, "Dev mode via GBB");
227 TEST_EQ(shared->recovery_reason, 0, " recovery reason");
228 TEST_EQ(iparams.out_flags,
229 VB_INIT_OUT_CLEAR_RAM |
230 VB_INIT_OUT_ENABLE_DISPLAY |
231 VB_INIT_OUT_ENABLE_USB_STORAGE |
Bill Richardson45de9c92012-07-10 20:08:13 -0700232 VB_INIT_OUT_ENABLE_DEVELOPER |
Randall Spangleracd6f462012-06-13 16:43:59 -0700233 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
234 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
235
Randall Spangler391b3102011-09-02 11:28:24 -0700236 /* Recovery mode from NV storage */
237 ResetMocks();
238 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
239 VbNvTeardown(&vnc);
240 TestVbInit(0, 0, "Recovery mode - from nv");
241 TEST_EQ(shared->recovery_reason, 123, " recovery reason");
242 TEST_EQ(iparams.out_flags,
243 VB_INIT_OUT_ENABLE_RECOVERY |
244 VB_INIT_OUT_CLEAR_RAM |
245 VB_INIT_OUT_ENABLE_DISPLAY |
246 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
247 TEST_EQ(shared->flags, 0, " shared flags");
248
249 /* Recovery mode from recovery button */
250 ResetMocks();
251 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED;
252 TestVbInit(0, 0, "Recovery mode - button");
253 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL,
254 " recovery reason");
255 TEST_EQ(iparams.out_flags,
256 VB_INIT_OUT_ENABLE_RECOVERY |
257 VB_INIT_OUT_CLEAR_RAM |
258 VB_INIT_OUT_ENABLE_DISPLAY |
259 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
260 TEST_EQ(shared->flags, VBSD_BOOT_REC_SWITCH_ON, " shared flags");
261
262 /* Recovery button reason supersedes NV reason */
263 ResetMocks();
264 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED;
265 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
266 VbNvTeardown(&vnc);
267 TestVbInit(0, 0, "Recovery mode - button AND nv");
268 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL,
269 " recovery reason");
270
271 /* Recovery mode from previous boot fail */
272 ResetMocks();
273 iparams.flags = VB_INIT_FLAG_PREVIOUS_BOOT_FAIL;
274 TestVbInit(0, 0, "Recovery mode - previous boot fail");
275 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_FIRMWARE,
276 " recovery reason");
277 TEST_EQ(iparams.out_flags,
278 VB_INIT_OUT_ENABLE_RECOVERY |
279 VB_INIT_OUT_CLEAR_RAM |
280 VB_INIT_OUT_ENABLE_DISPLAY |
281 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
282 TEST_EQ(shared->flags, 0, " shared flags");
283
284 /* Recovery mode from NV supersedes previous boot fail */
285 ResetMocks();
286 iparams.flags = VB_INIT_FLAG_PREVIOUS_BOOT_FAIL;
287 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
288 VbNvTeardown(&vnc);
289 TestVbInit(0, 0, "Recovery mode - previous boot fail AND nv");
290 TEST_EQ(shared->recovery_reason, 123, " recovery reason");
291
292 /* Dev + recovery = recovery */
293 ResetMocks();
294 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED | VB_INIT_FLAG_DEV_SWITCH_ON;
295 TestVbInit(0, 0, "Recovery mode - button");
296 TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL,
297 " recovery reason");
298 TEST_EQ(iparams.out_flags,
299 VB_INIT_OUT_ENABLE_RECOVERY |
300 VB_INIT_OUT_CLEAR_RAM |
301 VB_INIT_OUT_ENABLE_DISPLAY |
302 VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
303 TEST_EQ(shared->flags,
304 VBSD_BOOT_REC_SWITCH_ON | VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
305}
306
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700307static void VbInitTestTPM(void) {
308
309 /* Rollback setup needs to reboot */
310 ResetMocks();
311 mock_rfs_retval = TPM_E_MUST_REBOOT;
312 TestVbInit(VBERROR_TPM_REBOOT_REQUIRED, 0, "Rollback TPM reboot (rec=0)");
313 ResetMocks();
314 mock_rfs_retval = TPM_E_MUST_REBOOT;
315 iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED;
316 TestVbInit(VBERROR_TPM_REBOOT_REQUIRED, VBNV_RECOVERY_RO_TPM_REBOOT,
317 "Rollback TPM reboot, in recovery, first time");
318 /* Ignore if we already tried rebooting */
319 ResetMocks();
320 mock_rfs_retval = TPM_E_MUST_REBOOT;
321 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_REBOOT);
322 VbNvTeardown(&vnc);
323 TestVbInit(0, 0, "Rollback TPM reboot, in recovery, already retried");
324 TEST_EQ(shared->fw_version_tpm, 0x10001, " shared fw_version_tpm");
325
326 /* Other rollback setup errors */
327 ResetMocks();
328 mock_rfs_retval = TPM_E_IOERROR;
329 mock_tpm_version = 0x20002;
Bill Richardson640b1c42012-11-21 15:22:26 -0800330 TestVbInit(VBERROR_TPM_FIRMWARE_SETUP, VBNV_RECOVERY_RO_TPM_S_ERROR,
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700331 "Rollback TPM setup error - not in recovery");
332 TEST_EQ(shared->fw_version_tpm, 0, " shared fw_version_tpm not set");
333 ResetMocks();
334 mock_rfs_retval = TPM_E_IOERROR;
335 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_US_TEST);
336 VbNvTeardown(&vnc);
337 TestVbInit(0, 0, "Rollback TPM setup error ignored in recovery");
338 TEST_EQ(shared->fw_version_tpm, 0x10001, " shared fw_version_tpm");
339
340 /* Virtual developer switch, but not enabled. */
341 ResetMocks();
Bill Richardsonec8df162012-06-07 04:21:14 -0700342 iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700343 TestVbInit(0, 0, "TPM Dev mode off");
344 TEST_EQ(shared->recovery_reason, 0, " recovery reason");
345 TEST_EQ(iparams.out_flags, 0, " out flags");
Bill Richardsonec8df162012-06-07 04:21:14 -0700346 TEST_EQ(shared->flags, VBSD_HONOR_VIRT_DEV_SWITCH, " shared flags");
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700347
348 /* Virtual developer switch, enabled. */
349 ResetMocks();
350 iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
Bill Richardsonec8df162012-06-07 04:21:14 -0700351 mock_virt_dev_sw = 1;
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700352 TestVbInit(0, 0, "TPM Dev mode on");
353 TEST_EQ(shared->recovery_reason, 0, " recovery reason");
354 TEST_EQ(iparams.out_flags,
355 VB_INIT_OUT_CLEAR_RAM |
356 VB_INIT_OUT_ENABLE_DISPLAY |
357 VB_INIT_OUT_ENABLE_USB_STORAGE |
Bill Richardson45de9c92012-07-10 20:08:13 -0700358 VB_INIT_OUT_ENABLE_DEVELOPER |
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700359 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
Bill Richardsonec8df162012-06-07 04:21:14 -0700360 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON | VBSD_HONOR_VIRT_DEV_SWITCH,
361 " shared flags");
362
363 /* Ignore virtual developer switch, even though enabled. */
364 ResetMocks();
365 mock_virt_dev_sw = 1;
366 TestVbInit(0, 0, "TPM Dev mode on but ignored");
367 TEST_EQ(shared->recovery_reason, 0, " recovery reason");
368 TEST_EQ(iparams.out_flags, 0, " out flags");
369 TEST_EQ(shared->flags, 0, " shared flags");
370
371 /* HW dev switch on, no virtual developer switch */
372 ResetMocks();
373 iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON;
374 TestVbInit(0, 0, "HW Dev mode on");
375 TEST_EQ(shared->recovery_reason, 0, " recovery reason");
376 TEST_EQ(iparams.out_flags,
377 VB_INIT_OUT_CLEAR_RAM |
378 VB_INIT_OUT_ENABLE_DISPLAY |
379 VB_INIT_OUT_ENABLE_USB_STORAGE |
Bill Richardson45de9c92012-07-10 20:08:13 -0700380 VB_INIT_OUT_ENABLE_DEVELOPER |
Bill Richardsonec8df162012-06-07 04:21:14 -0700381 VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700382 TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
383}
384
Randall Spangler391b3102011-09-02 11:28:24 -0700385
386/* disable MSVC warnings on unused arguments */
387__pragma(warning (disable: 4100))
388
389int main(int argc, char* argv[]) {
390 int error_code = 0;
391
392 VbInitTest();
Bill Richardsonb75d8ad2012-05-17 13:26:05 -0700393 VbInitTestTPM();
Randall Spangler391b3102011-09-02 11:28:24 -0700394
395 if (!gTestSuccess)
396 error_code = 255;
397
398 return error_code;
399}