cmd: efidebug: Add support for TCG2 final events table
[platform/kernel/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 <efi_loader.h>
12 #include <efi_rng.h>
13 #include <exports.h>
14 #include <hexdump.h>
15 #include <log.h>
16 #include <malloc.h>
17 #include <mapmem.h>
18 #include <search.h>
19 #include <linux/ctype.h>
20
21 #define BS systab.boottime
22
23 /**
24  * efi_get_device_handle_info() - get information of UEFI device
25  *
26  * @handle:             Handle of UEFI device
27  * @dev_path_text:      Pointer to text of device path
28  * Return:              0 on success, -1 on failure
29  *
30  * Currently return a formatted text of device path.
31  */
32 static int efi_get_device_handle_info(efi_handle_t handle, u16 **dev_path_text)
33 {
34         struct efi_device_path *dp;
35         efi_status_t ret;
36
37         ret = EFI_CALL(BS->open_protocol(handle, &efi_guid_device_path,
38                                          (void **)&dp, NULL /* FIXME */, NULL,
39                                          EFI_OPEN_PROTOCOL_GET_PROTOCOL));
40         if (ret == EFI_SUCCESS) {
41                 *dev_path_text = efi_dp_str(dp);
42                 return 0;
43         } else {
44                 return -1;
45         }
46 }
47
48 #define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
49
50 static const char spc[] = "                ";
51 static const char sep[] = "================";
52
53 /**
54  * do_efi_show_devices() - show UEFI devices
55  *
56  * @cmdtp:      Command table
57  * @flag:       Command flag
58  * @argc:       Number of arguments
59  * @argv:       Argument array
60  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
61  *
62  * Implement efidebug "devices" sub-command.
63  * Show all UEFI devices and their information.
64  */
65 static int do_efi_show_devices(struct cmd_tbl *cmdtp, int flag,
66                                int argc, char *const argv[])
67 {
68         efi_handle_t *handles;
69         efi_uintn_t num, i;
70         u16 *dev_path_text;
71         efi_status_t ret;
72
73         ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
74                                                 &num, &handles));
75         if (ret != EFI_SUCCESS)
76                 return CMD_RET_FAILURE;
77
78         if (!num)
79                 return CMD_RET_SUCCESS;
80
81         printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
82         printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
83         for (i = 0; i < num; i++) {
84                 if (!efi_get_device_handle_info(handles[i], &dev_path_text)) {
85                         printf("%p %ls\n", handles[i], dev_path_text);
86                         efi_free_pool(dev_path_text);
87                 }
88         }
89
90         efi_free_pool(handles);
91
92         return CMD_RET_SUCCESS;
93 }
94
95 /**
96  * efi_get_driver_handle_info() - get information of UEFI driver
97  *
98  * @handle:             Handle of UEFI device
99  * @driver_name:        Driver name
100  * @image_path:         Pointer to text of device path
101  * Return:              0 on success, -1 on failure
102  *
103  * Currently return no useful information as all UEFI drivers are
104  * built-in..
105  */
106 static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
107                                       u16 **image_path)
108 {
109         struct efi_handler *handler;
110         struct efi_loaded_image *image;
111         efi_status_t ret;
112
113         /*
114          * driver name
115          * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
116          */
117         *driver_name = NULL;
118
119         /* image name */
120         ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
121         if (ret != EFI_SUCCESS) {
122                 *image_path = NULL;
123                 return 0;
124         }
125
126         image = handler->protocol_interface;
127         *image_path = efi_dp_str(image->file_path);
128
129         return 0;
130 }
131
132 /**
133  * do_efi_show_drivers() - show UEFI drivers
134  *
135  * @cmdtp:      Command table
136  * @flag:       Command flag
137  * @argc:       Number of arguments
138  * @argv:       Argument array
139  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
140  *
141  * Implement efidebug "drivers" sub-command.
142  * Show all UEFI drivers and their information.
143  */
144 static int do_efi_show_drivers(struct cmd_tbl *cmdtp, int flag,
145                                int argc, char *const argv[])
146 {
147         efi_handle_t *handles;
148         efi_uintn_t num, i;
149         u16 *driver_name, *image_path_text;
150         efi_status_t ret;
151
152         ret = EFI_CALL(efi_locate_handle_buffer(
153                                 BY_PROTOCOL, &efi_guid_driver_binding_protocol,
154                                 NULL, &num, &handles));
155         if (ret != EFI_SUCCESS)
156                 return CMD_RET_FAILURE;
157
158         if (!num)
159                 return CMD_RET_SUCCESS;
160
161         printf("Driver%.*s Name                 Image Path\n",
162                EFI_HANDLE_WIDTH - 6, spc);
163         printf("%.*s ==================== ====================\n",
164                EFI_HANDLE_WIDTH, sep);
165         for (i = 0; i < num; i++) {
166                 if (!efi_get_driver_handle_info(handles[i], &driver_name,
167                                                 &image_path_text)) {
168                         if (image_path_text)
169                                 printf("%p %-20ls %ls\n", handles[i],
170                                        driver_name, image_path_text);
171                         else
172                                 printf("%p %-20ls <built-in>\n",
173                                        handles[i], driver_name);
174                         efi_free_pool(driver_name);
175                         efi_free_pool(image_path_text);
176                 }
177         }
178
179         efi_free_pool(handles);
180
181         return CMD_RET_SUCCESS;
182 }
183
184 static const struct {
185         const char *text;
186         const efi_guid_t guid;
187 } guid_list[] = {
188         {
189                 "Device Path",
190                 EFI_DEVICE_PATH_PROTOCOL_GUID,
191         },
192         {
193                 "Device Path To Text",
194                 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID,
195         },
196         {
197                 "Device Path Utilities",
198                 EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID,
199         },
200         {
201                 "Unicode Collation 2",
202                 EFI_UNICODE_COLLATION_PROTOCOL2_GUID,
203         },
204         {
205                 "Driver Binding",
206                 EFI_DRIVER_BINDING_PROTOCOL_GUID,
207         },
208         {
209                 "Simple Text Input",
210                 EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID,
211         },
212         {
213                 "Simple Text Input Ex",
214                 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID,
215         },
216         {
217                 "Simple Text Output",
218                 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID,
219         },
220         {
221                 "Block IO",
222                 EFI_BLOCK_IO_PROTOCOL_GUID,
223         },
224         {
225                 "Simple File System",
226                 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
227         },
228         {
229                 "Loaded Image",
230                 EFI_LOADED_IMAGE_PROTOCOL_GUID,
231         },
232         {
233                 "Graphics Output",
234                 EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
235         },
236         {
237                 "HII String",
238                 EFI_HII_STRING_PROTOCOL_GUID,
239         },
240         {
241                 "HII Database",
242                 EFI_HII_DATABASE_PROTOCOL_GUID,
243         },
244         {
245                 "HII Config Routing",
246                 EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
247         },
248         {
249                 "Load File2",
250                 EFI_LOAD_FILE2_PROTOCOL_GUID,
251         },
252         {
253                 "Random Number Generator",
254                 EFI_RNG_PROTOCOL_GUID,
255         },
256         {
257                 "Simple Network",
258                 EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
259         },
260         {
261                 "PXE Base Code",
262                 EFI_PXE_BASE_CODE_PROTOCOL_GUID,
263         },
264         /* Configuration table GUIDs */
265         {
266                 "ACPI table",
267                 EFI_ACPI_TABLE_GUID,
268         },
269         {
270                 "device tree",
271                 EFI_FDT_GUID,
272         },
273         {
274                 "SMBIOS table",
275                 SMBIOS_TABLE_GUID,
276         },
277         {
278                 "Runtime properties",
279                 EFI_RT_PROPERTIES_TABLE_GUID,
280         },
281         {
282                 "TCG2 Final Events Table",
283                 EFI_TCG2_FINAL_EVENTS_TABLE_GUID,
284         },
285 };
286
287 /**
288  * get_guid_text - get string of GUID
289  *
290  * Return description of GUID.
291  *
292  * @guid:       GUID
293  * Return:      description of GUID or NULL
294  */
295 static const char *get_guid_text(const void *guid)
296 {
297         int i;
298
299         for (i = 0; i < ARRAY_SIZE(guid_list); i++) {
300                 /*
301                  * As guidcmp uses memcmp() we can safely accept unaligned
302                  * GUIDs.
303                  */
304                 if (!guidcmp(&guid_list[i].guid, guid))
305                         return guid_list[i].text;
306         }
307
308         return NULL;
309 }
310
311 /**
312  * do_efi_show_handles() - show UEFI handles
313  *
314  * @cmdtp:      Command table
315  * @flag:       Command flag
316  * @argc:       Number of arguments
317  * @argv:       Argument array
318  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
319  *
320  * Implement efidebug "dh" sub-command.
321  * Show all UEFI handles and their information, currently all protocols
322  * added to handle.
323  */
324 static int do_efi_show_handles(struct cmd_tbl *cmdtp, int flag,
325                                int argc, char *const argv[])
326 {
327         efi_handle_t *handles;
328         efi_guid_t **guid;
329         efi_uintn_t num, count, i, j;
330         const char *guid_text;
331         efi_status_t ret;
332
333         ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
334                                                 &num, &handles));
335         if (ret != EFI_SUCCESS)
336                 return CMD_RET_FAILURE;
337
338         if (!num)
339                 return CMD_RET_SUCCESS;
340
341         printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
342         printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
343         for (i = 0; i < num; i++) {
344                 printf("%p", handles[i]);
345                 ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
346                                                         &count));
347                 if (ret || !count) {
348                         putc('\n');
349                         continue;
350                 }
351
352                 for (j = 0; j < count; j++) {
353                         if (j)
354                                 printf(", ");
355                         else
356                                 putc(' ');
357
358                         guid_text = get_guid_text(guid[j]);
359                         if (guid_text)
360                                 puts(guid_text);
361                         else
362                                 printf("%pUl", guid[j]);
363                 }
364                 putc('\n');
365         }
366
367         efi_free_pool(handles);
368
369         return CMD_RET_SUCCESS;
370 }
371
372 /**
373  * do_efi_show_images() - show UEFI images
374  *
375  * @cmdtp:      Command table
376  * @flag:       Command flag
377  * @argc:       Number of arguments
378  * @argv:       Argument array
379  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
380  *
381  * Implement efidebug "images" sub-command.
382  * Show all UEFI loaded images and their information.
383  */
384 static int do_efi_show_images(struct cmd_tbl *cmdtp, int flag,
385                               int argc, char *const argv[])
386 {
387         efi_print_image_infos(NULL);
388
389         return CMD_RET_SUCCESS;
390 }
391
392 static const char * const efi_mem_type_string[] = {
393         [EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
394         [EFI_LOADER_CODE] = "LOADER CODE",
395         [EFI_LOADER_DATA] = "LOADER DATA",
396         [EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
397         [EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
398         [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
399         [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
400         [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
401         [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
402         [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
403         [EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
404         [EFI_MMAP_IO] = "IO",
405         [EFI_MMAP_IO_PORT] = "IO PORT",
406         [EFI_PAL_CODE] = "PAL",
407         [EFI_PERSISTENT_MEMORY_TYPE] = "PERSISTENT",
408 };
409
410 static const struct efi_mem_attrs {
411         const u64 bit;
412         const char *text;
413 } efi_mem_attrs[] = {
414         {EFI_MEMORY_UC, "UC"},
415         {EFI_MEMORY_UC, "UC"},
416         {EFI_MEMORY_WC, "WC"},
417         {EFI_MEMORY_WT, "WT"},
418         {EFI_MEMORY_WB, "WB"},
419         {EFI_MEMORY_UCE, "UCE"},
420         {EFI_MEMORY_WP, "WP"},
421         {EFI_MEMORY_RP, "RP"},
422         {EFI_MEMORY_XP, "WP"},
423         {EFI_MEMORY_NV, "NV"},
424         {EFI_MEMORY_MORE_RELIABLE, "REL"},
425         {EFI_MEMORY_RO, "RO"},
426         {EFI_MEMORY_SP, "SP"},
427         {EFI_MEMORY_RUNTIME, "RT"},
428 };
429
430 /**
431  * print_memory_attributes() - print memory map attributes
432  *
433  * @attributes: Attribute value
434  *
435  * Print memory map attributes
436  */
437 static void print_memory_attributes(u64 attributes)
438 {
439         int sep, i;
440
441         for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
442                 if (attributes & efi_mem_attrs[i].bit) {
443                         if (sep) {
444                                 putc('|');
445                         } else {
446                                 putc(' ');
447                                 sep = 1;
448                         }
449                         puts(efi_mem_attrs[i].text);
450                 }
451 }
452
453 #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
454
455 /**
456  * do_efi_show_memmap() - show UEFI memory map
457  *
458  * @cmdtp:      Command table
459  * @flag:       Command flag
460  * @argc:       Number of arguments
461  * @argv:       Argument array
462  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
463  *
464  * Implement efidebug "memmap" sub-command.
465  * Show UEFI memory map.
466  */
467 static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
468                               int argc, char *const argv[])
469 {
470         struct efi_mem_desc *memmap = NULL, *map;
471         efi_uintn_t map_size = 0;
472         const char *type;
473         int i;
474         efi_status_t ret;
475
476         ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
477         if (ret == EFI_BUFFER_TOO_SMALL) {
478                 map_size += sizeof(struct efi_mem_desc); /* for my own */
479                 ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
480                                         (void *)&memmap);
481                 if (ret != EFI_SUCCESS)
482                         return CMD_RET_FAILURE;
483                 ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
484         }
485         if (ret != EFI_SUCCESS) {
486                 efi_free_pool(memmap);
487                 return CMD_RET_FAILURE;
488         }
489
490         printf("Type             Start%.*s End%.*s Attributes\n",
491                EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
492         printf("================ %.*s %.*s ==========\n",
493                EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
494         /*
495          * Coverity check: dereferencing null pointer "map."
496          * This is a false positive as memmap will always be
497          * populated by allocate_pool() above.
498          */
499         for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
500                 if (map->type < ARRAY_SIZE(efi_mem_type_string))
501                         type = efi_mem_type_string[map->type];
502                 else
503                         type = "(unknown)";
504
505                 printf("%-16s %.*llx-%.*llx", type,
506                        EFI_PHYS_ADDR_WIDTH,
507                        (u64)map_to_sysmem((void *)(uintptr_t)
508                                           map->physical_start),
509                        EFI_PHYS_ADDR_WIDTH,
510                        (u64)map_to_sysmem((void *)(uintptr_t)
511                                           (map->physical_start +
512                                            map->num_pages * EFI_PAGE_SIZE)));
513
514                 print_memory_attributes(map->attribute);
515                 putc('\n');
516         }
517
518         efi_free_pool(memmap);
519
520         return CMD_RET_SUCCESS;
521 }
522
523 /**
524  * do_efi_show_tables() - show UEFI configuration tables
525  *
526  * @cmdtp:      Command table
527  * @flag:       Command flag
528  * @argc:       Number of arguments
529  * @argv:       Argument array
530  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
531  *
532  * Implement efidebug "tables" sub-command.
533  * Show UEFI configuration tables.
534  */
535 static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
536                               int argc, char *const argv[])
537 {
538         efi_uintn_t i;
539         const char *guid_str;
540
541         for (i = 0; i < systab.nr_tables; ++i) {
542                 guid_str = get_guid_text(&systab.tables[i].guid);
543                 if (!guid_str)
544                         guid_str = "";
545                 printf("%pUl %s\n", &systab.tables[i].guid, guid_str);
546         }
547
548         return CMD_RET_SUCCESS;
549 }
550
551 /**
552  * do_efi_boot_add() - set UEFI load option
553  *
554  * @cmdtp:      Command table
555  * @flag:       Command flag
556  * @argc:       Number of arguments
557  * @argv:       Argument array
558  * Return:      CMD_RET_SUCCESS on success,
559  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
560  *
561  * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
562  *
563  *     efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
564  */
565 static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
566                            int argc, char *const argv[])
567 {
568         int id;
569         char *endp;
570         char var_name[9];
571         u16 var_name16[9], *p;
572         efi_guid_t guid;
573         size_t label_len, label_len16;
574         u16 *label;
575         struct efi_device_path *device_path = NULL, *file_path = NULL;
576         struct efi_load_option lo;
577         void *data = NULL;
578         efi_uintn_t size;
579         efi_status_t ret;
580         int r = CMD_RET_SUCCESS;
581
582         if (argc < 6 || argc > 7)
583                 return CMD_RET_USAGE;
584
585         id = (int)simple_strtoul(argv[1], &endp, 16);
586         if (*endp != '\0' || id > 0xffff)
587                 return CMD_RET_USAGE;
588
589         sprintf(var_name, "Boot%04X", id);
590         p = var_name16;
591         utf8_utf16_strncpy(&p, var_name, 9);
592
593         guid = efi_global_variable_guid;
594
595         /* attributes */
596         lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
597
598         /* label */
599         label_len = strlen(argv[2]);
600         label_len16 = utf8_utf16_strnlen(argv[2], label_len);
601         label = malloc((label_len16 + 1) * sizeof(u16));
602         if (!label)
603                 return CMD_RET_FAILURE;
604         lo.label = label; /* label will be changed below */
605         utf8_utf16_strncpy(&label, argv[2], label_len);
606
607         /* file path */
608         ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
609                                &file_path);
610         if (ret != EFI_SUCCESS) {
611                 printf("Cannot create device path for \"%s %s\"\n",
612                        argv[3], argv[4]);
613                 r = CMD_RET_FAILURE;
614                 goto out;
615         }
616         lo.file_path = file_path;
617         lo.file_path_length = efi_dp_size(file_path)
618                                 + sizeof(struct efi_device_path); /* for END */
619
620         /* optional data */
621         if (argc == 6)
622                 lo.optional_data = NULL;
623         else
624                 lo.optional_data = (const u8 *)argv[6];
625
626         size = efi_serialize_load_option(&lo, (u8 **)&data);
627         if (!size) {
628                 r = CMD_RET_FAILURE;
629                 goto out;
630         }
631
632         ret = EFI_CALL(efi_set_variable(var_name16, &guid,
633                                         EFI_VARIABLE_NON_VOLATILE |
634                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
635                                         EFI_VARIABLE_RUNTIME_ACCESS,
636                                         size, data));
637         if (ret != EFI_SUCCESS) {
638                 printf("Cannot set %ls\n", var_name16);
639                 r = CMD_RET_FAILURE;
640         }
641 out:
642         free(data);
643         efi_free_pool(device_path);
644         efi_free_pool(file_path);
645         free(lo.label);
646
647         return r;
648 }
649
650 /**
651  * do_efi_boot_rm() - delete UEFI load options
652  *
653  * @cmdtp:      Command table
654  * @flag:       Command flag
655  * @argc:       Number of arguments
656  * @argv:       Argument array
657  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
658  *
659  * Implement efidebug "boot rm" sub-command.
660  * Delete UEFI load options.
661  *
662  *     efidebug boot rm <id> ...
663  */
664 static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
665                           int argc, char *const argv[])
666 {
667         efi_guid_t guid;
668         int id, i;
669         char *endp;
670         char var_name[9];
671         u16 var_name16[9], *p;
672         efi_status_t ret;
673
674         if (argc == 1)
675                 return CMD_RET_USAGE;
676
677         guid = efi_global_variable_guid;
678         for (i = 1; i < argc; i++, argv++) {
679                 id = (int)simple_strtoul(argv[1], &endp, 16);
680                 if (*endp != '\0' || id > 0xffff)
681                         return CMD_RET_FAILURE;
682
683                 sprintf(var_name, "Boot%04X", id);
684                 p = var_name16;
685                 utf8_utf16_strncpy(&p, var_name, 9);
686
687                 ret = EFI_CALL(efi_set_variable(var_name16, &guid, 0, 0, NULL));
688                 if (ret) {
689                         printf("Cannot remove %ls\n", var_name16);
690                         return CMD_RET_FAILURE;
691                 }
692         }
693
694         return CMD_RET_SUCCESS;
695 }
696
697 /**
698  * show_efi_boot_opt_data() - dump UEFI load option
699  *
700  * @varname16:  variable name
701  * @data:       value of UEFI load option variable
702  * @size:       size of the boot option
703  *
704  * Decode the value of UEFI load option variable and print information.
705  */
706 static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
707 {
708         struct efi_load_option lo;
709         char *label, *p;
710         size_t label_len16, label_len;
711         u16 *dp_str;
712         efi_status_t ret;
713
714         ret = efi_deserialize_load_option(&lo, data, size);
715         if (ret != EFI_SUCCESS) {
716                 printf("%ls: invalid load option\n", varname16);
717                 return;
718         }
719
720         label_len16 = u16_strlen(lo.label);
721         label_len = utf16_utf8_strnlen(lo.label, label_len16);
722         label = malloc(label_len + 1);
723         if (!label)
724                 return;
725         p = label;
726         utf16_utf8_strncpy(&p, lo.label, label_len16);
727
728         printf("%ls:\nattributes: %c%c%c (0x%08x)\n",
729                varname16,
730                /* ACTIVE */
731                lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
732                /* FORCE RECONNECT */
733                lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
734                /* HIDDEN */
735                lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
736                lo.attributes);
737         printf("  label: %s\n", label);
738
739         dp_str = efi_dp_str(lo.file_path);
740         printf("  file_path: %ls\n", dp_str);
741         efi_free_pool(dp_str);
742
743         printf("  data:\n");
744         print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
745                        lo.optional_data, *size, true);
746         free(label);
747 }
748
749 /**
750  * show_efi_boot_opt() - dump UEFI load option
751  *
752  * @varname16:  variable name
753  *
754  * Dump information defined by UEFI load option.
755  */
756 static void show_efi_boot_opt(u16 *varname16)
757 {
758         void *data;
759         efi_uintn_t size;
760         efi_status_t ret;
761
762         size = 0;
763         ret = EFI_CALL(efi_get_variable(varname16, &efi_global_variable_guid,
764                                         NULL, &size, NULL));
765         if (ret == EFI_BUFFER_TOO_SMALL) {
766                 data = malloc(size);
767                 if (!data) {
768                         printf("ERROR: Out of memory\n");
769                         return;
770                 }
771                 ret = EFI_CALL(efi_get_variable(varname16,
772                                                 &efi_global_variable_guid,
773                                                 NULL, &size, data));
774                 if (ret == EFI_SUCCESS)
775                         show_efi_boot_opt_data(varname16, data, &size);
776                 free(data);
777         }
778 }
779
780 static int u16_tohex(u16 c)
781 {
782         if (c >= '0' && c <= '9')
783                 return c - '0';
784         if (c >= 'A' && c <= 'F')
785                 return c - 'A' + 10;
786
787         /* not hexadecimal */
788         return -1;
789 }
790
791 /**
792  * show_efi_boot_dump() - dump all UEFI load options
793  *
794  * @cmdtp:      Command table
795  * @flag:       Command flag
796  * @argc:       Number of arguments
797  * @argv:       Argument array
798  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
799  *
800  * Implement efidebug "boot dump" sub-command.
801  * Dump information of all UEFI load options defined.
802  *
803  *     efidebug boot dump
804  */
805 static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
806                             int argc, char *const argv[])
807 {
808         u16 *var_name16, *p;
809         efi_uintn_t buf_size, size;
810         efi_guid_t guid;
811         int id, i, digit;
812         efi_status_t ret;
813
814         if (argc > 1)
815                 return CMD_RET_USAGE;
816
817         buf_size = 128;
818         var_name16 = malloc(buf_size);
819         if (!var_name16)
820                 return CMD_RET_FAILURE;
821
822         var_name16[0] = 0;
823         for (;;) {
824                 size = buf_size;
825                 ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
826                                                           &guid));
827                 if (ret == EFI_NOT_FOUND)
828                         break;
829                 if (ret == EFI_BUFFER_TOO_SMALL) {
830                         buf_size = size;
831                         p = realloc(var_name16, buf_size);
832                         if (!p) {
833                                 free(var_name16);
834                                 return CMD_RET_FAILURE;
835                         }
836                         var_name16 = p;
837                         ret = EFI_CALL(efi_get_next_variable_name(&size,
838                                                                   var_name16,
839                                                                   &guid));
840                 }
841                 if (ret != EFI_SUCCESS) {
842                         free(var_name16);
843                         return CMD_RET_FAILURE;
844                 }
845
846                 if (memcmp(var_name16, L"Boot", 8))
847                         continue;
848
849                 for (id = 0, i = 0; i < 4; i++) {
850                         digit = u16_tohex(var_name16[4 + i]);
851                         if (digit < 0)
852                                 break;
853                         id = (id << 4) + digit;
854                 }
855                 if (i == 4 && !var_name16[8])
856                         show_efi_boot_opt(var_name16);
857         }
858
859         free(var_name16);
860
861         return CMD_RET_SUCCESS;
862 }
863
864 /**
865  * show_efi_boot_order() - show order of UEFI load options
866  *
867  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
868  *
869  * Show order of UEFI load options defined by BootOrder variable.
870  */
871 static int show_efi_boot_order(void)
872 {
873         u16 *bootorder;
874         efi_uintn_t size;
875         int num, i;
876         char var_name[9];
877         u16 var_name16[9], *p16;
878         void *data;
879         struct efi_load_option lo;
880         char *label, *p;
881         size_t label_len16, label_len;
882         efi_status_t ret;
883
884         size = 0;
885         ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
886                                         NULL, &size, NULL));
887         if (ret != EFI_BUFFER_TOO_SMALL) {
888                 if (ret == EFI_NOT_FOUND) {
889                         printf("BootOrder not defined\n");
890                         return CMD_RET_SUCCESS;
891                 } else {
892                         return CMD_RET_FAILURE;
893                 }
894         }
895         bootorder = malloc(size);
896         if (!bootorder) {
897                 printf("ERROR: Out of memory\n");
898                 return CMD_RET_FAILURE;
899         }
900         ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
901                                         NULL, &size, bootorder));
902         if (ret != EFI_SUCCESS) {
903                 ret = CMD_RET_FAILURE;
904                 goto out;
905         }
906
907         num = size / sizeof(u16);
908         for (i = 0; i < num; i++) {
909                 sprintf(var_name, "Boot%04X", bootorder[i]);
910                 p16 = var_name16;
911                 utf8_utf16_strncpy(&p16, var_name, 9);
912
913                 size = 0;
914                 ret = EFI_CALL(efi_get_variable(var_name16,
915                                                 &efi_global_variable_guid, NULL,
916                                                 &size, NULL));
917                 if (ret != EFI_BUFFER_TOO_SMALL) {
918                         printf("%2d: %s: (not defined)\n", i + 1, var_name);
919                         continue;
920                 }
921
922                 data = malloc(size);
923                 if (!data) {
924                         ret = CMD_RET_FAILURE;
925                         goto out;
926                 }
927                 ret = EFI_CALL(efi_get_variable(var_name16,
928                                                 &efi_global_variable_guid, NULL,
929                                                 &size, data));
930                 if (ret != EFI_SUCCESS) {
931                         free(data);
932                         ret = CMD_RET_FAILURE;
933                         goto out;
934                 }
935
936                 ret = efi_deserialize_load_option(&lo, data, &size);
937                 if (ret != EFI_SUCCESS) {
938                         printf("%ls: invalid load option\n", var_name16);
939                         ret = CMD_RET_FAILURE;
940                         goto out;
941                 }
942
943                 label_len16 = u16_strlen(lo.label);
944                 label_len = utf16_utf8_strnlen(lo.label, label_len16);
945                 label = malloc(label_len + 1);
946                 if (!label) {
947                         free(data);
948                         ret = CMD_RET_FAILURE;
949                         goto out;
950                 }
951                 p = label;
952                 utf16_utf8_strncpy(&p, lo.label, label_len16);
953                 printf("%2d: %s: %s\n", i + 1, var_name, label);
954                 free(label);
955
956                 free(data);
957         }
958 out:
959         free(bootorder);
960
961         return ret;
962 }
963
964 /**
965  * do_efi_boot_next() - manage UEFI BootNext variable
966  *
967  * @cmdtp:      Command table
968  * @flag:       Command flag
969  * @argc:       Number of arguments
970  * @argv:       Argument array
971  * Return:      CMD_RET_SUCCESS on success,
972  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
973  *
974  * Implement efidebug "boot next" sub-command.
975  * Set BootNext variable.
976  *
977  *     efidebug boot next <id>
978  */
979 static int do_efi_boot_next(struct cmd_tbl *cmdtp, int flag,
980                             int argc, char *const argv[])
981 {
982         u16 bootnext;
983         efi_uintn_t size;
984         char *endp;
985         efi_guid_t guid;
986         efi_status_t ret;
987         int r = CMD_RET_SUCCESS;
988
989         if (argc != 2)
990                 return CMD_RET_USAGE;
991
992         bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
993         if (*endp) {
994                 printf("invalid value: %s\n", argv[1]);
995                 r = CMD_RET_FAILURE;
996                 goto out;
997         }
998
999         guid = efi_global_variable_guid;
1000         size = sizeof(u16);
1001         ret = EFI_CALL(efi_set_variable(L"BootNext", &guid,
1002                                         EFI_VARIABLE_NON_VOLATILE |
1003                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
1004                                         EFI_VARIABLE_RUNTIME_ACCESS,
1005                                         size, &bootnext));
1006         if (ret != EFI_SUCCESS) {
1007                 printf("Cannot set BootNext\n");
1008                 r = CMD_RET_FAILURE;
1009         }
1010 out:
1011         return r;
1012 }
1013
1014 /**
1015  * do_efi_boot_order() - manage UEFI BootOrder variable
1016  *
1017  * @cmdtp:      Command table
1018  * @flag:       Command flag
1019  * @argc:       Number of arguments
1020  * @argv:       Argument array
1021  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1022  *
1023  * Implement efidebug "boot order" sub-command.
1024  * Show order of UEFI load options, or change it in BootOrder variable.
1025  *
1026  *     efidebug boot order [<id> ...]
1027  */
1028 static int do_efi_boot_order(struct cmd_tbl *cmdtp, int flag,
1029                              int argc, char *const argv[])
1030 {
1031         u16 *bootorder = NULL;
1032         efi_uintn_t size;
1033         int id, i;
1034         char *endp;
1035         efi_guid_t guid;
1036         efi_status_t ret;
1037         int r = CMD_RET_SUCCESS;
1038
1039         if (argc == 1)
1040                 return show_efi_boot_order();
1041
1042         argc--;
1043         argv++;
1044
1045         size = argc * sizeof(u16);
1046         bootorder = malloc(size);
1047         if (!bootorder)
1048                 return CMD_RET_FAILURE;
1049
1050         for (i = 0; i < argc; i++) {
1051                 id = (int)simple_strtoul(argv[i], &endp, 16);
1052                 if (*endp != '\0' || id > 0xffff) {
1053                         printf("invalid value: %s\n", argv[i]);
1054                         r = CMD_RET_FAILURE;
1055                         goto out;
1056                 }
1057
1058                 bootorder[i] = (u16)id;
1059         }
1060
1061         guid = efi_global_variable_guid;
1062         ret = EFI_CALL(efi_set_variable(L"BootOrder", &guid,
1063                                         EFI_VARIABLE_NON_VOLATILE |
1064                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
1065                                         EFI_VARIABLE_RUNTIME_ACCESS,
1066                                         size, bootorder));
1067         if (ret != EFI_SUCCESS) {
1068                 printf("Cannot set BootOrder\n");
1069                 r = CMD_RET_FAILURE;
1070         }
1071 out:
1072         free(bootorder);
1073
1074         return r;
1075 }
1076
1077 static struct cmd_tbl cmd_efidebug_boot_sub[] = {
1078         U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
1079         U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
1080         U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
1081         U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
1082         U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
1083                          "", ""),
1084 };
1085
1086 /**
1087  * do_efi_boot_opt() - manage UEFI load options
1088  *
1089  * @cmdtp:      Command table
1090  * @flag:       Command flag
1091  * @argc:       Number of arguments
1092  * @argv:       Argument array
1093  * Return:      CMD_RET_SUCCESS on success,
1094  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1095  *
1096  * Implement efidebug "boot" sub-command.
1097  */
1098 static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
1099                            int argc, char *const argv[])
1100 {
1101         struct cmd_tbl *cp;
1102
1103         if (argc < 2)
1104                 return CMD_RET_USAGE;
1105
1106         argc--; argv++;
1107
1108         cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
1109                           ARRAY_SIZE(cmd_efidebug_boot_sub));
1110         if (!cp)
1111                 return CMD_RET_USAGE;
1112
1113         return cp->cmd(cmdtp, flag, argc, argv);
1114 }
1115
1116 /**
1117  * do_efi_test_bootmgr() - run simple bootmgr for test
1118  *
1119  * @cmdtp:      Command table
1120  * @flag:       Command flag
1121  * @argc:       Number of arguments
1122  * @argv:       Argument array
1123  * Return:      CMD_RET_SUCCESS on success,
1124  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1125  *
1126  * Implement efidebug "test bootmgr" sub-command.
1127  * Run simple bootmgr for test.
1128  *
1129  *     efidebug test bootmgr
1130  */
1131 static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
1132                                int argc, char * const argv[])
1133 {
1134         efi_handle_t image;
1135         efi_uintn_t exit_data_size = 0;
1136         u16 *exit_data = NULL;
1137         efi_status_t ret;
1138         void *load_options = NULL;
1139
1140         ret = efi_bootmgr_load(&image, &load_options);
1141         printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1142
1143         /* We call efi_start_image() even if error for test purpose. */
1144         ret = EFI_CALL(efi_start_image(image, &exit_data_size, &exit_data));
1145         printf("efi_start_image() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1146         if (ret && exit_data)
1147                 efi_free_pool(exit_data);
1148
1149         efi_restore_gd();
1150
1151         free(load_options);
1152         return CMD_RET_SUCCESS;
1153 }
1154
1155 static struct cmd_tbl cmd_efidebug_test_sub[] = {
1156         U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
1157                          "", ""),
1158 };
1159
1160 /**
1161  * do_efi_test() - manage UEFI load options
1162  *
1163  * @cmdtp:      Command table
1164  * @flag:       Command flag
1165  * @argc:       Number of arguments
1166  * @argv:       Argument array
1167  * Return:      CMD_RET_SUCCESS on success,
1168  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1169  *
1170  * Implement efidebug "test" sub-command.
1171  */
1172 static int do_efi_test(struct cmd_tbl *cmdtp, int flag,
1173                        int argc, char * const argv[])
1174 {
1175         struct cmd_tbl *cp;
1176
1177         if (argc < 2)
1178                 return CMD_RET_USAGE;
1179
1180         argc--; argv++;
1181
1182         cp = find_cmd_tbl(argv[0], cmd_efidebug_test_sub,
1183                           ARRAY_SIZE(cmd_efidebug_test_sub));
1184         if (!cp)
1185                 return CMD_RET_USAGE;
1186
1187         return cp->cmd(cmdtp, flag, argc, argv);
1188 }
1189
1190 /**
1191  * do_efi_query_info() - QueryVariableInfo EFI service
1192  *
1193  * @cmdtp:      Command table
1194  * @flag:       Command flag
1195  * @argc:       Number of arguments
1196  * @argv:       Argument array
1197  * Return:      CMD_RET_SUCCESS on success,
1198  *              CMD_RET_USAGE or CMD_RET_FAILURE on failure
1199  *
1200  * Implement efidebug "test" sub-command.
1201  */
1202
1203 static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
1204                              int argc, char * const argv[])
1205 {
1206         efi_status_t ret;
1207         u32 attr = 0;
1208         u64 max_variable_storage_size;
1209         u64 remain_variable_storage_size;
1210         u64 max_variable_size;
1211         int i;
1212
1213         for (i = 1; i < argc; i++) {
1214                 if (!strcmp(argv[i], "-bs"))
1215                         attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
1216                 else if (!strcmp(argv[i], "-rt"))
1217                         attr |= EFI_VARIABLE_RUNTIME_ACCESS;
1218                 else if (!strcmp(argv[i], "-nv"))
1219                         attr |= EFI_VARIABLE_NON_VOLATILE;
1220                 else if (!strcmp(argv[i], "-at"))
1221                         attr |=
1222                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1223         }
1224
1225         ret = EFI_CALL(efi_query_variable_info(attr,
1226                                                &max_variable_storage_size,
1227                                                &remain_variable_storage_size,
1228                                                &max_variable_size));
1229         if (ret != EFI_SUCCESS) {
1230                 printf("Error: Cannot query UEFI variables, r = %lu\n",
1231                        ret & ~EFI_ERROR_MASK);
1232                 return CMD_RET_FAILURE;
1233         }
1234
1235         printf("Max storage size %llu\n", max_variable_storage_size);
1236         printf("Remaining storage size %llu\n", remain_variable_storage_size);
1237         printf("Max variable size %llu\n", max_variable_size);
1238
1239         return CMD_RET_SUCCESS;
1240 }
1241
1242 static struct cmd_tbl cmd_efidebug_sub[] = {
1243         U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
1244         U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
1245                          "", ""),
1246         U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
1247                          "", ""),
1248         U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
1249                          "", ""),
1250         U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
1251                          "", ""),
1252         U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
1253                          "", ""),
1254         U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
1255                          "", ""),
1256         U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
1257                          "", ""),
1258         U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
1259                          "", ""),
1260 };
1261
1262 /**
1263  * do_efidebug() - display and configure UEFI environment
1264  *
1265  * @cmdtp:      Command table
1266  * @flag:       Command flag
1267  * @argc:       Number of arguments
1268  * @argv:       Argument array
1269  * Return:      CMD_RET_SUCCESS on success,
1270  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1271  *
1272  * Implement efidebug command which allows us to display and
1273  * configure UEFI environment.
1274  */
1275 static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
1276                        int argc, char *const argv[])
1277 {
1278         struct cmd_tbl *cp;
1279         efi_status_t r;
1280
1281         if (argc < 2)
1282                 return CMD_RET_USAGE;
1283
1284         argc--; argv++;
1285
1286         /* Initialize UEFI drivers */
1287         r = efi_init_obj_list();
1288         if (r != EFI_SUCCESS) {
1289                 printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
1290                        r & ~EFI_ERROR_MASK);
1291                 return CMD_RET_FAILURE;
1292         }
1293
1294         cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
1295                           ARRAY_SIZE(cmd_efidebug_sub));
1296         if (!cp)
1297                 return CMD_RET_USAGE;
1298
1299         return cp->cmd(cmdtp, flag, argc, argv);
1300 }
1301
1302 #ifdef CONFIG_SYS_LONGHELP
1303 static char efidebug_help_text[] =
1304         "  - UEFI Shell-like interface to configure UEFI environment\n"
1305         "\n"
1306         "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
1307         "  - set UEFI BootXXXX variable\n"
1308         "    <load options> will be passed to UEFI application\n"
1309         "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
1310         "  - delete UEFI BootXXXX variables\n"
1311         "efidebug boot dump\n"
1312         "  - dump all UEFI BootXXXX variables\n"
1313         "efidebug boot next <bootid>\n"
1314         "  - set UEFI BootNext variable\n"
1315         "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
1316         "  - set/show UEFI boot order\n"
1317         "\n"
1318         "efidebug devices\n"
1319         "  - show UEFI devices\n"
1320         "efidebug drivers\n"
1321         "  - show UEFI drivers\n"
1322         "efidebug dh\n"
1323         "  - show UEFI handles\n"
1324         "efidebug images\n"
1325         "  - show loaded images\n"
1326         "efidebug memmap\n"
1327         "  - show UEFI memory map\n"
1328         "efidebug tables\n"
1329         "  - show UEFI configuration tables\n"
1330         "efidebug test bootmgr\n"
1331         "  - run simple bootmgr for test\n"
1332         "efidebug query [-nv][-bs][-rt][-at]\n"
1333         "  - show size of UEFI variables store\n";
1334 #endif
1335
1336 U_BOOT_CMD(
1337         efidebug, 10, 0, do_efidebug,
1338         "Configure UEFI environment",
1339         efidebug_help_text
1340 );