summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/memlayout.h5
-rw-r--r--src/vboot/Kconfig8
-rw-r--r--src/vboot/vboot_loader.c84
3 files changed, 50 insertions, 47 deletions
diff --git a/src/include/memlayout.h b/src/include/memlayout.h
index a68b21f4d6..b39a8955c9 100644
--- a/src/include/memlayout.h
+++ b/src/include/memlayout.h
@@ -153,7 +153,10 @@
STR(Verstage exceeded its allotted size! (sz))); \
INCLUDE "verstage/lib/program.ld"
- #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) VERSTAGE(addr, size)
+ #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) \
+ _ = ASSERT(IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE) == 1, \
+ "Must set RETURN_FROM_VERSTAGE to overlap romstage."); \
+ VERSTAGE(addr, size)
#else
#define VERSTAGE(addr, sz) \
REGION(verstage, addr, sz, 1)
diff --git a/src/vboot/Kconfig b/src/vboot/Kconfig
index 0c72d4775e..a92a2fa5e1 100644
--- a/src/vboot/Kconfig
+++ b/src/vboot/Kconfig
@@ -83,7 +83,13 @@ config VBOOT_DISABLE_DEV_ON_RECOVERY
config SEPARATE_VERSTAGE
bool "Vboot verification is built into a separate stage"
default n
- depends on VBOOT
+ depends on VBOOT && VBOOT_STARTS_IN_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
+ not set, the verification code is linked directly into the bootblock
+ or the romstage and runs as part of that stage (cf. related options
+ VBOOT_STARTS_IN_BOOTBLOCK/_ROMSTAGE and RETURN_FROM_VERSTAGE).
config RETURN_FROM_VERSTAGE
bool "The separate verification stage returns to its caller"
diff --git a/src/vboot/vboot_loader.c b/src/vboot/vboot_loader.c
index 9593358e3b..3629402f7e 100644
--- a/src/vboot/vboot_loader.c
+++ b/src/vboot/vboot_loader.c
@@ -25,75 +25,69 @@
#include <vboot/symbols.h>
#include <vboot/vboot_common.h>
+/* Ensure vboot configuration is valid: */
+_Static_assert(IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK) +
+ IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) == 1,
+ "vboot must either start in bootblock or romstage (not both!)");
+_Static_assert(!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE) ||
+ IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK),
+ "stand-alone verstage must start in (i.e. after) bootblock");
+_Static_assert(!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE) ||
+ IS_ENABLED(CONFIG_SEPARATE_VERSTAGE),
+ "return from verstage only makes sense for separate verstages");
+
/* The stage loading code is compiled and entered from multiple stages. The
* helper functions below attempt to provide more clarity on when certain
* code should be called. */
static int verification_should_run(void)
{
- if (ENV_VERSTAGE && IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
- return 1;
-
- if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) {
- if (ENV_ROMSTAGE &&
- IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
- return 1;
- if (ENV_BOOTBLOCK &&
- IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
- return 1;
- }
-
- return 0;
+ if (IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
+ return ENV_VERSTAGE;
+ else if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
+ return ENV_ROMSTAGE;
+ else if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
+ return ENV_BOOTBLOCK;
+ else
+ die("impossible!");
}
static int verstage_should_load(void)
{
- if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
+ if (IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
+ return ENV_BOOTBLOCK;
+ else
return 0;
-
- if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
- return 1;
-
- if (ENV_BOOTBLOCK && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
- return 1;
-
- return 0;
}
static int vboot_executed CAR_GLOBAL;
int vb2_logic_executed(void)
{
- /* If this stage is supposed to run the vboot logic ensure it has been
- * executed. */
- if (verification_should_run() && car_get_var(vboot_executed))
+ /* If we are in a stage that would load the verstage or execute the
+ vboot logic directly, we store the answer in a global. */
+ if (verstage_should_load() || verification_should_run())
+ return car_get_var(vboot_executed);
+
+ if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) {
+ /* All other stages are "after the bootblock" */
+ return !ENV_BOOTBLOCK;
+ } else if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) {
+ /* Post-RAM stages are "after the romstage" */
+#ifdef __PRE_RAM__
+ return 0;
+#else
return 1;
-
- /* If this stage is supposed to load verstage and verstage is returning
- * back to the calling stage check that it has been executed. */
- if (verstage_should_load() && IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE))
- if (car_get_var(vboot_executed))
- return 1;
-
- /* Handle all other stages post vboot execution. */
- if (!ENV_BOOTBLOCK) {
- if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
- return 1;
- if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) &&
- !ENV_ROMSTAGE)
- return 1;
+#endif
+ } else {
+ die("impossible!");
}
-
- return 0;
}
static void vboot_prepare(void)
{
if (verification_should_run()) {
- /*
- * Note that this path isn't taken when
- * CONFIG_RETURN_FROM_VERSTAGE is employed.
- */
+ /* Note: this path is not used for RETURN_FROM_VERSTAGE */
verstage_main();
car_set_var(vboot_executed, 1);
vb2_save_recovery_reason_vbnv();