1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  UEFI Shell-like command
4  *
5  *  Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
6  */
7 
8 #include <charset.h>
9 #include <common.h>
10 #include <command.h>
11 #include <efi_dt_fixup.h>
12 #include <efi_loader.h>
13 #include <efi_rng.h>
14 #include <exports.h>
15 #include <hexdump.h>
16 #include <log.h>
17 #include <malloc.h>
18 #include <mapmem.h>
19 #include <part.h>
20 #include <search.h>
21 #include <linux/ctype.h>
22 
23 #define BS systab.boottime
24 #define RT systab.runtime
25 
26 #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
27 /**
28  * do_efi_capsule_update() - process a capsule update
29  *
30  * @cmdtp:	Command table
31  * @flag:	Command flag
32  * @argc:	Number of arguments
33  * @argv:	Argument array
34  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
35  *
36  * Implement efidebug "capsule update" sub-command.
37  * process a capsule update.
38  *
39  *     efidebug capsule update [-v] <capsule address>
40  */
do_efi_capsule_update(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])41 static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag,
42 				 int argc, char * const argv[])
43 {
44 	struct efi_capsule_header *capsule;
45 	int verbose = 0;
46 	char *endp;
47 	efi_status_t ret;
48 
49 	if (argc != 2 && argc != 3)
50 		return CMD_RET_USAGE;
51 
52 	if (argc == 3) {
53 		if (strcmp(argv[1], "-v"))
54 			return CMD_RET_USAGE;
55 
56 		verbose = 1;
57 		argc--;
58 		argv++;
59 	}
60 
61 	capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
62 	if (endp == argv[1]) {
63 		printf("Invalid address: %s", argv[1]);
64 		return CMD_RET_FAILURE;
65 	}
66 
67 	if (verbose) {
68 		printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
69 		printf("Capsule flags: 0x%x\n", capsule->flags);
70 		printf("Capsule header size: 0x%x\n", capsule->header_size);
71 		printf("Capsule image size: 0x%x\n",
72 		       capsule->capsule_image_size);
73 	}
74 
75 	ret = EFI_CALL(RT->update_capsule(&capsule, 1, 0));
76 	if (ret) {
77 		printf("Cannot handle a capsule at %p", capsule);
78 		return CMD_RET_FAILURE;
79 	}
80 
81 	return CMD_RET_SUCCESS;
82 }
83 
do_efi_capsule_on_disk_update(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])84 static int do_efi_capsule_on_disk_update(struct cmd_tbl *cmdtp, int flag,
85 					 int argc, char * const argv[])
86 {
87 	efi_status_t ret;
88 
89 	ret = efi_launch_capsules();
90 
91 	return ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
92 }
93 
94 /**
95  * do_efi_capsule_show() - show capsule information
96  *
97  * @cmdtp:	Command table
98  * @flag:	Command flag
99  * @argc:	Number of arguments
100  * @argv:	Argument array
101  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
102  *
103  * Implement efidebug "capsule show" sub-command.
104  * show capsule information.
105  *
106  *     efidebug capsule show <capsule address>
107  */
do_efi_capsule_show(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])108 static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag,
109 			       int argc, char * const argv[])
110 {
111 	struct efi_capsule_header *capsule;
112 	char *endp;
113 
114 	if (argc != 2)
115 		return CMD_RET_USAGE;
116 
117 	capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
118 	if (endp == argv[1]) {
119 		printf("Invalid address: %s", argv[1]);
120 		return CMD_RET_FAILURE;
121 	}
122 
123 	printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
124 	printf("Capsule flags: 0x%x\n", capsule->flags);
125 	printf("Capsule header size: 0x%x\n", capsule->header_size);
126 	printf("Capsule image size: 0x%x\n",
127 	       capsule->capsule_image_size);
128 
129 	return CMD_RET_SUCCESS;
130 }
131 
132 /**
133  * do_efi_capsule_res() - show a capsule update result
134  *
135  * @cmdtp:	Command table
136  * @flag:	Command flag
137  * @argc:	Number of arguments
138  * @argv:	Argument array
139  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
140  *
141  * Implement efidebug "capsule result" sub-command.
142  * show a capsule update result.
143  * If result number is not specified, CapsuleLast will be shown.
144  *
145  *     efidebug capsule result [<capsule result number>]
146  */
do_efi_capsule_res(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])147 static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag,
148 			      int argc, char * const argv[])
149 {
150 	int capsule_id;
151 	char *endp;
152 	char var_name[12];
153 	u16 var_name16[12], *p;
154 	efi_guid_t guid;
155 	struct efi_capsule_result_variable_header *result = NULL;
156 	efi_uintn_t size;
157 	efi_status_t ret;
158 
159 	if (argc != 1 && argc != 2)
160 		return CMD_RET_USAGE;
161 
162 	guid = efi_guid_capsule_report;
163 	if (argc == 1) {
164 		size = sizeof(var_name16);
165 		ret = EFI_CALL(RT->get_variable(L"CapsuleLast", &guid, NULL,
166 						&size, var_name16));
167 		if (ret != EFI_SUCCESS) {
168 			if (ret == EFI_NOT_FOUND)
169 				printf("CapsuleLast doesn't exist\n");
170 			else
171 				printf("Failed to get CapsuleLast\n");
172 
173 			return CMD_RET_FAILURE;
174 		}
175 		printf("CapsuleLast is %ls\n", var_name16);
176 	} else {
177 		argc--;
178 		argv++;
179 
180 		capsule_id = simple_strtoul(argv[0], &endp, 16);
181 		if (capsule_id < 0 || capsule_id > 0xffff)
182 			return CMD_RET_USAGE;
183 
184 		sprintf(var_name, "Capsule%04X", capsule_id);
185 		p = var_name16;
186 		utf8_utf16_strncpy(&p, var_name, 9);
187 	}
188 
189 	size = 0;
190 	ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
191 	if (ret == EFI_BUFFER_TOO_SMALL) {
192 		result = malloc(size);
193 		if (!result)
194 			return CMD_RET_FAILURE;
195 		ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
196 						result));
197 	}
198 	if (ret != EFI_SUCCESS) {
199 		free(result);
200 		printf("Failed to get %ls\n", var_name16);
201 
202 		return CMD_RET_FAILURE;
203 	}
204 
205 	printf("Result total size: 0x%x\n", result->variable_total_size);
206 	printf("Capsule guid: %pUl\n", &result->capsule_guid);
207 	printf("Time processed: %04d-%02d-%02d %02d:%02d:%02d\n",
208 	       result->capsule_processed.year, result->capsule_processed.month,
209 	       result->capsule_processed.day, result->capsule_processed.hour,
210 	       result->capsule_processed.minute,
211 	       result->capsule_processed.second);
212 	printf("Capsule status: 0x%lx\n", result->capsule_status);
213 
214 	free(result);
215 
216 	return CMD_RET_SUCCESS;
217 }
218 
219 static struct cmd_tbl cmd_efidebug_capsule_sub[] = {
220 	U_BOOT_CMD_MKENT(update, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_update,
221 			 "", ""),
222 	U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
223 			 "", ""),
224 	U_BOOT_CMD_MKENT(disk-update, 0, 0, do_efi_capsule_on_disk_update,
225 			 "", ""),
226 	U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
227 			 "", ""),
228 };
229 
230 /**
231  * do_efi_capsule() - manage UEFI capsules
232  *
233  * @cmdtp:	Command table
234  * @flag:	Command flag
235  * @argc:	Number of arguments
236  * @argv:	Argument array
237  * Return:	CMD_RET_SUCCESS on success,
238  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
239  *
240  * Implement efidebug "capsule" sub-command.
241  */
do_efi_capsule(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])242 static int do_efi_capsule(struct cmd_tbl *cmdtp, int flag,
243 			  int argc, char * const argv[])
244 {
245 	struct cmd_tbl *cp;
246 
247 	if (argc < 2)
248 		return CMD_RET_USAGE;
249 
250 	argc--; argv++;
251 
252 	cp = find_cmd_tbl(argv[0], cmd_efidebug_capsule_sub,
253 			  ARRAY_SIZE(cmd_efidebug_capsule_sub));
254 	if (!cp)
255 		return CMD_RET_USAGE;
256 
257 	return cp->cmd(cmdtp, flag, argc, argv);
258 }
259 #endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */
260 
261 /**
262  * efi_get_device_handle_info() - get information of UEFI device
263  *
264  * @handle:		Handle of UEFI device
265  * @dev_path_text:	Pointer to text of device path
266  * Return:		0 on success, -1 on failure
267  *
268  * Currently return a formatted text of device path.
269  */
efi_get_device_handle_info(efi_handle_t handle,u16 ** dev_path_text)270 static int efi_get_device_handle_info(efi_handle_t handle, u16 **dev_path_text)
271 {
272 	struct efi_device_path *dp;
273 	efi_status_t ret;
274 
275 	ret = EFI_CALL(BS->open_protocol(handle, &efi_guid_device_path,
276 					 (void **)&dp, NULL /* FIXME */, NULL,
277 					 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
278 	if (ret == EFI_SUCCESS) {
279 		*dev_path_text = efi_dp_str(dp);
280 		return 0;
281 	} else {
282 		return -1;
283 	}
284 }
285 
286 #define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
287 
288 static const char spc[] = "                ";
289 static const char sep[] = "================";
290 
291 /**
292  * do_efi_show_devices() - show UEFI devices
293  *
294  * @cmdtp:	Command table
295  * @flag:	Command flag
296  * @argc:	Number of arguments
297  * @argv:	Argument array
298  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
299  *
300  * Implement efidebug "devices" sub-command.
301  * Show all UEFI devices and their information.
302  */
do_efi_show_devices(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])303 static int do_efi_show_devices(struct cmd_tbl *cmdtp, int flag,
304 			       int argc, char *const argv[])
305 {
306 	efi_handle_t *handles;
307 	efi_uintn_t num, i;
308 	u16 *dev_path_text;
309 	efi_status_t ret;
310 
311 	ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
312 						&num, &handles));
313 	if (ret != EFI_SUCCESS)
314 		return CMD_RET_FAILURE;
315 
316 	if (!num)
317 		return CMD_RET_SUCCESS;
318 
319 	printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
320 	printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
321 	for (i = 0; i < num; i++) {
322 		if (!efi_get_device_handle_info(handles[i], &dev_path_text)) {
323 			printf("%p %ls\n", handles[i], dev_path_text);
324 			efi_free_pool(dev_path_text);
325 		}
326 	}
327 
328 	efi_free_pool(handles);
329 
330 	return CMD_RET_SUCCESS;
331 }
332 
333 /**
334  * efi_get_driver_handle_info() - get information of UEFI driver
335  *
336  * @handle:		Handle of UEFI device
337  * @driver_name:	Driver name
338  * @image_path:		Pointer to text of device path
339  * Return:		0 on success, -1 on failure
340  *
341  * Currently return no useful information as all UEFI drivers are
342  * built-in..
343  */
efi_get_driver_handle_info(efi_handle_t handle,u16 ** driver_name,u16 ** image_path)344 static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
345 				      u16 **image_path)
346 {
347 	struct efi_handler *handler;
348 	struct efi_loaded_image *image;
349 	efi_status_t ret;
350 
351 	/*
352 	 * driver name
353 	 * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
354 	 */
355 	*driver_name = NULL;
356 
357 	/* image name */
358 	ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
359 	if (ret != EFI_SUCCESS) {
360 		*image_path = NULL;
361 		return 0;
362 	}
363 
364 	image = handler->protocol_interface;
365 	*image_path = efi_dp_str(image->file_path);
366 
367 	return 0;
368 }
369 
370 /**
371  * do_efi_show_drivers() - show UEFI drivers
372  *
373  * @cmdtp:	Command table
374  * @flag:	Command flag
375  * @argc:	Number of arguments
376  * @argv:	Argument array
377  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
378  *
379  * Implement efidebug "drivers" sub-command.
380  * Show all UEFI drivers and their information.
381  */
do_efi_show_drivers(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])382 static int do_efi_show_drivers(struct cmd_tbl *cmdtp, int flag,
383 			       int argc, char *const argv[])
384 {
385 	efi_handle_t *handles;
386 	efi_uintn_t num, i;
387 	u16 *driver_name, *image_path_text;
388 	efi_status_t ret;
389 
390 	ret = EFI_CALL(efi_locate_handle_buffer(
391 				BY_PROTOCOL, &efi_guid_driver_binding_protocol,
392 				NULL, &num, &handles));
393 	if (ret != EFI_SUCCESS)
394 		return CMD_RET_FAILURE;
395 
396 	if (!num)
397 		return CMD_RET_SUCCESS;
398 
399 	printf("Driver%.*s Name                 Image Path\n",
400 	       EFI_HANDLE_WIDTH - 6, spc);
401 	printf("%.*s ==================== ====================\n",
402 	       EFI_HANDLE_WIDTH, sep);
403 	for (i = 0; i < num; i++) {
404 		if (!efi_get_driver_handle_info(handles[i], &driver_name,
405 						&image_path_text)) {
406 			if (image_path_text)
407 				printf("%p %-20ls %ls\n", handles[i],
408 				       driver_name, image_path_text);
409 			else
410 				printf("%p %-20ls <built-in>\n",
411 				       handles[i], driver_name);
412 			efi_free_pool(driver_name);
413 			efi_free_pool(image_path_text);
414 		}
415 	}
416 
417 	efi_free_pool(handles);
418 
419 	return CMD_RET_SUCCESS;
420 }
421 
422 static const struct {
423 	const char *text;
424 	const efi_guid_t guid;
425 } guid_list[] = {
426 	{
427 		"Device Path",
428 		EFI_DEVICE_PATH_PROTOCOL_GUID,
429 	},
430 	{
431 		"Device Path To Text",
432 		EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID,
433 	},
434 	{
435 		"Device Path Utilities",
436 		EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID,
437 	},
438 	{
439 		"Unicode Collation 2",
440 		EFI_UNICODE_COLLATION_PROTOCOL2_GUID,
441 	},
442 	{
443 		"Driver Binding",
444 		EFI_DRIVER_BINDING_PROTOCOL_GUID,
445 	},
446 	{
447 		"Simple Text Input",
448 		EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID,
449 	},
450 	{
451 		"Simple Text Input Ex",
452 		EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID,
453 	},
454 	{
455 		"Simple Text Output",
456 		EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID,
457 	},
458 	{
459 		"Block IO",
460 		EFI_BLOCK_IO_PROTOCOL_GUID,
461 	},
462 	{
463 		"Simple File System",
464 		EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
465 	},
466 	{
467 		"Loaded Image",
468 		EFI_LOADED_IMAGE_PROTOCOL_GUID,
469 	},
470 	{
471 		"Graphics Output",
472 		EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
473 	},
474 	{
475 		"HII String",
476 		EFI_HII_STRING_PROTOCOL_GUID,
477 	},
478 	{
479 		"HII Database",
480 		EFI_HII_DATABASE_PROTOCOL_GUID,
481 	},
482 	{
483 		"HII Config Routing",
484 		EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
485 	},
486 	{
487 		"Load File2",
488 		EFI_LOAD_FILE2_PROTOCOL_GUID,
489 	},
490 	{
491 		"Random Number Generator",
492 		EFI_RNG_PROTOCOL_GUID,
493 	},
494 	{
495 		"Simple Network",
496 		EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
497 	},
498 	{
499 		"PXE Base Code",
500 		EFI_PXE_BASE_CODE_PROTOCOL_GUID,
501 	},
502 	{
503 		"Device-Tree Fixup",
504 		EFI_DT_FIXUP_PROTOCOL_GUID,
505 	},
506 	{
507 		"System Partition",
508 		PARTITION_SYSTEM_GUID
509 	},
510 	{
511 		"Firmware Management",
512 		EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID
513 	},
514 	/* Configuration table GUIDs */
515 	{
516 		"ACPI table",
517 		EFI_ACPI_TABLE_GUID,
518 	},
519 	{
520 		"device tree",
521 		EFI_FDT_GUID,
522 	},
523 	{
524 		"SMBIOS table",
525 		SMBIOS_TABLE_GUID,
526 	},
527 	{
528 		"Runtime properties",
529 		EFI_RT_PROPERTIES_TABLE_GUID,
530 	},
531 	{
532 		"TCG2 Final Events Table",
533 		EFI_TCG2_FINAL_EVENTS_TABLE_GUID,
534 	},
535 };
536 
537 /**
538  * get_guid_text - get string of GUID
539  *
540  * Return description of GUID.
541  *
542  * @guid:	GUID
543  * Return:	description of GUID or NULL
544  */
get_guid_text(const void * guid)545 static const char *get_guid_text(const void *guid)
546 {
547 	int i;
548 
549 	for (i = 0; i < ARRAY_SIZE(guid_list); i++) {
550 		/*
551 		 * As guidcmp uses memcmp() we can safely accept unaligned
552 		 * GUIDs.
553 		 */
554 		if (!guidcmp(&guid_list[i].guid, guid))
555 			return guid_list[i].text;
556 	}
557 
558 	return NULL;
559 }
560 
561 /**
562  * do_efi_show_handles() - show UEFI handles
563  *
564  * @cmdtp:	Command table
565  * @flag:	Command flag
566  * @argc:	Number of arguments
567  * @argv:	Argument array
568  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
569  *
570  * Implement efidebug "dh" sub-command.
571  * Show all UEFI handles and their information, currently all protocols
572  * added to handle.
573  */
do_efi_show_handles(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])574 static int do_efi_show_handles(struct cmd_tbl *cmdtp, int flag,
575 			       int argc, char *const argv[])
576 {
577 	efi_handle_t *handles;
578 	efi_guid_t **guid;
579 	efi_uintn_t num, count, i, j;
580 	const char *guid_text;
581 	efi_status_t ret;
582 
583 	ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
584 						&num, &handles));
585 	if (ret != EFI_SUCCESS)
586 		return CMD_RET_FAILURE;
587 
588 	if (!num)
589 		return CMD_RET_SUCCESS;
590 
591 	printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
592 	printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
593 	for (i = 0; i < num; i++) {
594 		printf("%p", handles[i]);
595 		ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
596 							&count));
597 		if (ret || !count) {
598 			putc('\n');
599 			continue;
600 		}
601 
602 		for (j = 0; j < count; j++) {
603 			if (j)
604 				printf(", ");
605 			else
606 				putc(' ');
607 
608 			guid_text = get_guid_text(guid[j]);
609 			if (guid_text)
610 				puts(guid_text);
611 			else
612 				printf("%pUl", guid[j]);
613 		}
614 		putc('\n');
615 	}
616 
617 	efi_free_pool(handles);
618 
619 	return CMD_RET_SUCCESS;
620 }
621 
622 /**
623  * do_efi_show_images() - show UEFI images
624  *
625  * @cmdtp:	Command table
626  * @flag:	Command flag
627  * @argc:	Number of arguments
628  * @argv:	Argument array
629  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
630  *
631  * Implement efidebug "images" sub-command.
632  * Show all UEFI loaded images and their information.
633  */
do_efi_show_images(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])634 static int do_efi_show_images(struct cmd_tbl *cmdtp, int flag,
635 			      int argc, char *const argv[])
636 {
637 	efi_print_image_infos(NULL);
638 
639 	return CMD_RET_SUCCESS;
640 }
641 
642 static const char * const efi_mem_type_string[] = {
643 	[EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
644 	[EFI_LOADER_CODE] = "LOADER CODE",
645 	[EFI_LOADER_DATA] = "LOADER DATA",
646 	[EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
647 	[EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
648 	[EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
649 	[EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
650 	[EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
651 	[EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
652 	[EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
653 	[EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
654 	[EFI_MMAP_IO] = "IO",
655 	[EFI_MMAP_IO_PORT] = "IO PORT",
656 	[EFI_PAL_CODE] = "PAL",
657 	[EFI_PERSISTENT_MEMORY_TYPE] = "PERSISTENT",
658 };
659 
660 static const struct efi_mem_attrs {
661 	const u64 bit;
662 	const char *text;
663 } efi_mem_attrs[] = {
664 	{EFI_MEMORY_UC, "UC"},
665 	{EFI_MEMORY_UC, "UC"},
666 	{EFI_MEMORY_WC, "WC"},
667 	{EFI_MEMORY_WT, "WT"},
668 	{EFI_MEMORY_WB, "WB"},
669 	{EFI_MEMORY_UCE, "UCE"},
670 	{EFI_MEMORY_WP, "WP"},
671 	{EFI_MEMORY_RP, "RP"},
672 	{EFI_MEMORY_XP, "WP"},
673 	{EFI_MEMORY_NV, "NV"},
674 	{EFI_MEMORY_MORE_RELIABLE, "REL"},
675 	{EFI_MEMORY_RO, "RO"},
676 	{EFI_MEMORY_SP, "SP"},
677 	{EFI_MEMORY_RUNTIME, "RT"},
678 };
679 
680 /**
681  * print_memory_attributes() - print memory map attributes
682  *
683  * @attributes:	Attribute value
684  *
685  * Print memory map attributes
686  */
print_memory_attributes(u64 attributes)687 static void print_memory_attributes(u64 attributes)
688 {
689 	int sep, i;
690 
691 	for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
692 		if (attributes & efi_mem_attrs[i].bit) {
693 			if (sep) {
694 				putc('|');
695 			} else {
696 				putc(' ');
697 				sep = 1;
698 			}
699 			puts(efi_mem_attrs[i].text);
700 		}
701 }
702 
703 #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
704 
705 /**
706  * do_efi_show_memmap() - show UEFI memory map
707  *
708  * @cmdtp:	Command table
709  * @flag:	Command flag
710  * @argc:	Number of arguments
711  * @argv:	Argument array
712  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
713  *
714  * Implement efidebug "memmap" sub-command.
715  * Show UEFI memory map.
716  */
do_efi_show_memmap(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])717 static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
718 			      int argc, char *const argv[])
719 {
720 	struct efi_mem_desc *memmap = NULL, *map;
721 	efi_uintn_t map_size = 0;
722 	const char *type;
723 	int i;
724 	efi_status_t ret;
725 
726 	ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
727 	if (ret == EFI_BUFFER_TOO_SMALL) {
728 		map_size += sizeof(struct efi_mem_desc); /* for my own */
729 		ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
730 					(void *)&memmap);
731 		if (ret != EFI_SUCCESS)
732 			return CMD_RET_FAILURE;
733 		ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
734 	}
735 	if (ret != EFI_SUCCESS) {
736 		efi_free_pool(memmap);
737 		return CMD_RET_FAILURE;
738 	}
739 
740 	printf("Type             Start%.*s End%.*s Attributes\n",
741 	       EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
742 	printf("================ %.*s %.*s ==========\n",
743 	       EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
744 	/*
745 	 * Coverity check: dereferencing null pointer "map."
746 	 * This is a false positive as memmap will always be
747 	 * populated by allocate_pool() above.
748 	 */
749 	for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
750 		if (map->type < ARRAY_SIZE(efi_mem_type_string))
751 			type = efi_mem_type_string[map->type];
752 		else
753 			type = "(unknown)";
754 
755 		printf("%-16s %.*llx-%.*llx", type,
756 		       EFI_PHYS_ADDR_WIDTH,
757 		       (u64)map_to_sysmem((void *)(uintptr_t)
758 					  map->physical_start),
759 		       EFI_PHYS_ADDR_WIDTH,
760 		       (u64)map_to_sysmem((void *)(uintptr_t)
761 					  (map->physical_start +
762 					   map->num_pages * EFI_PAGE_SIZE)));
763 
764 		print_memory_attributes(map->attribute);
765 		putc('\n');
766 	}
767 
768 	efi_free_pool(memmap);
769 
770 	return CMD_RET_SUCCESS;
771 }
772 
773 /**
774  * do_efi_show_tables() - show UEFI configuration tables
775  *
776  * @cmdtp:	Command table
777  * @flag:	Command flag
778  * @argc:	Number of arguments
779  * @argv:	Argument array
780  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
781  *
782  * Implement efidebug "tables" sub-command.
783  * Show UEFI configuration tables.
784  */
do_efi_show_tables(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])785 static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
786 			      int argc, char *const argv[])
787 {
788 	efi_uintn_t i;
789 	const char *guid_str;
790 
791 	for (i = 0; i < systab.nr_tables; ++i) {
792 		guid_str = get_guid_text(&systab.tables[i].guid);
793 		if (!guid_str)
794 			guid_str = "";
795 		printf("%pUl %s\n", &systab.tables[i].guid, guid_str);
796 	}
797 
798 	return CMD_RET_SUCCESS;
799 }
800 
801 /**
802  * do_efi_boot_add() - set UEFI load option
803  *
804  * @cmdtp:	Command table
805  * @flag:	Command flag
806  * @argc:	Number of arguments
807  * @argv:	Argument array
808  * Return:	CMD_RET_SUCCESS on success,
809  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
810  *
811  * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
812  *
813  *     efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
814  */
do_efi_boot_add(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])815 static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
816 			   int argc, char *const argv[])
817 {
818 	int id;
819 	char *endp;
820 	char var_name[9];
821 	u16 var_name16[9], *p;
822 	efi_guid_t guid;
823 	size_t label_len, label_len16;
824 	u16 *label;
825 	struct efi_device_path *device_path = NULL, *file_path = NULL;
826 	struct efi_load_option lo;
827 	void *data = NULL;
828 	efi_uintn_t size;
829 	efi_status_t ret;
830 	int r = CMD_RET_SUCCESS;
831 
832 	if (argc < 6 || argc > 7)
833 		return CMD_RET_USAGE;
834 
835 	id = (int)simple_strtoul(argv[1], &endp, 16);
836 	if (*endp != '\0' || id > 0xffff)
837 		return CMD_RET_USAGE;
838 
839 	sprintf(var_name, "Boot%04X", id);
840 	p = var_name16;
841 	utf8_utf16_strncpy(&p, var_name, 9);
842 
843 	guid = efi_global_variable_guid;
844 
845 	/* attributes */
846 	lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
847 
848 	/* label */
849 	label_len = strlen(argv[2]);
850 	label_len16 = utf8_utf16_strnlen(argv[2], label_len);
851 	label = malloc((label_len16 + 1) * sizeof(u16));
852 	if (!label)
853 		return CMD_RET_FAILURE;
854 	lo.label = label; /* label will be changed below */
855 	utf8_utf16_strncpy(&label, argv[2], label_len);
856 
857 	/* file path */
858 	ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
859 			       &file_path);
860 	if (ret != EFI_SUCCESS) {
861 		printf("Cannot create device path for \"%s %s\"\n",
862 		       argv[3], argv[4]);
863 		r = CMD_RET_FAILURE;
864 		goto out;
865 	}
866 	lo.file_path = file_path;
867 	lo.file_path_length = efi_dp_size(file_path)
868 				+ sizeof(struct efi_device_path); /* for END */
869 
870 	/* optional data */
871 	if (argc == 6)
872 		lo.optional_data = NULL;
873 	else
874 		lo.optional_data = (const u8 *)argv[6];
875 
876 	size = efi_serialize_load_option(&lo, (u8 **)&data);
877 	if (!size) {
878 		r = CMD_RET_FAILURE;
879 		goto out;
880 	}
881 
882 	ret = EFI_CALL(efi_set_variable(var_name16, &guid,
883 					EFI_VARIABLE_NON_VOLATILE |
884 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
885 					EFI_VARIABLE_RUNTIME_ACCESS,
886 					size, data));
887 	if (ret != EFI_SUCCESS) {
888 		printf("Cannot set %ls\n", var_name16);
889 		r = CMD_RET_FAILURE;
890 	}
891 out:
892 	free(data);
893 	efi_free_pool(device_path);
894 	efi_free_pool(file_path);
895 	free(lo.label);
896 
897 	return r;
898 }
899 
900 /**
901  * do_efi_boot_rm() - delete UEFI load options
902  *
903  * @cmdtp:	Command table
904  * @flag:	Command flag
905  * @argc:	Number of arguments
906  * @argv:	Argument array
907  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
908  *
909  * Implement efidebug "boot rm" sub-command.
910  * Delete UEFI load options.
911  *
912  *     efidebug boot rm <id> ...
913  */
do_efi_boot_rm(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])914 static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
915 			  int argc, char *const argv[])
916 {
917 	efi_guid_t guid;
918 	int id, i;
919 	char *endp;
920 	char var_name[9];
921 	u16 var_name16[9], *p;
922 	efi_status_t ret;
923 
924 	if (argc == 1)
925 		return CMD_RET_USAGE;
926 
927 	guid = efi_global_variable_guid;
928 	for (i = 1; i < argc; i++, argv++) {
929 		id = (int)simple_strtoul(argv[1], &endp, 16);
930 		if (*endp != '\0' || id > 0xffff)
931 			return CMD_RET_FAILURE;
932 
933 		sprintf(var_name, "Boot%04X", id);
934 		p = var_name16;
935 		utf8_utf16_strncpy(&p, var_name, 9);
936 
937 		ret = EFI_CALL(efi_set_variable(var_name16, &guid, 0, 0, NULL));
938 		if (ret) {
939 			printf("Cannot remove %ls\n", var_name16);
940 			return CMD_RET_FAILURE;
941 		}
942 	}
943 
944 	return CMD_RET_SUCCESS;
945 }
946 
947 /**
948  * show_efi_boot_opt_data() - dump UEFI load option
949  *
950  * @varname16:	variable name
951  * @data:	value of UEFI load option variable
952  * @size:	size of the boot option
953  *
954  * Decode the value of UEFI load option variable and print information.
955  */
show_efi_boot_opt_data(u16 * varname16,void * data,size_t * size)956 static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
957 {
958 	struct efi_load_option lo;
959 	char *label, *p;
960 	size_t label_len16, label_len;
961 	u16 *dp_str;
962 	efi_status_t ret;
963 
964 	ret = efi_deserialize_load_option(&lo, data, size);
965 	if (ret != EFI_SUCCESS) {
966 		printf("%ls: invalid load option\n", varname16);
967 		return;
968 	}
969 
970 	label_len16 = u16_strlen(lo.label);
971 	label_len = utf16_utf8_strnlen(lo.label, label_len16);
972 	label = malloc(label_len + 1);
973 	if (!label)
974 		return;
975 	p = label;
976 	utf16_utf8_strncpy(&p, lo.label, label_len16);
977 
978 	printf("%ls:\nattributes: %c%c%c (0x%08x)\n",
979 	       varname16,
980 	       /* ACTIVE */
981 	       lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
982 	       /* FORCE RECONNECT */
983 	       lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
984 	       /* HIDDEN */
985 	       lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
986 	       lo.attributes);
987 	printf("  label: %s\n", label);
988 
989 	dp_str = efi_dp_str(lo.file_path);
990 	printf("  file_path: %ls\n", dp_str);
991 	efi_free_pool(dp_str);
992 
993 	printf("  data:\n");
994 	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
995 		       lo.optional_data, *size, true);
996 	free(label);
997 }
998 
999 /**
1000  * show_efi_boot_opt() - dump UEFI load option
1001  *
1002  * @varname16:	variable name
1003  *
1004  * Dump information defined by UEFI load option.
1005  */
show_efi_boot_opt(u16 * varname16)1006 static void show_efi_boot_opt(u16 *varname16)
1007 {
1008 	void *data;
1009 	efi_uintn_t size;
1010 	efi_status_t ret;
1011 
1012 	size = 0;
1013 	ret = EFI_CALL(efi_get_variable(varname16, &efi_global_variable_guid,
1014 					NULL, &size, NULL));
1015 	if (ret == EFI_BUFFER_TOO_SMALL) {
1016 		data = malloc(size);
1017 		if (!data) {
1018 			printf("ERROR: Out of memory\n");
1019 			return;
1020 		}
1021 		ret = EFI_CALL(efi_get_variable(varname16,
1022 						&efi_global_variable_guid,
1023 						NULL, &size, data));
1024 		if (ret == EFI_SUCCESS)
1025 			show_efi_boot_opt_data(varname16, data, &size);
1026 		free(data);
1027 	}
1028 }
1029 
u16_tohex(u16 c)1030 static int u16_tohex(u16 c)
1031 {
1032 	if (c >= '0' && c <= '9')
1033 		return c - '0';
1034 	if (c >= 'A' && c <= 'F')
1035 		return c - 'A' + 10;
1036 
1037 	/* not hexadecimal */
1038 	return -1;
1039 }
1040 
1041 /**
1042  * show_efi_boot_dump() - dump all UEFI load options
1043  *
1044  * @cmdtp:	Command table
1045  * @flag:	Command flag
1046  * @argc:	Number of arguments
1047  * @argv:	Argument array
1048  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1049  *
1050  * Implement efidebug "boot dump" sub-command.
1051  * Dump information of all UEFI load options defined.
1052  *
1053  *     efidebug boot dump
1054  */
do_efi_boot_dump(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1055 static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
1056 			    int argc, char *const argv[])
1057 {
1058 	u16 *var_name16, *p;
1059 	efi_uintn_t buf_size, size;
1060 	efi_guid_t guid;
1061 	int id, i, digit;
1062 	efi_status_t ret;
1063 
1064 	if (argc > 1)
1065 		return CMD_RET_USAGE;
1066 
1067 	buf_size = 128;
1068 	var_name16 = malloc(buf_size);
1069 	if (!var_name16)
1070 		return CMD_RET_FAILURE;
1071 
1072 	var_name16[0] = 0;
1073 	for (;;) {
1074 		size = buf_size;
1075 		ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
1076 							  &guid));
1077 		if (ret == EFI_NOT_FOUND)
1078 			break;
1079 		if (ret == EFI_BUFFER_TOO_SMALL) {
1080 			buf_size = size;
1081 			p = realloc(var_name16, buf_size);
1082 			if (!p) {
1083 				free(var_name16);
1084 				return CMD_RET_FAILURE;
1085 			}
1086 			var_name16 = p;
1087 			ret = EFI_CALL(efi_get_next_variable_name(&size,
1088 								  var_name16,
1089 								  &guid));
1090 		}
1091 		if (ret != EFI_SUCCESS) {
1092 			free(var_name16);
1093 			return CMD_RET_FAILURE;
1094 		}
1095 
1096 		if (memcmp(var_name16, L"Boot", 8))
1097 			continue;
1098 
1099 		for (id = 0, i = 0; i < 4; i++) {
1100 			digit = u16_tohex(var_name16[4 + i]);
1101 			if (digit < 0)
1102 				break;
1103 			id = (id << 4) + digit;
1104 		}
1105 		if (i == 4 && !var_name16[8])
1106 			show_efi_boot_opt(var_name16);
1107 	}
1108 
1109 	free(var_name16);
1110 
1111 	return CMD_RET_SUCCESS;
1112 }
1113 
1114 /**
1115  * show_efi_boot_order() - show order of UEFI load options
1116  *
1117  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1118  *
1119  * Show order of UEFI load options defined by BootOrder variable.
1120  */
show_efi_boot_order(void)1121 static int show_efi_boot_order(void)
1122 {
1123 	u16 *bootorder;
1124 	efi_uintn_t size;
1125 	int num, i;
1126 	char var_name[9];
1127 	u16 var_name16[9], *p16;
1128 	void *data;
1129 	struct efi_load_option lo;
1130 	char *label, *p;
1131 	size_t label_len16, label_len;
1132 	efi_status_t ret;
1133 
1134 	size = 0;
1135 	ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
1136 					NULL, &size, NULL));
1137 	if (ret != EFI_BUFFER_TOO_SMALL) {
1138 		if (ret == EFI_NOT_FOUND) {
1139 			printf("BootOrder not defined\n");
1140 			return CMD_RET_SUCCESS;
1141 		} else {
1142 			return CMD_RET_FAILURE;
1143 		}
1144 	}
1145 	bootorder = malloc(size);
1146 	if (!bootorder) {
1147 		printf("ERROR: Out of memory\n");
1148 		return CMD_RET_FAILURE;
1149 	}
1150 	ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
1151 					NULL, &size, bootorder));
1152 	if (ret != EFI_SUCCESS) {
1153 		ret = CMD_RET_FAILURE;
1154 		goto out;
1155 	}
1156 
1157 	num = size / sizeof(u16);
1158 	for (i = 0; i < num; i++) {
1159 		sprintf(var_name, "Boot%04X", bootorder[i]);
1160 		p16 = var_name16;
1161 		utf8_utf16_strncpy(&p16, var_name, 9);
1162 
1163 		size = 0;
1164 		ret = EFI_CALL(efi_get_variable(var_name16,
1165 						&efi_global_variable_guid, NULL,
1166 						&size, NULL));
1167 		if (ret != EFI_BUFFER_TOO_SMALL) {
1168 			printf("%2d: %s: (not defined)\n", i + 1, var_name);
1169 			continue;
1170 		}
1171 
1172 		data = malloc(size);
1173 		if (!data) {
1174 			ret = CMD_RET_FAILURE;
1175 			goto out;
1176 		}
1177 		ret = EFI_CALL(efi_get_variable(var_name16,
1178 						&efi_global_variable_guid, NULL,
1179 						&size, data));
1180 		if (ret != EFI_SUCCESS) {
1181 			free(data);
1182 			ret = CMD_RET_FAILURE;
1183 			goto out;
1184 		}
1185 
1186 		ret = efi_deserialize_load_option(&lo, data, &size);
1187 		if (ret != EFI_SUCCESS) {
1188 			printf("%ls: invalid load option\n", var_name16);
1189 			ret = CMD_RET_FAILURE;
1190 			goto out;
1191 		}
1192 
1193 		label_len16 = u16_strlen(lo.label);
1194 		label_len = utf16_utf8_strnlen(lo.label, label_len16);
1195 		label = malloc(label_len + 1);
1196 		if (!label) {
1197 			free(data);
1198 			ret = CMD_RET_FAILURE;
1199 			goto out;
1200 		}
1201 		p = label;
1202 		utf16_utf8_strncpy(&p, lo.label, label_len16);
1203 		printf("%2d: %s: %s\n", i + 1, var_name, label);
1204 		free(label);
1205 
1206 		free(data);
1207 	}
1208 out:
1209 	free(bootorder);
1210 
1211 	return ret;
1212 }
1213 
1214 /**
1215  * do_efi_boot_next() - manage UEFI BootNext variable
1216  *
1217  * @cmdtp:	Command table
1218  * @flag:	Command flag
1219  * @argc:	Number of arguments
1220  * @argv:	Argument array
1221  * Return:	CMD_RET_SUCCESS on success,
1222  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1223  *
1224  * Implement efidebug "boot next" sub-command.
1225  * Set BootNext variable.
1226  *
1227  *     efidebug boot next <id>
1228  */
do_efi_boot_next(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1229 static int do_efi_boot_next(struct cmd_tbl *cmdtp, int flag,
1230 			    int argc, char *const argv[])
1231 {
1232 	u16 bootnext;
1233 	efi_uintn_t size;
1234 	char *endp;
1235 	efi_guid_t guid;
1236 	efi_status_t ret;
1237 	int r = CMD_RET_SUCCESS;
1238 
1239 	if (argc != 2)
1240 		return CMD_RET_USAGE;
1241 
1242 	bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
1243 	if (*endp) {
1244 		printf("invalid value: %s\n", argv[1]);
1245 		r = CMD_RET_FAILURE;
1246 		goto out;
1247 	}
1248 
1249 	guid = efi_global_variable_guid;
1250 	size = sizeof(u16);
1251 	ret = EFI_CALL(efi_set_variable(L"BootNext", &guid,
1252 					EFI_VARIABLE_NON_VOLATILE |
1253 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
1254 					EFI_VARIABLE_RUNTIME_ACCESS,
1255 					size, &bootnext));
1256 	if (ret != EFI_SUCCESS) {
1257 		printf("Cannot set BootNext\n");
1258 		r = CMD_RET_FAILURE;
1259 	}
1260 out:
1261 	return r;
1262 }
1263 
1264 /**
1265  * do_efi_boot_order() - manage UEFI BootOrder variable
1266  *
1267  * @cmdtp:	Command table
1268  * @flag:	Command flag
1269  * @argc:	Number of arguments
1270  * @argv:	Argument array
1271  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1272  *
1273  * Implement efidebug "boot order" sub-command.
1274  * Show order of UEFI load options, or change it in BootOrder variable.
1275  *
1276  *     efidebug boot order [<id> ...]
1277  */
do_efi_boot_order(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1278 static int do_efi_boot_order(struct cmd_tbl *cmdtp, int flag,
1279 			     int argc, char *const argv[])
1280 {
1281 	u16 *bootorder = NULL;
1282 	efi_uintn_t size;
1283 	int id, i;
1284 	char *endp;
1285 	efi_guid_t guid;
1286 	efi_status_t ret;
1287 	int r = CMD_RET_SUCCESS;
1288 
1289 	if (argc == 1)
1290 		return show_efi_boot_order();
1291 
1292 	argc--;
1293 	argv++;
1294 
1295 	size = argc * sizeof(u16);
1296 	bootorder = malloc(size);
1297 	if (!bootorder)
1298 		return CMD_RET_FAILURE;
1299 
1300 	for (i = 0; i < argc; i++) {
1301 		id = (int)simple_strtoul(argv[i], &endp, 16);
1302 		if (*endp != '\0' || id > 0xffff) {
1303 			printf("invalid value: %s\n", argv[i]);
1304 			r = CMD_RET_FAILURE;
1305 			goto out;
1306 		}
1307 
1308 		bootorder[i] = (u16)id;
1309 	}
1310 
1311 	guid = efi_global_variable_guid;
1312 	ret = EFI_CALL(efi_set_variable(L"BootOrder", &guid,
1313 					EFI_VARIABLE_NON_VOLATILE |
1314 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
1315 					EFI_VARIABLE_RUNTIME_ACCESS,
1316 					size, bootorder));
1317 	if (ret != EFI_SUCCESS) {
1318 		printf("Cannot set BootOrder\n");
1319 		r = CMD_RET_FAILURE;
1320 	}
1321 out:
1322 	free(bootorder);
1323 
1324 	return r;
1325 }
1326 
1327 static struct cmd_tbl cmd_efidebug_boot_sub[] = {
1328 	U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
1329 	U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
1330 	U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
1331 	U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
1332 	U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
1333 			 "", ""),
1334 };
1335 
1336 /**
1337  * do_efi_boot_opt() - manage UEFI load options
1338  *
1339  * @cmdtp:	Command table
1340  * @flag:	Command flag
1341  * @argc:	Number of arguments
1342  * @argv:	Argument array
1343  * Return:	CMD_RET_SUCCESS on success,
1344  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1345  *
1346  * Implement efidebug "boot" sub-command.
1347  */
do_efi_boot_opt(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1348 static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
1349 			   int argc, char *const argv[])
1350 {
1351 	struct cmd_tbl *cp;
1352 
1353 	if (argc < 2)
1354 		return CMD_RET_USAGE;
1355 
1356 	argc--; argv++;
1357 
1358 	cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
1359 			  ARRAY_SIZE(cmd_efidebug_boot_sub));
1360 	if (!cp)
1361 		return CMD_RET_USAGE;
1362 
1363 	return cp->cmd(cmdtp, flag, argc, argv);
1364 }
1365 
1366 /**
1367  * do_efi_test_bootmgr() - run simple bootmgr for test
1368  *
1369  * @cmdtp:	Command table
1370  * @flag:	Command flag
1371  * @argc:	Number of arguments
1372  * @argv:	Argument array
1373  * Return:	CMD_RET_SUCCESS on success,
1374  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1375  *
1376  * Implement efidebug "test bootmgr" sub-command.
1377  * Run simple bootmgr for test.
1378  *
1379  *     efidebug test bootmgr
1380  */
do_efi_test_bootmgr(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1381 static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
1382 					      int argc, char * const argv[])
1383 {
1384 	efi_handle_t image;
1385 	efi_uintn_t exit_data_size = 0;
1386 	u16 *exit_data = NULL;
1387 	efi_status_t ret;
1388 	void *load_options = NULL;
1389 
1390 	ret = efi_bootmgr_load(&image, &load_options);
1391 	printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1392 
1393 	/* We call efi_start_image() even if error for test purpose. */
1394 	ret = EFI_CALL(efi_start_image(image, &exit_data_size, &exit_data));
1395 	printf("efi_start_image() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1396 	if (ret && exit_data)
1397 		efi_free_pool(exit_data);
1398 
1399 	efi_restore_gd();
1400 
1401 	free(load_options);
1402 	return CMD_RET_SUCCESS;
1403 }
1404 
1405 static struct cmd_tbl cmd_efidebug_test_sub[] = {
1406 #ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
1407 	U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
1408 			 "", ""),
1409 #endif
1410 };
1411 
1412 /**
1413  * do_efi_test() - manage UEFI load options
1414  *
1415  * @cmdtp:	Command table
1416  * @flag:	Command flag
1417  * @argc:	Number of arguments
1418  * @argv:	Argument array
1419  * Return:	CMD_RET_SUCCESS on success,
1420  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1421  *
1422  * Implement efidebug "test" sub-command.
1423  */
do_efi_test(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1424 static int do_efi_test(struct cmd_tbl *cmdtp, int flag,
1425 		       int argc, char * const argv[])
1426 {
1427 	struct cmd_tbl *cp;
1428 
1429 	if (argc < 2)
1430 		return CMD_RET_USAGE;
1431 
1432 	argc--; argv++;
1433 
1434 	cp = find_cmd_tbl(argv[0], cmd_efidebug_test_sub,
1435 			  ARRAY_SIZE(cmd_efidebug_test_sub));
1436 	if (!cp)
1437 		return CMD_RET_USAGE;
1438 
1439 	return cp->cmd(cmdtp, flag, argc, argv);
1440 }
1441 
1442 /**
1443  * do_efi_query_info() - QueryVariableInfo EFI service
1444  *
1445  * @cmdtp:	Command table
1446  * @flag:	Command flag
1447  * @argc:	Number of arguments
1448  * @argv:	Argument array
1449  * Return:	CMD_RET_SUCCESS on success,
1450  *		CMD_RET_USAGE or CMD_RET_FAILURE on failure
1451  *
1452  * Implement efidebug "test" sub-command.
1453  */
1454 
do_efi_query_info(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1455 static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
1456 			     int argc, char * const argv[])
1457 {
1458 	efi_status_t ret;
1459 	u32 attr = 0;
1460 	u64 max_variable_storage_size;
1461 	u64 remain_variable_storage_size;
1462 	u64 max_variable_size;
1463 	int i;
1464 
1465 	for (i = 1; i < argc; i++) {
1466 		if (!strcmp(argv[i], "-bs"))
1467 			attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
1468 		else if (!strcmp(argv[i], "-rt"))
1469 			attr |= EFI_VARIABLE_RUNTIME_ACCESS;
1470 		else if (!strcmp(argv[i], "-nv"))
1471 			attr |= EFI_VARIABLE_NON_VOLATILE;
1472 		else if (!strcmp(argv[i], "-at"))
1473 			attr |=
1474 				EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1475 	}
1476 
1477 	ret = EFI_CALL(efi_query_variable_info(attr,
1478 					       &max_variable_storage_size,
1479 					       &remain_variable_storage_size,
1480 					       &max_variable_size));
1481 	if (ret != EFI_SUCCESS) {
1482 		printf("Error: Cannot query UEFI variables, r = %lu\n",
1483 		       ret & ~EFI_ERROR_MASK);
1484 		return CMD_RET_FAILURE;
1485 	}
1486 
1487 	printf("Max storage size %llu\n", max_variable_storage_size);
1488 	printf("Remaining storage size %llu\n", remain_variable_storage_size);
1489 	printf("Max variable size %llu\n", max_variable_size);
1490 
1491 	return CMD_RET_SUCCESS;
1492 }
1493 
1494 static struct cmd_tbl cmd_efidebug_sub[] = {
1495 	U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
1496 #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1497 	U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule,
1498 			 "", ""),
1499 #endif
1500 	U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
1501 			 "", ""),
1502 	U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
1503 			 "", ""),
1504 	U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
1505 			 "", ""),
1506 	U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
1507 			 "", ""),
1508 	U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
1509 			 "", ""),
1510 	U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
1511 			 "", ""),
1512 	U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
1513 			 "", ""),
1514 	U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
1515 			 "", ""),
1516 };
1517 
1518 /**
1519  * do_efidebug() - display and configure UEFI environment
1520  *
1521  * @cmdtp:	Command table
1522  * @flag:	Command flag
1523  * @argc:	Number of arguments
1524  * @argv:	Argument array
1525  * Return:	CMD_RET_SUCCESS on success,
1526  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1527  *
1528  * Implement efidebug command which allows us to display and
1529  * configure UEFI environment.
1530  */
do_efidebug(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])1531 static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
1532 		       int argc, char *const argv[])
1533 {
1534 	struct cmd_tbl *cp;
1535 	efi_status_t r;
1536 
1537 	if (argc < 2)
1538 		return CMD_RET_USAGE;
1539 
1540 	argc--; argv++;
1541 
1542 	/* Initialize UEFI drivers */
1543 	r = efi_init_obj_list();
1544 	if (r != EFI_SUCCESS) {
1545 		printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
1546 		       r & ~EFI_ERROR_MASK);
1547 		return CMD_RET_FAILURE;
1548 	}
1549 
1550 	cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
1551 			  ARRAY_SIZE(cmd_efidebug_sub));
1552 	if (!cp)
1553 		return CMD_RET_USAGE;
1554 
1555 	return cp->cmd(cmdtp, flag, argc, argv);
1556 }
1557 
1558 #ifdef CONFIG_SYS_LONGHELP
1559 static char efidebug_help_text[] =
1560 	"  - UEFI Shell-like interface to configure UEFI environment\n"
1561 	"\n"
1562 	"efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
1563 	"  - set UEFI BootXXXX variable\n"
1564 	"    <load options> will be passed to UEFI application\n"
1565 	"efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
1566 	"  - delete UEFI BootXXXX variables\n"
1567 	"efidebug boot dump\n"
1568 	"  - dump all UEFI BootXXXX variables\n"
1569 	"efidebug boot next <bootid>\n"
1570 	"  - set UEFI BootNext variable\n"
1571 	"efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
1572 	"  - set/show UEFI boot order\n"
1573 	"\n"
1574 #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1575 	"efidebug capsule update [-v] <capsule address>\n"
1576 	"  - process a capsule\n"
1577 	"efidebug capsule disk-update\n"
1578 	"  - update a capsule from disk\n"
1579 	"efidebug capsule show <capsule address>\n"
1580 	"  - show capsule information\n"
1581 	"efidebug capsule result [<capsule result var>]\n"
1582 	"  - show a capsule update result\n"
1583 	"\n"
1584 #endif
1585 	"efidebug devices\n"
1586 	"  - show UEFI devices\n"
1587 	"efidebug drivers\n"
1588 	"  - show UEFI drivers\n"
1589 	"efidebug dh\n"
1590 	"  - show UEFI handles\n"
1591 	"efidebug images\n"
1592 	"  - show loaded images\n"
1593 	"efidebug memmap\n"
1594 	"  - show UEFI memory map\n"
1595 	"efidebug tables\n"
1596 	"  - show UEFI configuration tables\n"
1597 #ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
1598 	"efidebug test bootmgr\n"
1599 	"  - run simple bootmgr for test\n"
1600 #endif
1601 	"efidebug query [-nv][-bs][-rt][-at]\n"
1602 	"  - show size of UEFI variables store\n";
1603 #endif
1604 
1605 U_BOOT_CMD(
1606 	efidebug, 10, 0, do_efidebug,
1607 	"Configure UEFI environment",
1608 	efidebug_help_text
1609 );
1610