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 6 /* Non-volatile storage routines for verified boot. */ 7 8 #ifndef VBOOT_REFERENCE_NVSTORAGE_H_ 9 #define VBOOT_REFERENCE_NVSTORAGE_H_ 10 #include <stdint.h> 11 12 #define VBNV_BLOCK_SIZE 16 /* Size of NV storage block in bytes */ 13 14 typedef struct VbNvContext { 15 /* Raw NV data. Caller must fill this before calling VbNvSetup(). */ 16 uint8_t raw[VBNV_BLOCK_SIZE]; 17 /* 18 * Flag indicating whether raw data has changed. Set by VbNvTeardown() 19 * if the raw data has changed and needs to be stored to the underlying 20 * non-volatile data store. 21 */ 22 int raw_changed; 23 24 /* 25 * Internal data for NV storage routines. Caller should not touch 26 * these fields. 27 */ 28 int regenerate_crc; 29 } VbNvContext; 30 31 /* Parameter type for VbNvGet(), VbNvSet(). */ 32 typedef enum VbNvParam { 33 /* 34 * Parameter values have been reset to defaults (flag for firmware). 35 * 0=clear; 1=set. 36 */ 37 VBNV_FIRMWARE_SETTINGS_RESET = 0, 38 /* 39 * Parameter values have been reset to defaults (flag for kernel). 40 * 0=clear; 1=set. 41 */ 42 VBNV_KERNEL_SETTINGS_RESET, 43 /* Request debug reset on next S3->S0 transition. 0=clear; 1=set. */ 44 VBNV_DEBUG_RESET_MODE, 45 /* 46 * Number of times to try booting RW firmware slot B before slot A. 47 * Valid range: 0-15. 48 * 49 * Vboot2: Number of times to try the firmware in VBNV_FW_TRY_NEXT. 50 * 51 * These refer to the same field, but have different enum values so 52 * case statement don't complain about duplicates. 53 */ 54 VBNV_TRY_B_COUNT, 55 VBNV_FW_TRY_COUNT, 56 /* 57 * Request recovery mode on next boot; see VBNB_RECOVERY_* below for 58 * currently defined reason codes. 8-bit value. 59 */ 60 VBNV_RECOVERY_REQUEST, 61 /* 62 * Localization index for screen bitmaps displayed by firmware. 63 * 8-bit value. 64 */ 65 VBNV_LOCALIZATION_INDEX, 66 /* Field reserved for kernel/user-mode use; 32-bit value. */ 67 VBNV_KERNEL_FIELD, 68 /* Allow booting from USB in developer mode. 0=no, 1=yes. */ 69 VBNV_DEV_BOOT_USB, 70 /* Allow booting of legacy OSes in developer mode. 0=no, 1=yes. */ 71 VBNV_DEV_BOOT_LEGACY, 72 /* Only boot Google-signed images in developer mode. 0=no, 1=yes. */ 73 VBNV_DEV_BOOT_SIGNED_ONLY, 74 /* 75 * Set by userspace to request that RO firmware disable dev-mode on the 76 * next boot. This is likely only possible if the dev-switch is 77 * virtual. 78 */ 79 VBNV_DISABLE_DEV_REQUEST, 80 /* 81 * Set and cleared by vboot to request that the video Option ROM be 82 * loaded at boot time, so that BIOS screens can be displayed. 0=no, 83 * 1=yes. 84 */ 85 VBNV_OPROM_NEEDED, 86 /* Request that the firmware clear the TPM owner on the next boot. */ 87 VBNV_CLEAR_TPM_OWNER_REQUEST, 88 /* Flag that TPM owner was cleared on request. */ 89 VBNV_CLEAR_TPM_OWNER_DONE, 90 /* More details on recovery reason */ 91 VBNV_RECOVERY_SUBCODE, 92 /* Request that NVRAM be backed up at next boot if possible. */ 93 VBNV_BACKUP_NVRAM_REQUEST, 94 95 /* Vboot2: Firmware slot to try next. 0=A, 1=B */ 96 VBNV_FW_TRY_NEXT, 97 /* Vboot2: Firmware slot tried this boot (0=A, 1=B) */ 98 VBNV_FW_TRIED, 99 /* Vboot2: Result of trying that firmware (see vb2_fw_result) */ 100 VBNV_FW_RESULT, 101 /* Firmware slot tried previous boot (0=A, 1=B) */ 102 VBNV_FW_PREV_TRIED, 103 /* Result of trying that firmware (see vb2_fw_result) */ 104 VBNV_FW_PREV_RESULT, 105 106 } VbNvParam; 107 108 /* Result of trying the firmware in VBNV_FW_TRIED */ 109 typedef enum VbFwResult { 110 /* Unknown */ 111 VBNV_FW_RESULT_UNKNOWN = 0, 112 113 /* Trying a new slot, but haven't reached success/failure */ 114 VBNV_FW_RESULT_TRYING = 1, 115 116 /* Successfully booted to the OS */ 117 VBNV_FW_RESULT_SUCCESS = 2, 118 119 /* Known failure */ 120 VBNV_FW_RESULT_FAILURE = 3, 121 122 } VbFwResult; 123 124 /* Recovery reason codes for VBNV_RECOVERY_REQUEST */ 125 /* Recovery not requested. */ 126 #define VBNV_RECOVERY_NOT_REQUESTED 0x00 127 /* 128 * Recovery requested from legacy utility. (Prior to the NV storage spec, 129 * recovery mode was a single bitfield; this value is reserved so that scripts 130 * which wrote 1 to the recovery field are distinguishable from scripts whch 131 * use the recovery reasons listed here. 132 */ 133 #define VBNV_RECOVERY_LEGACY 0x01 134 /* User manually requested recovery via recovery button */ 135 #define VBNV_RECOVERY_RO_MANUAL 0x02 136 /* RW firmware failed signature check (neither RW firmware slot was valid) */ 137 #define VBNV_RECOVERY_RO_INVALID_RW 0x03 138 /* S3 resume failed */ 139 #define VBNV_RECOVERY_RO_S3_RESUME 0x04 140 /* TPM error in read-only firmware (deprecated) */ 141 #define VBNV_RECOVERY_DEP_RO_TPM_ERROR 0x05 142 /* Shared data error in read-only firmware */ 143 #define VBNV_RECOVERY_RO_SHARED_DATA 0x06 144 /* Test error from S3Resume() */ 145 #define VBNV_RECOVERY_RO_TEST_S3 0x07 146 /* Test error from LoadFirmwareSetup() */ 147 #define VBNV_RECOVERY_RO_TEST_LFS 0x08 148 /* Test error from LoadFirmware() */ 149 #define VBNV_RECOVERY_RO_TEST_LF 0x09 150 /* 151 * RW firmware failed signature check (neither RW firmware slot was valid). 152 * Recovery reason is VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + the check value 153 * for the slot which came closest to validating; see VBSD_LF_CHECK_* in 154 * vboot_struct.h. 155 */ 156 #define VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN 0x10 157 #define VBNV_RECOVERY_RO_INVALID_RW_CHECK_MAX 0x1F 158 /* 159 * Firmware boot failure outside of verified boot (RAM init, missing SSD, 160 * etc.). 161 */ 162 #define VBNV_RECOVERY_RO_FIRMWARE 0x20 163 /* 164 * Recovery mode TPM initialization requires a system reboot. The system was 165 * already in recovery mode for some other reason when this happened. 166 */ 167 #define VBNV_RECOVERY_RO_TPM_REBOOT 0x21 168 /* EC software sync - other error */ 169 #define VBNV_RECOVERY_EC_SOFTWARE_SYNC 0x22 170 /* EC software sync - unable to determine active EC image */ 171 #define VBNV_RECOVERY_EC_UNKNOWN_IMAGE 0x23 172 /* EC software sync - error obtaining EC image hash (deprecated) */ 173 #define VBNV_RECOVERY_DEP_EC_HASH 0x24 174 /* EC software sync - error obtaining expected EC image */ 175 #define VBNV_RECOVERY_EC_EXPECTED_IMAGE 0x25 176 /* EC software sync - error updating EC */ 177 #define VBNV_RECOVERY_EC_UPDATE 0x26 178 /* EC software sync - unable to jump to EC-RW */ 179 #define VBNV_RECOVERY_EC_JUMP_RW 0x27 180 /* EC software sync - unable to protect / unprotect EC-RW */ 181 #define VBNV_RECOVERY_EC_PROTECT 0x28 182 /* EC software sync - error obtaining expected EC hash */ 183 #define VBNV_RECOVERY_EC_EXPECTED_HASH 0x29 184 /* EC software sync - expected EC image doesn't match hash */ 185 #define VBNV_RECOVERY_EC_HASH_MISMATCH 0x2A 186 /* VB2: Secure data inititalization error */ 187 #define VBNV_RECOVERY_VB2_SECDATA_INIT 0x2B 188 /* VB2: GBB header is bad */ 189 #define VBNV_RECOVERY_VB2_GBB_HEADER 0x2C 190 /* VB2: Unable to clear TPM owner */ 191 #define VBNV_RECOVERY_VB2_TPM_CLEAR_OWNER 0x2D 192 /* VB2: Error determining/updating virtual dev switch */ 193 #define VBNV_RECOVERY_VB2_DEV_SWITCH 0x2E 194 /* VB2: Error determining firmware slot */ 195 #define VBNV_RECOVERY_VB2_FW_SLOT 0x2F 196 /* Unspecified/unknown error in read-only firmware */ 197 #define VBNV_RECOVERY_RO_UNSPECIFIED 0x3F 198 /* 199 * User manually requested recovery by pressing a key at developer 200 * warning screen 201 */ 202 #define VBNV_RECOVERY_RW_DEV_SCREEN 0x41 203 /* No OS kernel detected */ 204 #define VBNV_RECOVERY_RW_NO_OS 0x42 205 /* OS kernel failed signature check */ 206 #define VBNV_RECOVERY_RW_INVALID_OS 0x43 207 /* TPM error in rewritable firmware (deprecated) */ 208 #define VBNV_RECOVERY_DEP_RW_TPM_ERROR 0x44 209 /* RW firmware in dev mode, but dev switch is off */ 210 #define VBNV_RECOVERY_RW_DEV_MISMATCH 0x45 211 /* Shared data error in rewritable firmware */ 212 #define VBNV_RECOVERY_RW_SHARED_DATA 0x46 213 /* Test error from LoadKernel() */ 214 #define VBNV_RECOVERY_RW_TEST_LK 0x47 215 /* No bootable disk found (deprecated)*/ 216 #define VBNV_RECOVERY_DEP_RW_NO_DISK 0x48 217 /* Rebooting did not correct TPM_E_FAIL or TPM_E_FAILEDSELFTEST */ 218 #define VBNV_RECOVERY_TPM_E_FAIL 0x49 219 /* TPM setup error in read-only firmware */ 220 #define VBNV_RECOVERY_RO_TPM_S_ERROR 0x50 221 /* TPM write error in read-only firmware */ 222 #define VBNV_RECOVERY_RO_TPM_W_ERROR 0x51 223 /* TPM lock error in read-only firmware */ 224 #define VBNV_RECOVERY_RO_TPM_L_ERROR 0x52 225 /* TPM update error in read-only firmware */ 226 #define VBNV_RECOVERY_RO_TPM_U_ERROR 0x53 227 /* TPM read error in rewritable firmware */ 228 #define VBNV_RECOVERY_RW_TPM_R_ERROR 0x54 229 /* TPM write error in rewritable firmware */ 230 #define VBNV_RECOVERY_RW_TPM_W_ERROR 0x55 231 /* TPM lock error in rewritable firmware */ 232 #define VBNV_RECOVERY_RW_TPM_L_ERROR 0x56 233 /* EC software sync unable to get EC image hash */ 234 #define VBNV_RECOVERY_EC_HASH_FAILED 0x57 235 /* EC software sync invalid image hash size */ 236 #define VBNV_RECOVERY_EC_HASH_SIZE 0x58 237 /* Unspecified error while trying to load kernel */ 238 #define VBNV_RECOVERY_LK_UNSPECIFIED 0x59 239 /* No bootable storage device in system */ 240 #define VBNV_RECOVERY_RW_NO_DISK 0x5A 241 /* No bootable kernel found on disk */ 242 #define VBNV_RECOVERY_RW_NO_KERNEL 0x5B 243 /* Unspecified/unknown error in rewritable firmware */ 244 #define VBNV_RECOVERY_RW_UNSPECIFIED 0x7F 245 /* DM-verity error */ 246 #define VBNV_RECOVERY_KE_DM_VERITY 0x81 247 /* Unspecified/unknown error in kernel */ 248 #define VBNV_RECOVERY_KE_UNSPECIFIED 0xBF 249 /* Recovery mode test from user-mode */ 250 #define VBNV_RECOVERY_US_TEST 0xC1 251 /* Unspecified/unknown error in user-mode */ 252 #define VBNV_RECOVERY_US_UNSPECIFIED 0xFF 253 254 /** 255 * Initialize the NV storage library. 256 * 257 * This must be called before any other functions in this library. Returns 0 258 * if success, non-zero if error. 259 * 260 * Proper calling procedure: 261 * 1) Allocate a context struct. 262 * 2) If multi-threaded/multi-process, acquire a lock to prevent 263 * other processes from modifying the underlying storage. 264 * 3) Read underlying storage and fill in context->raw. 265 * 4) Call VbNvSetup(). 266 * 267 * If you have access to global variables, you may want to wrap all that in 268 * your own VbNvOpen() function. We don't do that in here because there are no 269 * global variables in UEFI BIOS during the PEI phase (that's also why we have 270 * to pass around a context pointer). 271 */ 272 int VbNvSetup(VbNvContext *context); 273 274 /** 275 * Clean up and flush changes back to the raw data. 276 * 277 * This must be called after other functions in this library. Returns 0 if 278 * success, non-zero if error. 279 * 280 * Proper calling procedure: 281 * 1) Call VbNvExit(). 282 * 2) If context.raw_changed, write data back to underlying storage. 283 * 3) Release any lock you acquired before calling VbNvSetup(). 284 * 4) Free the context struct. 285 * 286 * If you have access to global variables, you may want to wrap this 287 * in your own VbNvClose() function. 288 */ 289 int VbNvTeardown(VbNvContext *context); 290 291 /** 292 * Read a NV storage parameter into *dest. 293 * 294 * Returns 0 if success, non-zero if error. 295 * 296 * This may only be called between VbNvSetup() and VbNvTeardown(). 297 */ 298 int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest); 299 300 /** 301 * Set a NV storage param to a new value. 302 * 303 * Returns 0 if success, non-zero if error. 304 * 305 * This may only be called between VbNvSetup() and VbNvTeardown(). 306 */ 307 int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value); 308 309 /** 310 * Attempt to restore some fields of a lost VbNvContext from a backup area. 311 * The rest of the fields are unchanged, so they'd need to be set to their 312 * appropriate defaults by calling VbNvSetup() first (which is usually how we 313 * know the fields have been lost). 314 * 315 * Returns 0 if success, non-zero if error. 316 * 317 * This may only be called between VbNvSetup() and VbNvTeardown(). 318 */ 319 int RestoreNvFromBackup(VbNvContext *vnc); 320 321 /** 322 * Attempt to save some fields of the VbNvContext to a backup area. 323 * 324 * Returns 0 if success, non-zero if error. If it succeeds, it will clear the 325 * VBNV_BACKUP_NVRAM_REQUEST flag in the VbNvContext. 326 * 327 * This may only be called when the backup area is writable. 328 */ 329 int SaveNvToBackup(VbNvContext *vnc); 330 331 #endif /* VBOOT_REFERENCE_NVSTORAGE_H_ */ 332