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