[PATCH v3 06/22] passage: Support an incoming passage

Simon Glass sjg at chromium.org
Thu Apr 17 20:15:48 CEST 2025


Plumb in the ability for U-Boot proper to accept an incoming standard
passage from a previous phase, such as SPL or TF-A. This allows data to
be passed from binary to binary when firmware is booting.

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

Changes in v3:
- Add passage_valid() to decide if stdpass was provided
- Make the global_data fields present only when needed
- Move arch_passage_entry() into this patch
- Move passage.h into this patch

Changes in v2:
- Rebase to master
- Rework global_data for new stdpass convention

 Makefile                          |  2 +-
 common/Kconfig                    | 31 ++++++++++++++++++
 common/board_f.c                  | 13 +++++---
 include/asm-generic/global_data.h | 37 +++++++++++++++++++++
 include/passage.h                 | 53 +++++++++++++++++++++++++++++++
 lib/asm-offsets.c                 |  8 +++++
 scripts/Makefile.xpl              |  2 +-
 7 files changed, 139 insertions(+), 7 deletions(-)
 create mode 100644 include/passage.h

diff --git a/Makefile b/Makefile
index 73939748e54..3577c2c9a22 100644
--- a/Makefile
+++ b/Makefile
@@ -1396,7 +1396,7 @@ endif
 
 binman_dtb := $(shell echo $(CONFIG_BINMAN_DTB))
 ifeq ($(strip $(binman_dtb)),)
-ifeq ($(CONFIG_OF_EMBED),y)
+ifneq ($(CONFIG_OF_EMBED)$(CONFIG_OF_PASSAGE),)
 binman_dtb = ./dts/dt.dtb
 else
 binman_dtb = ./u-boot.dtb
diff --git a/common/Kconfig b/common/Kconfig
index be517b80eb5..c6a8fa54363 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1089,6 +1089,14 @@ config BLOBLIST_PASSAGE_MANDATORY
 	  U-Boot will report an error when a valid incoming bloblist does not
 	  exist.
 
+config BLOBLIST_PASSAGE
+	bool "Obtain bloblist from standard passage information"
+	help
+	  Rather than allocating the bloblist, get it from the standard
+	  passage provided by an earlier phase, e.g. SPL. The bloblist address
+	  and size are used as is, except that the bloblist is of course
+	  relocated when U-Boot relocates.
+
 endchoice
 
 config BLOBLIST_ADDR
@@ -1148,6 +1156,13 @@ config SPL_BLOBLIST_ALLOC
 	  specify a fixed address on systems where this is unknown or can
 	  change at runtime.
 
+config SPL_BLOBLIST_PASSAGE
+	bool "Obtain bloblist from standard passage information"
+	help
+	  Rather than allocating the bloblist, get it from the standard
+	  passage provided by an earlier phase, e.g. TPL. The bloblist address
+	  and size are used as is within SPL, then passed on to U-Boot.
+
 endchoice
 
 endif # SPL_BLOBLIST
@@ -1212,6 +1227,22 @@ endif # VPL_BLOBLIST
 
 endmenu
 
+config PASSAGE_IN
+	bool "Support the standard-passage protocol (in)"
+	help
+	  This enables a standard protocol for entering U-Boot, providing
+	  parameters in a bloblist with a devicetree. It allows the various
+	  firmware phases to communicate state and settings to following
+	  phases.
+
+config SPL_PASSAGE_IN
+	bool "Support the standard-passage protocol in SPL (in)"
+	help
+	  This enables a standard protocol for entering SPL, providing
+	  parameters in a bloblist and a devicetree. It allows the various
+	  firmware phases to communicate state and settings to following
+	  phases.
+
 source "common/spl/Kconfig"
 
 config IMAGE_SIGN_INFO
