blob: 04080794cafa56c9b8a3f21e5c4f7616b6bd2c41 [file] [log] [blame]
Tom Rinif739fcd2018-05-07 17:02:21 -04001// SPDX-License-Identifier: GPL-2.0+
Rob Clarkad644e72017-09-13 18:05:37 -04002/*
Heinrich Schuchardtf0b0f7f2020-03-19 17:15:18 +00003 * UEFI runtime variable services
Rob Clarkad644e72017-09-13 18:05:37 -04004 *
Heinrich Schuchardtf0b0f7f2020-03-19 17:15:18 +00005 * Copyright (c) 2017 Rob Clark
Rob Clarkad644e72017-09-13 18:05:37 -04006 */
7
Heinrich Schuchardte731af42019-10-26 23:53:48 +02008#include <common.h>
Rob Clarkad644e72017-09-13 18:05:37 -04009#include <efi_loader.h>
Simon Glassf3998fd2019-08-02 09:44:25 -060010#include <env_internal.h>
Heinrich Schuchardte731af42019-10-26 23:53:48 +020011#include <hexdump.h>
12#include <malloc.h>
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090013#include <rtc.h>
AKASHI Takahirod99a87f2019-01-21 12:43:13 +010014#include <search.h>
Simon Glassba06b3c2020-05-10 11:39:52 -060015#include <uuid.h>
AKASHI Takahiroe3f5c9c2020-04-21 09:38:17 +090016#include <crypto/pkcs7_parser.h>
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090017#include <linux/compat.h>
Simon Glass3db71102019-11-14 12:57:16 -070018#include <u-boot/crc.h>
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090019
AKASHI Takahiro434ffb62020-04-14 11:51:42 +090020enum efi_secure_mode {
21 EFI_MODE_SETUP,
22 EFI_MODE_USER,
23 EFI_MODE_AUDIT,
24 EFI_MODE_DEPLOYED,
25};
26
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090027const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
28static bool efi_secure_boot;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +090029static int efi_secure_mode;
AKASHI Takahiro83535162020-04-14 11:51:43 +090030static u8 efi_vendor_keys;
Rob Clarkad644e72017-09-13 18:05:37 -040031
32#define READ_ONLY BIT(31)
33
Heinrich Schuchardt306bf6e2020-05-06 01:51:04 +020034static efi_status_t efi_get_variable_common(u16 *variable_name,
35 const efi_guid_t *vendor,
36 u32 *attributes,
37 efi_uintn_t *data_size, void *data);
38
39static efi_status_t efi_set_variable_common(u16 *variable_name,
40 const efi_guid_t *vendor,
41 u32 attributes,
42 efi_uintn_t data_size,
43 const void *data,
44 bool ro_check);
45
Rob Clarkad644e72017-09-13 18:05:37 -040046/*
47 * Mapping between EFI variables and u-boot variables:
48 *
49 * efi_$guid_$varname = {attributes}(type)value
50 *
51 * For example:
52 *
53 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
54 * "{ro,boot,run}(blob)0000000000000000"
55 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
56 * "(blob)00010000"
57 *
58 * The attributes are a comma separated list of these possible
59 * attributes:
60 *
61 * + ro - read-only
62 * + boot - boot-services access
63 * + run - runtime access
64 *
65 * NOTE: with current implementation, no variables are available after
66 * ExitBootServices, and all are persisted (if possible).
67 *
68 * If not specified, the attributes default to "{boot}".
69 *
70 * The required type is one of:
71 *
72 * + utf8 - raw utf8 string
73 * + blob - arbitrary length hex string
74 *
75 * Maybe a utf16 type would be useful to for a string value to be auto
76 * converted to utf16?
77 */
78
Heinrich Schuchardt506dc522018-09-23 04:08:09 +020079#define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_"))
Rob Clarkad644e72017-09-13 18:05:37 -040080
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +010081/**
82 * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot
83 * variable name
84 *
85 * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring
86 * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by
87 * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'.
88 *
89 * @native: pointer to pointer to U-Boot variable name
90 * @variable_name: UEFI variable name
91 * @vendor: vendor GUID
92 * Return: status code
93 */
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +020094static efi_status_t efi_to_native(char **native, const u16 *variable_name,
Heinrich Schuchardt0bda81b2018-12-30 20:53:51 +010095 const efi_guid_t *vendor)
Rob Clarkad644e72017-09-13 18:05:37 -040096{
97 size_t len;
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +020098 char *pos;
Rob Clarkad644e72017-09-13 18:05:37 -040099
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +0200100 len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
101 *native = malloc(len);
102 if (!*native)
103 return EFI_OUT_OF_RESOURCES;
Rob Clarkad644e72017-09-13 18:05:37 -0400104
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +0200105 pos = *native;
106 pos += sprintf(pos, "efi_%pUl_", vendor);
107 utf16_utf8_strcpy(&pos, variable_name);
Rob Clarkad644e72017-09-13 18:05:37 -0400108
109 return EFI_SUCCESS;
110}
111
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100112/**
113 * prefix() - skip over prefix
114 *
115 * Skip over a prefix string.
116 *
117 * @str: string with prefix
118 * @prefix: prefix string
119 * Return: string without prefix, or NULL if prefix not found
120 */
Rob Clarkad644e72017-09-13 18:05:37 -0400121static const char *prefix(const char *str, const char *prefix)
122{
123 size_t n = strlen(prefix);
124 if (!strncmp(prefix, str, n))
125 return str + n;
126 return NULL;
127}
128
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100129/**
130 * parse_attr() - decode attributes part of variable value
131 *
132 * Convert the string encoded attributes of a UEFI variable to a bit mask.
133 * TODO: Several attributes are not supported.
134 *
135 * @str: value of U-Boot variable
136 * @attrp: pointer to UEFI attributes
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900137 * @timep: pointer to time attribute
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100138 * Return: pointer to remainder of U-Boot variable value
139 */
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900140static const char *parse_attr(const char *str, u32 *attrp, u64 *timep)
Rob Clarkad644e72017-09-13 18:05:37 -0400141{
142 u32 attr = 0;
143 char sep = '{';
144
145 if (*str != '{') {
146 *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
147 return str;
148 }
149
150 while (*str == sep) {
151 const char *s;
152
153 str++;
154
155 if ((s = prefix(str, "ro"))) {
156 attr |= READ_ONLY;
AKASHI Takahirocee2cbc2019-06-04 15:52:06 +0900157 } else if ((s = prefix(str, "nv"))) {
158 attr |= EFI_VARIABLE_NON_VOLATILE;
Rob Clarkad644e72017-09-13 18:05:37 -0400159 } else if ((s = prefix(str, "boot"))) {
160 attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
161 } else if ((s = prefix(str, "run"))) {
162 attr |= EFI_VARIABLE_RUNTIME_ACCESS;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900163 } else if ((s = prefix(str, "time="))) {
164 attr |= EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
165 hex2bin((u8 *)timep, s, sizeof(*timep));
166 s += sizeof(*timep) * 2;
167 } else if (*str == '}') {
168 break;
Rob Clarkad644e72017-09-13 18:05:37 -0400169 } else {
170 printf("invalid attribute: %s\n", str);
171 break;
172 }
173
174 str = s;
175 sep = ',';
176 }
177
178 str++;
179
180 *attrp = attr;
181
182 return str;
183}
184
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900185/**
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900186 * efi_set_secure_state - modify secure boot state variables
187 * @sec_boot: value of SecureBoot
188 * @setup_mode: value of SetupMode
189 * @audit_mode: value of AuditMode
190 * @deployed_mode: value of DeployedMode
191 *
192 * Modify secure boot stat-related variables as indicated.
193 *
194 * Return: status code
195 */
196static efi_status_t efi_set_secure_state(int sec_boot, int setup_mode,
197 int audit_mode, int deployed_mode)
198{
199 u32 attributes;
200 efi_status_t ret;
201
202 attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
203 EFI_VARIABLE_RUNTIME_ACCESS |
204 READ_ONLY;
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200205 ret = efi_set_variable_common(L"SecureBoot", &efi_global_variable_guid,
206 attributes, sizeof(sec_boot), &sec_boot,
207 false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900208 if (ret != EFI_SUCCESS)
209 goto err;
210
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200211 ret = efi_set_variable_common(L"SetupMode", &efi_global_variable_guid,
212 attributes, sizeof(setup_mode),
213 &setup_mode, false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900214 if (ret != EFI_SUCCESS)
215 goto err;
216
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200217 ret = efi_set_variable_common(L"AuditMode", &efi_global_variable_guid,
218 attributes, sizeof(audit_mode),
219 &audit_mode, false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900220 if (ret != EFI_SUCCESS)
221 goto err;
222
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200223 ret = efi_set_variable_common(L"DeployedMode",
224 &efi_global_variable_guid, attributes,
225 sizeof(deployed_mode), &deployed_mode,
226 false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900227err:
228 return ret;
229}
230
231/**
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900232 * efi_transfer_secure_state - handle a secure boot state transition
233 * @mode: new state
234 *
235 * Depending on @mode, secure boot related variables are updated.
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200236 * Those variables are *read-only* for users, efi_set_variable_common()
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900237 * is called here.
238 *
Heinrich Schuchardt30f92ce2020-05-03 16:29:00 +0200239 * Return: status code
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900240 */
241static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
242{
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900243 efi_status_t ret;
244
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900245 debug("Switching secure state from %d to %d\n", efi_secure_mode, mode);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900246
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900247 if (mode == EFI_MODE_DEPLOYED) {
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900248 ret = efi_set_secure_state(1, 0, 0, 1);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900249 if (ret != EFI_SUCCESS)
250 goto err;
251
252 efi_secure_boot = true;
253 } else if (mode == EFI_MODE_AUDIT) {
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200254 ret = efi_set_variable_common(L"PK", &efi_global_variable_guid,
255 EFI_VARIABLE_BOOTSERVICE_ACCESS |
256 EFI_VARIABLE_RUNTIME_ACCESS,
257 0, NULL, false);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900258 if (ret != EFI_SUCCESS)
259 goto err;
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900260
261 ret = efi_set_secure_state(0, 1, 1, 0);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900262 if (ret != EFI_SUCCESS)
263 goto err;
264
265 efi_secure_boot = true;
266 } else if (mode == EFI_MODE_USER) {
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900267 ret = efi_set_secure_state(1, 0, 0, 0);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900268 if (ret != EFI_SUCCESS)
269 goto err;
270
271 efi_secure_boot = true;
272 } else if (mode == EFI_MODE_SETUP) {
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900273 ret = efi_set_secure_state(0, 1, 0, 0);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900274 if (ret != EFI_SUCCESS)
275 goto err;
276 } else {
277 return EFI_INVALID_PARAMETER;
278 }
279
AKASHI Takahiro83535162020-04-14 11:51:43 +0900280 efi_secure_mode = mode;
281
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900282 return EFI_SUCCESS;
283
284err:
285 /* TODO: What action should be taken here? */
286 printf("ERROR: Secure state transition failed\n");
287 return ret;
288}
289
290/**
291 * efi_init_secure_state - initialize secure boot state
292 *
Heinrich Schuchardt30f92ce2020-05-03 16:29:00 +0200293 * Return: status code
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900294 */
295static efi_status_t efi_init_secure_state(void)
296{
AKASHI Takahiro83535162020-04-14 11:51:43 +0900297 enum efi_secure_mode mode;
298 efi_uintn_t size;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900299 efi_status_t ret;
300
AKASHI Takahiro83535162020-04-14 11:51:43 +0900301 /*
302 * TODO:
303 * Since there is currently no "platform-specific" installation
304 * method of Platform Key, we can't say if VendorKeys is 0 or 1
305 * precisely.
306 */
307
308 size = 0;
Heinrich Schuchardt306bf6e2020-05-06 01:51:04 +0200309 ret = efi_get_variable_common(L"PK", &efi_global_variable_guid,
310 NULL, &size, NULL);
AKASHI Takahiro83535162020-04-14 11:51:43 +0900311 if (ret == EFI_BUFFER_TOO_SMALL) {
312 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
313 mode = EFI_MODE_USER;
314 else
315 mode = EFI_MODE_SETUP;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900316
AKASHI Takahiro83535162020-04-14 11:51:43 +0900317 efi_vendor_keys = 0;
318 } else if (ret == EFI_NOT_FOUND) {
319 mode = EFI_MODE_SETUP;
320 efi_vendor_keys = 1;
321 } else {
322 goto err;
323 }
324
325 ret = efi_transfer_secure_state(mode);
326 if (ret == EFI_SUCCESS)
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200327 ret = efi_set_variable_common(L"VendorKeys",
328 &efi_global_variable_guid,
329 EFI_VARIABLE_BOOTSERVICE_ACCESS |
330 EFI_VARIABLE_RUNTIME_ACCESS |
331 READ_ONLY,
332 sizeof(efi_vendor_keys),
333 &efi_vendor_keys, false);
AKASHI Takahiro83535162020-04-14 11:51:43 +0900334
335err:
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900336 return ret;
337}
338
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100339/**
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900340 * efi_secure_boot_enabled - return if secure boot is enabled or not
341 *
342 * Return: true if enabled, false if disabled
343 */
344bool efi_secure_boot_enabled(void)
345{
346 return efi_secure_boot;
347}
348
349#ifdef CONFIG_EFI_SECURE_BOOT
350static u8 pkcs7_hdr[] = {
351 /* SEQUENCE */
352 0x30, 0x82, 0x05, 0xc7,
353 /* OID: pkcs7-signedData */
354 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
355 /* Context Structured? */
356 0xa0, 0x82, 0x05, 0xb8,
357};
358
359/**
360 * efi_variable_parse_signature - parse a signature in variable
361 * @buf: Pointer to variable's value
362 * @buflen: Length of @buf
363 *
364 * Parse a signature embedded in variable's value and instantiate
365 * a pkcs7_message structure. Since pkcs7_parse_message() accepts only
366 * pkcs7's signedData, some header needed be prepended for correctly
367 * parsing authentication data, particularly for variable's.
368 *
369 * Return: Pointer to pkcs7_message structure on success, NULL on error
370 */
371static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
372 size_t buflen)
373{
374 u8 *ebuf;
375 size_t ebuflen, len;
376 struct pkcs7_message *msg;
377
378 /*
379 * This is the best assumption to check if the binary is
380 * already in a form of pkcs7's signedData.
381 */
382 if (buflen > sizeof(pkcs7_hdr) &&
383 !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
384 msg = pkcs7_parse_message(buf, buflen);
385 goto out;
386 }
387
388 /*
389 * Otherwise, we should add a dummy prefix sequence for pkcs7
390 * message parser to be able to process.
391 * NOTE: EDK2 also uses similar hack in WrapPkcs7Data()
392 * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c
393 * TODO:
394 * The header should be composed in a more refined manner.
395 */
396 debug("Makeshift prefix added to authentication data\n");
397 ebuflen = sizeof(pkcs7_hdr) + buflen;
398 if (ebuflen <= 0x7f) {
399 debug("Data is too short\n");
400 return NULL;
401 }
402
403 ebuf = malloc(ebuflen);
404 if (!ebuf) {
405 debug("Out of memory\n");
406 return NULL;
407 }
408
409 memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr));
410 memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen);
411 len = ebuflen - 4;
412 ebuf[2] = (len >> 8) & 0xff;
413 ebuf[3] = len & 0xff;
414 len = ebuflen - 0x13;
415 ebuf[0x11] = (len >> 8) & 0xff;
416 ebuf[0x12] = len & 0xff;
417
418 msg = pkcs7_parse_message(ebuf, ebuflen);
419
420 free(ebuf);
421
422out:
423 if (IS_ERR(msg))
424 return NULL;
425
426 return msg;
427}
428
429/**
430 * efi_variable_authenticate - authenticate a variable
431 * @variable: Variable name in u16
432 * @vendor: Guid of variable
433 * @data_size: Size of @data
434 * @data: Pointer to variable's value
435 * @given_attr: Attributes to be given at SetVariable()
436 * @env_attr: Attributes that an existing variable holds
437 * @time: signed time that an existing variable holds
438 *
439 * Called by efi_set_variable() to verify that the input is correct.
440 * Will replace the given data pointer with another that points to
441 * the actual data to store in the internal memory.
442 * On success, @data and @data_size will be replaced with variable's
443 * actual data, excluding authentication data, and its size, and variable's
444 * attributes and signed time will also be returned in @env_attr and @time,
445 * respectively.
446 *
Heinrich Schuchardt30f92ce2020-05-03 16:29:00 +0200447 * Return: status code
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900448 */
449static efi_status_t efi_variable_authenticate(u16 *variable,
450 const efi_guid_t *vendor,
451 efi_uintn_t *data_size,
452 const void **data, u32 given_attr,
453 u32 *env_attr, u64 *time)
454{
455 const struct efi_variable_authentication_2 *auth;
456 struct efi_signature_store *truststore, *truststore2;
457 struct pkcs7_message *var_sig;
458 struct efi_image_regions *regs;
459 struct efi_time timestamp;
460 struct rtc_time tm;
461 u64 new_time;
462 efi_status_t ret;
463
464 var_sig = NULL;
465 truststore = NULL;
466 truststore2 = NULL;
467 regs = NULL;
468 ret = EFI_SECURITY_VIOLATION;
469
470 if (*data_size < sizeof(struct efi_variable_authentication_2))
471 goto err;
472
473 /* authentication data */
474 auth = *data;
475 if (*data_size < (sizeof(auth->time_stamp)
476 + auth->auth_info.hdr.dwLength))
477 goto err;
478
479 if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
480 goto err;
481
482 *data += sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength;
483 *data_size -= (sizeof(auth->time_stamp)
484 + auth->auth_info.hdr.dwLength);
485
486 memcpy(&timestamp, &auth->time_stamp, sizeof(timestamp));
487 memset(&tm, 0, sizeof(tm));
488 tm.tm_year = timestamp.year;
489 tm.tm_mon = timestamp.month;
490 tm.tm_mday = timestamp.day;
491 tm.tm_hour = timestamp.hour;
492 tm.tm_min = timestamp.minute;
493 tm.tm_sec = timestamp.second;
494 new_time = rtc_mktime(&tm);
495
496 if (!efi_secure_boot_enabled()) {
497 /* finished checking */
498 *time = new_time;
499 return EFI_SUCCESS;
500 }
501
502 if (new_time <= *time)
503 goto err;
504
505 /* data to be digested */
506 regs = calloc(sizeof(*regs) + sizeof(struct image_region) * 5, 1);
507 if (!regs)
508 goto err;
509 regs->max = 5;
510 efi_image_region_add(regs, (uint8_t *)variable,
511 (uint8_t *)variable
512 + u16_strlen(variable) * sizeof(u16), 1);
513 efi_image_region_add(regs, (uint8_t *)vendor,
514 (uint8_t *)vendor + sizeof(*vendor), 1);
515 efi_image_region_add(regs, (uint8_t *)&given_attr,
516 (uint8_t *)&given_attr + sizeof(given_attr), 1);
517 efi_image_region_add(regs, (uint8_t *)&timestamp,
518 (uint8_t *)&timestamp + sizeof(timestamp), 1);
519 efi_image_region_add(regs, (uint8_t *)*data,
520 (uint8_t *)*data + *data_size, 1);
521
522 /* variable's signature list */
523 if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info))
524 goto err;
525 var_sig = efi_variable_parse_signature(auth->auth_info.cert_data,
526 auth->auth_info.hdr.dwLength
527 - sizeof(auth->auth_info));
Patrick Wildt9ad15222020-05-07 02:13:18 +0200528 if (!var_sig) {
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900529 debug("Parsing variable's signature failed\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900530 goto err;
531 }
532
533 /* signature database used for authentication */
534 if (u16_strcmp(variable, L"PK") == 0 ||
535 u16_strcmp(variable, L"KEK") == 0) {
536 /* with PK */
537 truststore = efi_sigstore_parse_sigdb(L"PK");
538 if (!truststore)
539 goto err;
540 } else if (u16_strcmp(variable, L"db") == 0 ||
541 u16_strcmp(variable, L"dbx") == 0) {
542 /* with PK and KEK */
543 truststore = efi_sigstore_parse_sigdb(L"KEK");
544 truststore2 = efi_sigstore_parse_sigdb(L"PK");
545
546 if (!truststore) {
547 if (!truststore2)
548 goto err;
549
550 truststore = truststore2;
551 truststore2 = NULL;
552 }
553 } else {
554 /* TODO: support private authenticated variables */
555 goto err;
556 }
557
558 /* verify signature */
559 if (efi_signature_verify_with_sigdb(regs, var_sig, truststore, NULL)) {
560 debug("Verified\n");
561 } else {
562 if (truststore2 &&
563 efi_signature_verify_with_sigdb(regs, var_sig,
564 truststore2, NULL)) {
565 debug("Verified\n");
566 } else {
567 debug("Verifying variable's signature failed\n");
568 goto err;
569 }
570 }
571
572 /* finished checking */
573 *time = rtc_mktime(&tm);
574 ret = EFI_SUCCESS;
575
576err:
577 efi_sigstore_free(truststore);
578 efi_sigstore_free(truststore2);
579 pkcs7_free_message(var_sig);
580 free(regs);
581
582 return ret;
583}
584#else
585static efi_status_t efi_variable_authenticate(u16 *variable,
586 const efi_guid_t *vendor,
587 efi_uintn_t *data_size,
588 const void **data, u32 given_attr,
589 u32 *env_attr, u64 *time)
590{
591 return EFI_SUCCESS;
592}
593#endif /* CONFIG_EFI_SECURE_BOOT */
594
Heinrich Schuchardt306bf6e2020-05-06 01:51:04 +0200595static efi_status_t efi_get_variable_common(u16 *variable_name,
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900596 const efi_guid_t *vendor,
597 u32 *attributes,
Heinrich Schuchardtc08cac02020-04-18 12:31:17 +0200598 efi_uintn_t *data_size, void *data)
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900599{
600 char *native_name;
601 efi_status_t ret;
602 unsigned long in_size;
603 const char *val = NULL, *s;
604 u64 time = 0;
605 u32 attr;
606
607 if (!variable_name || !vendor || !data_size)
608 return EFI_EXIT(EFI_INVALID_PARAMETER);
609
610 ret = efi_to_native(&native_name, variable_name, vendor);
611 if (ret)
612 return ret;
613
614 EFI_PRINT("get '%s'\n", native_name);
615
616 val = env_get(native_name);
617 free(native_name);
618 if (!val)
619 return EFI_NOT_FOUND;
620
621 val = parse_attr(val, &attr, &time);
622
623 in_size = *data_size;
624
625 if ((s = prefix(val, "(blob)"))) {
626 size_t len = strlen(s);
627
628 /* number of hexadecimal digits must be even */
629 if (len & 1)
630 return EFI_DEVICE_ERROR;
631
632 /* two characters per byte: */
633 len /= 2;
634 *data_size = len;
635
636 if (in_size < len) {
637 ret = EFI_BUFFER_TOO_SMALL;
638 goto out;
639 }
640
641 if (!data) {
642 debug("Variable with no data shouldn't exist.\n");
643 return EFI_INVALID_PARAMETER;
644 }
645
646 if (hex2bin(data, s, len))
647 return EFI_DEVICE_ERROR;
648
649 EFI_PRINT("got value: \"%s\"\n", s);
650 } else if ((s = prefix(val, "(utf8)"))) {
651 unsigned len = strlen(s) + 1;
652
653 *data_size = len;
654
655 if (in_size < len) {
656 ret = EFI_BUFFER_TOO_SMALL;
657 goto out;
658 }
659
660 if (!data) {
661 debug("Variable with no data shouldn't exist.\n");
662 return EFI_INVALID_PARAMETER;
663 }
664
665 memcpy(data, s, len);
666 ((char *)data)[len] = '\0';
667
668 EFI_PRINT("got value: \"%s\"\n", (char *)data);
669 } else {
670 EFI_PRINT("invalid value: '%s'\n", val);
671 return EFI_DEVICE_ERROR;
672 }
673
674out:
675 if (attributes)
676 *attributes = attr & EFI_VARIABLE_MASK;
677
678 return ret;
679}
680
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900681/**
682 * efi_efi_get_variable() - retrieve value of a UEFI variable
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100683 *
684 * This function implements the GetVariable runtime service.
685 *
686 * See the Unified Extensible Firmware Interface (UEFI) specification for
687 * details.
688 *
689 * @variable_name: name of the variable
690 * @vendor: vendor GUID
691 * @attributes: attributes of the variable
692 * @data_size: size of the buffer to which the variable value is copied
693 * @data: buffer to which the variable value is copied
694 * Return: status code
695 */
Heinrich Schuchardt0bda81b2018-12-30 20:53:51 +0100696efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
697 const efi_guid_t *vendor, u32 *attributes,
698 efi_uintn_t *data_size, void *data)
Rob Clarkad644e72017-09-13 18:05:37 -0400699{
Rob Clarkad644e72017-09-13 18:05:37 -0400700 efi_status_t ret;
Rob Clarkad644e72017-09-13 18:05:37 -0400701
Rob Clark778e6af2017-09-13 18:05:41 -0400702 EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
Rob Clarkad644e72017-09-13 18:05:37 -0400703 data_size, data);
704
Heinrich Schuchardtc08cac02020-04-18 12:31:17 +0200705 ret = efi_get_variable_common(variable_name, vendor, attributes,
706 data_size, data);
Heinrich Schuchardt487d8c72019-05-15 19:32:43 +0200707 return EFI_EXIT(ret);
Rob Clarkad644e72017-09-13 18:05:37 -0400708}
709
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100710static char *efi_variables_list;
711static char *efi_cur_variable;
712
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100713/**
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100714 * parse_uboot_variable() - parse a u-boot variable and get uefi-related
715 * information
716 * @variable: whole data of u-boot variable (ie. name=value)
717 * @variable_name_size: size of variable_name buffer in byte
718 * @variable_name: name of uefi variable in u16, null-terminated
719 * @vendor: vendor's guid
720 * @attributes: attributes
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100721 *
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100722 * A uefi variable is encoded into a u-boot variable as described above.
723 * This function parses such a u-boot variable and retrieve uefi-related
724 * information into respective parameters. In return, variable_name_size
725 * is the size of variable name including NULL.
726 *
727 * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
Heinrich Schuchardte5b44622019-07-14 12:11:16 +0200728 * the entire variable list has been returned,
729 * otherwise non-zero status code
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100730 */
731static efi_status_t parse_uboot_variable(char *variable,
732 efi_uintn_t *variable_name_size,
733 u16 *variable_name,
734 const efi_guid_t *vendor,
735 u32 *attributes)
736{
737 char *guid, *name, *end, c;
Heinrich Schuchardt4d7f5af2020-03-20 19:04:34 +0100738 size_t name_len;
739 efi_uintn_t old_variable_name_size;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900740 u64 time;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100741 u16 *p;
742
743 guid = strchr(variable, '_');
744 if (!guid)
745 return EFI_INVALID_PARAMETER;
746 guid++;
747 name = strchr(guid, '_');
748 if (!name)
749 return EFI_INVALID_PARAMETER;
750 name++;
751 end = strchr(name, '=');
752 if (!end)
753 return EFI_INVALID_PARAMETER;
754
755 name_len = end - name;
Heinrich Schuchardt4d7f5af2020-03-20 19:04:34 +0100756 old_variable_name_size = *variable_name_size;
757 *variable_name_size = sizeof(u16) * (name_len + 1);
758 if (old_variable_name_size < *variable_name_size)
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100759 return EFI_BUFFER_TOO_SMALL;
Heinrich Schuchardt4d7f5af2020-03-20 19:04:34 +0100760
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100761 end++; /* point to value */
762
763 /* variable name */
764 p = variable_name;
765 utf8_utf16_strncpy(&p, name, name_len);
766 variable_name[name_len] = 0;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100767
768 /* guid */
769 c = *(name - 1);
770 *(name - 1) = '\0'; /* guid need be null-terminated here */
AKASHI Takahirob433acb2020-05-08 14:51:21 +0900771 if (uuid_str_to_bin(guid, (unsigned char *)vendor,
772 UUID_STR_FORMAT_GUID))
773 /* The only error would be EINVAL. */
774 return EFI_INVALID_PARAMETER;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100775 *(name - 1) = c;
776
777 /* attributes */
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900778 parse_attr(end, attributes, &time);
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100779
780 return EFI_SUCCESS;
781}
782
783/**
784 * efi_get_next_variable_name() - enumerate the current variable names
Heinrich Schuchardte5b44622019-07-14 12:11:16 +0200785 *
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100786 * @variable_name_size: size of variable_name buffer in byte
787 * @variable_name: name of uefi variable's name in u16
788 * @vendor: vendor's guid
789 *
790 * This function implements the GetNextVariableName service.
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100791 *
792 * See the Unified Extensible Firmware Interface (UEFI) specification for
Heinrich Schuchardte5b44622019-07-14 12:11:16 +0200793 * details.
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100794 *
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100795 * Return: status code
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100796 */
Heinrich Schuchardt45c66f92018-05-17 07:57:05 +0200797efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
798 u16 *variable_name,
Heinrich Schuchardt7a4e7172020-03-22 18:28:20 +0100799 efi_guid_t *vendor)
Rob Clarkad644e72017-09-13 18:05:37 -0400800{
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100801 char *native_name, *variable;
802 ssize_t name_len, list_len;
803 char regex[256];
804 char * const regexlist[] = {regex};
805 u32 attributes;
806 int i;
807 efi_status_t ret;
808
Rob Clark778e6af2017-09-13 18:05:41 -0400809 EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
Rob Clarkad644e72017-09-13 18:05:37 -0400810
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100811 if (!variable_name_size || !variable_name || !vendor)
Heinrich Schuchardte7dae582019-03-19 18:36:21 +0100812 return EFI_EXIT(EFI_INVALID_PARAMETER);
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100813
814 if (variable_name[0]) {
815 /* check null-terminated string */
816 for (i = 0; i < *variable_name_size; i++)
817 if (!variable_name[i])
818 break;
819 if (i >= *variable_name_size)
820 return EFI_EXIT(EFI_INVALID_PARAMETER);
821
822 /* search for the last-returned variable */
823 ret = efi_to_native(&native_name, variable_name, vendor);
824 if (ret)
825 return EFI_EXIT(ret);
826
827 name_len = strlen(native_name);
828 for (variable = efi_variables_list; variable && *variable;) {
829 if (!strncmp(variable, native_name, name_len) &&
830 variable[name_len] == '=')
831 break;
832
833 variable = strchr(variable, '\n');
834 if (variable)
835 variable++;
836 }
837
838 free(native_name);
839 if (!(variable && *variable))
840 return EFI_EXIT(EFI_INVALID_PARAMETER);
841
842 /* next variable */
843 variable = strchr(variable, '\n');
844 if (variable)
845 variable++;
846 if (!(variable && *variable))
847 return EFI_EXIT(EFI_NOT_FOUND);
848 } else {
849 /*
850 *new search: free a list used in the previous search
851 */
852 free(efi_variables_list);
853 efi_variables_list = NULL;
854 efi_cur_variable = NULL;
855
856 snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
857 list_len = hexport_r(&env_htab, '\n',
858 H_MATCH_REGEX | H_MATCH_KEY,
859 &efi_variables_list, 0, 1, regexlist);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900860
Heinrich Schuchardteefb7902019-01-22 20:10:46 +0100861 if (list_len <= 1)
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100862 return EFI_EXIT(EFI_NOT_FOUND);
863
864 variable = efi_variables_list;
865 }
866
867 ret = parse_uboot_variable(variable, variable_name_size, variable_name,
868 vendor, &attributes);
869
870 return EFI_EXIT(ret);
Rob Clarkad644e72017-09-13 18:05:37 -0400871}
872
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200873static efi_status_t efi_set_variable_common(u16 *variable_name,
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900874 const efi_guid_t *vendor,
875 u32 attributes,
876 efi_uintn_t data_size,
877 const void *data,
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +0200878 bool ro_check)
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900879{
880 char *native_name = NULL, *old_data = NULL, *val = NULL, *s;
881 efi_uintn_t old_size;
882 bool append, delete;
883 u64 time = 0;
884 u32 attr;
885 efi_status_t ret = EFI_SUCCESS;
886
887 debug("%s: set '%s'\n", __func__, native_name);
888
889 if (!variable_name || !*variable_name || !vendor ||
890 ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
891 !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
892 ret = EFI_INVALID_PARAMETER;
893 goto err;
894 }
895
896 ret = efi_to_native(&native_name, variable_name, vendor);
897 if (ret)
898 goto err;
899
900 /* check if a variable exists */
901 old_size = 0;
902 attr = 0;
Heinrich Schuchardt306bf6e2020-05-06 01:51:04 +0200903 ret = efi_get_variable_common(variable_name, vendor, &attr,
904 &old_size, NULL);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900905 append = !!(attributes & EFI_VARIABLE_APPEND_WRITE);
906 attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE;
907 delete = !append && (!data_size || !attributes);
908
909 /* check attributes */
910 if (old_size) {
911 if (ro_check && (attr & READ_ONLY)) {
912 ret = EFI_WRITE_PROTECTED;
913 goto err;
914 }
915
916 /* attributes won't be changed */
917 if (!delete &&
918 ((ro_check && attr != attributes) ||
919 (!ro_check && ((attr & ~(u32)READ_ONLY)
920 != (attributes & ~(u32)READ_ONLY))))) {
921 ret = EFI_INVALID_PARAMETER;
922 goto err;
923 }
924 } else {
925 if (delete || append) {
926 /*
927 * Trying to delete or to update a non-existent
928 * variable.
929 */
930 ret = EFI_NOT_FOUND;
931 goto err;
932 }
933 }
934
935 if (((!u16_strcmp(variable_name, L"PK") ||
936 !u16_strcmp(variable_name, L"KEK")) &&
937 !guidcmp(vendor, &efi_global_variable_guid)) ||
938 ((!u16_strcmp(variable_name, L"db") ||
939 !u16_strcmp(variable_name, L"dbx")) &&
940 !guidcmp(vendor, &efi_guid_image_security_database))) {
941 /* authentication is mandatory */
942 if (!(attributes &
943 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
944 debug("%ls: AUTHENTICATED_WRITE_ACCESS required\n",
945 variable_name);
946 ret = EFI_INVALID_PARAMETER;
947 goto err;
948 }
949 }
950
951 /* authenticate a variable */
952 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
953 if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {
954 ret = EFI_INVALID_PARAMETER;
955 goto err;
956 }
957 if (attributes &
958 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
959 ret = efi_variable_authenticate(variable_name, vendor,
960 &data_size, &data,
961 attributes, &attr,
962 &time);
963 if (ret != EFI_SUCCESS)
964 goto err;
965
966 /* last chance to check for delete */
967 if (!data_size)
968 delete = true;
969 }
970 } else {
971 if (attributes &
972 (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
973 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
974 debug("Secure boot is not configured\n");
975 ret = EFI_INVALID_PARAMETER;
976 goto err;
977 }
978 }
979
980 /* delete a variable */
981 if (delete) {
982 /* !old_size case has been handled before */
983 val = NULL;
984 ret = EFI_SUCCESS;
985 goto out;
986 }
987
988 if (append) {
989 old_data = malloc(old_size);
990 if (!old_data) {
Heinrich Schuchardt3fdff6b2020-05-06 01:37:25 +0200991 ret = EFI_OUT_OF_RESOURCES;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900992 goto err;
993 }
Heinrich Schuchardt306bf6e2020-05-06 01:51:04 +0200994 ret = efi_get_variable_common(variable_name, vendor,
995 &attr, &old_size, old_data);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900996 if (ret != EFI_SUCCESS)
997 goto err;
998 } else {
999 old_size = 0;
1000 }
1001
1002 val = malloc(2 * old_size + 2 * data_size
1003 + strlen("{ro,run,boot,nv,time=0123456701234567}(blob)")
1004 + 1);
1005 if (!val) {
1006 ret = EFI_OUT_OF_RESOURCES;
1007 goto err;
1008 }
1009
1010 s = val;
1011
1012 /*
1013 * store attributes
1014 */
1015 attributes &= (READ_ONLY |
1016 EFI_VARIABLE_NON_VOLATILE |
1017 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1018 EFI_VARIABLE_RUNTIME_ACCESS |
1019 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS);
1020 s += sprintf(s, "{");
1021 while (attributes) {
1022 attr = 1 << (ffs(attributes) - 1);
1023
1024 if (attr == READ_ONLY) {
1025 s += sprintf(s, "ro");
1026 } else if (attr == EFI_VARIABLE_NON_VOLATILE) {
1027 s += sprintf(s, "nv");
1028 } else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) {
1029 s += sprintf(s, "boot");
1030 } else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) {
1031 s += sprintf(s, "run");
1032 } else if (attr ==
1033 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
1034 s += sprintf(s, "time=");
1035 s = bin2hex(s, (u8 *)&time, sizeof(time));
1036 }
1037
1038 attributes &= ~attr;
1039 if (attributes)
1040 s += sprintf(s, ",");
1041 }
1042 s += sprintf(s, "}");
1043 s += sprintf(s, "(blob)");
1044
1045 /* store payload: */
1046 if (append)
1047 s = bin2hex(s, old_data, old_size);
1048 s = bin2hex(s, data, data_size);
1049 *s = '\0';
1050
1051 EFI_PRINT("setting: %s=%s\n", native_name, val);
1052
1053out:
AKASHI Takahiro434ffb62020-04-14 11:51:42 +09001054 if (env_set(native_name, val)) {
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +09001055 ret = EFI_DEVICE_ERROR;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +09001056 } else {
AKASHI Takahiro83535162020-04-14 11:51:43 +09001057 bool vendor_keys_modified = false;
1058
AKASHI Takahiro434ffb62020-04-14 11:51:42 +09001059 if ((u16_strcmp(variable_name, L"PK") == 0 &&
1060 guidcmp(vendor, &efi_global_variable_guid) == 0)) {
1061 ret = efi_transfer_secure_state(
1062 (delete ? EFI_MODE_SETUP :
1063 EFI_MODE_USER));
1064 if (ret != EFI_SUCCESS)
1065 goto err;
AKASHI Takahiro83535162020-04-14 11:51:43 +09001066
1067 if (efi_secure_mode != EFI_MODE_SETUP)
1068 vendor_keys_modified = true;
1069 } else if ((u16_strcmp(variable_name, L"KEK") == 0 &&
1070 guidcmp(vendor, &efi_global_variable_guid) == 0)) {
1071 if (efi_secure_mode != EFI_MODE_SETUP)
1072 vendor_keys_modified = true;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +09001073 }
AKASHI Takahiro83535162020-04-14 11:51:43 +09001074
1075 /* update VendorKeys */
1076 if (vendor_keys_modified & efi_vendor_keys) {
1077 efi_vendor_keys = 0;
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +02001078 ret = efi_set_variable_common(
AKASHI Takahiro83535162020-04-14 11:51:43 +09001079 L"VendorKeys",
1080 &efi_global_variable_guid,
1081 EFI_VARIABLE_BOOTSERVICE_ACCESS
1082 | EFI_VARIABLE_RUNTIME_ACCESS
1083 | READ_ONLY,
1084 sizeof(efi_vendor_keys),
1085 &efi_vendor_keys,
1086 false);
1087 } else {
1088 ret = EFI_SUCCESS;
1089 }
AKASHI Takahiro434ffb62020-04-14 11:51:42 +09001090 }
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +09001091
1092err:
1093 free(native_name);
1094 free(old_data);
1095 free(val);
1096
1097 return ret;
1098}
1099
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +01001100/**
Heinrich Schuchardt8f89a572019-06-20 12:03:53 +02001101 * efi_set_variable() - set value of a UEFI variable
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +01001102 *
1103 * This function implements the SetVariable runtime service.
1104 *
1105 * See the Unified Extensible Firmware Interface (UEFI) specification for
1106 * details.
1107 *
1108 * @variable_name: name of the variable
1109 * @vendor: vendor GUID
1110 * @attributes: attributes of the variable
1111 * @data_size: size of the buffer with the variable value
1112 * @data: buffer with the variable value
1113 * Return: status code
1114 */
Heinrich Schuchardt0bda81b2018-12-30 20:53:51 +01001115efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
1116 const efi_guid_t *vendor, u32 attributes,
Heinrich Schuchardt452257a2018-12-30 21:03:15 +01001117 efi_uintn_t data_size, const void *data)
Rob Clarkad644e72017-09-13 18:05:37 -04001118{
Heinrich Schuchardt45c66f92018-05-17 07:57:05 +02001119 EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
Rob Clarkad644e72017-09-13 18:05:37 -04001120 data_size, data);
1121
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +09001122 /* READ_ONLY bit is not part of API */
1123 attributes &= ~(u32)READ_ONLY;
Rob Clarkad644e72017-09-13 18:05:37 -04001124
Heinrich Schuchardtbb0e5852020-05-03 10:02:20 +02001125 return EFI_EXIT(efi_set_variable_common(variable_name, vendor,
1126 attributes, data_size, data,
1127 true));
Rob Clarkad644e72017-09-13 18:05:37 -04001128}
Heinrich Schuchardtce435282019-06-20 12:13:05 +02001129
1130/**
1131 * efi_query_variable_info() - get information about EFI variables
1132 *
1133 * This function implements the QueryVariableInfo() runtime service.
1134 *
1135 * See the Unified Extensible Firmware Interface (UEFI) specification for
1136 * details.
1137 *
1138 * @attributes: bitmask to select variables to be
1139 * queried
1140 * @maximum_variable_storage_size: maximum size of storage area for the
1141 * selected variable types
1142 * @remaining_variable_storage_size: remaining size of storage are for the
1143 * selected variable types
1144 * @maximum_variable_size: maximum size of a variable of the
1145 * selected type
1146 * Returns: status code
1147 */
1148efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
1149 u32 attributes,
1150 u64 *maximum_variable_storage_size,
1151 u64 *remaining_variable_storage_size,
1152 u64 *maximum_variable_size)
1153{
1154 return EFI_UNSUPPORTED;
1155}
Heinrich Schuchardt88192092019-06-20 13:52:16 +02001156
1157/**
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001158 * efi_get_variable_runtime() - runtime implementation of GetVariable()
Heinrich Schuchardte5b44622019-07-14 12:11:16 +02001159 *
1160 * @variable_name: name of the variable
1161 * @vendor: vendor GUID
1162 * @attributes: attributes of the variable
1163 * @data_size: size of the buffer to which the variable value is copied
1164 * @data: buffer to which the variable value is copied
1165 * Return: status code
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001166 */
1167static efi_status_t __efi_runtime EFIAPI
1168efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
1169 u32 *attributes, efi_uintn_t *data_size, void *data)
1170{
1171 return EFI_UNSUPPORTED;
1172}
1173
1174/**
1175 * efi_get_next_variable_name_runtime() - runtime implementation of
1176 * GetNextVariable()
Heinrich Schuchardte5b44622019-07-14 12:11:16 +02001177 *
1178 * @variable_name_size: size of variable_name buffer in byte
1179 * @variable_name: name of uefi variable's name in u16
1180 * @vendor: vendor's guid
1181 * Return: status code
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001182 */
1183static efi_status_t __efi_runtime EFIAPI
1184efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
Heinrich Schuchardt7a4e7172020-03-22 18:28:20 +01001185 u16 *variable_name, efi_guid_t *vendor)
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001186{
1187 return EFI_UNSUPPORTED;
1188}
1189
1190/**
1191 * efi_set_variable_runtime() - runtime implementation of SetVariable()
Heinrich Schuchardte5b44622019-07-14 12:11:16 +02001192 *
1193 * @variable_name: name of the variable
1194 * @vendor: vendor GUID
1195 * @attributes: attributes of the variable
1196 * @data_size: size of the buffer with the variable value
1197 * @data: buffer with the variable value
1198 * Return: status code
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001199 */
1200static efi_status_t __efi_runtime EFIAPI
1201efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
1202 u32 attributes, efi_uintn_t data_size,
1203 const void *data)
1204{
1205 return EFI_UNSUPPORTED;
1206}
1207
1208/**
1209 * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
1210 */
1211void efi_variables_boot_exit_notify(void)
1212{
1213 efi_runtime_services.get_variable = efi_get_variable_runtime;
1214 efi_runtime_services.get_next_variable_name =
1215 efi_get_next_variable_name_runtime;
1216 efi_runtime_services.set_variable = efi_set_variable_runtime;
1217 efi_update_table_header_crc32(&efi_runtime_services.hdr);
1218}
1219
1220/**
Heinrich Schuchardt88192092019-06-20 13:52:16 +02001221 * efi_init_variables() - initialize variable services
1222 *
1223 * Return: status code
1224 */
1225efi_status_t efi_init_variables(void)
1226{
AKASHI Takahiro434ffb62020-04-14 11:51:42 +09001227 efi_status_t ret;
1228
1229 ret = efi_init_secure_state();
1230
1231 return ret;
Heinrich Schuchardt88192092019-06-20 13:52:16 +02001232}