1*49d81fdfSAKASHI Takahiro // SPDX-License-Identifier: GPL-2.0+
2*49d81fdfSAKASHI Takahiro /*
3*49d81fdfSAKASHI Takahiro * Integrate UEFI variables to u-boot env interface
4*49d81fdfSAKASHI Takahiro *
5*49d81fdfSAKASHI Takahiro * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
6*49d81fdfSAKASHI Takahiro */
7*49d81fdfSAKASHI Takahiro
8*49d81fdfSAKASHI Takahiro #include <charset.h>
9*49d81fdfSAKASHI Takahiro #include <common.h>
10*49d81fdfSAKASHI Takahiro #include <command.h>
11*49d81fdfSAKASHI Takahiro #include <efi_loader.h>
12*49d81fdfSAKASHI Takahiro #include <exports.h>
13*49d81fdfSAKASHI Takahiro #include <hexdump.h>
14*49d81fdfSAKASHI Takahiro #include <malloc.h>
15*49d81fdfSAKASHI Takahiro #include <linux/kernel.h>
16*49d81fdfSAKASHI Takahiro
17*49d81fdfSAKASHI Takahiro /*
18*49d81fdfSAKASHI Takahiro * From efi_variable.c,
19*49d81fdfSAKASHI Takahiro *
20*49d81fdfSAKASHI Takahiro * Mapping between UEFI variables and u-boot variables:
21*49d81fdfSAKASHI Takahiro *
22*49d81fdfSAKASHI Takahiro * efi_$guid_$varname = {attributes}(type)value
23*49d81fdfSAKASHI Takahiro */
24*49d81fdfSAKASHI Takahiro
25*49d81fdfSAKASHI Takahiro static const struct {
26*49d81fdfSAKASHI Takahiro u32 mask;
27*49d81fdfSAKASHI Takahiro char *text;
28*49d81fdfSAKASHI Takahiro } efi_var_attrs[] = {
29*49d81fdfSAKASHI Takahiro {EFI_VARIABLE_NON_VOLATILE, "NV"},
30*49d81fdfSAKASHI Takahiro {EFI_VARIABLE_BOOTSERVICE_ACCESS, "BS"},
31*49d81fdfSAKASHI Takahiro {EFI_VARIABLE_RUNTIME_ACCESS, "RT"},
32*49d81fdfSAKASHI Takahiro {EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, "AW"},
33*49d81fdfSAKASHI Takahiro {EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, "AT"},
34*49d81fdfSAKASHI Takahiro };
35*49d81fdfSAKASHI Takahiro
36*49d81fdfSAKASHI Takahiro /**
37*49d81fdfSAKASHI Takahiro * efi_dump_single_var() - show information about a UEFI variable
38*49d81fdfSAKASHI Takahiro *
39*49d81fdfSAKASHI Takahiro * @name: Name of the variable
40*49d81fdfSAKASHI Takahiro * @guid: Vendor GUID
41*49d81fdfSAKASHI Takahiro *
42*49d81fdfSAKASHI Takahiro * Show information encoded in one UEFI variable
43*49d81fdfSAKASHI Takahiro */
efi_dump_single_var(u16 * name,efi_guid_t * guid)44*49d81fdfSAKASHI Takahiro static void efi_dump_single_var(u16 *name, efi_guid_t *guid)
45*49d81fdfSAKASHI Takahiro {
46*49d81fdfSAKASHI Takahiro u32 attributes;
47*49d81fdfSAKASHI Takahiro u8 *data;
48*49d81fdfSAKASHI Takahiro efi_uintn_t size;
49*49d81fdfSAKASHI Takahiro int count, i;
50*49d81fdfSAKASHI Takahiro efi_status_t ret;
51*49d81fdfSAKASHI Takahiro
52*49d81fdfSAKASHI Takahiro data = NULL;
53*49d81fdfSAKASHI Takahiro size = 0;
54*49d81fdfSAKASHI Takahiro ret = EFI_CALL(efi_get_variable(name, guid, &attributes, &size, data));
55*49d81fdfSAKASHI Takahiro if (ret == EFI_BUFFER_TOO_SMALL) {
56*49d81fdfSAKASHI Takahiro data = malloc(size);
57*49d81fdfSAKASHI Takahiro if (!data)
58*49d81fdfSAKASHI Takahiro goto out;
59*49d81fdfSAKASHI Takahiro
60*49d81fdfSAKASHI Takahiro ret = EFI_CALL(efi_get_variable(name, guid, &attributes, &size,
61*49d81fdfSAKASHI Takahiro data));
62*49d81fdfSAKASHI Takahiro }
63*49d81fdfSAKASHI Takahiro if (ret == EFI_NOT_FOUND) {
64*49d81fdfSAKASHI Takahiro printf("Error: \"%ls\" not defined\n", name);
65*49d81fdfSAKASHI Takahiro goto out;
66*49d81fdfSAKASHI Takahiro }
67*49d81fdfSAKASHI Takahiro if (ret != EFI_SUCCESS)
68*49d81fdfSAKASHI Takahiro goto out;
69*49d81fdfSAKASHI Takahiro
70*49d81fdfSAKASHI Takahiro printf("%ls:", name);
71*49d81fdfSAKASHI Takahiro for (count = 0, i = 0; i < ARRAY_SIZE(efi_var_attrs); i++)
72*49d81fdfSAKASHI Takahiro if (attributes & efi_var_attrs[i].mask) {
73*49d81fdfSAKASHI Takahiro if (count)
74*49d81fdfSAKASHI Takahiro putc('|');
75*49d81fdfSAKASHI Takahiro else
76*49d81fdfSAKASHI Takahiro putc(' ');
77*49d81fdfSAKASHI Takahiro count++;
78*49d81fdfSAKASHI Takahiro puts(efi_var_attrs[i].text);
79*49d81fdfSAKASHI Takahiro }
80*49d81fdfSAKASHI Takahiro printf(", DataSize = 0x%zx\n", size);
81*49d81fdfSAKASHI Takahiro print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, data, size, true);
82*49d81fdfSAKASHI Takahiro
83*49d81fdfSAKASHI Takahiro out:
84*49d81fdfSAKASHI Takahiro free(data);
85*49d81fdfSAKASHI Takahiro }
86*49d81fdfSAKASHI Takahiro
87*49d81fdfSAKASHI Takahiro /**
88*49d81fdfSAKASHI Takahiro * efi_dump_vars() - show information about named UEFI variables
89*49d81fdfSAKASHI Takahiro *
90*49d81fdfSAKASHI Takahiro * @argc: Number of arguments (variables)
91*49d81fdfSAKASHI Takahiro * @argv: Argument (variable name) array
92*49d81fdfSAKASHI Takahiro * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
93*49d81fdfSAKASHI Takahiro *
94*49d81fdfSAKASHI Takahiro * Show information encoded in named UEFI variables
95*49d81fdfSAKASHI Takahiro */
efi_dump_vars(int argc,char * const argv[])96*49d81fdfSAKASHI Takahiro static int efi_dump_vars(int argc, char * const argv[])
97*49d81fdfSAKASHI Takahiro {
98*49d81fdfSAKASHI Takahiro u16 *var_name16, *p;
99*49d81fdfSAKASHI Takahiro efi_uintn_t buf_size, size;
100*49d81fdfSAKASHI Takahiro
101*49d81fdfSAKASHI Takahiro buf_size = 128;
102*49d81fdfSAKASHI Takahiro var_name16 = malloc(buf_size);
103*49d81fdfSAKASHI Takahiro if (!var_name16)
104*49d81fdfSAKASHI Takahiro return CMD_RET_FAILURE;
105*49d81fdfSAKASHI Takahiro
106*49d81fdfSAKASHI Takahiro for (; argc > 0; argc--, argv++) {
107*49d81fdfSAKASHI Takahiro size = (utf8_utf16_strlen(argv[0]) + 1) * sizeof(u16);
108*49d81fdfSAKASHI Takahiro if (buf_size < size) {
109*49d81fdfSAKASHI Takahiro buf_size = size;
110*49d81fdfSAKASHI Takahiro p = realloc(var_name16, buf_size);
111*49d81fdfSAKASHI Takahiro if (!p) {
112*49d81fdfSAKASHI Takahiro free(var_name16);
113*49d81fdfSAKASHI Takahiro return CMD_RET_FAILURE;
114*49d81fdfSAKASHI Takahiro }
115*49d81fdfSAKASHI Takahiro var_name16 = p;
116*49d81fdfSAKASHI Takahiro }
117*49d81fdfSAKASHI Takahiro
118*49d81fdfSAKASHI Takahiro p = var_name16;
119*49d81fdfSAKASHI Takahiro utf8_utf16_strcpy(&p, argv[0]);
120*49d81fdfSAKASHI Takahiro
121*49d81fdfSAKASHI Takahiro efi_dump_single_var(var_name16,
122*49d81fdfSAKASHI Takahiro (efi_guid_t *)&efi_global_variable_guid);
123*49d81fdfSAKASHI Takahiro }
124*49d81fdfSAKASHI Takahiro
125*49d81fdfSAKASHI Takahiro free(var_name16);
126*49d81fdfSAKASHI Takahiro
127*49d81fdfSAKASHI Takahiro return CMD_RET_SUCCESS;
128*49d81fdfSAKASHI Takahiro }
129*49d81fdfSAKASHI Takahiro
130*49d81fdfSAKASHI Takahiro /**
131*49d81fdfSAKASHI Takahiro * efi_dump_vars() - show information about all the UEFI variables
132*49d81fdfSAKASHI Takahiro *
133*49d81fdfSAKASHI Takahiro * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
134*49d81fdfSAKASHI Takahiro *
135*49d81fdfSAKASHI Takahiro * Show information encoded in all the UEFI variables
136*49d81fdfSAKASHI Takahiro */
efi_dump_var_all(void)137*49d81fdfSAKASHI Takahiro static int efi_dump_var_all(void)
138*49d81fdfSAKASHI Takahiro {
139*49d81fdfSAKASHI Takahiro u16 *var_name16, *p;
140*49d81fdfSAKASHI Takahiro efi_uintn_t buf_size, size;
141*49d81fdfSAKASHI Takahiro efi_guid_t guid;
142*49d81fdfSAKASHI Takahiro efi_status_t ret;
143*49d81fdfSAKASHI Takahiro
144*49d81fdfSAKASHI Takahiro buf_size = 128;
145*49d81fdfSAKASHI Takahiro var_name16 = malloc(buf_size);
146*49d81fdfSAKASHI Takahiro if (!var_name16)
147*49d81fdfSAKASHI Takahiro return CMD_RET_FAILURE;
148*49d81fdfSAKASHI Takahiro
149*49d81fdfSAKASHI Takahiro var_name16[0] = 0;
150*49d81fdfSAKASHI Takahiro for (;;) {
151*49d81fdfSAKASHI Takahiro size = buf_size;
152*49d81fdfSAKASHI Takahiro ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
153*49d81fdfSAKASHI Takahiro &guid));
154*49d81fdfSAKASHI Takahiro if (ret == EFI_NOT_FOUND)
155*49d81fdfSAKASHI Takahiro break;
156*49d81fdfSAKASHI Takahiro if (ret == EFI_BUFFER_TOO_SMALL) {
157*49d81fdfSAKASHI Takahiro buf_size = size;
158*49d81fdfSAKASHI Takahiro p = realloc(var_name16, buf_size);
159*49d81fdfSAKASHI Takahiro if (!p) {
160*49d81fdfSAKASHI Takahiro free(var_name16);
161*49d81fdfSAKASHI Takahiro return CMD_RET_FAILURE;
162*49d81fdfSAKASHI Takahiro }
163*49d81fdfSAKASHI Takahiro var_name16 = p;
164*49d81fdfSAKASHI Takahiro ret = EFI_CALL(efi_get_next_variable_name(&size,
165*49d81fdfSAKASHI Takahiro var_name16,
166*49d81fdfSAKASHI Takahiro &guid));
167*49d81fdfSAKASHI Takahiro }
168*49d81fdfSAKASHI Takahiro if (ret != EFI_SUCCESS) {
169*49d81fdfSAKASHI Takahiro free(var_name16);
170*49d81fdfSAKASHI Takahiro return CMD_RET_FAILURE;
171*49d81fdfSAKASHI Takahiro }
172*49d81fdfSAKASHI Takahiro
173*49d81fdfSAKASHI Takahiro efi_dump_single_var(var_name16, &guid);
174*49d81fdfSAKASHI Takahiro }
175*49d81fdfSAKASHI Takahiro
176*49d81fdfSAKASHI Takahiro free(var_name16);
177*49d81fdfSAKASHI Takahiro
178*49d81fdfSAKASHI Takahiro return CMD_RET_SUCCESS;
179*49d81fdfSAKASHI Takahiro }
180*49d81fdfSAKASHI Takahiro
181*49d81fdfSAKASHI Takahiro /**
182*49d81fdfSAKASHI Takahiro * do_env_print_efi() - show information about UEFI variables
183*49d81fdfSAKASHI Takahiro *
184*49d81fdfSAKASHI Takahiro * @cmdtp: Command table
185*49d81fdfSAKASHI Takahiro * @flag: Command flag
186*49d81fdfSAKASHI Takahiro * @argc: Number of arguments
187*49d81fdfSAKASHI Takahiro * @argv: Argument array
188*49d81fdfSAKASHI Takahiro * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
189*49d81fdfSAKASHI Takahiro *
190*49d81fdfSAKASHI Takahiro * This function is for "env print -e" or "printenv -e" command:
191*49d81fdfSAKASHI Takahiro * => env print -e [var [...]]
192*49d81fdfSAKASHI Takahiro * If one or more variable names are specified, show information
193*49d81fdfSAKASHI Takahiro * named UEFI variables, otherwise show all the UEFI variables.
194*49d81fdfSAKASHI Takahiro */
do_env_print_efi(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])195*49d81fdfSAKASHI Takahiro int do_env_print_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
196*49d81fdfSAKASHI Takahiro {
197*49d81fdfSAKASHI Takahiro efi_status_t ret;
198*49d81fdfSAKASHI Takahiro
199*49d81fdfSAKASHI Takahiro /* Initialize EFI drivers */
200*49d81fdfSAKASHI Takahiro ret = efi_init_obj_list();
201*49d81fdfSAKASHI Takahiro if (ret != EFI_SUCCESS) {
202*49d81fdfSAKASHI Takahiro printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
203*49d81fdfSAKASHI Takahiro ret & ~EFI_ERROR_MASK);
204*49d81fdfSAKASHI Takahiro return CMD_RET_FAILURE;
205*49d81fdfSAKASHI Takahiro }
206*49d81fdfSAKASHI Takahiro
207*49d81fdfSAKASHI Takahiro if (argc > 1)
208*49d81fdfSAKASHI Takahiro /* show specified UEFI variables */
209*49d81fdfSAKASHI Takahiro return efi_dump_vars(--argc, ++argv);
210*49d81fdfSAKASHI Takahiro
211*49d81fdfSAKASHI Takahiro /* enumerate and show all UEFI variables */
212*49d81fdfSAKASHI Takahiro return efi_dump_var_all();
213*49d81fdfSAKASHI Takahiro }
214*49d81fdfSAKASHI Takahiro
215*49d81fdfSAKASHI Takahiro /**
216*49d81fdfSAKASHI Takahiro * append_value() - encode UEFI variable's value
217*49d81fdfSAKASHI Takahiro * @bufp: Buffer of encoded UEFI variable's value
218*49d81fdfSAKASHI Takahiro * @sizep: Size of buffer
219*49d81fdfSAKASHI Takahiro * @data: data to be encoded into the value
220*49d81fdfSAKASHI Takahiro * Return: 0 on success, -1 otherwise
221*49d81fdfSAKASHI Takahiro *
222*49d81fdfSAKASHI Takahiro * Interpret a given data string and append it to buffer.
223*49d81fdfSAKASHI Takahiro * Buffer will be realloc'ed if necessary.
224*49d81fdfSAKASHI Takahiro *
225*49d81fdfSAKASHI Takahiro * Currently supported formats are:
226*49d81fdfSAKASHI Takahiro * =0x0123...: Hexadecimal number
227*49d81fdfSAKASHI Takahiro * =H0123...: Hexadecimal-byte array
228*49d81fdfSAKASHI Takahiro * ="...", =S"..." or <string>:
229*49d81fdfSAKASHI Takahiro * String
230*49d81fdfSAKASHI Takahiro */
append_value(char ** bufp,size_t * sizep,char * data)231*49d81fdfSAKASHI Takahiro static int append_value(char **bufp, size_t *sizep, char *data)
232*49d81fdfSAKASHI Takahiro {
233*49d81fdfSAKASHI Takahiro char *tmp_buf = NULL, *new_buf = NULL, *value;
234*49d81fdfSAKASHI Takahiro unsigned long len = 0;
235*49d81fdfSAKASHI Takahiro
236*49d81fdfSAKASHI Takahiro if (!strncmp(data, "=0x", 2)) { /* hexadecimal number */
237*49d81fdfSAKASHI Takahiro union {
238*49d81fdfSAKASHI Takahiro u8 u8;
239*49d81fdfSAKASHI Takahiro u16 u16;
240*49d81fdfSAKASHI Takahiro u32 u32;
241*49d81fdfSAKASHI Takahiro u64 u64;
242*49d81fdfSAKASHI Takahiro } tmp_data;
243*49d81fdfSAKASHI Takahiro unsigned long hex_value;
244*49d81fdfSAKASHI Takahiro void *hex_ptr;
245*49d81fdfSAKASHI Takahiro
246*49d81fdfSAKASHI Takahiro data += 3;
247*49d81fdfSAKASHI Takahiro len = strlen(data);
248*49d81fdfSAKASHI Takahiro if ((len & 0x1)) /* not multiple of two */
249*49d81fdfSAKASHI Takahiro return -1;
250*49d81fdfSAKASHI Takahiro
251*49d81fdfSAKASHI Takahiro len /= 2;
252*49d81fdfSAKASHI Takahiro if (len > 8)
253*49d81fdfSAKASHI Takahiro return -1;
254*49d81fdfSAKASHI Takahiro else if (len > 4)
255*49d81fdfSAKASHI Takahiro len = 8;
256*49d81fdfSAKASHI Takahiro else if (len > 2)
257*49d81fdfSAKASHI Takahiro len = 4;
258*49d81fdfSAKASHI Takahiro
259*49d81fdfSAKASHI Takahiro /* convert hex hexadecimal number */
260*49d81fdfSAKASHI Takahiro if (strict_strtoul(data, 16, &hex_value) < 0)
261*49d81fdfSAKASHI Takahiro return -1;
262*49d81fdfSAKASHI Takahiro
263*49d81fdfSAKASHI Takahiro tmp_buf = malloc(len);
264*49d81fdfSAKASHI Takahiro if (!tmp_buf)
265*49d81fdfSAKASHI Takahiro return -1;
266*49d81fdfSAKASHI Takahiro
267*49d81fdfSAKASHI Takahiro if (len == 1) {
268*49d81fdfSAKASHI Takahiro tmp_data.u8 = hex_value;
269*49d81fdfSAKASHI Takahiro hex_ptr = &tmp_data.u8;
270*49d81fdfSAKASHI Takahiro } else if (len == 2) {
271*49d81fdfSAKASHI Takahiro tmp_data.u16 = hex_value;
272*49d81fdfSAKASHI Takahiro hex_ptr = &tmp_data.u16;
273*49d81fdfSAKASHI Takahiro } else if (len == 4) {
274*49d81fdfSAKASHI Takahiro tmp_data.u32 = hex_value;
275*49d81fdfSAKASHI Takahiro hex_ptr = &tmp_data.u32;
276*49d81fdfSAKASHI Takahiro } else {
277*49d81fdfSAKASHI Takahiro tmp_data.u64 = hex_value;
278*49d81fdfSAKASHI Takahiro hex_ptr = &tmp_data.u64;
279*49d81fdfSAKASHI Takahiro }
280*49d81fdfSAKASHI Takahiro memcpy(tmp_buf, hex_ptr, len);
281*49d81fdfSAKASHI Takahiro value = tmp_buf;
282*49d81fdfSAKASHI Takahiro
283*49d81fdfSAKASHI Takahiro } else if (!strncmp(data, "=H", 2)) { /* hexadecimal-byte array */
284*49d81fdfSAKASHI Takahiro data += 2;
285*49d81fdfSAKASHI Takahiro len = strlen(data);
286*49d81fdfSAKASHI Takahiro if (len & 0x1) /* not multiple of two */
287*49d81fdfSAKASHI Takahiro return -1;
288*49d81fdfSAKASHI Takahiro
289*49d81fdfSAKASHI Takahiro len /= 2;
290*49d81fdfSAKASHI Takahiro tmp_buf = malloc(len);
291*49d81fdfSAKASHI Takahiro if (!tmp_buf)
292*49d81fdfSAKASHI Takahiro return -1;
293*49d81fdfSAKASHI Takahiro
294*49d81fdfSAKASHI Takahiro if (hex2bin((u8 *)tmp_buf, data, len) < 0)
295*49d81fdfSAKASHI Takahiro return -1;
296*49d81fdfSAKASHI Takahiro
297*49d81fdfSAKASHI Takahiro value = tmp_buf;
298*49d81fdfSAKASHI Takahiro } else { /* string */
299*49d81fdfSAKASHI Takahiro if (!strncmp(data, "=\"", 2) || !strncmp(data, "=S\"", 3)) {
300*49d81fdfSAKASHI Takahiro if (data[1] == '"')
301*49d81fdfSAKASHI Takahiro data += 2;
302*49d81fdfSAKASHI Takahiro else
303*49d81fdfSAKASHI Takahiro data += 3;
304*49d81fdfSAKASHI Takahiro value = data;
305*49d81fdfSAKASHI Takahiro len = strlen(data) - 1;
306*49d81fdfSAKASHI Takahiro if (data[len] != '"')
307*49d81fdfSAKASHI Takahiro return -1;
308*49d81fdfSAKASHI Takahiro } else {
309*49d81fdfSAKASHI Takahiro value = data;
310*49d81fdfSAKASHI Takahiro len = strlen(data);
311*49d81fdfSAKASHI Takahiro }
312*49d81fdfSAKASHI Takahiro }
313*49d81fdfSAKASHI Takahiro
314*49d81fdfSAKASHI Takahiro new_buf = realloc(*bufp, *sizep + len);
315*49d81fdfSAKASHI Takahiro if (!new_buf)
316*49d81fdfSAKASHI Takahiro goto out;
317*49d81fdfSAKASHI Takahiro
318*49d81fdfSAKASHI Takahiro memcpy(new_buf + *sizep, value, len);
319*49d81fdfSAKASHI Takahiro *bufp = new_buf;
320*49d81fdfSAKASHI Takahiro *sizep += len;
321*49d81fdfSAKASHI Takahiro
322*49d81fdfSAKASHI Takahiro out:
323*49d81fdfSAKASHI Takahiro free(tmp_buf);
324*49d81fdfSAKASHI Takahiro
325*49d81fdfSAKASHI Takahiro return 0;
326*49d81fdfSAKASHI Takahiro }
327*49d81fdfSAKASHI Takahiro
328*49d81fdfSAKASHI Takahiro /**
329*49d81fdfSAKASHI Takahiro * do_env_print_efi() - set UEFI variable
330*49d81fdfSAKASHI Takahiro *
331*49d81fdfSAKASHI Takahiro * @cmdtp: Command table
332*49d81fdfSAKASHI Takahiro * @flag: Command flag
333*49d81fdfSAKASHI Takahiro * @argc: Number of arguments
334*49d81fdfSAKASHI Takahiro * @argv: Argument array
335*49d81fdfSAKASHI Takahiro * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
336*49d81fdfSAKASHI Takahiro *
337*49d81fdfSAKASHI Takahiro * This function is for "env set -e" or "setenv -e" command:
338*49d81fdfSAKASHI Takahiro * => env set -e var [value ...]]
339*49d81fdfSAKASHI Takahiro * Encode values specified and set given UEFI variable.
340*49d81fdfSAKASHI Takahiro * If no value is specified, delete the variable.
341*49d81fdfSAKASHI Takahiro */
do_env_set_efi(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])342*49d81fdfSAKASHI Takahiro int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
343*49d81fdfSAKASHI Takahiro {
344*49d81fdfSAKASHI Takahiro char *var_name, *value = NULL;
345*49d81fdfSAKASHI Takahiro efi_uintn_t size = 0;
346*49d81fdfSAKASHI Takahiro u16 *var_name16 = NULL, *p;
347*49d81fdfSAKASHI Takahiro size_t len;
348*49d81fdfSAKASHI Takahiro efi_guid_t guid;
349*49d81fdfSAKASHI Takahiro efi_status_t ret;
350*49d81fdfSAKASHI Takahiro
351*49d81fdfSAKASHI Takahiro if (argc == 1)
352*49d81fdfSAKASHI Takahiro return CMD_RET_USAGE;
353*49d81fdfSAKASHI Takahiro
354*49d81fdfSAKASHI Takahiro /* Initialize EFI drivers */
355*49d81fdfSAKASHI Takahiro ret = efi_init_obj_list();
356*49d81fdfSAKASHI Takahiro if (ret != EFI_SUCCESS) {
357*49d81fdfSAKASHI Takahiro printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
358*49d81fdfSAKASHI Takahiro ret & ~EFI_ERROR_MASK);
359*49d81fdfSAKASHI Takahiro return CMD_RET_FAILURE;
360*49d81fdfSAKASHI Takahiro }
361*49d81fdfSAKASHI Takahiro
362*49d81fdfSAKASHI Takahiro var_name = argv[1];
363*49d81fdfSAKASHI Takahiro if (argc == 2) {
364*49d81fdfSAKASHI Takahiro /* delete */
365*49d81fdfSAKASHI Takahiro value = NULL;
366*49d81fdfSAKASHI Takahiro size = 0;
367*49d81fdfSAKASHI Takahiro } else { /* set */
368*49d81fdfSAKASHI Takahiro argc -= 2;
369*49d81fdfSAKASHI Takahiro argv += 2;
370*49d81fdfSAKASHI Takahiro
371*49d81fdfSAKASHI Takahiro for ( ; argc > 0; argc--, argv++)
372*49d81fdfSAKASHI Takahiro if (append_value(&value, &size, argv[0]) < 0) {
373*49d81fdfSAKASHI Takahiro ret = CMD_RET_FAILURE;
374*49d81fdfSAKASHI Takahiro goto out;
375*49d81fdfSAKASHI Takahiro }
376*49d81fdfSAKASHI Takahiro }
377*49d81fdfSAKASHI Takahiro
378*49d81fdfSAKASHI Takahiro len = utf8_utf16_strnlen(var_name, strlen(var_name));
379*49d81fdfSAKASHI Takahiro var_name16 = malloc((len + 1) * 2);
380*49d81fdfSAKASHI Takahiro if (!var_name16) {
381*49d81fdfSAKASHI Takahiro ret = CMD_RET_FAILURE;
382*49d81fdfSAKASHI Takahiro goto out;
383*49d81fdfSAKASHI Takahiro }
384*49d81fdfSAKASHI Takahiro p = var_name16;
385*49d81fdfSAKASHI Takahiro utf8_utf16_strncpy(&p, var_name, len + 1);
386*49d81fdfSAKASHI Takahiro
387*49d81fdfSAKASHI Takahiro guid = efi_global_variable_guid;
388*49d81fdfSAKASHI Takahiro ret = EFI_CALL(efi_set_variable(var_name16, &guid,
389*49d81fdfSAKASHI Takahiro EFI_VARIABLE_BOOTSERVICE_ACCESS |
390*49d81fdfSAKASHI Takahiro EFI_VARIABLE_RUNTIME_ACCESS,
391*49d81fdfSAKASHI Takahiro size, value));
392*49d81fdfSAKASHI Takahiro ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
393*49d81fdfSAKASHI Takahiro out:
394*49d81fdfSAKASHI Takahiro free(value);
395*49d81fdfSAKASHI Takahiro free(var_name16);
396*49d81fdfSAKASHI Takahiro
397*49d81fdfSAKASHI Takahiro return ret;
398*49d81fdfSAKASHI Takahiro }
399