b40bbe78df88a773fa9cfd94ac159fd99f421b58
[akaros.git] / kern / lib / crypto / 2nvstorage.c
1 /* Copyright (c) 2014 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 */
7
8 #include "2sysincludes.h"
9 #include "2common.h"
10 #include "2crc8.h"
11 #include "2misc.h"
12 #include "2nvstorage.h"
13 #include "2nvstorage_fields.h"
14
15 static void vb2_nv_regen_crc(struct vb2_context *ctx)
16 {
17         ctx->nvdata[VB2_NV_OFFS_CRC] = vb2_crc8(ctx->nvdata, VB2_NV_OFFS_CRC);
18         ctx->flags |= VB2_CONTEXT_NVDATA_CHANGED;
19 }
20
21 /**
22  * Check the CRC of the non-volatile storage context.
23  *
24  * Use this if reading from non-volatile storage may be flaky, and you want to
25  * retry reading it several times.
26  *
27  * This may be called before vb2_context_init().
28  *
29  * @param ctx           Context pointer
30  * @return VB2_SUCCESS, or non-zero error code if error.
31  */
32 int vb2_nv_check_crc(const struct vb2_context *ctx)
33 {
34         const uint8_t *p = ctx->nvdata;
35
36         /* Check header */
37         if (VB2_NV_HEADER_SIGNATURE !=
38             (p[VB2_NV_OFFS_HEADER] & VB2_NV_HEADER_MASK))
39                 return VB2_ERROR_NV_HEADER;
40
41         /* Check CRC */
42         if (vb2_crc8(p, VB2_NV_OFFS_CRC) != p[VB2_NV_OFFS_CRC])
43                 return VB2_ERROR_NV_CRC;
44
45         return VB2_SUCCESS;
46 }
47
48 void vb2_nv_init(struct vb2_context *ctx)
49 {
50         struct vb2_shared_data *sd = vb2_get_sd(ctx);
51         uint8_t *p = ctx->nvdata;
52
53         /* Check data for consistency */
54         if (vb2_nv_check_crc(ctx) != VB2_SUCCESS) {
55                 /* Data is inconsistent (bad CRC or header); reset defaults */
56                 memset(p, 0, VB2_NVDATA_SIZE);
57                 p[VB2_NV_OFFS_HEADER] = (VB2_NV_HEADER_SIGNATURE |
58                                          VB2_NV_HEADER_FW_SETTINGS_RESET |
59                                          VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
60
61                 /* Regenerate CRC */
62                 vb2_nv_regen_crc(ctx);
63
64                 /* Set status flag */
65                 sd->status |= VB2_SD_STATUS_NV_REINIT;
66                 /* TODO: unit test for status flag being set */
67         }
68
69         sd->status |= VB2_SD_STATUS_NV_INIT;
70 }
71
72 /* Macro for vb2_nv_get() single-bit settings to reduce duplicate code. */
73 #define GETBIT(offs, mask) (p[offs] & mask ? 1 : 0)
74
75 uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param)
76 {
77         const uint8_t *p = ctx->nvdata;
78
79         /*
80          * TODO: We could reduce the binary size for this code by #ifdef'ing
81          * out the params not used by firmware verification.
82          */
83         switch (param) {
84         case VB2_NV_FIRMWARE_SETTINGS_RESET:
85                 return GETBIT(VB2_NV_OFFS_HEADER,
86                               VB2_NV_HEADER_FW_SETTINGS_RESET);
87
88         case VB2_NV_KERNEL_SETTINGS_RESET:
89                 return GETBIT(VB2_NV_OFFS_HEADER,
90                               VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
91
92         case VB2_NV_DEBUG_RESET_MODE:
93                 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
94
95         case VB2_NV_TRY_NEXT:
96                 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
97
98         case VB2_NV_TRY_COUNT:
99                 return p[VB2_NV_OFFS_BOOT] & VB2_NV_BOOT_TRY_COUNT_MASK;
100
101         case VB2_NV_FW_TRIED:
102                 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
103
104         case VB2_NV_FW_RESULT:
105                 return p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_RESULT_MASK;
106
107         case VB2_NV_FW_PREV_TRIED:
108                 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
109
110         case VB2_NV_FW_PREV_RESULT:
111                 return (p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_PREV_RESULT_MASK)
112                         >> VB2_NV_BOOT2_PREV_RESULT_SHIFT;
113
114         case VB2_NV_RECOVERY_REQUEST:
115                 return p[VB2_NV_OFFS_RECOVERY];
116
117         case VB2_NV_RECOVERY_SUBCODE:
118                 return p[VB2_NV_OFFS_RECOVERY_SUBCODE];
119
120         case VB2_NV_LOCALIZATION_INDEX:
121                 return p[VB2_NV_OFFS_LOCALIZATION];
122
123         case VB2_NV_KERNEL_FIELD:
124                 return (p[VB2_NV_OFFS_KERNEL]
125                         | (p[VB2_NV_OFFS_KERNEL + 1] << 8)
126                         | (p[VB2_NV_OFFS_KERNEL + 2] << 16)
127                         | (p[VB2_NV_OFFS_KERNEL + 3] << 24));
128
129         case VB2_NV_DEV_BOOT_USB:
130                 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB);
131
132         case VB2_NV_DEV_BOOT_LEGACY:
133                 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
134
135         case VB2_NV_DEV_BOOT_SIGNED_ONLY:
136                 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
137
138         case VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP:
139                 return GETBIT(VB2_NV_OFFS_DEV,
140                               VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP);
141
142         case VB2_NV_DEV_DEFAULT_BOOT:
143                 return (p[VB2_NV_OFFS_DEV] & VB2_NV_DEV_FLAG_DEFAULT_BOOT)
144                         >> VB2_NV_DEV_DEFAULT_BOOT_SHIFT;
145
146         case VB2_NV_DISABLE_DEV_REQUEST:
147                 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
148
149         case VB2_NV_OPROM_NEEDED:
150                 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED);
151
152         case VB2_NV_BACKUP_NVRAM_REQUEST:
153                 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
154
155         case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
156                 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
157
158         case VB2_NV_CLEAR_TPM_OWNER_DONE:
159                 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
160
161         case VB2_NV_TPM_REQUESTED_REBOOT:
162                 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
163
164         case VB2_NV_REQ_WIPEOUT:
165                 return GETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
166
167         case VB2_NV_FASTBOOT_UNLOCK_IN_FW:
168                 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_UNLOCK_FASTBOOT);
169
170         case VB2_NV_BOOT_ON_AC_DETECT:
171                 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
172
173         case VB2_NV_TRY_RO_SYNC:
174                 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
175
176         case VB2_NV_BATTERY_CUTOFF_REQUEST:
177                 return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
178         }
179
180         /*
181          * Put default return outside the switch() instead of in default:, so
182          * that adding a new param will cause a compiler warning.
183          */
184         return 0;
185 }
186
187 #undef GETBIT
188
189 /* Macro for vb2_nv_set() single-bit settings to reduce duplicate code. */
190 #define SETBIT(offs, mask)                                      \
191         { if (value) p[offs] |= mask; else p[offs] &= ~mask; }
192
193 void vb2_nv_set(struct vb2_context *ctx,
194                 enum vb2_nv_param param,
195                 uint32_t value)
196 {
197         uint8_t *p = ctx->nvdata;
198
199         /* If not changing the value, don't regenerate the CRC. */
200         if (vb2_nv_get(ctx, param) == value)
201                 return;
202
203         /*
204          * TODO: We could reduce the binary size for this code by #ifdef'ing
205          * out the params not used by firmware verification.
206          */
207         switch (param) {
208         case VB2_NV_FIRMWARE_SETTINGS_RESET:
209                 SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_FW_SETTINGS_RESET);
210                 break;
211
212         case VB2_NV_KERNEL_SETTINGS_RESET:
213                 SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
214                 break;
215
216         case VB2_NV_DEBUG_RESET_MODE:
217                 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
218                 break;
219
220         case VB2_NV_TRY_NEXT:
221                 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
222                 break;
223
224         case VB2_NV_TRY_COUNT:
225                 /* Clip to valid range. */
226                 if (value > VB2_NV_BOOT_TRY_COUNT_MASK)
227                         value = VB2_NV_BOOT_TRY_COUNT_MASK;
228
229                 p[VB2_NV_OFFS_BOOT] &= ~VB2_NV_BOOT_TRY_COUNT_MASK;
230                 p[VB2_NV_OFFS_BOOT] |= (uint8_t)value;
231                 break;
232
233         case VB2_NV_FW_TRIED:
234                 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
235                 break;
236
237         case VB2_NV_FW_RESULT:
238                 /* Map out of range values to unknown */
239                 if (value > VB2_NV_BOOT2_RESULT_MASK)
240                         value = VB2_FW_RESULT_UNKNOWN;
241
242                 p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_RESULT_MASK;
243                 p[VB2_NV_OFFS_BOOT2] |= (uint8_t)value;
244                 break;
245
246         case VB2_NV_FW_PREV_TRIED:
247                 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
248                 break;
249
250         case VB2_NV_FW_PREV_RESULT:
251                 /* Map out of range values to unknown */
252                 if (value > VB2_NV_BOOT2_RESULT_MASK)
253                         value = VB2_FW_RESULT_UNKNOWN;
254
255                 p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_PREV_RESULT_MASK;
256                 p[VB2_NV_OFFS_BOOT2] |=
257                         (uint8_t)(value << VB2_NV_BOOT2_PREV_RESULT_SHIFT);
258                 break;
259
260         case VB2_NV_RECOVERY_REQUEST:
261                 /*
262                  * Map values outside the valid range to the legacy reason,
263                  * since we can't determine if we're called from kernel or user
264                  * mode.
265                  */
266                 if (value > 0xff)
267                         value = VB2_RECOVERY_LEGACY;
268                 p[VB2_NV_OFFS_RECOVERY] = (uint8_t)value;
269                 break;
270
271         case VB2_NV_RECOVERY_SUBCODE:
272                 p[VB2_NV_OFFS_RECOVERY_SUBCODE] = (uint8_t)value;
273                 break;
274
275         case VB2_NV_LOCALIZATION_INDEX:
276                 /* Map values outside the valid range to the default index. */
277                 if (value > 0xFF)
278                         value = 0;
279                 p[VB2_NV_OFFS_LOCALIZATION] = (uint8_t)value;
280                 break;
281
282         case VB2_NV_KERNEL_FIELD:
283                 p[VB2_NV_OFFS_KERNEL] = (uint8_t)(value);
284                 p[VB2_NV_OFFS_KERNEL + 1] = (uint8_t)(value >> 8);
285                 p[VB2_NV_OFFS_KERNEL + 2] = (uint8_t)(value >> 16);
286                 p[VB2_NV_OFFS_KERNEL + 3] = (uint8_t)(value >> 24);
287                 break;
288
289         case VB2_NV_DEV_BOOT_USB:
290                 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB);
291                 break;
292
293         case VB2_NV_DEV_BOOT_LEGACY:
294                 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
295                 break;
296
297         case VB2_NV_DEV_BOOT_SIGNED_ONLY:
298                 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
299                 break;
300
301         case VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP:
302                 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP);
303                 break;
304
305         case VB2_NV_DEV_DEFAULT_BOOT:
306                 /* Map out of range values to disk */
307                 if (value > (VB2_NV_DEV_FLAG_DEFAULT_BOOT >>
308                              VB2_NV_DEV_DEFAULT_BOOT_SHIFT))
309                         value = VB2_DEV_DEFAULT_BOOT_DISK;
310
311                 p[VB2_NV_OFFS_DEV] &= ~VB2_NV_DEV_FLAG_DEFAULT_BOOT;
312                 p[VB2_NV_OFFS_DEV] |=
313                         (uint8_t)(value << VB2_NV_DEV_DEFAULT_BOOT_SHIFT);
314                 break;
315
316         case VB2_NV_DISABLE_DEV_REQUEST:
317                 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
318                 break;
319
320         case VB2_NV_OPROM_NEEDED:
321                 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED);
322                 break;
323
324         case VB2_NV_BACKUP_NVRAM_REQUEST:
325                 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
326                 break;
327
328         case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
329                 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
330                 break;
331
332         case VB2_NV_CLEAR_TPM_OWNER_DONE:
333                 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
334                 break;
335
336         case VB2_NV_TPM_REQUESTED_REBOOT:
337                 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
338                 break;
339
340         case VB2_NV_REQ_WIPEOUT:
341                 SETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
342                 break;
343
344         case VB2_NV_FASTBOOT_UNLOCK_IN_FW:
345                 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_UNLOCK_FASTBOOT);
346                 break;
347
348         case VB2_NV_BOOT_ON_AC_DETECT:
349                 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
350                 break;
351
352         case VB2_NV_TRY_RO_SYNC:
353                 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
354                 break;
355
356         case VB2_NV_BATTERY_CUTOFF_REQUEST:
357                 SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
358                 break;
359         }
360
361         /*
362          * Note there is no default case.  This causes a compiler warning if
363          * a new param is added to the enum without adding support here.
364          */
365
366         /* Need to regenerate CRC, since the value changed. */
367         vb2_nv_regen_crc(ctx);
368 }
369
370 #undef SETBIT