[PATCH v3 6/7] Introduce Verifying Program Loader (VPL)
Simon Glass
sjg at chromium.org
Mon Jul 12 04:19:18 CEST 2021
Add support for VPL, a new phase of U-Boot. This runs after TPL. It is
responsible for selecting which SPL binary to run, based on a
verified-boot process.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
Changes in v3:
- Move VPL Kconfig options to a separate patch
- Add full build support for VPL
Changes in v2:
- Add some more VPL Kconfig options
Makefile | 13 +++++++++++++
common/spl/Kconfig | 15 ++++++++++++++-
common/spl/spl.c | 25 ++++++++++++++++++++++---
doc/develop/spl.rst | 6 +++++-
include/bootstage.h | 2 ++
include/linux/kconfig.h | 3 +++
include/spl.h | 20 +++++++++++++++++---
scripts/Kbuild.include | 4 ++++
scripts/Makefile.autoconf | 12 ++++++++++++
scripts/Makefile.build | 4 ++++
scripts/Makefile.lib | 5 +++++
scripts/Makefile.spl | 35 ++++++++++++++++++++++++++---------
12 files changed, 127 insertions(+), 17 deletions(-)
diff --git a/Makefile b/Makefile
index f7f62979ae2..b2ba80ca5de 100644
--- a/Makefile
+++ b/Makefile
@@ -946,6 +946,7 @@ INPUTS-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
endif
endif
INPUTS-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
+INPUTS-$(CONFIG_VPL) += vpl/u-boot-vpl.bin
INPUTS-$(CONFIG_OF_SEPARATE) += u-boot.dtb
INPUTS-$(CONFIG_BINMAN_STANDALONE_FDT) += u-boot.dtb
ifeq ($(CONFIG_SPL_FRAMEWORK),y)
@@ -1986,6 +1987,18 @@ tpl/u-boot-tpl.bin: tools prepare \
$(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all
$(TPL_SIZE_CHECK)
+tpl/u-boot-tpl: tools prepare \
+ $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_OF_HOSTFILE)$(CONFIG_TPL_OF_PLATDATA),dts/dt.dtb)
+ $(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all
+
+vpl/u-boot-vpl.bin: vpl/u-boot-vpl
+ @:
+ $(VPL_SIZE_CHECK)
+
+vpl/u-boot-vpl: tools prepare \
+ $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_OF_HOSTFILE)$(CONFIG_VPL_OF_PLATDATA),dts/dt.dtb)
+ $(Q)$(MAKE) obj=vpl -f $(srctree)/scripts/Makefile.spl all
+
TAG_SUBDIRS := $(patsubst %,$(srctree)/%,$(u-boot-dirs) include)
FIND := find
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 10384b835b2..0443197cd55 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1,4 +1,4 @@
-menu "SPL / TPL"
+menu "SPL / TPL / VPL"
config SUPPORT_SPL
bool
@@ -6,6 +6,9 @@ config SUPPORT_SPL
config SUPPORT_TPL
bool
+config SUPPORT_VPL
+ bool
+
config SPL_DFU_NO_RESET
bool
@@ -280,6 +283,16 @@ config SPL_READ_ONLY
writeable memory) of anything it wants to modify, such as
device-private data.
+config TPL_SEPARATE_BSS
+ bool "BSS section is in a different memory region from text"
+ default y if SPL_SEPARATE_BSS
+ help
+ Some platforms need a large BSS region in TPL and can provide this
+ because RAM is already set up. In this case BSS can be moved to RAM.
+ This option should then be enabled so that the correct device tree
+ location is used. Normally we put the device tree at the end of BSS
+ but with this option enabled, it goes at _image_binary_end.
+
config SPL_BANNER_PRINT
bool "Enable output of the SPL banner 'U-Boot SPL ...'"
default y
diff --git a/common/spl/spl.c b/common/spl/spl.c
index eba77cace6d..27ed855c018 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -55,6 +55,11 @@ binman_sym_declare(ulong, spl, image_pos);
binman_sym_declare(ulong, spl, size);
#endif
+#ifdef CONFIG_VPL
+binman_sym_declare(ulong, vpl, image_pos);
+binman_sym_declare(ulong, vpl, size);
+#endif
+
/* Define board data structure */
static struct bd_info bdata __attribute__ ((section(".data")));
@@ -139,21 +144,33 @@ void spl_fixup_fdt(void *fdt_blob)
ulong spl_get_image_pos(void)
{
- return spl_phase() == PHASE_TPL ?
+#ifdef CONFIG_VPL
+ if (spl_next_phase() == PHASE_VPL)
+ return binman_sym(ulong, vpl, image_pos);
+#endif
+ return spl_next_phase() == PHASE_SPL ?
binman_sym(ulong, spl, image_pos) :
binman_sym(ulong, u_boot_any, image_pos);
}
ulong spl_get_image_size(void)
{
- return spl_phase() == PHASE_TPL ?
+#ifdef CONFIG_VPL
+ if (spl_next_phase() == PHASE_VPL)
+ return binman_sym(ulong, vpl, size);
+#endif
+ return spl_next_phase() == PHASE_SPL ?
binman_sym(ulong, spl, size) :
binman_sym(ulong, u_boot_any, size);
}
ulong spl_get_image_text_base(void)
{
- return spl_phase() == PHASE_TPL ? CONFIG_SPL_TEXT_BASE :
+#ifdef CONFIG_VPL
+ if (spl_next_phase() == PHASE_VPL)
+ return CONFIG_VPL_TEXT_BASE;
+#endif
+ return spl_next_phase() == PHASE_SPL ? CONFIG_SPL_TEXT_BASE :
CONFIG_SYS_TEXT_BASE;
}
@@ -430,6 +447,8 @@ static enum bootstage_id get_bootstage_id(bool start)
if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL)
return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL;
+ else if (IS_ENABLED(CONFIG_VPL_BUILD) && phase == PHASE_VPL)
+ return start ? BOOTSTAGE_ID_START_VPL : BOOTSTAGE_ID_END_VPL;
else
return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL;
}
diff --git a/doc/develop/spl.rst b/doc/develop/spl.rst
index c2a29a8c0a4..ede79431118 100644
--- a/doc/develop/spl.rst
+++ b/doc/develop/spl.rst
@@ -62,7 +62,11 @@ U-Boot Phases
U-Boot boots through the following phases:
TPL
- Very early init, as tiny as possible. This loads SPL.
+ Very early init, as tiny as possible. This loads SPL (or VPL if enabled).
+
+VPL
+ Optional verification step, which can select one of several SPL binaries,
+ if A/B verified boot
SPL
Secondary program loader. Sets up SDRAM and loads U-Boot proper. It may also
diff --git a/include/bootstage.h b/include/bootstage.h
index f837a387c8c..1a384e5b60a 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -176,6 +176,8 @@ enum bootstage_id {
BOOTSTAGE_ID_END_TPL,
BOOTSTAGE_ID_START_SPL,
BOOTSTAGE_ID_END_SPL,
+ BOOTSTAGE_ID_START_VPL,
+ BOOTSTAGE_ID_END_VPL,
BOOTSTAGE_ID_START_UBOOT_F,
BOOTSTAGE_ID_START_UBOOT_R,
BOOTSTAGE_ID_USB_START,
diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
index d109ed3119e..26f1216f7da 100644
--- a/include/linux/kconfig.h
+++ b/include/linux/kconfig.h
@@ -37,6 +37,8 @@
#if defined(CONFIG_TPL_BUILD)
#define _CONFIG_PREFIX TPL_
+#elif defined(CONFIG_VPL_BUILD)
+#define _CONFIG_PREFIX VPL_
#elif defined(CONFIG_SPL_BUILD)
#define _CONFIG_PREFIX SPL_
#else
@@ -52,6 +54,7 @@
* CONFIG_FOO if CONFIG_SPL_BUILD is undefined,
* CONFIG_SPL_FOO if CONFIG_SPL_BUILD is defined.
* CONFIG_TPL_FOO if CONFIG_TPL_BUILD is defined.
+ * CONFIG_VPL_FOO if CONFIG_VPL_BUILD is defined.
*/
#define CONFIG_VAL(option) config_val(option)
diff --git a/include/spl.h b/include/spl.h
index cee9a42ddb5..d9fe4e1bfd4 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -60,6 +60,7 @@ static inline bool u_boot_first_phase(void)
enum u_boot_phase {
PHASE_NONE, /* Invalid phase, signifying before U-Boot */
PHASE_TPL, /* Running in TPL */
+ PHASE_VPL, /* Running in VPL */
PHASE_SPL, /* Running in SPL */
PHASE_BOARD_F, /* Running in U-Boot before relocation */
PHASE_BOARD_R, /* Running in U-Boot after relocation */
@@ -112,7 +113,9 @@ static inline enum u_boot_phase spl_phase(void)
{
#ifdef CONFIG_TPL_BUILD
return PHASE_TPL;
-#elif CONFIG_SPL_BUILD
+#elif defined(CONFIG_VPL_BUILD)
+ return PHASE_VPL;
+#elif defined(CONFIG_SPL_BUILD)
return PHASE_SPL;
#else
DECLARE_GLOBAL_DATA_PTR;
@@ -134,10 +137,15 @@ static inline enum u_boot_phase spl_prev_phase(void)
{
#ifdef CONFIG_TPL_BUILD
return PHASE_NONE;
+#elif defined(CONFIG_VPL_BUILD)
+ return PHASE_TPL; /* VPL requires TPL */
#elif defined(CONFIG_SPL_BUILD)
- return IS_ENABLED(CONFIG_TPL) ? PHASE_TPL : PHASE_NONE;
+ return IS_ENABLED(CONFIG_VPL) ? PHASE_VPL :
+ IS_ENABLED(CONFIG_TPL) ? PHASE_TPL :
+ PHASE_NONE;
#else
- return IS_ENABLED(CONFIG_SPL) ? PHASE_SPL : PHASE_NONE;
+ return IS_ENABLED(CONFIG_SPL) ? PHASE_SPL :
+ PHASE_NONE;
#endif
}
@@ -150,6 +158,8 @@ static inline enum u_boot_phase spl_prev_phase(void)
static inline enum u_boot_phase spl_next_phase(void)
{
#ifdef CONFIG_TPL_BUILD
+ return IS_ENABLED(CONFIG_VPL) ? PHASE_VPL : PHASE_SPL;
+#elif defined(CONFIG_VPL_BUILD)
return PHASE_SPL;
#else
return PHASE_BOARD_F;
@@ -166,6 +176,8 @@ static inline const char *spl_phase_name(enum u_boot_phase phase)
switch (phase) {
case PHASE_TPL:
return "TPL";
+ case PHASE_VPL:
+ return "VPL";
case PHASE_SPL:
return "SPL";
case PHASE_BOARD_F:
@@ -180,6 +192,8 @@ static inline const char *spl_phase_name(enum u_boot_phase phase)
#ifdef CONFIG_SPL_BUILD
# ifdef CONFIG_TPL_BUILD
# define SPL_TPL_NAME "TPL"
+# elif defined(CONFIG_VPL_BUILD)
+# define SPL_TPL_NAME "VPL"
# else
# define SPL_TPL_NAME "SPL"
# endif
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index dfb67226b08..c87d9c9f5f2 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -325,11 +325,15 @@ endif
ifdef CONFIG_SPL_BUILD
SPL_ := SPL_
+ifeq ($(CONFIG_VPL_BUILD),y)
+SPL_TPL_ := VPL_
+else
ifeq ($(CONFIG_TPL_BUILD),y)
SPL_TPL_ := TPL_
else
SPL_TPL_ := SPL_
endif
+endif
else
SPL_ :=
SPL_TPL_ :=
diff --git a/scripts/Makefile.autoconf b/scripts/Makefile.autoconf
index 0bfc1b2a629..ad556f80f71 100644
--- a/scripts/Makefile.autoconf
+++ b/scripts/Makefile.autoconf
@@ -18,6 +18,10 @@ ifeq ($(shell grep -q '^CONFIG_TPL=y' include/config/auto.conf 2>/dev/null && ec
__all: tpl/include/autoconf.mk
endif
+ifeq ($(shell grep -q '^CONFIG_VPL=y' include/config/auto.conf 2>/dev/null && echo y),y)
+__all: vpl/include/autoconf.mk
+endif
+
include include/config/auto.conf
include scripts/Kbuild.include
@@ -84,6 +88,10 @@ tpl/u-boot.cfg: include/config.h FORCE
$(Q)mkdir -p $(dir $@)
$(call cmd,u_boot_cfg,-DCONFIG_SPL_BUILD -DCONFIG_TPL_BUILD)
+vpl/u-boot.cfg: include/config.h FORCE
+ $(Q)mkdir -p $(dir $@)
+ $(call cmd,u_boot_cfg,-DCONFIG_SPL_BUILD -DCONFIG_VPL_BUILD)
+
include/autoconf.mk: u-boot.cfg
$(call cmd,autoconf)
@@ -95,6 +103,10 @@ tpl/include/autoconf.mk: tpl/u-boot.cfg
$(Q)mkdir -p $(dir $@)
$(call cmd,autoconf)
+vpl/include/autoconf.mk: vpl/u-boot.cfg
+ $(Q)mkdir -p $(dir $@)
+ $(call cmd,autoconf)
+
# include/config.h
# Prior to Kconfig, it was generated by mkconfig. Now it is created here.
define filechk_config_h
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 7e59ca54cd0..1d72ba18ebd 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -4,6 +4,9 @@
# ==========================================================================
# Modified for U-Boot
+prefix := vpl
+src := $(patsubst $(prefix)/%,%,$(obj))
+ifeq ($(obj),$(src))
prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
@@ -13,6 +16,7 @@ ifeq ($(obj),$(src))
prefix := .
endif
endif
+endif
PHONY := __build
__build:
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 78bbebe7e93..c08ad44db5f 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -556,16 +556,21 @@ cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \
# 'u-boot,dm-pre-reloc' property and thus are not needed by SPL. The second
# pass removes various unused properties from the remaining nodes.
# The output is typically a much smaller device tree file.
+ifeq ($(CONFIG_VPL_BUILD),y)
+fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-vpl
+else
ifeq ($(CONFIG_TPL_BUILD),y)
fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-tpl
else
fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-spl
endif
+endif
quiet_cmd_fdtgrep = FDTGREP $@
cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
-n /chosen -n /config -O dtb | \
$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
-P u-boot,dm-pre-reloc -P u-boot,dm-spl -P u-boot,dm-tpl \
+ -P u-boot,dm-vpl \
$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
# fdt_rm_props
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index ffe919dafab..082ddb9c5f2 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -27,8 +27,16 @@ UBOOTINCLUDE := -I$(obj)/include $(UBOOTINCLUDE)
KBUILD_CPPFLAGS += -DCONFIG_SPL_BUILD
ifeq ($(CONFIG_TPL_BUILD),y)
KBUILD_CPPFLAGS += -DCONFIG_TPL_BUILD
+else
+ifeq ($(CONFIG_VPL_BUILD),y)
+KBUILD_CPPFLAGS += -DCONFIG_VPL_BUILD
+endif
endif
+ifeq ($(CONFIG_VPL_BUILD),y)
+SPL_BIN := u-boot-vpl
+SPL_NAME := vpl
+else
ifeq ($(CONFIG_TPL_BUILD),y)
SPL_BIN := u-boot-tpl
SPL_NAME := tpl
@@ -36,16 +44,21 @@ else
SPL_BIN := u-boot-spl
SPL_NAME := spl
endif
+endif
export SPL_NAME
ifdef CONFIG_SPL_BUILD
SPL_ := SPL_
+ifeq ($(CONFIG_VPL_BUILD),y)
+SPL_TPL_ := VPL_
+else
ifeq ($(CONFIG_TPL_BUILD),y)
SPL_TPL_ := TPL_
else
SPL_TPL_ := SPL_
endif
+endif
else
SPL_ :=
SPL_TPL_ :=
@@ -57,6 +70,9 @@ endif
ifeq ($(obj)$(CONFIG_SUPPORT_TPL),tpl)
$(error You cannot build TPL without enabling CONFIG_SUPPORT_TPL)
endif
+ifeq ($(obj)$(CONFIG_SUPPORT_VPL),vpl)
+$(error You cannot build VPL without enabling CONFIG_SUPPORT_VPL)
+endif
include $(srctree)/config.mk
include $(srctree)/arch/$(ARCH)/Makefile
@@ -90,13 +106,12 @@ libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
endif
libs-y += common/init/
+# Special handling for a few options which support SPL/TPL/VPL
+libs-$(CONFIG_$(SPL_TPL_)LIBCOMMON_SUPPORT) += common/ cmd/ env/
+libs-$(CONFIG_$(SPL_TPL_)LIBGENERIC_SUPPORT) += lib/
+
# Special handling for a few options which support SPL/TPL
-ifeq ($(CONFIG_TPL_BUILD),y)
-libs-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/
-libs-$(CONFIG_TPL_LIBGENERIC_SUPPORT) += lib/
-else
-libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/
-libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/
+ifeq ($(CONFIG_TPL_BUILD)$(CONFIG_VPL_BUILD),)
ifdef CONFIG_SPL_FRAMEWORK
libs-$(CONFIG_PARTITIONS) += disk/
endif
@@ -182,7 +197,7 @@ LDPPFLAGS += \
sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')
# Turn various CONFIG symbols into IMAGE symbols for easy reuse of
-# the scripts between SPL and TPL.
+# the scripts between SPL, TPL and VPL.
ifneq ($(CONFIG_$(SPL_TPL_)MAX_SIZE),)
LDPPFLAGS += -DIMAGE_MAX_SIZE=$(CONFIG_$(SPL_TPL_)MAX_SIZE)
endif
@@ -264,6 +279,7 @@ ifeq ($(CONFIG_SYS_SOC),"at91")
INPUTS-y += $(obj)/boot.bin
endif
+ifndef CONFIG_VPL_BUILD
ifdef CONFIG_TPL_BUILD
INPUTS-$(CONFIG_TPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-start16-tpl.bin \
$(obj)/u-boot-x86-reset16-tpl.bin
@@ -271,6 +287,7 @@ else
INPUTS-$(CONFIG_SPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-start16-spl.bin \
$(obj)/u-boot-x86-reset16-spl.bin
endif
+endif
INPUTS-$(CONFIG_ARCH_ZYNQ) += $(obj)/boot.bin
INPUTS-$(CONFIG_ARCH_ZYNQMP) += $(obj)/boot.bin
@@ -310,7 +327,7 @@ endif
ifneq ($(build_dtb),)
$(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \
- $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
+ $(if $(CONFIG_$(SPL_TPL_)SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
$(FINAL_DTB_CONTAINER) FORCE
$(call if_changed,cat)
@@ -401,7 +418,7 @@ LDFLAGS_$(SPL_BIN) += $(call ld-option, --no-dynamic-linker)
LDFLAGS_$(SPL_BIN) += --build-id=none
-# Pick the best-match (i.e. SPL_TEXT_BASE for SPL, TPL_TEXT_BASE for TPL)
+# Pick the best match (e.g. SPL_TEXT_BASE for SPL, TPL_TEXT_BASE for TPL)
ifneq ($(CONFIG_$(SPL_TPL_)TEXT_BASE),)
LDFLAGS_$(SPL_BIN) += -Ttext $(CONFIG_$(SPL_TPL_)TEXT_BASE)
endif
--
2.32.0.93.g670b81a890-goog
More information about the U-Boot
mailing list