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