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 VbTryLoadKernel()
6 */
7
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 #include "gbb_header.h"
14 #include "load_kernel_fw.h"
15 #include "rollback_index.h"
16 #include "test_common.h"
17 #include "utility.h"
18 #include "vboot_api.h"
19 #include "vboot_kernel.h"
20
21 #define MAX_TEST_DISKS 10
22 #define DEFAULT_COUNT -1
23
24 typedef struct {
25 uint64_t bytes_per_lba;
26 uint64_t lba_count;
27 uint32_t flags;
28 const char *diskname;
29 } disk_desc_t;
30
31 typedef struct {
32 char *name;
33
34 /* inputs for test case */
35 uint32_t want_flags;
36 VbError_t diskgetinfo_return_val;
37 disk_desc_t disks_to_provide[MAX_TEST_DISKS];
38 int disk_count_to_return;
39 VbError_t loadkernel_return_val[MAX_TEST_DISKS];
40 uint8_t external_expected[MAX_TEST_DISKS];
41
42 /* outputs from test */
43 uint32_t expected_recovery_request_val;
44 const char *expected_to_find_disk;
45 const char *expected_to_load_disk;
46 uint32_t expected_return_val;
47
48 } test_case_t;
49
50 /****************************************************************************/
51 /* Test cases */
52
53 static const char pickme[] = "correct choice";
54 #define DONT_CARE ((const char *)42)
55
56 test_case_t test[] = {
57 {
58 .name = "first removable drive",
59 .want_flags = VB_DISK_FLAG_REMOVABLE,
60 .disks_to_provide = {
61 /* too small */
62 {512, 10, VB_DISK_FLAG_REMOVABLE, 0},
63 /* wrong LBA */
64 {2048, 100, VB_DISK_FLAG_REMOVABLE, 0},
65 /* wrong type */
66 {512, 100, VB_DISK_FLAG_FIXED, 0},
67 /* wrong flags */
68 {512, 100, 0, 0},
69 /* still wrong flags */
70 {512, 100, -1, 0},
71 {512, 100,
72 VB_DISK_FLAG_REMOVABLE | VB_DISK_FLAG_EXTERNAL_GPT,
73 pickme},
74 /* already got one */
75 {512, 100, VB_DISK_FLAG_REMOVABLE, "holygrail"},
76 },
77 .disk_count_to_return = DEFAULT_COUNT,
78 .diskgetinfo_return_val = VBERROR_SUCCESS,
79 .loadkernel_return_val = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
80 .external_expected = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
81
82 .expected_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED,
83 .expected_to_find_disk = pickme,
84 .expected_to_load_disk = pickme,
85 .expected_return_val = VBERROR_SUCCESS
86 },
87 {
88 .name = "second removable drive",
89 .want_flags = VB_DISK_FLAG_REMOVABLE,
90 .disks_to_provide = {
91 /* wrong flags */
92 {512, 100, 0, 0},
93 {512, 100, VB_DISK_FLAG_REMOVABLE, "not yet"},
94 {512, 100, VB_DISK_FLAG_REMOVABLE, pickme},
95 },
96 .disk_count_to_return = DEFAULT_COUNT,
97 .diskgetinfo_return_val = VBERROR_SUCCESS,
98 .loadkernel_return_val = {1, 0, 1, 1, 1, 1, 1, 1, 1, 1,},
99
100 .expected_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED,
101 .expected_to_find_disk = pickme,
102 .expected_to_load_disk = pickme,
103 .expected_return_val = VBERROR_SUCCESS
104 },
105 {
106 .name = "first fixed drive",
107 .want_flags = VB_DISK_FLAG_FIXED,
108 .disks_to_provide = {
109 /* too small */
110 {512, 10, VB_DISK_FLAG_FIXED, 0},
111 /* wrong LBA */
112 {2048, 100, VB_DISK_FLAG_FIXED, 0},
113 /* wrong type */
114 {512, 100, VB_DISK_FLAG_REMOVABLE, 0},
115 /* wrong flags */
116 {512, 100, 0, 0},
117 /* still wrong flags */
118 {512, 100, -1, 0},
119 /* flags */
120 {512, 100, VB_DISK_FLAG_REMOVABLE|VB_DISK_FLAG_FIXED,
121 0},
122 {512, 100, VB_DISK_FLAG_FIXED, pickme},
123 /* already got one */
124 {512, 100, VB_DISK_FLAG_FIXED, "holygrail"},
125 },
126 .disk_count_to_return = DEFAULT_COUNT,
127 .diskgetinfo_return_val = VBERROR_SUCCESS,
128 .loadkernel_return_val = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
129
130 .expected_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED,
131 .expected_to_find_disk = pickme,
132 .expected_to_load_disk = pickme,
133 .expected_return_val = VBERROR_SUCCESS
134 },
135 {
136 .name = "no drives at all",
137 .want_flags = VB_DISK_FLAG_FIXED,
138 .disks_to_provide = {},
139 .disk_count_to_return = DEFAULT_COUNT,
140 .diskgetinfo_return_val = VBERROR_SUCCESS,
141 .loadkernel_return_val = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
142
143 .expected_recovery_request_val = VBNV_RECOVERY_RW_NO_DISK,
144 .expected_to_find_disk = 0,
145 .expected_to_load_disk = 0,
146 .expected_return_val = VBERROR_NO_DISK_FOUND
147 },
148 {
149 .name = "no valid drives",
150 .want_flags = VB_DISK_FLAG_FIXED,
151 .disks_to_provide = {
152 /* too small */
153 {512, 10, VB_DISK_FLAG_FIXED, 0},
154 /* wrong LBA */
155 {2048, 100, VB_DISK_FLAG_FIXED, 0},
156 /* wrong type */
157 {512, 100, VB_DISK_FLAG_REMOVABLE, 0},
158 /* wrong flags */
159 {512, 100, 0, 0},
160 /* still wrong flags */
161 {512, 100, -1, 0},
162 /* doesn't load */
163 {512, 100, VB_DISK_FLAG_FIXED, "bad1"},
164 /* doesn't load */
165 {512, 100, VB_DISK_FLAG_FIXED, "bad2"},
166 },
167 .disk_count_to_return = DEFAULT_COUNT,
168 .diskgetinfo_return_val = VBERROR_SUCCESS,
169 .loadkernel_return_val = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
170
171 .expected_recovery_request_val = VBNV_RECOVERY_RW_NO_KERNEL,
172 .expected_to_find_disk = DONT_CARE,
173 .expected_to_load_disk = 0,
174 .expected_return_val = 1
175 },
176 };
177
178 /****************************************************************************/
179
180 /* Mock data */
181 static LoadKernelParams lkparams;
182 static VbDiskInfo mock_disks[MAX_TEST_DISKS];
183 static test_case_t *t;
184 static int load_kernel_calls;
185 static uint32_t got_recovery_request_val;
186 static const char *got_find_disk;
187 static const char *got_load_disk;
188 static uint32_t got_return_val;
189 static uint32_t got_external_mismatch;
190
191 /**
192 * Reset mock data (for use before each test)
193 */
ResetMocks(int i)194 static void ResetMocks(int i)
195 {
196 Memset(&lkparams, 0, sizeof(lkparams));
197 Memset(&mock_disks, 0, sizeof(mock_disks));
198 load_kernel_calls = 0;
199
200 got_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED;
201 got_find_disk = 0;
202 got_load_disk = 0;
203 got_return_val = 0xdeadbeef;
204
205 t = test + i;
206 }
207
is_nonzero(const void * vptr,size_t count)208 int is_nonzero(const void *vptr, size_t count)
209 {
210 const char *p = (const char *)vptr;
211 while (count--)
212 if (*p++)
213 return 1;
214
215 return 0;
216 }
217
218 /****************************************************************************/
219 /* Mocked verification functions */
220
VbExDiskGetInfo(VbDiskInfo ** infos_ptr,uint32_t * count,uint32_t disk_flags)221 VbError_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count,
222 uint32_t disk_flags)
223 {
224 int i;
225 int num_disks = 0;
226
227 VBDEBUG(("My %s\n", __FUNCTION__));
228
229 *infos_ptr = mock_disks;
230
231 for(i = 0; i < MAX_TEST_DISKS; i++) {
232 if (is_nonzero(&t->disks_to_provide[i],
233 sizeof(t->disks_to_provide[i]))) {
234 mock_disks[num_disks].bytes_per_lba =
235 t->disks_to_provide[i].bytes_per_lba;
236 mock_disks[num_disks].lba_count =
237 mock_disks[num_disks].streaming_lba_count =
238 t->disks_to_provide[i].lba_count;
239 mock_disks[num_disks].flags =
240 t->disks_to_provide[i].flags;
241 mock_disks[num_disks].handle = (VbExDiskHandle_t)
242 t->disks_to_provide[i].diskname;
243 VBDEBUG((" mock_disk[%d] %" PRIu64 " %" PRIu64
244 " 0x%x %s\n", i,
245 mock_disks[num_disks].bytes_per_lba,
246 mock_disks[num_disks].lba_count,
247 mock_disks[num_disks].flags,
248 (mock_disks[num_disks].handle
249 ? (char *)mock_disks[num_disks].handle
250 : "0")));
251 num_disks++;
252 } else {
253 mock_disks[num_disks].handle =
254 (VbExDiskHandle_t)"INVALID";
255 }
256 }
257
258 if (t->disk_count_to_return >= 0)
259 *count = t->disk_count_to_return;
260 else
261 *count = num_disks;
262
263 VBDEBUG((" *count=%" PRIu32 "\n", *count));
264 VBDEBUG((" return 0x%x\n", t->diskgetinfo_return_val));
265
266 return t->diskgetinfo_return_val;
267 }
268
VbExDiskFreeInfo(VbDiskInfo * infos,VbExDiskHandle_t preserve_handle)269 VbError_t VbExDiskFreeInfo(VbDiskInfo *infos,
270 VbExDiskHandle_t preserve_handle)
271 {
272 got_load_disk = (const char *)preserve_handle;
273 VBDEBUG(("%s(): got_load_disk = %s\n", __FUNCTION__,
274 got_load_disk ? got_load_disk : "0"));
275 return VBERROR_SUCCESS;
276 }
277
LoadKernel(LoadKernelParams * params,VbCommonParams * cparams)278 VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams)
279 {
280 got_find_disk = (const char *)params->disk_handle;
281 VBDEBUG(("%s(%d): got_find_disk = %s\n", __FUNCTION__,
282 load_kernel_calls,
283 got_find_disk ? got_find_disk : "0"));
284 if (t->external_expected[load_kernel_calls] !=
285 !!(params->boot_flags & BOOT_FLAG_EXTERNAL_GPT))
286 got_external_mismatch++;
287 return t->loadkernel_return_val[load_kernel_calls++];
288 }
289
VbNvSet(VbNvContext * context,VbNvParam param,uint32_t value)290 int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value)
291 {
292 VBDEBUG(("%s(): got_recovery_request_val = %d (0x%x)\n", __FUNCTION__,
293 value, value));
294 got_recovery_request_val = value;
295 return 0;
296 }
297
298 /****************************************************************************/
299
VbTryLoadKernelTest(void)300 static void VbTryLoadKernelTest(void)
301 {
302 int i;
303 int num_tests = sizeof(test) / sizeof(test[0]);
304
305 for (i = 0; i < num_tests; i++) {
306 printf("Test case: %s ...\n", test[i].name);
307 ResetMocks(i);
308 TEST_EQ(VbTryLoadKernel(0, &lkparams, test[i].want_flags),
309 t->expected_return_val, " return value");
310 TEST_EQ(got_recovery_request_val,
311 t->expected_recovery_request_val, " recovery_request");
312 if (t->expected_to_find_disk != DONT_CARE) {
313 TEST_PTR_EQ(got_find_disk, t->expected_to_find_disk,
314 " find disk");
315 TEST_PTR_EQ(got_load_disk, t->expected_to_load_disk,
316 " load disk");
317 }
318 TEST_EQ(got_external_mismatch, 0, " external GPT errors");
319 }
320 }
321
main(void)322 int main(void)
323 {
324 VbTryLoadKernelTest();
325
326 if (vboot_api_stub_check_memory())
327 return 255;
328
329 return gTestSuccess ? 0 : 255;
330 }
331