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