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