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