xref: /openbmc/u-boot/cmd/nvedit_efi.c (revision 66c433ed)
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