vboot_api_kernel3_tests.c revision 7f43669630cb42e40ca6ddc1128eefea8fd339d9
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 3 - software sync 6 */ 7 8#include <stdio.h> 9#include <stdlib.h> 10 11#include "gbb_header.h" 12#include "host_common.h" 13#include "load_kernel_fw.h" 14#include "rollback_index.h" 15#include "test_common.h" 16#include "vboot_audio.h" 17#include "vboot_common.h" 18#include "vboot_kernel.h" 19#include "vboot_nvstorage.h" 20#include "vboot_struct.h" 21 22/* Mock data */ 23static VbCommonParams cparams; 24static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 25static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 26static GoogleBinaryBlockHeader gbb; 27 28static int trust_ec; 29static int mock_in_rw; 30static VbError_t in_rw_retval; 31static int protect_retval; 32static int ec_protected; 33static int run_retval; 34static int ec_run_image; 35static int update_retval; 36static int ec_updated; 37static int get_expected_retval; 38 39static uint8_t mock_ec_hash[32]; 40static int mock_ec_hash_size; 41static uint8_t want_ec_hash[32]; 42static int want_ec_hash_size; 43static uint8_t mock_sha[32]; 44 45static uint32_t screens_displayed[8]; 46static uint32_t screens_count = 0; 47 48/* Reset mock data (for use before each test) */ 49static void ResetMocks(void) 50{ 51 Memset(&cparams, 0, sizeof(cparams)); 52 cparams.shared_data_size = sizeof(shared_data); 53 cparams.shared_data_blob = shared_data; 54 cparams.gbb_data = &gbb; 55 56 Memset(&gbb, 0, sizeof(gbb)); 57 gbb.major_version = GBB_MAJOR_VER; 58 gbb.minor_version = GBB_MINOR_VER; 59 gbb.flags = 0; 60 61 /* 62 * Only the outermost vboot_api_kernel call sets vboot_api_kernel's 63 * vnc. So clear it here too. 64 */ 65 Memset(VbApiKernelGetVnc(), 0, sizeof(VbNvContext)); 66 VbNvSetup(VbApiKernelGetVnc()); 67 VbNvTeardown(VbApiKernelGetVnc()); /* So CRC gets generated */ 68 69 Memset(&shared_data, 0, sizeof(shared_data)); 70 VbSharedDataInit(shared, sizeof(shared_data)); 71 72 trust_ec = 0; 73 mock_in_rw = 0; 74 ec_protected = 0; 75 ec_run_image = -1; /* 0 = RO, 1 = RW */ 76 ec_updated = 0; 77 in_rw_retval = VBERROR_SUCCESS; 78 protect_retval = VBERROR_SUCCESS; 79 update_retval = VBERROR_SUCCESS; 80 run_retval = VBERROR_SUCCESS; 81 get_expected_retval = VBERROR_SUCCESS; 82 83 Memset(mock_ec_hash, 0, sizeof(mock_ec_hash)); 84 mock_ec_hash[0] = 42; 85 mock_ec_hash_size = sizeof(mock_ec_hash); 86 87 Memset(want_ec_hash, 0, sizeof(want_ec_hash)); 88 want_ec_hash[0] = 42; 89 want_ec_hash_size = sizeof(want_ec_hash); 90 91 Memset(mock_sha, 0, sizeof(want_ec_hash)); 92 mock_sha[0] = 42; 93 94 // TODO: ensure these are actually needed 95 96 Memset(screens_displayed, 0, sizeof(screens_displayed)); 97 screens_count = 0; 98} 99 100/* Mock functions */ 101 102int VbExTrustEC(void) 103{ 104 return trust_ec; 105} 106 107VbError_t VbExEcRunningRW(int *in_rw) 108{ 109 *in_rw = mock_in_rw; 110 return in_rw_retval; 111} 112 113VbError_t VbExEcProtectRW(void) 114{ 115 ec_protected = 1; 116 return protect_retval; 117} 118 119VbError_t VbExEcStayInRO(void) 120{ 121 ec_run_image = 0; 122 return run_retval; 123} 124 125VbError_t VbExEcJumpToRW(void) 126{ 127 ec_run_image = 1; 128 return run_retval; 129} 130 131VbError_t VbExEcHashRW(const uint8_t **hash, int *hash_size) 132{ 133 *hash = mock_ec_hash; 134 *hash_size = mock_ec_hash_size; 135 return mock_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED; 136} 137 138VbError_t VbExEcGetExpectedRW(enum VbSelectFirmware_t select, 139 const uint8_t **image, int *image_size) 140{ 141 static uint8_t fake_image[64] = {5, 6, 7, 8}; 142 *image = fake_image; 143 *image_size = sizeof(fake_image); 144 return get_expected_retval; 145} 146 147VbError_t VbExEcGetExpectedRWHash(enum VbSelectFirmware_t select, 148 const uint8_t **hash, int *hash_size) 149{ 150 *hash = want_ec_hash; 151 *hash_size = want_ec_hash_size; 152 153 if (want_ec_hash_size == -1) 154 return VBERROR_EC_GET_EXPECTED_HASH_FROM_IMAGE; 155 else 156 return want_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED; 157} 158 159uint8_t *internal_SHA256(const uint8_t *data, uint64_t len, uint8_t *digest) 160{ 161 Memcpy(digest, mock_sha, sizeof(mock_sha)); 162 return digest; 163} 164 165VbError_t VbExEcUpdateRW(const uint8_t *image, int image_size) 166{ 167 ec_updated = 1; 168 return update_retval; 169} 170 171VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force, 172 VbNvContext *vncptr) 173{ 174 if (screens_count < ARRAY_SIZE(screens_displayed)) 175 screens_displayed[screens_count++] = screen; 176 177 return VBERROR_SUCCESS; 178} 179 180static void test_ssync(VbError_t retval, int recovery_reason, const char *desc) 181{ 182 uint32_t u; 183 184 TEST_EQ(VbEcSoftwareSync(&cparams), retval, desc); 185 VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u); 186 TEST_EQ(u, recovery_reason, " recovery reason"); 187} 188 189/* Tests */ 190 191static void VbSoftwareSyncTest(void) 192{ 193 /* Recovery cases */ 194 ResetMocks(); 195 shared->recovery_reason = 123; 196 test_ssync(0, 0, "In recovery, EC-RO"); 197 TEST_EQ(ec_protected, 0, " ec protected"); 198 199 ResetMocks(); 200 shared->recovery_reason = 123; 201 mock_in_rw = 1; 202 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 203 123, "Recovery needs EC-RO"); 204 205 /* AP-RO cases */ 206 ResetMocks(); 207 in_rw_retval = VBERROR_SIMULATED; 208 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 209 VBNV_RECOVERY_EC_UNKNOWN_IMAGE, "Unknown EC image"); 210 211 ResetMocks(); 212 shared->flags |= VBSD_LF_USE_RO_NORMAL; 213 mock_in_rw = 1; 214 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 215 0, "AP-RO needs EC-RO"); 216 217 ResetMocks(); 218 shared->flags |= VBSD_LF_USE_RO_NORMAL; 219 test_ssync(0, 0, "AP-RO, EC-RO"); 220 TEST_EQ(ec_protected, 1, " ec protected"); 221 TEST_EQ(ec_run_image, 0, " ec run image"); 222 223 ResetMocks(); 224 shared->flags |= VBSD_LF_USE_RO_NORMAL; 225 run_retval = VBERROR_SIMULATED; 226 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 227 VBNV_RECOVERY_EC_SOFTWARE_SYNC, "Stay in RO fail"); 228 229 ResetMocks(); 230 shared->flags |= VBSD_LF_USE_RO_NORMAL; 231 protect_retval = VBERROR_SIMULATED; 232 test_ssync(VBERROR_SIMULATED, 233 VBNV_RECOVERY_EC_PROTECT, "Protect error"); 234 235 /* Calculate hashes */ 236 ResetMocks(); 237 mock_ec_hash_size = 0; 238 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 239 VBNV_RECOVERY_EC_HASH_FAILED, "Bad EC hash"); 240 241 ResetMocks(); 242 mock_ec_hash_size = 16; 243 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 244 VBNV_RECOVERY_EC_HASH_SIZE, "Bad EC hash size"); 245 246 ResetMocks(); 247 want_ec_hash_size = 0; 248 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 249 VBNV_RECOVERY_EC_EXPECTED_HASH, "Bad precalculated hash"); 250 251 ResetMocks(); 252 want_ec_hash_size = 16; 253 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 254 VBNV_RECOVERY_EC_EXPECTED_HASH, 255 "Bad precalculated hash size"); 256 257 ResetMocks(); 258 mock_in_rw = 1; 259 want_ec_hash_size = -1; 260 test_ssync(0, 0, "No precomputed hash"); 261 262 ResetMocks(); 263 want_ec_hash_size = -1; 264 get_expected_retval = VBERROR_SIMULATED; 265 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 266 VBNV_RECOVERY_EC_EXPECTED_IMAGE, "Can't fetch image"); 267 268 /* Updates required */ 269 ResetMocks(); 270 mock_in_rw = 1; 271 want_ec_hash[0]++; 272 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 273 VBNV_RECOVERY_EC_HASH_MISMATCH, 274 "Precalculated hash mismatch"); 275 276 ResetMocks(); 277 mock_in_rw = 1; 278 mock_ec_hash[0]++; 279 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 280 0, "Pending update needs reboot"); 281 282 ResetMocks(); 283 mock_ec_hash[0]++; 284 test_ssync(0, 0, "Update without reboot"); 285 TEST_EQ(ec_protected, 1, " ec protected"); 286 TEST_EQ(ec_run_image, 1, " ec run image"); 287 TEST_EQ(ec_updated, 1, " ec updated"); 288 289 ResetMocks(); 290 mock_ec_hash[0]++; 291 update_retval = VBERROR_EC_REBOOT_TO_RO_REQUIRED; 292 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 293 0, "Reboot after update"); 294 TEST_EQ(ec_updated, 1, " ec updated"); 295 296 ResetMocks(); 297 mock_ec_hash[0]++; 298 update_retval = VBERROR_SIMULATED; 299 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 300 VBNV_RECOVERY_EC_UPDATE, "Update failed"); 301 302 ResetMocks(); 303 mock_ec_hash[0]++; 304 shared->flags |= VBSD_EC_SLOW_UPDATE; 305 test_ssync(0, 0, "Slow update"); 306 TEST_EQ(screens_displayed[0], VB_SCREEN_WAIT, " wait screen"); 307 308 /* RW cases, no update */ 309 ResetMocks(); 310 mock_in_rw = 1; 311 test_ssync(0, 0, "AP-RW, EC-RW"); 312 313 ResetMocks(); 314 test_ssync(0, 0, "AP-RW, EC-RO -> EC-RW"); 315 TEST_EQ(ec_protected, 1, " ec protected"); 316 TEST_EQ(ec_run_image, 1, " ec run image"); 317 TEST_EQ(ec_updated, 0, " ec updated"); 318 319 ResetMocks(); 320 run_retval = VBERROR_SIMULATED; 321 test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 322 VBNV_RECOVERY_EC_JUMP_RW, "Jump to RW fail"); 323 324 ResetMocks(); 325 protect_retval = VBERROR_SIMULATED; 326 test_ssync(VBERROR_SIMULATED, 327 VBNV_RECOVERY_EC_PROTECT, "Protect error"); 328} 329 330int main(void) 331{ 332 VbSoftwareSyncTest(); 333 334 return gTestSuccess ? 0 : 255; 335} 336