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