summaryrefslogtreecommitdiff
path: root/firmware/include/vboot_nvstorage.h
blob: 665a5e5dd68ffdd1febbd28b5e5d2bfb9ab16273 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/* 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 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,
	/* 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,

} VbNvParam;

/* 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
/* 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
/* 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_ */