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