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