Home | History | Annotate | Download | only in tests
      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  */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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