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