[PATCH v2 3/5] bootmeth: efi: use the firmware-owned devicetree

Carlo Caione <[email protected]>
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <[email protected]>
When a firmware-owned devicetree source is configured, stage it at the
same fdt_addr_r value used by the normal EFI bootmeth fallback and pass it
through bflow->fdt_addr to efi_install_fdt().

Use the shared helper in both disk and network paths. Only -ENOENT, meaning
that no source is configured, permits the existing ESP, network or
prior-stage fallback. Any failure after a source is configured ends that
bootflow.

The firmware-owned devicetree is complete and authoritative, so do not
apply extension-board overlays on top of it; those combinations belong in
the FIT.

Signed-off-by: Carlo Caione <[email protected]>
---
 boot/bootmeth_efi.c | 45 +++++++++++++++++++++++++++++++++++++++------
 1 file changed, 39 insertions(+), 6 deletions(-)

diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index e187dc39912..469a07e9540 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -17,6 +17,7 @@
 #include <efi_loader.h>
 #include <env.h>
 #include <extension_board.h>
+#include <firmware_fdt.h>
 #include <fs.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -100,7 +101,7 @@ static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
 static int distro_efi_try_bootflow_files(struct udevice *dev,
 					 struct bootflow *bflow)
 {
-	ulong fdt_addr, size, overlay_addr;
+	ulong fdt_addr, fw_fdt_size, size, overlay_addr;
 	const struct extension *extension;
 	struct fdt_header *working_fdt;
 	struct blk_desc *desc = NULL;
@@ -130,6 +131,22 @@ static int distro_efi_try_bootflow_files(struct udevice *dev,
 
 	fdt_addr = env_get_hex("fdt_addr_r", 0);
 
+	/*
+	 * A staged firmware-owned devicetree is complete and authoritative,
+	 * so return without considering any other devicetree source. The
+	 * extension overlays below are deliberately not applied on top:
+	 * such combinations belong in the FIT as configurations.
+	 */
+	ret = efi_stage_firmware_fdt(fdt_addr, &fw_fdt_size,
+				     &bflow->fdt_fname);
+	if (!ret) {
+		bflow->fdt_size = fw_fdt_size;
+		bflow->fdt_addr = fdt_addr;
+		return 0;
+	}
+	if (ret != -ENOENT)
+		return log_msg_ret("fwf", ret);
+
 	/* try the various available names */
 	ret = -ENOENT;
 	*fname = '\0';
@@ -222,9 +239,9 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow)
 	char file_addr[17], fname[256];
 	char *tftp_argv[] = {"tftp", file_addr, fname, NULL};
 	struct cmd_tbl cmdtp = {};	/* dummy */
-	const char *addr_str, *fdt_addr_str, *bootfile_name;
+	const char *addr_str, *bootfile_name;
 	int ret, arch, size;
-	ulong addr, fdt_addr;
+	ulong addr, fdt_addr, fw_fdt_size;
 	char str[36];
 
 	ret = get_efi_pxe_vci(str, sizeof(str));
@@ -268,6 +285,24 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow)
 	if (!bflow->fname)
 		return log_msg_ret("fi0", -ENOMEM);
 
+	/*
+	 * Read fdt_addr_r once so the firmware-FDT source and network fallback
+	 * below stage at the same address. A configured firmware-owned
+	 * devicetree outranks the network-provided one (and the prior-stage /
+	 * built-in devicetree below), so a DHCP/TFTP server cannot replace it.
+	 */
+	fdt_addr = env_get_hex("fdt_addr_r", 0);
+	ret = efi_stage_firmware_fdt(fdt_addr, &fw_fdt_size,
+				     &bflow->fdt_fname);
+	if (!ret) {
+		bflow->fdt_size = fw_fdt_size;
+		bflow->fdt_addr = fdt_addr;
+		bflow->state = BOOTFLOWST_READY;
+		return 0;
+	}
+	if (ret != -ENOENT)
+		return log_msg_ret("fwf", ret);
+
 	/* read the DT file also */
 	ret = efi_get_distro_fdt_name(fname, sizeof(fname), 0);
 	if (ret == -EALREADY) {
@@ -279,10 +314,8 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow)
 		return log_msg_ret("nam", ret);
 	}
 
-	fdt_addr_str = env_get("fdt_addr_r");
-	if (!fdt_addr_str)
+	if (!fdt_addr)
 		return log_msg_ret("fdt", -EINVAL);
-	fdt_addr = hextoul(fdt_addr_str, NULL);
 	sprintf(file_addr, "%lx", fdt_addr);
 
 	bflow->fdt_fname = strdup(fname);

-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.