xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2nvstorage.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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