1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * EFI application loader 4 * 5 * Copyright (c) 2016 Alexander Graf 6 */ 7 8 #include <charset.h> 9 #include <common.h> 10 #include <command.h> 11 #include <dm.h> 12 #include <efi_loader.h> 13 #include <efi_selftest.h> 14 #include <errno.h> 15 #include <linux/libfdt.h> 16 #include <linux/libfdt_env.h> 17 #include <mapmem.h> 18 #include <memalign.h> 19 #include <asm/global_data.h> 20 #include <asm-generic/sections.h> 21 #include <asm-generic/unaligned.h> 22 #include <linux/linkage.h> 23 24 #ifdef CONFIG_ARMV7_NONSEC 25 #include <asm/armv7.h> 26 #include <asm/secure.h> 27 #endif 28 29 DECLARE_GLOBAL_DATA_PTR; 30 31 #define OBJ_LIST_NOT_INITIALIZED 1 32 33 static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; 34 35 static struct efi_device_path *bootefi_image_path; 36 static struct efi_device_path *bootefi_device_path; 37 38 /* Initialize and populate EFI object list */ 39 efi_status_t efi_init_obj_list(void) 40 { 41 efi_status_t ret = EFI_SUCCESS; 42 43 /* Initialize once only */ 44 if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED) 45 return efi_obj_list_initialized; 46 47 /* Initialize system table */ 48 ret = efi_initialize_system_table(); 49 if (ret != EFI_SUCCESS) 50 goto out; 51 52 /* Initialize EFI driver uclass */ 53 ret = efi_driver_init(); 54 if (ret != EFI_SUCCESS) 55 goto out; 56 57 ret = efi_console_register(); 58 if (ret != EFI_SUCCESS) 59 goto out; 60 #ifdef CONFIG_PARTITIONS 61 ret = efi_disk_register(); 62 if (ret != EFI_SUCCESS) 63 goto out; 64 #endif 65 #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) 66 ret = efi_gop_register(); 67 if (ret != EFI_SUCCESS) 68 goto out; 69 #endif 70 #ifdef CONFIG_NET 71 ret = efi_net_register(); 72 if (ret != EFI_SUCCESS) 73 goto out; 74 #endif 75 #ifdef CONFIG_GENERATE_ACPI_TABLE 76 ret = efi_acpi_register(); 77 if (ret != EFI_SUCCESS) 78 goto out; 79 #endif 80 #ifdef CONFIG_GENERATE_SMBIOS_TABLE 81 ret = efi_smbios_register(); 82 if (ret != EFI_SUCCESS) 83 goto out; 84 #endif 85 ret = efi_watchdog_register(); 86 if (ret != EFI_SUCCESS) 87 goto out; 88 89 /* Initialize EFI runtime services */ 90 ret = efi_reset_system_init(); 91 if (ret != EFI_SUCCESS) 92 goto out; 93 94 out: 95 efi_obj_list_initialized = ret; 96 return ret; 97 } 98 99 /* 100 * Allow unaligned memory access. 101 * 102 * This routine is overridden by architectures providing this feature. 103 */ 104 void __weak allow_unaligned(void) 105 { 106 } 107 108 /* 109 * Set the load options of an image from an environment variable. 110 * 111 * @loaded_image_info: the image 112 * @env_var: name of the environment variable 113 */ 114 static void set_load_options(struct efi_loaded_image *loaded_image_info, 115 const char *env_var) 116 { 117 size_t size; 118 const char *env = env_get(env_var); 119 120 loaded_image_info->load_options = NULL; 121 loaded_image_info->load_options_size = 0; 122 if (!env) 123 return; 124 size = strlen(env) + 1; 125 loaded_image_info->load_options = calloc(size, sizeof(u16)); 126 if (!loaded_image_info->load_options) { 127 printf("ERROR: Out of memory\n"); 128 return; 129 } 130 utf8_to_utf16(loaded_image_info->load_options, (u8 *)env, size); 131 loaded_image_info->load_options_size = size * 2; 132 } 133 134 /** 135 * copy_fdt() - Copy the device tree to a new location available to EFI 136 * 137 * The FDT is relocated into a suitable location within the EFI memory map. 138 * An additional 12KB is added to the space in case the device tree needs to be 139 * expanded later with fdt_open_into(). 140 * 141 * @fdt_addr: On entry, address of start of FDT. On exit, address of relocated 142 * FDT start 143 * @fdt_sizep: Returns new size of FDT, including 144 * @return new relocated address of FDT 145 */ 146 static efi_status_t copy_fdt(ulong *fdt_addrp, ulong *fdt_sizep) 147 { 148 unsigned long fdt_ram_start = -1L, fdt_pages; 149 efi_status_t ret = 0; 150 void *fdt, *new_fdt; 151 u64 new_fdt_addr; 152 uint fdt_size; 153 int i; 154 155 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 156 u64 ram_start = gd->bd->bi_dram[i].start; 157 u64 ram_size = gd->bd->bi_dram[i].size; 158 159 if (!ram_size) 160 continue; 161 162 if (ram_start < fdt_ram_start) 163 fdt_ram_start = ram_start; 164 } 165 166 /* 167 * Give us at least 4KB of breathing room in case the device tree needs 168 * to be expanded later. Round up to the nearest EFI page boundary. 169 */ 170 fdt = map_sysmem(*fdt_addrp, 0); 171 fdt_size = fdt_totalsize(fdt); 172 fdt_size += 4096 * 3; 173 fdt_size = ALIGN(fdt_size + EFI_PAGE_SIZE - 1, EFI_PAGE_SIZE); 174 fdt_pages = fdt_size >> EFI_PAGE_SHIFT; 175 176 /* Safe fdt location is at 127MB */ 177 new_fdt_addr = fdt_ram_start + (127 * 1024 * 1024) + fdt_size; 178 ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, 179 EFI_RUNTIME_SERVICES_DATA, fdt_pages, 180 &new_fdt_addr); 181 if (ret != EFI_SUCCESS) { 182 /* If we can't put it there, put it somewhere */ 183 new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); 184 ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, 185 EFI_RUNTIME_SERVICES_DATA, fdt_pages, 186 &new_fdt_addr); 187 if (ret != EFI_SUCCESS) { 188 printf("ERROR: Failed to reserve space for FDT\n"); 189 goto done; 190 } 191 } 192 193 new_fdt = map_sysmem(new_fdt_addr, fdt_size); 194 memcpy(new_fdt, fdt, fdt_totalsize(fdt)); 195 fdt_set_totalsize(new_fdt, fdt_size); 196 197 *fdt_addrp = new_fdt_addr; 198 *fdt_sizep = fdt_size; 199 done: 200 return ret; 201 } 202 203 static efi_status_t efi_do_enter( 204 efi_handle_t image_handle, struct efi_system_table *st, 205 EFIAPI efi_status_t (*entry)( 206 efi_handle_t image_handle, 207 struct efi_system_table *st)) 208 { 209 efi_status_t ret = EFI_LOAD_ERROR; 210 211 if (entry) 212 ret = entry(image_handle, st); 213 st->boottime->exit(image_handle, ret, 0, NULL); 214 return ret; 215 } 216 217 #ifdef CONFIG_ARM64 218 static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)( 219 efi_handle_t image_handle, struct efi_system_table *st), 220 efi_handle_t image_handle, struct efi_system_table *st) 221 { 222 /* Enable caches again */ 223 dcache_enable(); 224 225 return efi_do_enter(image_handle, st, entry); 226 } 227 #endif 228 229 #ifdef CONFIG_ARMV7_NONSEC 230 static bool is_nonsec; 231 232 static efi_status_t efi_run_in_hyp(EFIAPI efi_status_t (*entry)( 233 efi_handle_t image_handle, struct efi_system_table *st), 234 efi_handle_t image_handle, struct efi_system_table *st) 235 { 236 /* Enable caches again */ 237 dcache_enable(); 238 239 is_nonsec = true; 240 241 return efi_do_enter(image_handle, st, entry); 242 } 243 #endif 244 245 /* 246 * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges 247 * 248 * The mem_rsv entries of the FDT are added to the memory map. Any failures are 249 * ignored because this is not critical and we would rather continue to try to 250 * boot. 251 * 252 * @fdt: Pointer to device tree 253 */ 254 static void efi_carve_out_dt_rsv(void *fdt) 255 { 256 int nr_rsv, i; 257 uint64_t addr, size, pages; 258 259 nr_rsv = fdt_num_mem_rsv(fdt); 260 261 /* Look for an existing entry and add it to the efi mem map. */ 262 for (i = 0; i < nr_rsv; i++) { 263 if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) 264 continue; 265 266 pages = ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT; 267 if (!efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE, 268 false)) 269 printf("FDT memrsv map %d: Failed to add to map\n", i); 270 } 271 } 272 273 static efi_status_t efi_install_fdt(ulong fdt_addr) 274 { 275 bootm_headers_t img = { 0 }; 276 ulong fdt_pages, fdt_size, fdt_start; 277 efi_status_t ret; 278 void *fdt; 279 280 fdt = map_sysmem(fdt_addr, 0); 281 if (fdt_check_header(fdt)) { 282 printf("ERROR: invalid device tree\n"); 283 return EFI_INVALID_PARAMETER; 284 } 285 286 /* Prepare fdt for payload */ 287 ret = copy_fdt(&fdt_addr, &fdt_size); 288 if (ret) 289 return ret; 290 291 unmap_sysmem(fdt); 292 fdt = map_sysmem(fdt_addr, 0); 293 fdt_size = fdt_totalsize(fdt); 294 if (image_setup_libfdt(&img, fdt, 0, NULL)) { 295 printf("ERROR: failed to process device tree\n"); 296 return EFI_LOAD_ERROR; 297 } 298 299 efi_carve_out_dt_rsv(fdt); 300 301 /* Link to it in the efi tables */ 302 ret = efi_install_configuration_table(&efi_guid_fdt, fdt); 303 if (ret != EFI_SUCCESS) 304 return EFI_OUT_OF_RESOURCES; 305 306 /* And reserve the space in the memory map */ 307 fdt_start = fdt_addr; 308 fdt_pages = fdt_size >> EFI_PAGE_SHIFT; 309 310 ret = efi_add_memory_map(fdt_start, fdt_pages, 311 EFI_BOOT_SERVICES_DATA, true); 312 313 return ret; 314 } 315 316 /* 317 * Load an EFI payload into a newly allocated piece of memory, register all 318 * EFI objects it would want to access and jump to it. 319 */ 320 static efi_status_t do_bootefi_exec(void *efi, 321 struct efi_device_path *device_path, 322 struct efi_device_path *image_path) 323 { 324 struct efi_loaded_image loaded_image_info = {}; 325 struct efi_object loaded_image_info_obj = {}; 326 struct efi_object mem_obj = {}; 327 struct efi_device_path *memdp = NULL; 328 efi_status_t ret; 329 330 EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, 331 struct efi_system_table *st); 332 333 /* 334 * Special case for efi payload not loaded from disk, such as 335 * 'bootefi hello' or for example payload loaded directly into 336 * memory via jtag/etc: 337 */ 338 if (!device_path && !image_path) { 339 printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); 340 /* actual addresses filled in after efi_load_pe() */ 341 memdp = efi_dp_from_mem(0, 0, 0); 342 device_path = image_path = memdp; 343 efi_add_handle(&mem_obj); 344 345 ret = efi_add_protocol(mem_obj.handle, &efi_guid_device_path, 346 device_path); 347 if (ret != EFI_SUCCESS) 348 goto exit; 349 } else { 350 assert(device_path && image_path); 351 } 352 353 efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, 354 device_path, image_path); 355 356 /* 357 * gd lives in a fixed register which may get clobbered while we execute 358 * the payload. So save it here and restore it on every callback entry 359 */ 360 efi_save_gd(); 361 362 /* Transfer environment variable bootargs as load options */ 363 set_load_options(&loaded_image_info, "bootargs"); 364 /* Load the EFI payload */ 365 entry = efi_load_pe(efi, &loaded_image_info); 366 if (!entry) { 367 ret = EFI_LOAD_ERROR; 368 goto exit; 369 } 370 371 if (memdp) { 372 struct efi_device_path_memory *mdp = (void *)memdp; 373 mdp->memory_type = loaded_image_info.image_code_type; 374 mdp->start_address = (uintptr_t)loaded_image_info.image_base; 375 mdp->end_address = mdp->start_address + 376 loaded_image_info.image_size; 377 } 378 379 /* we don't support much: */ 380 env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported", 381 "{ro,boot}(blob)0000000000000000"); 382 383 /* Call our payload! */ 384 debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); 385 386 if (setjmp(&loaded_image_info.exit_jmp)) { 387 ret = loaded_image_info.exit_status; 388 goto exit; 389 } 390 391 #ifdef CONFIG_ARM64 392 /* On AArch64 we need to make sure we call our payload in < EL3 */ 393 if (current_el() == 3) { 394 smp_kick_all_cpus(); 395 dcache_disable(); /* flush cache before switch to EL2 */ 396 397 /* Move into EL2 and keep running there */ 398 armv8_switch_to_el2((ulong)entry, 399 (ulong)&loaded_image_info_obj.handle, 400 (ulong)&systab, 0, (ulong)efi_run_in_el2, 401 ES_TO_AARCH64); 402 403 /* Should never reach here, efi exits with longjmp */ 404 while (1) { } 405 } 406 #endif 407 408 #ifdef CONFIG_ARMV7_NONSEC 409 if (armv7_boot_nonsec() && !is_nonsec) { 410 dcache_disable(); /* flush cache before switch to HYP */ 411 412 armv7_init_nonsec(); 413 secure_ram_addr(_do_nonsec_entry)( 414 efi_run_in_hyp, 415 (uintptr_t)entry, 416 (uintptr_t)loaded_image_info_obj.handle, 417 (uintptr_t)&systab); 418 419 /* Should never reach here, efi exits with longjmp */ 420 while (1) { } 421 } 422 #endif 423 424 ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry); 425 426 exit: 427 /* image has returned, loaded-image obj goes *poof*: */ 428 list_del(&loaded_image_info_obj.link); 429 if (mem_obj.handle) 430 list_del(&mem_obj.link); 431 432 return ret; 433 } 434 435 static int do_bootefi_bootmgr_exec(void) 436 { 437 struct efi_device_path *device_path, *file_path; 438 void *addr; 439 efi_status_t r; 440 441 /* 442 * gd lives in a fixed register which may get clobbered while we execute 443 * the payload. So save it here and restore it on every callback entry 444 */ 445 efi_save_gd(); 446 447 addr = efi_bootmgr_load(&device_path, &file_path); 448 if (!addr) 449 return 1; 450 451 printf("## Starting EFI application at %p ...\n", addr); 452 r = do_bootefi_exec(addr, device_path, file_path); 453 printf("## Application terminated, r = %lu\n", 454 r & ~EFI_ERROR_MASK); 455 456 if (r != EFI_SUCCESS) 457 return 1; 458 459 return 0; 460 } 461 462 /* Interpreter command to boot an arbitrary EFI image from memory */ 463 static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 464 { 465 unsigned long addr; 466 char *saddr; 467 efi_status_t r; 468 unsigned long fdt_addr; 469 470 /* Allow unaligned memory access */ 471 allow_unaligned(); 472 473 /* Initialize EFI drivers */ 474 r = efi_init_obj_list(); 475 if (r != EFI_SUCCESS) { 476 printf("Error: Cannot set up EFI drivers, r = %lu\n", 477 r & ~EFI_ERROR_MASK); 478 return CMD_RET_FAILURE; 479 } 480 481 if (argc < 2) 482 return CMD_RET_USAGE; 483 484 if (argc > 2) { 485 fdt_addr = simple_strtoul(argv[2], NULL, 16); 486 if (!fdt_addr && *argv[2] != '0') 487 return CMD_RET_USAGE; 488 /* Install device tree */ 489 r = efi_install_fdt(fdt_addr); 490 if (r != EFI_SUCCESS) { 491 printf("ERROR: failed to install device tree\n"); 492 return CMD_RET_FAILURE; 493 } 494 } else { 495 /* Remove device tree. EFI_NOT_FOUND can be ignored here */ 496 efi_install_configuration_table(&efi_guid_fdt, NULL); 497 printf("WARNING: booting without device tree\n"); 498 } 499 #ifdef CONFIG_CMD_BOOTEFI_HELLO 500 if (!strcmp(argv[1], "hello")) { 501 ulong size = __efi_helloworld_end - __efi_helloworld_begin; 502 503 saddr = env_get("loadaddr"); 504 if (saddr) 505 addr = simple_strtoul(saddr, NULL, 16); 506 else 507 addr = CONFIG_SYS_LOAD_ADDR; 508 memcpy(map_sysmem(addr, size), __efi_helloworld_begin, size); 509 } else 510 #endif 511 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST 512 if (!strcmp(argv[1], "selftest")) { 513 struct efi_loaded_image loaded_image_info = {}; 514 struct efi_object loaded_image_info_obj = {}; 515 516 /* Construct a dummy device path. */ 517 bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 518 (uintptr_t)&efi_selftest, 519 (uintptr_t)&efi_selftest); 520 bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); 521 522 efi_setup_loaded_image(&loaded_image_info, 523 &loaded_image_info_obj, 524 bootefi_device_path, bootefi_image_path); 525 /* 526 * gd lives in a fixed register which may get clobbered while we 527 * execute the payload. So save it here and restore it on every 528 * callback entry 529 */ 530 efi_save_gd(); 531 /* Transfer environment variable efi_selftest as load options */ 532 set_load_options(&loaded_image_info, "efi_selftest"); 533 /* Execute the test */ 534 r = efi_selftest(loaded_image_info_obj.handle, &systab); 535 efi_restore_gd(); 536 free(loaded_image_info.load_options); 537 list_del(&loaded_image_info_obj.link); 538 return r != EFI_SUCCESS; 539 } else 540 #endif 541 if (!strcmp(argv[1], "bootmgr")) { 542 return do_bootefi_bootmgr_exec(); 543 } else { 544 saddr = argv[1]; 545 546 addr = simple_strtoul(saddr, NULL, 16); 547 /* Check that a numeric value was passed */ 548 if (!addr && *saddr != '0') 549 return CMD_RET_USAGE; 550 551 } 552 553 printf("## Starting EFI application at %08lx ...\n", addr); 554 r = do_bootefi_exec(map_sysmem(addr, 0), bootefi_device_path, 555 bootefi_image_path); 556 printf("## Application terminated, r = %lu\n", 557 r & ~EFI_ERROR_MASK); 558 559 if (r != EFI_SUCCESS) 560 return 1; 561 else 562 return 0; 563 } 564 565 #ifdef CONFIG_SYS_LONGHELP 566 static char bootefi_help_text[] = 567 "<image address> [fdt address]\n" 568 " - boot EFI payload stored at address <image address>.\n" 569 " If specified, the device tree located at <fdt address> gets\n" 570 " exposed as EFI configuration table.\n" 571 #ifdef CONFIG_CMD_BOOTEFI_HELLO 572 "bootefi hello\n" 573 " - boot a sample Hello World application stored within U-Boot\n" 574 #endif 575 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST 576 "bootefi selftest [fdt address]\n" 577 " - boot an EFI selftest application stored within U-Boot\n" 578 " Use environment variable efi_selftest to select a single test.\n" 579 " Use 'setenv efi_selftest list' to enumerate all tests.\n" 580 #endif 581 "bootefi bootmgr [fdt addr]\n" 582 " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n" 583 "\n" 584 " If specified, the device tree located at <fdt address> gets\n" 585 " exposed as EFI configuration table.\n"; 586 #endif 587 588 U_BOOT_CMD( 589 bootefi, 3, 0, do_bootefi, 590 "Boots an EFI payload from memory", 591 bootefi_help_text 592 ); 593 594 void efi_set_bootdev(const char *dev, const char *devnr, const char *path) 595 { 596 char filename[32] = { 0 }; /* dp->str is u16[32] long */ 597 char *s; 598 599 if (strcmp(dev, "Net")) { 600 struct blk_desc *desc; 601 disk_partition_t fs_partition; 602 int part; 603 604 part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition, 605 1); 606 if (part < 0) 607 return; 608 609 bootefi_device_path = efi_dp_from_part(desc, part); 610 } else { 611 #ifdef CONFIG_NET 612 bootefi_device_path = efi_dp_from_eth(); 613 #endif 614 } 615 616 if (!path) 617 return; 618 619 if (strcmp(dev, "Net")) { 620 /* Add leading / to fs paths, because they're absolute */ 621 snprintf(filename, sizeof(filename), "/%s", path); 622 } else { 623 snprintf(filename, sizeof(filename), "%s", path); 624 } 625 /* DOS style file path: */ 626 s = filename; 627 while ((s = strchr(s, '/'))) 628 *s++ = '\\'; 629 bootefi_image_path = efi_dp_from_file(NULL, 0, filename); 630 } 631