[PATCH 17/31] passage: Support a control devicetree

Simon Glass sjg at chromium.org
Mon Nov 1 02:17:19 CET 2021


Add support for accepting a control devicetree from the incoming passage.
This allows SPL (or some other program) to pass a devicetree to U-Boot
proper in a standard way.

Pass the devicetree through the early parts of U-Boot needs a list care.
If it is in the bloblist, there is no need to reserve a separate space for
it to relocate into, since it will be relocated as part of the bloblist.

Also we must init the bloblist before calling fdtdec_setup(), so the
devicetree can be read from the bloblist*. This is not normally safe,
since malloc() is be called by bloblist_init() if CONFIG_BLOBLIST_ALLOC
is enabled. But in the case of a devicetree in the incoming passage, we
know we won't need to allocate the bloblist, since the previous phase has
set it up for us.

Finally, move the reloc_fdt() call after the reloc_bloblist() since, as
mentioned above, when the passage is used there is no need to relocate the
devicetree.

There is one subtlety here. If bloblist support is not enabled in U-Boot,
it can still receive a control devicetree, using the passage_dtb_off value
added to passage_bloblist. This allows the devicetree passing to work
even if the bloblist itself is ignored. In that case we do need to
relocate the devicetree. Use a global_data flag for this case.

* Actually we could init the bloblist later, since we have the offset of
the devicetree in a register, but that seems like an extreme measure,
bypassing U-Boot's own bloblist implementation to get at the data.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 common/bloblist.c                 |  1 +
 common/board_f.c                  | 16 ++++++++++++----
 dts/Kconfig                       | 12 ++++++++++++
 include/asm-generic/global_data.h |  4 ++++
 include/bloblist.h                |  1 +
 lib/fdtdec.c                      | 30 ++++++++++++++++++++++++++++++
 6 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/common/bloblist.c b/common/bloblist.c
