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