Merge branch '2021-02-02-drop-asm_global_data-when-unused'
[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, (u64)NULL));
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         /* Configuration table GUIDs */
511         {
512                 "ACPI table",
513                 EFI_ACPI_TABLE_GUID,
514         },
515         {
516                 "device tree",
517                 EFI_FDT_GUID,
518         },
519         {
520                 "SMBIOS table",
521                 SMBIOS_TABLE_GUID,
522         },
523         {
524                 "Runtime properties",
525                 EFI_RT_PROPERTIES_TABLE_GUID,
526         },
527         {
528                 "TCG2 Final Events Table",
529                 EFI_TCG2_FINAL_EVENTS_TABLE_GUID,
530         },
531 };
532
533 /**
534  * get_guid_text - get string of GUID
535  *
536  * Return description of GUID.
537  *
538  * @guid:       GUID
539  * Return:      description of GUID or NULL
540  */
541 static const char *get_guid_text(const void *guid)
542 {
543         int i;
544
545         for (i = 0; i < ARRAY_SIZE(guid_list); i++) {
546                 /*
547                  * As guidcmp uses memcmp() we can safely accept unaligned
548                  * GUIDs.
549                  */
550                 if (!guidcmp(&guid_list[i].guid, guid))
551                         return guid_list[i].text;
552         }
553
554         return NULL;
555 }
556
557 /**
558  * do_efi_show_handles() - show UEFI handles
559  *
560  * @cmdtp:      Command table
561  * @flag:       Command flag
562  * @argc:       Number of arguments
563  * @argv:       Argument array
564  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
565  *
566  * Implement efidebug "dh" sub-command.
567  * Show all UEFI handles and their information, currently all protocols
568  * added to handle.
569  */
570 static int do_efi_show_handles(struct cmd_tbl *cmdtp, int flag,
571                                int argc, char *const argv[])
572 {
573         efi_handle_t *handles;
574         efi_guid_t **guid;
575         efi_uintn_t num, count, i, j;
576         const char *guid_text;
577         efi_status_t ret;
578
579         ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
580                                                 &num, &handles));
581         if (ret != EFI_SUCCESS)
582                 return CMD_RET_FAILURE;
583
584         if (!num)
585                 return CMD_RET_SUCCESS;
586
587         printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
588         printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
589         for (i = 0; i < num; i++) {
590                 printf("%p", handles[i]);
591                 ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
592                                                         &count));
593                 if (ret || !count) {
594                         putc('\n');
595                         continue;
596                 }
597
598                 for (j = 0; j < count; j++) {
599                         if (j)
600                                 printf(", ");
601                         else
602                                 putc(' ');
603
604                         guid_text = get_guid_text(guid[j]);
605                         if (guid_text)
606                                 puts(guid_text);
607                         else
608                                 printf("%pUl", guid[j]);
609                 }
610                 putc('\n');
611         }
612
613         efi_free_pool(handles);
614
615         return CMD_RET_SUCCESS;
616 }
617
618 /**
619  * do_efi_show_images() - show UEFI images
620  *
621  * @cmdtp:      Command table
622  * @flag:       Command flag
623  * @argc:       Number of arguments
624  * @argv:       Argument array
625  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
626  *
627  * Implement efidebug "images" sub-command.
628  * Show all UEFI loaded images and their information.
629  */
630 static int do_efi_show_images(struct cmd_tbl *cmdtp, int flag,
631                               int argc, char *const argv[])
632 {
633         efi_print_image_infos(NULL);
634
635         return CMD_RET_SUCCESS;
636 }
637
638 static const char * const efi_mem_type_string[] = {
639         [EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
640         [EFI_LOADER_CODE] = "LOADER CODE",
641         [EFI_LOADER_DATA] = "LOADER DATA",
642         [EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
643         [EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
644         [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
645         [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
646         [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
647         [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
648         [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
649         [EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
650         [EFI_MMAP_IO] = "IO",
651         [EFI_MMAP_IO_PORT] = "IO PORT",
652         [EFI_PAL_CODE] = "PAL",
653         [EFI_PERSISTENT_MEMORY_TYPE] = "PERSISTENT",
654 };
655
656 static const struct efi_mem_attrs {
657         const u64 bit;
658         const char *text;
659 } efi_mem_attrs[] = {
660         {EFI_MEMORY_UC, "UC"},
661         {EFI_MEMORY_UC, "UC"},
662         {EFI_MEMORY_WC, "WC"},
663         {EFI_MEMORY_WT, "WT"},
664         {EFI_MEMORY_WB, "WB"},
665         {EFI_MEMORY_UCE, "UCE"},
666         {EFI_MEMORY_WP, "WP"},
667         {EFI_MEMORY_RP, "RP"},
668         {EFI_MEMORY_XP, "WP"},
669         {EFI_MEMORY_NV, "NV"},
670         {EFI_MEMORY_MORE_RELIABLE, "REL"},
671         {EFI_MEMORY_RO, "RO"},
672         {EFI_MEMORY_SP, "SP"},
673         {EFI_MEMORY_RUNTIME, "RT"},
674 };
675
676 /**
677  * print_memory_attributes() - print memory map attributes
678  *
679  * @attributes: Attribute value
680  *
681  * Print memory map attributes
682  */
683 static void print_memory_attributes(u64 attributes)
684 {
685         int sep, i;
686
687         for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
688                 if (attributes & efi_mem_attrs[i].bit) {
689                         if (sep) {
690                                 putc('|');
691                         } else {
692                                 putc(' ');
693                                 sep = 1;
694                         }
695                         puts(efi_mem_attrs[i].text);
696                 }
697 }
698
699 #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
700
701 /**
702  * do_efi_show_memmap() - show UEFI memory map
703  *
704  * @cmdtp:      Command table
705  * @flag:       Command flag
706  * @argc:       Number of arguments
707  * @argv:       Argument array
708  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
709  *
710  * Implement efidebug "memmap" sub-command.
711  * Show UEFI memory map.
712  */
713 static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
714                               int argc, char *const argv[])
715 {
716         struct efi_mem_desc *memmap = NULL, *map;
717         efi_uintn_t map_size = 0;
718         const char *type;
719         int i;
720         efi_status_t ret;
721
722         ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
723         if (ret == EFI_BUFFER_TOO_SMALL) {
724                 map_size += sizeof(struct efi_mem_desc); /* for my own */
725                 ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
726                                         (void *)&memmap);
727                 if (ret != EFI_SUCCESS)
728                         return CMD_RET_FAILURE;
729                 ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
730         }
731         if (ret != EFI_SUCCESS) {
732                 efi_free_pool(memmap);
733                 return CMD_RET_FAILURE;
734         }
735
736         printf("Type             Start%.*s End%.*s Attributes\n",
737                EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
738         printf("================ %.*s %.*s ==========\n",
739                EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
740         /*
741          * Coverity check: dereferencing null pointer "map."
742          * This is a false positive as memmap will always be
743          * populated by allocate_pool() above.
744          */
745         for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
746                 if (map->type < ARRAY_SIZE(efi_mem_type_string))
747                         type = efi_mem_type_string[map->type];
748                 else
749                         type = "(unknown)";
750
751                 printf("%-16s %.*llx-%.*llx", type,
752                        EFI_PHYS_ADDR_WIDTH,
753                        (u64)map_to_sysmem((void *)(uintptr_t)
754                                           map->physical_start),
755                        EFI_PHYS_ADDR_WIDTH,
756                        (u64)map_to_sysmem((void *)(uintptr_t)
757                                           (map->physical_start +
758                                            map->num_pages * EFI_PAGE_SIZE)));
759
760                 print_memory_attributes(map->attribute);
761                 putc('\n');
762         }
763
764         efi_free_pool(memmap);
765
766         return CMD_RET_SUCCESS;
767 }
768
769 /**
770  * do_efi_show_tables() - show UEFI configuration tables
771  *
772  * @cmdtp:      Command table
773  * @flag:       Command flag
774  * @argc:       Number of arguments
775  * @argv:       Argument array
776  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
777  *
778  * Implement efidebug "tables" sub-command.
779  * Show UEFI configuration tables.
780  */
781 static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
782                               int argc, char *const argv[])
783 {
784         efi_uintn_t i;
785         const char *guid_str;
786
787         for (i = 0; i < systab.nr_tables; ++i) {
788                 guid_str = get_guid_text(&systab.tables[i].guid);
789                 if (!guid_str)
790                         guid_str = "";
791                 printf("%pUl %s\n", &systab.tables[i].guid, guid_str);
792         }
793
794         return CMD_RET_SUCCESS;
795 }
796
797 /**
798  * do_efi_boot_add() - set UEFI load option
799  *
800  * @cmdtp:      Command table
801  * @flag:       Command flag
802  * @argc:       Number of arguments
803  * @argv:       Argument array
804  * Return:      CMD_RET_SUCCESS on success,
805  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
806  *
807  * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
808  *
809  *     efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
810  */
811 static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
812                            int argc, char *const argv[])
813 {
814         int id;
815         char *endp;
816         char var_name[9];
817         u16 var_name16[9], *p;
818         efi_guid_t guid;
819         size_t label_len, label_len16;
820         u16 *label;
821         struct efi_device_path *device_path = NULL, *file_path = NULL;
822         struct efi_load_option lo;
823         void *data = NULL;
824         efi_uintn_t size;
825         efi_status_t ret;
826         int r = CMD_RET_SUCCESS;
827
828         if (argc < 6 || argc > 7)
829                 return CMD_RET_USAGE;
830
831         id = (int)simple_strtoul(argv[1], &endp, 16);
832         if (*endp != '\0' || id > 0xffff)
833                 return CMD_RET_USAGE;
834
835         sprintf(var_name, "Boot%04X", id);
836         p = var_name16;
837         utf8_utf16_strncpy(&p, var_name, 9);
838
839         guid = efi_global_variable_guid;
840
841         /* attributes */
842         lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
843
844         /* label */
845         label_len = strlen(argv[2]);
846         label_len16 = utf8_utf16_strnlen(argv[2], label_len);
847         label = malloc((label_len16 + 1) * sizeof(u16));
848         if (!label)
849                 return CMD_RET_FAILURE;
850         lo.label = label; /* label will be changed below */
851         utf8_utf16_strncpy(&label, argv[2], label_len);
852
853         /* file path */
854         ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
855                                &file_path);
856         if (ret != EFI_SUCCESS) {
857                 printf("Cannot create device path for \"%s %s\"\n",
858                        argv[3], argv[4]);
859                 r = CMD_RET_FAILURE;
860                 goto out;
861         }
862         lo.file_path = file_path;
863         lo.file_path_length = efi_dp_size(file_path)
864                                 + sizeof(struct efi_device_path); /* for END */
865
866         /* optional data */
867         if (argc == 6)
868                 lo.optional_data = NULL;
869         else
870                 lo.optional_data = (const u8 *)argv[6];
871
872         size = efi_serialize_load_option(&lo, (u8 **)&data);
873         if (!size) {
874                 r = CMD_RET_FAILURE;
875                 goto out;
876         }
877
878         ret = EFI_CALL(efi_set_variable(var_name16, &guid,
879                                         EFI_VARIABLE_NON_VOLATILE |
880                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
881                                         EFI_VARIABLE_RUNTIME_ACCESS,
882                                         size, data));
883         if (ret != EFI_SUCCESS) {
884                 printf("Cannot set %ls\n", var_name16);
885                 r = CMD_RET_FAILURE;
886         }
887 out:
888         free(data);
889         efi_free_pool(device_path);
890         efi_free_pool(file_path);
891         free(lo.label);
892
893         return r;
894 }
895
896 /**
897  * do_efi_boot_rm() - delete UEFI load options
898  *
899  * @cmdtp:      Command table
900  * @flag:       Command flag
901  * @argc:       Number of arguments
902  * @argv:       Argument array
903  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
904  *
905  * Implement efidebug "boot rm" sub-command.
906  * Delete UEFI load options.
907  *
908  *     efidebug boot rm <id> ...
909  */
910 static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
911                           int argc, char *const argv[])
912 {
913         efi_guid_t guid;
914         int id, i;
915         char *endp;
916         char var_name[9];
917         u16 var_name16[9], *p;
918         efi_status_t ret;
919
920         if (argc == 1)
921                 return CMD_RET_USAGE;
922
923         guid = efi_global_variable_guid;
924         for (i = 1; i < argc; i++, argv++) {
925                 id = (int)simple_strtoul(argv[1], &endp, 16);
926                 if (*endp != '\0' || id > 0xffff)
927                         return CMD_RET_FAILURE;
928
929                 sprintf(var_name, "Boot%04X", id);
930                 p = var_name16;
931                 utf8_utf16_strncpy(&p, var_name, 9);
932
933                 ret = EFI_CALL(efi_set_variable(var_name16, &guid, 0, 0, NULL));
934                 if (ret) {
935                         printf("Cannot remove %ls\n", var_name16);
936                         return CMD_RET_FAILURE;
937                 }
938         }
939
940         return CMD_RET_SUCCESS;
941 }
942
943 /**
944  * show_efi_boot_opt_data() - dump UEFI load option
945  *
946  * @varname16:  variable name
947  * @data:       value of UEFI load option variable
948  * @size:       size of the boot option
949  *
950  * Decode the value of UEFI load option variable and print information.
951  */
952 static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
953 {
954         struct efi_load_option lo;
955         char *label, *p;
956         size_t label_len16, label_len;
957         u16 *dp_str;
958         efi_status_t ret;
959
960         ret = efi_deserialize_load_option(&lo, data, size);
961         if (ret != EFI_SUCCESS) {
962                 printf("%ls: invalid load option\n", varname16);
963                 return;
964         }
965
966         label_len16 = u16_strlen(lo.label);
967         label_len = utf16_utf8_strnlen(lo.label, label_len16);
968         label = malloc(label_len + 1);
969         if (!label)
970                 return;
971         p = label;
972         utf16_utf8_strncpy(&p, lo.label, label_len16);
973
974         printf("%ls:\nattributes: %c%c%c (0x%08x)\n",
975                varname16,
976                /* ACTIVE */
977                lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
978                /* FORCE RECONNECT */
979                lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
980                /* HIDDEN */
981                lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
982                lo.attributes);
983         printf("  label: %s\n", label);
984
985         dp_str = efi_dp_str(lo.file_path);
986         printf("  file_path: %ls\n", dp_str);
987         efi_free_pool(dp_str);
988
989         printf("  data:\n");
990         print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
991                        lo.optional_data, *size, true);
992         free(label);
993 }
994
995 /**
996  * show_efi_boot_opt() - dump UEFI load option
997  *
998  * @varname16:  variable name
999  *
1000  * Dump information defined by UEFI load option.
1001  */
1002 static void show_efi_boot_opt(u16 *varname16)
1003 {
1004         void *data;
1005         efi_uintn_t size;
1006         efi_status_t ret;
1007
1008         size = 0;
1009         ret = EFI_CALL(efi_get_variable(varname16, &efi_global_variable_guid,
1010                                         NULL, &size, NULL));
1011         if (ret == EFI_BUFFER_TOO_SMALL) {
1012                 data = malloc(size);
1013                 if (!data) {
1014                         printf("ERROR: Out of memory\n");
1015                         return;
1016                 }
1017                 ret = EFI_CALL(efi_get_variable(varname16,
1018                                                 &efi_global_variable_guid,
1019                                                 NULL, &size, data));
1020                 if (ret == EFI_SUCCESS)
1021                         show_efi_boot_opt_data(varname16, data, &size);
1022                 free(data);
1023         }
1024 }
1025
1026 static int u16_tohex(u16 c)
1027 {
1028         if (c >= '0' && c <= '9')
1029                 return c - '0';
1030         if (c >= 'A' && c <= 'F')
1031                 return c - 'A' + 10;
1032
1033         /* not hexadecimal */
1034         return -1;
1035 }
1036
1037 /**
1038  * show_efi_boot_dump() - dump all UEFI load options
1039  *
1040  * @cmdtp:      Command table
1041  * @flag:       Command flag
1042  * @argc:       Number of arguments
1043  * @argv:       Argument array
1044  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1045  *
1046  * Implement efidebug "boot dump" sub-command.
1047  * Dump information of all UEFI load options defined.
1048  *
1049  *     efidebug boot dump
1050  */
1051 static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
1052                             int argc, char *const argv[])
1053 {
1054         u16 *var_name16, *p;
1055         efi_uintn_t buf_size, size;
1056         efi_guid_t guid;
1057         int id, i, digit;
1058         efi_status_t ret;
1059
1060         if (argc > 1)
1061                 return CMD_RET_USAGE;
1062
1063         buf_size = 128;
1064         var_name16 = malloc(buf_size);
1065         if (!var_name16)
1066                 return CMD_RET_FAILURE;
1067
1068         var_name16[0] = 0;
1069         for (;;) {
1070                 size = buf_size;
1071                 ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
1072                                                           &guid));
1073                 if (ret == EFI_NOT_FOUND)
1074                         break;
1075                 if (ret == EFI_BUFFER_TOO_SMALL) {
1076                         buf_size = size;
1077                         p = realloc(var_name16, buf_size);
1078                         if (!p) {
1079                                 free(var_name16);
1080                                 return CMD_RET_FAILURE;
1081                         }
1082                         var_name16 = p;
1083                         ret = EFI_CALL(efi_get_next_variable_name(&size,
1084                                                                   var_name16,
1085                                                                   &guid));
1086                 }
1087                 if (ret != EFI_SUCCESS) {
1088                         free(var_name16);
1089                         return CMD_RET_FAILURE;
1090                 }
1091
1092                 if (memcmp(var_name16, L"Boot", 8))
1093                         continue;
1094
1095                 for (id = 0, i = 0; i < 4; i++) {
1096                         digit = u16_tohex(var_name16[4 + i]);
1097                         if (digit < 0)
1098                                 break;
1099                         id = (id << 4) + digit;
1100                 }
1101                 if (i == 4 && !var_name16[8])
1102                         show_efi_boot_opt(var_name16);
1103         }
1104
1105         free(var_name16);
1106
1107         return CMD_RET_SUCCESS;
1108 }
1109
1110 /**
1111  * show_efi_boot_order() - show order of UEFI load options
1112  *
1113  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1114  *
1115  * Show order of UEFI load options defined by BootOrder variable.
1116  */
1117 static int show_efi_boot_order(void)
1118 {
1119         u16 *bootorder;
1120         efi_uintn_t size;
1121         int num, i;
1122         char var_name[9];
1123         u16 var_name16[9], *p16;
1124         void *data;
1125         struct efi_load_option lo;
1126         char *label, *p;
1127         size_t label_len16, label_len;
1128         efi_status_t ret;
1129
1130         size = 0;
1131         ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
1132                                         NULL, &size, NULL));
1133         if (ret != EFI_BUFFER_TOO_SMALL) {
1134                 if (ret == EFI_NOT_FOUND) {
1135                         printf("BootOrder not defined\n");
1136                         return CMD_RET_SUCCESS;
1137                 } else {
1138                         return CMD_RET_FAILURE;
1139                 }
1140         }
1141         bootorder = malloc(size);
1142         if (!bootorder) {
1143                 printf("ERROR: Out of memory\n");
1144                 return CMD_RET_FAILURE;
1145         }
1146         ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
1147                                         NULL, &size, bootorder));
1148         if (ret != EFI_SUCCESS) {
1149                 ret = CMD_RET_FAILURE;
1150                 goto out;
1151         }
1152
1153         num = size / sizeof(u16);
1154         for (i = 0; i < num; i++) {
1155                 sprintf(var_name, "Boot%04X", bootorder[i]);
1156                 p16 = var_name16;
1157                 utf8_utf16_strncpy(&p16, var_name, 9);
1158
1159                 size = 0;
1160                 ret = EFI_CALL(efi_get_variable(var_name16,
1161                                                 &efi_global_variable_guid, NULL,
1162                                                 &size, NULL));
1163                 if (ret != EFI_BUFFER_TOO_SMALL) {
1164                         printf("%2d: %s: (not defined)\n", i + 1, var_name);
1165                         continue;
1166                 }
1167
1168                 data = malloc(size);
1169                 if (!data) {
1170                         ret = CMD_RET_FAILURE;
1171                         goto out;
1172                 }
1173                 ret = EFI_CALL(efi_get_variable(var_name16,
1174                                                 &efi_global_variable_guid, NULL,
1175                                                 &size, data));
1176                 if (ret != EFI_SUCCESS) {
1177                         free(data);
1178                         ret = CMD_RET_FAILURE;
1179                         goto out;
1180                 }
1181
1182                 ret = efi_deserialize_load_option(&lo, data, &size);
1183                 if (ret != EFI_SUCCESS) {
1184                         printf("%ls: invalid load option\n", var_name16);
1185                         ret = CMD_RET_FAILURE;
1186                         goto out;
1187                 }
1188
1189                 label_len16 = u16_strlen(lo.label);
1190                 label_len = utf16_utf8_strnlen(lo.label, label_len16);
1191                 label = malloc(label_len + 1);
1192                 if (!label) {
1193                         free(data);
1194                         ret = CMD_RET_FAILURE;
1195                         goto out;
1196                 }
1197                 p = label;
1198                 utf16_utf8_strncpy(&p, lo.label, label_len16);
1199                 printf("%2d: %s: %s\n", i + 1, var_name, label);
1200                 free(label);
1201
1202                 free(data);
1203         }
1204 out:
1205         free(bootorder);
1206
1207         return ret;
1208 }
1209
1210 /**
1211  * do_efi_boot_next() - manage UEFI BootNext variable
1212  *
1213  * @cmdtp:      Command table
1214  * @flag:       Command flag
1215  * @argc:       Number of arguments
1216  * @argv:       Argument array
1217  * Return:      CMD_RET_SUCCESS on success,
1218  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1219  *
1220  * Implement efidebug "boot next" sub-command.
1221  * Set BootNext variable.
1222  *
1223  *     efidebug boot next <id>
1224  */
1225 static int do_efi_boot_next(struct cmd_tbl *cmdtp, int flag,
1226                             int argc, char *const argv[])
1227 {
1228         u16 bootnext;
1229         efi_uintn_t size;
1230         char *endp;
1231         efi_guid_t guid;
1232         efi_status_t ret;
1233         int r = CMD_RET_SUCCESS;
1234
1235         if (argc != 2)
1236                 return CMD_RET_USAGE;
1237
1238         bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
1239         if (*endp) {
1240                 printf("invalid value: %s\n", argv[1]);
1241                 r = CMD_RET_FAILURE;
1242                 goto out;
1243         }
1244
1245         guid = efi_global_variable_guid;
1246         size = sizeof(u16);
1247         ret = EFI_CALL(efi_set_variable(L"BootNext", &guid,
1248                                         EFI_VARIABLE_NON_VOLATILE |
1249                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
1250                                         EFI_VARIABLE_RUNTIME_ACCESS,
1251                                         size, &bootnext));
1252         if (ret != EFI_SUCCESS) {
1253                 printf("Cannot set BootNext\n");
1254                 r = CMD_RET_FAILURE;
1255         }
1256 out:
1257         return r;
1258 }
1259
1260 /**
1261  * do_efi_boot_order() - manage UEFI BootOrder variable
1262  *
1263  * @cmdtp:      Command table
1264  * @flag:       Command flag
1265  * @argc:       Number of arguments
1266  * @argv:       Argument array
1267  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1268  *
1269  * Implement efidebug "boot order" sub-command.
1270  * Show order of UEFI load options, or change it in BootOrder variable.
1271  *
1272  *     efidebug boot order [<id> ...]
1273  */
1274 static int do_efi_boot_order(struct cmd_tbl *cmdtp, int flag,
1275                              int argc, char *const argv[])
1276 {
1277         u16 *bootorder = NULL;
1278         efi_uintn_t size;
1279         int id, i;
1280         char *endp;
1281         efi_guid_t guid;
1282         efi_status_t ret;
1283         int r = CMD_RET_SUCCESS;
1284
1285         if (argc == 1)
1286                 return show_efi_boot_order();
1287
1288         argc--;
1289         argv++;
1290
1291         size = argc * sizeof(u16);
1292         bootorder = malloc(size);
1293         if (!bootorder)
1294                 return CMD_RET_FAILURE;
1295
1296         for (i = 0; i < argc; i++) {
1297                 id = (int)simple_strtoul(argv[i], &endp, 16);
1298                 if (*endp != '\0' || id > 0xffff) {
1299                         printf("invalid value: %s\n", argv[i]);
1300                         r = CMD_RET_FAILURE;
1301                         goto out;
1302                 }
1303
1304                 bootorder[i] = (u16)id;
1305         }
1306
1307         guid = efi_global_variable_guid;
1308         ret = EFI_CALL(efi_set_variable(L"BootOrder", &guid,
1309                                         EFI_VARIABLE_NON_VOLATILE |
1310                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
1311                                         EFI_VARIABLE_RUNTIME_ACCESS,
1312                                         size, bootorder));
1313         if (ret != EFI_SUCCESS) {
1314                 printf("Cannot set BootOrder\n");
1315                 r = CMD_RET_FAILURE;
1316         }
1317 out:
1318         free(bootorder);
1319
1320         return r;
1321 }
1322
1323 static struct cmd_tbl cmd_efidebug_boot_sub[] = {
1324         U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
1325         U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
1326         U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
1327         U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
1328         U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
1329                          "", ""),
1330 };
1331
1332 /**
1333  * do_efi_boot_opt() - manage UEFI load options
1334  *
1335  * @cmdtp:      Command table
1336  * @flag:       Command flag
1337  * @argc:       Number of arguments
1338  * @argv:       Argument array
1339  * Return:      CMD_RET_SUCCESS on success,
1340  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1341  *
1342  * Implement efidebug "boot" sub-command.
1343  */
1344 static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
1345                            int argc, char *const argv[])
1346 {
1347         struct cmd_tbl *cp;
1348
1349         if (argc < 2)
1350                 return CMD_RET_USAGE;
1351
1352         argc--; argv++;
1353
1354         cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
1355                           ARRAY_SIZE(cmd_efidebug_boot_sub));
1356         if (!cp)
1357                 return CMD_RET_USAGE;
1358
1359         return cp->cmd(cmdtp, flag, argc, argv);
1360 }
1361
1362 /**
1363  * do_efi_test_bootmgr() - run simple bootmgr for test
1364  *
1365  * @cmdtp:      Command table
1366  * @flag:       Command flag
1367  * @argc:       Number of arguments
1368  * @argv:       Argument array
1369  * Return:      CMD_RET_SUCCESS on success,
1370  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1371  *
1372  * Implement efidebug "test bootmgr" sub-command.
1373  * Run simple bootmgr for test.
1374  *
1375  *     efidebug test bootmgr
1376  */
1377 static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
1378                                               int argc, char * const argv[])
1379 {
1380         efi_handle_t image;
1381         efi_uintn_t exit_data_size = 0;
1382         u16 *exit_data = NULL;
1383         efi_status_t ret;
1384         void *load_options = NULL;
1385
1386         ret = efi_bootmgr_load(&image, &load_options);
1387         printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1388
1389         /* We call efi_start_image() even if error for test purpose. */
1390         ret = EFI_CALL(efi_start_image(image, &exit_data_size, &exit_data));
1391         printf("efi_start_image() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1392         if (ret && exit_data)
1393                 efi_free_pool(exit_data);
1394
1395         efi_restore_gd();
1396
1397         free(load_options);
1398         return CMD_RET_SUCCESS;
1399 }
1400
1401 static struct cmd_tbl cmd_efidebug_test_sub[] = {
1402 #ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
1403         U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
1404                          "", ""),
1405 #endif
1406 };
1407
1408 /**
1409  * do_efi_test() - manage UEFI load options
1410  *
1411  * @cmdtp:      Command table
1412  * @flag:       Command flag
1413  * @argc:       Number of arguments
1414  * @argv:       Argument array
1415  * Return:      CMD_RET_SUCCESS on success,
1416  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1417  *
1418  * Implement efidebug "test" sub-command.
1419  */
1420 static int do_efi_test(struct cmd_tbl *cmdtp, int flag,
1421                        int argc, char * const argv[])
1422 {
1423         struct cmd_tbl *cp;
1424
1425         if (argc < 2)
1426                 return CMD_RET_USAGE;
1427
1428         argc--; argv++;
1429
1430         cp = find_cmd_tbl(argv[0], cmd_efidebug_test_sub,
1431                           ARRAY_SIZE(cmd_efidebug_test_sub));
1432         if (!cp)
1433                 return CMD_RET_USAGE;
1434
1435         return cp->cmd(cmdtp, flag, argc, argv);
1436 }
1437
1438 /**
1439  * do_efi_query_info() - QueryVariableInfo EFI service
1440  *
1441  * @cmdtp:      Command table
1442  * @flag:       Command flag
1443  * @argc:       Number of arguments
1444  * @argv:       Argument array
1445  * Return:      CMD_RET_SUCCESS on success,
1446  *              CMD_RET_USAGE or CMD_RET_FAILURE on failure
1447  *
1448  * Implement efidebug "test" sub-command.
1449  */
1450
1451 static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
1452                              int argc, char * const argv[])
1453 {
1454         efi_status_t ret;
1455         u32 attr = 0;
1456         u64 max_variable_storage_size;
1457         u64 remain_variable_storage_size;
1458         u64 max_variable_size;
1459         int i;
1460
1461         for (i = 1; i < argc; i++) {
1462                 if (!strcmp(argv[i], "-bs"))
1463                         attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
1464                 else if (!strcmp(argv[i], "-rt"))
1465                         attr |= EFI_VARIABLE_RUNTIME_ACCESS;
1466                 else if (!strcmp(argv[i], "-nv"))
1467                         attr |= EFI_VARIABLE_NON_VOLATILE;
1468                 else if (!strcmp(argv[i], "-at"))
1469                         attr |=
1470                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1471         }
1472
1473         ret = EFI_CALL(efi_query_variable_info(attr,
1474                                                &max_variable_storage_size,
1475                                                &remain_variable_storage_size,
1476                                                &max_variable_size));
1477         if (ret != EFI_SUCCESS) {
1478                 printf("Error: Cannot query UEFI variables, r = %lu\n",
1479                        ret & ~EFI_ERROR_MASK);
1480                 return CMD_RET_FAILURE;
1481         }
1482
1483         printf("Max storage size %llu\n", max_variable_storage_size);
1484         printf("Remaining storage size %llu\n", remain_variable_storage_size);
1485         printf("Max variable size %llu\n", max_variable_size);
1486
1487         return CMD_RET_SUCCESS;
1488 }
1489
1490 static struct cmd_tbl cmd_efidebug_sub[] = {
1491         U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
1492 #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1493         U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule,
1494                          "", ""),
1495 #endif
1496         U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
1497                          "", ""),
1498         U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
1499                          "", ""),
1500         U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
1501                          "", ""),
1502         U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
1503                          "", ""),
1504         U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
1505                          "", ""),
1506         U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
1507                          "", ""),
1508         U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
1509                          "", ""),
1510         U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
1511                          "", ""),
1512 };
1513
1514 /**
1515  * do_efidebug() - display and configure UEFI environment
1516  *
1517  * @cmdtp:      Command table
1518  * @flag:       Command flag
1519  * @argc:       Number of arguments
1520  * @argv:       Argument array
1521  * Return:      CMD_RET_SUCCESS on success,
1522  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1523  *
1524  * Implement efidebug command which allows us to display and
1525  * configure UEFI environment.
1526  */
1527 static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
1528                        int argc, char *const argv[])
1529 {
1530         struct cmd_tbl *cp;
1531         efi_status_t r;
1532
1533         if (argc < 2)
1534                 return CMD_RET_USAGE;
1535
1536         argc--; argv++;
1537
1538         /* Initialize UEFI drivers */
1539         r = efi_init_obj_list();
1540         if (r != EFI_SUCCESS) {
1541                 printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
1542                        r & ~EFI_ERROR_MASK);
1543                 return CMD_RET_FAILURE;
1544         }
1545
1546         cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
1547                           ARRAY_SIZE(cmd_efidebug_sub));
1548         if (!cp)
1549                 return CMD_RET_USAGE;
1550
1551         return cp->cmd(cmdtp, flag, argc, argv);
1552 }
1553
1554 #ifdef CONFIG_SYS_LONGHELP
1555 static char efidebug_help_text[] =
1556         "  - UEFI Shell-like interface to configure UEFI environment\n"
1557         "\n"
1558         "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
1559         "  - set UEFI BootXXXX variable\n"
1560         "    <load options> will be passed to UEFI application\n"
1561         "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
1562         "  - delete UEFI BootXXXX variables\n"
1563         "efidebug boot dump\n"
1564         "  - dump all UEFI BootXXXX variables\n"
1565         "efidebug boot next <bootid>\n"
1566         "  - set UEFI BootNext variable\n"
1567         "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
1568         "  - set/show UEFI boot order\n"
1569         "\n"
1570 #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1571         "efidebug capsule update [-v] <capsule address>\n"
1572         "  - process a capsule\n"
1573         "efidebug capsule disk-update\n"
1574         "  - update a capsule from disk\n"
1575         "efidebug capsule show <capsule address>\n"
1576         "  - show capsule information\n"
1577         "efidebug capsule result [<capsule result var>]\n"
1578         "  - show a capsule update result\n"
1579         "\n"
1580 #endif
1581         "efidebug devices\n"
1582         "  - show UEFI devices\n"
1583         "efidebug drivers\n"
1584         "  - show UEFI drivers\n"
1585         "efidebug dh\n"
1586         "  - show UEFI handles\n"
1587         "efidebug images\n"
1588         "  - show loaded images\n"
1589         "efidebug memmap\n"
1590         "  - show UEFI memory map\n"
1591         "efidebug tables\n"
1592         "  - show UEFI configuration tables\n"
1593 #ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
1594         "efidebug test bootmgr\n"
1595         "  - run simple bootmgr for test\n"
1596 #endif
1597         "efidebug query [-nv][-bs][-rt][-at]\n"
1598         "  - show size of UEFI variables store\n";
1599 #endif
1600
1601 U_BOOT_CMD(
1602         efidebug, 10, 0, do_efidebug,
1603         "Configure UEFI environment",
1604         efidebug_help_text
1605 );