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>
---

 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

Reply via email to