]> Git Repo - J-u-boot.git/blob - cmd/efidebug.c
Merge patch series "spi: Various Kconfig fixes"
[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  * enum efi_lo_dp_part - part of device path in load option
657  */
658 enum efi_lo_dp_part {
659         /** @EFI_LO_DP_PART_BINARY: binary */
660         EFI_LO_DP_PART_BINARY,
661         /** @EFI_LO_DP_PART_INITRD: initial RAM disk */
662         EFI_LO_DP_PART_INITRD,
663         /** @EFI_LP_DP_PART_FDT: device-tree */
664         EFI_LP_DP_PART_FDT,
665 };
666
667 /**
668  * create_lo_dp_part() - create a special device path for our Boot### option
669  *
670  * @dev:        device
671  * @part:       disk partition
672  * @file:       filename
673  * @shortform:  create short form device path
674  * @type:       part of device path to be created
675  * Return:      pointer to the device path or ERR_PTR
676  */
677 static
678 struct efi_device_path *create_lo_dp_part(const char *dev, const char *part,
679                                           const char *file, bool shortform,
680                                           enum efi_lo_dp_part type)
681
682 {
683         struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL, *short_fp = NULL;
684         struct efi_device_path *dp = NULL;
685         const struct efi_device_path *dp_prefix;
686         efi_status_t ret;
687         const struct efi_lo_dp_prefix fdt_dp = {
688                 .vendor = {
689                         {
690                         DEVICE_PATH_TYPE_MEDIA_DEVICE,
691                         DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
692                         sizeof(fdt_dp.vendor),
693                         },
694                         EFI_FDT_GUID,
695                 },
696                 .end = {
697                         DEVICE_PATH_TYPE_END,
698                         DEVICE_PATH_SUB_TYPE_END,
699                         sizeof(fdt_dp.end),
700                 }
701         };
702         const struct efi_lo_dp_prefix initrd_dp = {
703                 .vendor = {
704                         {
705                         DEVICE_PATH_TYPE_MEDIA_DEVICE,
706                         DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
707                         sizeof(initrd_dp.vendor),
708                         },
709                         EFI_INITRD_MEDIA_GUID,
710                 },
711                 .end = {
712                         DEVICE_PATH_TYPE_END,
713                         DEVICE_PATH_SUB_TYPE_END,
714                         sizeof(initrd_dp.end),
715                 }
716         };
717
718         switch (type) {
719         case EFI_LO_DP_PART_INITRD:
720                 dp_prefix = &initrd_dp.vendor.dp;
721                 break;
722         case EFI_LP_DP_PART_FDT:
723                 dp_prefix = &fdt_dp.vendor.dp;
724                 break;
725         default:
726                 dp_prefix = NULL;
727                 break;
728         }
729
730         ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp);
731         if (ret != EFI_SUCCESS) {
732                 printf("Cannot create device path for \"%s %s\"\n", part, file);
733                 goto out;
734         }
735         if (shortform)
736                 short_fp = efi_dp_shorten(tmp_fp);
737         if (!short_fp)
738                 short_fp = tmp_fp;
739
740         dp = efi_dp_concat(dp_prefix, short_fp, 0);
741
742 out:
743         efi_free_pool(tmp_dp);
744         efi_free_pool(tmp_fp);
745         return dp;
746 }
747
748 /**
749  * efi_boot_add_uri() - set URI load option
750  *
751  * @argc:               Number of arguments
752  * @argv:               Argument array
753  * @var_name16:         variable name buffer
754  * @var_name16_size:    variable name buffer size
755  * @lo:                 pointer to the load option
756  * @file_path:          buffer to set the generated device path pointer
757  * @fp_size:            file_path size
758  * Return:              CMD_RET_SUCCESS on success,
759  *                      CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
760  */
761 static int efi_boot_add_uri(int argc, char *const argv[], u16 *var_name16,
762                             size_t var_name16_size, struct efi_load_option *lo,
763                             struct efi_device_path **file_path,
764                             efi_uintn_t *fp_size)
765 {
766         int id;
767         char *pos;
768         char *endp;
769         u16 *label;
770         efi_uintn_t uridp_len;
771         struct efi_device_path_uri *uridp;
772
773         if (argc < 3 || lo->label)
774                 return CMD_RET_USAGE;
775
776         id = (int)hextoul(argv[1], &endp);
777         if (*endp != '\0' || id > 0xffff)
778                 return CMD_RET_USAGE;
779
780         label = efi_convert_string(argv[2]);
781         if (!label)
782                 return CMD_RET_FAILURE;
783
784         if (!wget_validate_uri(argv[3])) {
785                 printf("ERROR: invalid URI\n");
786                 return CMD_RET_FAILURE;
787         }
788
789         efi_create_indexed_name(var_name16, var_name16_size, "Boot", id);
790         lo->label = label;
791
792         uridp_len = sizeof(struct efi_device_path) + strlen(argv[3]) + 1;
793         uridp = efi_alloc(uridp_len + sizeof(END));
794         if (!uridp) {
795                 log_err("Out of memory\n");
796                 return CMD_RET_FAILURE;
797         }
798         uridp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
799         uridp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_URI;
800         uridp->dp.length = uridp_len;
801         strcpy(uridp->uri, argv[3]);
802         pos = (char *)uridp + uridp_len;
803         memcpy(pos, &END, sizeof(END));
804
805         *file_path = &uridp->dp;
806         *fp_size += uridp_len + sizeof(END);
807
808         return CMD_RET_SUCCESS;
809 }
810
811 /**
812  * do_efi_boot_add() - set UEFI load option
813  *
814  * @cmdtp:      Command table
815  * @flag:       Command flag
816  * @argc:       Number of arguments
817  * @argv:       Argument array
818  * Return:      CMD_RET_SUCCESS on success,
819  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
820  *
821  * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
822  *
823  * efidebug boot add -b <id> <label> <interface> <devnum>[:<part>] <file>
824  *                   -i <file> <interface2> <devnum2>[:<part>] <initrd>
825  *                   -s '<options>'
826  */
827 static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
828                            int argc, char *const argv[])
829 {
830         int id;
831         char *endp;
832         u16 var_name16[9];
833         efi_guid_t guid;
834         u16 *label;
835         struct efi_device_path *file_path = NULL;
836         struct efi_device_path *initrd_dp = NULL;
837         struct efi_device_path *fdt_dp = NULL;
838         struct efi_load_option lo;
839         void *data = NULL;
840         efi_uintn_t size;
841         efi_uintn_t fp_size = 0;
842         efi_status_t ret;
843         int r = CMD_RET_SUCCESS;
844
845         guid = efi_global_variable_guid;
846
847         /* attributes */
848         lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
849         lo.optional_data = NULL;
850         lo.label = NULL;
851
852         argc--;
853         argv++; /* 'add' */
854         for (; argc > 0; argc--, argv++) {
855                 int shortform;
856
857                 if (*argv[0] != '-' || strlen(argv[0]) != 2) {
858                                 r = CMD_RET_USAGE;
859                                 goto out;
860                 }
861                 shortform = 0;
862                 switch (argv[0][1]) {
863                 case 'b':
864                         shortform = 1;
865                         /* fallthrough */
866                 case 'B':
867                         if (argc <  5 || lo.label) {
868                                 r = CMD_RET_USAGE;
869                                 goto out;
870                         }
871                         id = (int)hextoul(argv[1], &endp);
872                         if (*endp != '\0' || id > 0xffff)
873                                 return CMD_RET_USAGE;
874
875                         efi_create_indexed_name(var_name16, sizeof(var_name16),
876                                                 "Boot", id);
877
878                         /* label */
879                         label = efi_convert_string(argv[2]);
880                         if (!label)
881                                 return CMD_RET_FAILURE;
882                         lo.label = label; /* label will be changed below */
883
884                         /* file path */
885                         file_path = create_lo_dp_part(argv[3], argv[4], argv[5],
886                                                       shortform,
887                                                       EFI_LO_DP_PART_BINARY);
888                         argc -= 5;
889                         argv += 5;
890                         break;
891                 case 'd':
892                         shortform = 1;
893                         fallthrough;
894                 case 'D':
895                         if (argc < 3 || fdt_dp) {
896                                 r = CMD_RET_USAGE;
897                                 goto out;
898                         }
899
900                         fdt_dp = create_lo_dp_part(argv[1], argv[2], argv[3],
901                                                    shortform,
902                                                    EFI_LP_DP_PART_FDT);
903                         if (!fdt_dp) {
904                                 printf("Cannot add a device-tree\n");
905                                 r = CMD_RET_FAILURE;
906                                 goto out;
907                         }
908                         argc -= 3;
909                         argv += 3;
910                         break;
911                 case 'i':
912                         shortform = 1;
913                         /* fallthrough */
914                 case 'I':
915                         if (argc < 3 || initrd_dp) {
916                                 r = CMD_RET_USAGE;
917                                 goto out;
918                         }
919
920                         initrd_dp = create_lo_dp_part(argv[1], argv[2], argv[3],
921                                                       shortform,
922                                                       EFI_LO_DP_PART_INITRD);
923                         if (!initrd_dp) {
924                                 printf("Cannot add an initrd\n");
925                                 r = CMD_RET_FAILURE;
926                                 goto out;
927                         }
928                         argc -= 3;
929                         argv += 3;
930                         break;
931                 case 's':
932                         if (argc < 1 || lo.optional_data) {
933                                 r = CMD_RET_USAGE;
934                                 goto out;
935                         }
936                         lo.optional_data = (const u8 *)argv[1];
937                         argc -= 1;
938                         argv += 1;
939                         break;
940                 case 'u':
941                         if (IS_ENABLED(CONFIG_EFI_HTTP_BOOT)) {
942                                 r = efi_boot_add_uri(argc, argv, var_name16,
943                                                      sizeof(var_name16), &lo,
944                                                      &file_path, &fp_size);
945                                 if (r != CMD_RET_SUCCESS)
946                                         goto out;
947                                 argc -= 3;
948                                 argv += 3;
949                         } else{
950                                 r = CMD_RET_USAGE;
951                                 goto out;
952                         }
953                         break;
954                 default:
955                         r = CMD_RET_USAGE;
956                         goto out;
957                 }
958         }
959
960         if (!file_path) {
961                 printf("Missing binary\n");
962                 r = CMD_RET_USAGE;
963                 goto out;
964         }
965
966         ret = efi_load_option_dp_join(&file_path, &fp_size, initrd_dp, fdt_dp);
967         if (ret != EFI_SUCCESS) {
968                 printf("Cannot create final device path\n");
969                 r = CMD_RET_FAILURE;
970                 goto out;
971         }
972
973         lo.file_path = file_path;
974         lo.file_path_length = fp_size;
975
976         size = efi_serialize_load_option(&lo, (u8 **)&data);
977         if (!size) {
978                 r = CMD_RET_FAILURE;
979                 goto out;
980         }
981
982         ret = efi_set_variable_int(var_name16, &guid,
983                                    EFI_VARIABLE_NON_VOLATILE |
984                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
985                                    EFI_VARIABLE_RUNTIME_ACCESS,
986                                    size, data, false);
987         if (ret != EFI_SUCCESS) {
988                 printf("Cannot set %ls\n", var_name16);
989                 r = CMD_RET_FAILURE;
990         }
991
992 out:
993         free(data);
994         efi_free_pool(initrd_dp);
995         efi_free_pool(fdt_dp);
996         efi_free_pool(file_path);
997         free(lo.label);
998
999         return r;
1000 }
1001
1002 /**
1003  * do_efi_boot_rm() - delete UEFI load options
1004  *
1005  * @cmdtp:      Command table
1006  * @flag:       Command flag
1007  * @argc:       Number of arguments
1008  * @argv:       Argument array
1009  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1010  *
1011  * Implement efidebug "boot rm" sub-command.
1012  * Delete UEFI load options.
1013  *
1014  *     efidebug boot rm <id> ...
1015  */
1016 static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
1017                           int argc, char *const argv[])
1018 {
1019         efi_guid_t guid;
1020         int id, i;
1021         char *endp;
1022         u16 var_name16[9];
1023         efi_status_t ret;
1024
1025         if (argc == 1)
1026                 return CMD_RET_USAGE;
1027
1028         guid = efi_global_variable_guid;
1029         for (i = 1; i < argc; i++, argv++) {
1030                 id = (int)hextoul(argv[1], &endp);
1031                 if (*endp != '\0' || id > 0xffff)
1032                         return CMD_RET_FAILURE;
1033
1034                 efi_create_indexed_name(var_name16, sizeof(var_name16),
1035                                         "Boot", id);
1036                 ret = efi_set_variable_int(var_name16, &guid, 0, 0, NULL,
1037                                            false);
1038                 if (ret) {
1039                         printf("Cannot remove %ls\n", var_name16);
1040                         return CMD_RET_FAILURE;
1041                 }
1042         }
1043
1044         return CMD_RET_SUCCESS;
1045 }
1046
1047 /**
1048  * show_efi_boot_opt_data() - dump UEFI load option
1049  *
1050  * @varname16:  variable name
1051  * @data:       value of UEFI load option variable
1052  * @size:       size of the boot option
1053  *
1054  * Decode the value of UEFI load option variable and print information.
1055  */
1056 static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
1057 {
1058         struct efi_device_path *fdt_path;
1059         struct efi_device_path *initrd_path;
1060         struct efi_load_option lo;
1061         efi_status_t ret;
1062
1063         ret = efi_deserialize_load_option(&lo, data, size);
1064         if (ret != EFI_SUCCESS) {
1065                 printf("%ls: invalid load option\n", varname16);
1066                 return;
1067         }
1068
1069         printf("%ls:\nattributes: %c%c%c (0x%08x)\n",
1070                varname16,
1071                /* ACTIVE */
1072                lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
1073                /* FORCE RECONNECT */
1074                lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
1075                /* HIDDEN */
1076                lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
1077                lo.attributes);
1078         printf("  label: %ls\n", lo.label);
1079
1080         printf("  file_path: %pD\n", lo.file_path);
1081
1082         initrd_path = efi_dp_from_lo(&lo, &efi_lf2_initrd_guid);
1083         if (initrd_path) {
1084                 printf("  initrd_path: %pD\n", initrd_path);
1085                 efi_free_pool(initrd_path);
1086         }
1087
1088         fdt_path = efi_dp_from_lo(&lo, &efi_guid_fdt);
1089         if (fdt_path) {
1090                 printf("  device-tree path: %pD\n", fdt_path);
1091                 efi_free_pool(fdt_path);
1092         }
1093
1094         printf("  data:\n");
1095         print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
1096                        lo.optional_data, *size, true);
1097 }
1098
1099 /**
1100  * show_efi_boot_opt() - dump UEFI load option
1101  *
1102  * @varname16:  variable name
1103  *
1104  * Dump information defined by UEFI load option.
1105  */
1106 static void show_efi_boot_opt(u16 *varname16)
1107 {
1108         void *data;
1109         efi_uintn_t size;
1110         efi_status_t ret;
1111
1112         size = 0;
1113         ret = efi_get_variable_int(varname16, &efi_global_variable_guid,
1114                                    NULL, &size, NULL, NULL);
1115         if (ret == EFI_BUFFER_TOO_SMALL) {
1116                 data = malloc(size);
1117                 if (!data) {
1118                         printf("ERROR: Out of memory\n");
1119                         return;
1120                 }
1121                 ret = efi_get_variable_int(varname16, &efi_global_variable_guid,
1122                                            NULL, &size, data, NULL);
1123                 if (ret == EFI_SUCCESS)
1124                         show_efi_boot_opt_data(varname16, data, &size);
1125                 free(data);
1126         }
1127 }
1128
1129 /**
1130  * do_efi_boot_dump() - dump all UEFI load options
1131  *
1132  * @cmdtp:      Command table
1133  * @flag:       Command flag
1134  * @argc:       Number of arguments
1135  * @argv:       Argument array
1136  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1137  *
1138  * Implement efidebug "boot dump" sub-command.
1139  * Dump information of all UEFI load options defined.
1140  *
1141  *     efidebug boot dump
1142  */
1143 static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
1144                             int argc, char *const argv[])
1145 {
1146         u16 *var_name16, *p;
1147         efi_uintn_t buf_size, size;
1148         efi_guid_t guid;
1149         efi_status_t ret;
1150
1151         if (argc > 1)
1152                 return CMD_RET_USAGE;
1153
1154         buf_size = 128;
1155         var_name16 = malloc(buf_size);
1156         if (!var_name16)
1157                 return CMD_RET_FAILURE;
1158
1159         var_name16[0] = 0;
1160         for (;;) {
1161                 size = buf_size;
1162                 ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
1163                 if (ret == EFI_NOT_FOUND)
1164                         break;
1165                 if (ret == EFI_BUFFER_TOO_SMALL) {
1166                         buf_size = size;
1167                         p = realloc(var_name16, buf_size);
1168                         if (!p) {
1169                                 free(var_name16);
1170                                 return CMD_RET_FAILURE;
1171                         }
1172                         var_name16 = p;
1173                         ret = efi_get_next_variable_name_int(&size, var_name16,
1174                                                              &guid);
1175                 }
1176                 if (ret != EFI_SUCCESS) {
1177                         free(var_name16);
1178                         return CMD_RET_FAILURE;
1179                 }
1180
1181                 if (efi_varname_is_load_option(var_name16, NULL))
1182                         show_efi_boot_opt(var_name16);
1183         }
1184
1185         free(var_name16);
1186
1187         return CMD_RET_SUCCESS;
1188 }
1189
1190 /**
1191  * show_efi_boot_order() - show order of UEFI load options
1192  *
1193  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1194  *
1195  * Show order of UEFI load options defined by BootOrder variable.
1196  */
1197 static int show_efi_boot_order(void)
1198 {
1199         u16 *bootorder;
1200         efi_uintn_t size;
1201         int num, i;
1202         u16 var_name16[9];
1203         void *data;
1204         struct efi_load_option lo;
1205         efi_status_t ret;
1206
1207         size = 0;
1208         ret = efi_get_variable_int(u"BootOrder", &efi_global_variable_guid,
1209                                    NULL, &size, NULL, NULL);
1210         if (ret != EFI_BUFFER_TOO_SMALL) {
1211                 if (ret == EFI_NOT_FOUND) {
1212                         printf("BootOrder not defined\n");
1213                         return CMD_RET_SUCCESS;
1214                 } else {
1215                         return CMD_RET_FAILURE;
1216                 }
1217         }
1218         bootorder = malloc(size);
1219         if (!bootorder) {
1220                 printf("ERROR: Out of memory\n");
1221                 return CMD_RET_FAILURE;
1222         }
1223         ret = efi_get_variable_int(u"BootOrder", &efi_global_variable_guid,
1224                                    NULL, &size, bootorder, NULL);
1225         if (ret != EFI_SUCCESS) {
1226                 ret = CMD_RET_FAILURE;
1227                 goto out;
1228         }
1229
1230         num = size / sizeof(u16);
1231         for (i = 0; i < num; i++) {
1232                 efi_create_indexed_name(var_name16, sizeof(var_name16),
1233                                         "Boot", bootorder[i]);
1234
1235                 size = 0;
1236                 ret = efi_get_variable_int(var_name16,
1237                                            &efi_global_variable_guid, NULL,
1238                                            &size, NULL, NULL);
1239                 if (ret != EFI_BUFFER_TOO_SMALL) {
1240                         printf("%2d: %ls: (not defined)\n", i + 1, var_name16);
1241                         continue;
1242                 }
1243
1244                 data = malloc(size);
1245                 if (!data) {
1246                         ret = CMD_RET_FAILURE;
1247                         goto out;
1248                 }
1249                 ret = efi_get_variable_int(var_name16,
1250                                            &efi_global_variable_guid, NULL,
1251                                            &size, data, NULL);
1252                 if (ret != EFI_SUCCESS) {
1253                         free(data);
1254                         ret = CMD_RET_FAILURE;
1255                         goto out;
1256                 }
1257
1258                 ret = efi_deserialize_load_option(&lo, data, &size);
1259                 if (ret != EFI_SUCCESS) {
1260                         printf("%ls: invalid load option\n", var_name16);
1261                         ret = CMD_RET_FAILURE;
1262                         goto out;
1263                 }
1264
1265                 printf("%2d: %ls: %ls\n", i + 1, var_name16, lo.label);
1266
1267                 free(data);
1268         }
1269 out:
1270         free(bootorder);
1271
1272         return ret;
1273 }
1274
1275 /**
1276  * do_efi_boot_next() - manage UEFI BootNext 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,
1283  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1284  *
1285  * Implement efidebug "boot next" sub-command.
1286  * Set BootNext variable.
1287  *
1288  *     efidebug boot next <id>
1289  */
1290 static int do_efi_boot_next(struct cmd_tbl *cmdtp, int flag,
1291                             int argc, char *const argv[])
1292 {
1293         u16 bootnext;
1294         efi_uintn_t size;
1295         char *endp;
1296         efi_guid_t guid;
1297         efi_status_t ret;
1298         int r = CMD_RET_SUCCESS;
1299
1300         if (argc != 2)
1301                 return CMD_RET_USAGE;
1302
1303         bootnext = (u16)hextoul(argv[1], &endp);
1304         if (*endp) {
1305                 printf("invalid value: %s\n", argv[1]);
1306                 r = CMD_RET_FAILURE;
1307                 goto out;
1308         }
1309
1310         guid = efi_global_variable_guid;
1311         size = sizeof(u16);
1312         ret = efi_set_variable_int(u"BootNext", &guid,
1313                                    EFI_VARIABLE_NON_VOLATILE |
1314                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
1315                                    EFI_VARIABLE_RUNTIME_ACCESS,
1316                                    size, &bootnext, false);
1317         if (ret != EFI_SUCCESS) {
1318                 printf("Cannot set BootNext\n");
1319                 r = CMD_RET_FAILURE;
1320         }
1321 out:
1322         return r;
1323 }
1324
1325 /**
1326  * do_efi_boot_order() - manage UEFI BootOrder variable
1327  *
1328  * @cmdtp:      Command table
1329  * @flag:       Command flag
1330  * @argc:       Number of arguments
1331  * @argv:       Argument array
1332  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1333  *
1334  * Implement efidebug "boot order" sub-command.
1335  * Show order of UEFI load options, or change it in BootOrder variable.
1336  *
1337  *     efidebug boot order [<id> ...]
1338  */
1339 static int do_efi_boot_order(struct cmd_tbl *cmdtp, int flag,
1340                              int argc, char *const argv[])
1341 {
1342         u16 *bootorder = NULL;
1343         efi_uintn_t size;
1344         int id, i;
1345         char *endp;
1346         efi_guid_t guid;
1347         efi_status_t ret;
1348         int r = CMD_RET_SUCCESS;
1349
1350         if (argc == 1)
1351                 return show_efi_boot_order();
1352
1353         argc--;
1354         argv++;
1355
1356         size = argc * sizeof(u16);
1357         bootorder = malloc(size);
1358         if (!bootorder)
1359                 return CMD_RET_FAILURE;
1360
1361         for (i = 0; i < argc; i++) {
1362                 id = (int)hextoul(argv[i], &endp);
1363                 if (*endp != '\0' || id > 0xffff) {
1364                         printf("invalid value: %s\n", argv[i]);
1365                         r = CMD_RET_FAILURE;
1366                         goto out;
1367                 }
1368
1369                 bootorder[i] = (u16)id;
1370         }
1371
1372         guid = efi_global_variable_guid;
1373         ret = efi_set_variable_int(u"BootOrder", &guid,
1374                                    EFI_VARIABLE_NON_VOLATILE |
1375                                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
1376                                    EFI_VARIABLE_RUNTIME_ACCESS,
1377                                    size, bootorder, true);
1378         if (ret != EFI_SUCCESS) {
1379                 printf("Cannot set BootOrder\n");
1380                 r = CMD_RET_FAILURE;
1381         }
1382 out:
1383         free(bootorder);
1384
1385         return r;
1386 }
1387
1388 static struct cmd_tbl cmd_efidebug_boot_sub[] = {
1389         U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
1390         U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
1391         U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
1392         U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
1393         U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
1394                          "", ""),
1395 };
1396
1397 /**
1398  * do_efi_boot_opt() - manage UEFI load options
1399  *
1400  * @cmdtp:      Command table
1401  * @flag:       Command flag
1402  * @argc:       Number of arguments
1403  * @argv:       Argument array
1404  * Return:      CMD_RET_SUCCESS on success,
1405  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1406  *
1407  * Implement efidebug "boot" sub-command.
1408  */
1409 static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
1410                            int argc, char *const argv[])
1411 {
1412         struct cmd_tbl *cp;
1413
1414         if (argc < 2)
1415                 return CMD_RET_USAGE;
1416
1417         argc--; argv++;
1418
1419         cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
1420                           ARRAY_SIZE(cmd_efidebug_boot_sub));
1421         if (!cp)
1422                 return CMD_RET_USAGE;
1423
1424         return cp->cmd(cmdtp, flag, argc, argv);
1425 }
1426
1427 /**
1428  * do_efi_test_bootmgr() - run simple bootmgr for test
1429  *
1430  * @cmdtp:      Command table
1431  * @flag:       Command flag
1432  * @argc:       Number of arguments
1433  * @argv:       Argument array
1434  * Return:      CMD_RET_SUCCESS on success,
1435  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1436  *
1437  * Implement efidebug "test bootmgr" sub-command.
1438  * Run simple bootmgr for test.
1439  *
1440  *     efidebug test bootmgr
1441  */
1442 static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
1443                                               int argc, char * const argv[])
1444 {
1445         efi_handle_t image;
1446         efi_uintn_t exit_data_size = 0;
1447         u16 *exit_data = NULL;
1448         efi_status_t ret;
1449         void *load_options = NULL;
1450
1451         ret = efi_bootmgr_load(&image, &load_options);
1452         printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1453         if (ret != EFI_SUCCESS)
1454                 return CMD_RET_SUCCESS;
1455
1456         /* We call efi_start_image() even if error for test purpose. */
1457         ret = EFI_CALL(efi_start_image(image, &exit_data_size, &exit_data));
1458         printf("efi_start_image() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1459         if (ret && exit_data)
1460                 efi_free_pool(exit_data);
1461
1462         free(load_options);
1463         return CMD_RET_SUCCESS;
1464 }
1465
1466 static struct cmd_tbl cmd_efidebug_test_sub[] = {
1467 #ifdef CONFIG_EFI_BOOTMGR
1468         U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
1469                          "", ""),
1470 #endif
1471 };
1472
1473 /**
1474  * do_efi_test() - manage UEFI load options
1475  *
1476  * @cmdtp:      Command table
1477  * @flag:       Command flag
1478  * @argc:       Number of arguments
1479  * @argv:       Argument array
1480  * Return:      CMD_RET_SUCCESS on success,
1481  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1482  *
1483  * Implement efidebug "test" sub-command.
1484  */
1485 static int do_efi_test(struct cmd_tbl *cmdtp, int flag,
1486                        int argc, char * const argv[])
1487 {
1488         struct cmd_tbl *cp;
1489
1490         if (argc < 2)
1491                 return CMD_RET_USAGE;
1492
1493         argc--; argv++;
1494
1495         cp = find_cmd_tbl(argv[0], cmd_efidebug_test_sub,
1496                           ARRAY_SIZE(cmd_efidebug_test_sub));
1497         if (!cp)
1498                 return CMD_RET_USAGE;
1499
1500         return cp->cmd(cmdtp, flag, argc, argv);
1501 }
1502
1503 /**
1504  * do_efi_query_info() - QueryVariableInfo EFI service
1505  *
1506  * @cmdtp:      Command table
1507  * @flag:       Command flag
1508  * @argc:       Number of arguments
1509  * @argv:       Argument array
1510  * Return:      CMD_RET_SUCCESS on success,
1511  *              CMD_RET_USAGE or CMD_RET_FAILURE on failure
1512  *
1513  * Implement efidebug "test" sub-command.
1514  */
1515
1516 static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
1517                              int argc, char * const argv[])
1518 {
1519         efi_status_t ret;
1520         u32 attr = 0;
1521         u64 max_variable_storage_size;
1522         u64 remain_variable_storage_size;
1523         u64 max_variable_size;
1524         int i;
1525
1526         for (i = 1; i < argc; i++) {
1527                 if (!strcmp(argv[i], "-bs"))
1528                         attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
1529                 else if (!strcmp(argv[i], "-rt"))
1530                         attr |= EFI_VARIABLE_RUNTIME_ACCESS;
1531                 else if (!strcmp(argv[i], "-nv"))
1532                         attr |= EFI_VARIABLE_NON_VOLATILE;
1533                 else if (!strcmp(argv[i], "-at"))
1534                         attr |=
1535                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1536         }
1537
1538         ret = efi_query_variable_info_int(attr, &max_variable_storage_size,
1539                                           &remain_variable_storage_size,
1540                                           &max_variable_size);
1541         if (ret != EFI_SUCCESS) {
1542                 printf("Error: Cannot query UEFI variables, r = %lu\n",
1543                        ret & ~EFI_ERROR_MASK);
1544                 return CMD_RET_FAILURE;
1545         }
1546
1547         printf("Max storage size %llu\n", max_variable_storage_size);
1548         printf("Remaining storage size %llu\n", remain_variable_storage_size);
1549         printf("Max variable size %llu\n", max_variable_size);
1550
1551         return CMD_RET_SUCCESS;
1552 }
1553
1554 static struct cmd_tbl cmd_efidebug_sub[] = {
1555         U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
1556 #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1557         U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule,
1558                          "", ""),
1559 #endif
1560         U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
1561                          "", ""),
1562         U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
1563                          "", ""),
1564         U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
1565                          "", ""),
1566         U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
1567                          "", ""),
1568         U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
1569                          "", ""),
1570         U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
1571                          "", ""),
1572         U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
1573                          "", ""),
1574 };
1575
1576 /**
1577  * do_efidebug() - display and configure UEFI environment
1578  *
1579  * @cmdtp:      Command table
1580  * @flag:       Command flag
1581  * @argc:       Number of arguments
1582  * @argv:       Argument array
1583  * Return:      CMD_RET_SUCCESS on success,
1584  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1585  *
1586  * Implement efidebug command which allows us to display and
1587  * configure UEFI environment.
1588  */
1589 static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
1590                        int argc, char *const argv[])
1591 {
1592         struct cmd_tbl *cp;
1593         efi_status_t r;
1594
1595         if (argc < 2)
1596                 return CMD_RET_USAGE;
1597
1598         argc--; argv++;
1599
1600         /* Initialize UEFI drivers */
1601         r = efi_init_obj_list();
1602         if (r != EFI_SUCCESS) {
1603                 printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
1604                        r & ~EFI_ERROR_MASK);
1605                 return CMD_RET_FAILURE;
1606         }
1607
1608         cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
1609                           ARRAY_SIZE(cmd_efidebug_sub));
1610         if (!cp)
1611                 return CMD_RET_USAGE;
1612
1613         return cp->cmd(cmdtp, flag, argc, argv);
1614 }
1615
1616 U_BOOT_LONGHELP(efidebug,
1617         "  - UEFI Shell-like interface to configure UEFI environment\n"
1618         "\n"
1619         "efidebug boot add - set UEFI BootXXXX variable\n"
1620         "  -b|-B <bootid> <label> <interface> <devnum>[:<part>] <file path>\n"
1621         "  -d|-D <interface> <devnum>[:<part>] <device-tree file path>\n"
1622         "  -i|-I <interface> <devnum>[:<part>] <initrd file path>\n"
1623         "  (-b, -d, -i for short form device path)\n"
1624 #if (IS_ENABLED(CONFIG_EFI_HTTP_BOOT))
1625         "  -u <bootid> <label> <uri>\n"
1626 #endif
1627         "  -s '<optional data>'\n"
1628         "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
1629         "  - delete UEFI BootXXXX variables\n"
1630         "efidebug boot dump\n"
1631         "  - dump all UEFI BootXXXX variables\n"
1632         "efidebug boot next <bootid>\n"
1633         "  - set UEFI BootNext variable\n"
1634         "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
1635         "  - set/show UEFI boot order\n"
1636         "\n"
1637 #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1638         "efidebug capsule update [-v] <capsule address>\n"
1639         "  - process a capsule\n"
1640         "efidebug capsule disk-update\n"
1641         "  - update a capsule from disk\n"
1642         "efidebug capsule show <capsule address>\n"
1643         "  - show capsule information\n"
1644         "efidebug capsule result [<capsule result var>]\n"
1645         "  - show a capsule update result\n"
1646 #ifdef CONFIG_EFI_ESRT
1647         "efidebug capsule esrt\n"
1648         "  - print the ESRT\n"
1649 #endif
1650         "\n"
1651 #endif
1652         "efidebug drivers\n"
1653         "  - show UEFI drivers\n"
1654         "efidebug dh\n"
1655         "  - show UEFI handles\n"
1656         "efidebug images\n"
1657         "  - show loaded images\n"
1658         "efidebug memmap\n"
1659         "  - show UEFI memory map\n"
1660         "efidebug tables\n"
1661         "  - show UEFI configuration tables\n"
1662 #ifdef CONFIG_EFI_BOOTMGR
1663         "efidebug test bootmgr\n"
1664         "  - run simple bootmgr for test\n"
1665 #endif
1666         "efidebug query [-nv][-bs][-rt][-at]\n"
1667         "  - show size of UEFI variables store\n");
1668
1669 U_BOOT_CMD(
1670         efidebug, CONFIG_SYS_MAXARGS, 0, do_efidebug,
1671         "Configure UEFI environment",
1672         efidebug_help_text
1673 );
This page took 0.127247 seconds and 4 git commands to generate.