index d36e0a94dff..310ca87dbc4 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -39,6 +39,7 @@ static struct tag_name {
 	{ BLOBLISTT_NONE, "(none)" },
 
 	/* BLOBLISTT_AREA_FIRMWARE_TOP */
+	{ BLOBLISTT_CONTROL_DTB, "Control DTB" },
 
 	/* BLOBLISTT_AREA_FIRMWARE */
 	{ BLOBLISTT_ACPI_GNVS, "ACPI GNVS" },
diff --git a/common/board_f.c b/common/board_f.c
index 86c77a42847..3684c21a0f7 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -517,7 +517,7 @@ static int reserve_global_data(void)
 
 static int reserve_fdt(void)
 {
-	if (!IS_ENABLED(CONFIG_OF_EMBED)) {
+	if (!IS_ENABLED(CONFIG_OF_EMBED) && !(gd->flags & GD_FLG_OF_PASSAGE)) {
 		/*
 		 * If the device tree is sitting immediately above our image
 		 * then we must relocate it. If it is embedded in the data
@@ -622,7 +622,12 @@ static int init_post(void)
 
 static int reloc_fdt(void)
 {
-	if (!IS_ENABLED(CONFIG_OF_EMBED)) {
+	if (IS_ENABLED(CONFIG_OF_PASSAGE) && (gd->flags & GD_FLG_OF_PASSAGE)) {
+		void *blob = bloblist_find(BLOBLISTT_CONTROL_DTB, 0);
+
+		log_info("passage: Control dtb relocated to %p\n", blob);
+		gd->fdt_blob = blob;
+	} else if (!IS_ENABLED(CONFIG_OF_EMBED)) {
 		if (gd->flags & GD_FLG_SKIP_RELOC)
 			return 0;
 		if (gd->new_fdt) {
@@ -819,6 +824,9 @@ __weak int clear_bss(void)
 
 static const init_fnc_t init_sequence_f[] = {
 	setup_mon_len,
+#ifdef CONFIG_OF_PASSAGE
+	bloblist_init,
+#endif
 #ifdef CONFIG_OF_CONTROL
 	fdtdec_setup,
 #endif
@@ -828,7 +836,7 @@ static const init_fnc_t init_sequence_f[] = {
 	initf_malloc,
 	log_init,
 	initf_bootstage,	/* uses its own timer, so does not need DM */
-#ifdef CONFIG_BLOBLIST
+#if !defined(CONFIG_OF_PASSAGE) && defined(CONFIG_BLOBLIST)
 	bloblist_init,
 #endif
 	setup_spl_handoff,
@@ -938,9 +946,9 @@ static const init_fnc_t init_sequence_f[] = {
 	setup_bdinfo,
 	display_new_sp,
 	INIT_FUNC_WATCHDOG_RESET
-	reloc_fdt,
 	reloc_bootstage,
 	reloc_bloblist,
+	reloc_fdt,
 	setup_reloc,
 #if defined(CONFIG_X86) || defined(CONFIG_ARC)
 	copy_uboot_to_ram,
diff --git a/dts/Kconfig b/dts/Kconfig
index 5dcc79d5192..7e4d9852a44 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -96,6 +96,18 @@ config OF_EMBED
 
 endchoice
 
+config OF_PASSAGE
+	bool "Devicetree provided by the standard passage protocol"
+	help
+	  If this option is enabled, the device tree may be provided by the
+	  standard passage, meaning that a previous phase/stage passes a
+	  bloblist containing this. This is the standard way to pass a
+	  devicetree between firmware components at runtime. The device tree
+	  bundled with the image (if any) will be overridden / ignored.
+
+	  Note: If BLOBLIST is not enabled, this does not decode the
+	  bloblist, but just picks up the devicetree by itself.
+
 config OF_BOARD
 	bool "Provided by the board (e.g a previous loader) at runtime"
 	default y if SANDBOX
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index ef4119f27f4..717fe2edb46 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -627,6 +627,10 @@ enum gd_flags {
 	 * @GD_FLG_SMP_READY: SMP initialization is complete
 	 */
 	GD_FLG_SMP_READY = 0x80000,
+	/**
+	 * @GD_FLG_OF_PASSAGE: Using devicetree from standard passage protocol
+	 */
+	GD_FLG_OF_PASSAGE = 0x80000,
 };
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/bloblist.h b/include/bloblist.h
index 2ede0ce3150..607e42129d4 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -31,6 +31,7 @@ enum bloblist_tag_t {
 	 * projects.
 	 */
 	BLOBLISTT_AREA_FIRMWARE_TOP = 0x1,
+	BLOBLISTT_CONTROL_DTB = 1,	/* Devicetree used for control */
 
 	/* Standard area to allocate blobs used across firmware components */
 	BLOBLISTT_AREA_FIRMWARE = 0x100,
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 31a509bc221..4ca56e06b2f 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -3,8 +3,11 @@
  * Copyright (c) 2011 The Chromium OS Authors.
  */
 
+#define LOG_CATEGORY	LOGC_DT
+
 #ifndef USE_HOSTCC
 #include <common.h>
+#include <bloblist.h>
 #include <boot_fit.h>
 #include <dm.h>
 #include <hang.h>
@@ -1631,6 +1634,33 @@ int fdtdec_setup(void)
 	else /* embed dtb in ELF file for testing / development */
 		gd->fdt_blob = dtb_dt_embedded();
 
+	/* Passed in via the standard passage */
+	if (IS_ENABLED(CONFIG_OF_PASSAGE) && gd->passage_dtb_off) {
+		void *fdt = NULL;
+
+		/* Use the bloblist if available */
+		if (CONFIG_IS_ENABLED(BLOBLIST)) {
+			fdt = bloblist_find(BLOBLISTT_CONTROL_DTB, 0);
+
+			if (fdt)
+				gd->flags |= GD_FLG_OF_PASSAGE;
+		} else {
+			void *bloblist;
+
+			/* Cursory check for a valid bloblist; use the offset */
+			bloblist = bloblist_check_magic(gd->passage_bloblist);
+			if (bloblist) {
+				fdt = bloblist + gd->passage_dtb_off;
+				log_debug("passage: Found dtb offset %lx\n",
+					  gd->passage_dtb_off);
+			}
+		}
+		if (fdt) {
+			gd->fdt_blob = fdt;
+			log_debug("passage: Found control dtb at %p\n", fdt);
+		}
+	}
+
 	/* Allow the board to override the fdt address. */
 	if (IS_ENABLED(CONFIG_OF_BOARD)) {
 		gd->fdt_blob = board_fdt_blob_setup(&ret);
-- 
2.33.1.1089.g2158813163f-goog



More information about the U-Boot mailing list