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 vboot_api_kernel, part 4 - select and load kernel 6 */ 7 8 #include <stdint.h> 9 #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 */ 24 static VbCommonParams cparams; 25 static VbSelectAndLoadKernelParams kparams; 26 static VbNvContext vnc; 27 static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 28 static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 29 static GoogleBinaryBlockHeader gbb; 30 31 static int ecsync_retval; 32 static uint32_t rkr_version; 33 static uint32_t new_version; 34 static int rkr_retval, rkw_retval, rkl_retval; 35 static VbError_t vbboot_retval; 36 37 /* Reset mock data (for use before each test) */ 38 static void ResetMocks(void) 39 { 40 Memset(&cparams, 0, sizeof(cparams)); 41 cparams.shared_data_size = sizeof(shared_data); 42 cparams.shared_data_blob = shared_data; 43 cparams.gbb_data = &gbb; 44 cparams.gbb_size = sizeof(gbb); 45 46 Memset(&kparams, 0, sizeof(kparams)); 47 48 Memset(&gbb, 0, sizeof(gbb)); 49 gbb.major_version = GBB_MAJOR_VER; 50 gbb.minor_version = GBB_MINOR_VER; 51 gbb.flags = 0; 52 53 Memset(&vnc, 0, sizeof(vnc)); 54 VbNvSetup(&vnc); 55 VbNvTeardown(&vnc); /* So CRC gets generated */ 56 57 Memset(&shared_data, 0, sizeof(shared_data)); 58 VbSharedDataInit(shared, sizeof(shared_data)); 59 60 ecsync_retval = VBERROR_SUCCESS; 61 rkr_version = new_version = 0x10002; 62 rkr_retval = rkw_retval = rkl_retval = VBERROR_SUCCESS; 63 vbboot_retval = VBERROR_SUCCESS; 64 } 65 66 /* Mock functions */ 67 68 VbError_t VbExNvStorageRead(uint8_t *buf) 69 { 70 Memcpy(buf, vnc.raw, sizeof(vnc.raw)); 71 return VBERROR_SUCCESS; 72 } 73 74 VbError_t VbExNvStorageWrite(const uint8_t *buf) 75 { 76 Memcpy(vnc.raw, buf, sizeof(vnc.raw)); 77 return VBERROR_SUCCESS; 78 } 79 80 VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams) 81 { 82 return ecsync_retval; 83 } 84 85 uint32_t RollbackKernelRead(uint32_t *version) 86 { 87 *version = rkr_version; 88 return rkr_retval; 89 } 90 91 uint32_t RollbackKernelWrite(uint32_t version) 92 { 93 TEST_EQ(version, new_version, "RollbackKernelWrite new version"); 94 rkr_version = version; 95 return rkw_retval; 96 } 97 98 uint32_t RollbackKernelLock(int recovery_mode) 99 { 100 return rkl_retval; 101 } 102 103 VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p) 104 { 105 shared->kernel_version_tpm = new_version; 106 107 if (vbboot_retval == -1) 108 return VBERROR_SIMULATED; 109 110 return vbboot_retval; 111 } 112 113 VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p) 114 { 115 shared->kernel_version_tpm = new_version; 116 117 if (vbboot_retval == -2) 118 return VBERROR_SIMULATED; 119 120 return vbboot_retval; 121 } 122 123 VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p) 124 { 125 shared->kernel_version_tpm = new_version; 126 127 if (vbboot_retval == -3) 128 return VBERROR_SIMULATED; 129 130 return vbboot_retval; 131 } 132 133 static void test_slk(VbError_t retval, int recovery_reason, const char *desc) 134 { 135 uint32_t u; 136 137 TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams), retval, desc); 138 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u); 139 TEST_EQ(u, recovery_reason, " recovery reason"); 140 } 141 142 /* Tests */ 143 144 static void VbSlkTest(void) 145 { 146 ResetMocks(); 147 test_slk(0, 0, "Normal"); 148 149 /* Software sync */ 150 ResetMocks(); 151 shared->flags |= VBSD_EC_SOFTWARE_SYNC; 152 ecsync_retval = VBERROR_SIMULATED; 153 test_slk(VBERROR_SIMULATED, 0, "EC sync bad"); 154 155 ResetMocks(); 156 ecsync_retval = VBERROR_SIMULATED; 157 test_slk(0, 0, "EC sync not done"); 158 159 ResetMocks(); 160 shared->flags |= VBSD_EC_SOFTWARE_SYNC; 161 gbb.flags |= GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC; 162 ecsync_retval = VBERROR_SIMULATED; 163 test_slk(0, 0, "EC sync disabled by GBB"); 164 165 /* Rollback kernel version */ 166 ResetMocks(); 167 rkr_retval = 123; 168 test_slk(VBERROR_TPM_READ_KERNEL, 169 VBNV_RECOVERY_RW_TPM_R_ERROR, "Read kernel rollback"); 170 171 ResetMocks(); 172 new_version = 0x20003; 173 test_slk(0, 0, "Roll forward"); 174 TEST_EQ(rkr_version, 0x20003, " version"); 175 176 ResetMocks(); 177 new_version = 0x20003; 178 shared->flags |= VBSD_FWB_TRIED; 179 shared->firmware_index = 1; 180 test_slk(0, 0, "Don't roll forward during try B"); 181 TEST_EQ(rkr_version, 0x10002, " version"); 182 183 ResetMocks(); 184 vbboot_retval = VBERROR_INVALID_KERNEL_FOUND; 185 VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); 186 VbNvTeardown(&vnc); 187 shared->flags |= VBSD_FWB_TRIED; 188 shared->firmware_index = 1; 189 test_slk(VBERROR_INVALID_KERNEL_FOUND, 190 0, "Don't go to recovery if try b fails to find a kernel"); 191 192 ResetMocks(); 193 new_version = 0x20003; 194 rkw_retval = 123; 195 test_slk(VBERROR_TPM_WRITE_KERNEL, 196 VBNV_RECOVERY_RW_TPM_W_ERROR, "Write kernel rollback"); 197 198 ResetMocks(); 199 rkl_retval = 123; 200 test_slk(VBERROR_TPM_LOCK_KERNEL, 201 VBNV_RECOVERY_RW_TPM_L_ERROR, "Lock kernel rollback"); 202 203 /* Boot normal */ 204 ResetMocks(); 205 vbboot_retval = -1; 206 test_slk(VBERROR_SIMULATED, 0, "Normal boot bad"); 207 208 /* Boot dev */ 209 ResetMocks(); 210 shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; 211 vbboot_retval = -2; 212 test_slk(VBERROR_SIMULATED, 0, "Dev boot bad"); 213 214 ResetMocks(); 215 shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; 216 new_version = 0x20003; 217 test_slk(0, 0, "Dev doesn't roll forward"); 218 TEST_EQ(rkr_version, 0x10002, " version"); 219 220 /* Boot recovery */ 221 ResetMocks(); 222 shared->recovery_reason = 123; 223 vbboot_retval = -3; 224 test_slk(VBERROR_SIMULATED, 0, "Recovery boot bad"); 225 226 ResetMocks(); 227 shared->recovery_reason = 123; 228 new_version = 0x20003; 229 test_slk(0, 0, "Recovery doesn't roll forward"); 230 TEST_EQ(rkr_version, 0x10002, " version"); 231 232 ResetMocks(); 233 shared->recovery_reason = 123; 234 rkr_retval = rkw_retval = rkl_retval = VBERROR_SIMULATED; 235 test_slk(0, 0, "Recovery ignore TPM errors"); 236 237 238 239 // todo: rkr/w/l fail ignored if recovery 240 241 242 } 243 244 int main(void) 245 { 246 VbSlkTest(); 247 248 if (vboot_api_stub_check_memory()) 249 return 255; 250 251 return gTestSuccess ? 0 : 255; 252 } 253