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