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