blob: 46f35bc60ba0d4cfdbeed1cf3c02758864ee4bce [file] [log] [blame]
Tom Rini70df9d62018-05-07 17:02:21 -04001// SPDX-License-Identifier: GPL-2.0+
Rob Clark15f3d742017-09-13 18:05:37 -04002/*
3 * EFI utils
4 *
5 * Copyright (c) 2017 Rob Clark
Rob Clark15f3d742017-09-13 18:05:37 -04006 */
7
Heinrich Schuchardt147d5d32019-10-26 23:53:48 +02008#include <common.h>
Rob Clark15f3d742017-09-13 18:05:37 -04009#include <efi_loader.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060010#include <env_internal.h>
Heinrich Schuchardt147d5d32019-10-26 23:53:48 +020011#include <hexdump.h>
12#include <malloc.h>
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +010013#include <search.h>
Rob Clark15f3d742017-09-13 18:05:37 -040014
15#define READ_ONLY BIT(31)
16
17/*
18 * Mapping between EFI variables and u-boot variables:
19 *
20 * efi_$guid_$varname = {attributes}(type)value
21 *
22 * For example:
23 *
24 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
25 * "{ro,boot,run}(blob)0000000000000000"
26 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
27 * "(blob)00010000"
28 *
29 * The attributes are a comma separated list of these possible
30 * attributes:
31 *
32 * + ro - read-only
33 * + boot - boot-services access
34 * + run - runtime access
35 *
36 * NOTE: with current implementation, no variables are available after
37 * ExitBootServices, and all are persisted (if possible).
38 *
39 * If not specified, the attributes default to "{boot}".
40 *
41 * The required type is one of:
42 *
43 * + utf8 - raw utf8 string
44 * + blob - arbitrary length hex string
45 *
46 * Maybe a utf16 type would be useful to for a string value to be auto
47 * converted to utf16?
48 */
49
Heinrich Schuchardt44389cb2018-09-23 04:08:09 +020050#define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_"))
Rob Clark15f3d742017-09-13 18:05:37 -040051
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +010052/**
53 * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot
54 * variable name
55 *
56 * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring
57 * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by
58 * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'.
59 *
60 * @native: pointer to pointer to U-Boot variable name
61 * @variable_name: UEFI variable name
62 * @vendor: vendor GUID
63 * Return: status code
64 */
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +020065static efi_status_t efi_to_native(char **native, const u16 *variable_name,
Heinrich Schuchardte06ae192018-12-30 20:53:51 +010066 const efi_guid_t *vendor)
Rob Clark15f3d742017-09-13 18:05:37 -040067{
68 size_t len;
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +020069 char *pos;
Rob Clark15f3d742017-09-13 18:05:37 -040070
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +020071 len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
72 *native = malloc(len);
73 if (!*native)
74 return EFI_OUT_OF_RESOURCES;
Rob Clark15f3d742017-09-13 18:05:37 -040075
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +020076 pos = *native;
77 pos += sprintf(pos, "efi_%pUl_", vendor);
78 utf16_utf8_strcpy(&pos, variable_name);
Rob Clark15f3d742017-09-13 18:05:37 -040079
80 return EFI_SUCCESS;
81}
82
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +010083/**
84 * prefix() - skip over prefix
85 *
86 * Skip over a prefix string.
87 *
88 * @str: string with prefix
89 * @prefix: prefix string
90 * Return: string without prefix, or NULL if prefix not found
91 */
Rob Clark15f3d742017-09-13 18:05:37 -040092static const char *prefix(const char *str, const char *prefix)
93{
94 size_t n = strlen(prefix);
95 if (!strncmp(prefix, str, n))
96 return str + n;
97 return NULL;
98}
99
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100100/**
101 * parse_attr() - decode attributes part of variable value
102 *
103 * Convert the string encoded attributes of a UEFI variable to a bit mask.
104 * TODO: Several attributes are not supported.
105 *
106 * @str: value of U-Boot variable
107 * @attrp: pointer to UEFI attributes
108 * Return: pointer to remainder of U-Boot variable value
109 */
Rob Clark15f3d742017-09-13 18:05:37 -0400110static const char *parse_attr(const char *str, u32 *attrp)
111{
112 u32 attr = 0;
113 char sep = '{';
114
115 if (*str != '{') {
116 *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
117 return str;
118 }
119
120 while (*str == sep) {
121 const char *s;
122
123 str++;
124
125 if ((s = prefix(str, "ro"))) {
126 attr |= READ_ONLY;
AKASHI Takahiro7f334332019-06-04 15:52:06 +0900127 } else if ((s = prefix(str, "nv"))) {
128 attr |= EFI_VARIABLE_NON_VOLATILE;
Rob Clark15f3d742017-09-13 18:05:37 -0400129 } else if ((s = prefix(str, "boot"))) {
130 attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
131 } else if ((s = prefix(str, "run"))) {
132 attr |= EFI_VARIABLE_RUNTIME_ACCESS;
133 } else {
134 printf("invalid attribute: %s\n", str);
135 break;
136 }
137
138 str = s;
139 sep = ',';
140 }
141
142 str++;
143
144 *attrp = attr;
145
146 return str;
147}
148
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100149/**
Heinrich Schuchardt0f042f92019-06-20 12:03:53 +0200150 * efi_get_variable() - retrieve value of a UEFI variable
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100151 *
152 * This function implements the GetVariable runtime service.
153 *
154 * See the Unified Extensible Firmware Interface (UEFI) specification for
155 * details.
156 *
157 * @variable_name: name of the variable
158 * @vendor: vendor GUID
159 * @attributes: attributes of the variable
160 * @data_size: size of the buffer to which the variable value is copied
161 * @data: buffer to which the variable value is copied
162 * Return: status code
163 */
Heinrich Schuchardte06ae192018-12-30 20:53:51 +0100164efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
165 const efi_guid_t *vendor, u32 *attributes,
166 efi_uintn_t *data_size, void *data)
Rob Clark15f3d742017-09-13 18:05:37 -0400167{
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200168 char *native_name;
Rob Clark15f3d742017-09-13 18:05:37 -0400169 efi_status_t ret;
170 unsigned long in_size;
171 const char *val, *s;
172 u32 attr;
173
Rob Clark238f88c2017-09-13 18:05:41 -0400174 EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
Rob Clark15f3d742017-09-13 18:05:37 -0400175 data_size, data);
176
177 if (!variable_name || !vendor || !data_size)
178 return EFI_EXIT(EFI_INVALID_PARAMETER);
179
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200180 ret = efi_to_native(&native_name, variable_name, vendor);
Rob Clark15f3d742017-09-13 18:05:37 -0400181 if (ret)
182 return EFI_EXIT(ret);
183
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200184 EFI_PRINT("get '%s'\n", native_name);
Rob Clark15f3d742017-09-13 18:05:37 -0400185
186 val = env_get(native_name);
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200187 free(native_name);
Rob Clark15f3d742017-09-13 18:05:37 -0400188 if (!val)
189 return EFI_EXIT(EFI_NOT_FOUND);
190
191 val = parse_attr(val, &attr);
192
193 in_size = *data_size;
194
195 if ((s = prefix(val, "(blob)"))) {
Heinrich Schuchardt2d8aedc2019-01-18 12:31:54 +0100196 size_t len = strlen(s);
Rob Clark15f3d742017-09-13 18:05:37 -0400197
Ivan Gorinovd3ea6b72018-05-11 13:18:25 -0700198 /* number of hexadecimal digits must be even */
199 if (len & 1)
200 return EFI_EXIT(EFI_DEVICE_ERROR);
201
Rob Clark15f3d742017-09-13 18:05:37 -0400202 /* two characters per byte: */
Ivan Gorinovd3ea6b72018-05-11 13:18:25 -0700203 len /= 2;
Rob Clark15f3d742017-09-13 18:05:37 -0400204 *data_size = len;
205
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200206 if (in_size < len) {
207 ret = EFI_BUFFER_TOO_SMALL;
208 goto out;
209 }
Rob Clark15f3d742017-09-13 18:05:37 -0400210
211 if (!data)
212 return EFI_EXIT(EFI_INVALID_PARAMETER);
213
Heinrich Schuchardt2d8aedc2019-01-18 12:31:54 +0100214 if (hex2bin(data, s, len))
Rob Clark15f3d742017-09-13 18:05:37 -0400215 return EFI_EXIT(EFI_DEVICE_ERROR);
216
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200217 EFI_PRINT("got value: \"%s\"\n", s);
Rob Clark15f3d742017-09-13 18:05:37 -0400218 } else if ((s = prefix(val, "(utf8)"))) {
219 unsigned len = strlen(s) + 1;
220
221 *data_size = len;
222
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200223 if (in_size < len) {
224 ret = EFI_BUFFER_TOO_SMALL;
225 goto out;
226 }
Rob Clark15f3d742017-09-13 18:05:37 -0400227
228 if (!data)
229 return EFI_EXIT(EFI_INVALID_PARAMETER);
230
231 memcpy(data, s, len);
232 ((char *)data)[len] = '\0';
233
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200234 EFI_PRINT("got value: \"%s\"\n", (char *)data);
Rob Clark15f3d742017-09-13 18:05:37 -0400235 } else {
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200236 EFI_PRINT("invalid value: '%s'\n", val);
Rob Clark15f3d742017-09-13 18:05:37 -0400237 return EFI_EXIT(EFI_DEVICE_ERROR);
238 }
239
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200240out:
Rob Clark15f3d742017-09-13 18:05:37 -0400241 if (attributes)
242 *attributes = attr & EFI_VARIABLE_MASK;
243
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200244 return EFI_EXIT(ret);
Rob Clark15f3d742017-09-13 18:05:37 -0400245}
246
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100247static char *efi_variables_list;
248static char *efi_cur_variable;
249
250/**
251 * parse_uboot_variable() - parse a u-boot variable and get uefi-related
252 * information
253 * @variable: whole data of u-boot variable (ie. name=value)
254 * @variable_name_size: size of variable_name buffer in byte
255 * @variable_name: name of uefi variable in u16, null-terminated
256 * @vendor: vendor's guid
257 * @attributes: attributes
258 *
259 * A uefi variable is encoded into a u-boot variable as described above.
260 * This function parses such a u-boot variable and retrieve uefi-related
261 * information into respective parameters. In return, variable_name_size
262 * is the size of variable name including NULL.
263 *
264 * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200265 * the entire variable list has been returned,
266 * otherwise non-zero status code
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100267 */
268static efi_status_t parse_uboot_variable(char *variable,
269 efi_uintn_t *variable_name_size,
270 u16 *variable_name,
271 const efi_guid_t *vendor,
272 u32 *attributes)
273{
274 char *guid, *name, *end, c;
275 unsigned long name_len;
276 u16 *p;
277
278 guid = strchr(variable, '_');
279 if (!guid)
280 return EFI_INVALID_PARAMETER;
281 guid++;
282 name = strchr(guid, '_');
283 if (!name)
284 return EFI_INVALID_PARAMETER;
285 name++;
286 end = strchr(name, '=');
287 if (!end)
288 return EFI_INVALID_PARAMETER;
289
290 name_len = end - name;
291 if (*variable_name_size < (name_len + 1)) {
292 *variable_name_size = name_len + 1;
293 return EFI_BUFFER_TOO_SMALL;
294 }
295 end++; /* point to value */
296
297 /* variable name */
298 p = variable_name;
299 utf8_utf16_strncpy(&p, name, name_len);
300 variable_name[name_len] = 0;
301 *variable_name_size = name_len + 1;
302
303 /* guid */
304 c = *(name - 1);
305 *(name - 1) = '\0'; /* guid need be null-terminated here */
306 uuid_str_to_bin(guid, (unsigned char *)vendor, UUID_STR_FORMAT_GUID);
307 *(name - 1) = c;
308
309 /* attributes */
310 parse_attr(end, attributes);
311
312 return EFI_SUCCESS;
313}
314
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100315/**
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100316 * efi_get_next_variable_name() - enumerate the current variable names
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200317 *
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100318 * @variable_name_size: size of variable_name buffer in byte
319 * @variable_name: name of uefi variable's name in u16
320 * @vendor: vendor's guid
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100321 *
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100322 * This function implements the GetNextVariableName service.
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100323 *
324 * See the Unified Extensible Firmware Interface (UEFI) specification for
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200325 * details.
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100326 *
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100327 * Return: status code
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100328 */
Heinrich Schuchardtd6a6baa2018-05-17 07:57:05 +0200329efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
330 u16 *variable_name,
Heinrich Schuchardte06ae192018-12-30 20:53:51 +0100331 const efi_guid_t *vendor)
Rob Clark15f3d742017-09-13 18:05:37 -0400332{
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100333 char *native_name, *variable;
334 ssize_t name_len, list_len;
335 char regex[256];
336 char * const regexlist[] = {regex};
337 u32 attributes;
338 int i;
339 efi_status_t ret;
340
Rob Clark238f88c2017-09-13 18:05:41 -0400341 EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
Rob Clark15f3d742017-09-13 18:05:37 -0400342
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100343 if (!variable_name_size || !variable_name || !vendor)
Heinrich Schuchardt793a6252019-03-19 18:36:21 +0100344 return EFI_EXIT(EFI_INVALID_PARAMETER);
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100345
346 if (variable_name[0]) {
347 /* check null-terminated string */
348 for (i = 0; i < *variable_name_size; i++)
349 if (!variable_name[i])
350 break;
351 if (i >= *variable_name_size)
352 return EFI_EXIT(EFI_INVALID_PARAMETER);
353
354 /* search for the last-returned variable */
355 ret = efi_to_native(&native_name, variable_name, vendor);
356 if (ret)
357 return EFI_EXIT(ret);
358
359 name_len = strlen(native_name);
360 for (variable = efi_variables_list; variable && *variable;) {
361 if (!strncmp(variable, native_name, name_len) &&
362 variable[name_len] == '=')
363 break;
364
365 variable = strchr(variable, '\n');
366 if (variable)
367 variable++;
368 }
369
370 free(native_name);
371 if (!(variable && *variable))
372 return EFI_EXIT(EFI_INVALID_PARAMETER);
373
374 /* next variable */
375 variable = strchr(variable, '\n');
376 if (variable)
377 variable++;
378 if (!(variable && *variable))
379 return EFI_EXIT(EFI_NOT_FOUND);
380 } else {
381 /*
382 *new search: free a list used in the previous search
383 */
384 free(efi_variables_list);
385 efi_variables_list = NULL;
386 efi_cur_variable = NULL;
387
388 snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
389 list_len = hexport_r(&env_htab, '\n',
390 H_MATCH_REGEX | H_MATCH_KEY,
391 &efi_variables_list, 0, 1, regexlist);
Heinrich Schuchardtfd738482019-01-22 20:10:46 +0100392 /* 1 indicates that no match was found */
393 if (list_len <= 1)
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100394 return EFI_EXIT(EFI_NOT_FOUND);
395
396 variable = efi_variables_list;
397 }
398
399 ret = parse_uboot_variable(variable, variable_name_size, variable_name,
400 vendor, &attributes);
401
402 return EFI_EXIT(ret);
Rob Clark15f3d742017-09-13 18:05:37 -0400403}
404
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100405/**
Heinrich Schuchardt0f042f92019-06-20 12:03:53 +0200406 * efi_set_variable() - set value of a UEFI variable
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100407 *
408 * This function implements the SetVariable runtime service.
409 *
410 * See the Unified Extensible Firmware Interface (UEFI) specification for
411 * details.
412 *
413 * @variable_name: name of the variable
414 * @vendor: vendor GUID
415 * @attributes: attributes of the variable
416 * @data_size: size of the buffer with the variable value
417 * @data: buffer with the variable value
418 * Return: status code
419 */
Heinrich Schuchardte06ae192018-12-30 20:53:51 +0100420efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
421 const efi_guid_t *vendor, u32 attributes,
Heinrich Schuchardt73e2ab02018-12-30 21:03:15 +0100422 efi_uintn_t data_size, const void *data)
Rob Clark15f3d742017-09-13 18:05:37 -0400423{
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200424 char *native_name = NULL, *val = NULL, *s;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900425 const char *old_val;
426 size_t old_size;
Rob Clark15f3d742017-09-13 18:05:37 -0400427 efi_status_t ret = EFI_SUCCESS;
Rob Clark15f3d742017-09-13 18:05:37 -0400428 u32 attr;
429
Heinrich Schuchardtd6a6baa2018-05-17 07:57:05 +0200430 EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
Rob Clark15f3d742017-09-13 18:05:37 -0400431 data_size, data);
432
Heinrich Schuchardtadba3962019-06-12 23:28:42 +0200433 if (!variable_name || !*variable_name || !vendor ||
434 ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900435 !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200436 ret = EFI_INVALID_PARAMETER;
437 goto out;
438 }
Rob Clark15f3d742017-09-13 18:05:37 -0400439
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200440 ret = efi_to_native(&native_name, variable_name, vendor);
Rob Clark15f3d742017-09-13 18:05:37 -0400441 if (ret)
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200442 goto out;
Rob Clark15f3d742017-09-13 18:05:37 -0400443
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900444 old_val = env_get(native_name);
445 if (old_val) {
446 old_val = parse_attr(old_val, &attr);
Rob Clark15f3d742017-09-13 18:05:37 -0400447
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900448 /* check read-only first */
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200449 if (attr & READ_ONLY) {
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200450 ret = EFI_WRITE_PROTECTED;
451 goto out;
452 }
AKASHI Takahiro186b5a42019-05-24 15:59:03 +0900453
Heinrich Schuchardta6c25fb2019-09-23 22:38:53 +0200454 if ((data_size == 0 &&
455 !(attributes & EFI_VARIABLE_APPEND_WRITE)) ||
456 !attributes) {
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900457 /* delete the variable: */
458 env_set(native_name, NULL);
459 ret = EFI_SUCCESS;
460 goto out;
461 }
462
463 /* attributes won't be changed */
464 if (attr != (attributes & ~EFI_VARIABLE_APPEND_WRITE)) {
AKASHI Takahiro186b5a42019-05-24 15:59:03 +0900465 ret = EFI_INVALID_PARAMETER;
466 goto out;
467 }
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900468
469 if (attributes & EFI_VARIABLE_APPEND_WRITE) {
470 if (!prefix(old_val, "(blob)")) {
Heinrich Schuchardte044a762019-09-23 22:18:09 +0200471 ret = EFI_DEVICE_ERROR;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900472 goto out;
473 }
474 old_size = strlen(old_val);
475 } else {
476 old_size = 0;
477 }
478 } else {
Heinrich Schuchardt8021bbe2019-09-26 21:40:18 +0200479 if (data_size == 0 || !attributes ||
480 (attributes & EFI_VARIABLE_APPEND_WRITE)) {
481 /*
482 * Trying to delete or to update a non-existent
483 * variable.
484 */
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900485 ret = EFI_NOT_FOUND;
486 goto out;
487 }
488
489 old_size = 0;
Rob Clark15f3d742017-09-13 18:05:37 -0400490 }
491
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900492 val = malloc(old_size + 2 * data_size
493 + strlen("{ro,run,boot,nv}(blob)") + 1);
Heinrich Schuchardtbd095f52018-10-02 05:30:05 +0200494 if (!val) {
495 ret = EFI_OUT_OF_RESOURCES;
496 goto out;
497 }
Rob Clark15f3d742017-09-13 18:05:37 -0400498
499 s = val;
500
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900501 /* store attributes */
AKASHI Takahiro7f334332019-06-04 15:52:06 +0900502 attributes &= (EFI_VARIABLE_NON_VOLATILE |
503 EFI_VARIABLE_BOOTSERVICE_ACCESS |
504 EFI_VARIABLE_RUNTIME_ACCESS);
Rob Clark15f3d742017-09-13 18:05:37 -0400505 s += sprintf(s, "{");
506 while (attributes) {
507 u32 attr = 1 << (ffs(attributes) - 1);
508
AKASHI Takahiro7f334332019-06-04 15:52:06 +0900509 if (attr == EFI_VARIABLE_NON_VOLATILE)
510 s += sprintf(s, "nv");
511 else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)
Rob Clark15f3d742017-09-13 18:05:37 -0400512 s += sprintf(s, "boot");
513 else if (attr == EFI_VARIABLE_RUNTIME_ACCESS)
514 s += sprintf(s, "run");
515
516 attributes &= ~attr;
517 if (attributes)
518 s += sprintf(s, ",");
519 }
520 s += sprintf(s, "}");
521
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900522 if (old_size)
523 /* APPEND_WRITE */
524 s += sprintf(s, old_val);
525 else
526 s += sprintf(s, "(blob)");
527
Rob Clark15f3d742017-09-13 18:05:37 -0400528 /* store payload: */
Heinrich Schuchardt807899d2019-01-18 18:54:26 +0100529 s = bin2hex(s, data, data_size);
Rob Clark15f3d742017-09-13 18:05:37 -0400530 *s = '\0';
531
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200532 EFI_PRINT("setting: %s=%s\n", native_name, val);
Rob Clark15f3d742017-09-13 18:05:37 -0400533
534 if (env_set(native_name, val))
535 ret = EFI_DEVICE_ERROR;
536
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200537out:
538 free(native_name);
Rob Clark15f3d742017-09-13 18:05:37 -0400539 free(val);
540
541 return EFI_EXIT(ret);
542}
Heinrich Schuchardt9b19dae2019-06-20 12:13:05 +0200543
544/**
545 * efi_query_variable_info() - get information about EFI variables
546 *
547 * This function implements the QueryVariableInfo() runtime service.
548 *
549 * See the Unified Extensible Firmware Interface (UEFI) specification for
550 * details.
551 *
552 * @attributes: bitmask to select variables to be
553 * queried
554 * @maximum_variable_storage_size: maximum size of storage area for the
555 * selected variable types
556 * @remaining_variable_storage_size: remaining size of storage are for the
557 * selected variable types
558 * @maximum_variable_size: maximum size of a variable of the
559 * selected type
560 * Returns: status code
561 */
562efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
563 u32 attributes,
564 u64 *maximum_variable_storage_size,
565 u64 *remaining_variable_storage_size,
566 u64 *maximum_variable_size)
567{
568 return EFI_UNSUPPORTED;
569}
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +0200570
571/**
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200572 * efi_get_variable_runtime() - runtime implementation of GetVariable()
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200573 *
574 * @variable_name: name of the variable
575 * @vendor: vendor GUID
576 * @attributes: attributes of the variable
577 * @data_size: size of the buffer to which the variable value is copied
578 * @data: buffer to which the variable value is copied
579 * Return: status code
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200580 */
581static efi_status_t __efi_runtime EFIAPI
582efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
583 u32 *attributes, efi_uintn_t *data_size, void *data)
584{
585 return EFI_UNSUPPORTED;
586}
587
588/**
589 * efi_get_next_variable_name_runtime() - runtime implementation of
590 * GetNextVariable()
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200591 *
592 * @variable_name_size: size of variable_name buffer in byte
593 * @variable_name: name of uefi variable's name in u16
594 * @vendor: vendor's guid
595 * Return: status code
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200596 */
597static efi_status_t __efi_runtime EFIAPI
598efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
599 u16 *variable_name, const efi_guid_t *vendor)
600{
601 return EFI_UNSUPPORTED;
602}
603
604/**
605 * efi_set_variable_runtime() - runtime implementation of SetVariable()
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200606 *
607 * @variable_name: name of the variable
608 * @vendor: vendor GUID
609 * @attributes: attributes of the variable
610 * @data_size: size of the buffer with the variable value
611 * @data: buffer with the variable value
612 * Return: status code
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200613 */
614static efi_status_t __efi_runtime EFIAPI
615efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
616 u32 attributes, efi_uintn_t data_size,
617 const void *data)
618{
619 return EFI_UNSUPPORTED;
620}
621
622/**
623 * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
624 */
625void efi_variables_boot_exit_notify(void)
626{
627 efi_runtime_services.get_variable = efi_get_variable_runtime;
628 efi_runtime_services.get_next_variable_name =
629 efi_get_next_variable_name_runtime;
630 efi_runtime_services.set_variable = efi_set_variable_runtime;
631 efi_update_table_header_crc32(&efi_runtime_services.hdr);
632}
633
634/**
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +0200635 * efi_init_variables() - initialize variable services
636 *
637 * Return: status code
638 */
639efi_status_t efi_init_variables(void)
640{
641 return EFI_SUCCESS;
642}