bootefi.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. * EFI application loader
  3. *
  4. * Copyright (c) 2016 Alexander Graf
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <common.h>
  9. #include <command.h>
  10. #include <dm.h>
  11. #include <efi_loader.h>
  12. #include <errno.h>
  13. #include <libfdt.h>
  14. #include <libfdt_env.h>
  15. #include <memalign.h>
  16. #include <asm/global_data.h>
  17. #include <asm-generic/sections.h>
  18. #include <linux/linkage.h>
  19. DECLARE_GLOBAL_DATA_PTR;
  20. static uint8_t efi_obj_list_initalized;
  21. /*
  22. * When booting using the "bootefi" command, we don't know which
  23. * physical device the file came from. So we create a pseudo-device
  24. * called "bootefi" with the device path /bootefi.
  25. *
  26. * In addition to the originating device we also declare the file path
  27. * of "bootefi" based loads to be /bootefi.
  28. */
  29. static struct efi_device_path_file_path bootefi_image_path[] = {
  30. {
  31. .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
  32. .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
  33. .dp.length = sizeof(bootefi_image_path[0]),
  34. .str = { 'b','o','o','t','e','f','i' },
  35. }, {
  36. .dp.type = DEVICE_PATH_TYPE_END,
  37. .dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
  38. .dp.length = sizeof(bootefi_image_path[0]),
  39. }
  40. };
  41. static struct efi_device_path_file_path bootefi_device_path[] = {
  42. {
  43. .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
  44. .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
  45. .dp.length = sizeof(bootefi_image_path[0]),
  46. .str = { 'b','o','o','t','e','f','i' },
  47. }, {
  48. .dp.type = DEVICE_PATH_TYPE_END,
  49. .dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
  50. .dp.length = sizeof(bootefi_image_path[0]),
  51. }
  52. };
  53. /* The EFI loaded_image interface for the image executed via "bootefi" */
  54. static struct efi_loaded_image loaded_image_info = {
  55. .device_handle = bootefi_device_path,
  56. .file_path = bootefi_image_path,
  57. };
  58. /* The EFI object struct for the image executed via "bootefi" */
  59. static struct efi_object loaded_image_info_obj = {
  60. .handle = &loaded_image_info,
  61. .protocols = {
  62. {
  63. /*
  64. * When asking for the loaded_image interface, just
  65. * return handle which points to loaded_image_info
  66. */
  67. .guid = &efi_guid_loaded_image,
  68. .protocol_interface = &loaded_image_info,
  69. },
  70. {
  71. /*
  72. * When asking for the device path interface, return
  73. * bootefi_device_path
  74. */
  75. .guid = &efi_guid_device_path,
  76. .protocol_interface = bootefi_device_path,
  77. },
  78. {
  79. .guid = &efi_guid_console_control,
  80. .protocol_interface = (void *) &efi_console_control
  81. },
  82. {
  83. .guid = &efi_guid_device_path_to_text_protocol,
  84. .protocol_interface = (void *) &efi_device_path_to_text
  85. },
  86. },
  87. };
  88. /* The EFI object struct for the device the "bootefi" image was loaded from */
  89. static struct efi_object bootefi_device_obj = {
  90. .handle = bootefi_device_path,
  91. .protocols = {
  92. {
  93. /* When asking for the device path interface, return
  94. * bootefi_device_path */
  95. .guid = &efi_guid_device_path,
  96. .protocol_interface = bootefi_device_path
  97. }
  98. },
  99. };
  100. /* Initialize and populate EFI object list */
  101. static void efi_init_obj_list(void)
  102. {
  103. efi_obj_list_initalized = 1;
  104. list_add_tail(&loaded_image_info_obj.link, &efi_obj_list);
  105. list_add_tail(&bootefi_device_obj.link, &efi_obj_list);
  106. efi_console_register();
  107. #ifdef CONFIG_PARTITIONS
  108. efi_disk_register();
  109. #endif
  110. #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO)
  111. efi_gop_register();
  112. #endif
  113. #ifdef CONFIG_NET
  114. void *nethandle = loaded_image_info.device_handle;
  115. efi_net_register(&nethandle);
  116. if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6))
  117. loaded_image_info.device_handle = nethandle;
  118. else
  119. loaded_image_info.device_handle = bootefi_device_path;
  120. #endif
  121. #ifdef CONFIG_GENERATE_SMBIOS_TABLE
  122. efi_smbios_register();
  123. #endif
  124. /* Initialize EFI runtime services */
  125. efi_reset_system_init();
  126. efi_get_time_init();
  127. }
  128. static void *copy_fdt(void *fdt)
  129. {
  130. u64 fdt_size = fdt_totalsize(fdt);
  131. unsigned long fdt_ram_start = -1L, fdt_pages;
  132. u64 new_fdt_addr;
  133. void *new_fdt;
  134. int i;
  135. for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
  136. u64 ram_start = gd->bd->bi_dram[i].start;
  137. u64 ram_size = gd->bd->bi_dram[i].size;
  138. if (!ram_size)
  139. continue;
  140. if (ram_start < fdt_ram_start)
  141. fdt_ram_start = ram_start;
  142. }
  143. /* Give us at least 4kb breathing room */
  144. fdt_size = ALIGN(fdt_size + 4096, EFI_PAGE_SIZE);
  145. fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
  146. /* Safe fdt location is at 128MB */
  147. new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size;
  148. if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages,
  149. &new_fdt_addr) != EFI_SUCCESS) {
  150. /* If we can't put it there, put it somewhere */
  151. new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
  152. if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages,
  153. &new_fdt_addr) != EFI_SUCCESS) {
  154. printf("ERROR: Failed to reserve space for FDT\n");
  155. return NULL;
  156. }
  157. }
  158. new_fdt = (void*)(ulong)new_fdt_addr;
  159. memcpy(new_fdt, fdt, fdt_totalsize(fdt));
  160. fdt_set_totalsize(new_fdt, fdt_size);
  161. return new_fdt;
  162. }
  163. static ulong efi_do_enter(void *image_handle,
  164. struct efi_system_table *st,
  165. asmlinkage ulong (*entry)(void *image_handle,
  166. struct efi_system_table *st))
  167. {
  168. efi_status_t ret = EFI_LOAD_ERROR;
  169. if (entry)
  170. ret = entry(image_handle, st);
  171. st->boottime->exit(image_handle, ret, 0, NULL);
  172. return ret;
  173. }
  174. #ifdef CONFIG_ARM64
  175. static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)(
  176. void *image_handle, struct efi_system_table *st),
  177. void *image_handle, struct efi_system_table *st)
  178. {
  179. /* Enable caches again */
  180. dcache_enable();
  181. return efi_do_enter(image_handle, st, entry);
  182. }
  183. #endif
  184. /*
  185. * Load an EFI payload into a newly allocated piece of memory, register all
  186. * EFI objects it would want to access and jump to it.
  187. */
  188. static unsigned long do_bootefi_exec(void *efi, void *fdt)
  189. {
  190. ulong (*entry)(void *image_handle, struct efi_system_table *st)
  191. asmlinkage;
  192. ulong fdt_pages, fdt_size, fdt_start, fdt_end;
  193. const efi_guid_t fdt_guid = EFI_FDT_GUID;
  194. bootm_headers_t img = { 0 };
  195. /*
  196. * gd lives in a fixed register which may get clobbered while we execute
  197. * the payload. So save it here and restore it on every callback entry
  198. */
  199. efi_save_gd();
  200. if (fdt && !fdt_check_header(fdt)) {
  201. /* Prepare fdt for payload */
  202. fdt = copy_fdt(fdt);
  203. if (image_setup_libfdt(&img, fdt, 0, NULL)) {
  204. printf("ERROR: Failed to process device tree\n");
  205. return -EINVAL;
  206. }
  207. /* Link to it in the efi tables */
  208. efi_install_configuration_table(&fdt_guid, fdt);
  209. /* And reserve the space in the memory map */
  210. fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK;
  211. fdt_end = ((ulong)fdt) + fdt_totalsize(fdt);
  212. fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
  213. fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
  214. /* Give a bootloader the chance to modify the device tree */
  215. fdt_pages += 2;
  216. efi_add_memory_map(fdt_start, fdt_pages,
  217. EFI_BOOT_SERVICES_DATA, true);
  218. } else {
  219. printf("WARNING: Invalid device tree, expect boot to fail\n");
  220. efi_install_configuration_table(&fdt_guid, NULL);
  221. }
  222. /* Load the EFI payload */
  223. entry = efi_load_pe(efi, &loaded_image_info);
  224. if (!entry)
  225. return -ENOENT;
  226. /* Initialize and populate EFI object list */
  227. if (!efi_obj_list_initalized)
  228. efi_init_obj_list();
  229. /* Call our payload! */
  230. debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
  231. if (setjmp(&loaded_image_info.exit_jmp)) {
  232. return loaded_image_info.exit_status;
  233. }
  234. #ifdef CONFIG_ARM64
  235. /* On AArch64 we need to make sure we call our payload in < EL3 */
  236. if (current_el() == 3) {
  237. smp_kick_all_cpus();
  238. dcache_disable(); /* flush cache before switch to EL2 */
  239. /* Move into EL2 and keep running there */
  240. armv8_switch_to_el2((ulong)entry, (ulong)&loaded_image_info,
  241. (ulong)&systab, 0, (ulong)efi_run_in_el2,
  242. ES_TO_AARCH64);
  243. /* Should never reach here, efi exits with longjmp */
  244. while (1) { }
  245. }
  246. #endif
  247. return efi_do_enter(&loaded_image_info, &systab, entry);
  248. }
  249. /* Interpreter command to boot an arbitrary EFI image from memory */
  250. static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  251. {
  252. char *saddr, *sfdt;
  253. unsigned long addr, fdt_addr = 0;
  254. unsigned long r;
  255. if (argc < 2)
  256. return CMD_RET_USAGE;
  257. #ifdef CONFIG_CMD_BOOTEFI_HELLO
  258. if (!strcmp(argv[1], "hello")) {
  259. ulong size = __efi_helloworld_end - __efi_helloworld_begin;
  260. saddr = env_get("loadaddr");
  261. if (saddr)
  262. addr = simple_strtoul(saddr, NULL, 16);
  263. else
  264. addr = CONFIG_SYS_LOAD_ADDR;
  265. memcpy((char *)addr, __efi_helloworld_begin, size);
  266. } else
  267. #endif
  268. #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
  269. if (!strcmp(argv[1], "selftest")) {
  270. /*
  271. * gd lives in a fixed register which may get clobbered while we
  272. * execute the payload. So save it here and restore it on every
  273. * callback entry
  274. */
  275. efi_save_gd();
  276. /* Initialize and populate EFI object list */
  277. if (!efi_obj_list_initalized)
  278. efi_init_obj_list();
  279. loaded_image_info.device_handle = bootefi_device_path;
  280. loaded_image_info.file_path = bootefi_image_path;
  281. return efi_selftest(&loaded_image_info, &systab);
  282. } else
  283. #endif
  284. {
  285. saddr = argv[1];
  286. addr = simple_strtoul(saddr, NULL, 16);
  287. if (argc > 2) {
  288. sfdt = argv[2];
  289. fdt_addr = simple_strtoul(sfdt, NULL, 16);
  290. }
  291. }
  292. printf("## Starting EFI application at %08lx ...\n", addr);
  293. r = do_bootefi_exec((void *)addr, (void*)fdt_addr);
  294. printf("## Application terminated, r = %lu\n",
  295. r & ~EFI_ERROR_MASK);
  296. if (r != EFI_SUCCESS)
  297. return 1;
  298. else
  299. return 0;
  300. }
  301. #ifdef CONFIG_SYS_LONGHELP
  302. static char bootefi_help_text[] =
  303. "<image address> [fdt address]\n"
  304. " - boot EFI payload stored at address <image address>.\n"
  305. " If specified, the device tree located at <fdt address> gets\n"
  306. " exposed as EFI configuration table.\n"
  307. #ifdef CONFIG_CMD_BOOTEFI_HELLO
  308. "bootefi hello\n"
  309. " - boot a sample Hello World application stored within U-Boot\n"
  310. #endif
  311. #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
  312. "bootefi selftest\n"
  313. " - boot an EFI selftest application stored within U-Boot\n"
  314. #endif
  315. ;
  316. #endif
  317. U_BOOT_CMD(
  318. bootefi, 3, 0, do_bootefi,
  319. "Boots an EFI payload from memory",
  320. bootefi_help_text
  321. );
  322. void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
  323. {
  324. __maybe_unused struct blk_desc *desc;
  325. char devname[32] = { 0 }; /* dp->str is u16[32] long */
  326. char *colon, *s;
  327. #if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION)
  328. desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
  329. #endif
  330. #ifdef CONFIG_BLK
  331. if (desc) {
  332. snprintf(devname, sizeof(devname), "%s", desc->bdev->name);
  333. } else
  334. #endif
  335. {
  336. /* Assemble the condensed device name we use in efi_disk.c */
  337. snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
  338. }
  339. colon = strchr(devname, ':');
  340. #if CONFIG_IS_ENABLED(ISO_PARTITION)
  341. /* For ISOs we create partition block devices */
  342. if (desc && (desc->type != DEV_TYPE_UNKNOWN) &&
  343. (desc->part_type == PART_TYPE_ISO)) {
  344. if (!colon)
  345. snprintf(devname, sizeof(devname), "%s:1", devname);
  346. colon = NULL;
  347. }
  348. #endif
  349. if (colon)
  350. *colon = '\0';
  351. /* Patch bootefi_device_path to the target device */
  352. memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str));
  353. ascii2unicode(bootefi_device_path[0].str, devname);
  354. /* Patch bootefi_image_path to the target file path */
  355. memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
  356. if (strcmp(dev, "Net")) {
  357. /* Add leading / to fs paths, because they're absolute */
  358. snprintf(devname, sizeof(devname), "/%s", path);
  359. } else {
  360. snprintf(devname, sizeof(devname), "%s", path);
  361. }
  362. /* DOS style file path: */
  363. s = devname;
  364. while ((s = strchr(s, '/')))
  365. *s++ = '\\';
  366. ascii2unicode(bootefi_image_path[0].str, devname);
  367. }