blob: 0d6bafc76d3eeecfc2c7c7fb529e3163cc11bba7 [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>
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +020010#include <efi_variable.h>
Simon Glass09140112020-05-10 11:40:03 -060011#include <env.h>
Simon Glassf3998fd2019-08-02 09:44:25 -060012#include <env_internal.h>
Heinrich Schuchardte731af42019-10-26 23:53:48 +020013#include <hexdump.h>
14#include <malloc.h>
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090015#include <rtc.h>
AKASHI Takahirod99a87f2019-01-21 12:43:13 +010016#include <search.h>
Simon Glassba06b3c2020-05-10 11:39:52 -060017#include <uuid.h>
AKASHI Takahiroe3f5c9c2020-04-21 09:38:17 +090018#include <crypto/pkcs7_parser.h>
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090019#include <linux/compat.h>
Simon Glass3db71102019-11-14 12:57:16 -070020#include <u-boot/crc.h>
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090021
AKASHI Takahiro434ffb62020-04-14 11:51:42 +090022enum efi_secure_mode {
23 EFI_MODE_SETUP,
24 EFI_MODE_USER,
25 EFI_MODE_AUDIT,
26 EFI_MODE_DEPLOYED,
27};
28
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +090029static bool efi_secure_boot;
Heinrich Schuchardt915f15a2020-06-24 12:14:49 +020030static enum efi_secure_mode efi_secure_mode;
AKASHI Takahiro83535162020-04-14 11:51:43 +090031static u8 efi_vendor_keys;
Rob Clarkad644e72017-09-13 18:05:37 -040032
Rob Clarkad644e72017-09-13 18:05:37 -040033/*
34 * Mapping between EFI variables and u-boot variables:
35 *
36 * efi_$guid_$varname = {attributes}(type)value
37 *
38 * For example:
39 *
40 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
41 * "{ro,boot,run}(blob)0000000000000000"
42 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
43 * "(blob)00010000"
44 *
45 * The attributes are a comma separated list of these possible
46 * attributes:
47 *
48 * + ro - read-only
49 * + boot - boot-services access
50 * + run - runtime access
51 *
52 * NOTE: with current implementation, no variables are available after
53 * ExitBootServices, and all are persisted (if possible).
54 *
55 * If not specified, the attributes default to "{boot}".
56 *
57 * The required type is one of:
58 *
59 * + utf8 - raw utf8 string
60 * + blob - arbitrary length hex string
61 *
62 * Maybe a utf16 type would be useful to for a string value to be auto
63 * converted to utf16?
64 */
65
Heinrich Schuchardt506dc522018-09-23 04:08:09 +020066#define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_"))
Rob Clarkad644e72017-09-13 18:05:37 -040067
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +010068/**
69 * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot
70 * variable name
71 *
72 * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring
73 * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by
74 * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'.
75 *
76 * @native: pointer to pointer to U-Boot variable name
77 * @variable_name: UEFI variable name
78 * @vendor: vendor GUID
79 * Return: status code
80 */
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +020081static efi_status_t efi_to_native(char **native, const u16 *variable_name,
Heinrich Schuchardt0bda81b2018-12-30 20:53:51 +010082 const efi_guid_t *vendor)
Rob Clarkad644e72017-09-13 18:05:37 -040083{
84 size_t len;
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +020085 char *pos;
Rob Clarkad644e72017-09-13 18:05:37 -040086
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +020087 len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
88 *native = malloc(len);
89 if (!*native)
90 return EFI_OUT_OF_RESOURCES;
Rob Clarkad644e72017-09-13 18:05:37 -040091
Heinrich Schuchardtdcdb64f2018-08-31 21:31:31 +020092 pos = *native;
93 pos += sprintf(pos, "efi_%pUl_", vendor);
94 utf16_utf8_strcpy(&pos, variable_name);
Rob Clarkad644e72017-09-13 18:05:37 -040095
96 return EFI_SUCCESS;
97}
98
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +010099/**
100 * prefix() - skip over prefix
101 *
102 * Skip over a prefix string.
103 *
104 * @str: string with prefix
105 * @prefix: prefix string
106 * Return: string without prefix, or NULL if prefix not found
107 */
Rob Clarkad644e72017-09-13 18:05:37 -0400108static const char *prefix(const char *str, const char *prefix)
109{
110 size_t n = strlen(prefix);
111 if (!strncmp(prefix, str, n))
112 return str + n;
113 return NULL;
114}
115
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100116/**
117 * parse_attr() - decode attributes part of variable value
118 *
119 * Convert the string encoded attributes of a UEFI variable to a bit mask.
120 * TODO: Several attributes are not supported.
121 *
122 * @str: value of U-Boot variable
123 * @attrp: pointer to UEFI attributes
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900124 * @timep: pointer to time attribute
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100125 * Return: pointer to remainder of U-Boot variable value
126 */
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900127static const char *parse_attr(const char *str, u32 *attrp, u64 *timep)
Rob Clarkad644e72017-09-13 18:05:37 -0400128{
129 u32 attr = 0;
130 char sep = '{';
131
132 if (*str != '{') {
133 *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
134 return str;
135 }
136
137 while (*str == sep) {
138 const char *s;
139
140 str++;
141
142 if ((s = prefix(str, "ro"))) {
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200143 attr |= EFI_VARIABLE_READ_ONLY;
AKASHI Takahirocee2cbc2019-06-04 15:52:06 +0900144 } else if ((s = prefix(str, "nv"))) {
145 attr |= EFI_VARIABLE_NON_VOLATILE;
Rob Clarkad644e72017-09-13 18:05:37 -0400146 } else if ((s = prefix(str, "boot"))) {
147 attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
148 } else if ((s = prefix(str, "run"))) {
149 attr |= EFI_VARIABLE_RUNTIME_ACCESS;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900150 } else if ((s = prefix(str, "time="))) {
151 attr |= EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
152 hex2bin((u8 *)timep, s, sizeof(*timep));
153 s += sizeof(*timep) * 2;
154 } else if (*str == '}') {
155 break;
Rob Clarkad644e72017-09-13 18:05:37 -0400156 } else {
157 printf("invalid attribute: %s\n", str);
158 break;
159 }
160
161 str = s;
162 sep = ',';
163 }
164
165 str++;
166
167 *attrp = attr;
168
169 return str;
170}
171
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900172/**
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900173 * efi_set_secure_state - modify secure boot state variables
Heinrich Schuchardtd80dd9e2020-06-24 12:38:00 +0200174 * @secure_boot: value of SecureBoot
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900175 * @setup_mode: value of SetupMode
176 * @audit_mode: value of AuditMode
177 * @deployed_mode: value of DeployedMode
178 *
Heinrich Schuchardtd80dd9e2020-06-24 12:38:00 +0200179 * Modify secure boot status related variables as indicated.
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900180 *
181 * Return: status code
182 */
Heinrich Schuchardtd80dd9e2020-06-24 12:38:00 +0200183static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
184 u8 audit_mode, u8 deployed_mode)
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900185{
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900186 efi_status_t ret;
Heinrich Schuchardt55a83052020-07-04 18:34:15 +0200187 const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
188 EFI_VARIABLE_RUNTIME_ACCESS |
189 EFI_VARIABLE_READ_ONLY;
190 const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
191 EFI_VARIABLE_RUNTIME_ACCESS;
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900192
Heinrich Schuchardt198bf642020-07-05 02:29:50 +0200193 efi_secure_boot = secure_boot;
194
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200195 ret = efi_set_variable_int(L"SecureBoot", &efi_global_variable_guid,
Heinrich Schuchardt55a83052020-07-04 18:34:15 +0200196 attributes_ro, sizeof(secure_boot),
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200197 &secure_boot, false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900198 if (ret != EFI_SUCCESS)
199 goto err;
200
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200201 ret = efi_set_variable_int(L"SetupMode", &efi_global_variable_guid,
Heinrich Schuchardt55a83052020-07-04 18:34:15 +0200202 attributes_ro, sizeof(setup_mode),
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200203 &setup_mode, false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900204 if (ret != EFI_SUCCESS)
205 goto err;
206
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200207 ret = efi_set_variable_int(L"AuditMode", &efi_global_variable_guid,
Heinrich Schuchardt55a83052020-07-04 18:34:15 +0200208 audit_mode || setup_mode ?
209 attributes_ro : attributes_rw,
210 sizeof(audit_mode), &audit_mode, false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900211 if (ret != EFI_SUCCESS)
212 goto err;
213
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200214 ret = efi_set_variable_int(L"DeployedMode",
Heinrich Schuchardt55a83052020-07-04 18:34:15 +0200215 &efi_global_variable_guid,
216 audit_mode || deployed_mode || setup_mode ?
217 attributes_ro : attributes_rw,
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200218 sizeof(deployed_mode), &deployed_mode,
219 false);
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900220err:
221 return ret;
222}
223
224/**
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900225 * efi_transfer_secure_state - handle a secure boot state transition
226 * @mode: new state
227 *
228 * Depending on @mode, secure boot related variables are updated.
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200229 * Those variables are *read-only* for users, efi_set_variable_int()
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900230 * is called here.
231 *
Heinrich Schuchardt30f92ce2020-05-03 16:29:00 +0200232 * Return: status code
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900233 */
234static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
235{
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900236 efi_status_t ret;
237
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900238 EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
239 mode);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900240
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900241 if (mode == EFI_MODE_DEPLOYED) {
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900242 ret = efi_set_secure_state(1, 0, 0, 1);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900243 if (ret != EFI_SUCCESS)
244 goto err;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900245 } else if (mode == EFI_MODE_AUDIT) {
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200246 ret = efi_set_variable_int(L"PK", &efi_global_variable_guid,
247 EFI_VARIABLE_BOOTSERVICE_ACCESS |
248 EFI_VARIABLE_RUNTIME_ACCESS,
249 0, NULL, false);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900250 if (ret != EFI_SUCCESS)
251 goto err;
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900252
253 ret = efi_set_secure_state(0, 1, 1, 0);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900254 if (ret != EFI_SUCCESS)
255 goto err;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900256 } else if (mode == EFI_MODE_USER) {
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900257 ret = efi_set_secure_state(1, 0, 0, 0);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900258 if (ret != EFI_SUCCESS)
259 goto err;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900260 } else if (mode == EFI_MODE_SETUP) {
AKASHI Takahirof0ff75f2020-04-21 09:39:20 +0900261 ret = efi_set_secure_state(0, 1, 0, 0);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900262 if (ret != EFI_SUCCESS)
263 goto err;
264 } else {
265 return EFI_INVALID_PARAMETER;
266 }
267
AKASHI Takahiro83535162020-04-14 11:51:43 +0900268 efi_secure_mode = mode;
269
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900270 return EFI_SUCCESS;
271
272err:
273 /* TODO: What action should be taken here? */
274 printf("ERROR: Secure state transition failed\n");
275 return ret;
276}
277
278/**
279 * efi_init_secure_state - initialize secure boot state
280 *
Heinrich Schuchardt30f92ce2020-05-03 16:29:00 +0200281 * Return: status code
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900282 */
283static efi_status_t efi_init_secure_state(void)
284{
Heinrich Schuchardtfd7b6732020-07-04 22:41:26 +0200285 enum efi_secure_mode mode = EFI_MODE_SETUP;
286 efi_uintn_t size = 0;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900287 efi_status_t ret;
288
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200289 ret = efi_get_variable_int(L"PK", &efi_global_variable_guid,
290 NULL, &size, NULL, NULL);
AKASHI Takahiro83535162020-04-14 11:51:43 +0900291 if (ret == EFI_BUFFER_TOO_SMALL) {
292 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
293 mode = EFI_MODE_USER;
AKASHI Takahiro83535162020-04-14 11:51:43 +0900294 }
295
296 ret = efi_transfer_secure_state(mode);
Heinrich Schuchardtfd7b6732020-07-04 22:41:26 +0200297 if (ret != EFI_SUCCESS)
298 return ret;
AKASHI Takahiro83535162020-04-14 11:51:43 +0900299
Heinrich Schuchardtfd7b6732020-07-04 22:41:26 +0200300 /* As we do not provide vendor keys this variable is always 0. */
301 ret = efi_set_variable_int(L"VendorKeys",
302 &efi_global_variable_guid,
303 EFI_VARIABLE_BOOTSERVICE_ACCESS |
304 EFI_VARIABLE_RUNTIME_ACCESS |
305 EFI_VARIABLE_READ_ONLY,
306 sizeof(efi_vendor_keys),
307 &efi_vendor_keys, false);
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900308 return ret;
309}
310
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100311/**
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900312 * efi_secure_boot_enabled - return if secure boot is enabled or not
313 *
314 * Return: true if enabled, false if disabled
315 */
316bool efi_secure_boot_enabled(void)
317{
318 return efi_secure_boot;
319}
320
321#ifdef CONFIG_EFI_SECURE_BOOT
322static u8 pkcs7_hdr[] = {
323 /* SEQUENCE */
324 0x30, 0x82, 0x05, 0xc7,
325 /* OID: pkcs7-signedData */
326 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
327 /* Context Structured? */
328 0xa0, 0x82, 0x05, 0xb8,
329};
330
331/**
332 * efi_variable_parse_signature - parse a signature in variable
333 * @buf: Pointer to variable's value
334 * @buflen: Length of @buf
335 *
336 * Parse a signature embedded in variable's value and instantiate
337 * a pkcs7_message structure. Since pkcs7_parse_message() accepts only
338 * pkcs7's signedData, some header needed be prepended for correctly
339 * parsing authentication data, particularly for variable's.
340 *
341 * Return: Pointer to pkcs7_message structure on success, NULL on error
342 */
343static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
344 size_t buflen)
345{
346 u8 *ebuf;
347 size_t ebuflen, len;
348 struct pkcs7_message *msg;
349
350 /*
351 * This is the best assumption to check if the binary is
352 * already in a form of pkcs7's signedData.
353 */
354 if (buflen > sizeof(pkcs7_hdr) &&
355 !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
356 msg = pkcs7_parse_message(buf, buflen);
357 goto out;
358 }
359
360 /*
361 * Otherwise, we should add a dummy prefix sequence for pkcs7
362 * message parser to be able to process.
363 * NOTE: EDK2 also uses similar hack in WrapPkcs7Data()
364 * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c
365 * TODO:
366 * The header should be composed in a more refined manner.
367 */
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900368 EFI_PRINT("Makeshift prefix added to authentication data\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900369 ebuflen = sizeof(pkcs7_hdr) + buflen;
370 if (ebuflen <= 0x7f) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900371 EFI_PRINT("Data is too short\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900372 return NULL;
373 }
374
375 ebuf = malloc(ebuflen);
376 if (!ebuf) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900377 EFI_PRINT("Out of memory\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900378 return NULL;
379 }
380
381 memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr));
382 memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen);
383 len = ebuflen - 4;
384 ebuf[2] = (len >> 8) & 0xff;
385 ebuf[3] = len & 0xff;
386 len = ebuflen - 0x13;
387 ebuf[0x11] = (len >> 8) & 0xff;
388 ebuf[0x12] = len & 0xff;
389
390 msg = pkcs7_parse_message(ebuf, ebuflen);
391
392 free(ebuf);
393
394out:
395 if (IS_ERR(msg))
396 return NULL;
397
398 return msg;
399}
400
401/**
402 * efi_variable_authenticate - authenticate a variable
403 * @variable: Variable name in u16
404 * @vendor: Guid of variable
405 * @data_size: Size of @data
406 * @data: Pointer to variable's value
407 * @given_attr: Attributes to be given at SetVariable()
408 * @env_attr: Attributes that an existing variable holds
409 * @time: signed time that an existing variable holds
410 *
411 * Called by efi_set_variable() to verify that the input is correct.
412 * Will replace the given data pointer with another that points to
413 * the actual data to store in the internal memory.
414 * On success, @data and @data_size will be replaced with variable's
415 * actual data, excluding authentication data, and its size, and variable's
416 * attributes and signed time will also be returned in @env_attr and @time,
417 * respectively.
418 *
Heinrich Schuchardt30f92ce2020-05-03 16:29:00 +0200419 * Return: status code
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900420 */
421static efi_status_t efi_variable_authenticate(u16 *variable,
422 const efi_guid_t *vendor,
423 efi_uintn_t *data_size,
424 const void **data, u32 given_attr,
425 u32 *env_attr, u64 *time)
426{
427 const struct efi_variable_authentication_2 *auth;
428 struct efi_signature_store *truststore, *truststore2;
429 struct pkcs7_message *var_sig;
430 struct efi_image_regions *regs;
431 struct efi_time timestamp;
432 struct rtc_time tm;
433 u64 new_time;
434 efi_status_t ret;
435
436 var_sig = NULL;
437 truststore = NULL;
438 truststore2 = NULL;
439 regs = NULL;
440 ret = EFI_SECURITY_VIOLATION;
441
442 if (*data_size < sizeof(struct efi_variable_authentication_2))
443 goto err;
444
445 /* authentication data */
446 auth = *data;
447 if (*data_size < (sizeof(auth->time_stamp)
448 + auth->auth_info.hdr.dwLength))
449 goto err;
450
451 if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
452 goto err;
453
Heinrich Schuchardt33f183f2020-07-01 12:44:00 +0200454 memcpy(&timestamp, &auth->time_stamp, sizeof(timestamp));
455 if (timestamp.pad1 || timestamp.nanosecond || timestamp.timezone ||
456 timestamp.daylight || timestamp.pad2)
457 goto err;
458
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900459 *data += sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength;
460 *data_size -= (sizeof(auth->time_stamp)
461 + auth->auth_info.hdr.dwLength);
462
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900463 memset(&tm, 0, sizeof(tm));
464 tm.tm_year = timestamp.year;
465 tm.tm_mon = timestamp.month;
466 tm.tm_mday = timestamp.day;
467 tm.tm_hour = timestamp.hour;
468 tm.tm_min = timestamp.minute;
469 tm.tm_sec = timestamp.second;
470 new_time = rtc_mktime(&tm);
471
472 if (!efi_secure_boot_enabled()) {
473 /* finished checking */
474 *time = new_time;
475 return EFI_SUCCESS;
476 }
477
478 if (new_time <= *time)
479 goto err;
480
481 /* data to be digested */
482 regs = calloc(sizeof(*regs) + sizeof(struct image_region) * 5, 1);
483 if (!regs)
484 goto err;
485 regs->max = 5;
486 efi_image_region_add(regs, (uint8_t *)variable,
487 (uint8_t *)variable
488 + u16_strlen(variable) * sizeof(u16), 1);
489 efi_image_region_add(regs, (uint8_t *)vendor,
490 (uint8_t *)vendor + sizeof(*vendor), 1);
491 efi_image_region_add(regs, (uint8_t *)&given_attr,
492 (uint8_t *)&given_attr + sizeof(given_attr), 1);
493 efi_image_region_add(regs, (uint8_t *)&timestamp,
494 (uint8_t *)&timestamp + sizeof(timestamp), 1);
495 efi_image_region_add(regs, (uint8_t *)*data,
496 (uint8_t *)*data + *data_size, 1);
497
498 /* variable's signature list */
499 if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info))
500 goto err;
501 var_sig = efi_variable_parse_signature(auth->auth_info.cert_data,
502 auth->auth_info.hdr.dwLength
503 - sizeof(auth->auth_info));
Patrick Wildt9ad15222020-05-07 02:13:18 +0200504 if (!var_sig) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900505 EFI_PRINT("Parsing variable's signature failed\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900506 goto err;
507 }
508
509 /* signature database used for authentication */
510 if (u16_strcmp(variable, L"PK") == 0 ||
511 u16_strcmp(variable, L"KEK") == 0) {
512 /* with PK */
513 truststore = efi_sigstore_parse_sigdb(L"PK");
514 if (!truststore)
515 goto err;
516 } else if (u16_strcmp(variable, L"db") == 0 ||
517 u16_strcmp(variable, L"dbx") == 0) {
518 /* with PK and KEK */
519 truststore = efi_sigstore_parse_sigdb(L"KEK");
520 truststore2 = efi_sigstore_parse_sigdb(L"PK");
521
522 if (!truststore) {
523 if (!truststore2)
524 goto err;
525
526 truststore = truststore2;
527 truststore2 = NULL;
528 }
529 } else {
530 /* TODO: support private authenticated variables */
531 goto err;
532 }
533
534 /* verify signature */
535 if (efi_signature_verify_with_sigdb(regs, var_sig, truststore, NULL)) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900536 EFI_PRINT("Verified\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900537 } else {
538 if (truststore2 &&
539 efi_signature_verify_with_sigdb(regs, var_sig,
540 truststore2, NULL)) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900541 EFI_PRINT("Verified\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900542 } else {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900543 EFI_PRINT("Verifying variable's signature failed\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900544 goto err;
545 }
546 }
547
548 /* finished checking */
Heinrich Schuchardt3a92f852020-06-30 12:02:14 +0200549 *time = new_time;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900550 ret = EFI_SUCCESS;
551
552err:
553 efi_sigstore_free(truststore);
554 efi_sigstore_free(truststore2);
555 pkcs7_free_message(var_sig);
556 free(regs);
557
558 return ret;
559}
560#else
561static efi_status_t efi_variable_authenticate(u16 *variable,
562 const efi_guid_t *vendor,
563 efi_uintn_t *data_size,
564 const void **data, u32 given_attr,
565 u32 *env_attr, u64 *time)
566{
567 return EFI_SUCCESS;
568}
569#endif /* CONFIG_EFI_SECURE_BOOT */
570
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200571efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
572 u32 *attributes, efi_uintn_t *data_size,
573 void *data, u64 *timep)
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900574{
575 char *native_name;
576 efi_status_t ret;
577 unsigned long in_size;
578 const char *val = NULL, *s;
579 u64 time = 0;
580 u32 attr;
581
582 if (!variable_name || !vendor || !data_size)
Heinrich Schuchardte4c1c482020-06-29 11:49:58 +0200583 return EFI_INVALID_PARAMETER;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900584
585 ret = efi_to_native(&native_name, variable_name, vendor);
586 if (ret)
587 return ret;
588
589 EFI_PRINT("get '%s'\n", native_name);
590
591 val = env_get(native_name);
592 free(native_name);
593 if (!val)
594 return EFI_NOT_FOUND;
595
596 val = parse_attr(val, &attr, &time);
597
Heinrich Schuchardtcb711602020-07-01 15:32:47 +0200598 if (timep)
599 *timep = time;
600
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900601 in_size = *data_size;
602
603 if ((s = prefix(val, "(blob)"))) {
604 size_t len = strlen(s);
605
606 /* number of hexadecimal digits must be even */
607 if (len & 1)
608 return EFI_DEVICE_ERROR;
609
610 /* two characters per byte: */
611 len /= 2;
612 *data_size = len;
613
614 if (in_size < len) {
615 ret = EFI_BUFFER_TOO_SMALL;
616 goto out;
617 }
618
619 if (!data) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900620 EFI_PRINT("Variable with no data shouldn't exist.\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900621 return EFI_INVALID_PARAMETER;
622 }
623
624 if (hex2bin(data, s, len))
625 return EFI_DEVICE_ERROR;
626
627 EFI_PRINT("got value: \"%s\"\n", s);
628 } else if ((s = prefix(val, "(utf8)"))) {
629 unsigned len = strlen(s) + 1;
630
631 *data_size = len;
632
633 if (in_size < len) {
634 ret = EFI_BUFFER_TOO_SMALL;
635 goto out;
636 }
637
638 if (!data) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900639 EFI_PRINT("Variable with no data shouldn't exist.\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900640 return EFI_INVALID_PARAMETER;
641 }
642
643 memcpy(data, s, len);
644 ((char *)data)[len] = '\0';
645
646 EFI_PRINT("got value: \"%s\"\n", (char *)data);
647 } else {
648 EFI_PRINT("invalid value: '%s'\n", val);
649 return EFI_DEVICE_ERROR;
650 }
651
652out:
653 if (attributes)
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200654 *attributes = attr;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900655
656 return ret;
657}
658
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100659static char *efi_variables_list;
660static char *efi_cur_variable;
661
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100662/**
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100663 * parse_uboot_variable() - parse a u-boot variable and get uefi-related
664 * information
665 * @variable: whole data of u-boot variable (ie. name=value)
666 * @variable_name_size: size of variable_name buffer in byte
667 * @variable_name: name of uefi variable in u16, null-terminated
668 * @vendor: vendor's guid
669 * @attributes: attributes
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +0100670 *
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100671 * A uefi variable is encoded into a u-boot variable as described above.
672 * This function parses such a u-boot variable and retrieve uefi-related
673 * information into respective parameters. In return, variable_name_size
674 * is the size of variable name including NULL.
675 *
676 * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
Heinrich Schuchardte5b44622019-07-14 12:11:16 +0200677 * the entire variable list has been returned,
678 * otherwise non-zero status code
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100679 */
680static efi_status_t parse_uboot_variable(char *variable,
681 efi_uintn_t *variable_name_size,
682 u16 *variable_name,
683 const efi_guid_t *vendor,
684 u32 *attributes)
685{
686 char *guid, *name, *end, c;
Heinrich Schuchardt4d7f5af2020-03-20 19:04:34 +0100687 size_t name_len;
688 efi_uintn_t old_variable_name_size;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900689 u64 time;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100690 u16 *p;
691
692 guid = strchr(variable, '_');
693 if (!guid)
694 return EFI_INVALID_PARAMETER;
695 guid++;
696 name = strchr(guid, '_');
697 if (!name)
698 return EFI_INVALID_PARAMETER;
699 name++;
700 end = strchr(name, '=');
701 if (!end)
702 return EFI_INVALID_PARAMETER;
703
704 name_len = end - name;
Heinrich Schuchardt4d7f5af2020-03-20 19:04:34 +0100705 old_variable_name_size = *variable_name_size;
706 *variable_name_size = sizeof(u16) * (name_len + 1);
707 if (old_variable_name_size < *variable_name_size)
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100708 return EFI_BUFFER_TOO_SMALL;
Heinrich Schuchardt4d7f5af2020-03-20 19:04:34 +0100709
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100710 end++; /* point to value */
711
712 /* variable name */
713 p = variable_name;
714 utf8_utf16_strncpy(&p, name, name_len);
715 variable_name[name_len] = 0;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100716
717 /* guid */
718 c = *(name - 1);
719 *(name - 1) = '\0'; /* guid need be null-terminated here */
AKASHI Takahirob433acb2020-05-08 14:51:21 +0900720 if (uuid_str_to_bin(guid, (unsigned char *)vendor,
721 UUID_STR_FORMAT_GUID))
722 /* The only error would be EINVAL. */
723 return EFI_INVALID_PARAMETER;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100724 *(name - 1) = c;
725
726 /* attributes */
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900727 parse_attr(end, attributes, &time);
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100728
729 return EFI_SUCCESS;
730}
731
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200732efi_status_t efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
733 u16 *variable_name,
734 efi_guid_t *vendor)
Rob Clarkad644e72017-09-13 18:05:37 -0400735{
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100736 char *native_name, *variable;
737 ssize_t name_len, list_len;
738 char regex[256];
739 char * const regexlist[] = {regex};
740 u32 attributes;
741 int i;
742 efi_status_t ret;
743
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100744 if (!variable_name_size || !variable_name || !vendor)
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200745 return EFI_INVALID_PARAMETER;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100746
747 if (variable_name[0]) {
748 /* check null-terminated string */
749 for (i = 0; i < *variable_name_size; i++)
750 if (!variable_name[i])
751 break;
752 if (i >= *variable_name_size)
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200753 return EFI_INVALID_PARAMETER;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100754
755 /* search for the last-returned variable */
756 ret = efi_to_native(&native_name, variable_name, vendor);
757 if (ret)
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200758 return ret;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100759
760 name_len = strlen(native_name);
761 for (variable = efi_variables_list; variable && *variable;) {
762 if (!strncmp(variable, native_name, name_len) &&
763 variable[name_len] == '=')
764 break;
765
766 variable = strchr(variable, '\n');
767 if (variable)
768 variable++;
769 }
770
771 free(native_name);
772 if (!(variable && *variable))
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200773 return EFI_INVALID_PARAMETER;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100774
775 /* next variable */
776 variable = strchr(variable, '\n');
777 if (variable)
778 variable++;
779 if (!(variable && *variable))
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200780 return EFI_NOT_FOUND;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100781 } else {
782 /*
783 *new search: free a list used in the previous search
784 */
785 free(efi_variables_list);
786 efi_variables_list = NULL;
787 efi_cur_variable = NULL;
788
789 snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
790 list_len = hexport_r(&env_htab, '\n',
791 H_MATCH_REGEX | H_MATCH_KEY,
792 &efi_variables_list, 0, 1, regexlist);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900793
Heinrich Schuchardteefb7902019-01-22 20:10:46 +0100794 if (list_len <= 1)
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200795 return EFI_NOT_FOUND;
AKASHI Takahirod99a87f2019-01-21 12:43:13 +0100796
797 variable = efi_variables_list;
798 }
799
800 ret = parse_uboot_variable(variable, variable_name_size, variable_name,
801 vendor, &attributes);
802
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200803 return ret;
Rob Clarkad644e72017-09-13 18:05:37 -0400804}
805
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200806efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
807 u32 attributes, efi_uintn_t data_size,
808 const void *data, bool ro_check)
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900809{
810 char *native_name = NULL, *old_data = NULL, *val = NULL, *s;
811 efi_uintn_t old_size;
812 bool append, delete;
813 u64 time = 0;
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200814 u32 old_attr;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900815 efi_status_t ret = EFI_SUCCESS;
816
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900817 if (!variable_name || !*variable_name || !vendor ||
818 ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
819 !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
820 ret = EFI_INVALID_PARAMETER;
821 goto err;
822 }
823
824 ret = efi_to_native(&native_name, variable_name, vendor);
825 if (ret)
826 goto err;
827
828 /* check if a variable exists */
829 old_size = 0;
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200830 old_attr = 0;
831 ret = efi_get_variable_int(variable_name, vendor, &old_attr,
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200832 &old_size, NULL, &time);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900833 append = !!(attributes & EFI_VARIABLE_APPEND_WRITE);
834 attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE;
835 delete = !append && (!data_size || !attributes);
836
837 /* check attributes */
838 if (old_size) {
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200839 if (ro_check && (old_attr & EFI_VARIABLE_READ_ONLY)) {
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900840 ret = EFI_WRITE_PROTECTED;
841 goto err;
842 }
843
844 /* attributes won't be changed */
845 if (!delete &&
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200846 ((ro_check && old_attr != attributes) ||
847 (!ro_check && ((old_attr & ~(u32)EFI_VARIABLE_READ_ONLY)
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200848 != (attributes & ~(u32)EFI_VARIABLE_READ_ONLY))))) {
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900849 ret = EFI_INVALID_PARAMETER;
850 goto err;
851 }
852 } else {
853 if (delete || append) {
854 /*
855 * Trying to delete or to update a non-existent
856 * variable.
857 */
858 ret = EFI_NOT_FOUND;
859 goto err;
860 }
861 }
862
863 if (((!u16_strcmp(variable_name, L"PK") ||
864 !u16_strcmp(variable_name, L"KEK")) &&
865 !guidcmp(vendor, &efi_global_variable_guid)) ||
866 ((!u16_strcmp(variable_name, L"db") ||
867 !u16_strcmp(variable_name, L"dbx")) &&
868 !guidcmp(vendor, &efi_guid_image_security_database))) {
869 /* authentication is mandatory */
870 if (!(attributes &
871 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900872 EFI_PRINT("%ls: AUTHENTICATED_WRITE_ACCESS required\n",
873 variable_name);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900874 ret = EFI_INVALID_PARAMETER;
875 goto err;
876 }
877 }
878
879 /* authenticate a variable */
880 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
881 if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {
882 ret = EFI_INVALID_PARAMETER;
883 goto err;
884 }
885 if (attributes &
886 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
887 ret = efi_variable_authenticate(variable_name, vendor,
888 &data_size, &data,
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200889 attributes, &old_attr,
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900890 &time);
891 if (ret != EFI_SUCCESS)
892 goto err;
893
894 /* last chance to check for delete */
895 if (!data_size)
896 delete = true;
897 }
898 } else {
899 if (attributes &
900 (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
901 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
AKASHI Takahiroce3c3862020-06-09 14:09:34 +0900902 EFI_PRINT("Secure boot is not configured\n");
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900903 ret = EFI_INVALID_PARAMETER;
904 goto err;
905 }
906 }
907
908 /* delete a variable */
909 if (delete) {
910 /* !old_size case has been handled before */
911 val = NULL;
912 ret = EFI_SUCCESS;
913 goto out;
914 }
915
916 if (append) {
917 old_data = malloc(old_size);
918 if (!old_data) {
Heinrich Schuchardt3fdff6b2020-05-06 01:37:25 +0200919 ret = EFI_OUT_OF_RESOURCES;
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900920 goto err;
921 }
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200922 ret = efi_get_variable_int(variable_name, vendor,
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200923 &old_attr, &old_size, old_data, NULL);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900924 if (ret != EFI_SUCCESS)
925 goto err;
926 } else {
927 old_size = 0;
928 }
929
930 val = malloc(2 * old_size + 2 * data_size
931 + strlen("{ro,run,boot,nv,time=0123456701234567}(blob)")
932 + 1);
933 if (!val) {
934 ret = EFI_OUT_OF_RESOURCES;
935 goto err;
936 }
937
938 s = val;
939
940 /*
941 * store attributes
942 */
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200943 attributes &= (EFI_VARIABLE_READ_ONLY |
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900944 EFI_VARIABLE_NON_VOLATILE |
945 EFI_VARIABLE_BOOTSERVICE_ACCESS |
946 EFI_VARIABLE_RUNTIME_ACCESS |
947 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS);
948 s += sprintf(s, "{");
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200949 for (u32 attr_rem = attributes; attr_rem;) {
950 u32 attr = 1 << (ffs(attr_rem) - 1);
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900951
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +0200952 if (attr == EFI_VARIABLE_READ_ONLY) {
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900953 s += sprintf(s, "ro");
954 } else if (attr == EFI_VARIABLE_NON_VOLATILE) {
955 s += sprintf(s, "nv");
956 } else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) {
957 s += sprintf(s, "boot");
958 } else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) {
959 s += sprintf(s, "run");
960 } else if (attr ==
961 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
962 s += sprintf(s, "time=");
963 s = bin2hex(s, (u8 *)&time, sizeof(time));
964 }
965
Heinrich Schuchardt37fa7cb2020-06-17 12:20:46 +0200966 attr_rem &= ~attr;
967 if (attr_rem)
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900968 s += sprintf(s, ",");
969 }
970 s += sprintf(s, "}");
971 s += sprintf(s, "(blob)");
972
973 /* store payload: */
974 if (append)
975 s = bin2hex(s, old_data, old_size);
976 s = bin2hex(s, data, data_size);
977 *s = '\0';
978
979 EFI_PRINT("setting: %s=%s\n", native_name, val);
980
981out:
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900982 if (env_set(native_name, val)) {
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900983 ret = EFI_DEVICE_ERROR;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900984 } else {
Heinrich Schuchardtfd7b6732020-07-04 22:41:26 +0200985 if (!u16_strcmp(variable_name, L"PK"))
986 ret = efi_init_secure_state();
987 else
AKASHI Takahiro83535162020-04-14 11:51:43 +0900988 ret = EFI_SUCCESS;
AKASHI Takahiro434ffb62020-04-14 11:51:42 +0900989 }
AKASHI Takahiro767f6ee2020-04-14 11:51:41 +0900990
991err:
992 free(native_name);
993 free(old_data);
994 free(val);
995
996 return ret;
997}
998
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +0200999efi_status_t efi_query_variable_info_int(u32 attributes,
1000 u64 *maximum_variable_storage_size,
1001 u64 *remaining_variable_storage_size,
1002 u64 *maximum_variable_size)
1003{
1004 return EFI_UNSUPPORTED;
1005}
1006
Heinrich Schuchardt77d4d392019-01-18 19:52:05 +01001007/**
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +02001008 * efi_query_variable_info_runtime() - runtime implementation of
1009 * QueryVariableInfo()
Heinrich Schuchardtce435282019-06-20 12:13:05 +02001010 *
1011 * @attributes: bitmask to select variables to be
1012 * queried
1013 * @maximum_variable_storage_size: maximum size of storage area for the
1014 * selected variable types
1015 * @remaining_variable_storage_size: remaining size of storage are for the
1016 * selected variable types
1017 * @maximum_variable_size: maximum size of a variable of the
1018 * selected type
1019 * Returns: status code
1020 */
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +02001021efi_status_t __efi_runtime EFIAPI efi_query_variable_info_runtime(
Heinrich Schuchardtce435282019-06-20 12:13:05 +02001022 u32 attributes,
1023 u64 *maximum_variable_storage_size,
1024 u64 *remaining_variable_storage_size,
1025 u64 *maximum_variable_size)
1026{
1027 return EFI_UNSUPPORTED;
1028}
Heinrich Schuchardt88192092019-06-20 13:52:16 +02001029
1030/**
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001031 * efi_get_variable_runtime() - runtime implementation of GetVariable()
Heinrich Schuchardte5b44622019-07-14 12:11:16 +02001032 *
1033 * @variable_name: name of the variable
1034 * @vendor: vendor GUID
1035 * @attributes: attributes of the variable
1036 * @data_size: size of the buffer to which the variable value is copied
1037 * @data: buffer to which the variable value is copied
1038 * Return: status code
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001039 */
1040static efi_status_t __efi_runtime EFIAPI
1041efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
1042 u32 *attributes, efi_uintn_t *data_size, void *data)
1043{
1044 return EFI_UNSUPPORTED;
1045}
1046
1047/**
1048 * efi_get_next_variable_name_runtime() - runtime implementation of
1049 * GetNextVariable()
Heinrich Schuchardte5b44622019-07-14 12:11:16 +02001050 *
1051 * @variable_name_size: size of variable_name buffer in byte
1052 * @variable_name: name of uefi variable's name in u16
1053 * @vendor: vendor's guid
1054 * Return: status code
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001055 */
1056static efi_status_t __efi_runtime EFIAPI
1057efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
Heinrich Schuchardt7a4e7172020-03-22 18:28:20 +01001058 u16 *variable_name, efi_guid_t *vendor)
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001059{
1060 return EFI_UNSUPPORTED;
1061}
1062
1063/**
1064 * efi_set_variable_runtime() - runtime implementation of SetVariable()
Heinrich Schuchardte5b44622019-07-14 12:11:16 +02001065 *
1066 * @variable_name: name of the variable
1067 * @vendor: vendor GUID
1068 * @attributes: attributes of the variable
1069 * @data_size: size of the buffer with the variable value
1070 * @data: buffer with the variable value
1071 * Return: status code
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001072 */
1073static efi_status_t __efi_runtime EFIAPI
1074efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
1075 u32 attributes, efi_uintn_t data_size,
1076 const void *data)
1077{
1078 return EFI_UNSUPPORTED;
1079}
1080
1081/**
1082 * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
1083 */
1084void efi_variables_boot_exit_notify(void)
1085{
1086 efi_runtime_services.get_variable = efi_get_variable_runtime;
1087 efi_runtime_services.get_next_variable_name =
1088 efi_get_next_variable_name_runtime;
1089 efi_runtime_services.set_variable = efi_set_variable_runtime;
Heinrich Schuchardt01df8cf2020-06-26 17:57:48 +02001090 efi_runtime_services.query_variable_info =
1091 efi_query_variable_info_runtime;
Heinrich Schuchardt29018ab2019-06-20 15:25:48 +02001092 efi_update_table_header_crc32(&efi_runtime_services.hdr);
1093}
1094
1095/**
Heinrich Schuchardt88192092019-06-20 13:52:16 +02001096 * efi_init_variables() - initialize variable services
1097 *
1098 * Return: status code
1099 */
1100efi_status_t efi_init_variables(void)
1101{
AKASHI Takahiro434ffb62020-04-14 11:51:42 +09001102 efi_status_t ret;
1103
1104 ret = efi_init_secure_state();
1105
1106 return ret;
Heinrich Schuchardt88192092019-06-20 13:52:16 +02001107}