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