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