bootmeth_efi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Bootmethod for distro boot via EFI
  4. *
  5. * Copyright 2021 Google LLC
  6. * Written by Simon Glass <sjg@chromium.org>
  7. */
  8. #define LOG_CATEGORY UCLASS_BOOTSTD
  9. #include <common.h>
  10. #include <bootdev.h>
  11. #include <bootflow.h>
  12. #include <bootmeth.h>
  13. #include <command.h>
  14. #include <dm.h>
  15. #include <efi_loader.h>
  16. #include <fs.h>
  17. #include <malloc.h>
  18. #include <mapmem.h>
  19. #include <mmc.h>
  20. #include <net.h>
  21. #include <pxe_utils.h>
  22. #include <linux/sizes.h>
  23. #define EFI_DIRNAME "efi/boot/"
  24. /**
  25. * get_efi_leafname() - Get the leaf name for the EFI file we expect
  26. *
  27. * @str: Place to put leaf name for this architecture, e.g. "bootaa64.efi".
  28. * Must have at least 16 bytes of space
  29. * @max_len: Length of @str, must be >=16
  30. */
  31. static int get_efi_leafname(char *str, int max_len)
  32. {
  33. const char *base;
  34. if (max_len < 16)
  35. return log_msg_ret("spc", -ENOSPC);
  36. if (IS_ENABLED(CONFIG_ARM64))
  37. base = "bootaa64";
  38. else if (IS_ENABLED(CONFIG_ARM))
  39. base = "bootarm";
  40. else if (IS_ENABLED(CONFIG_X86_RUN_32BIT))
  41. base = "bootia32";
  42. else if (IS_ENABLED(CONFIG_X86_RUN_64BIT))
  43. base = "bootx64";
  44. else if (IS_ENABLED(CONFIG_ARCH_RV32I))
  45. base = "bootriscv32";
  46. else if (IS_ENABLED(CONFIG_ARCH_RV64I))
  47. base = "bootriscv64";
  48. else if (IS_ENABLED(CONFIG_SANDBOX))
  49. base = "bootsbox";
  50. else
  51. return -EINVAL;
  52. strcpy(str, base);
  53. strcat(str, ".efi");
  54. return 0;
  55. }
  56. static int get_efi_pxe_arch(void)
  57. {
  58. /* http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml */
  59. if (IS_ENABLED(CONFIG_ARM64))
  60. return 0xb;
  61. else if (IS_ENABLED(CONFIG_ARM))
  62. return 0xa;
  63. else if (IS_ENABLED(CONFIG_X86_64))
  64. return 0x6;
  65. else if (IS_ENABLED(CONFIG_X86))
  66. return 0x7;
  67. else if (IS_ENABLED(CONFIG_ARCH_RV32I))
  68. return 0x19;
  69. else if (IS_ENABLED(CONFIG_ARCH_RV64I))
  70. return 0x1b;
  71. else if (IS_ENABLED(CONFIG_SANDBOX))
  72. return 0; /* not used */
  73. return -EINVAL;
  74. }
  75. static int get_efi_pxe_vci(char *str, int max_len)
  76. {
  77. int ret;
  78. ret = get_efi_pxe_arch();
  79. if (ret < 0)
  80. return ret;
  81. snprintf(str, max_len, "PXEClient:Arch:%05x:UNDI:003000", ret);
  82. return 0;
  83. }
  84. /**
  85. * bootmeth_uses_network() - check if the media device is Ethernet
  86. *
  87. * @bflow: Bootflow to check
  88. * Returns: true if the media device is Ethernet, else false
  89. */
  90. static bool bootmeth_uses_network(struct bootflow *bflow)
  91. {
  92. const struct udevice *media = dev_get_parent(bflow->dev);
  93. return IS_ENABLED(CONFIG_CMD_DHCP) &&
  94. device_get_uclass_id(media) == UCLASS_ETH;
  95. }
  96. static void set_efi_bootdev(struct blk_desc *desc, struct bootflow *bflow)
  97. {
  98. const struct udevice *media_dev;
  99. int size = bflow->size;
  100. const char *dev_name;
  101. char devnum_str[9];
  102. char dirname[200];
  103. char *last_slash;
  104. /*
  105. * This is a horrible hack to tell EFI about this boot device. Once we
  106. * unify EFI with the rest of U-Boot we can clean this up. The same hack
  107. * exists in multiple places, e.g. in the fs, tftp and load commands.
  108. *
  109. * Once we can clean up the EFI code to make proper use of driver model,
  110. * this can go away.
  111. */
  112. media_dev = dev_get_parent(bflow->dev);
  113. snprintf(devnum_str, sizeof(devnum_str), "%x:%x",
  114. desc ? desc->devnum : dev_seq(media_dev),
  115. bflow->part);
  116. strlcpy(dirname, bflow->fname, sizeof(dirname));
  117. last_slash = strrchr(dirname, '/');
  118. if (last_slash)
  119. *last_slash = '\0';
  120. log_debug("setting bootdev %s, %s, %s, %p, %x\n",
  121. dev_get_uclass_name(media_dev), devnum_str, bflow->fname,
  122. bflow->buf, size);
  123. dev_name = device_get_uclass_id(media_dev) == UCLASS_MASS_STORAGE ?
  124. "usb" : dev_get_uclass_name(media_dev);
  125. efi_set_bootdev(dev_name, devnum_str, bflow->fname, bflow->buf, size);
  126. }
  127. static int efiload_read_file(struct bootflow *bflow, ulong addr)
  128. {
  129. struct blk_desc *desc = NULL;
  130. loff_t bytes_read;
  131. int ret;
  132. if (bflow->blk)
  133. desc = dev_get_uclass_plat(bflow->blk);
  134. ret = bootmeth_setup_fs(bflow, desc);
  135. if (ret)
  136. return log_msg_ret("set", ret);
  137. ret = fs_read(bflow->fname, addr, 0, bflow->size, &bytes_read);
  138. if (ret)
  139. return log_msg_ret("read", ret);
  140. bflow->buf = map_sysmem(addr, bflow->size);
  141. set_efi_bootdev(desc, bflow);
  142. return 0;
  143. }
  144. static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
  145. {
  146. /* This only works on block and network devices */
  147. if (bootflow_iter_check_blk(iter) && bootflow_iter_check_net(iter))
  148. return log_msg_ret("blk", -ENOTSUPP);
  149. /* This works on block devices and network devices */
  150. if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
  151. return log_msg_ret("pxe", -ENOTSUPP);
  152. return 0;
  153. }
  154. /**
  155. * distro_efi_get_fdt_name() - Get the filename for reading the .dtb file
  156. *
  157. * @fname: Place to put filename
  158. * @size: Max size of filename
  159. * @seq: Sequence number, to cycle through options (0=first)
  160. * Returns: 0 on success, -ENOENT if the "fdtfile" env var does not exist,
  161. * -EINVAL if there are no more options, -EALREADY if the control FDT should be
  162. * used
  163. */
  164. static int distro_efi_get_fdt_name(char *fname, int size, int seq)
  165. {
  166. const char *fdt_fname;
  167. const char *prefix;
  168. /* select the prefix */
  169. switch (seq) {
  170. case 0:
  171. /* this is the default */
  172. prefix = "/dtb";
  173. break;
  174. case 1:
  175. prefix = "";
  176. break;
  177. case 2:
  178. prefix = "/dtb/current";
  179. break;
  180. default:
  181. return log_msg_ret("pref", -EINVAL);
  182. }
  183. fdt_fname = env_get("fdtfile");
  184. if (fdt_fname) {
  185. snprintf(fname, size, "%s/%s", prefix, fdt_fname);
  186. log_debug("Using device tree: %s\n", fname);
  187. } else if (IS_ENABLED(CONFIG_OF_HAS_PRIOR_STAGE)) {
  188. strcpy(fname, "<prior>");
  189. return log_msg_ret("pref", -EALREADY);
  190. /* Use this fallback only for 32-bit ARM */
  191. } else if (IS_ENABLED(CONFIG_ARM) && !IS_ENABLED(CONFIG_ARM64)) {
  192. const char *soc = env_get("soc");
  193. const char *board = env_get("board");
  194. const char *boardver = env_get("boardver");
  195. /* cf the code in label_boot() which seems very complex */
  196. snprintf(fname, size, "%s/%s%s%s%s.dtb", prefix,
  197. soc ? soc : "", soc ? "-" : "", board ? board : "",
  198. boardver ? boardver : "");
  199. log_debug("Using default device tree: %s\n", fname);
  200. } else {
  201. return log_msg_ret("env", -ENOENT);
  202. }
  203. return 0;
  204. }
  205. /*
  206. * distro_efi_try_bootflow_files() - Check that files are present
  207. *
  208. * This reads any FDT file and checks whether the bootflow file is present, for
  209. * later reading. We avoid reading the bootflow now, since it is likely large,
  210. * it may take a long time and we want to avoid needing to allocate memory for
  211. * it
  212. *
  213. * @dev: bootmeth device to use
  214. * @bflow: bootflow to update
  215. */
  216. static int distro_efi_try_bootflow_files(struct udevice *dev,
  217. struct bootflow *bflow)
  218. {
  219. struct blk_desc *desc = NULL;
  220. ulong fdt_addr, size;
  221. char fname[256];
  222. int ret, seq;
  223. /* We require a partition table */
  224. if (!bflow->part)
  225. return -ENOENT;
  226. strcpy(fname, EFI_DIRNAME);
  227. ret = get_efi_leafname(fname + strlen(fname),
  228. sizeof(fname) - strlen(fname));
  229. if (ret)
  230. return log_msg_ret("leaf", ret);
  231. if (bflow->blk)
  232. desc = dev_get_uclass_plat(bflow->blk);
  233. ret = bootmeth_try_file(bflow, desc, NULL, fname);
  234. if (ret)
  235. return log_msg_ret("try", ret);
  236. /* Since we can access the file, let's call it ready */
  237. bflow->state = BOOTFLOWST_READY;
  238. fdt_addr = env_get_hex("fdt_addr_r", 0);
  239. /* try the various available names */
  240. ret = -ENOENT;
  241. *fname = '\0';
  242. for (seq = 0; ret == -ENOENT; seq++) {
  243. ret = distro_efi_get_fdt_name(fname, sizeof(fname), seq);
  244. if (ret == -EALREADY)
  245. bflow->flags = BOOTFLOWF_USE_PRIOR_FDT;
  246. if (!ret) {
  247. /* Limit FDT files to 4MB */
  248. size = SZ_4M;
  249. ret = bootmeth_common_read_file(dev, bflow, fname,
  250. fdt_addr, &size);
  251. }
  252. }
  253. if (*fname) {
  254. bflow->fdt_fname = strdup(fname);
  255. if (!bflow->fdt_fname)
  256. return log_msg_ret("fil", -ENOMEM);
  257. }
  258. if (!ret) {
  259. bflow->fdt_size = size;
  260. bflow->fdt_addr = fdt_addr;
  261. /*
  262. * TODO: Apply extension overlay
  263. *
  264. * Here we need to load and apply the extension overlay. This is
  265. * not implemented. See do_extension_apply(). The extension
  266. * stuff needs an implementation in boot/extension.c so it is
  267. * separate from the command code. Really the extension stuff
  268. * should use the device tree and a uclass / driver interface
  269. * rather than implementing its own list
  270. */
  271. } else {
  272. log_debug("No device tree available\n");
  273. }
  274. return 0;
  275. }
  276. static int distro_efi_read_bootflow_net(struct bootflow *bflow)
  277. {
  278. char file_addr[17], fname[256];
  279. char *tftp_argv[] = {"tftp", file_addr, fname, NULL};
  280. struct cmd_tbl cmdtp = {}; /* dummy */
  281. const char *addr_str, *fdt_addr_str;
  282. int ret, arch, size;
  283. ulong addr, fdt_addr;
  284. char str[36];
  285. ret = get_efi_pxe_vci(str, sizeof(str));
  286. if (ret)
  287. return log_msg_ret("vci", ret);
  288. ret = get_efi_pxe_arch();
  289. if (ret < 0)
  290. return log_msg_ret("arc", ret);
  291. arch = ret;
  292. ret = env_set("bootp_vci", str);
  293. if (ret)
  294. return log_msg_ret("vcs", ret);
  295. ret = env_set_ulong("bootp_arch", arch);
  296. if (ret)
  297. return log_msg_ret("ars", ret);
  298. /* figure out the load address */
  299. addr_str = env_get("kernel_addr_r");
  300. addr = addr_str ? hextoul(addr_str, NULL) : image_load_addr;
  301. /* clear any previous bootfile */
  302. env_set("bootfile", NULL);
  303. /* read the kernel */
  304. ret = dhcp_run(addr, NULL, true);
  305. if (ret)
  306. return log_msg_ret("dhc", ret);
  307. size = env_get_hex("filesize", -1);
  308. if (size <= 0)
  309. return log_msg_ret("sz", -EINVAL);
  310. bflow->size = size;
  311. /* do the hideous EFI hack */
  312. efi_set_bootdev("Net", "", bflow->fname, map_sysmem(addr, 0),
  313. bflow->size);
  314. /* read the DT file also */
  315. fdt_addr_str = env_get("fdt_addr_r");
  316. if (!fdt_addr_str)
  317. return log_msg_ret("fdt", -EINVAL);
  318. fdt_addr = hextoul(fdt_addr_str, NULL);
  319. sprintf(file_addr, "%lx", fdt_addr);
  320. /* We only allow the first prefix with PXE */
  321. ret = distro_efi_get_fdt_name(fname, sizeof(fname), 0);
  322. if (ret)
  323. return log_msg_ret("nam", ret);
  324. bflow->fdt_fname = strdup(fname);
  325. if (!bflow->fdt_fname)
  326. return log_msg_ret("fil", -ENOMEM);
  327. if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) {
  328. bflow->fdt_size = env_get_hex("filesize", 0);
  329. bflow->fdt_addr = fdt_addr;
  330. } else {
  331. log_debug("No device tree available\n");
  332. }
  333. bflow->state = BOOTFLOWST_READY;
  334. return 0;
  335. }
  336. static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow)
  337. {
  338. int ret;
  339. if (bootmeth_uses_network(bflow)) {
  340. /* we only support reading from one device, so ignore 'dev' */
  341. ret = distro_efi_read_bootflow_net(bflow);
  342. if (ret)
  343. return log_msg_ret("net", ret);
  344. } else {
  345. ret = distro_efi_try_bootflow_files(dev, bflow);
  346. if (ret)
  347. return log_msg_ret("blk", ret);
  348. }
  349. return 0;
  350. }
  351. static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow)
  352. {
  353. ulong kernel, fdt;
  354. char cmd[50];
  355. int ret;
  356. kernel = env_get_hex("kernel_addr_r", 0);
  357. if (!bootmeth_uses_network(bflow)) {
  358. ret = efiload_read_file(bflow, kernel);
  359. if (ret)
  360. return log_msg_ret("read", ret);
  361. /*
  362. * use the provided device tree if available, else fall back to
  363. * the control FDT
  364. */
  365. if (bflow->fdt_fname)
  366. fdt = bflow->fdt_addr;
  367. else
  368. fdt = (ulong)map_to_sysmem(gd->fdt_blob);
  369. } else {
  370. /*
  371. * This doesn't actually work for network devices:
  372. *
  373. * do_bootefi_image() No UEFI binary known at 0x02080000
  374. *
  375. * But this is the same behaviour for distro boot, so it can be
  376. * fixed here.
  377. */
  378. fdt = env_get_hex("fdt_addr_r", 0);
  379. }
  380. /*
  381. * At some point we can add a real interface to bootefi so we can call
  382. * this directly. For now, go through the CLI, like distro boot.
  383. */
  384. snprintf(cmd, sizeof(cmd), "bootefi %lx %lx", kernel, fdt);
  385. if (run_command(cmd, 0))
  386. return log_msg_ret("run", -EINVAL);
  387. return 0;
  388. }
  389. static int distro_bootmeth_efi_bind(struct udevice *dev)
  390. {
  391. struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
  392. plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ?
  393. "EFI boot from an .efi file" : "EFI";
  394. return 0;
  395. }
  396. static struct bootmeth_ops distro_efi_bootmeth_ops = {
  397. .check = distro_efi_check,
  398. .read_bootflow = distro_efi_read_bootflow,
  399. .read_file = bootmeth_common_read_file,
  400. .boot = distro_efi_boot,
  401. };
  402. static const struct udevice_id distro_efi_bootmeth_ids[] = {
  403. { .compatible = "u-boot,distro-efi" },
  404. { }
  405. };
  406. U_BOOT_DRIVER(bootmeth_efi) = {
  407. .name = "bootmeth_efi",
  408. .id = UCLASS_BOOTMETH,
  409. .of_match = distro_efi_bootmeth_ids,
  410. .ops = &distro_efi_bootmeth_ops,
  411. .bind = distro_bootmeth_efi_bind,
  412. };