security/vboot: Add option to run verstage before bootblock

For AMD's family 17h, verstage can run as a userspace app in the PSP
before the X86 is released. The flags for this have been made generic
to support any other future systems that might run verstage before
the main processor starts.

Although an attempt has been made to make things somewhat generic,
since this is the first and currently only chip to support verstage
before bootblock, there are a number of options which might ultimately
be needed which have currently been left out for simplicity.  Examples
of this are:
- PCI is not currently supported - this is currently just a given
instead of making a separate Kconfig option for it.
- The PSP uses an ARM v7 processor, so that's the only processor that
is getting updated for the verstage-before-bootblock option.

BUG=b:158124527
TEST=Build with following patches

Signed-off-by: Martin Roth <martin@coreboot.org>
Change-Id: I4849777cb7ba9f90fe8428b82c21884d1e662b96
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41814
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
diff --git a/src/security/vboot/Kconfig b/src/security/vboot/Kconfig
index d317cb6..0637edc 100644
--- a/src/security/vboot/Kconfig
+++ b/src/security/vboot/Kconfig
@@ -71,6 +71,13 @@
 	help
 	  VBNV is stored in flash storage
 
+config VBOOT_STARTS_BEFORE_BOOTBLOCK
+	def_bool n
+	select VBOOT_SEPARATE_VERSTAGE
+	help
+	  Firmware verification happens before the main processor is brought
+	  online.
+
 config VBOOT_STARTS_IN_BOOTBLOCK
 	bool
 	default n
@@ -109,7 +116,7 @@
 config VBOOT_SEPARATE_VERSTAGE
 	bool
 	default n
-	depends on VBOOT_STARTS_IN_BOOTBLOCK
+	depends on VBOOT_STARTS_IN_BOOTBLOCK || VBOOT_STARTS_BEFORE_BOOTBLOCK
 	help
 	  If this option is set, vboot verification runs in a standalone stage
 	  that is loaded from the bootblock and exits into romstage. If it is
diff --git a/src/security/vboot/Makefile.inc b/src/security/vboot/Makefile.inc
index bc1dc5c..1e0166e 100644
--- a/src/security/vboot/Makefile.inc
+++ b/src/security/vboot/Makefile.inc
@@ -96,7 +96,9 @@
 bootblock-y += common.c
 verstage-y += vboot_logic.c
 verstage-y += common.c
+ifeq ($(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK),)
 verstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += verstage.c
+endif
 ifeq (${CONFIG_VBOOT_MOCK_SECDATA},y)
 verstage-y += secdata_mock.c
 romstage-y += secdata_mock.c
@@ -122,10 +124,12 @@
 
 $(eval $(call vboot-for-stage,verstage))
 
+ifeq ($(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK),)
 cbfs-files-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += $(CONFIG_CBFS_PREFIX)/verstage
 $(CONFIG_CBFS_PREFIX)/verstage-file := $(objcbfs)/verstage.elf
 $(CONFIG_CBFS_PREFIX)/verstage-type := stage
 $(CONFIG_CBFS_PREFIX)/verstage-compression := $(CBFS_PRERAM_COMPRESS_FLAG)
+endif	# CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK
 
 ifeq ($(CONFIG_ARCH_VERSTAGE_X86_32)$(CONFIG_ARCH_VERSTAGE_X86_64),y)
 $(CONFIG_CBFS_PREFIX)/verstage-options := -a 64 -S ".car.data"
