blob: fa13d4e9697d2199000185050492a8c62159695c [file] [log] [blame]
Randall Spangler7f436692013-02-05 12:42:36 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Tests for vboot_api_kernel, part 3 - software sync
6 */
7
Bill Richardson0c3ba242013-03-29 11:09:30 -07008#include <stdint.h>
Randall Spangler7f436692013-02-05 12:42:36 -08009#include <stdio.h>
10#include <stdlib.h>
11
12#include "gbb_header.h"
13#include "host_common.h"
14#include "load_kernel_fw.h"
15#include "rollback_index.h"
16#include "test_common.h"
17#include "vboot_audio.h"
18#include "vboot_common.h"
19#include "vboot_kernel.h"
20#include "vboot_nvstorage.h"
21#include "vboot_struct.h"
22
23/* Mock data */
24static VbCommonParams cparams;
25static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
26static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
27static GoogleBinaryBlockHeader gbb;
28
29static int trust_ec;
30static int mock_in_rw;
31static VbError_t in_rw_retval;
32static int protect_retval;
33static int ec_protected;
34static int run_retval;
35static int ec_run_image;
36static int update_retval;
37static int ec_updated;
38static int get_expected_retval;
Randall Spangler886a9042013-02-11 10:08:51 -080039static int shutdown_request_calls_left;
Randall Spangler7f436692013-02-05 12:42:36 -080040
41static uint8_t mock_ec_hash[32];
42static int mock_ec_hash_size;
43static uint8_t want_ec_hash[32];
44static int want_ec_hash_size;
45static uint8_t mock_sha[32];
46
47static uint32_t screens_displayed[8];
48static uint32_t screens_count = 0;
49
50/* Reset mock data (for use before each test) */
51static void ResetMocks(void)
52{
53 Memset(&cparams, 0, sizeof(cparams));
54 cparams.shared_data_size = sizeof(shared_data);
55 cparams.shared_data_blob = shared_data;
56 cparams.gbb_data = &gbb;
57
58 Memset(&gbb, 0, sizeof(gbb));
59 gbb.major_version = GBB_MAJOR_VER;
60 gbb.minor_version = GBB_MINOR_VER;
61 gbb.flags = 0;
62
63 /*
64 * Only the outermost vboot_api_kernel call sets vboot_api_kernel's
65 * vnc. So clear it here too.
66 */
67 Memset(VbApiKernelGetVnc(), 0, sizeof(VbNvContext));
68 VbNvSetup(VbApiKernelGetVnc());
69 VbNvTeardown(VbApiKernelGetVnc()); /* So CRC gets generated */
70
71 Memset(&shared_data, 0, sizeof(shared_data));
72 VbSharedDataInit(shared, sizeof(shared_data));
73
74 trust_ec = 0;
75 mock_in_rw = 0;
76 ec_protected = 0;
77 ec_run_image = -1; /* 0 = RO, 1 = RW */
78 ec_updated = 0;
79 in_rw_retval = VBERROR_SUCCESS;
80 protect_retval = VBERROR_SUCCESS;
81 update_retval = VBERROR_SUCCESS;
82 run_retval = VBERROR_SUCCESS;
83 get_expected_retval = VBERROR_SUCCESS;
Randall Spangler886a9042013-02-11 10:08:51 -080084 shutdown_request_calls_left = -1;
Randall Spangler7f436692013-02-05 12:42:36 -080085
86 Memset(mock_ec_hash, 0, sizeof(mock_ec_hash));
87 mock_ec_hash[0] = 42;
88 mock_ec_hash_size = sizeof(mock_ec_hash);
89
90 Memset(want_ec_hash, 0, sizeof(want_ec_hash));
91 want_ec_hash[0] = 42;
92 want_ec_hash_size = sizeof(want_ec_hash);
93
94 Memset(mock_sha, 0, sizeof(want_ec_hash));
95 mock_sha[0] = 42;
96
97 // TODO: ensure these are actually needed
98
99 Memset(screens_displayed, 0, sizeof(screens_displayed));
100 screens_count = 0;
101}
102
103/* Mock functions */
104
Randall Spangler886a9042013-02-11 10:08:51 -0800105uint32_t VbExIsShutdownRequested(void)
106{
107 if (shutdown_request_calls_left == 0)
108 return 1;
109 else if (shutdown_request_calls_left > 0)
110 shutdown_request_calls_left--;
111
112 return 0;
113}
114
Randall Spangler7f436692013-02-05 12:42:36 -0800115int VbExTrustEC(void)
116{
117 return trust_ec;
118}
119
120VbError_t VbExEcRunningRW(int *in_rw)
121{
122 *in_rw = mock_in_rw;
123 return in_rw_retval;
124}
125
126VbError_t VbExEcProtectRW(void)
127{
128 ec_protected = 1;
129 return protect_retval;
130}
131
132VbError_t VbExEcStayInRO(void)
133{
134 ec_run_image = 0;
135 return run_retval;
136}
137
138VbError_t VbExEcJumpToRW(void)
139{
140 ec_run_image = 1;
141 return run_retval;
142}
143
144VbError_t VbExEcHashRW(const uint8_t **hash, int *hash_size)
145{
146 *hash = mock_ec_hash;
147 *hash_size = mock_ec_hash_size;
148 return mock_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED;
149}
150
151VbError_t VbExEcGetExpectedRW(enum VbSelectFirmware_t select,
152 const uint8_t **image, int *image_size)
153{
154 static uint8_t fake_image[64] = {5, 6, 7, 8};
155 *image = fake_image;
156 *image_size = sizeof(fake_image);
157 return get_expected_retval;
158}
159
160VbError_t VbExEcGetExpectedRWHash(enum VbSelectFirmware_t select,
161 const uint8_t **hash, int *hash_size)
162{
163 *hash = want_ec_hash;
164 *hash_size = want_ec_hash_size;
165
166 if (want_ec_hash_size == -1)
167 return VBERROR_EC_GET_EXPECTED_HASH_FROM_IMAGE;
168 else
169 return want_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED;
170}
171
172uint8_t *internal_SHA256(const uint8_t *data, uint64_t len, uint8_t *digest)
173{
174 Memcpy(digest, mock_sha, sizeof(mock_sha));
175 return digest;
176}
177
178VbError_t VbExEcUpdateRW(const uint8_t *image, int image_size)
179{
180 ec_updated = 1;
181 return update_retval;
182}
183
184VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force,
185 VbNvContext *vncptr)
186{
187 if (screens_count < ARRAY_SIZE(screens_displayed))
188 screens_displayed[screens_count++] = screen;
189
190 return VBERROR_SUCCESS;
191}
192
193static void test_ssync(VbError_t retval, int recovery_reason, const char *desc)
194{
195 uint32_t u;
196
197 TEST_EQ(VbEcSoftwareSync(&cparams), retval, desc);
198 VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u);
199 TEST_EQ(u, recovery_reason, " recovery reason");
200}
201
202/* Tests */
203
204static void VbSoftwareSyncTest(void)
205{
206 /* Recovery cases */
207 ResetMocks();
208 shared->recovery_reason = 123;
209 test_ssync(0, 0, "In recovery, EC-RO");
210 TEST_EQ(ec_protected, 0, " ec protected");
211
212 ResetMocks();
213 shared->recovery_reason = 123;
214 mock_in_rw = 1;
215 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
216 123, "Recovery needs EC-RO");
217
218 /* AP-RO cases */
219 ResetMocks();
220 in_rw_retval = VBERROR_SIMULATED;
221 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
222 VBNV_RECOVERY_EC_UNKNOWN_IMAGE, "Unknown EC image");
223
224 ResetMocks();
225 shared->flags |= VBSD_LF_USE_RO_NORMAL;
226 mock_in_rw = 1;
227 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
228 0, "AP-RO needs EC-RO");
229
230 ResetMocks();
231 shared->flags |= VBSD_LF_USE_RO_NORMAL;
232 test_ssync(0, 0, "AP-RO, EC-RO");
233 TEST_EQ(ec_protected, 1, " ec protected");
234 TEST_EQ(ec_run_image, 0, " ec run image");
235
236 ResetMocks();
237 shared->flags |= VBSD_LF_USE_RO_NORMAL;
238 run_retval = VBERROR_SIMULATED;
239 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
240 VBNV_RECOVERY_EC_SOFTWARE_SYNC, "Stay in RO fail");
241
242 ResetMocks();
243 shared->flags |= VBSD_LF_USE_RO_NORMAL;
244 protect_retval = VBERROR_SIMULATED;
245 test_ssync(VBERROR_SIMULATED,
246 VBNV_RECOVERY_EC_PROTECT, "Protect error");
247
Randall Spangler19c99692013-06-10 12:31:00 -0700248 /* No longer check for shutdown requested */
Randall Spangler886a9042013-02-11 10:08:51 -0800249 ResetMocks();
250 shared->flags |= VBSD_LF_USE_RO_NORMAL;
251 shutdown_request_calls_left = 0;
Randall Spangler19c99692013-06-10 12:31:00 -0700252 test_ssync(0, 0, "AP-RO shutdown requested");
Randall Spangler886a9042013-02-11 10:08:51 -0800253
Randall Spangler7f436692013-02-05 12:42:36 -0800254 /* Calculate hashes */
255 ResetMocks();
256 mock_ec_hash_size = 0;
257 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
258 VBNV_RECOVERY_EC_HASH_FAILED, "Bad EC hash");
259
260 ResetMocks();
261 mock_ec_hash_size = 16;
262 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
263 VBNV_RECOVERY_EC_HASH_SIZE, "Bad EC hash size");
264
265 ResetMocks();
266 want_ec_hash_size = 0;
267 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
268 VBNV_RECOVERY_EC_EXPECTED_HASH, "Bad precalculated hash");
269
270 ResetMocks();
271 want_ec_hash_size = 16;
272 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
273 VBNV_RECOVERY_EC_EXPECTED_HASH,
274 "Bad precalculated hash size");
275
276 ResetMocks();
277 mock_in_rw = 1;
278 want_ec_hash_size = -1;
279 test_ssync(0, 0, "No precomputed hash");
280
281 ResetMocks();
282 want_ec_hash_size = -1;
283 get_expected_retval = VBERROR_SIMULATED;
284 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
285 VBNV_RECOVERY_EC_EXPECTED_IMAGE, "Can't fetch image");
286
287 /* Updates required */
288 ResetMocks();
289 mock_in_rw = 1;
290 want_ec_hash[0]++;
291 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
292 VBNV_RECOVERY_EC_HASH_MISMATCH,
293 "Precalculated hash mismatch");
294
295 ResetMocks();
296 mock_in_rw = 1;
297 mock_ec_hash[0]++;
298 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
299 0, "Pending update needs reboot");
300
301 ResetMocks();
302 mock_ec_hash[0]++;
303 test_ssync(0, 0, "Update without reboot");
304 TEST_EQ(ec_protected, 1, " ec protected");
305 TEST_EQ(ec_run_image, 1, " ec run image");
306 TEST_EQ(ec_updated, 1, " ec updated");
307
308 ResetMocks();
309 mock_ec_hash[0]++;
310 update_retval = VBERROR_EC_REBOOT_TO_RO_REQUIRED;
311 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
312 0, "Reboot after update");
313 TEST_EQ(ec_updated, 1, " ec updated");
314
315 ResetMocks();
316 mock_ec_hash[0]++;
317 update_retval = VBERROR_SIMULATED;
318 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
319 VBNV_RECOVERY_EC_UPDATE, "Update failed");
320
321 ResetMocks();
322 mock_ec_hash[0]++;
323 shared->flags |= VBSD_EC_SLOW_UPDATE;
324 test_ssync(0, 0, "Slow update");
325 TEST_EQ(screens_displayed[0], VB_SCREEN_WAIT, " wait screen");
326
327 /* RW cases, no update */
328 ResetMocks();
329 mock_in_rw = 1;
330 test_ssync(0, 0, "AP-RW, EC-RW");
331
332 ResetMocks();
333 test_ssync(0, 0, "AP-RW, EC-RO -> EC-RW");
334 TEST_EQ(ec_protected, 1, " ec protected");
335 TEST_EQ(ec_run_image, 1, " ec run image");
336 TEST_EQ(ec_updated, 0, " ec updated");
337
338 ResetMocks();
339 run_retval = VBERROR_SIMULATED;
340 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
341 VBNV_RECOVERY_EC_JUMP_RW, "Jump to RW fail");
342
343 ResetMocks();
344 protect_retval = VBERROR_SIMULATED;
345 test_ssync(VBERROR_SIMULATED,
346 VBNV_RECOVERY_EC_PROTECT, "Protect error");
Randall Spangler886a9042013-02-11 10:08:51 -0800347
Randall Spangler19c99692013-06-10 12:31:00 -0700348 /* No longer check for shutdown requested */
Randall Spangler886a9042013-02-11 10:08:51 -0800349 ResetMocks();
350 shutdown_request_calls_left = 0;
Randall Spangler19c99692013-06-10 12:31:00 -0700351 test_ssync(0, 0,
Randall Spangler886a9042013-02-11 10:08:51 -0800352 "AP-RW, EC-RO -> EC-RW shutdown requested");
353
354 ResetMocks();
355 mock_in_rw = 1;
356 shutdown_request_calls_left = 0;
Randall Spangler19c99692013-06-10 12:31:00 -0700357 test_ssync(0, 0, "AP-RW shutdown requested");
Randall Spangler7f436692013-02-05 12:42:36 -0800358}
359
360int main(void)
361{
362 VbSoftwareSyncTest();
363
Simon Glass25001852013-08-16 02:47:57 -0600364 if (vboot_api_stub_check_memory())
365 return 255;
366
Randall Spangler7f436692013-02-05 12:42:36 -0800367 return gTestSuccess ? 0 : 255;
368}