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