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