Home | History | Annotate | Download | only in tests
      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