@@ -167,8 +171,8 @@
 # Use $(sort) to cut down on extra spaces that would be translated to commas
 regions-for-file = $(subst $(spc),$(comma),$(sort \
 	$(if $(filter \
-		$(if $(filter y,$(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)),, \
-			%/romstage) \
+		$(if $(filter y,$(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)), \
+			%/romstage,) \
 		mts \
 		%/verstage \
 		locales \
diff --git a/src/security/vboot/common.c b/src/security/vboot/common.c
index db51fa1..0121f56 100644
--- a/src/security/vboot/common.c
+++ b/src/security/vboot/common.c
@@ -18,8 +18,7 @@
 	if (cbmem_possibly_online())
 		wb = cbmem_find(CBMEM_ID_VBOOT_WORKBUF);
 
-	if (wb == NULL && CONFIG(VBOOT_STARTS_IN_BOOTBLOCK) &&
-	    preram_symbols_available())
+	if (wb == NULL && !CONFIG(VBOOT_STARTS_IN_ROMSTAGE) && preram_symbols_available())
 		wb = _vboot2_work;
 
 	assert(wb != NULL);
@@ -76,6 +75,11 @@
 	void *wb_cbmem = cbmem_add(CBMEM_ID_VBOOT_WORKBUF, cbmem_size);
 	assert(wb_cbmem != NULL);
 	/*
+	 * On platforms where VBOOT_STARTS_BEFORE_BOOTBLOCK, the verification
+	 * occurs before the main processor starts running.  The vboot data-
+	 * structure is available in the _vboot2_work memory area as soon
+	 * as the main processor is released.
+	 *
 	 * For platforms where VBOOT_STARTS_IN_BOOTBLOCK, vboot verification
 	 * occurs before CBMEM is brought online, using pre-RAM. In order to
 	 * make vboot data structures available downstream, copy vboot workbuf
@@ -85,7 +89,7 @@
 	 * after CBMEM is brought online.  Directly initialize vboot data
 	 * structures in CBMEM, which will also be available downstream.
 	 */
-	if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK))
+	if (!CONFIG(VBOOT_STARTS_IN_ROMSTAGE))
 		rv = vb2api_relocate(wb_cbmem, _vboot2_work, cbmem_size,
 				     &vboot_ctx);
 	else
diff --git a/src/security/vboot/misc.h b/src/security/vboot/misc.h
index 8af0c82..4701021 100644
--- a/src/security/vboot/misc.h
+++ b/src/security/vboot/misc.h
@@ -57,7 +57,7 @@
 
 static inline int verstage_should_load(void)
 {
-	if (CONFIG(VBOOT_SEPARATE_VERSTAGE))
+	if (CONFIG(VBOOT_SEPARATE_VERSTAGE) && !CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK))
 		return ENV_BOOTBLOCK;
 	else
 		return 0;
@@ -80,6 +80,8 @@
 	} else if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) {
 		/* Post-RAM stages are "after the romstage" */
 		return !ENV_ROMSTAGE_OR_BEFORE;
+	} else if (CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK)) {
+		return !ENV_SEPARATE_VERSTAGE;
 	} else {
 		dead_code();
 	}
diff --git a/src/security/vboot/vboot_loader.c b/src/security/vboot/vboot_loader.c
index dc8ba37..bca4c3e 100644
--- a/src/security/vboot/vboot_loader.c
+++ b/src/security/vboot/vboot_loader.c
@@ -10,11 +10,12 @@
 
 /* Ensure vboot configuration is valid: */
 _Static_assert(CONFIG(VBOOT_STARTS_IN_BOOTBLOCK) +
+	       CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK) +
 	       CONFIG(VBOOT_STARTS_IN_ROMSTAGE) == 1,
-	       "vboot must either start in bootblock or romstage (not both!)");
-_Static_assert(!CONFIG(VBOOT_SEPARATE_VERSTAGE) ||
-	       CONFIG(VBOOT_STARTS_IN_BOOTBLOCK),
-	       "stand-alone verstage must start in (i.e. after) bootblock");
+	       "vboot must start in bootblock, PSP or romstage (but only one!)");
+_Static_assert(!CONFIG(VBOOT_SEPARATE_VERSTAGE) || CONFIG(VBOOT_STARTS_IN_BOOTBLOCK) ||
+	       CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK),
+	       "stand-alone verstage must start in or before bootblock ");
 _Static_assert(!CONFIG(VBOOT_RETURN_FROM_VERSTAGE) ||
 	       CONFIG(VBOOT_SEPARATE_VERSTAGE),
 	       "return from verstage only makes sense for separate verstages");