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