diff --git a/common/board_f.c b/common/board_f.c
index bff465d9cb2..e9ffa2d7fed 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -700,11 +700,14 @@ static int reloc_bootstage(void)
 static int reloc_bloblist(void)
 {
 #ifdef CONFIG_BLOBLIST
-	/*
-	 * Relocate only if we are supposed to send it
-	 */
-	if ((gd->flags & GD_FLG_SKIP_RELOC) &&
-	    CONFIG_BLOBLIST_SIZE == CONFIG_BLOBLIST_SIZE_RELOC) {
+	int size = bloblist_get_size();
+	int new_size = CONFIG_BLOBLIST_SIZE_RELOC;
+
+	if (!new_size)
+		new_size = size;
+
+	/* Relocate only if we are supposed to send it */
+	if ((gd->flags & GD_FLG_SKIP_RELOC) && size == new_size) {
 		debug("Not relocating bloblist\n");
 		return 0;
 	}
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 506ee51cdb0..464b9c3eee1 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -219,6 +219,35 @@ struct global_data {
 	 */
 	long precon_buf_idx;
 #endif
+#if CONFIG_IS_ENABLED(PASSAGE_IN)
+	/**
+	 * @passage_mach: Incoming machine information from standard passage
+	 *
+	 * Provides a value which indicates whether passage is used, e.g.
+	 * PASSAGE_ABI_MACH
+	 */
+	ulong passage_mach;
+	/**
+	 * @passage_bloblist: Incoming bloblist from standard passage
+	 *
+	 * Provides the address of the bloblist passed in by the previous stage
+	 * or phase. If this is zero, there is none.
+	 */
+	ulong passage_bloblist;
+
+	/**
+	 * @passage_dtb: Incoming control devicetree within standard passage
+	 *
+	 * Provides the address (typically within the bloblist) where the
+	 * control DTB is stored. If this is zero, there is none.
+	 *
+	 * Note: This must be set to the correct value if the control DTB exists
+	 * since SPL may use this and ignore the bloblist, e.g. if bloblist
+	 * support is not enabled for code-size reasons. If this value is not
+	 * valid, any devicetree passed in the passage_bloblist is ignored.
+	 */
+	ulong passage_dtb;
+#endif
 #ifdef CONFIG_DM
 	/**
 	 * @dm_root: root instance for Driver Model
@@ -581,6 +610,14 @@ static_assert(sizeof(struct global_data) == GD_SIZE);
 #define gd_video_size()		0
 #endif
 
+#if CONFIG_IS_ENABLED(PASSAGE_IN)
+#define gd_passage_bloblist()	gd->passage_bloblist
+#define gd_passage_dtb()	gd->passage_dtb
+#else
+#define gd_passage_bloblist()	0
+#define gd_passage_dtb()	0
+#endif
+
 /**
  * enum gd_flags - global data flags
  *
diff --git a/include/passage.h b/include/passage.h
new file mode 100644
index 00000000000..b71796f5eaf
--- /dev/null
+++ b/include/passage.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Standard passage implementation
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg at chromium.org>
+ */
+
+#ifndef __PASSAGE_H
+#define __PASSAGE_H
+
+#include <stdbool.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+	PASSAGE_ABI_MACH	= 0x4a0fb10bul,
+	PASSAGE_ABI_VERSION	= 1ul,
+};
+
+static inline ulong passage_mach_version(void)
+{
+#if BITS_PER_LONG == 64
+	return PASSAGE_ABI_MACH | (ulong)PASSAGE_ABI_VERSION << 32;
+#else
+	return (PASSAGE_ABI_MACH & 0xffffff) | (PASSAGE_ABI_VERSION << 24);
+#endif
+}
+
+/**
+ * passage_valid() - See if standard passage was provided by the previous phase
+ *
+ * Return: true if standard passage was provided, else false
+ */
+static inline bool passage_valid(void)
+{
+#if CONFIG_IS_ENABLED(BLOBLIST_PASSAGE)
+	return gd->passage_mach == passage_mach_version();
+#else
+	return false;
+#endif
+}
+
+/* arch_passage_entry() - Jump to the next phase, using standard passage
+ *
+ * @entry_addr: Address to jump to
+ * @bloblist: Bloblist address to pass
+ * @fdt: FDT to pass
+ */
+void __noreturn arch_passage_entry(ulong entry_addr, ulong bloblist, ulong fdt);
+
+#endif
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
index b6bbcbf76ca..23ee9aab47e 100644
--- a/lib/asm-offsets.c
+++ b/lib/asm-offsets.c
@@ -48,5 +48,13 @@ int main(void)
 	DEFINE(GD_ENV_ADDR, offsetof(struct global_data, env_addr));
 #endif
 
+#if CONFIG_IS_ENABLED(PASSAGE_IN)
+	DEFINE(GD_PASSAGE_MACH, offsetof(struct global_data, passage_mach));
+	DEFINE(GD_PASSAGE_BLOBLIST,
+	       offsetof(struct global_data, passage_bloblist));
+	DEFINE(GD_PASSAGE_DTB,
+	       offsetof(struct global_data, passage_dtb));
+#endif
+
 	return 0;
 }
diff --git a/scripts/Makefile.xpl b/scripts/Makefile.xpl
index 43f27874f9f..b25866e9676 100644
--- a/scripts/Makefile.xpl
+++ b/scripts/Makefile.xpl
@@ -322,7 +322,7 @@ endif
 #   - we have either OF_SEPARATE or OF_HOSTFILE
 build_dtb :=
 ifneq ($(CONFIG_$(PHASE_)OF_REAL),)
-ifneq ($(CONFIG_OF_SEPARATE)$(CONFIG_SANDBOX),)
+ifneq ($(CONFIG_OF_SEPARATE)$(CONFIG_OF_PASSAGE),$(CONFIG_SANDBOX),)
 build_dtb := y
 endif
 endif
-- 
2.43.0



More information about the U-Boot mailing list