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
14typedef 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(). */
32typedef 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 */
109typedef 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 */
272int 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 */
289int 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 */
298int 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 */
307int 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 */
319int 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 */
329int SaveNvToBackup(VbNvContext *vnc);
330
331#endif  /* VBOOT_REFERENCE_NVSTORAGE_H_ */
332