1 /* Copyright 2014 The ChromiumOS Authors
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 */
7
8 #include "2common.h"
9 #include "2crc8.h"
10 #include "2misc.h"
11 #include "2nvstorage_fields.h"
12 #include "2nvstorage.h"
13 #include "2sysincludes.h"
14
vb2_nv_regen_crc(struct vb2_context * ctx)15 static void vb2_nv_regen_crc(struct vb2_context *ctx)
16 {
17 const int offs = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
18 VB2_NV_OFFS_CRC_V2 : VB2_NV_OFFS_CRC_V1;
19
20 ctx->nvdata[offs] = vb2_crc8(ctx->nvdata, offs);
21 ctx->flags |= VB2_CONTEXT_NVDATA_CHANGED;
22 }
23
vb2_nv_get_size(const struct vb2_context * ctx)24 int vb2_nv_get_size(const struct vb2_context *ctx)
25 {
26 return ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
27 VB2_NVDATA_SIZE_V2 : VB2_NVDATA_SIZE;
28 }
29
30 /**
31 * Check the CRC of the non-volatile storage context.
32 *
33 * Use this if reading from non-volatile storage may be flaky, and you want to
34 * retry reading it several times.
35 *
36 * This may be called before vb2_context_init().
37 *
38 * @param ctx Context pointer
39 * @return VB2_SUCCESS, or non-zero error code if error.
40 */
vb2_nv_check_crc(const struct vb2_context * ctx)41 vb2_error_t vb2_nv_check_crc(const struct vb2_context *ctx)
42 {
43 const uint8_t *p = ctx->nvdata;
44 const int offs = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
45 VB2_NV_OFFS_CRC_V2 : VB2_NV_OFFS_CRC_V1;
46 const int sig = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
47 VB2_NV_HEADER_SIGNATURE_V2 : VB2_NV_HEADER_SIGNATURE_V1;
48
49 /* Check header */
50 if (sig != (p[VB2_NV_OFFS_HEADER] & VB2_NV_HEADER_SIGNATURE_MASK))
51 return VB2_ERROR_NV_HEADER;
52
53 /* Check CRC */
54 if (vb2_crc8(p, offs) != p[offs])
55 return VB2_ERROR_NV_CRC;
56
57 return VB2_SUCCESS;
58 }
59
vb2_nv_init(struct vb2_context * ctx)60 void vb2_nv_init(struct vb2_context *ctx)
61 {
62 const int sig = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
63 VB2_NV_HEADER_SIGNATURE_V2 : VB2_NV_HEADER_SIGNATURE_V1;
64 struct vb2_shared_data *sd = vb2_get_sd(ctx);
65 uint8_t *p = ctx->nvdata;
66
67 if (sd->status & VB2_SD_STATUS_NV_INIT)
68 return;
69
70 /* Check data for consistency */
71 if (vb2_nv_check_crc(ctx) != VB2_SUCCESS) {
72 /* Data is inconsistent (bad CRC or header); reset defaults */
73 memset(p, 0, VB2_NVDATA_SIZE_V2);
74 p[VB2_NV_OFFS_HEADER] = (sig |
75 VB2_NV_HEADER_FW_SETTINGS_RESET |
76 VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
77
78 /* Regenerate CRC */
79 vb2_nv_regen_crc(ctx);
80
81 /* Set status flag. */
82 sd->status |= VB2_SD_STATUS_NV_REINIT;
83
84 /* TODO: unit test for status flag being set */
85 } else {
86 #ifndef CHROMEOS_ENVIRONMENT
87 /* Always clear this on first reboot that didn't need reinit. */
88 vb2_nv_set(ctx, VB2_NV_FIRMWARE_SETTINGS_RESET, 0);
89 #endif
90 }
91
92 sd->status |= VB2_SD_STATUS_NV_INIT;
93 }
94
95 /* Macro for vb2_nv_get() single-bit settings to reduce duplicate code. */
96 #define GETBIT(offs, mask) (p[offs] & mask ? 1 : 0)
97
vb2_nv_get(struct vb2_context * ctx,enum vb2_nv_param param)98 uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param)
99 {
100 const uint8_t *p = ctx->nvdata;
101
102 /*
103 * TODO: We could reduce the binary size for this code by #ifdef'ing
104 * out the params not used by firmware verification.
105 */
106 switch (param) {
107 case VB2_NV_FIRMWARE_SETTINGS_RESET:
108 return GETBIT(VB2_NV_OFFS_HEADER,
109 VB2_NV_HEADER_FW_SETTINGS_RESET);
110
111 case VB2_NV_KERNEL_SETTINGS_RESET:
112 return GETBIT(VB2_NV_OFFS_HEADER,
113 VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
114
115 case VB2_NV_DEBUG_RESET_MODE:
116 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
117
118 case VB2_NV_TRY_NEXT:
119 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
120
121 case VB2_NV_TRY_COUNT:
122 return p[VB2_NV_OFFS_BOOT] & VB2_NV_BOOT_TRY_COUNT_MASK;
123
124 case VB2_NV_FW_TRIED:
125 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
126
127 case VB2_NV_FW_RESULT:
128 return p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_RESULT_MASK;
129
130 case VB2_NV_FW_PREV_TRIED:
131 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
132
133 case VB2_NV_FW_PREV_RESULT:
134 return (p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_PREV_RESULT_MASK)
135 >> VB2_NV_BOOT2_PREV_RESULT_SHIFT;
136
137 case VB2_NV_RECOVERY_REQUEST:
138 return p[VB2_NV_OFFS_RECOVERY];
139
140 case VB2_NV_DIAG_REQUEST:
141 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_REQ_DIAG);
142
143 case VB2_NV_RECOVERY_SUBCODE:
144 return p[VB2_NV_OFFS_RECOVERY_SUBCODE];
145
146 case VB2_NV_LOCALIZATION_INDEX:
147 return p[VB2_NV_OFFS_LOCALIZATION];
148
149 case VB2_NV_KERNEL_FIELD:
150 return p[VB2_NV_OFFS_KERNEL1] | (p[VB2_NV_OFFS_KERNEL2] << 8);
151
152 case VB2_NV_DEV_BOOT_EXTERNAL:
153 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_EXTERNAL);
154
155 case VB2_NV_DEV_BOOT_ALTFW:
156 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
157
158 case VB2_NV_DEV_BOOT_SIGNED_ONLY:
159 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
160
161 case VB2_NV_DEV_DEFAULT_BOOT:
162 return (p[VB2_NV_OFFS_DEV] & VB2_NV_DEV_FLAG_DEFAULT_BOOT)
163 >> VB2_NV_DEV_DEFAULT_BOOT_SHIFT;
164
165 case VB2_NV_DEV_ENABLE_UDC:
166 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_UDC);
167
168 case VB2_NV_DISABLE_DEV_REQUEST:
169 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
170
171 case VB2_NV_DISPLAY_REQUEST:
172 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISPLAY_REQUEST);
173
174 case VB2_NV_BACKUP_NVRAM_REQUEST:
175 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
176
177 case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
178 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
179
180 case VB2_NV_CLEAR_TPM_OWNER_DONE:
181 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
182
183 case VB2_NV_TPM_REQUESTED_REBOOT:
184 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
185
186 case VB2_NV_REQ_WIPEOUT:
187 return GETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
188
189 case VB2_NV_BOOT_ON_AC_DETECT:
190 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
191
192 case VB2_NV_TRY_RO_SYNC:
193 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
194
195 case VB2_NV_BATTERY_CUTOFF_REQUEST:
196 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
197
198 case VB2_NV_KERNEL_MAX_ROLLFORWARD:
199 return (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1]
200 | (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2] << 8)
201 | (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3] << 16)
202 | ((uint32_t)p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4]
203 << 24));
204
205 case VB2_NV_FW_MAX_ROLLFORWARD:
206 /* Field only present in V2 */
207 if (!(ctx->flags & VB2_CONTEXT_NVDATA_V2))
208 return VB2_FW_MAX_ROLLFORWARD_V1_DEFAULT;
209
210 return (p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD1]
211 | (p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD2] << 8)
212 | (p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD3] << 16)
213 | ((uint32_t)p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD4] << 24));
214
215 case VB2_NV_POST_EC_SYNC_DELAY:
216 return GETBIT(VB2_NV_OFFS_MISC,
217 VB2_NV_MISC_POST_EC_SYNC_DELAY);
218
219 case VB2_NV_MINIOS_PRIORITY:
220 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_MINIOS_PRIORITY);
221
222 case VB2_NV_DEPRECATED_DEV_BOOT_FASTBOOT_FULL_CAP:
223 case VB2_NV_DEPRECATED_FASTBOOT_UNLOCK_IN_FW:
224 case VB2_NV_DEPRECATED_ENABLE_ALT_OS_REQUEST:
225 case VB2_NV_DEPRECATED_DISABLE_ALT_OS_REQUEST:
226 return 0;
227 }
228
229 /*
230 * Put default return outside the switch() instead of in default:, so
231 * that adding a new param will cause a compiler warning.
232 */
233 return 0;
234 }
235
236 #undef GETBIT
237
238 /* Macro for vb2_nv_set() single-bit settings to reduce duplicate code. */
239 #define SETBIT(offs, mask) \
240 { if (value) p[offs] |= mask; else p[offs] &= ~mask; }
241
242 test_mockable
vb2_nv_set(struct vb2_context * ctx,enum vb2_nv_param param,uint32_t value)243 void vb2_nv_set(struct vb2_context *ctx,
244 enum vb2_nv_param param,
245 uint32_t value)
246 {
247 uint8_t *p = ctx->nvdata;
248
249 /* If not changing the value, don't regenerate the CRC. */
250 if (vb2_nv_get(ctx, param) == value)
251 return;
252
253 /*
254 * TODO: We could reduce the binary size for this code by #ifdef'ing
255 * out the params not used by firmware verification.
256 */
257 switch (param) {
258 case VB2_NV_FIRMWARE_SETTINGS_RESET:
259 SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_FW_SETTINGS_RESET);
260 break;
261
262 case VB2_NV_KERNEL_SETTINGS_RESET:
263 SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
264 break;
265
266 case VB2_NV_DEBUG_RESET_MODE:
267 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
268 break;
269
270 case VB2_NV_TRY_NEXT:
271 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
272 break;
273
274 case VB2_NV_TRY_COUNT:
275 /* Clip to valid range. */
276 if (value > VB2_NV_BOOT_TRY_COUNT_MASK)
277 value = VB2_NV_BOOT_TRY_COUNT_MASK;
278
279 p[VB2_NV_OFFS_BOOT] &= ~VB2_NV_BOOT_TRY_COUNT_MASK;
280 p[VB2_NV_OFFS_BOOT] |= (uint8_t)value;
281 break;
282
283 case VB2_NV_FW_TRIED:
284 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
285 break;
286
287 case VB2_NV_FW_RESULT:
288 /* Map out of range values to unknown */
289 if (value > VB2_NV_BOOT2_RESULT_MASK)
290 value = VB2_FW_RESULT_UNKNOWN;
291
292 p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_RESULT_MASK;
293 p[VB2_NV_OFFS_BOOT2] |= (uint8_t)value;
294 break;
295
296 case VB2_NV_FW_PREV_TRIED:
297 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
298 break;
299
300 case VB2_NV_FW_PREV_RESULT:
301 /* Map out of range values to unknown */
302 if (value > VB2_NV_BOOT2_RESULT_MASK)
303 value = VB2_FW_RESULT_UNKNOWN;
304
305 p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_PREV_RESULT_MASK;
306 p[VB2_NV_OFFS_BOOT2] |=
307 (uint8_t)(value << VB2_NV_BOOT2_PREV_RESULT_SHIFT);
308 break;
309
310 case VB2_NV_RECOVERY_REQUEST:
311 /*
312 * Map values outside the valid range to the legacy reason,
313 * since we can't determine if we're called from kernel or user
314 * mode.
315 */
316 if (value > 0xff)
317 value = VB2_RECOVERY_LEGACY;
318 p[VB2_NV_OFFS_RECOVERY] = (uint8_t)value;
319 break;
320
321 case VB2_NV_DIAG_REQUEST:
322 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_REQ_DIAG);
323 break;
324
325 case VB2_NV_RECOVERY_SUBCODE:
326 p[VB2_NV_OFFS_RECOVERY_SUBCODE] = (uint8_t)value;
327 break;
328
329 case VB2_NV_LOCALIZATION_INDEX:
330 /* Map values outside the valid range to the default index. */
331 if (value > 0xFF)
332 value = 0;
333 p[VB2_NV_OFFS_LOCALIZATION] = (uint8_t)value;
334 break;
335
336 case VB2_NV_KERNEL_FIELD:
337 p[VB2_NV_OFFS_KERNEL1] = (uint8_t)(value);
338 p[VB2_NV_OFFS_KERNEL2] = (uint8_t)(value >> 8);
339 break;
340
341 case VB2_NV_DEV_BOOT_EXTERNAL:
342 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_EXTERNAL);
343 break;
344
345 case VB2_NV_DEV_BOOT_ALTFW:
346 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
347 break;
348
349 case VB2_NV_DEV_BOOT_SIGNED_ONLY:
350 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
351 break;
352
353 case VB2_NV_DEV_DEFAULT_BOOT:
354 /* Map out of range values to disk */
355 if (value > (VB2_NV_DEV_FLAG_DEFAULT_BOOT >>
356 VB2_NV_DEV_DEFAULT_BOOT_SHIFT))
357 value = VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL;
358
359 p[VB2_NV_OFFS_DEV] &= ~VB2_NV_DEV_FLAG_DEFAULT_BOOT;
360 p[VB2_NV_OFFS_DEV] |=
361 (uint8_t)(value << VB2_NV_DEV_DEFAULT_BOOT_SHIFT);
362 break;
363
364 case VB2_NV_DEV_ENABLE_UDC:
365 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_UDC);
366 break;
367
368 case VB2_NV_DISABLE_DEV_REQUEST:
369 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
370 break;
371
372 case VB2_NV_DISPLAY_REQUEST:
373 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISPLAY_REQUEST);
374 break;
375
376 case VB2_NV_BACKUP_NVRAM_REQUEST:
377 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
378 break;
379
380 case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
381 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
382 break;
383
384 case VB2_NV_CLEAR_TPM_OWNER_DONE:
385 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
386 break;
387
388 case VB2_NV_TPM_REQUESTED_REBOOT:
389 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
390 break;
391
392 case VB2_NV_REQ_WIPEOUT:
393 SETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
394 break;
395
396 case VB2_NV_BOOT_ON_AC_DETECT:
397 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
398 break;
399
400 case VB2_NV_TRY_RO_SYNC:
401 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
402 break;
403
404 case VB2_NV_BATTERY_CUTOFF_REQUEST:
405 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
406 break;
407
408 case VB2_NV_KERNEL_MAX_ROLLFORWARD:
409 p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1] = (uint8_t)(value);
410 p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2] = (uint8_t)(value >> 8);
411 p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3] = (uint8_t)(value >> 16);
412 p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4] = (uint8_t)(value >> 24);
413 break;
414
415 case VB2_NV_FW_MAX_ROLLFORWARD:
416 /* Field only present in V2 */
417 if (!(ctx->flags & VB2_CONTEXT_NVDATA_V2))
418 return;
419
420 p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD1] = (uint8_t)(value);
421 p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD2] = (uint8_t)(value >> 8);
422 p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD3] = (uint8_t)(value >> 16);
423 p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD4] = (uint8_t)(value >> 24);
424 break;
425
426 case VB2_NV_POST_EC_SYNC_DELAY:
427 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_POST_EC_SYNC_DELAY);
428 break;
429
430 case VB2_NV_MINIOS_PRIORITY:
431 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_MINIOS_PRIORITY);
432 break;
433
434 case VB2_NV_DEPRECATED_DEV_BOOT_FASTBOOT_FULL_CAP:
435 case VB2_NV_DEPRECATED_FASTBOOT_UNLOCK_IN_FW:
436 case VB2_NV_DEPRECATED_ENABLE_ALT_OS_REQUEST:
437 case VB2_NV_DEPRECATED_DISABLE_ALT_OS_REQUEST:
438 return;
439 }
440
441 /*
442 * Note there is no default case. This causes a compiler warning if
443 * a new param is added to the enum without adding support here.
444 */
445
446 /* Need to regenerate CRC, since the value changed. */
447 vb2_nv_regen_crc(ctx);
448 }
449
450 #undef SETBIT
451