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 firmware NV storage library. 6 */ 7 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include "test_common.h" 14 #include "vboot_common.h" 15 #include "vboot_nvstorage.h" 16 17 /* Single NV storage field to test */ 18 typedef struct VbNvField { 19 VbNvParam param; /* Parameter index */ 20 uint32_t default_value; /* Expected default value */ 21 uint32_t test_value; /* Value to test writing */ 22 uint32_t test_value2; /* Second value to test writing */ 23 char* desc; /* Field description */ 24 } VbNvField; 25 26 /* Array of fields to test, terminated with a field with desc==NULL. */ 27 static VbNvField nvfields[] = { 28 {VBNV_DEBUG_RESET_MODE, 0, 1, 0, "debug reset mode"}, 29 {VBNV_TRY_B_COUNT, 0, 6, 15, "try B count"}, 30 {VBNV_RECOVERY_REQUEST, 0, 0x42, 0xED, "recovery request"}, 31 {VBNV_LOCALIZATION_INDEX, 0, 0x69, 0xB0, "localization index"}, 32 {VBNV_KERNEL_FIELD, 0, 0x12345678, 0xFEDCBA98, "kernel field"}, 33 {VBNV_DEV_BOOT_USB, 0, 1, 0, "dev boot usb"}, 34 {VBNV_DEV_BOOT_LEGACY, 0, 1, 0, "dev boot legacy"}, 35 {VBNV_DEV_BOOT_SIGNED_ONLY, 0, 1, 0, "dev boot custom"}, 36 {VBNV_DISABLE_DEV_REQUEST, 0, 1, 0, "disable dev request"}, 37 {VBNV_CLEAR_TPM_OWNER_REQUEST, 0, 1, 0, "clear tpm owner request"}, 38 {VBNV_CLEAR_TPM_OWNER_DONE, 0, 1, 0, "clear tpm owner done"}, 39 {VBNV_OPROM_NEEDED, 0, 1, 0, "oprom needed"}, 40 {VBNV_FW_TRY_COUNT, 0, 8, 15, "try count"}, 41 {VBNV_FW_TRY_NEXT, 0, 1, 0, "try next"}, 42 {VBNV_FW_TRIED, 0, 1, 0, "firmware tried"}, 43 {VBNV_FW_RESULT, VBNV_FW_RESULT_UNKNOWN, 1, 2, "firmware result"}, 44 {VBNV_FW_PREV_TRIED, 0, 1, 0, "firmware prev tried"}, 45 {VBNV_FW_PREV_RESULT, VBNV_FW_RESULT_UNKNOWN, 1, 3, "firmware prev result"}, 46 {0, 0, 0, 0, NULL} 47 }; 48 49 static void VbNvStorageTest(void) { 50 51 VbNvField* vnf; 52 VbNvContext c; 53 uint8_t goodcrc; 54 uint32_t data; 55 56 memset(&c, 0xA6, sizeof(c)); 57 58 /* Open with invalid data should set defaults */ 59 TEST_EQ(VbNvSetup(&c), 0, "VbNvSetup()"); 60 TEST_EQ(c.raw[0], 0x70, "VbNvSetup() reset header byte"); 61 /* Close then regenerates the CRC */ 62 TEST_EQ(VbNvTeardown(&c), 0, "VbNvTeardown()"); 63 TEST_NEQ(c.raw[15], 0, "VbNvTeardown() CRC"); 64 TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed"); 65 goodcrc = c.raw[15]; 66 /* Another open-close pair should not cause further changes */ 67 VbNvSetup(&c); 68 VbNvTeardown(&c); 69 TEST_EQ(c.raw_changed, 0, "VbNvTeardown() didn't change"); 70 TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same"); 71 72 /* Perturbing the header should force defaults */ 73 c.raw[0] ^= 0x40; 74 VbNvSetup(&c); 75 TEST_EQ(c.raw[0], 0x70, "VbNvSetup() reset header byte again"); 76 /* Close then regenerates the CRC */ 77 VbNvTeardown(&c); 78 TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed again"); 79 TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same again"); 80 81 /* So should perturbing some other byte */ 82 TEST_EQ(c.raw[11], 0, "Kernel byte starts at 0"); 83 c.raw[11] = 12; 84 VbNvSetup(&c); 85 TEST_EQ(c.raw[11], 0, "VbNvSetup() reset kernel byte"); 86 /* Close then regenerates the CRC */ 87 VbNvTeardown(&c); 88 TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed again"); 89 TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same again"); 90 91 /* Clear the kernel and firmware flags */ 92 VbNvSetup(&c); 93 TEST_EQ(VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data), 0, 94 "Get firmware settings reset"); 95 TEST_EQ(data, 1, "Firmware settings are reset"); 96 TEST_EQ(VbNvSet(&c, VBNV_FIRMWARE_SETTINGS_RESET, 0), 0, 97 "Clear firmware settings reset"); 98 VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data); 99 TEST_EQ(data, 0, "Firmware settings are clear"); 100 101 TEST_EQ(VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data), 0, 102 "Get kernel settings reset"); 103 TEST_EQ(data, 1, "Kernel settings are reset"); 104 TEST_EQ(VbNvSet(&c, VBNV_KERNEL_SETTINGS_RESET, 0), 0, 105 "Clear kernel settings reset"); 106 VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data); 107 TEST_EQ(data, 0, "Kernel settings are clear"); 108 TEST_EQ(c.raw[0], 0x40, "Header byte now just has the header bit"); 109 VbNvTeardown(&c); 110 /* That should have changed the CRC */ 111 TEST_NEQ(c.raw[15], goodcrc, "VbNvTeardown() CRC changed due to flags clear"); 112 113 /* Test explicitly setting the reset flags again */ 114 VbNvSetup(&c); 115 VbNvSet(&c, VBNV_FIRMWARE_SETTINGS_RESET, 1); 116 VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data); 117 TEST_EQ(data, 1, "Firmware settings forced reset"); 118 VbNvSet(&c, VBNV_FIRMWARE_SETTINGS_RESET, 0); 119 120 VbNvSet(&c, VBNV_KERNEL_SETTINGS_RESET, 1); 121 VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data); 122 TEST_EQ(data, 1, "Kernel settings forced reset"); 123 VbNvSet(&c, VBNV_KERNEL_SETTINGS_RESET, 0); 124 VbNvTeardown(&c); 125 126 /* Get/set an invalid field */ 127 VbNvSetup(&c); 128 TEST_EQ(VbNvGet(&c, -1, &data), 1, "Get invalid setting"); 129 TEST_EQ(VbNvSet(&c, -1, 0), 1, "Set invalid setting"); 130 VbNvTeardown(&c); 131 132 /* Test other fields */ 133 VbNvSetup(&c); 134 /* Test all defaults first, since some fields alias onto others */ 135 for (vnf = nvfields; vnf->desc; vnf++) { 136 printf("Testing field: %s\n", vnf->desc); 137 TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, " get"); 138 TEST_EQ(data, vnf->default_value, " default"); 139 } 140 /* Now test get/set */ 141 for (vnf = nvfields; vnf->desc; vnf++) { 142 printf("Testing field: %s\n", vnf->desc); 143 TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value), 0, " set 1"); 144 TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, " get 1"); 145 TEST_EQ(data, vnf->test_value, " value 1"); 146 147 TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value2), 0, " set 2"); 148 TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, " get 2"); 149 TEST_EQ(data, vnf->test_value2, " value 2"); 150 } 151 VbNvTeardown(&c); 152 153 /* None of those changes should have caused a reset to defaults */ 154 VbNvSetup(&c); 155 VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data); 156 TEST_EQ(data, 0, "Firmware settings are still clear"); 157 VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data); 158 TEST_EQ(data, 0, "Kernel settings are still clear"); 159 VbNvTeardown(&c); 160 161 /* Verify writing identical settings doesn't cause the CRC to regenerate */ 162 VbNvSetup(&c); 163 TEST_EQ(c.regenerate_crc, 0, "No regen CRC on open"); 164 for (vnf = nvfields; vnf->desc; vnf++) 165 TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value2), 0, vnf->desc); 166 TEST_EQ(c.regenerate_crc, 0, "No regen CRC if data not changed"); 167 VbNvTeardown(&c); 168 TEST_EQ(c.raw_changed, 0, "No raw change if data not changed"); 169 170 /* Test out-of-range fields mapping to defaults */ 171 VbNvSetup(&c); 172 VbNvSet(&c, VBNV_TRY_B_COUNT, 16); 173 VbNvGet(&c, VBNV_TRY_B_COUNT, &data); 174 TEST_EQ(data, 15, "Try b count out of range"); 175 VbNvSetup(&c); 176 VbNvSet(&c, VBNV_FW_TRY_COUNT, 16); 177 VbNvGet(&c, VBNV_FW_TRY_COUNT, &data); 178 TEST_EQ(data, 15, "Try count out of range"); 179 VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0x101); 180 VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data); 181 TEST_EQ(data, VBNV_RECOVERY_LEGACY, "Recovery request out of range"); 182 VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0x102); 183 VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data); 184 TEST_EQ(data, 0, "Localization index out of range"); 185 VbNvSet(&c, VBNV_FW_RESULT, VBNV_FW_RESULT_UNKNOWN + 100); 186 VbNvGet(&c, VBNV_FW_RESULT, &data); 187 TEST_EQ(data, VBNV_FW_RESULT_UNKNOWN, "Firmware result out of range"); 188 VbNvTeardown(&c); 189 } 190 191 192 int main(int argc, char* argv[]) { 193 int error_code = 0; 194 195 VbNvStorageTest(); 196 197 if (vboot_api_stub_check_memory()) 198 error_code = 255; 199 if (!gTestSuccess) 200 error_code = 255; 201 202 return error_code; 203 } 204