| /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* Non-volatile storage routines for verified boot. */ |
| |
| #ifndef VBOOT_REFERENCE_NVSTORAGE_H_ |
| #define VBOOT_REFERENCE_NVSTORAGE_H_ |
| #include <stdint.h> |
| |
| #define VBNV_BLOCK_SIZE 16 /* Size of NV storage block in bytes */ |
| |
| typedef struct VbNvContext { |
| /* Raw NV data. Caller must fill this before calling VbNvSetup(). */ |
| uint8_t raw[VBNV_BLOCK_SIZE]; |
| /* |
| * Flag indicating whether raw data has changed. Set by VbNvTeardown() |
| * if the raw data has changed and needs to be stored to the underlying |
| * non-volatile data store. |
| */ |
| int raw_changed; |
| |
| /* |
| * Internal data for NV storage routines. Caller should not touch |
| * these fields. |
| */ |
| int regenerate_crc; |
| } VbNvContext; |
| |
| /* Parameter type for VbNvGet(), VbNvSet(). */ |
| typedef enum VbNvParam { |
| /* |
| * Parameter values have been reset to defaults (flag for firmware). |
| * 0=clear; 1=set. |
| */ |
| VBNV_FIRMWARE_SETTINGS_RESET = 0, |
| /* |
| * Parameter values have been reset to defaults (flag for kernel). |
| * 0=clear; 1=set. |
| */ |
| VBNV_KERNEL_SETTINGS_RESET, |
| /* Request debug reset on next S3->S0 transition. 0=clear; 1=set. */ |
| VBNV_DEBUG_RESET_MODE, |
| /* |
| * Number of times to try booting RW firmware slot B before slot A. |
| * Valid range: 0-15. |
| * |
| * Vboot2: Number of times to try the firmware in VBNV_FW_TRY_NEXT. |
| * |
| * These refer to the same field, but have different enum values so |
| * case statement don't complain about duplicates. |
| */ |
| VBNV_TRY_B_COUNT, |
| VBNV_FW_TRY_COUNT, |
| /* |
| * Request recovery mode on next boot; see VBNB_RECOVERY_* below for |
| * currently defined reason codes. 8-bit value. |
| */ |
| VBNV_RECOVERY_REQUEST, |
| /* |
| * Localization index for screen bitmaps displayed by firmware. |
| * 8-bit value. |
| */ |
| VBNV_LOCALIZATION_INDEX, |
| /* Field reserved for kernel/user-mode use; 32-bit value. */ |
| VBNV_KERNEL_FIELD, |
| /* Allow booting from USB in developer mode. 0=no, 1=yes. */ |
| VBNV_DEV_BOOT_USB, |
| /* Allow booting of legacy OSes in developer mode. 0=no, 1=yes. */ |
| VBNV_DEV_BOOT_LEGACY, |
| /* Only boot Google-signed images in developer mode. 0=no, 1=yes. */ |
| VBNV_DEV_BOOT_SIGNED_ONLY, |
| /* |
| * Allow full fastboot capability in firmware in developer mode. |
| * 0=no, 1=yes. |
| */ |
| VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, |
| /* Set default boot mode (see VbDevDefaultBoot) */ |
| VBNV_DEV_DEFAULT_BOOT, |
| /* |
| * Set by userspace to request that RO firmware disable dev-mode on the |
| * next boot. This is likely only possible if the dev-switch is |
| * virtual. |
| */ |
| VBNV_DISABLE_DEV_REQUEST, |
| /* |
| * Set and cleared by vboot to request that the video Option ROM be |
| * loaded at boot time, so that BIOS screens can be displayed. 0=no, |
| * 1=yes. |
| */ |
| VBNV_OPROM_NEEDED, |
| /* Request that the firmware clear the TPM owner on the next boot. */ |
| VBNV_CLEAR_TPM_OWNER_REQUEST, |
| /* Flag that TPM owner was cleared on request. */ |
| VBNV_CLEAR_TPM_OWNER_DONE, |
| /* TPM requested a reboot */ |
| VBNV_TPM_REQUESTED_REBOOT, |
| /* More details on recovery reason */ |
| VBNV_RECOVERY_SUBCODE, |
| /* Request that NVRAM be backed up at next boot if possible. */ |
| VBNV_BACKUP_NVRAM_REQUEST, |
| |
| /* Vboot2: Firmware slot to try next. 0=A, 1=B */ |
| VBNV_FW_TRY_NEXT, |
| /* Vboot2: Firmware slot tried this boot (0=A, 1=B) */ |
| VBNV_FW_TRIED, |
| /* Vboot2: Result of trying that firmware (see vb2_fw_result) */ |
| VBNV_FW_RESULT, |
| /* Firmware slot tried previous boot (0=A, 1=B) */ |
| VBNV_FW_PREV_TRIED, |
| /* Result of trying that firmware (see vb2_fw_result) */ |
| VBNV_FW_PREV_RESULT, |
| /* Wipeout request from firmware present. */ |
| VBNV_FW_REQ_WIPEOUT, |
| |
| /* Fastboot: Unlock in firmware, 0=disabled, 1=enabled. */ |
| VBNV_FASTBOOT_UNLOCK_IN_FW, |
| /* Boot system when AC detected (0=no, 1=yes). */ |
| VBNV_BOOT_ON_AC_DETECT, |
| /* Try to update the EC-RO image (0=no, 1=yes). */ |
| VBNV_TRY_RO_SYNC, |
| |
| } VbNvParam; |
| |
| /* Set default boot in developer mode */ |
| typedef enum VbDevDefaultBoot { |
| /* Default to boot from disk*/ |
| VBNV_DEV_DEFAULT_BOOT_DISK = 0, |
| |
| /* Default to boot from USB */ |
| VBNV_DEV_DEFAULT_BOOT_USB = 1, |
| |
| /* Default to boot legacy OS */ |
| VBNV_DEV_DEFAULT_BOOT_LEGACY = 2, |
| |
| } VbDevDefaultBoot; |
| |
| /* Result of trying the firmware in VBNV_FW_TRIED */ |
| typedef enum VbFwResult { |
| /* Unknown */ |
| VBNV_FW_RESULT_UNKNOWN = 0, |
| |
| /* Trying a new slot, but haven't reached success/failure */ |
| VBNV_FW_RESULT_TRYING = 1, |
| |
| /* Successfully booted to the OS */ |
| VBNV_FW_RESULT_SUCCESS = 2, |
| |
| /* Known failure */ |
| VBNV_FW_RESULT_FAILURE = 3, |
| |
| } VbFwResult; |
| |
| /* Recovery reason codes for VBNV_RECOVERY_REQUEST */ |
| /* Recovery not requested. */ |
| #define VBNV_RECOVERY_NOT_REQUESTED 0x00 |
| /* |
| * Recovery requested from legacy utility. (Prior to the NV storage spec, |
| * recovery mode was a single bitfield; this value is reserved so that scripts |
| * which wrote 1 to the recovery field are distinguishable from scripts whch |
| * use the recovery reasons listed here. |
| */ |
| #define VBNV_RECOVERY_LEGACY 0x01 |
| /* User manually requested recovery via recovery button */ |
| #define VBNV_RECOVERY_RO_MANUAL 0x02 |
| /* RW firmware failed signature check (neither RW firmware slot was valid) */ |
| #define VBNV_RECOVERY_RO_INVALID_RW 0x03 |
| /* S3 resume failed */ |
| #define VBNV_RECOVERY_RO_S3_RESUME 0x04 |
| /* TPM error in read-only firmware (deprecated) */ |
| #define VBNV_RECOVERY_DEP_RO_TPM_ERROR 0x05 |
| /* Shared data error in read-only firmware */ |
| #define VBNV_RECOVERY_RO_SHARED_DATA 0x06 |
| /* Test error from S3Resume() */ |
| #define VBNV_RECOVERY_RO_TEST_S3 0x07 |
| /* Test error from LoadFirmwareSetup() */ |
| #define VBNV_RECOVERY_RO_TEST_LFS 0x08 |
| /* Test error from LoadFirmware() */ |
| #define VBNV_RECOVERY_RO_TEST_LF 0x09 |
| /* |
| * RW firmware failed signature check (neither RW firmware slot was valid). |
| * Recovery reason is VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + the check value |
| * for the slot which came closest to validating; see VBSD_LF_CHECK_* in |
| * vboot_struct.h. |
| */ |
| #define VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN 0x10 |
| #define VBNV_RECOVERY_RO_INVALID_RW_CHECK_MAX 0x1F |
| /* |
| * Firmware boot failure outside of verified boot (RAM init, missing SSD, |
| * etc.). |
| */ |
| #define VBNV_RECOVERY_RO_FIRMWARE 0x20 |
| /* |
| * Recovery mode TPM initialization requires a system reboot. The system was |
| * already in recovery mode for some other reason when this happened. |
| */ |
| #define VBNV_RECOVERY_RO_TPM_REBOOT 0x21 |
| /* EC software sync - other error */ |
| #define VBNV_RECOVERY_EC_SOFTWARE_SYNC 0x22 |
| /* EC software sync - unable to determine active EC image */ |
| #define VBNV_RECOVERY_EC_UNKNOWN_IMAGE 0x23 |
| /* EC software sync - error obtaining EC image hash (deprecated) */ |
| #define VBNV_RECOVERY_DEP_EC_HASH 0x24 |
| /* EC software sync - error obtaining expected EC image */ |
| #define VBNV_RECOVERY_EC_EXPECTED_IMAGE 0x25 |
| /* EC software sync - error updating EC */ |
| #define VBNV_RECOVERY_EC_UPDATE 0x26 |
| /* EC software sync - unable to jump to EC-RW */ |
| #define VBNV_RECOVERY_EC_JUMP_RW 0x27 |
| /* EC software sync - unable to protect / unprotect EC-RW */ |
| #define VBNV_RECOVERY_EC_PROTECT 0x28 |
| /* EC software sync - error obtaining expected EC hash */ |
| #define VBNV_RECOVERY_EC_EXPECTED_HASH 0x29 |
| /* EC software sync - expected EC image doesn't match hash */ |
| #define VBNV_RECOVERY_EC_HASH_MISMATCH 0x2A |
| /* VB2: Secure data inititalization error */ |
| #define VBNV_RECOVERY_VB2_SECDATA_INIT 0x2B |
| /* VB2: GBB header is bad */ |
| #define VBNV_RECOVERY_VB2_GBB_HEADER 0x2C |
| /* VB2: Unable to clear TPM owner */ |
| #define VBNV_RECOVERY_VB2_TPM_CLEAR_OWNER 0x2D |
| /* VB2: Error determining/updating virtual dev switch */ |
| #define VBNV_RECOVERY_VB2_DEV_SWITCH 0x2E |
| /* VB2: Error determining firmware slot */ |
| #define VBNV_RECOVERY_VB2_FW_SLOT 0x2F |
| /* Unspecified/unknown error in read-only firmware */ |
| #define VBNV_RECOVERY_RO_UNSPECIFIED 0x3F |
| /* |
| * User manually requested recovery by pressing a key at developer |
| * warning screen |
| */ |
| #define VBNV_RECOVERY_RW_DEV_SCREEN 0x41 |
| /* No OS kernel detected */ |
| #define VBNV_RECOVERY_RW_NO_OS 0x42 |
| /* OS kernel failed signature check */ |
| #define VBNV_RECOVERY_RW_INVALID_OS 0x43 |
| /* TPM error in rewritable firmware (deprecated) */ |
| #define VBNV_RECOVERY_DEP_RW_TPM_ERROR 0x44 |
| /* RW firmware in dev mode, but dev switch is off */ |
| #define VBNV_RECOVERY_RW_DEV_MISMATCH 0x45 |
| /* Shared data error in rewritable firmware */ |
| #define VBNV_RECOVERY_RW_SHARED_DATA 0x46 |
| /* Test error from LoadKernel() */ |
| #define VBNV_RECOVERY_RW_TEST_LK 0x47 |
| /* No bootable disk found (deprecated)*/ |
| #define VBNV_RECOVERY_DEP_RW_NO_DISK 0x48 |
| /* Rebooting did not correct TPM_E_FAIL or TPM_E_FAILEDSELFTEST */ |
| #define VBNV_RECOVERY_TPM_E_FAIL 0x49 |
| /* TPM setup error in read-only firmware */ |
| #define VBNV_RECOVERY_RO_TPM_S_ERROR 0x50 |
| /* TPM write error in read-only firmware */ |
| #define VBNV_RECOVERY_RO_TPM_W_ERROR 0x51 |
| /* TPM lock error in read-only firmware */ |
| #define VBNV_RECOVERY_RO_TPM_L_ERROR 0x52 |
| /* TPM update error in read-only firmware */ |
| #define VBNV_RECOVERY_RO_TPM_U_ERROR 0x53 |
| /* TPM read error in rewritable firmware */ |
| #define VBNV_RECOVERY_RW_TPM_R_ERROR 0x54 |
| /* TPM write error in rewritable firmware */ |
| #define VBNV_RECOVERY_RW_TPM_W_ERROR 0x55 |
| /* TPM lock error in rewritable firmware */ |
| #define VBNV_RECOVERY_RW_TPM_L_ERROR 0x56 |
| /* EC software sync unable to get EC image hash */ |
| #define VBNV_RECOVERY_EC_HASH_FAILED 0x57 |
| /* EC software sync invalid image hash size */ |
| #define VBNV_RECOVERY_EC_HASH_SIZE 0x58 |
| /* Unspecified error while trying to load kernel */ |
| #define VBNV_RECOVERY_LK_UNSPECIFIED 0x59 |
| /* No bootable storage device in system */ |
| #define VBNV_RECOVERY_RW_NO_DISK 0x5A |
| /* No bootable kernel found on disk */ |
| #define VBNV_RECOVERY_RW_NO_KERNEL 0x5B |
| /* BCB-related error in RW firmware */ |
| #define VBNV_RECOVERY_RW_BCB_ERROR 0x5C |
| /* Fastboot mode requested in firmware */ |
| #define VBNV_RECOVERY_FW_FASTBOOT 0x5E |
| /* Unspecified/unknown error in rewritable firmware */ |
| #define VBNV_RECOVERY_RW_UNSPECIFIED 0x7F |
| /* DM-verity error */ |
| #define VBNV_RECOVERY_KE_DM_VERITY 0x81 |
| /* Unspecified/unknown error in kernel */ |
| #define VBNV_RECOVERY_KE_UNSPECIFIED 0xBF |
| /* Recovery mode test from user-mode */ |
| #define VBNV_RECOVERY_US_TEST 0xC1 |
| /* Recovery requested by user-mode via BCB */ |
| #define VBNV_RECOVERY_BCB_USER_MODE 0xC2 |
| /* Fastboot mode requested by user-mode */ |
| #define VBNV_RECOVERY_US_FASTBOOT 0xC3 |
| /* Unspecified/unknown error in user-mode */ |
| #define VBNV_RECOVERY_US_UNSPECIFIED 0xFF |
| |
| /** |
| * Initialize the NV storage library. |
| * |
| * This must be called before any other functions in this library. Returns 0 |
| * if success, non-zero if error. |
| * |
| * Proper calling procedure: |
| * 1) Allocate a context struct. |
| * 2) If multi-threaded/multi-process, acquire a lock to prevent |
| * other processes from modifying the underlying storage. |
| * 3) Read underlying storage and fill in context->raw. |
| * 4) Call VbNvSetup(). |
| * |
| * If you have access to global variables, you may want to wrap all that in |
| * your own VbNvOpen() function. We don't do that in here because there are no |
| * global variables in UEFI BIOS during the PEI phase (that's also why we have |
| * to pass around a context pointer). |
| */ |
| int VbNvSetup(VbNvContext *context); |
| |
| /** |
| * Clean up and flush changes back to the raw data. |
| * |
| * This must be called after other functions in this library. Returns 0 if |
| * success, non-zero if error. |
| * |
| * Proper calling procedure: |
| * 1) Call VbNvExit(). |
| * 2) If context.raw_changed, write data back to underlying storage. |
| * 3) Release any lock you acquired before calling VbNvSetup(). |
| * 4) Free the context struct. |
| * |
| * If you have access to global variables, you may want to wrap this |
| * in your own VbNvClose() function. |
| */ |
| int VbNvTeardown(VbNvContext *context); |
| |
| /** |
| * Read a NV storage parameter into *dest. |
| * |
| * Returns 0 if success, non-zero if error. |
| * |
| * This may only be called between VbNvSetup() and VbNvTeardown(). |
| */ |
| int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest); |
| |
| /** |
| * Set a NV storage param to a new value. |
| * |
| * Returns 0 if success, non-zero if error. |
| * |
| * This may only be called between VbNvSetup() and VbNvTeardown(). |
| */ |
| int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value); |
| |
| /** |
| * Attempt to restore some fields of a lost VbNvContext from a backup area. |
| * The rest of the fields are unchanged, so they'd need to be set to their |
| * appropriate defaults by calling VbNvSetup() first (which is usually how we |
| * know the fields have been lost). |
| * |
| * Returns 0 if success, non-zero if error. |
| * |
| * This may only be called between VbNvSetup() and VbNvTeardown(). |
| */ |
| int RestoreNvFromBackup(VbNvContext *vnc); |
| |
| /** |
| * Attempt to save some fields of the VbNvContext to a backup area. |
| * |
| * Returns 0 if success, non-zero if error. If it succeeds, it will clear the |
| * VBNV_BACKUP_NVRAM_REQUEST flag in the VbNvContext. |
| * |
| * This may only be called when the backup area is writable. |
| */ |
| int SaveNvToBackup(VbNvContext *vnc); |
| |
| #endif /* VBOOT_REFERENCE_NVSTORAGE_H_ */ |