[PATCH 4/4] Introduce Verifying Program Loader (VPL)
Simon Glass
sjg at chromium.org
Sat May 8 00:37:23 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>
---
common/Kconfig | 67 ++++++++++++++++
common/spl/Kconfig | 168 +++++++++++++++++++++++++++++++++++++++-
common/spl/spl.c | 25 +++++-
doc/develop/spl.rst | 6 +-
include/bootstage.h | 2 +
include/linux/kconfig.h | 3 +
include/spl.h | 20 ++++-
lib/Kconfig | 54 +++++++++++++
scripts/Kbuild.include | 4 +
scripts/Makefile.build | 4 +
10 files changed, 345 insertions(+), 8 deletions(-)
diff --git a/common/Kconfig b/common/Kconfig
index 26496f9a2e7..2a7f08af1dc 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -81,6 +81,15 @@ config TPL_LOGLEVEL
int
default LOGLEVEL
+config VPL_LOGLEVEL
+ int "loglevel for VPL"
+ default LOGLEVEL
+ help
+ All Messages with a loglevel smaller than the console loglevel will
+ be compiled in to VPL. See LOGLEVEL for a list of available log
+ levels. Setting this to a value above 4 may increase the code size
+ significantly.
+
config SILENT_CONSOLE
bool "Support a silent console"
help
@@ -254,6 +263,15 @@ config LOG
if LOG
+config VPL_LOG
+ bool "Enable logging support in VPL"
+ depends on LOG
+ help
+ This enables support for logging of status and debug messages. These
+ can be displayed on the console, recorded in a memory buffer, or
+ discarded if not needed. Logging supports various categories and
+ levels of severity.
+
config LOG_MAX_LEVEL
int "Maximum log level to record"
default 6
@@ -415,6 +433,47 @@ config TPL_LOG_CONSOLE
endif
+config VPL_LOG
+ bool "Enable logging support in VPL"
+ depends on LOG
+ help
+ This enables support for logging of status and debug messages. These
+ can be displayed on the console, recorded in a memory buffer, or
+ discarded if not needed. Logging supports various categories and
+ levels of severity.
+
+if VPL_LOG
+
+config VPL_LOG_MAX_LEVEL
+ int "Maximum log level to record in VPL"
+ default 3
+ help
+ This selects the maximum log level that will be recorded. Any value
+ higher than this will be ignored. If possible log statements below
+ this level will be discarded at build time. Levels:
+
+ 0 - emergency
+ 1 - alert
+ 2 - critical
+ 3 - error
+ 4 - warning
+ 5 - note
+ 6 - info
+ 7 - debug
+ 8 - debug content
+ 9 - debug hardware I/O
+
+config VPL_LOG_CONSOLE
+ bool "Allow log output to the console in VPL"
+ default y
+ help
+ Enables a log driver which writes log records to the console.
+ Generally the console is the serial port or LCD display. Only the
+ log message is shown - other details like level, category, file and
+ line number are omitted.
+
+endif
+
config LOG_ERROR_RETURN
bool "Log all functions which return an error"
help
@@ -711,6 +770,14 @@ config TPL_BLOBLIST
This enables a bloblist in TPL. The bloblist is set up in TPL and
passed to SPL and U-Boot proper.
+config VPL_BLOBLIST
+ bool "Support for a bloblist in VPL"
+ depends on BLOBLIST
+ default y if TPL_BLOBLIST
+ help
+ This enables a bloblist in VPL. The bloblist is set up in VPL and
+ passed to SPL and U-Boot proper.
+
config BLOBLIST_SIZE
hex "Size of bloblist"
depends on BLOBLIST
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index df5468f1ac2..274686fd3ad 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
@@ -297,6 +310,15 @@ config TPL_BANNER_PRINT
info. Disabling this option could be useful to reduce TPL boot time
(e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
+config VPL_BANNER_PRINT
+ bool "Enable output of the VPL banner 'U-Boot VPL ...'"
+ depends on VPL
+ default y
+ help
+ If this option is enabled, VPL will print the banner with version
+ info. Disabling this option could be useful to reduce VPL boot time
+ (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
+
config SPL_EARLY_BSS
depends on ARM && !ARM64
bool "Allows initializing BSS early before entering board_init_f"
@@ -817,6 +839,27 @@ config SPL_DM_SPI_FLASH
Enable support for SPI DM flash drivers in SPL.
endif
+
+if TPL
+
+config VPL_CACHE
+ depends on CACHE
+ bool "Support cache drivers in SPL"
+ help
+ Enable support for cache drivers in SPL.
+
+config VPL_DM_SPI
+ bool "Support SPI DM drivers in SPL"
+ help
+ Enable support for SPI DM drivers in SPL.
+
+config VPL_DM_SPI_FLASH
+ bool "Support SPI DM FLASH drivers in SPL"
+ help
+ Enable support for SPI DM flash drivers in SPL.
+
+endif
+
if SPL_UBI
config SPL_UBI_LOAD_BY_VOLNAME
bool "Support loading volumes by name"
@@ -1623,6 +1666,129 @@ config TPL_YMODEM_SUPPORT
endif # TPL
+config VPL
+ bool
+ depends on SUPPORT_SPL
+ prompt "Enable VPL"
+ help
+ If you want to build VPL as well as the normal image, TPL and SPL,
+ say Y.
+
+if VPL
+
+config VPL_FRAMEWORK
+ bool "Support VPL based upon the common SPL framework"
+ default y
+ help
+ Enable the SPL framework under common/spl/ for VPL builds.
+ This framework supports MMC, NAND and YMODEM and other methods
+ loading of U-Boot's next stage. If unsure, say Y.
+
+config VPL_LIBCOMMON_SUPPORT
+ bool "Support common libraries"
+ default y if SPL_LIBCOMMON_SUPPORT
+ help
+ Enable support for common U-Boot libraries within VPL. See
+ SPL_LIBCOMMON_SUPPORT for details.
+
+config VPL_LIBGENERIC_SUPPORT
+ bool "Support generic libraries"
+ default y if SPL_LIBGENERIC_SUPPORT
+ help
+ Enable support for generic U-Boot libraries within VPL. These
+ libraries include generic code to deal with device tree, hashing,
+ printf(), compression and the like. This option is enabled on many
+ boards. Enable this option to build the code in lib/ as part of an
+ SPL build.
+
+config VPL_DRIVERS_MISC_SUPPORT
+ bool "Support misc drivers"
+ default y if TPL_DRIVERS_MISC_SUPPORT
+ help
+ Enable miscellaneous drivers in VPL. These drivers perform various
+ tasks that don't fall nicely into other categories, Enable this
+ option to build the drivers in drivers/misc as part of an VPL
+ build, for those that support building in VPL (not all drivers do).
+
+config VPL_GPIO_SUPPORT
+ bool "Support GPIO in VPL"
+ default y if SPL_GPIO_SUPPORT
+ help
+ Enable support for GPIOs (General-purpose Input/Output) in VPL.
+ GPIOs allow U-Boot to read the state of an input line (high or
+ low) and set the state of an output line. This can be used to
+ drive LEDs, control power to various system parts and read user
+ input. GPIOs can be useful in TPL to enable a 'sign-of-life' LED,
+ for example. Enable this option to build the drivers in
+ drivers/gpio as part of an TPL build.
+
+config VPL_I2C_SUPPORT
+ bool "Support I2C in VPL"
+ default y if SPL_I2C_SUPPORT
+ help
+ Enable support for the I2C bus in TPL. Vee SPL_I2C_SUPPORT for
+ details.
+
+config VPL_PCH_SUPPORT
+ bool "Support PCH drivers"
+ default y if TPL_PCH_SUPPORT
+ help
+ Enable support for PCH (Platform Controller Hub) devices in VPL.
+ These are used to set up GPIOs and the SPI peripheral early in
+ boot. This enables the drivers in drivers/pch as part of a VPL
+ build.
+
+config VPL_PCI
+ bool "Support PCI drivers"
+ default y if SPL_PCI
+ help
+ Enable support for PCI in VPL. For platforms that need PCI to boot,
+ or must perform some init using PCI in VPL, this provides the
+ necessary driver support. This enables the drivers in drivers/pci
+ as part of a VPL build.
+
+config VPL_RTC_SUPPORT
+ bool "Support RTC drivers"
+ help
+ Enable RTC (Real-time Clock) support in VPL. This includes support
+ for reading and setting the time. Some RTC devices also have some
+ non-volatile (battery-backed) memory which is accessible if
+ needed. This enables the drivers in drivers/rtc as part of an VPL
+ build.
+
+config VPL_SERIAL_SUPPORT
+ bool "Support serial"
+ default y if TPL_SERIAL_SUPPORT
+ select VPL_PRINTF
+ select VPL_STRTO
+ help
+ Enable support for serial in VPL. See SPL_SERIAL_SUPPORT for
+ details.
+
+config VPL_SPI_SUPPORT
+ bool "Support SPI drivers"
+ help
+ Enable support for using SPI in VPL. See SPL_SPI_SUPPORT for
+ details.
+
+config VPL_SPI_FLASH_SUPPORT
+ bool "Support SPI flash drivers"
+ help
+ Enable support for using SPI flash in VPL, and loading U-Boot from
+ SPI flash. SPI flash (Serial Peripheral Bus flash) is named after
+ the SPI bus that is used to connect it to a system. It is a simple
+ but fast bidirectional 4-wire bus (clock, chip select and two data
+ lines). This enables the drivers in drivers/mtd/spi as part of an
+ VPL build. This normally requires VPL_SPI_SUPPORT.
+
+config VPL_TEXT_BASE
+ hex "VPL Text Base"
+ default 0x0
+ help
+ The address in memory that VPL will be running from.
+
+endif
+
config SPL_AT91_MCK_BYPASS
bool "Use external clock signal as a source of main clock for AT91 platforms"
depends on ARCH_AT91
diff --git a/common/spl/spl.c b/common/spl/spl.c
index a0a608fd772..cd428c1cbc9 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")));
@@ -137,21 +142,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;
}
@@ -428,6 +445,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 00c85fb86aa..23df36c8e80 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -174,6 +174,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/lib/Kconfig b/lib/Kconfig
index 6d2d41de301..da27e71abf3 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -72,6 +72,11 @@ config TPL_PRINTF
select TPL_SPRINTF
select TPL_STRTO if !TPL_USE_TINY_PRINTF
+config VPL_PRINTF
+ bool
+ select VPL_SPRINTF
+ select VPL_STRTO if !VPL_USE_TINY_PRINTF
+
config SPRINTF
bool
default y
@@ -82,6 +87,9 @@ config SPL_SPRINTF
config TPL_SPRINTF
bool
+config VPL_SPRINTF
+ bool
+
config SSCANF
bool
default n
@@ -96,6 +104,9 @@ config SPL_STRTO
config TPL_STRTO
bool
+config VPL_STRTO
+ bool
+
config IMAGE_SPARSE
bool
@@ -148,6 +159,17 @@ config TPL_USE_TINY_PRINTF
The supported format specifiers are %c, %s, %u/%d and %x.
+config VPL_USE_TINY_PRINTF
+ bool "Enable tiny printf() version for VPL"
+ depends on VPL
+ help
+ This option enables a tiny, stripped down printf version.
+ This should only be used in space limited environments,
+ like SPL versions with hard memory limits. This version
+ reduces the code size by about 2.5KiB on armv7.
+
+ The supported format specifiers are %c, %s, %u/%d and %x.
+
config PANIC_HANG
bool "Do not reset the system on fatal error"
help
@@ -331,6 +353,17 @@ config TPL_TPM
for the low-level TPM interface, but only one TPM is supported at
a time by the TPM library.
+config VPL_TPM
+ bool "Trusted Platform Module (TPM) Support in VPL"
+ depends on VPL_DM
+ help
+ This enables support for TPMs which can be used to provide security
+ features for your board. The TPM can be connected via LPC or I2C
+ and a sandbox TPM is provided for testing purposes. Use the 'tpm'
+ command to interactive the TPM. Driver model support is provided
+ for the low-level TPM interface, but only one TPM is supported at
+ a time by the TPM library.
+
endmenu
menu "Android Verified Boot"
@@ -627,6 +660,27 @@ config TPL_OF_LIBFDT_ASSUME_MASK
0xff means all assumptions are made and any invalid data may cause
unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+config VPL_OF_LIBFDT
+ bool "Enable the FDT library for VPL"
+ default y if VPL_OF_CONTROL && !VPL_OF_PLATDATA
+ help
+ This enables the FDT library (libfdt). It provides functions for
+ accessing binary device tree images in memory, such as adding and
+ removing nodes and properties, scanning through the tree and finding
+ particular compatible nodes. The library operates on a flattened
+ version of the device tree.
+
+config VPL_OF_LIBFDT_ASSUME_MASK
+ hex "Mask of conditions to assume for libfdt"
+ depends on VPL_OF_LIBFDT || FIT
+ default 0xff
+ help
+ Use this to change the assumptions made by libfdt in SPL about the
+ device tree it is working with. A value of 0 means that no assumptions
+ are made, and libfdt is able to deal with malicious data. A value of
+ 0xff means all assumptions are made and any invalid data may cause
+ unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+
config FDT_FIXUP_PARTITIONS
bool "overwrite MTD partitions in DTS through defined in 'mtdparts'"
depends on OF_LIBFDT
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.build b/scripts/Makefile.build
index 705a886cb98..b64a961f6fa 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:
--
2.31.1.607.g51e8a6a459-goog
More information about the U-Boot
mailing list