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 <s...@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 <s...@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