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 */ 24static VbCommonParams cparams; 25static VbSelectAndLoadKernelParams kparams; 26static VbNvContext vnc; 27static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 28static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 29static GoogleBinaryBlockHeader gbb; 30 31static int ecsync_retval; 32static uint32_t rkr_version; 33static uint32_t new_version; 34static int rkr_retval, rkw_retval, rkl_retval; 35static VbError_t vbboot_retval; 36 37/* Reset mock data (for use before each test) */ 38static 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 68VbError_t VbExNvStorageRead(uint8_t *buf) 69{ 70 Memcpy(buf, vnc.raw, sizeof(vnc.raw)); 71 return VBERROR_SUCCESS; 72} 73 74VbError_t VbExNvStorageWrite(const uint8_t *buf) 75{ 76 Memcpy(vnc.raw, buf, sizeof(vnc.raw)); 77 return VBERROR_SUCCESS; 78} 79 80VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams) 81{ 82 return ecsync_retval; 83} 84 85uint32_t RollbackKernelRead(uint32_t *version) 86{ 87 *version = rkr_version; 88 return rkr_retval; 89} 90 91uint32_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 98uint32_t RollbackKernelLock(int recovery_mode) 99{ 100 return rkl_retval; 101} 102 103VbError_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 113VbError_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 123VbError_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 133static 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 144static 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 244int main(void) 245{ 246 VbSlkTest(); 247 248 if (vboot_api_stub_check_memory()) 249 return 255; 250 251 return gTestSuccess ? 0 : 255; 252} 253