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