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