Merge commit '1269365169791c65a6bf6f364583209195874138' into cros_sdk

Updated vboot_reference to CrOS version 14283.0.0

BUG=b/202788640
TEST=local BE run
RELEASE_NOTE=Updated ChromeOS base to ChromeOS version 14283.0.0.

Change-Id: I7d97e04ac7e527d86cffe43a5edae39be555e908
diff --git a/.checkpatch.conf b/.checkpatch.conf
new file mode 100644
index 0000000..1f93e0e
--- /dev/null
+++ b/.checkpatch.conf
@@ -0,0 +1,21 @@
+# Not Linux, so don't expect a Linux tree.
+--no-tree
+
+# Ignore aspects we don't follow here.
+--ignore BLOCK_COMMENT_STYLE
+--ignore C99_COMMENTS
+--ignore CAMELCASE
+--ignore CONFIG_DESCRIPTION
+--ignore GLOBAL_INITIALISERS
+--ignore INITIALISED_STATIC
+--ignore LINE_SPACING
+--ignore MACRO_WITH_FLOW_CONTROL
+--ignore NEW_TYPEDEFS
+--ignore OPEN_BRACE
+--ignore PREFER_ALIGNED
+--ignore PREFER_PACKED
+--ignore PREFER_PRINTF
+--ignore SPACING
+--ignore SPDX_LICENSE_TAG
+--ignore SPLIT_STRING
+--ignore TRAILING_STATEMENTS
diff --git a/Makefile b/Makefile
index 327b753..82d6a44 100644
--- a/Makefile
+++ b/Makefile
@@ -123,7 +123,7 @@
 
 # Provide default CC and CFLAGS for firmware builds; if you have any -D flags,
 # please add them after this point (e.g., -DVBOOT_DEBUG).
-DEBUG_FLAGS := $(if ${DEBUG},-g -O0,-g -Os)
+DEBUG_FLAGS := $(if ${DEBUG},-g -Og,-g -Os)
 WERROR := -Werror
 FIRMWARE_FLAGS := -nostdinc -ffreestanding -fno-builtin -fno-stack-protector
 COMMON_FLAGS := -pipe ${WERROR} -Wall -Wstrict-prototypes -Wtype-limits \
@@ -171,7 +171,7 @@
 # Needs -Wl because LD is actually set to CC by default.
 LDFLAGS += -Wl,--gc-sections
 
-ifneq (${DEBUG},)
+ifneq (${DEBUG}$(filter-out 0,${TEST_PRINT}),)
 CFLAGS += -DVBOOT_DEBUG
 endif
 
@@ -235,13 +235,6 @@
 CFLAGS += -DDETACHABLE=0
 endif
 
-# pass DIAGNOSTIC_UI= (or =0) to make to disable feature
-ifneq ($(filter-out 0,${DIAGNOSTIC_UI}),)
-CFLAGS += -DDIAGNOSTIC_UI=1
-else
-CFLAGS += -DDIAGNOSTIC_UI=0
-endif
-
 # Confirm physical presence using keyboard
 ifneq ($(filter-out 0,${PHYSICAL_PRESENCE_KEYBOARD}),)
 CFLAGS += -DPHYSICAL_PRESENCE_KEYBOARD=1
@@ -422,12 +415,6 @@
 	firmware/lib20/api_kernel.c \
 	firmware/lib20/kernel.c
 
-# Only add these to firmware and test builds,
-# as regular host builds don't need them
-$(if ${FIRMWARE_ARCH},FWLIB_SRCS,TESTLIB_SRCS) += \
-	firmware/2lib/2ui.c \
-	firmware/2lib/2ui_screens.c \
-
 # TPM lightweight command library
 ifeq (${TPM2_MODE},)
 TLCL_SRCS = \
@@ -445,6 +432,14 @@
 	firmware/lib/tpm_lite/mocked_tlcl.c
 endif
 
+ifneq ($(filter-out 0,${X86_SHA_EXT}),)
+CFLAGS += -DX86_SHA_EXT
+FWLIB_SRCS += \
+	firmware/2lib/2sha256_x86.c
+endif
+# Even if X86_SHA_EXT is 0 we need cflags since this will be compiled for tests
+${BUILD}/firmware/2lib/2sha256_x86.o: CFLAGS += -mssse3 -mno-avx -msha
+
 ifeq (${FIRMWARE_ARCH},)
 # Include BIOS stubs in the firmware library when compiling for host
 # TODO: split out other stub funcs too
@@ -709,11 +704,13 @@
 TEST_NAMES = \
 	tests/cgptlib_test \
 	tests/chromeos_config_tests \
+	tests/gpt_misc_tests \
 	tests/sha_benchmark \
 	tests/subprocess_tests \
 	tests/vboot_api_kernel4_tests \
 	tests/vboot_api_kernel_tests \
 	tests/vboot_kernel_tests \
+	tests/vboot_kernel2_tests \
 	tests/verify_kernel
 
 ifeq (${MOCK_TPM}${TPM2_MODE},)
@@ -753,9 +750,6 @@
 	tests/vb2_secdata_kernel_tests \
 	tests/vb2_sha_api_tests \
 	tests/vb2_sha_tests \
-	tests/vb2_ui_tests \
-	tests/vb2_ui_action_tests \
-	tests/vb2_ui_utility_tests \
 	tests/hmac_test
 
 TEST20_NAMES = \
@@ -774,6 +768,11 @@
 
 TEST_NAMES += ${TEST2X_NAMES} ${TEST20_NAMES} ${TEST21_NAMES}
 
+# This is build-only test since we can't run this without
+# sha-ni extension on x86. To run this test, you have to
+# manually copy executable into compatible machine and run it.
+TEST_NAMES += tests/vb2_sha256_x86_tests
+
 # And a few more...
 ifeq (${TPM2_MODE},)
 TLCL_TEST_NAMES = \
@@ -1095,6 +1094,11 @@
 ${TEST20_BINS}: LIBS += ${FWLIB}
 ${TEST20_BINS}: LDLIBS += ${CRYPTO_LIBS}
 
+# Special build for sha256_x86 test
+X86_SHA256_TEST = ${BUILD_RUN}/tests/vb2_sha256_x86_tests
+${X86_SHA256_TEST}: ${BUILD}/firmware/2lib/2sha256_x86.o
+${X86_SHA256_TEST}: LIBS += ${BUILD}/firmware/2lib/2sha256_x86.o
+
 ${TESTLIB}: ${TESTLIB_OBJS}
 	@${PRINTF} "    RM            $(subst ${BUILD}/,,$@)\n"
 	${Q}rm -f $@
@@ -1255,6 +1259,7 @@
 
 .PHONY: runmisctests
 runmisctests: install_for_test
+	${RUNTEST} ${BUILD_RUN}/tests/gpt_misc_tests
 	${RUNTEST} ${BUILD_RUN}/tests/subprocess_tests
 ifeq (${MOCK_TPM}${TPM2_MODE},)
 # tlcl_tests only works when MOCK_TPM is disabled
@@ -1263,6 +1268,7 @@
 	${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel4_tests
 	${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel_tests
 	${RUNTEST} ${BUILD_RUN}/tests/vboot_kernel_tests
+	${RUNTEST} ${BUILD_RUN}/tests/vboot_kernel2_tests
 
 .PHONY: run2tests
 run2tests: install_for_test
@@ -1285,9 +1291,6 @@
 	${RUNTEST} ${BUILD_RUN}/tests/vb2_secdata_kernel_tests
 	${RUNTEST} ${BUILD_RUN}/tests/vb2_sha_api_tests
 	${RUNTEST} ${BUILD_RUN}/tests/vb2_sha_tests
-	${RUNTEST} ${BUILD_RUN}/tests/vb2_ui_tests
-	${RUNTEST} ${BUILD_RUN}/tests/vb2_ui_action_tests
-	${RUNTEST} ${BUILD_RUN}/tests/vb2_ui_utility_tests
 	${RUNTEST} ${BUILD_RUN}/tests/vb20_api_kernel_tests
 	${RUNTEST} ${BUILD_RUN}/tests/vb20_kernel_tests
 	${RUNTEST} ${BUILD_RUN}/tests/vb21_host_common_tests
diff --git a/OWNERS b/OWNERS
index 2f14d72..74ba71a 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,5 @@
-kitching@chromium.org
 jwerner@chromium.org
-rspangler@chromium.org
+yupingso@chromium.org
+furquan@chromium.org
+hungte@chromium.org
 *
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
index 8770083..54d538d 100644
--- a/PRESUBMIT.cfg
+++ b/PRESUBMIT.cfg
@@ -1,8 +1,12 @@
 [Hook Overrides]
 branch_check: true
+checkpatch_check: true
+long_line_check: false
 signoff_check: true
 
 # We are using Linux style indentation with tabs
 # The indentation is checked by checkpatch not the python script
 tab_check: false
 
+[Hook Overrides Options]
+cros_license_check: --exclude_regex=^\.checkpatch\.conf$
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c
index c3edd0f..2f888fd 100644
--- a/cgpt/cgpt_common.c
+++ b/cgpt/cgpt_common.c
@@ -672,6 +672,8 @@
 const Guid guid_chromeos_reserved = GPT_ENT_TYPE_CHROMEOS_RESERVED;
 const Guid guid_efi =               GPT_ENT_TYPE_EFI;
 const Guid guid_unused =            GPT_ENT_TYPE_UNUSED;
+const Guid guid_chromeos_minios =   GPT_ENT_TYPE_CHROMEOS_MINIOS;
+const Guid guid_chromeos_hibernate = GPT_ENT_TYPE_CHROMEOS_HIBERNATE;
 
 const static struct {
   const Guid *type;
@@ -686,6 +688,8 @@
   {&guid_chromeos_reserved, "reserved", "ChromeOS reserved"},
   {&guid_efi, "efi", "EFI System Partition"},
   {&guid_unused, "unused", "Unused (nonexistent) partition"},
+  {&guid_chromeos_minios, "minios", "ChromeOS miniOS"},
+  {&guid_chromeos_hibernate, "hibernate", "ChromeOS hibernate"},
 };
 
 /* Resolves human-readable GPT type.
diff --git a/firmware/2lib/2api.c b/firmware/2lib/2api.c
index aa1d25d..593a12c 100644
--- a/firmware/2lib/2api.c
+++ b/firmware/2lib/2api.c
@@ -59,6 +59,11 @@
 	if (rv)
 		vb2api_fail(ctx, VB2_RECOVERY_GBB_HEADER, rv);
 
+	/* Check for dev switch */
+	rv = vb2_check_dev_switch(ctx);
+	if (rv)
+		vb2api_fail(ctx, VB2_RECOVERY_DEV_SWITCH, rv);
+
 	/*
 	 * Check for recovery.  Note that this function returns void, since any
 	 * errors result in requesting recovery.  That's also why we don't
@@ -67,20 +72,6 @@
 	 */
 	vb2_check_recovery(ctx);
 
-	/* Check for dev switch */
-	rv = vb2_check_dev_switch(ctx);
-	if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
-		/*
-		 * Error in dev switch processing, and we weren't already
-		 * headed for recovery mode.  Reboot into recovery mode, since
-		 * it's too late to handle those errors this boot, and we need
-		 * to take a different path through the dev switch checking
-		 * code in that case.
-		 */
-		vb2api_fail(ctx, VB2_RECOVERY_DEV_SWITCH, rv);
-		return rv;
-	}
-
 	/*
 	 * Check for possible reasons to ask the firmware to make display
 	 * available.  VB2_CONTEXT_RECOVERY_MODE may have been set above by
diff --git a/firmware/2lib/2ec_sync.c b/firmware/2lib/2ec_sync.c
index 9c49ceb..20490e0 100644
--- a/firmware/2lib/2ec_sync.c
+++ b/firmware/2lib/2ec_sync.c
@@ -212,6 +212,10 @@
 		return VB2_REQUEST_REBOOT_EC_TO_RO;
 	}
 
+	/* We no longer trust the EC once it is already in RW or tries to jump
+	   to RW. */
+	ctx->flags &= ~VB2_CONTEXT_EC_TRUSTED;
+
 	/* Tell EC to jump to RW. It should already be in RW for EFS2. */
 	if (!(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW)) {
 		VB2_DEBUG("jumping to EC-RW\n");
diff --git a/firmware/2lib/2kernel.c b/firmware/2lib/2kernel.c
index 763214d..86fb286 100644
--- a/firmware/2lib/2kernel.c
+++ b/firmware/2lib/2kernel.c
@@ -11,7 +11,7 @@
 #include "2nvstorage.h"
 #include "2rsa.h"
 #include "2secdata.h"
-#include "vboot_kernel.h"
+#include "vboot_api.h"
 
 /**
  * Reset any NVRAM requests.
@@ -157,12 +157,14 @@
 		vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
 	sd->kernel_version = sd->kernel_version_secdata;
 
+	vb2_fill_dev_boot_flags(ctx);
+
 	/* Find the key to use to verify the kernel keyblock */
 	if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
 		/* Load recovery key from GBB. */
 		rv = vb2_gbb_read_recovery_key(ctx, &packed_key, NULL, &wb);
 		if (rv) {
-			if (vb2_allow_recovery(ctx))
+			if (vb2api_allow_recovery(ctx))
 				VB2_DIE("GBB read recovery key failed.\n");
 			else
 				/*
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index 75a9f36..efa33a8 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -375,8 +375,14 @@
 	return VB2_SUCCESS;
 }
 
-void vb2_enable_developer_mode(struct vb2_context *ctx)
+vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx)
 {
+	if (!vb2api_allow_recovery(ctx)) {
+		VB2_DEBUG("ERROR: Can only enable developer mode from manual "
+			  "recovery mode\n");
+		return VB2_ERROR_API_ENABLE_DEV_NOT_ALLOWED;
+	}
+
 	uint32_t flags;
 
 	VB2_DEBUG("Enabling developer mode...\n");
@@ -389,10 +395,29 @@
 		vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1);
 
 	VB2_DEBUG("Mode change will take effect on next reboot\n");
+
+	return VB2_SUCCESS;
+}
+
+vb2_error_t vb2api_disable_developer_mode(struct vb2_context *ctx)
+{
+	if (vb2api_gbb_get_flags(ctx) & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
+		VB2_DEBUG("ERROR: dev mode forced by GBB flag\n");
+		return VB2_ERROR_API_DISABLE_DEV_NOT_ALLOWED;
+	}
+
+	VB2_DEBUG("Leaving dev mode\n");
+	vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
+	return VB2_SUCCESS;
+}
+
+void vb2api_request_diagnostics(struct vb2_context *ctx) {
+	vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
+	VB2_DEBUG("Diagnostics requested\n");
 }
 
 test_mockable
-int vb2_allow_recovery(struct vb2_context *ctx)
+int vb2api_allow_recovery(struct vb2_context *ctx)
 {
 	if (ctx->flags & VB2_CONTEXT_NO_BOOT)
 		return 0;
@@ -432,7 +457,7 @@
 
 	/* But stow recovery reason as subcode for non-manual recovery. */
 	if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) &&
-	    !vb2_allow_recovery(ctx)) {
+	    !vb2api_allow_recovery(ctx)) {
 		VB2_DEBUG("Stow recovery reason as subcode (%#x)\n",
 			  sd->recovery_reason);
 		vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, sd->recovery_reason);
@@ -459,6 +484,11 @@
 	return vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX);
 }
 
+void vb2api_set_locale_id(struct vb2_context *ctx, uint32_t locale_id)
+{
+	vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, locale_id);
+}
+
 void vb2api_export_vbsd(struct vb2_context *ctx, void *dest)
 {
 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
@@ -532,12 +562,12 @@
 
 	switch (vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT)) {
 		case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL:
-			if (vb2_dev_boot_external_allowed(ctx))
+			if (ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED)
 				return VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
 			break;
 
 		case VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW:
-			if (vb2_dev_boot_altfw_allowed(ctx))
+			if (ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED)
 				return VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW;
 			break;
 	}
@@ -545,33 +575,25 @@
 	return VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL;
 }
 
-int vb2_dev_boot_allowed(struct vb2_context *ctx)
+void vb2_fill_dev_boot_flags(struct vb2_context *ctx)
 {
 	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
 
-	if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT))
-		return !!(gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON);
+	if (!vb2_secdata_fwmp_get_flag(ctx,
+				       VB2_SECDATA_FWMP_DEV_DISABLE_BOOT) ||
+	    (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON))
+		ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALLOWED;
 
-	return 1;
-}
+	if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL) ||
+	    (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) ||
+	    vb2_secdata_fwmp_get_flag(ctx,
+				      VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL))
+		ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED;
 
-int vb2_dev_boot_altfw_allowed(struct vb2_context *ctx)
-{
-	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
-
-	return vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW) ||
-	       (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW) ||
-	       vb2_secdata_fwmp_get_flag(ctx,
-					 VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW);
-}
-
-int vb2_dev_boot_external_allowed(struct vb2_context *ctx)
-{
-	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
-
-	return vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL) ||
-	       (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) ||
-	       vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL);
+	if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW) ||
+	    (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW) ||
+	    vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW))
+		ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED;
 }
 
 int vb2api_use_short_dev_screen_delay(struct vb2_context *ctx)
diff --git a/firmware/2lib/2nvstorage.c b/firmware/2lib/2nvstorage.c
index 1cd5ba2..4fd9808 100644
--- a/firmware/2lib/2nvstorage.c
+++ b/firmware/2lib/2nvstorage.c
@@ -80,6 +80,11 @@
 		sd->status |= VB2_SD_STATUS_NV_REINIT;
 
 		/* TODO: unit test for status flag being set */
+	} else {
+#ifndef CHROMEOS_ENVIRONMENT
+		/* Always clear this on first reboot that didn't need reinit. */
+		vb2_nv_set(ctx, VB2_NV_FIRMWARE_SETTINGS_RESET, 0);
+#endif
 	}
 
 	sd->status |= VB2_SD_STATUS_NV_INIT;
@@ -209,6 +214,9 @@
 		return GETBIT(VB2_NV_OFFS_MISC,
 			      VB2_NV_MISC_POST_EC_SYNC_DELAY);
 
+	case VB2_NV_MINIOS_PRIORITY:
+		return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_MINIOS_PRIORITY);
+
 	case VB2_NV_DEPRECATED_DEV_BOOT_FASTBOOT_FULL_CAP:
 	case VB2_NV_DEPRECATED_FASTBOOT_UNLOCK_IN_FW:
 	case VB2_NV_DEPRECATED_ENABLE_ALT_OS_REQUEST:
@@ -416,6 +424,10 @@
 		SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_POST_EC_SYNC_DELAY);
 		break;
 
+	case VB2_NV_MINIOS_PRIORITY:
+		SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_MINIOS_PRIORITY);
+		break;
+
 	case VB2_NV_DEPRECATED_DEV_BOOT_FASTBOOT_FULL_CAP:
 	case VB2_NV_DEPRECATED_FASTBOOT_UNLOCK_IN_FW:
 	case VB2_NV_DEPRECATED_ENABLE_ALT_OS_REQUEST:
diff --git a/firmware/2lib/2sha256.c b/firmware/2lib/2sha256.c
index c361237..0044113 100644
--- a/firmware/2lib/2sha256.c
+++ b/firmware/2lib/2sha256.c
@@ -1,3 +1,8 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
 /* SHA-256 and SHA-512 implementation based on code by Oliver Gay
  * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
  */
@@ -37,6 +42,7 @@
 
 #include "2common.h"
 #include "2sha.h"
+#include "2sha_private.h"
 #include "2sysincludes.h"
 
 #define SHFR(x, n)    (x >> n)
@@ -50,22 +56,6 @@
 #define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
 #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
 
-#define UNPACK32(x, str)				\
-	{						\
-		*((str) + 3) = (uint8_t) ((x)      );	\
-		*((str) + 2) = (uint8_t) ((x) >>  8);	\
-		*((str) + 1) = (uint8_t) ((x) >> 16);	\
-		*((str) + 0) = (uint8_t) ((x) >> 24);	\
-	}
-
-#define PACK32(str, x)						\
-	{							\
-		*(x) =   ((uint32_t) *((str) + 3)      )	\
-			| ((uint32_t) *((str) + 2) <<  8)       \
-			| ((uint32_t) *((str) + 1) << 16)       \
-			| ((uint32_t) *((str) + 0) << 24);      \
-	}
-
 /* Macros used for loops unrolling */
 
 #define SHA256_SCR(i)						\
@@ -77,13 +67,13 @@
 #define SHA256_EXP(a, b, c, d, e, f, g, h, j)				\
 	{								\
 		t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
-			+ sha256_k[j] + w[j];				\
+			+ vb2_sha256_k[j] + w[j];				\
 		t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);       \
 		wv[d] += t1;                                            \
 		wv[h] = t1 + t2;                                        \
 	}
 
-static const uint32_t sha256_h0[8] = {
+const uint32_t vb2_sha256_h0[8] = {
 	0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
 	0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
 };
@@ -93,7 +83,7 @@
 	0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
 };
 
-static const uint32_t sha256_k[64] = {
+const uint32_t vb2_sha256_k[64] = {
 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
 	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
 	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@@ -116,7 +106,7 @@
 void vb2_sha256_init(struct vb2_sha256_context *ctx,
 		     enum vb2_hash_algorithm algo)
 {
-	const uint32_t *h0 = algo == VB2_HASH_SHA224 ? sha224_h0 : sha256_h0;
+	const uint32_t *h0 = algo == VB2_HASH_SHA224 ? sha224_h0 : vb2_sha256_h0;
 
 #ifndef UNROLL_LOOPS
 	int i;
@@ -167,7 +157,7 @@
 
 		for (j = 0; j < 64; j++) {
 			t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
-				+ sha256_k[j] + w[j];
+				+ vb2_sha256_k[j] + w[j];
 			t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
 			wv[7] = wv[6];
 			wv[6] = wv[5];
diff --git a/firmware/2lib/2sha256_x86.c b/firmware/2lib/2sha256_x86.c
new file mode 100644
index 0000000..e80477e
--- /dev/null
+++ b/firmware/2lib/2sha256_x86.c
@@ -0,0 +1,255 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * SHA256 implementation using x86 SHA extension.
+ * Mainly from https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-x86.c,
+ * Written and place in public domain by Jeffrey Walton
+ * Based on code from Intel, and by Sean Gulley for
+ * the miTLS project.
+ */
+#include "2common.h"
+#include "2sha.h"
+#include "2sha_private.h"
+#include "2api.h"
+
+static struct vb2_sha256_context sha_ctx;
+
+typedef int vb2_m128i __attribute__ ((vector_size(16)));
+
+static inline vb2_m128i vb2_loadu_si128(vb2_m128i *ptr)
+{
+	vb2_m128i result;
+	asm volatile ("movups %1, %0" : "=x"(result) : "m"(*ptr));
+	return result;
+}
+
+static inline void vb2_storeu_si128(vb2_m128i *to, vb2_m128i from)
+{
+	asm volatile ("movups %1, %0" : "=m"(*to) : "x"(from));
+}
+
+static inline vb2_m128i vb2_add_epi32(vb2_m128i a, vb2_m128i b)
+{
+	return a + b;
+}
+
+static inline vb2_m128i vb2_shuffle_epi8(vb2_m128i value, vb2_m128i mask)
+{
+	asm ("pshufb %1, %0" : "+x"(value) : "xm"(mask));
+	return value;
+}
+
+static inline vb2_m128i vb2_shuffle_epi32(vb2_m128i value, int mask)
+{
+	vb2_m128i result;
+	asm ("pshufd %2, %1, %0" : "=x"(result) : "xm"(value), "i" (mask));
+	return result;
+}
+
+static inline vb2_m128i vb2_alignr_epi8(vb2_m128i a, vb2_m128i b, int imm8)
+{
+	asm ("palignr %2, %1, %0" : "+x"(a) : "xm"(b), "i"(imm8));
+	return a;
+}
+
+static inline vb2_m128i vb2_sha256msg1_epu32(vb2_m128i a, vb2_m128i b)
+{
+	asm ("sha256msg1 %1, %0" : "+x"(a) : "xm"(b));
+	return a;
+}
+
+static inline vb2_m128i vb2_sha256msg2_epu32(vb2_m128i a, vb2_m128i b)
+{
+	asm ("sha256msg2 %1, %0" : "+x"(a) : "xm"(b));
+	return a;
+}
+
+static inline vb2_m128i vb2_sha256rnds2_epu32(vb2_m128i a, vb2_m128i b,
+                                              vb2_m128i k)
+{
+	asm ("sha256rnds2 %1, %0" : "+x"(a) : "xm"(b), "Yz"(k));
+	return a;
+}
+
+#define SHA256_X86_PUT_STATE1(j, i) 					\
+	{								\
+		msgtmp[j] = vb2_loadu_si128((vb2_m128i *)			\
+				(message + (i << 6) + (j * 16)));	\
+		msgtmp[j] = vb2_shuffle_epi8(msgtmp[j], shuf_mask);	\
+		msg = vb2_add_epi32(msgtmp[j],				\
+			vb2_loadu_si128((vb2_m128i *)&vb2_sha256_k[j * 4]));	\
+		state1 = vb2_sha256rnds2_epu32(state1, state0, msg);	\
+	}
+
+#define SHA256_X86_PUT_STATE0()						\
+	{								\
+		msg    = vb2_shuffle_epi32(msg, 0x0E);			\
+		state0 = vb2_sha256rnds2_epu32(state0, state1, msg);	\
+	}
+
+#define SHA256_X86_LOOP(j)						\
+	{								\
+		int k = j & 3;						\
+		int prev_k = (k + 3) & 3;				\
+		int next_k = (k + 1) & 3;				\
+		msg = vb2_add_epi32(msgtmp[k],				\
+			vb2_loadu_si128((vb2_m128i *)&vb2_sha256_k[j * 4]));	\
+		state1 = vb2_sha256rnds2_epu32(state1, state0, msg);	\
+		tmp = vb2_alignr_epi8(msgtmp[k], msgtmp[prev_k], 4);	\
+		msgtmp[next_k] = vb2_add_epi32(msgtmp[next_k], tmp);	\
+		msgtmp[next_k] = vb2_sha256msg2_epu32(msgtmp[next_k],	\
+					msgtmp[k]);			\
+		SHA256_X86_PUT_STATE0();				\
+		msgtmp[prev_k] = vb2_sha256msg1_epu32(msgtmp[prev_k],	\
+				msgtmp[k]);				\
+	}
+
+static void vb2_sha256_transform_x86ext(const uint8_t *message,
+					unsigned int block_nb)
+{
+	vb2_m128i state0, state1, msg, abef_save, cdgh_save;
+	vb2_m128i msgtmp[4];
+	vb2_m128i tmp;
+	int i;
+	const vb2_m128i shuf_mask = {0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f};
+
+	state0 = vb2_loadu_si128((vb2_m128i *)&sha_ctx.h[0]);
+	state1 = vb2_loadu_si128((vb2_m128i *)&sha_ctx.h[4]);
+	for (i = 0; i < (int) block_nb; i++) {
+		abef_save = state0;
+		cdgh_save = state1;
+
+		SHA256_X86_PUT_STATE1(0, i);
+		SHA256_X86_PUT_STATE0();
+
+		SHA256_X86_PUT_STATE1(1, i);
+		SHA256_X86_PUT_STATE0();
+		msgtmp[0] = vb2_sha256msg1_epu32(msgtmp[0], msgtmp[1]);
+
+		SHA256_X86_PUT_STATE1(2, i);
+		SHA256_X86_PUT_STATE0();
+		msgtmp[1] = vb2_sha256msg1_epu32(msgtmp[1], msgtmp[2]);
+
+		SHA256_X86_PUT_STATE1(3, i);
+		tmp = vb2_alignr_epi8(msgtmp[3], msgtmp[2], 4);
+		msgtmp[0] = vb2_add_epi32(msgtmp[0], tmp);
+		msgtmp[0] = vb2_sha256msg2_epu32(msgtmp[0], msgtmp[3]);
+		SHA256_X86_PUT_STATE0();
+		msgtmp[2] = vb2_sha256msg1_epu32(msgtmp[2], msgtmp[3]);
+
+		SHA256_X86_LOOP(4);
+		SHA256_X86_LOOP(5);
+		SHA256_X86_LOOP(6);
+		SHA256_X86_LOOP(7);
+		SHA256_X86_LOOP(8);
+		SHA256_X86_LOOP(9);
+		SHA256_X86_LOOP(10);
+		SHA256_X86_LOOP(11);
+		SHA256_X86_LOOP(12);
+		SHA256_X86_LOOP(13);
+		SHA256_X86_LOOP(14);
+
+		msg = vb2_add_epi32(msgtmp[3],
+			vb2_loadu_si128((vb2_m128i *)&vb2_sha256_k[15 * 4]));
+		state1 = vb2_sha256rnds2_epu32(state1, state0, msg);
+		SHA256_X86_PUT_STATE0();
+
+		state0 = vb2_add_epi32(state0, abef_save);
+		state1 = vb2_add_epi32(state1, cdgh_save);
+
+	}
+
+	vb2_storeu_si128((vb2_m128i *)&sha_ctx.h[0], state0);
+	vb2_storeu_si128((vb2_m128i *)&sha_ctx.h[4], state1);
+}
+
+vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
+				       uint32_t data_size)
+{
+	if (hash_alg != VB2_HASH_SHA256)
+		return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
+
+	sha_ctx.h[0] = vb2_sha256_h0[5];
+	sha_ctx.h[1] = vb2_sha256_h0[4];
+	sha_ctx.h[2] = vb2_sha256_h0[1];
+	sha_ctx.h[3] = vb2_sha256_h0[0];
+	sha_ctx.h[4] = vb2_sha256_h0[7];
+	sha_ctx.h[5] = vb2_sha256_h0[6];
+	sha_ctx.h[6] = vb2_sha256_h0[3];
+	sha_ctx.h[7] = vb2_sha256_h0[2];
+	sha_ctx.size = 0;
+	sha_ctx.total_size = 0;
+	memset(sha_ctx.block, 0, sizeof(sha_ctx.block));
+
+	return VB2_SUCCESS;
+}
+
+vb2_error_t vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size)
+{
+	unsigned int remaining_blocks;
+	unsigned int new_size, rem_size, tmp_size;
+	const uint8_t *shifted_data;
+
+	tmp_size = VB2_SHA256_BLOCK_SIZE - sha_ctx.size;
+	rem_size = size < tmp_size ? size : tmp_size;
+
+	memcpy(&sha_ctx.block[sha_ctx.size], buf, rem_size);
+
+	if (sha_ctx.size + size < VB2_SHA256_BLOCK_SIZE) {
+		sha_ctx.size += size;
+		return VB2_SUCCESS;
+	}
+
+	new_size = size - rem_size;
+	remaining_blocks = new_size / VB2_SHA256_BLOCK_SIZE;
+
+	shifted_data = buf + rem_size;
+
+	vb2_sha256_transform_x86ext(sha_ctx.block, 1);
+	vb2_sha256_transform_x86ext(shifted_data, remaining_blocks);
+
+	rem_size = new_size % VB2_SHA256_BLOCK_SIZE;
+
+	memcpy(sha_ctx.block, &shifted_data[remaining_blocks * VB2_SHA256_BLOCK_SIZE],
+	       rem_size);
+
+	sha_ctx.size = rem_size;
+	sha_ctx.total_size += (remaining_blocks + 1) * VB2_SHA256_BLOCK_SIZE;
+	return VB2_SUCCESS;
+}
+
+vb2_error_t vb2ex_hwcrypto_digest_finalize(uint8_t *digest,
+					   uint32_t digest_size)
+{
+	unsigned int block_nb;
+	unsigned int pm_size;
+	unsigned int size_b;
+	unsigned int block_rem_size = sha_ctx.size % VB2_SHA256_BLOCK_SIZE;
+	if (digest_size != VB2_SHA256_DIGEST_SIZE) {
+		VB2_DEBUG("ERROR: Digest size does not match expected length.\n");
+		return VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE;
+	}
+
+	block_nb = (1 + ((VB2_SHA256_BLOCK_SIZE - SHA256_MIN_PAD_LEN)
+				< block_rem_size));
+
+	size_b = (sha_ctx.total_size + sha_ctx.size) * 8;
+	pm_size = block_nb * VB2_SHA256_BLOCK_SIZE;
+
+	memset(sha_ctx.block + sha_ctx.size, 0, pm_size - sha_ctx.size);
+	sha_ctx.block[sha_ctx.size] = SHA256_PAD_BEGIN;
+	UNPACK32(size_b, sha_ctx.block + pm_size - 4);
+
+	vb2_sha256_transform_x86ext(sha_ctx.block, block_nb);
+
+	UNPACK32(sha_ctx.h[3], &digest[ 0]);
+	UNPACK32(sha_ctx.h[2], &digest[ 4]);
+	UNPACK32(sha_ctx.h[7], &digest[ 8]);
+	UNPACK32(sha_ctx.h[6], &digest[12]);
+	UNPACK32(sha_ctx.h[1], &digest[16]);
+	UNPACK32(sha_ctx.h[0], &digest[20]);
+	UNPACK32(sha_ctx.h[5], &digest[24]);
+	UNPACK32(sha_ctx.h[4], &digest[28]);
+	return VB2_SUCCESS;
+}
diff --git a/firmware/2lib/2stub.c b/firmware/2lib/2stub.c
index 7cec2e5..956b4bb 100644
--- a/firmware/2lib/2stub.c
+++ b/firmware/2lib/2stub.c
@@ -50,7 +50,7 @@
 				enum vb2_resource_index index, uint32_t offset,
 				void *buf, uint32_t size)
 {
-	fprintf(stderr, "%s: function not implemented\n", __func__);
+	VB2_DEBUG("function not implemented\n");
 	return VB2_ERROR_EX_UNIMPLEMENTED;
 }
 
@@ -60,14 +60,14 @@
 __attribute__((weak))
 vb2_error_t vb2ex_tpm_clear_owner(struct vb2_context *ctx)
 {
-	fprintf(stderr, "%s: function not implemented\n", __func__);
+	VB2_DEBUG("function not implemented\n");
 	return VB2_ERROR_EX_UNIMPLEMENTED;
 }
 
 __attribute__((weak))
 vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val)
 {
-	fprintf(stderr, "%s: function not implemented\n", __func__);
+	VB2_DEBUG("function not implemented\n");
 	return VB2_ERROR_EX_UNIMPLEMENTED;
 }
 
@@ -201,12 +201,6 @@
 }
 
 __attribute__((weak))
-vb2_error_t vb2ex_diag_storage_test_control(enum vb2_diag_storage_test ops)
-{
-	return VB2_SUCCESS;
-}
-
-__attribute__((weak))
 vb2_error_t vb2ex_diag_memory_quick_test(int reset, const char **out)
 {
 	*out = "mock";
@@ -256,3 +250,27 @@
 	ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
 	return VB2_SUCCESS;
 }
+
+__attribute__((weak))
+vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *ctx)
+{
+	return VB2_SUCCESS;
+}
+
+__attribute__((weak))
+vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *ctx)
+{
+	return VB2_SUCCESS;
+}
+
+__attribute__((weak))
+vb2_error_t vb2ex_developer_ui(struct vb2_context *ctx)
+{
+	return VB2_SUCCESS;
+}
+
+__attribute__((weak))
+vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *ctx)
+{
+	return VB2_SUCCESS;
+}
diff --git a/firmware/2lib/2stub_hwcrypto.c b/firmware/2lib/2stub_hwcrypto.c
index 56272ad..87fb733 100644
--- a/firmware/2lib/2stub_hwcrypto.c
+++ b/firmware/2lib/2stub_hwcrypto.c
@@ -7,6 +7,7 @@
 
 #include "2api.h"
 
+#ifndef X86_SHA_EXT
 __attribute__((weak))
 vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
 				       uint32_t data_size)
@@ -26,6 +27,7 @@
 {
 	return VB2_ERROR_SHA_FINALIZE_ALGORITHM;  /* Should not be called. */
 }
+#endif
 
 __attribute__((weak))
 vb2_error_t vb2ex_hwcrypto_rsa_verify_digest(const struct vb2_public_key *key,
diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c
deleted file mode 100644
index 7173450..0000000
--- a/firmware/2lib/2ui.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * User interfaces for developer and recovery mode menus.
- */
-
-#include "2api.h"
-#include "2common.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2return_codes.h"
-#include "2ui.h"
-#include "2ui_private.h"
-#include "vboot_api.h"  /* For VB_SHUTDOWN_REQUEST_POWER_BUTTON */
-#include "vboot_kernel.h"
-
-/*****************************************************************************/
-/* Utility functions */
-
-/**
- * Check GBB flags against VbExIsShutdownRequested() shutdown request,
- * and check for VB_BUTTON_POWER_SHORT_PRESS key, to determine if a
- * shutdown is required.
- *
- * @param ui		UI context pointer
- * @return VB2_REQUEST_SHUTDOWN if shutdown needed, or VB2_SUCCESS
- */
-vb2_error_t check_shutdown_request(struct vb2_ui_context *ui)
-{
-	struct vb2_gbb_header *gbb = vb2_get_gbb(ui->ctx);
-	uint32_t shutdown_request = VbExIsShutdownRequested();
-
-	/*
-	 * Ignore power button push until after we have seen it released.
-	 * This avoids shutting down immediately if the power button is still
-	 * being held on startup. After we've recognized a valid power button
-	 * push then don't report the event until after the button is released.
-	 */
-	if (shutdown_request & VB_SHUTDOWN_REQUEST_POWER_BUTTON) {
-		shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-		if (ui->power_button == VB2_POWER_BUTTON_RELEASED)
-			ui->power_button = VB2_POWER_BUTTON_PRESSED;
-	} else {
-		if (ui->power_button == VB2_POWER_BUTTON_PRESSED)
-			shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-		ui->power_button = VB2_POWER_BUTTON_RELEASED;
-	}
-
-	if (ui->key == VB_BUTTON_POWER_SHORT_PRESS)
-		shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-
-	/* If desired, ignore shutdown request due to lid closure. */
-	if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN)
-		shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED;
-
-	/*
-	 * In detachables, disable shutdown due to power button.
-	 * It is used for menu selection instead.
-	 */
-	if (DETACHABLE)
-		shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-
-	if (shutdown_request)
-		return VB2_REQUEST_SHUTDOWN;
-
-	return VB2_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Error action functions */
-
-vb2_error_t error_exit_action(struct vb2_ui_context *ui)
-{
-	/*
-	 * If an error message is currently shown on the screen, any
-	 * key press clears that error.  Unset the key so that it is
-	 * not processed by other action functions.
-	 */
-	if (ui->key && ui->error_code) {
-		ui->error_code = VB2_UI_ERROR_NONE;
-		ui->key = 0;
-	}
-	return VB2_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Menu navigation functions */
-
-const struct vb2_menu *get_menu(struct vb2_ui_context *ui)
-{
-	const struct vb2_menu *menu;
-	static const struct vb2_menu empty_menu = {
-		.num_items = 0,
-		.items = NULL,
-	};
-	if (ui->state->screen->get_menu) {
-		menu = ui->state->screen->get_menu(ui);
-		return menu ? menu : &empty_menu;
-	} else {
-		return &ui->state->screen->menu;
-	}
-}
-
-vb2_error_t menu_navigation_action(struct vb2_ui_context *ui)
-{
-	uint32_t key = ui->key;
-
-	/* Map detachable button presses for simplicity. */
-	if (DETACHABLE) {
-		if (key == VB_BUTTON_VOL_UP_SHORT_PRESS)
-			key = VB_KEY_UP;
-		else if (key == VB_BUTTON_VOL_DOWN_SHORT_PRESS)
-			key = VB_KEY_DOWN;
-		else if (key == VB_BUTTON_POWER_SHORT_PRESS)
-			key = VB_KEY_ENTER;
-	}
-
-	switch (key) {
-	case VB_KEY_UP:
-		return vb2_ui_menu_prev(ui);
-	case VB_KEY_DOWN:
-		return vb2_ui_menu_next(ui);
-	case VB_KEY_ENTER:
-		return vb2_ui_menu_select(ui);
-	case VB_KEY_ESC:
-		return vb2_ui_screen_back(ui);
-	default:
-		if (key != 0)
-			VB2_DEBUG("Pressed key %#x, trusted? %d\n",
-				  ui->key, ui->key_trusted);
-	}
-
-	return VB2_SUCCESS;
-}
-
-vb2_error_t vb2_ui_menu_prev(struct vb2_ui_context *ui)
-{
-	int item;
-
-	if (!DETACHABLE && ui->key == VB_BUTTON_VOL_UP_SHORT_PRESS)
-		return VB2_SUCCESS;
-
-	item = ui->state->selected_item - 1;
-	while (item >= 0 && VB2_GET_BIT(ui->state->hidden_item_mask, item))
-		item--;
-	/* Only update if item is valid */
-	if (item >= 0)
-		ui->state->selected_item = item;
-
-	return VB2_SUCCESS;
-}
-
-vb2_error_t vb2_ui_menu_next(struct vb2_ui_context *ui)
-{
-	int item;
-	const struct vb2_menu *menu;
-
-	if (!DETACHABLE && ui->key == VB_BUTTON_VOL_DOWN_SHORT_PRESS)
-		return VB2_SUCCESS;
-
-	menu = get_menu(ui);
-	item = ui->state->selected_item + 1;
-	while (item < menu->num_items &&
-	       VB2_GET_BIT(ui->state->hidden_item_mask, item))
-		item++;
-	/* Only update if item is valid */
-	if (item < menu->num_items)
-		ui->state->selected_item = item;
-
-	return VB2_SUCCESS;
-}
-
-vb2_error_t vb2_ui_menu_select(struct vb2_ui_context *ui)
-{
-	const struct vb2_menu *menu;
-	const struct vb2_menu_item *menu_item;
-
-	if (!DETACHABLE && ui->key == VB_BUTTON_POWER_SHORT_PRESS)
-		return VB2_SUCCESS;
-
-	menu = get_menu(ui);
-	if (menu->num_items == 0)
-		return VB2_SUCCESS;
-
-	menu_item = &menu->items[ui->state->selected_item];
-
-	/* Cannot select a disabled menu item */
-	if (VB2_GET_BIT(ui->state->disabled_item_mask,
-			ui->state->selected_item)) {
-		VB2_DEBUG("Menu item <%s> disabled; ignoring\n",
-			  menu_item->text);
-		return VB2_SUCCESS;
-	}
-
-	if (menu_item->action) {
-		VB2_DEBUG("Menu item <%s> run action\n", menu_item->text);
-		return menu_item->action(ui);
-	} else if (menu_item->target) {
-		VB2_DEBUG("Menu item <%s> to target screen %#x\n",
-			  menu_item->text, menu_item->target);
-		return vb2_ui_screen_change(ui, menu_item->target);
-	}
-
-	VB2_DEBUG("Menu item <%s> no action or target screen\n",
-		  menu_item->text);
-	return VB2_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Screen navigation functions */
-
-vb2_error_t vb2_ui_screen_back(struct vb2_ui_context *ui)
-{
-	struct vb2_screen_state *tmp;
-
-	if (ui->state && ui->state->prev) {
-		tmp = ui->state->prev;
-		free(ui->state);
-		ui->state = tmp;
-		if (ui->state->screen->reinit)
-			VB2_TRY(ui->state->screen->reinit(ui));
-	} else {
-		VB2_DEBUG("ERROR: No previous screen; ignoring\n");
-	}
-
-	return VB2_REQUEST_UI_CONTINUE;
-}
-
-static vb2_error_t default_screen_init(struct vb2_ui_context *ui)
-{
-	const struct vb2_menu *menu = get_menu(ui);
-	ui->state->selected_item = 0;
-	if (menu->num_items > 1 && menu->items[0].is_language_select)
-		ui->state->selected_item = 1;
-	return VB2_SUCCESS;
-}
-
-vb2_error_t vb2_ui_screen_change(struct vb2_ui_context *ui, enum vb2_screen id)
-{
-	const struct vb2_screen_info *new_screen_info;
-	struct vb2_screen_state *cur_state;
-	int state_exists = 0;
-
-	new_screen_info = vb2_get_screen_info(id);
-	if (new_screen_info == NULL) {
-		VB2_DEBUG("ERROR: Screen entry %#x not found; ignoring\n", id);
-		return VB2_REQUEST_UI_CONTINUE;
-	}
-
-	/* Check to see if the screen state already exists in our stack. */
-	cur_state = ui->state;
-	while (cur_state != NULL) {
-		if (cur_state->screen->id == id) {
-			state_exists = 1;
-			break;
-		}
-		cur_state = cur_state->prev;
-	}
-
-	if (state_exists) {
-		/* Pop until the requested screen is at the top of stack. */
-		while (ui->state->screen->id != id) {
-			cur_state = ui->state;
-			ui->state = cur_state->prev;
-			free(cur_state);
-		}
-		if (ui->state->screen->reinit)
-			VB2_TRY(ui->state->screen->reinit(ui));
-	} else {
-		/* Allocate the requested screen on top of the stack. */
-		cur_state = malloc(sizeof(*ui->state));
-		memset(cur_state, 0, sizeof(*ui->state));
-		if (cur_state == NULL) {
-			VB2_DEBUG("WARNING: malloc failed; ignoring\n");
-			return VB2_REQUEST_UI_CONTINUE;
-		}
-		cur_state->prev = ui->state;
-		cur_state->screen = new_screen_info;
-		ui->state = cur_state;
-		if (ui->state->screen->init)
-			VB2_TRY(ui->state->screen->init(ui));
-		else
-			VB2_TRY(default_screen_init(ui));
-	}
-
-	return VB2_REQUEST_UI_CONTINUE;
-}
-
-/*****************************************************************************/
-/* Core UI loop */
-
-static vb2_error_t ui_loop_impl(
-	struct vb2_context *ctx, enum vb2_screen root_screen_id,
-	vb2_error_t (*global_action)(struct vb2_ui_context *ui))
-{
-	struct vb2_ui_context ui;
-	struct vb2_screen_state prev_state;
-	int prev_disable_timer;
-	enum vb2_ui_error prev_error_code;
-	const struct vb2_menu *menu;
-	const struct vb2_screen_info *root_info;
-	uint32_t key_flags;
-	uint32_t start_time_ms, elapsed_ms;
-	vb2_error_t rv;
-
-	memset(&ui, 0, sizeof(ui));
-	ui.ctx = ctx;
-	root_info = vb2_get_screen_info(root_screen_id);
-	if (root_info == NULL)
-		VB2_DIE("Root screen not found.\n");
-	ui.locale_id = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX);
-
-	rv = vb2_ui_screen_change(&ui, root_screen_id);
-	if (rv && rv != VB2_REQUEST_UI_CONTINUE)
-		return rv;
-
-	memset(&prev_state, 0, sizeof(prev_state));
-	prev_disable_timer = 0;
-	prev_error_code = VB2_UI_ERROR_NONE;
-
-	while (1) {
-		start_time_ms = vb2ex_mtime();
-
-		/* Draw if there are state changes. */
-		if (memcmp(&prev_state, ui.state, sizeof(*ui.state)) ||
-		    /* Redraw when timer is disabled. */
-		    prev_disable_timer != ui.disable_timer ||
-		    /* Redraw/beep on a transition. */
-		    prev_error_code != ui.error_code ||
-		    /* Beep. */
-		    ui.error_beep != 0 ||
-		    /* Redraw on a screen request to refresh. */
-		    ui.force_display) {
-
-			menu = get_menu(&ui);
-			VB2_DEBUG("<%s> menu item <%s>\n",
-				  ui.state->screen->name,
-				  menu->num_items ?
-				  menu->items[ui.state->selected_item].text :
-				  "null");
-			vb2ex_display_ui(ui.state->screen->id, ui.locale_id,
-					 ui.state->selected_item,
-					 ui.state->disabled_item_mask,
-					 ui.state->hidden_item_mask,
-					 ui.disable_timer,
-					 ui.state->current_page,
-					 ui.error_code);
-			if (ui.error_beep ||
-			    (ui.error_code &&
-			     prev_error_code != ui.error_code)) {
-				vb2ex_beep(250, 400);
-				ui.error_beep = 0;
-			}
-
-			/* Reset refresh flag. */
-			ui.force_display = 0;
-
-			/* Update prev variables. */
-			memcpy(&prev_state, ui.state, sizeof(*ui.state));
-			prev_disable_timer = ui.disable_timer;
-			prev_error_code = ui.error_code;
-		}
-
-		/* Grab new keyboard input. */
-		ui.key = VbExKeyboardReadWithFlags(&key_flags);
-		ui.key_trusted = !!(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD);
-
-		/* Check for shutdown request. */
-		rv = check_shutdown_request(&ui);
-		if (rv && rv != VB2_REQUEST_UI_CONTINUE) {
-			VB2_DEBUG("Shutdown requested!\n");
-			return rv;
-		}
-
-		/* Check if we need to exit an error box. */
-		rv = error_exit_action(&ui);
-		if (rv && rv != VB2_REQUEST_UI_CONTINUE)
-			return rv;
-
-		/* Run screen action. */
-		if (ui.state->screen->action) {
-			rv = ui.state->screen->action(&ui);
-			if (rv && rv != VB2_REQUEST_UI_CONTINUE)
-				return rv;
-		}
-
-		/* Run menu navigation action. */
-		rv = menu_navigation_action(&ui);
-		if (rv && rv != VB2_REQUEST_UI_CONTINUE)
-			return rv;
-
-		/* Run global action function if available. */
-		if (global_action) {
-			rv = global_action(&ui);
-			if (rv && rv != VB2_REQUEST_UI_CONTINUE)
-				return rv;
-		}
-
-		/* Delay. */
-		elapsed_ms = vb2ex_mtime() - start_time_ms;
-		if (elapsed_ms < KEY_DELAY_MS)
-			vb2ex_msleep(KEY_DELAY_MS - elapsed_ms);
-	}
-
-	return VB2_SUCCESS;
-}
-
-vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id,
-		    vb2_error_t (*global_action)(struct vb2_ui_context *ui))
-{
-	vb2_error_t rv = ui_loop_impl(ctx, root_screen_id, global_action);
-	if (rv == VB2_REQUEST_UI_EXIT)
-		return VB2_SUCCESS;
-	return rv;
-}
-
-/*****************************************************************************/
-/* Developer mode */
-
-vb2_error_t vb2_developer_menu(struct vb2_context *ctx)
-{
-	enum vb2_screen root_screen_id = VB2_SCREEN_DEVELOPER_MODE;
-	if (!vb2_dev_boot_allowed(ctx)) {
-		VB2_DEBUG("WARNING: Dev boot not allowed; forcing to-norm\n");
-		root_screen_id = VB2_SCREEN_DEVELOPER_TO_NORM;
-	}
-	return ui_loop(ctx, root_screen_id, developer_action);
-}
-
-vb2_error_t developer_action(struct vb2_ui_context *ui)
-{
-	/* Developer mode keyboard shortcuts */
-	if (ui->key == '\t')
-		return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO);
-
-	/* Ignore other shortcuts */
-	if (!vb2_dev_boot_allowed(ui->ctx))
-		return VB2_REQUEST_UI_CONTINUE;
-
-	if (ui->key == VB_KEY_CTRL('S'))
-		return vb2_ui_screen_change(ui, VB2_SCREEN_DEVELOPER_TO_NORM);
-	if (ui->key == VB_KEY_CTRL('U') ||
-	    (DETACHABLE && ui->key == VB_BUTTON_VOL_UP_LONG_PRESS))
-		return vb2_ui_developer_mode_boot_external_action(ui);
-	if (ui->key == VB_KEY_CTRL('D') ||
-	    (DETACHABLE && ui->key == VB_BUTTON_VOL_DOWN_LONG_PRESS))
-		return vb2_ui_developer_mode_boot_internal_action(ui);
-	if (ui->key == VB_KEY_CTRL('L'))  /* L for aLtfw (formerly Legacy) */
-		return vb2_ui_developer_mode_boot_altfw_action(ui);
-
-	return VB2_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Broken recovery */
-
-vb2_error_t vb2_broken_recovery_menu(struct vb2_context *ctx)
-{
-	return ui_loop(ctx, VB2_SCREEN_RECOVERY_BROKEN, broken_recovery_action);
-}
-
-vb2_error_t broken_recovery_action(struct vb2_ui_context *ui)
-{
-	/* Broken recovery keyboard shortcuts */
-	if (ui->key == '\t')
-		return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO);
-
-	return VB2_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Manual recovery */
-
-vb2_error_t vb2_manual_recovery_menu(struct vb2_context *ctx)
-{
-	return ui_loop(ctx, VB2_SCREEN_RECOVERY_SELECT, manual_recovery_action);
-}
-
-vb2_error_t manual_recovery_action(struct vb2_ui_context *ui)
-{
-	/* See if we have a recovery kernel available yet. */
-	vb2_error_t rv = VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_REMOVABLE);
-	if (rv == VB2_SUCCESS)
-		return VB2_REQUEST_UI_EXIT;
-
-	/* If disk validity state changed, switch to appropriate screen. */
-	if (ui->recovery_rv != rv) {
-		VB2_DEBUG("Recovery VbTryLoadKernel %#x --> %#x\n",
-			  ui->recovery_rv, rv);
-		ui->recovery_rv = rv;
-		return vb2_ui_screen_change(ui,
-					    rv == VB2_ERROR_LK_NO_DISK_FOUND ?
-					    VB2_SCREEN_RECOVERY_SELECT :
-					    VB2_SCREEN_RECOVERY_INVALID);
-	}
-
-	/* Manual recovery keyboard shortcuts */
-	if (ui->key == VB_KEY_CTRL('D') ||
-	    (DETACHABLE && ui->key == VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS))
-		return vb2_ui_screen_change(ui, VB2_SCREEN_RECOVERY_TO_DEV);
-
-	if (ui->key == '\t')
-		return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO);
-
-	return VB2_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Diagnostics */
-
-vb2_error_t vb2_diagnostic_menu(struct vb2_context *ctx)
-{
-	return ui_loop(ctx, VB2_SCREEN_DIAGNOSTICS, NULL);
-}
diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c
deleted file mode 100644
index a9359b5..0000000
--- a/firmware/2lib/2ui_screens.c
+++ /dev/null
@@ -1,1407 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Firmware screen definitions.
- */
-
-#include "2api.h"
-#include "2common.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2ui.h"
-#include "2ui_private.h"
-#include "vboot_api.h"
-#include "vboot_kernel.h"
-
-#define MENU_ITEMS(a) ((struct vb2_menu){ \
-	.num_items = ARRAY_SIZE(a), \
-	.items = a, \
-})
-
-#define LANGUAGE_SELECT_ITEM ((struct vb2_menu_item){ \
-	.text = "Language selection", \
-	.target = VB2_SCREEN_LANGUAGE_SELECT, \
-	.is_language_select = 1, \
-})
-
-#define NEXT_ITEM(target_screen) ((struct vb2_menu_item){ \
-	.text = "Next", \
-	.target = (target_screen), \
-})
-
-#define BACK_ITEM ((struct vb2_menu_item){ \
-	.text = "Back", \
-	.action = vb2_ui_screen_back, \
-})
-
-#define ADVANCED_OPTIONS_ITEM ((struct vb2_menu_item){ \
-	.text = "Advanced options", \
-	.target = VB2_SCREEN_ADVANCED_OPTIONS, \
-})
-
-/* Action that will power off the device. */
-static vb2_error_t power_off_action(struct vb2_ui_context *ui)
-{
-	return VB2_REQUEST_SHUTDOWN;
-}
-
-#define POWER_OFF_ITEM ((struct vb2_menu_item){ \
-	.text = "Power off", \
-	.action = power_off_action, \
-})
-
-/******************************************************************************/
-/*
- * Functions for ui error handling
- */
-
-static vb2_error_t set_ui_error(struct vb2_ui_context *ui,
-				enum vb2_ui_error error_code)
-{
-	/* Keep the first occurring error. */
-	if (ui->error_code)
-		VB2_DEBUG("When handling ui error %#x, another ui error "
-			  "occurred: %#x",
-			  ui->error_code, error_code);
-	else
-		ui->error_code = error_code;
-	/* Return to the ui loop to show the error code. */
-	return VB2_REQUEST_UI_CONTINUE;
-}
-
-static vb2_error_t set_ui_error_and_go_back(struct vb2_ui_context *ui,
-					    enum vb2_ui_error error_code)
-{
-	set_ui_error(ui, error_code);
-	return vb2_ui_screen_back(ui);
-}
-
-/******************************************************************************/
-/*
- * Functions used for log screens
- *
- * Expects that the page_count is valid and page_up_item and page_down_item are
- * assigned to correct menu item indices in all three functions, the
- * current_page is valid in prev and next actions, and the back_item is assigned
- * to a correct menu item index.
- */
-
-static vb2_error_t log_page_update(struct vb2_ui_context *ui,
-				   const char *new_log_string)
-{
-	const struct vb2_screen_info *screen = ui->state->screen;
-
-	if (new_log_string) {
-		ui->state->page_count = vb2ex_prepare_log_screen(
-			screen->id, ui->locale_id, new_log_string);
-		if (ui->state->page_count == 0) {
-			VB2_DEBUG("vb2ex_prepare_log_screen failed");
-			return VB2_ERROR_UI_LOG_INIT;
-		}
-		if (ui->state->current_page >= ui->state->page_count)
-			ui->state->current_page = ui->state->page_count - 1;
-		ui->force_display = 1;
-	}
-	VB2_CLR_BIT(ui->state->disabled_item_mask, screen->page_up_item);
-	VB2_CLR_BIT(ui->state->disabled_item_mask, screen->page_down_item);
-	if (ui->state->current_page == 0)
-		VB2_SET_BIT(ui->state->disabled_item_mask,
-			    screen->page_up_item);
-	if (ui->state->current_page == ui->state->page_count - 1)
-		VB2_SET_BIT(ui->state->disabled_item_mask,
-			    screen->page_down_item);
-
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t log_page_reset_to_top(struct vb2_ui_context *ui)
-{
-	const struct vb2_screen_info *screen = ui->state->screen;
-
-	ui->state->current_page = 0;
-	ui->state->selected_item = ui->state->page_count > 1
-					   ? screen->page_down_item
-					   : screen->back_item;
-	return log_page_update(ui, NULL);
-}
-
-static vb2_error_t log_page_show_back_or_cancel(struct vb2_ui_context *ui,
-						int is_show_cancel)
-{
-	int back_item = ui->state->screen->back_item;
-	int cancel_item = ui->state->screen->cancel_item;
-	VB2_CLR_BIT(ui->state->hidden_item_mask, back_item);
-	VB2_CLR_BIT(ui->state->hidden_item_mask, cancel_item);
-	if (is_show_cancel) {
-		VB2_SET_BIT(ui->state->hidden_item_mask, back_item);
-		if (ui->state->selected_item == back_item)
-			ui->state->selected_item = cancel_item;
-	} else {
-		VB2_SET_BIT(ui->state->hidden_item_mask, cancel_item);
-		if (ui->state->selected_item == cancel_item)
-			ui->state->selected_item = back_item;
-	}
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t log_page_prev_action(struct vb2_ui_context *ui)
-{
-	/* Validity check. */
-	if (ui->state->current_page == 0)
-		return VB2_SUCCESS;
-
-	ui->state->current_page--;
-	return log_page_update(ui, NULL);
-}
-
-static vb2_error_t log_page_next_action(struct vb2_ui_context *ui)
-{
-	/* Validity check. */
-	if (ui->state->current_page == ui->state->page_count - 1)
-		return VB2_SUCCESS;
-
-	ui->state->current_page++;
-	return log_page_update(ui, NULL);
-}
-
-#define PAGE_UP_ITEM ((struct vb2_menu_item){ \
-	.text = "Page up", \
-	.action = log_page_prev_action, \
-})
-
-#define PAGE_DOWN_ITEM ((struct vb2_menu_item){ \
-	.text = "Page down", \
-	.action = log_page_next_action, \
-})
-
-/******************************************************************************/
-/* VB2_SCREEN_LANGUAGE_SELECT */
-
-static vb2_error_t language_select_action(struct vb2_ui_context *ui)
-{
-	vb2_error_t rv;
-	ui->locale_id = ui->state->selected_item;
-	VB2_DEBUG("Locale changed to %u\n", ui->locale_id);
-
-	/* Write locale id back to nvdata. */
-	vb2_nv_set(ui->ctx, VB2_NV_LOCALIZATION_INDEX, ui->locale_id);
-
-	/* Commit nvdata changes immediately, in case of three-finger salute
-	   reboot.  Ignore commit errors in recovery mode. */
-	rv = vb2ex_commit_data(ui->ctx);
-	if (rv && !(ui->ctx->flags & VB2_CONTEXT_RECOVERY_MODE))
-		return rv;
-
-	return vb2_ui_screen_back(ui);
-}
-
-const struct vb2_menu *get_language_menu(struct vb2_ui_context *ui)
-{
-	int i;
-	uint32_t num_locales;
-	struct vb2_menu_item *items;
-
-	if (ui->language_menu.num_items > 0)
-		return &ui->language_menu;
-
-	num_locales = vb2ex_get_locale_count();
-	if (num_locales == 0) {
-		VB2_DEBUG("WARNING: No locales available; assuming 1 locale\n");
-		num_locales = 1;
-	}
-
-	items = malloc(num_locales * sizeof(struct vb2_menu_item));
-	if (!items) {
-		VB2_DEBUG("ERROR: malloc failed for language items\n");
-		return NULL;
-	}
-
-	for (i = 0; i < num_locales; i++) {
-		items[i].text = "Some language";
-		items[i].action = language_select_action;
-	}
-
-	ui->language_menu.num_items = num_locales;
-	ui->language_menu.items = items;
-	return &ui->language_menu;
-}
-
-static vb2_error_t language_select_init(struct vb2_ui_context *ui)
-{
-	const struct vb2_menu *menu = get_menu(ui);
-	if (menu->num_items == 0) {
-		VB2_DEBUG("ERROR: No menu items found; "
-			  "rejecting entering language selection screen\n");
-		return vb2_ui_screen_back(ui);
-	}
-	if (ui->locale_id < menu->num_items) {
-		ui->state->selected_item = ui->locale_id;
-	} else {
-		VB2_DEBUG("WARNING: Current locale not found in menu items; "
-			  "initializing selected_item to 0\n");
-		ui->state->selected_item = 0;
-	}
-	return VB2_SUCCESS;
-}
-
-static const struct vb2_screen_info language_select_screen = {
-	.id = VB2_SCREEN_LANGUAGE_SELECT,
-	.name = "Language selection screen",
-	.init = language_select_init,
-	.get_menu = get_language_menu,
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_BROKEN */
-
-static const struct vb2_menu_item recovery_broken_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	ADVANCED_OPTIONS_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_broken_screen = {
-	.id = VB2_SCREEN_RECOVERY_BROKEN,
-	.name = "Recover broken device",
-	.menu = MENU_ITEMS(recovery_broken_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_ADVANCED_OPTIONS */
-
-#define ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE 1
-#define ADVANCED_OPTIONS_ITEM_DEBUG_INFO 2
-
-vb2_error_t advanced_options_init(struct vb2_ui_context *ui)
-{
-	ui->state->selected_item = ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE;
-	if (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED ||
-	    !vb2_allow_recovery(ui->ctx)) {
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE);
-		ui->state->selected_item = ADVANCED_OPTIONS_ITEM_DEBUG_INFO;
-	}
-
-	return VB2_SUCCESS;
-}
-
-static const struct vb2_menu_item advanced_options_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE] = {
-		.text = "Enable developer mode",
-		.target = VB2_SCREEN_RECOVERY_TO_DEV,
-	},
-	[ADVANCED_OPTIONS_ITEM_DEBUG_INFO] = {
-		.text = "Debug info",
-		.target = VB2_SCREEN_DEBUG_INFO,
-	},
-	{
-		.text = "Firmware log",
-		.target = VB2_SCREEN_FIRMWARE_LOG,
-	},
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info advanced_options_screen = {
-	.id = VB2_SCREEN_ADVANCED_OPTIONS,
-	.name = "Advanced options",
-	.init = advanced_options_init,
-	.menu = MENU_ITEMS(advanced_options_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DEBUG_INFO */
-
-#define DEBUG_INFO_ITEM_PAGE_UP 1
-#define DEBUG_INFO_ITEM_PAGE_DOWN 2
-#define DEBUG_INFO_ITEM_BACK 3
-
-static vb2_error_t debug_info_set_content(struct vb2_ui_context *ui)
-{
-	const char *log_string = vb2ex_get_debug_info(ui->ctx);
-	if (!log_string)
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DEBUG_LOG);
-	if (vb2_is_error(log_page_update(ui, log_string)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DEBUG_LOG);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t debug_info_init(struct vb2_ui_context *ui)
-{
-	VB2_TRY(debug_info_set_content(ui));
-	if (vb2_is_error(log_page_reset_to_top(ui)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DEBUG_LOG);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t debug_info_reinit(struct vb2_ui_context *ui)
-{
-	return debug_info_set_content(ui);
-}
-
-static const struct vb2_menu_item debug_info_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[DEBUG_INFO_ITEM_PAGE_UP] = PAGE_UP_ITEM,
-	[DEBUG_INFO_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
-	[DEBUG_INFO_ITEM_BACK] = BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info debug_info_screen = {
-	.id = VB2_SCREEN_DEBUG_INFO,
-	.name = "Debug info",
-	.init = debug_info_init,
-	.reinit = debug_info_reinit,
-	.menu = MENU_ITEMS(debug_info_items),
-	.page_up_item = DEBUG_INFO_ITEM_PAGE_UP,
-	.page_down_item = DEBUG_INFO_ITEM_PAGE_DOWN,
-	.back_item = DEBUG_INFO_ITEM_BACK,
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_FIRMWARE_LOG */
-
-#define FIRMWARE_LOG_ITEM_PAGE_UP 1
-#define FIRMWARE_LOG_ITEM_PAGE_DOWN 2
-#define FIRMWARE_LOG_ITEM_BACK 3
-
-static vb2_error_t firmware_log_set_content(struct vb2_ui_context *ui,
-					    int reset)
-{
-	const char *log_string = vb2ex_get_firmware_log(reset);
-	if (!log_string)
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_FIRMWARE_LOG);
-	if (vb2_is_error(log_page_update(ui, log_string)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_FIRMWARE_LOG);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t firmware_log_init(struct vb2_ui_context *ui)
-{
-	VB2_TRY(firmware_log_set_content(ui, 1));
-	if (vb2_is_error(log_page_reset_to_top(ui)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_FIRMWARE_LOG);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t firmware_log_reinit(struct vb2_ui_context *ui)
-{
-	return firmware_log_set_content(ui, 0);
-}
-
-static const struct vb2_menu_item firmware_log_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[FIRMWARE_LOG_ITEM_PAGE_UP] = PAGE_UP_ITEM,
-	[FIRMWARE_LOG_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
-	[FIRMWARE_LOG_ITEM_BACK] = BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info firmware_log_screen = {
-	.id = VB2_SCREEN_FIRMWARE_LOG,
-	.name = "Firmware log",
-	.init = firmware_log_init,
-	.reinit = firmware_log_reinit,
-	.menu = MENU_ITEMS(firmware_log_items),
-	.page_up_item = FIRMWARE_LOG_ITEM_PAGE_UP,
-	.page_down_item = FIRMWARE_LOG_ITEM_PAGE_DOWN,
-	.back_item = FIRMWARE_LOG_ITEM_BACK,
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_SELECT */
-
-#define RECOVERY_SELECT_ITEM_PHONE 1
-#define RECOVERY_SELECT_ITEM_EXTERNAL_DISK 2
-#define RECOVERY_SELECT_ITEM_DIAGNOSTICS 3
-
-/* Set VB2_NV_DIAG_REQUEST and reboot. */
-static vb2_error_t launch_diagnostics_action(struct vb2_ui_context *ui)
-{
-	vb2_nv_set(ui->ctx, VB2_NV_DIAG_REQUEST, 1);
-	VB2_DEBUG("Diagnostics requested, rebooting\n");
-	return VB2_REQUEST_REBOOT;
-}
-
-vb2_error_t recovery_select_init(struct vb2_ui_context *ui)
-{
-	ui->state->selected_item = RECOVERY_SELECT_ITEM_PHONE;
-	if (!vb2api_phone_recovery_ui_enabled(ui->ctx)) {
-		VB2_DEBUG("WARNING: Phone recovery not available\n");
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    RECOVERY_SELECT_ITEM_PHONE);
-		ui->state->selected_item = RECOVERY_SELECT_ITEM_EXTERNAL_DISK;
-	}
-
-        if (!DIAGNOSTIC_UI || !vb2api_diagnostic_ui_enabled(ui->ctx))
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    RECOVERY_SELECT_ITEM_DIAGNOSTICS);
-
-	return VB2_SUCCESS;
-}
-
-static const struct vb2_menu_item recovery_select_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[RECOVERY_SELECT_ITEM_PHONE] = {
-		.text = "Recovery using phone",
-		.target = VB2_SCREEN_RECOVERY_PHONE_STEP1,
-	},
-	[RECOVERY_SELECT_ITEM_EXTERNAL_DISK] = {
-		.text = "Recovery using external disk",
-		.target = VB2_SCREEN_RECOVERY_DISK_STEP1,
-	},
-	[RECOVERY_SELECT_ITEM_DIAGNOSTICS] = {
-		.text = "Launch diagnostics",
-		.action = launch_diagnostics_action,
-	},
-	ADVANCED_OPTIONS_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_select_screen = {
-	.id = VB2_SCREEN_RECOVERY_SELECT,
-	.name = "Recovery method selection",
-	.init = recovery_select_init,
-	.menu = MENU_ITEMS(recovery_select_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_INVALID */
-
-static const struct vb2_menu_item recovery_invalid_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_invalid_screen = {
-	.id = VB2_SCREEN_RECOVERY_INVALID,
-	.name = "Invalid recovery inserted",
-	.menu = MENU_ITEMS(recovery_invalid_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_TO_DEV */
-
-#define RECOVERY_TO_DEV_ITEM_CONFIRM 1
-#define RECOVERY_TO_DEV_ITEM_CANCEL 2
-
-vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui)
-{
-	if (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED)
-		/* We're in dev mode, so let user know they can't transition */
-		return set_ui_error_and_go_back(
-			ui, VB2_UI_ERROR_DEV_MODE_ALREADY_ENABLED);
-
-	if (!PHYSICAL_PRESENCE_KEYBOARD && vb2ex_physical_presence_pressed()) {
-		VB2_DEBUG("Presence button stuck?\n");
-		return vb2_ui_screen_back(ui);
-	}
-
-	ui->state->selected_item = RECOVERY_TO_DEV_ITEM_CONFIRM;
-
-	/* Disable "Confirm" button for other physical presence types. */
-	if (!PHYSICAL_PRESENCE_KEYBOARD) {
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    RECOVERY_TO_DEV_ITEM_CONFIRM);
-		ui->state->selected_item = RECOVERY_TO_DEV_ITEM_CANCEL;
-	}
-
-	ui->physical_presence_button_pressed = 0;
-
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t recovery_to_dev_finalize(struct vb2_ui_context *ui)
-{
-	VB2_DEBUG("Physical presence confirmed!\n");
-
-	/* Validity check, should never happen. */
-	if (ui->state->screen->id != VB2_SCREEN_RECOVERY_TO_DEV ||
-	    (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) ||
-	    !vb2_allow_recovery(ui->ctx)) {
-		VB2_DEBUG("ERROR: Dev transition validity check failed\n");
-		return VB2_SUCCESS;
-	}
-
-	VB2_DEBUG("Enabling dev mode and rebooting...\n");
-	vb2_enable_developer_mode(ui->ctx);
-	return VB2_REQUEST_REBOOT_EC_TO_RO;
-}
-
-vb2_error_t recovery_to_dev_confirm_action(struct vb2_ui_context *ui)
-{
-	if (!ui->key_trusted) {
-		VB2_DEBUG("Reject untrusted %s confirmation\n",
-			  ui->key == VB_KEY_ENTER ? "ENTER" : "POWER");
-		/*
-		 * If physical presence is confirmed using the keyboard,
-		 * beep and notify the user when the ENTER key comes
-		 * from an untrusted keyboard.
-		 */
-		if (PHYSICAL_PRESENCE_KEYBOARD && ui->key == VB_KEY_ENTER)
-			return set_ui_error(
-				ui, VB2_UI_ERROR_UNTRUSTED_CONFIRMATION);
-		return VB2_SUCCESS;
-	}
-	return recovery_to_dev_finalize(ui);
-}
-
-vb2_error_t recovery_to_dev_action(struct vb2_ui_context *ui)
-{
-	int pressed;
-
-	if (ui->key == ' ') {
-		VB2_DEBUG("SPACE means cancel dev mode transition\n");
-		return vb2_ui_screen_back(ui);
-	}
-
-	/* Keyboard physical presence case covered by "Confirm" action. */
-	if (PHYSICAL_PRESENCE_KEYBOARD)
-		return VB2_SUCCESS;
-
-	pressed = vb2ex_physical_presence_pressed();
-	if (pressed) {
-		VB2_DEBUG("Physical presence button pressed, "
-			  "awaiting release\n");
-		ui->physical_presence_button_pressed = 1;
-		return VB2_SUCCESS;
-	}
-	if (!ui->physical_presence_button_pressed)
-		return VB2_SUCCESS;
-	VB2_DEBUG("Physical presence button released\n");
-
-	return recovery_to_dev_finalize(ui);
-}
-
-static const struct vb2_menu_item recovery_to_dev_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[RECOVERY_TO_DEV_ITEM_CONFIRM] = {
-		.text = "Confirm",
-		.action = recovery_to_dev_confirm_action,
-	},
-	[RECOVERY_TO_DEV_ITEM_CANCEL] = {
-		.text = "Cancel",
-		.action = vb2_ui_screen_back,
-	},
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_to_dev_screen = {
-	.id = VB2_SCREEN_RECOVERY_TO_DEV,
-	.name = "Transition to developer mode",
-	.init = recovery_to_dev_init,
-	.action = recovery_to_dev_action,
-	.menu = MENU_ITEMS(recovery_to_dev_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_PHONE_STEP1 */
-
-static const struct vb2_menu_item recovery_phone_step1_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	NEXT_ITEM(VB2_SCREEN_RECOVERY_PHONE_STEP2),
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_phone_step1_screen = {
-	.id = VB2_SCREEN_RECOVERY_PHONE_STEP1,
-	.name = "Phone recovery step 1",
-	.menu = MENU_ITEMS(recovery_phone_step1_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_PHONE_STEP2 */
-
-static const struct vb2_menu_item recovery_phone_step2_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_phone_step2_screen = {
-	.id = VB2_SCREEN_RECOVERY_PHONE_STEP2,
-	.name = "Phone recovery step 2",
-	.menu = MENU_ITEMS(recovery_phone_step2_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_DISK_STEP1 */
-
-static const struct vb2_menu_item recovery_disk_step1_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	NEXT_ITEM(VB2_SCREEN_RECOVERY_DISK_STEP2),
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_disk_step1_screen = {
-	.id = VB2_SCREEN_RECOVERY_DISK_STEP1,
-	.name = "Disk recovery step 1",
-	.menu = MENU_ITEMS(recovery_disk_step1_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_DISK_STEP2 */
-
-static const struct vb2_menu_item recovery_disk_step2_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	NEXT_ITEM(VB2_SCREEN_RECOVERY_DISK_STEP3),
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_disk_step2_screen = {
-	.id = VB2_SCREEN_RECOVERY_DISK_STEP2,
-	.name = "Disk recovery step 2",
-	.menu = MENU_ITEMS(recovery_disk_step2_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_RECOVERY_DISK_STEP3 */
-
-static const struct vb2_menu_item recovery_disk_step3_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info recovery_disk_step3_screen = {
-	.id = VB2_SCREEN_RECOVERY_DISK_STEP3,
-	.name = "Disk recovery step 3",
-	.menu = MENU_ITEMS(recovery_disk_step3_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DEVELOPER_MODE */
-
-#define DEVELOPER_MODE_ITEM_RETURN_TO_SECURE 1
-#define DEVELOPER_MODE_ITEM_BOOT_INTERNAL 2
-#define DEVELOPER_MODE_ITEM_BOOT_EXTERNAL 3
-#define DEVELOPER_MODE_ITEM_SELECT_ALTFW 4
-
-vb2_error_t developer_mode_init(struct vb2_ui_context *ui)
-{
-	enum vb2_dev_default_boot_target default_boot =
-		vb2api_get_dev_default_boot_target(ui->ctx);
-
-	/* Don't show "Return to secure mode" button if GBB forces dev mode. */
-	if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    DEVELOPER_MODE_ITEM_RETURN_TO_SECURE);
-
-	/* Don't show "Boot from external disk" button if not allowed. */
-	if (!vb2_dev_boot_external_allowed(ui->ctx))
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    DEVELOPER_MODE_ITEM_BOOT_EXTERNAL);
-
-	/* Don't show "Select alternate bootloader" button if not allowed. */
-	if (!vb2_dev_boot_altfw_allowed(ui->ctx))
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    DEVELOPER_MODE_ITEM_SELECT_ALTFW);
-
-	/* Choose the default selection. */
-	switch (default_boot) {
-	case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL:
-		ui->state->selected_item = DEVELOPER_MODE_ITEM_BOOT_EXTERNAL;
-		break;
-	case VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW:
-		ui->state->selected_item =
-			DEVELOPER_MODE_ITEM_SELECT_ALTFW;
-		break;
-	default:
-		ui->state->selected_item = DEVELOPER_MODE_ITEM_BOOT_INTERNAL;
-		break;
-	}
-
-	ui->start_time_ms = vb2ex_mtime();
-
-	return VB2_SUCCESS;
-}
-
-vb2_error_t vb2_ui_developer_mode_boot_internal_action(
-	struct vb2_ui_context *ui)
-{
-	if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ||
-	    !vb2_dev_boot_allowed(ui->ctx)) {
-		VB2_DEBUG("ERROR: Dev mode internal boot not allowed\n");
-		return VB2_SUCCESS;
-	}
-
-	VB2_TRY(VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_FIXED));
-	return VB2_REQUEST_UI_EXIT;
-}
-
-vb2_error_t vb2_ui_developer_mode_boot_external_action(
-	struct vb2_ui_context *ui)
-{
-	vb2_error_t rv;
-
-	/* Validity check, should never happen. */
-	if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ||
-	    !vb2_dev_boot_allowed(ui->ctx) ||
-	    !vb2_dev_boot_external_allowed(ui->ctx)) {
-		VB2_DEBUG("ERROR: Dev mode external boot not allowed\n");
-		ui->error_beep = 1;
-		return set_ui_error(ui, VB2_UI_ERROR_EXTERNAL_BOOT_DISABLED);
-	}
-
-	rv = VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_REMOVABLE);
-	if (rv == VB2_SUCCESS) {
-		return VB2_REQUEST_UI_EXIT;
-	} else if (rv == VB2_ERROR_LK_NO_DISK_FOUND) {
-		if (ui->state->screen->id !=
-		    VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL) {
-			VB2_DEBUG("No external disk found\n");
-			ui->error_beep = 1;
-		}
-		return vb2_ui_screen_change(
-			ui, VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL);
-	} else {
-		if (ui->state->screen->id !=
-		    VB2_SCREEN_DEVELOPER_INVALID_DISK) {
-			VB2_DEBUG("Invalid external disk: %#x\n", rv);
-			ui->error_beep = 1;
-		}
-		return vb2_ui_screen_change(
-			ui, VB2_SCREEN_DEVELOPER_INVALID_DISK);
-	}
-}
-
-vb2_error_t developer_mode_action(struct vb2_ui_context *ui)
-{
-	const int use_short = vb2api_use_short_dev_screen_delay(ui->ctx);
-	uint64_t elapsed_ms;
-
-	/* Once any user interaction occurs, stop the timer. */
-	if (ui->key)
-		ui->disable_timer = 1;
-	if (ui->disable_timer)
-		return VB2_SUCCESS;
-
-	elapsed_ms = vb2ex_mtime() - ui->start_time_ms;
-
-	/* If we're using short delay, wait 2 seconds and don't beep. */
-	if (use_short && elapsed_ms > DEV_DELAY_SHORT_MS) {
-		VB2_DEBUG("Booting default target after 2s\n");
-		ui->disable_timer = 1;
-		return vb2_ui_menu_select(ui);
-	}
-
-	/* Otherwise, beep at 20 and 20.5 seconds. */
-	if ((ui->beep_count == 0 && elapsed_ms > DEV_DELAY_BEEP1_MS) ||
-	    (ui->beep_count == 1 && elapsed_ms > DEV_DELAY_BEEP2_MS)) {
-		vb2ex_beep(250, 400);
-		ui->beep_count++;
-	}
-
-	/* Stop after 30 seconds. */
-	if (elapsed_ms > DEV_DELAY_NORMAL_MS) {
-		VB2_DEBUG("Booting default target after 30s\n");
-		ui->disable_timer = 1;
-		return vb2_ui_menu_select(ui);
-	}
-
-	return VB2_SUCCESS;
-}
-
-static const struct vb2_menu_item developer_mode_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[DEVELOPER_MODE_ITEM_RETURN_TO_SECURE] = {
-		.text = "Return to secure mode",
-		.target = VB2_SCREEN_DEVELOPER_TO_NORM,
-	},
-	[DEVELOPER_MODE_ITEM_BOOT_INTERNAL] = {
-		.text = "Boot from internal disk",
-		.action = vb2_ui_developer_mode_boot_internal_action,
-	},
-	[DEVELOPER_MODE_ITEM_BOOT_EXTERNAL] = {
-		.text = "Boot from external disk",
-		.action = vb2_ui_developer_mode_boot_external_action,
-	},
-	[DEVELOPER_MODE_ITEM_SELECT_ALTFW] = {
-		.text = "Select alternate bootloader",
-		.target = VB2_SCREEN_DEVELOPER_SELECT_ALTFW,
-	},
-	ADVANCED_OPTIONS_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info developer_mode_screen = {
-	.id = VB2_SCREEN_DEVELOPER_MODE,
-	.name = "Developer mode",
-	.init = developer_mode_init,
-	.action = developer_mode_action,
-	.menu = MENU_ITEMS(developer_mode_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DEVELOPER_TO_NORM */
-
-#define DEVELOPER_TO_NORM_ITEM_CONFIRM 1
-#define DEVELOPER_TO_NORM_ITEM_CANCEL 2
-
-static vb2_error_t developer_to_norm_init(struct vb2_ui_context *ui)
-{
-	/* Don't allow to-norm if GBB forces dev mode */
-	if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
-		VB2_DEBUG("ERROR: to-norm not allowed\n");
-		return set_ui_error_and_go_back(
-			ui, VB2_UI_ERROR_TO_NORM_NOT_ALLOWED);
-	}
-	ui->state->selected_item = DEVELOPER_TO_NORM_ITEM_CONFIRM;
-	/* Hide "Cancel" button if dev boot is not allowed */
-	if (!vb2_dev_boot_allowed(ui->ctx))
-		VB2_SET_BIT(ui->state->hidden_item_mask,
-			    DEVELOPER_TO_NORM_ITEM_CANCEL);
-	return VB2_SUCCESS;
-}
-
-vb2_error_t developer_to_norm_action(struct vb2_ui_context *ui)
-{
-	if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
-		VB2_DEBUG("ERROR: dev mode forced by GBB flag\n");
-		return VB2_SUCCESS;
-	}
-
-	VB2_DEBUG("Leaving dev mode\n");
-	vb2_nv_set(ui->ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
-	return VB2_REQUEST_REBOOT;
-}
-
-static const struct vb2_menu_item developer_to_norm_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[DEVELOPER_TO_NORM_ITEM_CONFIRM] = {
-		.text = "Confirm",
-		.action = developer_to_norm_action,
-	},
-	[DEVELOPER_TO_NORM_ITEM_CANCEL] = {
-		.text = "Cancel",
-		.action = vb2_ui_screen_back,
-	},
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info developer_to_norm_screen = {
-	.id = VB2_SCREEN_DEVELOPER_TO_NORM,
-	.name = "Transition to normal mode",
-	.init = developer_to_norm_init,
-	.menu = MENU_ITEMS(developer_to_norm_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL */
-
-static const struct vb2_menu_item developer_boot_external_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info developer_boot_external_screen = {
-	.id = VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL,
-	.name = "Developer boot from external disk",
-	.action = vb2_ui_developer_mode_boot_external_action,
-	.menu = MENU_ITEMS(developer_boot_external_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DEVELOPER_INVALID_DISK */
-
-static const struct vb2_menu_item developer_invalid_disk_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info developer_invalid_disk_screen = {
-	.id = VB2_SCREEN_DEVELOPER_INVALID_DISK,
-	.name = "Invalid external disk in dev mode",
-	.action = vb2_ui_developer_mode_boot_external_action,
-	.menu = MENU_ITEMS(developer_invalid_disk_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DEVELOPER_SELECT_ALTFW */
-
-static const struct vb2_menu_item developer_select_bootloader_items_before[] = {
-	LANGUAGE_SELECT_ITEM,
-};
-
-static const struct vb2_menu_item developer_select_bootloader_items_after[] = {
-	BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static vb2_error_t developer_select_bootloader_init(struct vb2_ui_context *ui)
-{
-	if (get_menu(ui)->num_items == 0)
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_ALTFW_EMPTY);
-	/* Select the first bootloader. */
-	ui->state->selected_item =
-		ARRAY_SIZE(developer_select_bootloader_items_before);
-	return VB2_SUCCESS;
-}
-
-vb2_error_t vb2_ui_developer_mode_boot_altfw_action(
-	struct vb2_ui_context *ui)
-{
-	uint32_t altfw_id;
-	const size_t menu_before_len =
-		ARRAY_SIZE(developer_select_bootloader_items_before);
-
-	if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ||
-	    !vb2_dev_boot_allowed(ui->ctx) ||
-	    !vb2_dev_boot_altfw_allowed(ui->ctx)) {
-		VB2_DEBUG("ERROR: Dev mode alternate bootloader not allowed\n");
-		return set_ui_error(ui, VB2_UI_ERROR_ALTFW_DISABLED);
-	}
-
-	if (vb2ex_get_altfw_count() == 0) {
-		VB2_DEBUG("ERROR: No alternate bootloader was found\n");
-		return set_ui_error(ui, VB2_UI_ERROR_ALTFW_EMPTY);
-	}
-
-	if (ui->key == VB_KEY_CTRL('L')) {
-		altfw_id = 0;
-		VB2_DEBUG("Try booting from default bootloader\n");
-	} else {
-		altfw_id = ui->state->selected_item - menu_before_len + 1;
-		VB2_DEBUG("Try booting from bootloader #%u\n", altfw_id);
-	}
-
-	/* vb2ex_run_altfw will not return if successful */
-	vb2ex_run_altfw(altfw_id);
-
-	VB2_DEBUG("ERROR: Alternate bootloader failed\n");
-	return set_ui_error(ui, VB2_UI_ERROR_ALTFW_FAILED);
-}
-
-static const struct vb2_menu *get_bootloader_menu(struct vb2_ui_context *ui)
-{
-	int i;
-	uint32_t num_bootloaders, num_items;
-	struct vb2_menu_item *items;
-	const size_t menu_before_len =
-		ARRAY_SIZE(developer_select_bootloader_items_before);
-	const size_t menu_after_len =
-		ARRAY_SIZE(developer_select_bootloader_items_after);
-
-	if (ui->bootloader_menu.num_items > 0)
-		return &ui->bootloader_menu;
-
-	num_bootloaders = vb2ex_get_altfw_count();
-	if (num_bootloaders == 0) {
-		VB2_DEBUG("ERROR: No bootloader was found\n");
-		return NULL;
-	}
-	VB2_DEBUG("num_bootloaders: %u\n", num_bootloaders);
-	num_items = num_bootloaders + menu_before_len + menu_after_len;
-	items = malloc(num_items * sizeof(struct vb2_menu_item));
-	if (!items) {
-		VB2_DEBUG("ERROR: malloc failed for bootloader items\n");
-		return NULL;
-	}
-
-	/* Copy prefix items to the begin. */
-	memcpy(&items[0],
-	       developer_select_bootloader_items_before,
-	       menu_before_len * sizeof(struct vb2_menu_item));
-
-	/* Copy bootloaders. */
-	for (i = 0; i < num_bootloaders; i++) {
-		items[i + menu_before_len].text = "Some bootloader";
-		items[i + menu_before_len].action =
-			vb2_ui_developer_mode_boot_altfw_action;
-	}
-
-	/* Copy postfix items to the end. */
-	memcpy(&items[num_items - menu_after_len],
-	       developer_select_bootloader_items_after,
-	       menu_after_len * sizeof(struct vb2_menu_item));
-
-	ui->bootloader_menu.num_items = num_items;
-	ui->bootloader_menu.items = items;
-
-	return &ui->bootloader_menu;
-}
-
-static const struct vb2_screen_info developer_select_bootloader_screen = {
-	.id = VB2_SCREEN_DEVELOPER_SELECT_ALTFW,
-	.name = "Select alternate bootloader",
-	.init = developer_select_bootloader_init,
-	.get_menu = get_bootloader_menu,
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DIAGNOSTICS */
-
-#define DIAGNOSTICS_ITEM_STORAGE_HEALTH 1
-#define DIAGNOSTICS_ITEM_STORAGE_TEST_SHORT 2
-#define DIAGNOSTICS_ITEM_STORAGE_TEST_EXTENDED 3
-
-static vb2_error_t diagnostics_init(struct vb2_ui_context *ui)
-{
-	const char *unused_log_string;
-	vb2_error_t rv = vb2ex_diag_get_storage_test_log(&unused_log_string);
-	if (rv == VB2_ERROR_EX_UNIMPLEMENTED) {
-		VB2_SET_BIT(ui->state->disabled_item_mask,
-			    DIAGNOSTICS_ITEM_STORAGE_TEST_SHORT);
-		VB2_SET_BIT(ui->state->disabled_item_mask,
-			    DIAGNOSTICS_ITEM_STORAGE_TEST_EXTENDED);
-	}
-	ui->state->selected_item = DIAGNOSTICS_ITEM_STORAGE_HEALTH;
-	return VB2_SUCCESS;
-}
-
-static const struct vb2_menu_item diagnostics_items[] = {
-	LANGUAGE_SELECT_ITEM,
-	[DIAGNOSTICS_ITEM_STORAGE_HEALTH] = {
-		.text = "Storage health info",
-		.target = VB2_SCREEN_DIAGNOSTICS_STORAGE_HEALTH,
-	},
-	[DIAGNOSTICS_ITEM_STORAGE_TEST_SHORT] = {
-		.text = "Storage self-test (short)",
-		.target = VB2_SCREEN_DIAGNOSTICS_STORAGE_TEST_SHORT,
-	},
-	[DIAGNOSTICS_ITEM_STORAGE_TEST_EXTENDED] = {
-		.text = "Storage self-test (Extended)",
-		.target = VB2_SCREEN_DIAGNOSTICS_STORAGE_TEST_EXTENDED,
-	},
-	{
-		.text = "Memory check (quick)",
-		.target = VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK,
-	},
-	{
-		.text = "Memory check (full)",
-		.target = VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL,
-	},
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info diagnostics_screen = {
-	.id = VB2_SCREEN_DIAGNOSTICS,
-	.name = "Diagnostic tools",
-	.init = diagnostics_init,
-	.menu = MENU_ITEMS(diagnostics_items),
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DIAGNOSTICS_STORAGE_HEALTH */
-
-#define DIAGNOSTICS_STORAGE_HEALTH_ITEM_PAGE_UP 0
-#define DIAGNOSTICS_STORAGE_HEALTH_ITEM_PAGE_DOWN 1
-#define DIAGNOSTICS_STORAGE_HEALTH_ITEM_BACK 2
-
-static vb2_error_t diagnostics_storage_health_init_impl(
-	struct vb2_ui_context *ui)
-{
-	const char *log_string;
-	VB2_TRY(vb2ex_diag_get_storage_health(&log_string));
-	VB2_TRY(log_page_update(ui, log_string));
-	return log_page_reset_to_top(ui);
-}
-
-static vb2_error_t diagnostics_storage_health_init(struct vb2_ui_context *ui)
-{
-	if (vb2_is_error(diagnostics_storage_health_init_impl(ui)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DIAGNOSTICS);
-	return VB2_SUCCESS;
-}
-
-static const struct vb2_menu_item diagnostics_storage_health_items[] = {
-	[DIAGNOSTICS_STORAGE_HEALTH_ITEM_PAGE_UP] = PAGE_UP_ITEM,
-	[DIAGNOSTICS_STORAGE_HEALTH_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
-	[DIAGNOSTICS_STORAGE_HEALTH_ITEM_BACK] = BACK_ITEM,
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info diagnostics_storage_health_screen = {
-	.id = VB2_SCREEN_DIAGNOSTICS_STORAGE_HEALTH,
-	.name = "Storage health info",
-	.init = diagnostics_storage_health_init,
-	.menu = MENU_ITEMS(diagnostics_storage_health_items),
-	.page_up_item = DIAGNOSTICS_STORAGE_HEALTH_ITEM_PAGE_UP,
-	.page_down_item = DIAGNOSTICS_STORAGE_HEALTH_ITEM_PAGE_DOWN,
-	.back_item = DIAGNOSTICS_STORAGE_HEALTH_ITEM_BACK,
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DIAGNOSTICS_STORAGE_TEST */
-
-#define DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_UP 0
-#define DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_DOWN 1
-#define DIAGNOSTICS_STORAGE_TEST_ITEM_BACK 2
-#define DIAGNOSTICS_STORAGE_TEST_ITEM_CANCEL 3
-
-static vb2_error_t diagnostics_storage_test_update_impl(
-	struct vb2_ui_context *ui)
-{
-	const char *log_string;
-	int is_test_running = 0;
-
-	/* Early return if the test is done. */
-	if (ui->state->test_finished)
-		return VB2_SUCCESS;
-
-	vb2_error_t rv = vb2ex_diag_get_storage_test_log(&log_string);
-	switch (rv) {
-	case VB2_ERROR_EX_DIAG_TEST_RUNNING:
-		is_test_running = 1;
-		break;
-	case VB2_SUCCESS:
-		ui->state->test_finished = 1;
-		break;
-	default:
-		VB2_DEBUG("vb2ex_diag_get_storage_test_log returned %#x\n", rv);
-		return rv;
-	}
-	VB2_TRY(log_page_show_back_or_cancel(ui, is_test_running));
-	return log_page_update(ui, log_string);
-}
-
-static vb2_error_t diagnostics_storage_test_update(struct vb2_ui_context *ui)
-{
-	if (vb2_is_error(diagnostics_storage_test_update_impl(ui)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DIAGNOSTICS);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t diagnostics_storage_test_control(
-	struct vb2_ui_context *ui, enum vb2_diag_storage_test op)
-{
-	if (vb2_is_error(vb2ex_diag_storage_test_control(op)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DIAGNOSTICS);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t diagnostics_storage_test_init(struct vb2_ui_context *ui)
-{
-	VB2_TRY(diagnostics_storage_test_update(ui));
-	if (vb2_is_error(log_page_reset_to_top(ui)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DIAGNOSTICS);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t diagnostics_storage_test_short_init(
-	struct vb2_ui_context *ui)
-{
-	VB2_TRY(diagnostics_storage_test_control(ui,
-						 VB2_DIAG_STORAGE_TEST_STOP));
-	VB2_TRY(diagnostics_storage_test_control(ui,
-						 VB2_DIAG_STORAGE_TEST_SHORT));
-	return diagnostics_storage_test_init(ui);
-}
-
-static vb2_error_t diagnostics_storage_test_extended_init(
-	struct vb2_ui_context *ui)
-{
-	VB2_TRY(diagnostics_storage_test_control(ui,
-						 VB2_DIAG_STORAGE_TEST_STOP));
-	VB2_TRY(diagnostics_storage_test_control(
-		ui, VB2_DIAG_STORAGE_TEST_EXTENDED));
-	return diagnostics_storage_test_init(ui);
-}
-
-static vb2_error_t diagnostics_storage_test_cancel(struct vb2_ui_context *ui)
-{
-	VB2_TRY(diagnostics_storage_test_control(ui,
-						 VB2_DIAG_STORAGE_TEST_STOP));
-	return vb2_ui_screen_back(ui);
-}
-
-static const struct vb2_menu_item diagnostics_storage_test_items[] = {
-	[DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_UP] = PAGE_UP_ITEM,
-	[DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
-	[DIAGNOSTICS_STORAGE_TEST_ITEM_BACK] = BACK_ITEM,
-	[DIAGNOSTICS_STORAGE_TEST_ITEM_CANCEL] = {
-		.text = "Cancel",
-		.action = diagnostics_storage_test_cancel,
-	},
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info diagnostics_storage_test_short_screen = {
-	.id = VB2_SCREEN_DIAGNOSTICS_STORAGE_TEST_SHORT,
-	.name = "Storage self-test (short)",
-	.init = diagnostics_storage_test_short_init,
-	.action = diagnostics_storage_test_update,
-	.menu = MENU_ITEMS(diagnostics_storage_test_items),
-	.page_up_item = DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_UP,
-	.page_down_item = DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_DOWN,
-	.back_item = DIAGNOSTICS_STORAGE_TEST_ITEM_BACK,
-	.cancel_item = DIAGNOSTICS_STORAGE_TEST_ITEM_CANCEL,
-};
-
-static const struct vb2_screen_info diagnostics_storage_test_extended_screen = {
-	.id = VB2_SCREEN_DIAGNOSTICS_STORAGE_TEST_EXTENDED,
-	.name = "Storage self-test (extended)",
-	.init = diagnostics_storage_test_extended_init,
-	.action = diagnostics_storage_test_update,
-	.menu = MENU_ITEMS(diagnostics_storage_test_items),
-	.page_up_item = DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_UP,
-	.page_down_item = DIAGNOSTICS_STORAGE_TEST_ITEM_PAGE_DOWN,
-	.back_item = DIAGNOSTICS_STORAGE_TEST_ITEM_BACK,
-	.cancel_item = DIAGNOSTICS_STORAGE_TEST_ITEM_CANCEL,
-};
-
-/******************************************************************************/
-/* VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK
-   VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL */
-
-#define DIAGNOSTICS_MEMORY_ITEM_PAGE_UP 0
-#define DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN 1
-#define DIAGNOSTICS_MEMORY_ITEM_BACK 2
-#define DIAGNOSTICS_MEMORY_ITEM_CANCEL 3
-
-typedef vb2_error_t (*memory_test_op_t)(int reset, const char **out);
-static vb2_error_t diagnostics_memory_update_screen_impl(
-	struct vb2_ui_context *ui, memory_test_op_t op, int reset)
-{
-	const char *log_string = NULL;
-	vb2_error_t rv;
-	int is_test_running = 0;
-
-	/* Early return if the memory test is done. */
-	if (ui->state->test_finished)
-		return VB2_SUCCESS;
-
-	rv = op(reset, &log_string);
-	switch (rv) {
-	/* The test is still running but the output buffer was unchanged. */
-	case VB2_ERROR_EX_DIAG_TEST_RUNNING:
-		return VB2_SUCCESS;
-	case VB2_ERROR_EX_DIAG_TEST_UPDATED:
-		is_test_running = 1;
-		break;
-	case VB2_SUCCESS:
-		ui->state->test_finished = 1;
-		break;
-	default:
-		VB2_DEBUG("memory_test_op returned %#x\n", rv);
-		return rv;
-	}
-	VB2_TRY(log_page_show_back_or_cancel(ui, is_test_running));
-	return log_page_update(ui, log_string);
-}
-
-static vb2_error_t diagnostics_memory_update_screen(struct vb2_ui_context *ui,
-						    memory_test_op_t op,
-						    int reset)
-{
-	if (vb2_is_error(diagnostics_memory_update_screen_impl(ui, op, reset)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DIAGNOSTICS);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t diagnostics_memory_init_quick(struct vb2_ui_context *ui)
-{
-	VB2_TRY(diagnostics_memory_update_screen(
-		ui, &vb2ex_diag_memory_quick_test, 1));
-	if (vb2_is_error(log_page_reset_to_top(ui)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DIAGNOSTICS);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t diagnostics_memory_init_full(struct vb2_ui_context *ui)
-{
-	VB2_TRY(diagnostics_memory_update_screen(
-		ui, &vb2ex_diag_memory_full_test, 1));
-	if (vb2_is_error(log_page_reset_to_top(ui)))
-		return set_ui_error_and_go_back(ui, VB2_UI_ERROR_DIAGNOSTICS);
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t diagnostics_memory_update_quick(struct vb2_ui_context *ui)
-{
-	return diagnostics_memory_update_screen(
-		ui, &vb2ex_diag_memory_quick_test, 0);
-}
-
-static vb2_error_t diagnostics_memory_update_full(struct vb2_ui_context *ui)
-{
-	return diagnostics_memory_update_screen(
-		ui, &vb2ex_diag_memory_full_test, 0);
-}
-
-static const struct vb2_menu_item diagnostics_memory_items[] = {
-	[DIAGNOSTICS_MEMORY_ITEM_PAGE_UP] = PAGE_UP_ITEM,
-	[DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
-	[DIAGNOSTICS_MEMORY_ITEM_BACK] = BACK_ITEM,
-	[DIAGNOSTICS_MEMORY_ITEM_CANCEL] = {
-		.text = "Cancel",
-		.action = vb2_ui_screen_back,
-	},
-	POWER_OFF_ITEM,
-};
-
-static const struct vb2_screen_info diagnostics_memory_quick_screen = {
-	.id = VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK,
-	.name = "Memory check (quick)",
-	.init = diagnostics_memory_init_quick,
-	.action = diagnostics_memory_update_quick,
-	.menu = MENU_ITEMS(diagnostics_memory_items),
-	.page_up_item = DIAGNOSTICS_MEMORY_ITEM_PAGE_UP,
-	.page_down_item = DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN,
-	.back_item = DIAGNOSTICS_MEMORY_ITEM_BACK,
-	.cancel_item = DIAGNOSTICS_MEMORY_ITEM_CANCEL,
-};
-
-static const struct vb2_screen_info diagnostics_memory_full_screen = {
-	.id = VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL,
-	.name = "Memory check (full)",
-	.init = diagnostics_memory_init_full,
-	.action = diagnostics_memory_update_full,
-	.menu = MENU_ITEMS(diagnostics_memory_items),
-	.page_up_item = DIAGNOSTICS_MEMORY_ITEM_PAGE_UP,
-	.page_down_item = DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN,
-	.back_item = DIAGNOSTICS_MEMORY_ITEM_BACK,
-	.cancel_item = DIAGNOSTICS_MEMORY_ITEM_CANCEL,
-};
-
-/******************************************************************************/
-/*
- * TODO(chromium:1035800): Refactor UI code across vboot and depthcharge.
- * Currently vboot and depthcharge maintain their own copies of menus/screens.
- * vboot detects keyboard input and controls the navigation among different menu
- * items and screens, while depthcharge performs the actual rendering of each
- * screen, based on the menu information passed from vboot.
- */
-static const struct vb2_screen_info *screens[] = {
-	&language_select_screen,
-	&recovery_broken_screen,
-	&advanced_options_screen,
-	&debug_info_screen,
-	&firmware_log_screen,
-	&recovery_select_screen,
-	&recovery_invalid_screen,
-	&recovery_to_dev_screen,
-	&recovery_phone_step1_screen,
-	&recovery_phone_step2_screen,
-	&recovery_disk_step1_screen,
-	&recovery_disk_step2_screen,
-	&recovery_disk_step3_screen,
-	&developer_mode_screen,
-	&developer_to_norm_screen,
-	&developer_boot_external_screen,
-	&developer_invalid_disk_screen,
-	&developer_select_bootloader_screen,
-	&diagnostics_screen,
-	&diagnostics_storage_health_screen,
-	&diagnostics_storage_test_short_screen,
-	&diagnostics_storage_test_extended_screen,
-	&diagnostics_memory_quick_screen,
-	&diagnostics_memory_full_screen,
-};
-
-const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen id)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(screens); i++) {
-		if (screens[i]->id == id)
-			return screens[i];
-	}
-	return NULL;
-}
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index fb656da..1f9d70f 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -240,6 +240,23 @@
 	 * it doesn't jump to RW when this flag is set.
 	 */
 	VB2_CONTEXT_EC_TRUSTED = (1 << 24),
+
+	/*
+	 * Boot into developer mode is allowed by FWMP or GBB flags.
+	 */
+	VB2_CONTEXT_DEV_BOOT_ALLOWED = (1 << 25),
+
+	/*
+	 * Boot into developer mode from external disk is allowed by nvdata,
+	 * FWMP or GBB flags.
+	 */
+	VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED = (1 << 26),
+
+	/*
+	 * Boot into developer mode from alternate bootloader is allowed by
+	 * nvdata, FWMP or GBB flags.
+	 */
+	VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED = (1 << 27),
 };
 
 /* Helper for aligning fields in vb2_context. */
@@ -283,8 +300,8 @@
 	/*
 	 * Secure data for firmware verification stage.  Caller must fill this
 	 * from some secure non-volatile location before calling
-	 * vb2api_fw_phase1.  If the VB2_CONTEXT_SECDATA_CHANGED flag is set
-	 * when a function returns, caller must save the data back to the
+	 * vb2api_fw_phase1.  If the VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED flag
+	 * is set when a function returns, caller must save the data back to the
 	 * secure non-volatile location and then clear the flag.
 	 */
 	uint8_t secdata_firmware[VB2_SECDATA_FIRMWARE_SIZE];
@@ -871,6 +888,14 @@
 uint32_t vb2api_get_locale_id(struct vb2_context *ctx);
 
 /**
+ * Set the locale id in nvdata.
+ *
+ * @param ctx		Vboot context
+ * @param locale_id 	The locale id to be set
+ */
+void vb2api_set_locale_id(struct vb2_context *ctx, uint32_t locale_id);
+
+/**
  * Whether phone recovery functionality is enabled or not.
  *
  * @param ctx		Vboot context
@@ -907,7 +932,8 @@
 };
 
 /**
- * Get the default boot target in developer mode.
+ * Get the default boot target in developer mode. This function must be called
+ * after vb2api_kernel_phase1.
  *
  * @param ctx		Vboot context
  * @return The developer mode default boot target.
@@ -923,6 +949,50 @@
  */
 int vb2api_use_short_dev_screen_delay(struct vb2_context *ctx);
 
+/**
+ * Check whether recovery is allowed or not.
+ *
+ * The only way to pass this check and proceed to the recovery process is to
+ * physically request a recovery (a.k.a. manual recovery).  All other recovery
+ * requests including manual recovery requested by a (compromised) host will
+ * end up with 'broken' screen.
+ *
+ * @param ctx		Vboot context
+ * @return 1 if recovery is allowed; 0 if no or uncertain.
+ */
+int vb2api_allow_recovery(struct vb2_context *ctx);
+
+/**
+ * Request to enable developer mode.
+ *
+ * Enables the developer flag in vb2_context firmware secdata.  Note that
+ * modified secdata must be saved for change to apply on reboot.
+ *
+ * NOTE: Doesn't update the LAST_BOOT_DEVELOPER secdata flag.  That should be
+ * done on the next boot.
+ *
+ * @param ctx		Vboot context
+ * @return VB2_SUCCESS if success; error if enabling developer mode is not
+ * allowed.
+ */
+vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx);
+
+/**
+ * Request to disable developer mode by setting VB2_NV_DIAG_REQUEST.
+ *
+ * @param ctx		Vboot context
+ * @return VB2_SUCCESS if success; other errors if the check of
+ * VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON failed.
+ */
+vb2_error_t vb2api_disable_developer_mode(struct vb2_context *ctx);
+
+/**
+ * Request diagnostics by setting VB2_NV_DIAG_REQUEST.
+ *
+ * @param ctx		Vboot context
+ */
+void vb2api_request_diagnostics(struct vb2_context *ctx);
+
 /*****************************************************************************/
 /* APIs provided by the caller to verified boot */
 
@@ -1324,6 +1394,53 @@
 /*****************************************************************************/
 /* Functions for UI display. */
 
+/**
+ * UI for a non-manual recovery ("BROKEN").
+ *
+ * Enter the broken screen UI, which shows that an unrecoverable error was
+ * encountered last boot. Wait for the user to physically reset or shut down.
+ *
+ * @param ctx		Vboot context
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *ctx);
+
+/**
+ * UI for a manual recovery-mode boot.
+ *
+ * Enter the recovery menu, which prompts the user to insert recovery media,
+ * navigate the step-by-step recovery, or enter developer mode if allowed.
+ *
+ * @param ctx		Vboot context
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *ctx);
+
+/**
+ * UI for a developer-mode boot.
+ *
+ * Enter the developer menu, which provides options to switch out of developer
+ * mode, boot from external media, use legacy bootloader, or boot Chrome OS from
+ * disk.
+ *
+ * If a timeout occurs, take the default boot action.
+ *
+ * @param ctx		Vboot context
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+vb2_error_t vb2ex_developer_ui(struct vb2_context *ctx);
+
+/**
+ * UI for a diagnostic tools boot.
+ *
+ * Enter the diagnostic tools menu, which provides debug information and
+ * diagnostic tests of various hardware components.
+ *
+ * @param ctx		Vboot context
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *ctx);
+
 /* Helpers for bitmask operations */
 #define VB2_SET_BIT(mask, index) ((mask) |= ((uint32_t)1 << (index)))
 #define VB2_CLR_BIT(mask, index) ((mask) &= ~((uint32_t)1 << (index)))
@@ -1386,6 +1503,8 @@
 	VB2_UI_ERROR_UNTRUSTED_CONFIRMATION,
 	/* To-norm not allowed */
 	VB2_UI_ERROR_TO_NORM_NOT_ALLOWED,
+	/* Internal boot failed */
+	VB2_UI_ERROR_INTERNAL_BOOT_FAILED,
 	/* External boot is disabled */
 	VB2_UI_ERROR_EXTERNAL_BOOT_DISABLED,
 	/* Alternate bootloader is disabled */
@@ -1589,17 +1708,6 @@
 vb2_error_t vb2ex_diag_memory_full_test(int reset, const char **out);
 
 /*****************************************************************************/
-/* Functions for diagnostics control. */
-
-enum vb2_diag_storage_test {
-	VB2_DIAG_STORAGE_TEST_STOP = 0,
-	VB2_DIAG_STORAGE_TEST_SHORT,
-	VB2_DIAG_STORAGE_TEST_EXTENDED,
-};
-
-vb2_error_t vb2ex_diag_storage_test_control(enum vb2_diag_storage_test ops);
-
-/*****************************************************************************/
 /* Timer. */
 
 /**
diff --git a/firmware/2lib/include/2common.h b/firmware/2lib/include/2common.h
index 918c50d..695f50d 100644
--- a/firmware/2lib/include/2common.h
+++ b/firmware/2lib/include/2common.h
@@ -86,10 +86,10 @@
 #endif
 
 #if (defined(__GNUC__) && __GNUC__ >= 7)
-#define VBOOT_FALLTHROUGH __attribute__((fallthrough))
+#define VBOOT_FALLTHROUGH __attribute__((__fallthrough__))
 #elif defined(__clang__)
-#if __has_attribute(fallthrough)
-#define VBOOT_FALLTHROUGH __attribute__((fallthrough))
+#if __has_attribute(__fallthrough__)
+#define VBOOT_FALLTHROUGH __attribute__((__fallthrough__))
 #endif
 #else
 #define VBOOT_FALLTHROUGH ((void)0)
@@ -298,7 +298,7 @@
 static inline const uint8_t *vb2_packed_key_data(
 	const struct vb2_packed_key *key)
 {
-	return (const uint8_t *)key + key->key_offset;
+	return (const uint8_t *)((uintptr_t)key + key->key_offset);
 }
 
 /**
@@ -331,7 +331,7 @@
 static inline const uint8_t *vb2_signature_data(
 	const struct vb2_signature *sig)
 {
-	return (const uint8_t *)sig + sig->sig_offset;
+	return (const uint8_t *)((uintptr_t)sig + sig->sig_offset);
 }
 
 /**
diff --git a/firmware/2lib/include/2misc.h b/firmware/2lib/include/2misc.h
index 3d96293..b36e127 100644
--- a/firmware/2lib/include/2misc.h
+++ b/firmware/2lib/include/2misc.h
@@ -162,32 +162,6 @@
 vb2_error_t vb2_load_kernel_preamble(struct vb2_context *ctx);
 
 /**
- * Utility function to enable developer mode.
- *
- * Enables the developer flag in vb2_context firmware secdata.  Note that
- * modified secdata must be saved for change to apply on reboot.
- *
- * NOTE: Doesn't update the LAST_BOOT_DEVELOPER secdata flag.  That should be
- * done on the next boot.
- *
- * @param ctx		Vboot context
- */
-void vb2_enable_developer_mode(struct vb2_context *ctx);
-
-/**
- * Check whether recovery is allowed or not.
- *
- * The only way to pass this check and proceed to the recovery process is to
- * physically request a recovery (a.k.a. manual recovery).  All other recovery
- * requests including manual recovery requested by a (compromised) host will
- * end up with 'broken' screen.
- *
- * @param ctx		Vboot context
- * @return 1 if recovery is allowed; 0 if no or uncertain.
- */
-int vb2_allow_recovery(struct vb2_context *ctx);
-
-/**
  * Clear recovery request appropriately.
  *
  * To avoid the recovery request "sticking" and the user being in a permanent
@@ -210,38 +184,11 @@
 void vb2_clear_recovery(struct vb2_context *ctx);
 
 /**
- * Determine if developer mode is allowed.
+ * Fill VB2_CONTEXT_DEV_BOOT_ALLOWED, VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED and
+ * VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED flags in ctx->flags.
  *
- * Developer boot is not allowed if and only if FWMP_DEV_DISABLE_BOOT is set and
- * GBB_FORCE_DEV_SWITCH_ON is not set.
- *
- * @param ctx		Vboot context
- * @return 1 if allowed, or 0 otherwise.
+ * @param ctx		Vboot context.
  */
-int vb2_dev_boot_allowed(struct vb2_context *ctx);
-
-/**
- * Determine if booting from legacy BIOS is allowed.
- *
- * Legacy BIOS is allowed if any of these flags are set:
- * VB2_NV_DEV_BOOT_ALTFW, VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW, and
- * VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW.
- *
- * @param ctx		Vboot context
- * @return 1 if allowed, or 0 otherwise.
- */
-int vb2_dev_boot_altfw_allowed(struct vb2_context *ctx);
-
-/**
- * Determine if booting from external disk is allowed.
- *
- * Booting from external disk is allowed if any of these flags are set:
- * VB2_NV_DEV_BOOT_EXTERNAL, VB2_GBB_FLAG_FORCE_DEV_BOOT_USB, and
- * VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL.
- *
- * @param ctx		Vboot context
- * @return 1 if allowed, or 0 otherwise.
- */
-int vb2_dev_boot_external_allowed(struct vb2_context *ctx);
+void vb2_fill_dev_boot_flags(struct vb2_context *ctx);
 
 #endif  /* VBOOT_REFERENCE_2MISC_H_ */
diff --git a/firmware/2lib/include/2nvstorage.h b/firmware/2lib/include/2nvstorage.h
index 2f40b23..fe75823 100644
--- a/firmware/2lib/include/2nvstorage.h
+++ b/firmware/2lib/include/2nvstorage.h
@@ -125,6 +125,8 @@
 	VB2_NV_POST_EC_SYNC_DELAY,
 	/* Request booting of diagnostic rom.  0=no, 1=yes. */
 	VB2_NV_DIAG_REQUEST,
+	/* Priority of miniOS partition to load: 0=MINIOS-A, 1=MINIOS-B. */
+	VB2_NV_MINIOS_PRIORITY,
 };
 
 /* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */
diff --git a/firmware/2lib/include/2nvstorage_fields.h b/firmware/2lib/include/2nvstorage_fields.h
index 9575e87..449b8fd 100644
--- a/firmware/2lib/include/2nvstorage_fields.h
+++ b/firmware/2lib/include/2nvstorage_fields.h
@@ -79,7 +79,7 @@
 #define VB2_NV_BOOT_DISABLE_DEV                0x40
 #define VB2_NV_BOOT_DEBUG_RESET                0x80
 
-/* Fields in VB2_NV_OFFS_BOOT2 (unused = 0x00) */
+/* Fields in VB2_NV_OFFS_BOOT2 */
 #define VB2_NV_BOOT2_RESULT_MASK               0x03
 #define VB2_NV_BOOT2_TRIED                     0x04
 #define VB2_NV_BOOT2_TRY_NEXT                  0x08
@@ -102,11 +102,12 @@
 #define VB2_NV_TPM_CLEAR_OWNER_DONE            0x02
 #define VB2_NV_TPM_REBOOTED                    0x04
 
-/* Fields in VB2_NV_OFFS_MISC (unused = 0x80) */
+/* Fields in VB2_NV_OFFS_MISC (unused = 0xa0) */
 #define VB2_NV_MISC_DEPRECATED_UNLOCK_FASTBOOT            0x01
 #define VB2_NV_MISC_BOOT_ON_AC_DETECT          0x02
 #define VB2_NV_MISC_TRY_RO_SYNC		       0x04
 #define VB2_NV_MISC_BATTERY_CUTOFF             0x08
+#define VB2_NV_MISC_MINIOS_PRIORITY            0x10
 #define VB2_NV_MISC_POST_EC_SYNC_DELAY         0x40
 
 #endif  /* VBOOT_REFERENCE_2NVSTORAGE_FIELDS_H_ */
diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h
index 4512ff8..0dc7c44 100644
--- a/firmware/2lib/include/2return_codes.h
+++ b/firmware/2lib/include/2return_codes.h
@@ -454,168 +454,174 @@
 	VB2_ERROR_MISC = VB2_ERROR_BASE + 0x080000,
 
 	/* Work buffer too small (see vb2api_init and vb2api_reinit) */
-	VB2_ERROR_WORKBUF_SMALL,
+	VB2_ERROR_WORKBUF_SMALL = 0x10080001,
 
 	/* Work buffer unaligned (see vb2api_init and vb2api_reinit) */
-	VB2_ERROR_WORKBUF_ALIGN,
+	VB2_ERROR_WORKBUF_ALIGN = 0x10080002,
 
 	/* Work buffer too small in GBB-related function */
-	VB2_ERROR_GBB_WORKBUF,
+	VB2_ERROR_GBB_WORKBUF = 0x10080003,
 
 	/* Bad magic number in vb2_read_gbb_header() */
-	VB2_ERROR_GBB_MAGIC,
+	VB2_ERROR_GBB_MAGIC = 0x10080004,
 
 	/* Incompatible version in vb2_read_gbb_header() */
-	VB2_ERROR_GBB_VERSION,
+	VB2_ERROR_GBB_VERSION = 0x10080005,
 
 	/* Old version in vb2_read_gbb_header() */
-	VB2_ERROR_GBB_TOO_OLD,
+	VB2_ERROR_GBB_TOO_OLD = 0x10080006,
 
 	/* Header size too small in vb2_read_gbb_header() */
-	VB2_ERROR_GBB_HEADER_SIZE,
+	VB2_ERROR_GBB_HEADER_SIZE = 0x10080007,
 
 	/* Work buffer too small for root key in vb2_load_fw_keyblock() */
-	VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY,
+	VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY = 0x10080008,
 
 	/* Work buffer too small for header in vb2_load_fw_keyblock() */
-	VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER,
+	VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER = 0x10080009,
 
 	/* Work buffer too small for keyblock in vb2_load_fw_keyblock() */
-	VB2_ERROR_FW_KEYBLOCK_WORKBUF,
+	VB2_ERROR_FW_KEYBLOCK_WORKBUF = 0x1008000a,
 
 	/* Keyblock version out of range in vb2_load_fw_keyblock() */
-	VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE,
+	VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE = 0x1008000b,
 
 	/* Keyblock version rollback in vb2_load_fw_keyblock() */
-	VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK,
+	VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK = 0x1008000c,
 
 	/* Missing firmware data key in vb2_load_fw_preamble() */
-	VB2_ERROR_FW_PREAMBLE2_DATA_KEY,
+	VB2_ERROR_FW_PREAMBLE2_DATA_KEY = 0x1008000d,
 
 	/* Work buffer too small for header in vb2_load_fw_preamble() */
-	VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER,
+	VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER = 0x1008000e,
 
 	/* Work buffer too small for preamble in vb2_load_fw_preamble() */
-	VB2_ERROR_FW_PREAMBLE2_WORKBUF,
+	VB2_ERROR_FW_PREAMBLE2_WORKBUF = 0x1008000f,
 
 	/* Firmware version out of range in vb2_load_fw_preamble() */
-	VB2_ERROR_FW_PREAMBLE_VERSION_RANGE,
+	VB2_ERROR_FW_PREAMBLE_VERSION_RANGE = 0x10080010,
 
 	/* Firmware version rollback in vb2_load_fw_preamble() */
-	VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK,
+	VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK = 0x10080011,
 
 	/* Not enough space in work buffer for resource object */
-	VB2_ERROR_READ_RESOURCE_OBJECT_BUF,
+	VB2_ERROR_READ_RESOURCE_OBJECT_BUF = 0x10080012,
 
 	/* Work buffer too small for header in vb2_load_kernel_keyblock() */
-	VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF_HEADER,
+	VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF_HEADER = 0x10080013,
 
 	/* Work buffer too small for keyblock in vb2_load_kernel_keyblock() */
-	VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF,
+	VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF = 0x10080014,
 
 	/* Keyblock version out of range in vb2_load_kernel_keyblock() */
-	VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE,
+	VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE = 0x10080015,
 
 	/* Keyblock version rollback in vb2_load_kernel_keyblock() */
-	VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK,
+	VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK = 0x10080016,
 
 	/*
 	 * Keyblock flags don't match current mode in
 	 * vb2_load_kernel_keyblock().
 	 */
-	VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG,
-	VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG,
+	VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG = 0x10080017,
+	VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG = 0x10080018,
 
 	/* Missing firmware data key in vb2_load_kernel_preamble() */
-	VB2_ERROR_KERNEL_PREAMBLE2_DATA_KEY,
+	VB2_ERROR_KERNEL_PREAMBLE2_DATA_KEY = 0x10080019,
 
 	/* Work buffer too small for header in vb2_load_kernel_preamble() */
-	VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF_HEADER,
+	VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF_HEADER = 0x1008001a,
 
 	/* Work buffer too small for preamble in vb2_load_kernel_preamble() */
-	VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF,
+	VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF = 0x1008001b,
 
 	/* Kernel version out of range in vb2_load_kernel_preamble() */
-	VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE,
+	VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE = 0x1008001c,
 
 	/* Kernel version rollback in vb2_load_kernel_preamble() */
-	VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK,
+	VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK = 0x1008001d,
 
 	/* Kernel preamble not loaded before calling vb2api_get_kernel_size() */
-	VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE,
+	VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE = 0x1008001e,
 
 	/* Unable to unpack kernel subkey in vb2_verify_vblock();
 	 * deprecated and replaced with VB2_ERROR_UNPACK_KEY_* */
-	VB2_ERROR_DEPRECATED_VBLOCK_KERNEL_SUBKEY,
+	VB2_ERROR_DEPRECATED_VBLOCK_KERNEL_SUBKEY = 0x1008001f,
 
 	/*
 	 * Got a self-signed kernel in vb2_verify_vblock(), but need an
 	 * officially signed one; deprecated and replaced with
 	 * VB2_ERROR_KERNEL_KEYBLOCK_*.
 	 */
-	VB2_ERROR_DEPRECATED_VBLOCK_SELF_SIGNED,
+	VB2_ERROR_DEPRECATED_VBLOCK_SELF_SIGNED = 0x10080020,
 
 	/* Invalid keyblock hash in vb2_verify_vblock();
 	 * deprecated and replaced with VB2_ERROR_KERNEL_KEYBLOCK_* */
-	VB2_ERROR_DEPRECATED_VBLOCK_KEYBLOCK_HASH,
+	VB2_ERROR_DEPRECATED_VBLOCK_KEYBLOCK_HASH = 0x10080021,
 
 	/* Invalid keyblock in vb2_verify_vblock();
 	 * deprecated and replaced with VB2_ERROR_KERNEL_KEYBLOCK_* */
-	VB2_ERROR_DEPRECATED_VBLOCK_KEYBLOCK,
+	VB2_ERROR_DEPRECATED_VBLOCK_KEYBLOCK = 0x10080022,
 
 	/* Wrong dev key hash in vb2_verify_kernel_vblock_dev_key_hash() */
-	VB2_ERROR_KERNEL_KEYBLOCK_DEV_KEY_HASH,
+	VB2_ERROR_KERNEL_KEYBLOCK_DEV_KEY_HASH = 0x10080023,
 
 	/* Work buffer too small in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_WORKBUF,
+	VB2_ERROR_LOAD_PARTITION_WORKBUF = 0x10080024,
 
 	/* Unable to read vblock in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_READ_VBLOCK,
+	VB2_ERROR_LOAD_PARTITION_READ_VBLOCK = 0x10080025,
 
 	/* Unable to verify vblock in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK,
+	VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK = 0x10080026,
 
 	/* Kernel body offset too large in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_BODY_OFFSET,
+	VB2_ERROR_LOAD_PARTITION_BODY_OFFSET = 0x10080027,
 
 	/* Kernel body too big in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_BODY_SIZE,
+	VB2_ERROR_LOAD_PARTITION_BODY_SIZE = 0x10080028,
 
 	/* Unable to read kernel body in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_READ_BODY,
+	VB2_ERROR_LOAD_PARTITION_READ_BODY = 0x10080029,
 
 	/* Unable to unpack data key in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_DATA_KEY,
+	VB2_ERROR_LOAD_PARTITION_DATA_KEY = 0x1008002a,
 
 	/* Unable to verify body in vb2_load_partition() */
-	VB2_ERROR_LOAD_PARTITION_VERIFY_BODY,
+	VB2_ERROR_LOAD_PARTITION_VERIFY_BODY = 0x1008002b,
 
 	/* Unable to get EC image hash in ec_sync_phase1() */
-	VB2_ERROR_EC_HASH_IMAGE,
+	VB2_ERROR_EC_HASH_IMAGE = 0x1008002c,
 
 	/* Unable to get expected EC image hash in ec_sync_phase1() */
-	VB2_ERROR_EC_HASH_EXPECTED,
+	VB2_ERROR_EC_HASH_EXPECTED = 0x1008002d,
 
 	/* Expected and image hashes are different size in ec_sync_phase1() */
-	VB2_ERROR_EC_HASH_SIZE,
+	VB2_ERROR_EC_HASH_SIZE = 0x1008002e,
 
 	/* Incompatible version for vb2_shared_data structure being loaded */
-	VB2_ERROR_SHARED_DATA_VERSION,
+	VB2_ERROR_SHARED_DATA_VERSION = 0x1008002f,
 
 	/* Bad magic number in vb2_shared_data structure */
-	VB2_ERROR_SHARED_DATA_MAGIC,
+	VB2_ERROR_SHARED_DATA_MAGIC = 0x10080030,
 
 	/* Some part of GBB data is invalid */
-	VB2_ERROR_GBB_INVALID,
+	VB2_ERROR_GBB_INVALID = 0x10080031,
 
 	/* Invalid parameter */
-	VB2_ERROR_INVALID_PARAMETER,
+	VB2_ERROR_INVALID_PARAMETER = 0x10080032,
 
 	/* Problem with workbuf validity (see vb2api_init and vb2api_reinit) */
-	VB2_ERROR_WORKBUF_INVALID,
+	VB2_ERROR_WORKBUF_INVALID = 0x10080033,
 
-	/* Escape from NO_BOOT mode is detected. */
-	VB2_ERROR_ESCAPE_NO_BOOT,
+	/* Escape from NO_BOOT mode is detected */
+	VB2_ERROR_ESCAPE_NO_BOOT = 0x10080034,
+
+	/*
+	 * Keyblock flags don't match current mode in
+	 * vb2_load_kernel_keyblock().
+	 */
+	VB2_ERROR_KERNEL_KEYBLOCK_MINIOS_FLAG = 0x10080035,
 
 	/**********************************************************************
 	 * API-level errors
@@ -701,6 +707,12 @@
 	/* Digest buffer passed into vb2api_check_hash incorrect. */
 	VB2_ERROR_API_CHECK_DIGEST_SIZE,
 
+	/* Disabling developer mode is not allowed by GBB flags */
+	VB2_ERROR_API_DISABLE_DEV_NOT_ALLOWED,
+
+	/* Enabling developer mode is not allowed in non-recovery mode */
+	VB2_ERROR_API_ENABLE_DEV_NOT_ALLOWED,
+
 	/**********************************************************************
 	 * Errors which may be generated by implementations of vb2ex functions.
 	 * Implementation may also return its own specific errors, which should
diff --git a/firmware/2lib/include/2sha_private.h b/firmware/2lib/include/2sha_private.h
new file mode 100644
index 0000000..ffa79f2
--- /dev/null
+++ b/firmware/2lib/include/2sha_private.h
@@ -0,0 +1,38 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Constants & macro for sha algorithms.
+ */
+
+#ifndef VBOOT_REFERENCE_2SHA_PRIVATE_H_
+#define VBOOT_REFERENCE_2SHA_PRIVATE_H_
+
+/* Sha256 padding is consisted of 0x80 + zeros + length of message (8 byte).
+ * So minimum length for padding is 9.
+ */
+#define SHA256_MIN_PAD_LEN 9
+
+/* Beginning of sha256 padding is always 0x80 when messages are in bytes
+ */
+#define SHA256_PAD_BEGIN 0x80
+
+extern const uint32_t vb2_sha256_h0[8];
+extern const uint32_t vb2_sha256_k[64];
+
+#define UNPACK32(x, str)				\
+	{						\
+		*((str) + 3) = (uint8_t) ((x)      );	\
+		*((str) + 2) = (uint8_t) ((x) >>  8);	\
+		*((str) + 1) = (uint8_t) ((x) >> 16);	\
+		*((str) + 0) = (uint8_t) ((x) >> 24);	\
+	}
+
+#define PACK32(str, x)						\
+	{							\
+		*(x) =   ((uint32_t) *((str) + 3)      )	\
+			| ((uint32_t) *((str) + 2) <<  8)       \
+			| ((uint32_t) *((str) + 1) << 16)       \
+			| ((uint32_t) *((str) + 0) << 24);      \
+	}
+#endif  /* VBOOT_REFERENCE_2SHA_PRIVATE_H_ */
diff --git a/firmware/2lib/include/2struct.h b/firmware/2lib/include/2struct.h
index b79bbd0..ea193d7 100644
--- a/firmware/2lib/include/2struct.h
+++ b/firmware/2lib/include/2struct.h
@@ -364,6 +364,8 @@
 #define VB2_KEYBLOCK_FLAG_DEVELOPER_1 0x2  /* Developer switch on */
 #define VB2_KEYBLOCK_FLAG_RECOVERY_0 0x4  /* Not recovery mode */
 #define VB2_KEYBLOCK_FLAG_RECOVERY_1 0x8  /* Recovery mode */
+#define VB2_KEYBLOCK_FLAG_MINIOS_0 0x10  /* Not miniOS boot */
+#define VB2_KEYBLOCK_FLAG_MINIOS_1 0x20  /* miniOS boot */
 
 /*
  * Keyblock, containing the public key used to sign some other chunk of data.
diff --git a/firmware/2lib/include/2sysincludes.h b/firmware/2lib/include/2sysincludes.h
index 0671772..1e671e9 100644
--- a/firmware/2lib/include/2sysincludes.h
+++ b/firmware/2lib/include/2sysincludes.h
@@ -21,9 +21,4 @@
 #include <stdlib.h>
 #include <string.h>
 
-#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
-#include <byteswap.h>
-#include <memory.h>
-#endif
-
 #endif  /* VBOOT_REFERENCE_2SYSINCLUDES_H_ */
diff --git a/firmware/2lib/include/2ui.h b/firmware/2lib/include/2ui.h
deleted file mode 100644
index bfb2b8b..0000000
--- a/firmware/2lib/include/2ui.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * User interfaces for developer and recovery mode menus.
- */
-
-#ifndef VBOOT_REFERENCE_2UI_H_
-#define VBOOT_REFERENCE_2UI_H_
-
-#include <2api.h>
-#include <2sysincludes.h>
-
-/*****************************************************************************/
-/* Data structures */
-
-struct vb2_ui_context;  /* Forward declaration */
-
-struct vb2_menu_item {
-	/* Text description */
-	const char *text;
-	/* Target screen */
-	enum vb2_screen target;
-	/* Action function takes precedence over target screen if non-NULL. */
-	vb2_error_t (*action)(struct vb2_ui_context *ui);
-	/* Whether the item is language selection */
-	int is_language_select;
-};
-
-struct vb2_menu {
-	/* Number of menu items */
-	uint16_t num_items;
-	/* List of menu items */
-	const struct vb2_menu_item *items;
-};
-
-struct vb2_screen_info {
-	/* Screen id */
-	enum vb2_screen id;
-	/* Screen name for printing to console only */
-	const char *name;
-	/*
-	 * Init function runs once when changing to the screen which is not in
-	 * the history stack.
-	 */
-	vb2_error_t (*init)(struct vb2_ui_context *ui);
-	/*
-	 * Re-init function runs once when changing to the screen which is
-	 * already in the history stack, for example, when going back to the
-	 * screen. Exactly one of init() and reinit() will be called.
-	 */
-	vb2_error_t (*reinit)(struct vb2_ui_context *ui);
-	/* Action function runs repeatedly while on the screen. */
-	vb2_error_t (*action)(struct vb2_ui_context *ui);
-	/* Menu items. */
-	struct vb2_menu menu;
-	/*
-	 * Custom function for getting menu items. If non-null, field 'menu'
-	 * will be ignored.
-	 */
-	const struct vb2_menu *(*get_menu)(struct vb2_ui_context *ui);
-	/*
-	 * Indices of menu items;
-	 * used by log_page_* functions in 2ui_screens.c.
-	 */
-	uint32_t page_up_item;
-	uint32_t page_down_item;
-	uint32_t back_item;
-	uint32_t cancel_item;
-};
-
-struct vb2_screen_state {
-	const struct vb2_screen_info *screen;
-	uint32_t selected_item;
-	uint32_t disabled_item_mask;
-	uint32_t hidden_item_mask;
-
-	/* For log screen. */
-	uint32_t page_count;
-	uint32_t current_page;
-
-	/* For minidiag test screens. */
-	int test_finished;  /* Do not update screen if the content is done */
-
-	struct vb2_screen_state *prev;
-};
-
-enum vb2_power_button {
-	VB2_POWER_BUTTON_HELD_SINCE_BOOT = 0,
-	VB2_POWER_BUTTON_RELEASED,
-	VB2_POWER_BUTTON_PRESSED,  /* Must have been previously released */
-};
-
-struct vb2_ui_context {
-	struct vb2_context *ctx;
-	struct vb2_screen_state *state;
-	uint32_t locale_id;
-	uint32_t key;
-	int key_trusted;
-
-	/* For check_shutdown_request. */
-	enum vb2_power_button power_button;
-
-	/* For developer mode. */
-	int disable_timer;
-	uint32_t start_time_ms;
-	int beep_count;
-
-	/* For manual recovery. */
-	vb2_error_t recovery_rv;
-
-	/* For to_dev transition flow. */
-	int physical_presence_button_pressed;
-
-	/* For language selection screen. */
-	struct vb2_menu language_menu;
-
-	/* For bootloader selection screen. */
-	struct vb2_menu bootloader_menu;
-
-	/* For error beep sound. */
-	int error_beep;
-
-	/* For displaying error messages. */
-	enum vb2_ui_error error_code;
-
-	/* Force calling vb2ex_display_ui for refreshing the screen. This flag
-	   will be reset after done. */
-	int force_display;
-};
-
-vb2_error_t vb2_ui_developer_mode_boot_internal_action(
-	struct vb2_ui_context *ui);
-vb2_error_t vb2_ui_developer_mode_boot_external_action(
-	struct vb2_ui_context *ui);
-vb2_error_t vb2_ui_developer_mode_boot_altfw_action(
-	struct vb2_ui_context *ui);
-
-/**
- * Get info struct of a screen.
- *
- * @param id		Screen from enum vb2_screen
- *
- * @return screen info struct on success, NULL on error.
- */
-const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen id);
-
-/*****************************************************************************/
-/* Menu navigation functions */
-
-/**
- * Move selection to the previous menu item.
- *
- * Update selected_item, taking into account hidden indices (from
- * hidden_item_mask).  The selection does not wrap, meaning that we block
- * on 0 when we hit the start of the menu.
- *
- * @param ui		UI context pointer
- * @return VB2_SUCCESS, or error code on error.
- */
-vb2_error_t vb2_ui_menu_prev(struct vb2_ui_context *ui);
-
-/**
- * Move selection to the next menu item.
- *
- * Update selected_item, taking into account hidden indices (from
- * hidden_item_mask).  The selection does not wrap, meaning that we block
- * on the max index when we hit the end of the menu.
- *
- * @param ui		UI context pointer
- * @return VB2_SUCCESS, or error code on error.
- */
-vb2_error_t vb2_ui_menu_next(struct vb2_ui_context *ui);
-
-/**
- * Select the current menu item.
- *
- * The caller should take care of returning after this function, and should not
- * continue executing under the assumption that the screen has *not* changed.
- *
- * If the current menu item has an action associated with it, run the action.
- * Otherwise, navigate to the target screen.  If neither of these are set, then
- * selecting the menu item is a no-op.
- *
- * @param ui		UI context pointer
- * @return VB2_SUCCESS, or error code on error.
- */
-vb2_error_t vb2_ui_menu_select(struct vb2_ui_context *ui);
-
-/*****************************************************************************/
-/* Screen navigation functions */
-/**
- * After these functions are called, no assumptions may be made about which
- * screen is currently displayed, and thus execution should return to ui_loop.
- * VB2_REQUEST_UI_CONTINUE is returned rather than VB2_SUCCESS, so VB2_TRY can
- * be used to wrapped to these functions and the callers of these functions.
- */
-/**
- * Return back to the previous screen.
- *
- * The caller should take care of returning after this function, and should not
- * continue executing under the assumption that the screen has *not* changed.
- *
- * If the current screen is already the root screen, the request is ignored.
- *
- * TODO(b/157625765): Consider falling into recovery mode (BROKEN screen) when
- * the current screen is already the root screen.
- *
- * @param ui		UI context pointer
- * @return VB2_REQUEST_UI_CONTINUE, or error code on error.
- */
-vb2_error_t vb2_ui_screen_back(struct vb2_ui_context *ui);
-
-/**
- * Change to the given screen.
- *
- * The caller should take care of returning after this function, and should not
- * continue executing under the assumption that the screen has *not* changed.
- *
- * If the screen is not found, the request is ignored.
- *
- * TODO(b/157625765): Consider falling into recovery mode (BROKEN screen) when
- * the target screen is not found.
- *
- * @param ui		UI context pointer
- * @param id		Screen from enum vb2_screen
- * @return VB2_REQUEST_UI_CONTINUE, or error code on error.
- */
-vb2_error_t vb2_ui_screen_change(struct vb2_ui_context *ui, enum vb2_screen id);
-
-/*****************************************************************************/
-/* UI loops */
-
-/**
- * UI for a developer-mode boot.
- *
- * Enter the developer menu, which provides options to switch out of developer
- * mode, boot from external media, use legacy bootloader, or boot Chrome OS from
- * disk.
- *
- * If a timeout occurs, take the default boot action.
- *
- * @param ctx		Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2_developer_menu(struct vb2_context *ctx);
-
-/**
- * UI for a non-manual recovery ("BROKEN").
- *
- * Enter the recovery menu, which shows that an unrecoverable error was
- * encountered last boot. Wait for the user to physically reset or shut down.
- *
- * @param ctx		Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2_broken_recovery_menu(struct vb2_context *ctx);
-
-/**
- * UI for a manual recovery-mode boot.
- *
- * Enter the recovery menu, which prompts the user to insert recovery media,
- * navigate the step-by-step recovery, or enter developer mode if allowed.
- *
- * @param ctx		Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2_manual_recovery_menu(struct vb2_context *ctx);
-
-/**
- * UI for a diagnostic tools boot.
- *
- * Enter the diagnostic tools menu, which provides debug information and
- * diagnostic tests of various hardware components.
- *
- * @param ctx		Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2_diagnostic_menu(struct vb2_context *ctx);
-
-#endif  /* VBOOT_REFERENCE_2UI_H_ */
diff --git a/firmware/2lib/include/2ui_private.h b/firmware/2lib/include/2ui_private.h
deleted file mode 100644
index 6ce6cf8..0000000
--- a/firmware/2lib/include/2ui_private.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Private declarations for 2ui.c. Defined here for testing purposes.
- */
-
-#include "2api.h"
-#include "2common.h"
-
-#ifndef VBOOT_REFERENCE_2UI_PRIVATE_H_
-#define VBOOT_REFERENCE_2UI_PRIVATE_H_
-
-/* Time-related constants */
-#define KEY_DELAY_MS 20  /* Delay between key scans in UI loops */
-#define DEV_DELAY_SHORT_MS (2 * VB2_MSEC_PER_SEC)  /* 2 seconds */
-#define DEV_DELAY_NORMAL_MS (30 * VB2_MSEC_PER_SEC)  /* 30 seconds */
-#define DEV_DELAY_BEEP1_MS (20 * VB2_MSEC_PER_SEC)  /* 20 seconds */
-#define DEV_DELAY_BEEP2_MS (20 * VB2_MSEC_PER_SEC + 500)  /* 20.5 seconds */
-
-/* From 2ui.c */
-vb2_error_t check_shutdown_request(struct vb2_ui_context *ui);
-const struct vb2_menu *get_menu(struct vb2_ui_context *ui);
-vb2_error_t error_exit_action(struct vb2_ui_context *ui);
-vb2_error_t menu_navigation_action(struct vb2_ui_context *ui);
-vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id,
-		    vb2_error_t (*global_action)(struct vb2_ui_context *ui));
-vb2_error_t developer_action(struct vb2_ui_context *ui);
-vb2_error_t broken_recovery_action(struct vb2_ui_context *ui);
-vb2_error_t manual_recovery_action(struct vb2_ui_context *ui);
-
-/* From 2ui_screens.c */
-const struct vb2_menu *get_language_menu(struct vb2_ui_context *ui);
-vb2_error_t advanced_options_init(struct vb2_ui_context *ui);
-vb2_error_t recovery_select_init(struct vb2_ui_context *ui);
-vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui);
-vb2_error_t recovery_to_dev_confirm_action(struct vb2_ui_context *ui);
-vb2_error_t recovery_to_dev_action(struct vb2_ui_context *ui);
-vb2_error_t developer_mode_init(struct vb2_ui_context *ui);
-vb2_error_t developer_mode_action(struct vb2_ui_context *ui);
-vb2_error_t developer_to_norm_action(struct vb2_ui_context *ui);
-
-#endif  /* VBOOT_REFERENCE_2UI_PRIVATE_H_ */
diff --git a/firmware/include/gpt.h b/firmware/include/gpt.h
index ff6ee32..9f50509 100644
--- a/firmware/include/gpt.h
+++ b/firmware/include/gpt.h
@@ -53,6 +53,10 @@
 	{{{0xebd0a0a2,0xb9e5,0x4433,0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}}}}
 #define GPT_ENT_TYPE_LINUX_FS \
 	{{{0x0fc63daf,0x8483,0x4772,0x8e,0x79,{0x3d,0x69,0xd8,0x47,0x7d,0xe4}}}}
+#define GPT_ENT_TYPE_CHROMEOS_MINIOS \
+	{{{0x09845860,0x705f,0x4bb5,0xb1,0x6c,{0x8a,0x8a,0x09,0x9c,0xaf,0x52}}}}
+#define GPT_ENT_TYPE_CHROMEOS_HIBERNATE \
+	{{{0x3f0f8318,0xf146,0x4e6b,0x82,0x22,{0xc2,0x8c,0x8f,0x02,0xe0,0xd5}}}}
 
 #define UUID_NODE_LEN 6
 #define GUID_SIZE 16
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index 2b1d838..f19ee74 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -77,6 +77,33 @@
 vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
 				  VbSelectAndLoadKernelParams *kparams);
 
+/**
+ * Attempt loading a kernel from the specified type(s) of disks.
+ *
+ * If successful, sets kparams.disk_handle to the disk for the kernel and
+ * returns VB2_SUCCESS.
+ *
+ * @param ctx			Vboot context
+ * @param disk_flags		Flags to pass to VbExDiskGetInfo()
+ * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error.
+ */
+vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags);
+
+/**
+ * Attempt loading a miniOS kernel from internal disk.
+ *
+ * Scans sectors at the start and end of the disk, and looks for miniOS kernels
+ * starting at the beginning of the sector.  Attempts loading any miniOS
+ * kernels found.
+ *
+ * If successful, sets lkp.disk_handle to the disk for the kernel and returns
+ * VB2_SUCCESS.
+ *
+ * @param ctx			Vboot context
+ * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error.
+ */
+vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx);
+
 /*****************************************************************************/
 /* Disk access (previously in boot_device.h) */
 
@@ -255,82 +282,6 @@
 void VbExStreamClose(VbExStream_t stream);
 
 /*****************************************************************************/
-/* Keyboard and switches */
-
-/* Key code for CTRL + letter */
-#define VB_KEY_CTRL(letter) (letter & 0x1f)
-
-/* Key code for fn keys */
-#define VB_KEY_F(num) (num + 0x108)
-
-/* Key codes for required non-printable-ASCII characters. */
-enum VbKeyCode_t {
-	VB_KEY_ENTER = '\r',
-	VB_KEY_ESC = 0x1b,
-	VB_KEY_BACKSPACE = 0x8,
-	VB_KEY_UP = 0x100,
-	VB_KEY_DOWN = 0x101,
-	VB_KEY_LEFT = 0x102,
-	VB_KEY_RIGHT = 0x103,
-	VB_KEY_CTRL_ENTER = 0x104,
-};
-
-/*
- * WARNING!!! Before updating the codes in enum VbButtonCode_t, ensure that the
- * code does not overlap the values in VbKeyCode_t unless the button action is
- * the same as key action.
- */
-enum VbButtonCode_t {
-	/* Volume up/down short press match the values in 8042 driver. */
-	VB_BUTTON_VOL_UP_SHORT_PRESS = 0x62,
-	VB_BUTTON_VOL_DOWN_SHORT_PRESS = 0x63,
-	/* Dummy values used below. */
-	VB_BUTTON_POWER_SHORT_PRESS = 0x90,
-	VB_BUTTON_VOL_UP_LONG_PRESS = 0x91,
-	VB_BUTTON_VOL_DOWN_LONG_PRESS = 0x92,
-	VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS = 0x93,
-};
-
-/* Flags for additional information.
- * TODO(semenzato): consider adding flags for modifiers instead of
- * making up some of the key codes above.
- */
-enum VbKeyFlags_t {
-	VB_KEY_FLAG_TRUSTED_KEYBOARD = 1 << 0,
-};
-
-/**
- * Read the next keypress from the keyboard buffer.
- *
- * Returns the keypress, or zero if no keypress is pending or error.
- *
- * The following keys must be returned as ASCII character codes:
- *    0x08          Backspace
- *    0x09          Tab
- *    0x0D          Enter (carriage return)
- *    0x01 - 0x1A   Ctrl+A - Ctrl+Z (yes, those alias with backspace/tab/enter)
- *    0x1B          Esc (VB_KEY_ESC)
- *    0x20          Space
- *    0x30 - 0x39   '0' - '9'
- *    0x60 - 0x7A   'a' - 'z'
- *
- * Some extended keys must also be supported; see the VB_KEY_* defines above.
- *
- * Keys ('/') or key-chords (Fn+Q) not defined above may be handled in any of
- * the following ways:
- *    1. Filter (don't report anything if one of these keys is pressed).
- *    2. Report as ASCII (if a well-defined ASCII value exists for the key).
- *    3. Report as any other value in the range 0x200 - 0x2FF.
- * It is not permitted to report a key as a multi-byte code (for example,
- * sending an arrow key as the sequence of keys '\x1b', '[', '1', 'A'). */
-uint32_t VbExKeyboardRead(void);
-
-/**
- * Same as VbExKeyboardRead(), but return extra information.
- */
-uint32_t VbExKeyboardReadWithFlags(uint32_t *flags_ptr);
-
-/*****************************************************************************/
 /* Misc */
 
 /**
diff --git a/firmware/lib/include/load_kernel_fw.h b/firmware/lib/include/load_kernel_fw.h
index 96c8f86..af45470 100644
--- a/firmware/lib/include/load_kernel_fw.h
+++ b/firmware/lib/include/load_kernel_fw.h
@@ -12,10 +12,11 @@
 #include "vboot_api.h"
 
 /**
- * Attempt to load the kernel from the current device.
+ * Attempt to load kernel from the specified device.
  *
  * @param ctx		Vboot context
  * @param params	Params specific to loading the kernel
+ * @param disk_info	Disk from which to read kernel
  *
  * Returns VB2_SUCCESS if successful.  If unsuccessful, returns an error code.
  */
@@ -23,4 +24,17 @@
 		       VbSelectAndLoadKernelParams *params,
 		       VbDiskInfo *disk_info);
 
+/**
+ * Attempt to load miniOS kernel from the specified device.
+ *
+ * @param ctx		Vboot context
+ * @param params	Params specific to loading the kernel
+ * @param disk_info	Disk from which to read kernel
+ *
+ * Returns VB2_SUCCESS if successful.  If unsuccessful, returns an error code.
+ */
+vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx,
+			     VbSelectAndLoadKernelParams *params,
+			     VbDiskInfo *disk_info);
+
 #endif  /* VBOOT_REFERENCE_LOAD_KERNEL_FW_H_ */
diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h
deleted file mode 100644
index a9dc824..0000000
--- a/firmware/lib/include/vboot_kernel.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Data structure and API definitions for a verified boot kernel image.
- * (Firmware Portion)
- */
-
-#ifndef VBOOT_REFERENCE_VBOOT_KERNEL_H_
-#define VBOOT_REFERENCE_VBOOT_KERNEL_H_
-
-#include "cgptlib.h"
-#include "gpt_misc.h"
-#include "load_kernel_fw.h"
-#include "vboot_api.h"
-
-struct vb2_context;
-
-/**
- * Attempt loading a kernel from the specified type(s) of disks.
- *
- * If successful, sets lkp.disk_handle to the disk for the kernel and returns
- * VB2_SUCCESS.
- *
- * @param ctx			Vboot context
- * @param disk_flags		Flags to pass to VbExDiskGetInfo()
- * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error.
- */
-vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags);
-
-#endif  /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */
diff --git a/firmware/lib/include/vboot_struct.h b/firmware/lib/include/vboot_struct.h
index 8a06892..374dfd4 100644
--- a/firmware/lib/include/vboot_struct.h
+++ b/firmware/lib/include/vboot_struct.h
@@ -10,7 +10,7 @@
 
 #include <stdint.h>
 
-#include "vboot_kernel.h"
+#include "2sysincludes.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/firmware/lib/include/vboot_test.h b/firmware/lib/include/vboot_test.h
index 41e8e5d..fb1f52a 100644
--- a/firmware/lib/include/vboot_test.h
+++ b/firmware/lib/include/vboot_test.h
@@ -12,6 +12,6 @@
  * vboot_api_kernel.c */
 
 struct VbSelectAndLoadKernelParams;
-struct VbSelectAndLoadKernelParams *VbApiKernelGetParams(void);
+struct VbSelectAndLoadKernelParams **VbApiKernelGetParamsPtr(void);
 
 #endif  /* VBOOT_REFERENCE_TEST_API_H_ */
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 93de040..2abd57e 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -13,21 +13,19 @@
 #include "2rsa.h"
 #include "2secdata.h"
 #include "2sysincludes.h"
-#include "2ui.h"
 #include "load_kernel_fw.h"
 #include "vboot_api.h"
-#include "vboot_kernel.h"
 #include "vboot_struct.h"
 #include "vboot_test.h"
 
 /* Global variables */
-static VbSelectAndLoadKernelParams lkp;
+static VbSelectAndLoadKernelParams *kparams_ptr;
 
 #ifdef CHROMEOS_ENVIRONMENT
 /* Global variable accessor for unit tests */
-struct VbSelectAndLoadKernelParams *VbApiKernelGetParams(void)
+struct VbSelectAndLoadKernelParams **VbApiKernelGetParamsPtr(void)
 {
-	return &lkp;
+	return &kparams_ptr;
 }
 #endif
 
@@ -63,15 +61,20 @@
 		 ((info->flags & VB_DISK_FLAG_SELECT_MASK) - 1)) == 0;
 }
 
-test_mockable
-vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags)
+static vb2_error_t VbTryLoadKernelImpl(struct vb2_context *ctx,
+				       uint32_t disk_flags, int minios)
 {
 	vb2_error_t rv = VB2_ERROR_LK_NO_DISK_FOUND;
 	VbDiskInfo* disk_info = NULL;
 	uint32_t disk_count = 0;
 	uint32_t i;
+	vb2_error_t new_rv;
 
-	lkp.disk_handle = NULL;
+	/* TODO: Should have been set by VbSelectAndLoadKernel. Remove when
+	   this global is no longer needed. */
+	VB2_ASSERT(kparams_ptr);
+
+	kparams_ptr->disk_handle = NULL;
 
 	/* Find disks */
 	if (VB2_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count, disk_flags))
@@ -89,10 +92,16 @@
 				  disk_info[i].flags);
 			continue;
 		}
+		kparams_ptr->disk_handle = disk_info[i].handle;
 
-		lkp.disk_handle = disk_info[i].handle;
-		vb2_error_t new_rv = LoadKernel(ctx, &lkp, &disk_info[i]);
-		VB2_DEBUG("LoadKernel() = %#x\n", new_rv);
+		if (minios) {
+			new_rv = LoadMiniOsKernel(ctx, kparams_ptr,
+						  &disk_info[i]);
+			VB2_DEBUG("LoadMiniOsKernel() = %#x\n", new_rv);
+		} else {
+			new_rv = LoadKernel(ctx, kparams_ptr, &disk_info[i]);
+			VB2_DEBUG("LoadKernel() = %#x\n", new_rv);
+		}
 
 		/* Stop now if we found a kernel. */
 		if (VB2_SUCCESS == new_rv) {
@@ -130,38 +139,16 @@
 	return rv;
 }
 
-static vb2_error_t vb2_kernel_init_kparams(struct vb2_context *ctx,
-					   VbSelectAndLoadKernelParams *kparams)
+test_mockable
+vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags)
 {
-	/* Fill in params for calls to LoadKernel() */
-	memset(&lkp, 0, sizeof(lkp));
-	lkp.kernel_buffer = kparams->kernel_buffer;
-	lkp.kernel_buffer_size = kparams->kernel_buffer_size;
-
-	/* Clear output params in case we fail */
-	kparams->disk_handle = NULL;
-	kparams->partition_number = 0;
-	kparams->bootloader_address = 0;
-	kparams->bootloader_size = 0;
-	kparams->flags = 0;
-	memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));
-
-	return VB2_SUCCESS;
+	return VbTryLoadKernelImpl(ctx, disk_flags, 0);
 }
 
-static void vb2_kernel_fill_kparams(struct vb2_context *ctx,
-				    VbSelectAndLoadKernelParams *kparams)
+test_mockable
+vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx)
 {
-	/* Save disk parameters */
-	kparams->disk_handle = lkp.disk_handle;
-	kparams->partition_number = lkp.partition_number;
-	kparams->bootloader_address = lkp.bootloader_address;
-	kparams->bootloader_size = lkp.bootloader_size;
-	kparams->flags = lkp.flags;
-	kparams->kernel_buffer = lkp.kernel_buffer;
-	kparams->kernel_buffer_size = lkp.kernel_buffer_size;
-	memcpy(kparams->partition_guid, lkp.partition_guid,
-	       sizeof(kparams->partition_guid));
+	return VbTryLoadKernelImpl(ctx, VB_DISK_FLAG_FIXED, 1);
 }
 
 vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
@@ -170,12 +157,14 @@
 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
 	vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
 
+	/* TODO: Send this argument through subsequent function calls, rather
+	   than relying on a global to pass it to VbTryLoadKernel. */
+	kparams_ptr = kparams;
+
 	/* Init nvstorage space. TODO(kitching): Remove once we add assertions
 	   to vb2_nv_get and vb2_nv_set. */
 	vb2_nv_init(ctx);
 
-	VB2_TRY(vb2_kernel_init_kparams(ctx, kparams));
-
 	VB2_TRY(vb2api_kernel_phase1(ctx));
 
 	VB2_DEBUG("GBB flags are %#x\n", gbb_flags);
@@ -222,11 +211,11 @@
 			VB2_DEBUG("NO_BOOT in RECOVERY mode\n");
 
 		/* Recovery boot.  This has UI. */
-		if (vb2_allow_recovery(ctx))
-			VB2_TRY(vb2_manual_recovery_menu(ctx));
+		if (vb2api_allow_recovery(ctx))
+			VB2_TRY(vb2ex_manual_recovery_ui(ctx));
 		else
-			VB2_TRY(vb2_broken_recovery_menu(ctx));
-	} else if (DIAGNOSTIC_UI && vb2api_diagnostic_ui_enabled(ctx) &&
+			VB2_TRY(vb2ex_broken_screen_ui(ctx));
+	} else if (vb2api_diagnostic_ui_enabled(ctx) &&
 		   vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
 		/*
 		 * Need to clear the request flag and commit nvdata changes
@@ -237,7 +226,7 @@
 		vb2ex_commit_data(ctx);
 
 		/* Diagnostic boot.  This has UI. */
-		VB2_TRY(vb2_diagnostic_menu(ctx));
+		VB2_TRY(vb2ex_diagnostic_ui(ctx));
 		/*
 		 * The diagnostic menu should either boot a rom, or
 		 * return either of reboot or shutdown.
@@ -245,7 +234,7 @@
 		return VB2_REQUEST_REBOOT;
 	} else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) {
 		/* Developer boot.  This has UI. */
-		VB2_TRY(vb2_developer_menu(ctx));
+		VB2_TRY(vb2ex_developer_ui(ctx));
 	} else {
 		/* Normal boot */
 		VB2_TRY(vb2_normal_boot(ctx));
@@ -262,6 +251,5 @@
 		return VB2_ERROR_ESCAPE_NO_BOOT;
 	}
 
-	vb2_kernel_fill_kparams(ctx, kparams);
 	return VB2_SUCCESS;
 }
diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c
index 05458b0..34a8a42 100644
--- a/firmware/lib/vboot_kernel.c
+++ b/firmware/lib/vboot_kernel.c
@@ -18,6 +18,17 @@
 #include "load_kernel_fw.h"
 #include "vboot_api.h"
 
+enum vb2_load_partition_flags {
+	VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY = (1 << 0),
+	VB2_LOAD_PARTITION_FLAG_MINIOS = (1 << 1),
+};
+
+#define KBUF_SIZE 65536  /* Bytes to read at start of kernel partition */
+
+/* Minimum context work buffer size needed for vb2_load_partition() */
+#define VB2_LOAD_PARTITION_WORKBUF_BYTES	\
+	(VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES + KBUF_SIZE)
+
 #define LOWEST_TPM_VERSION 0xffffffff
 
 enum vb2_boot_mode {
@@ -163,15 +174,17 @@
 /**
  * Verify a kernel vblock.
  *
+ * @param ctx		Vboot context
  * @param kbuf		Buffer containing the vblock
  * @param kbuf_size	Size of the buffer in bytes
+ * @param lpflags	Flags (one or more of vb2_load_partition_flags)
  * @param wb		Work buffer.  Must be at least
  *			VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES bytes.
  * @return VB2_SUCCESS, or non-zero error code.
  */
 static vb2_error_t vb2_verify_kernel_vblock(
 	struct vb2_context *ctx, uint8_t *kbuf, uint32_t kbuf_size,
-	struct vb2_workbuf *wb)
+	uint32_t lpflags, struct vb2_workbuf *wb)
 {
 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
 
@@ -240,6 +253,15 @@
 		if (need_keyblock_valid)
 			return VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG;
 	}
+	if (!(keyblock->keyblock_flags &
+	      ((lpflags & VB2_LOAD_PARTITION_FLAG_MINIOS) ?
+	       VB2_KEYBLOCK_FLAG_MINIOS_1 :
+	       VB2_KEYBLOCK_FLAG_MINIOS_0))) {
+		VB2_DEBUG("Keyblock miniOS flag mismatch.\n");
+		keyblock_valid = 0;
+		if (need_keyblock_valid)
+			return VB2_ERROR_KERNEL_KEYBLOCK_MINIOS_FLAG;
+	}
 
 	/* Check for rollback of key version except in recovery mode. */
 	enum vb2_boot_mode boot_mode = get_boot_mode(ctx);
@@ -299,6 +321,29 @@
 		return rv;
 	}
 
+	/* Rollback check for miniOS */
+	if (need_keyblock_valid && (lpflags & VB2_LOAD_PARTITION_FLAG_MINIOS)) {
+		if (preamble->kernel_version <
+		    (sd->kernel_version_secdata >> 24)) {
+			keyblock_valid = 0;
+			if (need_keyblock_valid) {
+				VB2_DEBUG("miniOS kernel version too old.\n");
+				return VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK;
+			}
+		}
+		if (preamble->kernel_version > 0xff) {
+			/*
+			 * Key version is stored in the top 8 bits of 16 bits
+			 * in the TPM, so key versions greater than 0xFF can't
+			 * be stored properly.
+			 */
+			VB2_DEBUG("Key version > 0xFF.\n");
+			keyblock_valid = 0;
+			if (need_keyblock_valid)
+				return VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE;
+		}
+	}
+
 	/*
 	 * Kernel preamble version is the lower 16 bits of the composite
 	 * kernel version.
@@ -321,29 +366,18 @@
 	return VB2_SUCCESS;
 }
 
-enum vb2_load_partition_flags {
-	/* Only check the vblock to */
-	VB2_LOAD_PARTITION_VBLOCK_ONLY = (1 << 0),
-};
-
-#define KBUF_SIZE 65536  /* Bytes to read at start of kernel partition */
-
-/* Minimum context work buffer size needed for vb2_load_partition() */
-#define VB2_LOAD_PARTITION_WORKBUF_BYTES	\
-	(VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES + KBUF_SIZE)
-
 /**
  * Load and verify a partition from the stream.
  *
  * @param ctx		Vboot context
- * @param stream	Stream to load kernel from
- * @param flags		Flags (one or more of vb2_load_partition_flags)
  * @param params	Load-kernel parameters
+ * @param stream	Stream to load kernel from
+ * @param lpflags	Flags (one or more of vb2_load_partition_flags)
  * @return VB2_SUCCESS, or non-zero error code.
  */
 static vb2_error_t vb2_load_partition(
-	struct vb2_context *ctx, VbExStream_t stream, uint32_t flags,
-	VbSelectAndLoadKernelParams *params)
+	struct vb2_context *ctx, VbSelectAndLoadKernelParams *params,
+	VbExStream_t stream, uint32_t lpflags)
 {
 	uint32_t read_ms = 0, start_ts;
 	struct vb2_workbuf wb;
@@ -362,11 +396,10 @@
 	}
 	read_ms += vb2ex_mtime() - start_ts;
 
-	if (vb2_verify_kernel_vblock(ctx, kbuf, KBUF_SIZE, &wb)) {
+	if (vb2_verify_kernel_vblock(ctx, kbuf, KBUF_SIZE, lpflags, &wb))
 		return VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK;
-	}
 
-	if (flags & VB2_LOAD_PARTITION_VBLOCK_ONLY)
+	if (lpflags & VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY)
 		return VB2_SUCCESS;
 
 	struct vb2_keyblock *keyblock = get_keyblock(kbuf);
@@ -456,6 +489,143 @@
 	return VB2_SUCCESS;
 }
 
+static vb2_error_t try_minios_kernel(struct vb2_context *ctx,
+				     VbSelectAndLoadKernelParams *params,
+				     VbDiskInfo *disk_info,
+				     uint64_t sector) {
+	VbExStream_t stream;
+	uint64_t sectors_left = disk_info->lba_count - sector;
+	const uint32_t lpflags = VB2_LOAD_PARTITION_FLAG_MINIOS;
+	vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
+
+	/* Re-open stream at correct offset to pass to vb2_load_partition. */
+	if (VbExStreamOpen(params->disk_handle, sector, sectors_left,
+			   &stream)) {
+		VB2_DEBUG("Unable to open disk handle.\n");
+		return rv;
+	}
+
+	rv = vb2_load_partition(ctx, params, stream, lpflags);
+	VB2_DEBUG("vb2_load_partition returned: %d\n", rv);
+
+	VbExStreamClose(stream);
+
+	if (rv)
+		return VB2_ERROR_LK_NO_KERNEL_FOUND;
+	return rv;
+}
+
+static vb2_error_t try_minios_sectors(struct vb2_context *ctx,
+				      VbSelectAndLoadKernelParams *params,
+				      VbDiskInfo *disk_info,
+				      uint64_t start, uint64_t count)
+{
+	const uint32_t buf_size = count * disk_info->bytes_per_lba;
+	char *buf;
+	VbExStream_t stream;
+	uint64_t isector;
+	vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
+
+	buf = malloc(buf_size);
+	if (buf == NULL) {
+		VB2_DEBUG("Unable to allocate disk read buffer.\n");
+		return rv;
+	}
+
+	if (VbExStreamOpen(params->disk_handle, start, count, &stream)) {
+		VB2_DEBUG("Unable to open disk handle.\n");
+		free(buf);
+		return rv;
+	}
+	if (VbExStreamRead(stream, buf_size, buf)) {
+		VB2_DEBUG("Unable to read disk.\n");
+		free(buf);
+		VbExStreamClose(stream);
+		return rv;
+	}
+	VbExStreamClose(stream);
+
+	for (isector = 0; isector < count; isector++) {
+		if (memcmp(buf + isector * disk_info->bytes_per_lba,
+			   VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE))
+			continue;
+		VB2_DEBUG("Match on sector %" PRIu64 " / %" PRIu64 "\n",
+			  start + isector,
+			  disk_info->lba_count - 1);
+		rv = try_minios_kernel(ctx, params, disk_info, start + isector);
+		if (rv == VB2_SUCCESS)
+			break;
+	}
+
+	free(buf);
+	return rv;
+}
+
+static vb2_error_t try_minios_sector_region(struct vb2_context *ctx,
+					    VbSelectAndLoadKernelParams *params,
+					    VbDiskInfo *disk_info,
+					    int end_region)
+{
+	const uint64_t disk_count_half = (disk_info->lba_count + 1) / 2;
+	const uint64_t check_count_256 = 256 * 1024
+		* 1024 / disk_info->bytes_per_lba;  // 256 MB
+	const uint64_t batch_count_1 = 1024
+		* 1024 / disk_info->bytes_per_lba;  // 1 MB
+	const uint64_t check_count = VB2_MIN(disk_count_half, check_count_256);
+	const uint64_t batch_count = VB2_MIN(disk_count_half, batch_count_1);
+	uint64_t sector;
+	uint64_t start;
+	uint64_t end;
+	const char *region_name;
+	vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
+
+	if (!end_region) {
+		start = 0;
+		end = check_count;
+		region_name = "start";
+	} else {
+		start = disk_info->lba_count - check_count;
+		end = disk_info->lba_count;
+		region_name = "end";
+	}
+
+	VB2_DEBUG("Checking %s of disk for kernels...\n", region_name);
+	for (sector = start; sector < end; sector += batch_count) {
+		rv = try_minios_sectors(ctx, params, disk_info, sector,
+					batch_count);
+		if (rv == VB2_SUCCESS)
+			return rv;
+	}
+
+	return rv;
+}
+
+/*
+ * Search for kernels by sector, rather than by partition.  Only sectors near
+ * the start and end of disks are considered, and the kernel must start exactly
+ * at the first byte of the sector.
+ */
+vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx,
+			     VbSelectAndLoadKernelParams *params,
+			     VbDiskInfo *disk_info)
+{
+	vb2_error_t rv;
+	int end_region_first = vb2_nv_get(ctx, VB2_NV_MINIOS_PRIORITY);
+
+	rv = try_minios_sector_region(ctx, params, disk_info, end_region_first);
+	if (rv)
+		rv = try_minios_sector_region(ctx, params, disk_info,
+					      !end_region_first);
+	if (rv)
+		return rv;
+
+	rv = vb2ex_tpm_set_mode(VB2_TPM_MODE_DISABLED);
+	if (rv)
+		VB2_DEBUG("Failed to disable TPM\n");
+
+	return rv;
+}
+
 vb2_error_t LoadKernel(struct vb2_context *ctx,
 		       VbSelectAndLoadKernelParams *params,
 		       VbDiskInfo *disk_info)
@@ -465,11 +635,8 @@
 	uint32_t lowest_version = LOWEST_TPM_VERSION;
 	vb2_error_t rv;
 
-	/* Clear output params in case we fail */
+	/* Clear output params */
 	params->partition_number = 0;
-	params->bootloader_address = 0;
-	params->bootloader_size = 0;
-	params->flags = 0;
 
 	/* Read GPT data */
 	GptData gpt;
@@ -518,14 +685,14 @@
 			 * If we already have a good kernel, we only needed to
 			 * look at the vblock versions to check for rollback.
 			 */
-			lpflags |= VB2_LOAD_PARTITION_VBLOCK_ONLY;
+			lpflags |= VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY;
 		}
 
-		rv = vb2_load_partition(ctx, stream, lpflags, params);
+		rv = vb2_load_partition(ctx, params, stream, lpflags);
 		VbExStreamClose(stream);
 
 		if (rv) {
-			VB2_DEBUG("Marking kernel as invalid.\n");
+			VB2_DEBUG("Marking kernel as invalid (err=%x).\n", rv);
 			GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
 			continue;
 		}
@@ -542,7 +709,7 @@
 		 * If we're only looking at headers, we're done with this
 		 * partition.
 		 */
-		if (lpflags & VB2_LOAD_PARTITION_VBLOCK_ONLY)
+		if (lpflags & VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY)
 			continue;
 
 		/*
diff --git a/firmware/stub/tpm_lite_stub.c b/firmware/stub/tpm_lite_stub.c
index b59db33..01704f8 100644
--- a/firmware/stub/tpm_lite_stub.c
+++ b/firmware/stub/tpm_lite_stub.c
@@ -43,15 +43,8 @@
  */
 static int exit_on_failure = 1;
 
-/* Similar to VbExError, only handle the non-exit case.
- */
-static int DoError(int result, const char* format, ...)
+static inline uint32_t try_exit(uint32_t result)
 {
-	va_list ap;
-	va_start(ap, format);
-	fprintf(stderr, "ERROR: ");
-	vfprintf(stderr, format, ap);
-	va_end(ap);
 	if (exit_on_failure)
 		exit(1);
 	return result;
@@ -62,13 +55,13 @@
 __attribute__((unused)) static void DbgPrintBytes(const uint8_t* a, int n)
 {
 	int i;
-	fprintf(stderr, "DEBUG: ");
+	VB2_DEBUG_RAW("DEBUG: ");
 	for (i = 0; i < n; i++) {
 		if (i && i % 16 == 0)
-			fprintf(stderr, "\nDEBUG: ");
-		fprintf(stderr, "%02x ", a[i]);
+			VB2_DEBUG_RAW("\nDEBUG: ");
+		VB2_DEBUG_RAW("%02x ", a[i]);
 	}
-	fprintf(stderr, "\n");
+	VB2_DEBUG_RAW("\n");
 }
 
 
@@ -79,13 +72,13 @@
 {
 	uint8_t response[TPM_MAX_COMMAND_SIZE];
 	if (in_len <= 0) {
-		return DoError(TPM_E_INPUT_TOO_SMALL,
-			       "invalid command length %d for command %#x\n",
-			       in_len, in[9]);
+		VB2_DEBUG("ERROR: invalid command length %d for command %#x\n",
+			  in_len, in[9]);
+		return try_exit(TPM_E_INPUT_TOO_SMALL);
 	} else if (tpm_fd < 0) {
-		return DoError(TPM_E_NO_DEVICE,
-			       "the TPM device was not opened.  " \
-			       "Forgot to call TlclLibInit?\n");
+		VB2_DEBUG("ERROR: the TPM device was not opened.  "
+			  "Forgot to call TlclLibInit?\n");
+		return try_exit(TPM_E_NO_DEVICE);
 	} else {
 		int n;
 		int retries = 0;
@@ -105,15 +98,15 @@
 				  retries + 1, strerror(errno));
 		}
 		if (n < 0) {
-			return DoError(TPM_E_WRITE_FAILURE,
-				       "write failure to TPM device: %s "
-				       "(first error %d)\n",
-				       strerror(errno), first_errno);
+			VB2_DEBUG("ERROR: write failure to TPM device: %s "
+				  "(first error %d)\n",
+				  strerror(errno), first_errno);
+			return try_exit(TPM_E_WRITE_FAILURE);
 		} else if (n != in_len) {
-			return DoError(TPM_E_WRITE_FAILURE,
-				       "bad write size to TPM device: %d vs %u "
-				       "(%d retries, first error %d)\n",
-				       n, in_len, retries, first_errno);
+			VB2_DEBUG("ERROR: bad write size to TPM device: "
+				  "%d vs %u (%d retries, first error %d)\n",
+				  n, in_len, retries, first_errno);
+			return try_exit(TPM_E_WRITE_FAILURE);
 		}
 
 		/* Read response. Retry in case of communication errors.
@@ -131,18 +124,18 @@
 				  retries + 1, strerror(errno));
 		}
 		if (n == 0) {
-			return DoError(TPM_E_READ_EMPTY,
-				       "null read from TPM device\n");
+			VB2_DEBUG("ERROR: null read from TPM device\n");
+			return try_exit(TPM_E_READ_EMPTY);
 		} else if (n < 0) {
-			return DoError(TPM_E_READ_FAILURE,
-				       "read failure from TPM device: %s "
-				       "(first error %d)\n",
-				       strerror(errno), first_errno);
+			VB2_DEBUG("ERROR: read failure from TPM device: %s "
+				  "(first error %d)\n",
+				  strerror(errno), first_errno);
+			return try_exit(TPM_E_READ_FAILURE);
 		} else {
 			if (n > *pout_len) {
-				return DoError(TPM_E_RESPONSE_TOO_LARGE,
-					       "TPM response too long for "
-					       "output buffer\n");
+				VB2_DEBUG("ERROR: TPM response too long for "
+					  "output buffer\n");
+				return try_exit(TPM_E_RESPONSE_TOO_LARGE);
 			} else {
 				*pout_len = n;
 				memcpy(out, response, n);
@@ -221,9 +214,9 @@
 		delay.tv_nsec = OPEN_RETRY_DELAY_NS;
 		nanosleep(&delay, NULL);
 	}
-	return DoError(VB2_ERROR_UNKNOWN,
-		       "TPM: Cannot open TPM device %s: %s\n",
-		       device_path, strerror(saved_errno));
+	VB2_DEBUG("ERROR: TPM: Cannot open TPM device %s: %s\n",
+		  device_path, strerror(saved_errno));
+	return try_exit(VB2_ERROR_UNKNOWN);
 }
 
 uint32_t vb2ex_tpm_send_recv(const uint8_t* request, uint32_t request_length,
diff --git a/firmware/stub/vboot_api_stub.c b/firmware/stub/vboot_api_stub.c
index bc5f2fe..5e08556 100644
--- a/firmware/stub/vboot_api_stub.c
+++ b/firmware/stub/vboot_api_stub.c
@@ -19,18 +19,6 @@
 #include "vboot_test.h"
 
 __attribute__((weak))
-uint32_t VbExKeyboardRead(void)
-{
-	return 0;
-}
-
-__attribute__((weak))
-uint32_t VbExKeyboardReadWithFlags(uint32_t *flags_ptr)
-{
-	return 0;
-}
-
-__attribute__((weak))
 uint32_t VbExIsShutdownRequested(void)
 {
 	return 0;
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index 716b2b2..dbe6edd 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -72,6 +72,10 @@
 		printf(" !REC");
 	if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1)
 		printf(" REC");
+	if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0)
+		printf(" !MINIOS");
+	if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1)
+		printf(" MINIOS");
 	printf("\n");
 
 	struct vb2_packed_key *data_key = &keyblock->data_key;
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index 9bfa7fd..be8b634 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -20,7 +20,6 @@
 #include "2common.h"
 #include "file_type.h"
 #include "file_type_bios.h"
-#include "fmap.h"
 #include "futility.h"
 #include "futility_options.h"
 #include "host_common.h"
diff --git a/futility/cmd_vbutil_keyblock.c b/futility/cmd_vbutil_keyblock.c
index bec23c3..28a3ccd 100644
--- a/futility/cmd_vbutil_keyblock.c
+++ b/futility/cmd_vbutil_keyblock.c
@@ -222,6 +222,10 @@
 		printf(" !REC");
 	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1)
 		printf(" REC");
+	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0)
+		printf(" !MINIOS");
+	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1)
+		printf(" MINIOS");
 	printf("\n");
 
 	struct vb2_packed_key *data_key = &block->data_key;
diff --git a/futility/vb1_helper.c b/futility/vb1_helper.c
index 39bb16a..2a0e87a 100644
--- a/futility/vb1_helper.c
+++ b/futility/vb1_helper.c
@@ -548,6 +548,10 @@
 		printf(" !REC");
 	if (g_keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1)
 		printf(" REC");
+	if (g_keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0)
+		printf(" !MINIOS");
+	if (g_keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1)
+		printf(" MINIOS");
 	printf("\n");
 	printf("  Data key algorithm:  %u %s\n", data_key->algorithm,
 	       vb2_get_crypto_algorithm_name(data_key->algorithm));
diff --git a/host/arch/arm/lib/crossystem_arch.c b/host/arch/arm/lib/crossystem_arch.c
index 0223b70..116f8fc 100644
--- a/host/arch/arm/lib/crossystem_arch.c
+++ b/host/arch/arm/lib/crossystem_arch.c
@@ -35,7 +35,9 @@
 #define PLATFORM_DEV_PATH "/sys/devices/platform/chromeos_arm"
 /* These should match the Linux GPIO name (i.e., 'gpio-line-names'). */
 #define GPIO_NAME_RECOVERY_SW_L "RECOVERY_SW_L"
+#define GPIO_NAME_RECOVERY_SW "RECOVERY_SW"
 #define GPIO_NAME_WP_L "AP_FLASH_WP_L"
+#define GPIO_NAME_WP "AP_FLASH_WP"
 /* Device for NVCTX write */
 #define NVCTX_PATH "/dev/mmcblk%d"
 /* Base name for GPIO files */
@@ -481,6 +483,9 @@
 		value = gpiod_read(GPIO_NAME_RECOVERY_SW_L, true);
 		if (value != -1)
 			return value;
+		value = gpiod_read(GPIO_NAME_RECOVERY_SW, false);
+		if (value != -1)
+			return value;
 		/* Try the deprecated chromeos_arm platform device next. */
 		return VbGetPlatformGpioStatus("recovery");
 	} else if (!strcasecmp(name, "wpsw_cur")) {
@@ -489,6 +494,9 @@
 		value = gpiod_read(GPIO_NAME_WP_L, true);
 		if (value != -1)
 			return value;
+		value = gpiod_read(GPIO_NAME_WP, false);
+		if (value != -1)
+			return value;
 		/* Try the deprecated chromeos_arm platform device next. */
 		return VbGetPlatformGpioStatus("write-protect");
 	} else if (!strcasecmp(name, "recoverysw_ec_boot")) {
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 9d23091..02443b1 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -13,6 +13,7 @@
 #include "2common.h"
 #include "2nvstorage.h"
 #include "2sysincludes.h"
+#include "chromeos_config.h"
 #include "crossystem_arch.h"
 #include "crossystem.h"
 #include "crossystem_vbnv.h"
@@ -490,7 +491,19 @@
 const char *VbGetSystemPropertyString(const char *name, char *dest,
 				      size_t size)
 {
-	/* Check architecture-dependent properties first */
+	/* Check for HWID override via cros_config */
+	if (!strcasecmp(name, "hwid")) {
+		char *hwid_override;
+
+		if (chromeos_config_get_string("/", "hwid-override",
+					       &hwid_override) == VB2_SUCCESS) {
+			StrCopy(dest, hwid_override, size);
+			free(hwid_override);
+			return dest;
+		}
+	}
+
+	/* Check architecture-dependent properties */
 	if (VbGetArchPropertyString(name, dest, size))
 		return dest;
 
@@ -532,6 +545,8 @@
 			return default_boot[v];
 		else
 			return "unknown";
+	} else if (!strcasecmp(name, "minios_priority")) {
+		return vb2_get_nv_storage(VB2_NV_MINIOS_PRIORITY) ? "B" : "A";
 	}
 
 	return NULL;
@@ -671,7 +686,13 @@
 			return vb2_set_nv_storage(VB2_NV_TRY_NEXT, 1);
 		else
 			return -1;
-
+	} else if (!strcasecmp(name, "minios_priority")) {
+		if (!strcasecmp(value, "A"))
+			return vb2_set_nv_storage(VB2_NV_MINIOS_PRIORITY, 0);
+		else if (!strcasecmp(value, "B"))
+			return vb2_set_nv_storage(VB2_NV_MINIOS_PRIORITY, 1);
+		else
+			return -1;
 	} else if (!strcasecmp(name, "fw_result")) {
 		int i;
 
diff --git a/host/lib/include/host_misc.h b/host/lib/include/host_misc.h
index 0249420..298e742 100644
--- a/host/lib/include/host_misc.h
+++ b/host/lib/include/host_misc.h
@@ -9,6 +9,7 @@
 #define VBOOT_REFERENCE_HOST_MISC_H_
 
 #include "vboot_struct.h"
+#include "vboot_api.h"
 
 /* Copy up to dest_size-1 characters from src to dest, ensuring null
  * termination (which strncpy() doesn't do).  Returns the destination
diff --git a/scripts/image_signing/sign_android_image.sh b/scripts/image_signing/sign_android_image.sh
index cb45fe9..a7d0fc6 100755
--- a/scripts/image_signing/sign_android_image.sh
+++ b/scripts/image_signing/sign_android_image.sh
@@ -54,8 +54,10 @@
 
   info "Start signing framework apks"
 
-  image_content_integrity_check "${system_mnt}" "${working_dir}" \
-                                "Prepare apks signing"
+  if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \
+                                     "Prepare apks signing"; then
+    return 1
+  fi
 
   # Counters for validity check.
   local counter_platform=0
@@ -120,8 +122,10 @@
         --in "${temp_apk}" --out "${signed_apk}" \
         ${extra_flags}
     fi
-    image_content_integrity_check "${system_mnt}" "${working_dir}" \
-                                  "sign apk ${signed_apk}"
+    if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \
+                                       "sign apk ${signed_apk}"; then
+      return 1
+    fi
 
     # Copy the content instead of mv to avoid owner/mode changes.
     sudo cp "${signed_apk}" "${apk}" && rm -f "${signed_apk}"
@@ -133,8 +137,10 @@
 
     : $(( counter_${keyname} += 1 ))
     : $(( counter_total += 1 ))
-    image_content_integrity_check "${system_mnt}" "${working_dir}" \
-                                  "update re-signed apk ${apk}"
+    if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \
+                                       "update re-signed apk ${apk}"; then
+      return 1
+    fi
   done < <(find "${system_mnt}/system" -type f -name '*.apk' -print0)
 
   info "Found ${counter_platform} platform APKs."
@@ -149,6 +155,8 @@
         ${counter_total} -lt 25 ]]; then
     die "Number of re-signed package seems to be wrong"
   fi
+
+  return 0
 }
 
 # Extracts certificate from the provided public key.
@@ -250,11 +258,14 @@
   snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.new"
   local d
   if ! d=$(diff "${working_dir}"/properties.{orig,new}); then
-    die "Unexpected change of file property, diff due to ${reason}\n${d}"
+    error "Unexpected change of file property, diff due to ${reason}\n${d}"
+    return 1
   fi
+
+  return 0
 }
 
-main() {
+sign_android_internal() {
   local root_fs_dir=$1
   local key_dir=$2
 
@@ -262,7 +273,6 @@
   # Keep this aligned with
   # src/private-overlays/project-cheets-private/scripts/board_specific_setup.sh
   local system_image=""
-  local compression_flags=""
   local selinux_dir="${root_fs_dir}/etc/selinux"
   local file_contexts=""
   local vm_candidate="${root_fs_dir}/opt/google/vms/android/system.raw.img"
@@ -270,11 +280,9 @@
       "${root_fs_dir}/opt/google/containers/android/system.raw.img")
   if [[ -f "${vm_candidate}" ]]; then
     system_image="${vm_candidate}"
-    compression_flags="-comp lz4 -Xhc -b 256K"
     file_contexts="${selinux_dir}/arc/contexts/files/android_file_contexts_vm"
   elif [[ -f "${container_candidate}" ]]; then
     system_image="${container_candidate}"
-    compression_flags="-comp gzip"
     file_contexts="${selinux_dir}/arc/contexts/files/android_file_contexts"
   else
     die "System image does not exist"
@@ -297,6 +305,21 @@
     die "System image does not exist: ${system_img}"
   fi
 
+  # NOTE: Keep compression_flags aligned with
+  # src/private-overlays/project-cheets-private/scripts/board_specific_setup.sh
+  local compression_flags=""
+  local compression=$(sudo "${unsquashfs}" -s "${system_img}" \
+    | grep -e ^"Compression\s")
+  if [[ "${compression}" == "Compression gzip" ]]; then
+    compression_flags="-comp gzip"
+  elif [[ "${compression}" == "Compression lz4" ]]; then
+    compression_flags="-comp lz4 -Xhc -b 256K"
+  elif [[ "${compression}" == "Compression zstd" ]]; then
+    compression_flags="-comp zstd"
+  else
+    die "Unexpected compression type: ${compression}"
+  fi
+
   if ! type -P zipalign &>/dev/null || ! type -P signapk &>/dev/null \
     || ! type -P apksigner &>/dev/null; then
     # TODO(victorhsieh): Make this an error.  This is not treating as error
@@ -313,17 +336,26 @@
 
   snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.orig"
 
-  sign_framework_apks "${system_mnt}" "${key_dir}" "${working_dir}"
-  image_content_integrity_check "${system_mnt}" "${working_dir}" \
-                                "sign_framework_apks"
+  if ! sign_framework_apks "${system_mnt}" "${key_dir}" "${working_dir}"; then
+    return 1
+  fi
+
+  if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \
+                                     "sign_framework_apks"; then
+    return 1
+  fi
 
   update_sepolicy "${system_mnt}" "${key_dir}"
-  image_content_integrity_check "${system_mnt}" "${working_dir}" \
-                                "update_sepolicy"
+  if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \
+                                      "update_sepolicy"; then
+    return 1
+  fi
 
   replace_ota_cert "${system_mnt}" "${key_dir}/releasekey.x509.pem"
-  image_content_integrity_check "${system_mnt}" "${working_dir}" \
-                                "replace_ota_cert"
+  if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \
+                                     "replace_ota_cert"; then
+    return 1
+  fi
 
   # Packages cache needs to be regenerated when the key and timestamp are
   # changed for apks.
@@ -367,17 +399,33 @@
     info "Packages cache ${packages_cache} does not exist. Skip regeneration."
   fi
 
-  info "Repacking squashfs image"
+  info "Repacking squashfs image with compression flags '${compression_flags}'"
   local old_size=$(stat -c '%s' "${system_img}")
   # Remove old system image to prevent mksquashfs tries to merge both images.
   sudo rm -rf "${system_img}"
-  # Note, compression_flags is a combination of flags. Keep this aligned with
-  # src/private-overlays/project-cheets-private/scripts/board_specific_setup.sh
   sudo mksquashfs "${system_mnt}" "${system_img}" \
     ${compression_flags} -context-file "${file_contexts}" -mount-point "/" \
     -no-progress
   local new_size=$(stat -c '%s' "${system_img}")
   info "Android system image size change: ${old_size} -> ${new_size}"
+  return 0
+}
+
+main() {
+  # TODO(b/175081695): Remove retries once root problem is fixed.
+  local attempts
+  for (( attempts = 1; attempts <= 3; ++attempts )); do
+    if sign_android_internal "$@"; then
+      exit 0
+    fi
+    warn "Could not sign android image due to recoverable error, will retry," \
+         "attempt # ${attempts}."
+    warn "@@@ALERT@@@"
+    lsof -n
+    dmesg
+    mount
+  done
+  die "Unable to sign Android image; giving up."
 }
 
 main "$@"
diff --git a/scripts/image_signing/sign_official_build.sh b/scripts/image_signing/sign_official_build.sh
index 6167f0b..53a9264 100755
--- a/scripts/image_signing/sign_official_build.sh
+++ b/scripts/image_signing/sign_official_build.sh
@@ -9,15 +9,13 @@
 # Prerequisite tools needed in the system path:
 #
 #  futility (from src/platform/vboot_reference)
-#  vbutil_kernel (from src/platform/vboot_reference)
-#  vbutil_key (from src/platform/vboot_reference)
-#  cgpt (from src/platform/vboot_reference)
-#  dump_kernel_config (from src/platform/vboot_reference)
-#  verity (from src/platform/verity)
+#  verity (from src/platform2/verity)
 #  load_kernel_test (from src/platform/vboot_reference)
 #  dumpe2fs
+#  e2fsck
 #  sha1sum
-#  cbfstool (from src/third_party/coreboot)
+
+MINIOS_KERNEL_GUID="09845860-705f-4bb5-b16c-8a8a099caf52"
 
 # Load common constants and variables.
 . "$(dirname "$0")/common.sh"
@@ -27,15 +25,11 @@
   cat <<EOF
 Usage: $PROG <type> input_image /path/to/keys/dir [output_image] [version_file]
 where <type> is one of:
-             ssd  (sign an SSD image)
-             base (sign a base image, similar to an SSD image)
+             base (sign a base image)
              recovery (sign a USB recovery image)
              factory (sign a factory install image)
              update_payload (sign a delta update hash)
-             kernel (sign a kernel image)
-             recovery_kernel (sign a recovery_kernel image)
              firmware (sign a firmware image)
-             usb  (sign an image to boot directly from USB)
              verify (verify an image including rootfs hashes)
              accessory_usbpd (sign USB-PD accessory firmware)
              accessory_rwsig (sign accessory RW firmware)
@@ -84,8 +78,7 @@
 PATH=$PATH:/usr/sbin:/sbin
 
 # Make sure the tools we need are available.
-for prereqs in ${FUTILITY} vbutil_kernel cgpt dump_kernel_config verity \
-               cbfstool load_kernel_test dumpe2fs sha1sum e2fsck; do
+for prereqs in ${FUTILITY} verity load_kernel_test dumpe2fs e2fsck sha1sum; do
   type -P "${prereqs}" &>/dev/null || \
     die "${prereqs} tool not found."
 done
@@ -214,7 +207,7 @@
   info "Updating rootfs hash and updating config for Kernel partitions"
 
   # If we can't find dm parameters in the kernel config, bail out now.
-  local kernel_config=$(sudo dump_kernel_config "${loop_kern}")
+  local kernel_config=$(sudo ${FUTILITY} dump_kernel_config "${loop_kern}")
   local dm_config=$(get_dmparams_from_config "${kernel_config}")
   if [ -z "${dm_config}" ]; then
     error "Couldn't grab dm_config from kernel ${loop_kern}"
@@ -265,7 +258,7 @@
   for kernelpart in 2 4; do
     loop_kern="${loopdev}p${kernelpart}"
     if ! new_kernel_config="$(
-         sudo dump_kernel_config "${loop_kern}" 2>/dev/null)" &&
+         sudo ${FUTILITY} dump_kernel_config "${loop_kern}" 2>/dev/null)" &&
        [[ "${kernelpart}" == 4 ]]; then
       # Legacy images don't have partition 4.
       info "Skipping empty kernel partition 4 (legacy images)."
@@ -283,7 +276,7 @@
       keyblock="${kern_b_keyblock}"
       priv_key="${kern_b_privkey}"
     fi
-    sudo vbutil_kernel --repack "${loop_kern}" \
+    sudo ${FUTILITY} vbutil_kernel --repack "${loop_kern}" \
       --keyblock ${keyblock} \
       --signprivate ${priv_key} \
       --version "${KERNEL_VERSION}" \
@@ -302,13 +295,13 @@
   local temp_out_vb="$(make_temp_file)"
 
   local loop_kern="${loopdev}p4"
-  if [[ -z "$(sudo dump_kernel_config "${loop_kern}" 2>/dev/null)" ]]; then
+  if [[ -z "$(sudo ${FUTILITY} dump_kernel_config "${loop_kern}" 2>/dev/null)" ]]; then
     info "Building vmlinuz_hd.vblock from legacy image partition 2."
     loop_kern="${loopdev}p2"
   fi
 
   # vblock should always use kernel keyblock.
-  sudo vbutil_kernel --repack "${temp_out_vb}" \
+  sudo ${FUTILITY} vbutil_kernel --repack "${temp_out_vb}" \
     --keyblock "${KEY_DIR}/kernel.keyblock" \
     --signprivate "${KEY_DIR}/kernel_data_key.vbprivk" \
     --oldblob "${loop_kern}" \
@@ -402,52 +395,6 @@
   info "Signed firmware image output to ${image}"
 }
 
-# Sign a kernel in-place with the given keys.
-# Args: KERNEL_IMAGE KEY_DIR KERNEL_VERSION
-sign_kernel() {
-  local image=$1
-  local key_dir=$2
-  local kernel_version=$3
-
-  # Note: Although vbutil_kernel may correctly handle specifying the same
-  # output file as the input file, we do not want to rely on it correctly
-  # handing that. Hence, the use of a temporary file.
-  local temp_kernel=$(make_temp_file)
-
-  # Resign the kernel with new keys.
-  vbutil_kernel --repack "${temp_kernel}" \
-    --keyblock "${key_dir}/kernel.keyblock" \
-    --signprivate "${key_dir}/kernel_data_key.vbprivk" \
-    --version "${kernel_version}" \
-    --oldblob "${image}"
-
-  mv "${temp_kernel}" "${image}"
-  info "Signed kernel image output to ${image}"
-}
-
-# Sign a recovery kernel in-place with the given keys.
-# Args: KERNEL_IMAGE KEY_DIR KERNEL_VERSION
-sign_recovery_kernel() {
-  local image=$1
-  local key_dir=$2
-  local kernel_version=$3
-
-  # Note: Although vbutil_kernel may correctly handle specifying the same
-  # output file as the input file, we do not want to rely on it correctly
-  # handing that. Hence, the use of a temporary file.
-  local temp_kernel=$(make_temp_file)
-
-  # Resign the kernel with new recovery keys.
-  vbutil_kernel --repack "${temp_kernel}" \
-    --keyblock "${key_dir}/recovery_kernel.keyblock" \
-    --signprivate "${key_dir}/recovery_kernel_data_key.vbprivk" \
-    --version "${kernel_version}" \
-    --oldblob "${image}"
-
-  mv "${temp_kernel}" "${image}"
-  info "Signed recovery_kernel image output to ${image}"
-}
-
 # Sign a delta update payload (usually created by paygen).
 # Args: INPUT_IMAGE KEY_DIR OUTPUT_IMAGE
 sign_update_payload() {
@@ -464,7 +411,7 @@
     [8192]=10
   )
 
-  key_output=$(futility show "${key_file}")
+  key_output=$(${FUTILITY} show "${key_file}")
   key_size=$(echo "${key_output}" | sed -n '/Key length/s/[^0-9]*//p')
   algo=${algos[${key_size}]}
   if [[ -z ${algo} ]]; then
@@ -681,20 +628,23 @@
   echo "Signed with keyset in $(readlink -f "${KEY_DIR}") ." >>"${signer_notes}"
   # record recovery_key
   key="${KEY_DIR}/recovery_key.vbpubk"
-  sha1=$(vbutil_key --unpack "${key}" | grep sha1sum | cut -d" " -f9)
+  sha1=$(${FUTILITY} vbutil_key --unpack "${key}" \
+    | grep sha1sum | cut -d" " -f9)
   echo "recovery: ${sha1}" >>"${signer_notes}"
   # record root_key(s)
   if [[ -d "${shellball_keyset_dir}"  ]]; then
     echo "List sha1sum of all loem/model's signatures:" >>"${signer_notes}"
     for key in "${shellball_keyset_dir}"/rootkey.*; do
       model="${key##*.}"
-      sha1=$(vbutil_key --unpack "${key}" | grep sha1sum | cut -d" " -f9)
+      sha1=$(${FUTILITY} vbutil_key --unpack "${key}" \
+        | grep sha1sum | cut -d" " -f9)
       echo "  ${model}: ${sha1}" >>"${signer_notes}"
     done
   else
     echo "List sha1sum of single key's signature:" >>"${signer_notes}"
     key="${KEY_DIR}/root_key.vbpubk"
-    sha1=$(vbutil_key --unpack "${key}" | grep sha1sum | cut -d" " -f9)
+    sha1=$(${FUTILITY} vbutil_key --unpack "${key}" \
+      | grep sha1sum | cut -d" " -f9)
     echo "  root: ${sha1}" >>"${signer_notes}"
   fi
 
@@ -771,7 +721,11 @@
   elif [[ -z "${esp_dir}" ]]; then
     return 0
   fi
-  "${SCRIPT_DIR}/install_gsetup_certs.sh" "${esp_dir}" "${KEY_DIR}/uefi"
+  # TODO(b/199136347): First class this as an arg and pass from config
+  # in the signing repo. This is a temporary fix to unblock reven-release.
+  if [[ "${KEY_DIR}" != *"Reven"* ]]; then
+    "${SCRIPT_DIR}/install_gsetup_certs.sh" "${esp_dir}" "${KEY_DIR}/uefi"
+  fi
   "${SCRIPT_DIR}/sign_uefi.sh" "${esp_dir}" "${KEY_DIR}/uefi"
   sudo umount "${esp_dir}"
 
@@ -843,7 +797,7 @@
   local partnum
   for partnum in 2 4; do
     info "Considering Kernel partition ${partnum}"
-    kernel_config=$(sudo dump_kernel_config "${loopdev}p${partnum}")
+    kernel_config=$(sudo ${FUTILITY} dump_kernel_config "${loopdev}p${partnum}")
     local hash_image=$(make_temp_file)
     if ! calculate_rootfs_hash "${loop_rootfs}" "${kernel_config}" \
       "${hash_image}"; then
@@ -911,7 +865,8 @@
   local loop_kernb="${loopdev}p4"
 
   # Update the Kernel B hash in Kernel A command line
-  local old_kerna_config="$(sudo dump_kernel_config "${loop_kerna}")"
+  local old_kerna_config="$(sudo ${FUTILITY} \
+    dump_kernel_config "${loop_kerna}")"
   local old_kernb_hash="$(echo "$old_kerna_config" |
     sed -nEe "s#.*kern_b_hash=([a-z0-9]*).*#\1#p")"
   if [[ "${#old_kernb_hash}" -lt 64 ]]; then
@@ -928,7 +883,7 @@
   cat ${new_kerna_config}
 
   # Re-calculate kernel partition signature and command line.
-  sudo vbutil_kernel --repack "${loop_kerna}" \
+  sudo ${FUTILITY} vbutil_kernel --repack "${loop_kerna}" \
     --keyblock ${KEY_DIR}/recovery_kernel.keyblock \
     --signprivate ${KEY_DIR}/recovery_kernel_data_key.vbprivk \
     --version "${KERNEL_VERSION}" \
@@ -936,6 +891,58 @@
     --config ${new_kerna_config}
 }
 
+# Re-sign miniOS kernels with new keys.
+# Args: LOOPDEV KEYBLOCK PRIVKEY
+resign_minios_kernels() {
+  local loopdev="$1"
+  local keyblock="$2"
+  local priv_key="$3"
+
+  info "Searching for miniOS kernels to resign..."
+
+  local loop_minios
+  for loop_minios in "${loopdev}p"*; do
+    local part_type_guid
+    part_type_guid=$(sudo lsblk -rnb -o PARTTYPE "${loop_minios}")
+    if [[ "${part_type_guid}" != "${MINIOS_KERNEL_GUID}" ]]; then
+      continue
+    fi
+
+    # Skip miniOS partitions which are empty. This happens when miniOS
+    # kernels aren't written to the partitions because the feature is not
+    # enabled.
+    if ! sudo "${FUTILITY}" dump_kernel_config "${loop_minios}"; then
+      info "Skipping empty miniOS partition ${loop_minios}."
+      continue
+    fi
+
+    # Delay checking that keyblock and private key exist until we are certain
+    # of a valid miniOS partition.  Images that don't support miniOS might not
+    # provide these.  (This check is repeated twice, but that's okay.)
+    if [[ ! -e "${keyblock}" ]]; then
+      error "Resign miniOS: keyblock doesn't exist: ${keyblock}"
+      return 1
+    fi
+    if [[ ! -e "${priv_key}" ]]; then
+      error "Resign miniOS: private key doesn't exist: ${priv_key}"
+      return 1
+    fi
+
+    # Assume this is a miniOS kernel.
+    local minios_kernel_version=$((KERNEL_VERSION >> 24))
+    if sudo ${FUTILITY} vbutil_kernel --repack "${loop_minios}" \
+        --keyblock "${keyblock}" \
+        --signprivate "${priv_key}" \
+        --version "${minios_kernel_version}" \
+        --oldblob "${loop_minios}"; then
+      info "Resign miniOS ${loop_minios}: done"
+    else
+      error "Resign miniOS ${loop_minios}: failed"
+      return 1
+    fi
+  done
+}
+
 # Update the legacy bootloader templates in EFI partition if available.
 # Args: LOOPDEV KERNEL
 update_legacy_bootloader() {
@@ -952,7 +959,7 @@
   fi
 
   # If we can't find the dm parameter in the kernel config, bail out now.
-  local kernel_config=$(sudo dump_kernel_config "${loop_kern}")
+  local kernel_config=$(sudo ${FUTILITY} dump_kernel_config "${loop_kern}")
   local root_hexdigest="$(get_hash_from_config "${kernel_config}")"
   if [[ -z "${root_hexdigest}" ]]; then
     error "Couldn't grab root_digest from kernel partition ${loop_kern}"
@@ -983,7 +990,7 @@
 
 # Sign an image file with proper keys.
 # Args: IMAGE_TYPE INPUT OUTPUT DM_PARTNO KERN_A_KEYBLOCK KERN_A_PRIVKEY \
-#       KERN_B_KEYBLOCK KERN_B_PRIVKEY
+#       KERN_B_KEYBLOCK KERN_B_PRIVKEY MINIOS_KEYBLOCK MINIOS_PRIVKEY
 #
 # A ChromiumOS image file (INPUT) always contains 2 partitions (kernel A & B).
 # This function will rebuild hash data by DM_PARTNO, resign kernel partitions by
@@ -1000,6 +1007,8 @@
   local kernA_privkey="$6"
   local kernB_keyblock="$7"
   local kernB_privkey="$8"
+  local minios_keyblock="$9"
+  local minios_privkey="${10}"
 
   info "Preparing ${image_type} image..."
   cp --sparse=always "${input}" "${output}"
@@ -1020,7 +1029,7 @@
   # /boot in rootfs to update kernel.  We infer the BIOS type from the kernel
   # config.
   local loop_kerna="${loopdev}p2"
-  local kerna_config="$(sudo dump_kernel_config "${loop_kerna}")"
+  local kerna_config="$(sudo ${FUTILITY} dump_kernel_config "${loop_kerna}")"
   if [[ "${image_type}" != "factory_install" &&
         " ${kerna_config} " != *" cros_legacy "* &&
         " ${kerna_config} " != *" cros_efi "* ]]; then
@@ -1033,6 +1042,10 @@
   if [[ "${image_type}" == "recovery" ]]; then
     update_recovery_kernel_hash "${loopdev}"
   fi
+  if ! resign_minios_kernels "${loopdev}" "${minios_keyblock}" \
+      "${minios_privkey}"; then
+    return 1
+  fi
   if ! update_legacy_bootloader "${loopdev}" "${loop_kern}"; then
     # Error is already logged.
     return 1
@@ -1047,7 +1060,7 @@
   loopdev=$(loopback_partscan "${INPUT_IMAGE}")
   for partnum in 2 4; do
     info "kernel config in partition number ${partnum}:"
-    sudo dump_kernel_config "${loopdev}p${partnum}"
+    sudo ${FUTILITY} dump_kernel_config "${loopdev}p${partnum}"
     echo
   done
   exit 0
@@ -1077,46 +1090,36 @@
 info "Using kernel version: ${KERNEL_VERSION}"
 
 # Make all modifications on output copy.
-if [[ "${TYPE}" == "ssd" || "${TYPE}" == "base" ]]; then
-  sign_image_file "SSD" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \
-    "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk" \
-    "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk"
-elif [[ "${TYPE}" == "usb" ]]; then
-  sign_image_file "USB" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \
-    "${KEY_DIR}/recovery_kernel.keyblock" \
-    "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \
+if [[ "${TYPE}" == "base" ]]; then
+  sign_image_file "base" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \
     "${KEY_DIR}/kernel.keyblock" \
-    "${KEY_DIR}/kernel_data_key.vbprivk"
+    "${KEY_DIR}/kernel_data_key.vbprivk" \
+    "${KEY_DIR}/kernel.keyblock" \
+    "${KEY_DIR}/kernel_data_key.vbprivk" \
+    "${KEY_DIR}/minios_kernel.keyblock" \
+    "${KEY_DIR}/minios_kernel_data_key.vbprivk"
 elif [[ "${TYPE}" == "recovery" ]]; then
   sign_image_file "recovery" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 4 \
     "${KEY_DIR}/recovery_kernel.keyblock" \
     "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \
     "${KEY_DIR}/kernel.keyblock" \
-    "${KEY_DIR}/kernel_data_key.vbprivk"
+    "${KEY_DIR}/kernel_data_key.vbprivk" \
+    "${KEY_DIR}/minios_kernel.keyblock" \
+    "${KEY_DIR}/minios_kernel_data_key.vbprivk"
 elif [[ "${TYPE}" == "factory" ]]; then
   sign_image_file "factory_install" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \
     "${KEY_DIR}/installer_kernel.keyblock" \
     "${KEY_DIR}/installer_kernel_data_key.vbprivk" \
     "${KEY_DIR}/kernel.keyblock" \
-    "${KEY_DIR}/kernel_data_key.vbprivk"
+    "${KEY_DIR}/kernel_data_key.vbprivk" \
+    "${KEY_DIR}/minios_kernel.keyblock" \
+    "${KEY_DIR}/minios_kernel_data_key.vbprivk"
 elif [[ "${TYPE}" == "firmware" ]]; then
   if [[ -e "${KEY_DIR}/loem.ini" ]]; then
     die "LOEM signing not implemented yet for firmware images"
   fi
   cp ${INPUT_IMAGE} ${OUTPUT_IMAGE}
   sign_firmware ${OUTPUT_IMAGE} ${KEY_DIR} ${FIRMWARE_VERSION}
-elif [[ "${TYPE}" == "kernel" ]]; then
-  if [[ -e "${KEY_DIR}/loem.ini" ]]; then
-    die "LOEM signing not implemented yet for kernel images"
-  fi
-  cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
-  sign_kernel "${OUTPUT_IMAGE}" "${KEY_DIR}" "${KERNEL_VERSION}"
-elif [[ "${TYPE}" == "recovery_kernel" ]]; then
-  if [[ -e "${KEY_DIR}/loem.ini" ]]; then
-    die "LOEM signing not implemented yet for recovery_kernel images"
-  fi
-  cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
-  sign_recovery_kernel "${OUTPUT_IMAGE}" "${KEY_DIR}" "${KERNEL_VERSION}"
 elif [[ "${TYPE}" == "update_payload" ]]; then
   sign_update_payload ${INPUT_IMAGE} ${KEY_DIR} ${OUTPUT_IMAGE}
 elif [[ "${TYPE}" == "accessory_usbpd" ]]; then
@@ -1125,7 +1128,7 @@
     KEY_NAME="${KEY_DIR}/key"
   fi
   cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
-  futility sign --type usbpd1 --pem "${KEY_NAME}.pem" "${OUTPUT_IMAGE}"
+  ${FUTILITY} sign --type usbpd1 --pem "${KEY_NAME}.pem" "${OUTPUT_IMAGE}"
 elif [[ "${TYPE}" == "accessory_rwsig" ]]; then
   # If one key is present in this container, assume it's the right one.
   # See crbug.com/863464
@@ -1138,7 +1141,7 @@
     fi
   fi
   cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
-  futility sign --type rwsig --prikey "${KEY_NAME}" \
+  ${FUTILITY} sign --type rwsig --prikey "${KEY_NAME}" \
            --version "${FIRMWARE_VERSION}" "${OUTPUT_IMAGE}"
 elif [[ "${TYPE}" == "gsc_firmware" ]]; then
   sign_gsc_firmware "${INPUT_IMAGE}" "${KEY_DIR}" "${OUTPUT_IMAGE}"
diff --git a/scripts/image_signing/strip_boot_from_image.sh b/scripts/image_signing/strip_boot_from_image.sh
index 2971b08..0f36390 100755
--- a/scripts/image_signing/strip_boot_from_image.sh
+++ b/scripts/image_signing/strip_boot_from_image.sh
@@ -27,7 +27,7 @@
   local rootfs="$1"
 
   info "Zeroing freespace in ${rootfs}"
-  sudo fstrim -v "${rootfs}"
+  sudo sfill -llz "${rootfs}"
 }
 
 
diff --git a/scripts/keygeneration/common.sh b/scripts/keygeneration/common.sh
index 21d5334..da06f3c 100644
--- a/scripts/keygeneration/common.sh
+++ b/scripts/keygeneration/common.sh
@@ -58,18 +58,32 @@
 DEV_FIRMWARE_DATAKEY_ALGOID=${RSA4096_SHA256_ALGOID}
 
 RECOVERY_KERNEL_ALGOID=${RSA4096_SHA512_ALGOID}
+MINIOS_KERNEL_ALGOID=${RSA4096_SHA512_ALGOID}
 INSTALLER_KERNEL_ALGOID=${RSA4096_SHA512_ALGOID}
 KERNEL_SUBKEY_ALGOID=${RSA4096_SHA256_ALGOID}
 KERNEL_DATAKEY_ALGOID=${RSA2048_SHA256_ALGOID}
 
 # Keyblock modes determine which boot modes a signing key is valid for use
 # in verification.
-EC_KEYBLOCK_MODE=7  # Only allow RW EC firmware in non-recovery.
-FIRMWARE_KEYBLOCK_MODE=7  # Only allow RW firmware in non-recovery.
-DEV_FIRMWARE_KEYBLOCK_MODE=6  # Only allow in dev mode.
-RECOVERY_KERNEL_KEYBLOCK_MODE=11 # Only in recovery mode.
-KERNEL_KEYBLOCK_MODE=7  # Only allow in non-recovery.
-INSTALLER_KERNEL_KEYBLOCK_MODE=10  # Only allow in Dev + Recovery.
+#    !DEV 0x1      DEV 0x2
+#    !REC 0x4      REC 0x8
+# !MINIOS 0x10  MINIOS 0x20
+# Note that firmware keyblock modes are not used.  Consider deprecating.
+
+# Only allow RW EC firmware in non-recovery + non-miniOS.
+EC_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x4 | 0x10))
+# Only allow RW firmware in non-recovery + non-miniOS.
+FIRMWARE_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x4 | 0x10))
+# Only allow in dev mode + non-recovery + non-miniOS.
+DEV_FIRMWARE_KEYBLOCK_MODE=$((0x2 | 0x4 | 0x10))
+# Only allow in recovery mode + non-miniOS.
+RECOVERY_KERNEL_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x8 | 0x10))
+# Only allow in recovery mode + miniOS.
+MINIOS_KERNEL_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x8 | 0x20))
+# Only allow in non-recovery + non-miniOS.
+KERNEL_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x4 | 0x10))
+# Only allow in dev + recovery + non-miniOS.
+INSTALLER_KERNEL_KEYBLOCK_MODE=$((0x2 | 0x8 | 0x10))
 
 # Emit .vbpubk and .vbprivk using given basename and algorithm
 # NOTE: This function also appears in ../../utility/dev_make_keypair. Making
@@ -125,6 +139,8 @@
 #   0x02  Developer switch on
 #   0x04  Not recovery mode
 #   0x08  Recovery mode
+#   0x10  Not miniOS mode
+#   0x20  miniOS mode
 make_keyblock() {
   local base=$1
   local flags=$2
diff --git a/scripts/keygeneration/create_new_keys.sh b/scripts/keygeneration/create_new_keys.sh
index 40cccbc..11aedc1 100755
--- a/scripts/keygeneration/create_new_keys.sh
+++ b/scripts/keygeneration/create_new_keys.sh
@@ -43,6 +43,7 @@
   local root_key_algoid=${ROOT_KEY_ALGOID}
   local recovery_key_algoid=${RECOVERY_KEY_ALGOID}
   local recovery_kernel_algoid=${RECOVERY_KERNEL_ALGOID}
+  local minios_kernel_algoid=${MINIOS_KERNEL_ALGOID}
   local installer_kernel_algoid=${INSTALLER_KERNEL_ALGOID}
   local keyname
   local output_dir="${PWD}" setperms="false"
@@ -166,6 +167,7 @@
   # Create the recovery and factory installer keypairs
   make_pair recovery_key             ${recovery_key_algoid}
   make_pair recovery_kernel_data_key ${recovery_kernel_algoid}
+  make_pair minios_kernel_data_key   ${minios_kernel_algoid}
   make_pair installer_kernel_data_key ${installer_kernel_algoid}
 
   # Create the firmware keyblock for use only in Normal mode. This is redundant,
@@ -182,6 +184,9 @@
   # Create the recovery kernel keyblock for use only in Recovery mode.
   make_keyblock recovery_kernel ${RECOVERY_KERNEL_KEYBLOCK_MODE} recovery_kernel_data_key recovery_key
 
+  # Create the miniOS kernel keyblock for use only in miniOS mode.
+  make_keyblock minios_kernel ${MINIOS_KERNEL_KEYBLOCK_MODE} minios_kernel_data_key recovery_key
+
   # Create the normal kernel keyblock for use only in Normal mode.
   make_keyblock kernel ${KERNEL_KEYBLOCK_MODE} kernel_data_key kernel_subkey
 
diff --git a/tests/devkeys/ec.keyblock b/tests/devkeys/ec.keyblock
index 6b088f3..d934291 100644
--- a/tests/devkeys/ec.keyblock
+++ b/tests/devkeys/ec.keyblock
Binary files differ
diff --git a/tests/devkeys/firmware.keyblock b/tests/devkeys/firmware.keyblock
index 1e2273e..e3653f8 100644
--- a/tests/devkeys/firmware.keyblock
+++ b/tests/devkeys/firmware.keyblock
Binary files differ
diff --git a/tests/devkeys/installer_kernel.keyblock b/tests/devkeys/installer_kernel.keyblock
index cfa3bd1..282e1d6 100644
--- a/tests/devkeys/installer_kernel.keyblock
+++ b/tests/devkeys/installer_kernel.keyblock
Binary files differ
diff --git a/tests/devkeys/kernel.keyblock b/tests/devkeys/kernel.keyblock
index 9740be4..6bb7213 100644
--- a/tests/devkeys/kernel.keyblock
+++ b/tests/devkeys/kernel.keyblock
Binary files differ
diff --git a/tests/devkeys/minios_kernel.keyblock b/tests/devkeys/minios_kernel.keyblock
new file mode 100644
index 0000000..3675690
--- /dev/null
+++ b/tests/devkeys/minios_kernel.keyblock
Binary files differ
diff --git a/tests/devkeys/minios_kernel_data_key.vbprivk b/tests/devkeys/minios_kernel_data_key.vbprivk
new file mode 100644
index 0000000..da3a15b
--- /dev/null
+++ b/tests/devkeys/minios_kernel_data_key.vbprivk
Binary files differ
diff --git a/tests/devkeys/minios_kernel_data_key.vbpubk b/tests/devkeys/minios_kernel_data_key.vbpubk
new file mode 100644
index 0000000..34ff93b
--- /dev/null
+++ b/tests/devkeys/minios_kernel_data_key.vbpubk
Binary files differ
diff --git a/tests/devkeys/recovery_kernel.keyblock b/tests/devkeys/recovery_kernel.keyblock
index ad16e39..c1c8eff 100644
--- a/tests/devkeys/recovery_kernel.keyblock
+++ b/tests/devkeys/recovery_kernel.keyblock
Binary files differ
diff --git a/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock b/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock
index 6505d91..2266424 100644
--- a/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock
+++ b/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock
@@ -1,7 +1,7 @@
 Keyblock:                tests/devkeys/kernel.keyblock
   Signature:             ignored
   Size:                  0x4b8
-  Flags:                 7  !DEV DEV !REC
+  Flags:                 23  !DEV DEV !REC !MINIOS
   Data key algorithm:    4 RSA2048 SHA256
   Data key version:      1
   Data key sha1sum:      d6170aa480136f1f29cf339a5ab1b960585fa444
diff --git a/tests/futility/expect_output/vbutil_firmware.verify b/tests/futility/expect_output/vbutil_firmware.verify
index edc9c65..e23c169 100644
--- a/tests/futility/expect_output/vbutil_firmware.verify
+++ b/tests/futility/expect_output/vbutil_firmware.verify
@@ -1,6 +1,6 @@
 Keyblock:
   Size:                2232
-  Flags:               7 (ignored)
+  Flags:               23 (ignored)
   Data key algorithm:  7 RSA4096 SHA256
   Data key version:    1
   Data key sha1sum:    e2c1c92d7d7aa7dfed5e8375edd30b7ae52b7450
diff --git a/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock b/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock
index d55fce3..afb0faf 100644
--- a/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock
+++ b/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock
@@ -1,6 +1,6 @@
 Keyblock file:        tests/devkeys/kernel.keyblock
 Signature             valid
-Flags:                7  !DEV DEV !REC
+Flags:                23  !DEV DEV !REC !MINIOS
 Data key algorithm:   4 RSA2048 SHA256
 Data key version:     1
 Data key sha1sum:     d6170aa480136f1f29cf339a5ab1b960585fa444
diff --git a/tests/futility/test_sign_keyblocks.sh b/tests/futility/test_sign_keyblocks.sh
index 7ba43af..f689c89 100755
--- a/tests/futility/test_sign_keyblocks.sh
+++ b/tests/futility/test_sign_keyblocks.sh
@@ -18,7 +18,7 @@
 # Create a copy of an existing keyblock, using the old way
 ${FUTILITY} vbutil_keyblock --pack ${TMP}.keyblock0 \
   --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \
-  --flags 7 \
+  --flags 23 \
   --signprivate ${DEVKEYS}/root_key.vbprivk
 
 # Check it.
@@ -32,7 +32,7 @@
 # Now create it the new way
 ${FUTILITY} --debug sign \
   --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \
-  --flags 7 \
+  --flags 23 \
   --signprivate ${DEVKEYS}/root_key.vbprivk \
   --outfile ${TMP}.keyblock1
 
diff --git a/tests/gpt_misc_tests.c b/tests/gpt_misc_tests.c
new file mode 100644
index 0000000..e0a8d56
--- /dev/null
+++ b/tests/gpt_misc_tests.c
@@ -0,0 +1,378 @@
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Tests for vboot_kernel.c
+ */
+
+#include "2api.h"
+#include "cgptlib.h"
+#include "cgptlib_internal.h"
+#include "gpt.h"
+#include "test_common.h"
+
+#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args)
+#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, "  calls")
+
+/* Assumes 512-byte disk sectors */
+#define MOCK_SECTOR_SIZE  512
+#define MOCK_SECTOR_COUNT 1024
+
+/* Mock kernel partition */
+struct mock_part {
+	uint32_t start;
+	uint32_t size;
+};
+
+/* Mock data */
+static char call_log[4096];
+static int disk_read_to_fail;
+static int disk_write_to_fail;
+
+static VbExDiskHandle_t handle;
+static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
+static GptHeader *mock_gpt_primary =
+	(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
+static GptHeader *mock_gpt_secondary =
+	(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)];
+
+/**
+ * Prepare a valid GPT header that will pass CheckHeader() tests
+ */
+static void SetupGptHeader(GptHeader *h, int is_secondary)
+{
+	memset(h, '\0', MOCK_SECTOR_SIZE);
+
+	/* "EFI PART" */
+	memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
+	h->revision = GPT_HEADER_REVISION;
+	h->size = MIN_SIZE_OF_HEADER;
+
+	/* 16KB: 128 entries of 128 bytes */
+	h->size_of_entry = sizeof(GptEntry);
+	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
+
+	/* Set LBA pointers for primary or secondary header */
+	if (is_secondary) {
+		h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS;
+		h->entries_lba = h->my_lba - CalculateEntriesSectors(h,
+							MOCK_SECTOR_SIZE);
+	} else {
+		h->my_lba = GPT_PMBR_SECTORS;
+		h->entries_lba = h->my_lba + 1;
+	}
+
+	h->first_usable_lba = 2 + CalculateEntriesSectors(h, MOCK_SECTOR_SIZE);
+	h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h,
+								MOCK_SECTOR_SIZE);
+
+	h->header_crc32 = HeaderCrc(h);
+}
+
+static void ResetCallLog(void)
+{
+	*call_log = 0;
+}
+
+/**
+ * Reset mock data (for use before each test)
+ */
+static void ResetMocks(void)
+{
+	ResetCallLog();
+
+	memset(&mock_disk, 0, sizeof(mock_disk));
+	SetupGptHeader(mock_gpt_primary, 0);
+	SetupGptHeader(mock_gpt_secondary, 1);
+
+	disk_read_to_fail = -1;
+	disk_write_to_fail = -1;
+}
+
+/* Mocks */
+
+vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
+			 uint64_t lba_count, void *buffer)
+{
+	LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count);
+
+	if ((int)lba_start == disk_read_to_fail)
+		return VB2_ERROR_MOCK;
+
+	memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE],
+	       lba_count * MOCK_SECTOR_SIZE);
+
+	return VB2_SUCCESS;
+}
+
+vb2_error_t VbExDiskWrite(VbExDiskHandle_t h, uint64_t lba_start,
+			  uint64_t lba_count, const void *buffer)
+{
+	LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count);
+
+	if ((int)lba_start == disk_write_to_fail)
+		return VB2_ERROR_MOCK;
+
+	memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer,
+	       lba_count * MOCK_SECTOR_SIZE);
+
+	return VB2_SUCCESS;
+}
+
+/**
+ * Test reading/writing GPT
+ */
+static void ReadWriteGptTest(void)
+{
+	GptData g;
+	GptHeader *h;
+
+	g.sector_bytes = MOCK_SECTOR_SIZE;
+	g.streaming_drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT;
+	g.valid_headers = g.valid_entries = MASK_BOTH;
+
+	ResetMocks();
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead");
+	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+		   "VbExDiskRead(h, 2, 32)\n"
+		   "VbExDiskRead(h, 1023, 1)\n"
+		   "VbExDiskRead(h, 991, 32)\n");
+	ResetCallLog();
+	/*
+	 * Valgrind complains about access to uninitialized memory here, so
+	 * zero the primary header before each test.
+	 */
+	memset(g.primary_header, '\0', g.sector_bytes);
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
+	TEST_CALLS("");
+
+	/*
+	 * Invalidate primary GPT header,
+	 * check that AllocAndReadGptData still succeeds
+	 */
+	ResetMocks();
+	memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+		"AllocAndRead primary invalid");
+	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		1, "Primary header is invalid");
+	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		0, "Secondary header is valid");
+	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+		   "VbExDiskRead(h, 1023, 1)\n"
+		   "VbExDiskRead(h, 991, 32)\n");
+	WriteAndFreeGptData(handle, &g);
+
+	/*
+	 * Invalidate secondary GPT header,
+	 * check that AllocAndReadGptData still succeeds
+	 */
+	ResetMocks();
+	memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+		"AllocAndRead secondary invalid");
+	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		0, "Primary header is valid");
+	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		1, "Secondary header is invalid");
+	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+		   "VbExDiskRead(h, 2, 32)\n"
+		   "VbExDiskRead(h, 1023, 1)\n");
+	WriteAndFreeGptData(handle, &g);
+
+	/*
+	 * Invalidate primary AND secondary GPT header,
+	 * check that AllocAndReadGptData fails.
+	 */
+	ResetMocks();
+	memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
+	memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
+	TEST_EQ(AllocAndReadGptData(handle, &g), 1,
+		"AllocAndRead primary and secondary invalid");
+	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		1, "Primary header is invalid");
+	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		1, "Secondary header is invalid");
+	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+		   "VbExDiskRead(h, 1023, 1)\n");
+	WriteAndFreeGptData(handle, &g);
+
+	/*
+	 * Invalidate primary GPT header and check that it is
+	 * repaired by GptRepair().
+	 *
+	 * This would normally be called by LoadKernel()->GptInit()
+	 * but this callback is mocked in these tests.
+	 */
+	ResetMocks();
+	memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+		"Fix Primary GPT: AllocAndRead");
+	/* Call GptRepair() with input indicating secondary GPT is valid */
+	g.valid_headers = g.valid_entries = MASK_SECONDARY;
+	GptRepair(&g);
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
+		"Fix Primary GPT: WriteAndFreeGptData");
+	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+		   "VbExDiskRead(h, 1023, 1)\n"
+		   "VbExDiskRead(h, 991, 32)\n"
+		   "VbExDiskWrite(h, 1, 1)\n"
+		   "VbExDiskWrite(h, 2, 32)\n");
+	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		0, "Fix Primary GPT: Primary header is valid");
+
+	/*
+	 * Invalidate secondary GPT header and check that it can be
+	 * repaired by GptRepair().
+	 *
+	 * This would normally be called by LoadKernel()->GptInit()
+	 * but this callback is mocked in these tests.
+	 */
+	ResetMocks();
+	memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
+		"Fix Secondary GPT: AllocAndRead");
+	/* Call GptRepair() with input indicating primary GPT is valid */
+	g.valid_headers = g.valid_entries = MASK_PRIMARY;
+	GptRepair(&g);
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
+		"Fix Secondary GPT: WriteAndFreeGptData");
+	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
+		   "VbExDiskRead(h, 2, 32)\n"
+		   "VbExDiskRead(h, 1023, 1)\n"
+		   "VbExDiskWrite(h, 1023, 1)\n"
+		   "VbExDiskWrite(h, 991, 32)\n");
+	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
+		g.gpt_drive_sectors, 0, g.sector_bytes),
+		0, "Fix Secondary GPT: Secondary header is valid");
+
+	/* Data which is changed is written */
+	ResetMocks();
+	AllocAndReadGptData(handle, &g);
+	g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
+	ResetCallLog();
+	memset(g.primary_header, '\0', g.sector_bytes);
+	h = (GptHeader*)g.primary_header;
+	h->entries_lba = 2;
+	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
+	h->size_of_entry = sizeof(GptEntry);
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
+	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
+		   "VbExDiskWrite(h, 2, 32)\n");
+
+	/* Data which is changed is written */
+	ResetMocks();
+	AllocAndReadGptData(handle, &g);
+	g.modified = -1;
+	ResetCallLog();
+	memset(g.primary_header, '\0', g.sector_bytes);
+	h = (GptHeader*)g.primary_header;
+	h->entries_lba = 2;
+	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
+	h->size_of_entry = sizeof(GptEntry);
+	h = (GptHeader*)g.secondary_header;
+	h->entries_lba = 991;
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
+	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
+		   "VbExDiskWrite(h, 2, 32)\n"
+		   "VbExDiskWrite(h, 1023, 1)\n"
+		   "VbExDiskWrite(h, 991, 32)\n");
+
+	/* If legacy signature, don't modify GPT header/entries 1 */
+	ResetMocks();
+	AllocAndReadGptData(handle, &g);
+	h = (GptHeader *)g.primary_header;
+	memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
+	g.modified = -1;
+	ResetCallLog();
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
+	TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
+		   "VbExDiskWrite(h, 991, 32)\n");
+
+	/* Error reading */
+	ResetMocks();
+	disk_read_to_fail = 1;
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+	g.valid_headers = g.valid_entries = MASK_SECONDARY;
+	GptRepair(&g);
+	ResetCallLog();
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
+	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
+		   "VbExDiskWrite(h, 2, 32)\n");
+
+	ResetMocks();
+	disk_read_to_fail = 2;
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+	g.valid_headers = MASK_BOTH;
+	g.valid_entries = MASK_SECONDARY;
+	GptRepair(&g);
+	ResetCallLog();
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
+	TEST_CALLS("VbExDiskWrite(h, 2, 32)\n");
+
+	ResetMocks();
+	disk_read_to_fail = 991;
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+	g.valid_headers = MASK_BOTH;
+	g.valid_entries = MASK_PRIMARY;
+	GptRepair(&g);
+	ResetCallLog();
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2");
+	TEST_CALLS("VbExDiskWrite(h, 991, 32)\n");
+
+	ResetMocks();
+	disk_read_to_fail = 1023;
+	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+	g.valid_headers = g.valid_entries = MASK_PRIMARY;
+	GptRepair(&g);
+	ResetCallLog();
+	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2");
+	TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
+		   "VbExDiskWrite(h, 991, 32)\n");
+
+	/* Error writing */
+	ResetMocks();
+	disk_write_to_fail = 1;
+	AllocAndReadGptData(handle, &g);
+	g.modified = -1;
+	memset(g.primary_header, '\0', g.sector_bytes);
+	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
+
+	ResetMocks();
+	disk_write_to_fail = 2;
+	AllocAndReadGptData(handle, &g);
+	g.modified = -1;
+	memset(g.primary_header, '\0', g.sector_bytes);
+	h = (GptHeader*)g.primary_header;
+	h->entries_lba = 2;
+	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
+
+	ResetMocks();
+	disk_write_to_fail = 991;
+	AllocAndReadGptData(handle, &g);
+	g.modified = -1;
+	memset(g.primary_header, '\0', g.sector_bytes);
+	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
+
+	ResetMocks();
+	disk_write_to_fail = 1023;
+	AllocAndReadGptData(handle, &g);
+	g.modified = -1;
+	memset(g.primary_header, '\0', g.sector_bytes);
+	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
+
+}
+
+int main(void)
+{
+	ReadWriteGptTest();
+
+	return gTestSuccess ? 0 : 255;
+}
diff --git a/tests/load_kernel_tests.sh b/tests/load_kernel_tests.sh
index d5f41f2..45eedf4 100755
--- a/tests/load_kernel_tests.sh
+++ b/tests/load_kernel_tests.sh
@@ -31,10 +31,10 @@
     --key ${TESTKEY_DIR}/key_rsa2048.keyb --algorithm 4
 
 # Keyblock with kernel data key is signed by kernel subkey
-# Flags=5 means dev=0 rec=0
+# Flags=21 means dev=0 rec=0 minios=0
 ${FUTILITY} vbutil_keyblock --pack keyblock.test \
     --datapubkey datakey.test \
-    --flags 5 \
+    --flags 21 \
     --signprivate ${SCRIPT_DIR}/devkeys/kernel_subkey.vbprivk
 
 # Kernel preamble is signed with the kernel data key
diff --git a/tests/test_common.c b/tests/test_common.c
index 7e994f3..2ce3a5d 100644
--- a/tests/test_common.c
+++ b/tests/test_common.c
@@ -147,6 +147,20 @@
 	return !result;
 }
 
+int test_fail(int result,
+	      const char *preamble, const char *desc, const char *comment)
+{
+	if (result != 0) {
+		print_passed(preamble, desc, comment);
+	} else {
+		print_failed(preamble, desc, comment);
+		fprintf(stderr,
+			"	Didn't expect SUCCESS (0), but got it\n");
+		gTestSuccess = 0;
+	}
+	return result;
+}
+
 int test_true(int result,
 	      const char *preamble, const char *desc, const char *comment)
 {
diff --git a/tests/test_common.h b/tests/test_common.h
index e0d8ef3..c3da880 100644
--- a/tests/test_common.h
+++ b/tests/test_common.h
@@ -120,6 +120,17 @@
 		  #result " == 0", \
 		  comment)
 
+/* Return 1 if result is not 0 (VB2_SUCCESS or other), else return 1.
+ * Also update the global gTestSuccess flag if test fails. */
+int test_fail(int result,
+	      const char *preamble, const char *desc, const char *comment);
+
+#define TEST_FAIL(result, comment) \
+	test_fail(result, \
+		  __FILE__ ":" TOSTRING(__LINE__), \
+		  #result " != 0", \
+		  comment)
+
 /* Return 1 if vb2ex_abort() was called, else return 0.
  * Also update the global gTestSuccess flag if test fails. */
 int test_abort(int aborted,
diff --git a/tests/vb2_api_tests.c b/tests/vb2_api_tests.c
index 40fdf59..beab239 100644
--- a/tests/vb2_api_tests.c
+++ b/tests/vb2_api_tests.c
@@ -384,20 +384,14 @@
 	TEST_NEQ(ctx->flags & VB2_CONTEXT_RECOVERY_MODE, 0, "  recovery flag");
 	TEST_NEQ(ctx->flags & VB2_CONTEXT_CLEAR_RAM, 0, "  clear ram flag");
 
-	/* Dev switch error in normal mode reboots to recovery */
+	/* Dev switch error proceeds to a recovery boot */
 	reset_common_data(FOR_MISC);
 	retval_vb2_check_dev_switch = VB2_ERROR_MOCK;
-	TEST_EQ(vb2api_fw_phase1(ctx), VB2_ERROR_MOCK, "phase1 dev switch");
-	TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
-		VB2_RECOVERY_DEV_SWITCH, "  recovery request");
-
-	/* Dev switch error already in recovery mode just proceeds */
-	reset_common_data(FOR_MISC);
-	vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_RO_UNSPECIFIED);
-	retval_vb2_check_dev_switch = VB2_ERROR_MOCK;
 	TEST_EQ(vb2api_fw_phase1(ctx), VB2_ERROR_API_PHASE1_RECOVERY,
-		"phase1 dev switch error in recovery");
-	TEST_EQ(sd->recovery_reason, VB2_RECOVERY_RO_UNSPECIFIED,
+		"phase1 dev switch error proceeds to recovery");
+	TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
+		VB2_RECOVERY_DEV_SWITCH, "  recovery request");
+	TEST_EQ(sd->recovery_reason, VB2_RECOVERY_DEV_SWITCH,
 		"  recovery reason");
 	/* Check that DISPLAY_AVAILABLE gets set on recovery mode. */
 	TEST_NEQ(ctx->flags & VB2_CONTEXT_DISPLAY_INIT,
diff --git a/tests/vb2_auxfw_sync_tests.c b/tests/vb2_auxfw_sync_tests.c
index 48ce952..3987d64 100644
--- a/tests/vb2_auxfw_sync_tests.c
+++ b/tests/vb2_auxfw_sync_tests.c
@@ -16,7 +16,6 @@
 #include "host_common.h"
 #include "load_kernel_fw.h"
 #include "test_common.h"
-#include "vboot_kernel.h"
 #include "vboot_struct.h"
 
 /* Mock data */
diff --git a/tests/vb2_common2_tests.c b/tests/vb2_common2_tests.c
index 3f06289..5f065f8 100644
--- a/tests/vb2_common2_tests.c
+++ b/tests/vb2_common2_tests.c
@@ -41,6 +41,7 @@
 			/* shouldn't reach here but added for compiler */
 			return VB2_ERROR_MOCK;
 	}
+	return VB2_ERROR_MOCK;
 }
 
 vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
diff --git a/tests/vb2_common_tests.c b/tests/vb2_common_tests.c
index 11d183c..d76c402 100644
--- a/tests/vb2_common_tests.c
+++ b/tests/vb2_common_tests.c
@@ -276,9 +276,11 @@
 	{
 		struct vb2_packed_key k = {.key_offset = sizeof(k),
 					   .key_size = 128};
+		const void *lower_base;
 		TEST_SUCC(vb2_verify_packed_key_inside(&k, sizeof(k)+128, &k),
 			  "vb2_packed_key_inside() ok 1");
-		TEST_SUCC(vb2_verify_packed_key_inside(&k - 1,
+		lower_base = (const void *)((uintptr_t)&k - sizeof(k));
+		TEST_SUCC(vb2_verify_packed_key_inside(lower_base,
 						       2*sizeof(k)+128, &k),
 			  "vb2_packed_key_inside() ok 2");
 		TEST_EQ(vb2_verify_packed_key_inside(&k, 128, &k),
@@ -297,9 +299,11 @@
 	{
 		struct vb2_signature s = {.sig_offset = sizeof(s),
 					  .sig_size = 128};
+		const void *lower_base;
 		TEST_SUCC(vb2_verify_signature_inside(&s, sizeof(s)+128, &s),
 			"vb2_verify_signature_inside() ok 1");
-		TEST_SUCC(vb2_verify_signature_inside(&s - 1,
+		lower_base = (const void *)((uintptr_t)&s - sizeof(s));
+		TEST_SUCC(vb2_verify_signature_inside(lower_base,
 						      2*sizeof(s)+128, &s),
 			  "vb2_verify_signature_inside() ok 2");
 		TEST_EQ(vb2_verify_signature_inside(&s, 128, &s),
diff --git a/tests/vb2_ec_sync_tests.c b/tests/vb2_ec_sync_tests.c
index 8881ea7..16496e4 100644
--- a/tests/vb2_ec_sync_tests.c
+++ b/tests/vb2_ec_sync_tests.c
@@ -13,7 +13,6 @@
 #include "host_common.h"
 #include "load_kernel_fw.h"
 #include "test_common.h"
-#include "vboot_kernel.h"
 #include "vboot_struct.h"
 
 /* Mock data */
@@ -97,6 +96,13 @@
 	memset(hmir, 0, sizeof(hmir));
 	hmir[0] = 42;
 	vb2_secdata_kernel_set_ec_hash(ctx, hmir);
+
+	/*
+	 * This flag should not involve in the steps deciding whether EC is
+	 * running RW. The only concern here is we need to clear this flag after
+	 * attempting a jump to RW.
+	 */
+	ctx->flags |= VB2_CONTEXT_EC_TRUSTED;
 }
 
 /* Mock functions */
@@ -516,6 +522,8 @@
 	TEST_EQ(ec_ro_protected, 1, "ec ro protected");
 	TEST_EQ(ec_rw_protected, 1, "ec rw protected");
 	TEST_EQ(ec_run_image, 1, "ec run image");
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED,
+		   "  VB2_CONTEXT_EC_TRUSTED is cleared");
 
 	ResetMocks();
 	test_ssync(0, 0, "AP-RW, EC-RO -> EC-RW");
@@ -524,6 +532,8 @@
 	TEST_EQ(ec_ro_protected, 1, "  ec ro protected");
 	TEST_EQ(ec_rw_protected, 1, "  ec rw protected");
 	TEST_EQ(ec_run_image, 1, "  ec run image");
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED,
+		   "  VB2_CONTEXT_EC_TRUSTED is cleared");
 
 	ResetMocks();
 	jump_retval = VB2_ERROR_MOCK;
@@ -534,6 +544,8 @@
 	TEST_EQ(ec_ro_protected, 0, "  ec ro protected");
 	TEST_EQ(ec_rw_protected, 0, "  ec rw protected");
 	TEST_EQ(ec_run_image, 0, "  ec run image");
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED,
+		   "  VB2_CONTEXT_EC_TRUSTED is cleared");
 
 	ResetMocks();
 	jump_retval = VB2_REQUEST_REBOOT_EC_TO_RO;
@@ -544,6 +556,8 @@
 	TEST_EQ(ec_ro_protected, 0, "  ec ro protected");
 	TEST_EQ(ec_rw_protected, 0, "  ec rw protected");
 	TEST_EQ(ec_run_image, 0, "  ec run image");
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED,
+		   "  VB2_CONTEXT_EC_TRUSTED is cleared");
 
 	ResetMocks();
 	protect_retval = VB2_ERROR_MOCK;
@@ -553,6 +567,8 @@
 	TEST_EQ(ec_ro_protected, 0, "ec ro protected");
 	TEST_EQ(ec_rw_protected, 0, "ec rw protected");
 	TEST_EQ(ec_run_image, 1, "ec run image");
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED,
+		   "  VB2_CONTEXT_EC_TRUSTED is cleared");
 
 	/* No longer check for shutdown requested */
 	ResetMocks();
diff --git a/tests/vb2_kernel_tests.c b/tests/vb2_kernel_tests.c
index 0e1cb28..0dc0e74 100644
--- a/tests/vb2_kernel_tests.c
+++ b/tests/vb2_kernel_tests.c
@@ -15,6 +15,7 @@
 #include "2sysincludes.h"
 #include "test_common.h"
 #include "vboot_struct.h"
+#include "vboot_api.h"
 
 /* Common context for tests */
 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
diff --git a/tests/vb2_misc_tests.c b/tests/vb2_misc_tests.c
index a7cc115..c4b3ce4 100644
--- a/tests/vb2_misc_tests.c
+++ b/tests/vb2_misc_tests.c
@@ -58,7 +58,7 @@
 
 /* Mocked functions */
 
-int vb2_allow_recovery(struct vb2_context *c)
+int vb2api_allow_recovery(struct vb2_context *c)
 {
 	return allow_recovery_retval;
 }
@@ -640,24 +640,35 @@
 static void enable_dev_tests(void)
 {
 	reset_common_data();
-	vb2_enable_developer_mode(ctx);
+	allow_recovery_retval = 0;
+	TEST_FAIL(vb2api_enable_developer_mode(ctx),
+		 "vb2api_enable_developer_mode - failed");
+	TEST_EQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) &
+		VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE, 0,
+		"  dev mode flag not set");
+
+	reset_common_data();
+	allow_recovery_retval = 1;
+	TEST_SUCC(vb2api_enable_developer_mode(ctx),
+		  "vb2api_enable_developer_mode - success");
 	TEST_NEQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) &
 	         VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE, 0,
-		 "dev mode flag set");
+		 "  dev mode flag set");
 	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL), BOOT_EXTERNAL_ON_DEV,
-		"NV_DEV_BOOT_EXTERNAL set according to compile-time flag");
+		"  NV_DEV_BOOT_EXTERNAL set according to compile-time flag");
 
 	/* secdata_firmware not initialized, aborts */
 	reset_common_data();
+	allow_recovery_retval = 1;
 	sd->status &= ~VB2_SD_STATUS_SECDATA_FIRMWARE_INIT;
-	TEST_ABORT(vb2_enable_developer_mode(ctx),
+	TEST_ABORT(vb2api_enable_developer_mode(ctx),
 		   "secdata_firmware no init, enable dev mode aborted");
 	sd->status |= VB2_SD_STATUS_SECDATA_FIRMWARE_INIT;
 	TEST_EQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) &
 	        VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE, 0,
-		"dev mode flag not set");
+		"  dev mode flag not set");
 	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL), 0,
-		"NV_DEV_BOOT_EXTERNAL not set");
+		"  NV_DEV_BOOT_EXTERNAL not set");
 }
 
 static void tpm_clear_tests(void)
@@ -911,7 +922,7 @@
 
 	/* Boot from external disk */
 	reset_common_data();
-	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1);
+	ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED;
 	vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL);
 	TEST_EQ(vb2api_get_dev_default_boot_target(ctx),
@@ -926,7 +937,7 @@
 		VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL,
 		"default boot external not allowed");
 	reset_common_data();
-	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1);
+	ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED;
 	vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL);
 	TEST_EQ(vb2api_get_dev_default_boot_target(ctx),
@@ -935,7 +946,7 @@
 
 	/* Boot altfw */
 	reset_common_data();
-	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1);
+	ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED;
 	vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW);
 	TEST_EQ(vb2api_get_dev_default_boot_target(ctx),
@@ -950,7 +961,7 @@
 		VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL,
 		"default boot altfw not allowed");
 	reset_common_data();
-	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1);
+	ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED;
 	vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW);
 	TEST_EQ(vb2api_get_dev_default_boot_target(ctx),
@@ -958,84 +969,100 @@
 		"default boot altfw not allowed");
 }
 
-static void dev_boot_allowed_tests(void)
+static void fill_dev_boot_flags_tests(void)
 {
 	/* Dev boot - allowed by default */
 	reset_common_data();
-	TEST_EQ(vb2_dev_boot_allowed(ctx), 1, "dev boot - allowed by default");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALLOWED,
+		  "dev boot - allowed by default");
 
 	/* Dev boot - disabled by FWMP */
 	reset_common_data();
 	fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT;
-	TEST_EQ(vb2_dev_boot_allowed(ctx), 0, "dev boot - FWMP disabled");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALLOWED,
+		   "dev boot - FWMP disabled");
 
 	/* Dev boot - force enabled by GBB */
 	reset_common_data();
 	fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT;
 	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
-	TEST_EQ(vb2_dev_boot_allowed(ctx), 1, "dev boot - GBB force dev on");
-
-	/* Legacy boot - not allowed by default */
-	reset_common_data();
-	TEST_EQ(vb2_dev_boot_altfw_allowed(ctx), 0,
-		"dev boot altfw - not allowed by default");
-
-	/* Legacy boot - enabled by nvdata */
-	reset_common_data();
-	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1);
-	TEST_EQ(vb2_dev_boot_altfw_allowed(ctx), 1,
-		"dev boot altfw - nvdata enabled");
-
-	/* Legacy boot - enabled by FWMP */
-	reset_common_data();
-	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW;
-	TEST_EQ(vb2_dev_boot_altfw_allowed(ctx), 1,
-		"dev boot altfw - secdata enabled");
-
-	/* Legacy boot - force enabled by GBB */
-	reset_common_data();
-	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW;
-	TEST_EQ(vb2_dev_boot_altfw_allowed(ctx), 1,
-		"dev boot altfw - GBB force enabled");
-
-	/* Legacy boot - set all flags */
-	reset_common_data();
-	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1);
-	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW;
-	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW;
-	TEST_EQ(vb2_dev_boot_altfw_allowed(ctx), 1,
-		"dev boot altfw - all flags set");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALLOWED,
+		  "dev boot - GBB force dev on");
 
 	/* External boot - not allowed by default */
 	reset_common_data();
-	TEST_EQ(vb2_dev_boot_external_allowed(ctx), 0,
-		"dev boot external - not allowed by default");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED,
+		   "dev boot external - not allowed by default");
 
 	/* External boot - enabled by nvdata */
 	reset_common_data();
 	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1);
-	TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1,
-		"dev boot external - nvdata enabled");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED,
+		  "dev boot external - nvdata enabled");
 
 	/* External boot - enabled by FWMP */
 	reset_common_data();
 	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL;
-	TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1,
-		"dev boot external - secdata enabled");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED,
+		  "dev boot external - secdata enabled");
 
 	/* External boot - force enabled by GBB */
 	reset_common_data();
 	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_USB;
-	TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1,
-		"dev boot external - GBB force enabled");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED,
+		  "dev boot external - GBB force enabled");
 
 	/* External boot - set all flags */
 	reset_common_data();
 	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1);
 	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL;
 	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_USB;
-	TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1,
-		"dev boot external - all flags set");
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED,
+		  "dev boot external - all flags set");
+
+	/* Alternate boot - not allowed by default */
+	reset_common_data();
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_FALSE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED,
+		   "dev boot altfw - not allowed by default");
+
+	/* Alternate boot - enabled by nvdata */
+	reset_common_data();
+	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1);
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED,
+		  "dev boot altfw - nvdata enabled");
+
+	/* Alternate boot - enabled by FWMP */
+	reset_common_data();
+	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW;
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED,
+		  "dev boot altfw - secdata enabled");
+
+	/* Alternate boot - force enabled by GBB */
+	reset_common_data();
+	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW;
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED,
+		  "dev boot altfw - GBB force enabled");
+
+	/* Alternate boot - set all flags */
+	reset_common_data();
+	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1);
+	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW;
+	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW;
+	vb2_fill_dev_boot_flags(ctx);
+	TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED,
+		  "dev boot altfw - all flags set");
 }
 
 static void use_dev_screen_short_delay_tests(void)
@@ -1068,7 +1095,7 @@
 	phone_recovery_enabled_tests();
 	diagnostic_ui_enabled_tests();
 	dev_default_boot_tests();
-	dev_boot_allowed_tests();
+	fill_dev_boot_flags_tests();
 	use_dev_screen_short_delay_tests();
 
 	return gTestSuccess ? 0 : 255;
diff --git a/tests/vb2_sha256_x86_tests.c b/tests/vb2_sha256_x86_tests.c
new file mode 100644
index 0000000..06ba12e
--- /dev/null
+++ b/tests/vb2_sha256_x86_tests.c
@@ -0,0 +1,137 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* FIPS 180-2 Tests for message digest functions. */
+
+#include <cpuid.h>
+#include <stdio.h>
+
+#include "2api.h"
+#include "2sha.h"
+#include "sha_test_vectors.h"
+#include "test_common.h"
+
+vb2_error_t vb2_digest_buffer(const uint8_t *buf, uint32_t size,
+			      enum vb2_hash_algorithm hash_alg, uint8_t *digest,
+			      uint32_t digest_size)
+{
+	VB2_TRY(vb2ex_hwcrypto_digest_init(hash_alg, size));
+	VB2_TRY(vb2ex_hwcrypto_digest_extend(buf, size));
+
+	return vb2ex_hwcrypto_digest_finalize(digest, digest_size);
+
+}
+
+static void sha256_tests(void)
+{
+	uint8_t digest[VB2_SHA256_DIGEST_SIZE];
+	uint8_t *test_inputs[3];
+	const uint8_t expect_multiple[VB2_SHA256_DIGEST_SIZE] = {
+			0x07, 0x08, 0xb4, 0xca, 0x46, 0x4c, 0x40, 0x39,
+			0x07, 0x06, 0x88, 0x80, 0x30, 0x55, 0x5d, 0x86,
+			0x0e, 0x4a, 0x0d, 0x2b, 0xc6, 0xc4, 0x87, 0x39,
+			0x2c, 0x16, 0x55, 0xb0, 0x82, 0x13, 0x16, 0x29 };
+	int i;
+
+	test_inputs[0] = (uint8_t *) oneblock_msg;
+	test_inputs[1] = (uint8_t *) multiblock_msg1;
+	test_inputs[2] = (uint8_t *) long_msg;
+
+	for (i = 0; i < 3; i++) {
+		TEST_SUCC(vb2_digest_buffer(test_inputs[i],
+					    strlen((char *)test_inputs[i]),
+					    VB2_HASH_SHA256,
+					    digest, sizeof(digest)),
+			  "vb2_digest_buffer() SHA256");
+		TEST_EQ(memcmp(digest, sha256_results[i], sizeof(digest)),
+			0, "SHA-256 digest");
+	}
+
+	TEST_EQ(vb2_digest_buffer(test_inputs[0],
+				  strlen((char *)test_inputs[0]),
+				  VB2_HASH_SHA256, digest, sizeof(digest) - 1),
+		VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE,
+		"vb2_digest_buffer() too small");
+
+	/* Test multiple small extends */
+	vb2ex_hwcrypto_digest_init(VB2_HASH_SHA256, 15);
+	vb2ex_hwcrypto_digest_extend((uint8_t *)"test1", 5);
+	vb2ex_hwcrypto_digest_extend((uint8_t *)"test2", 5);
+	vb2ex_hwcrypto_digest_extend((uint8_t *)"test3", 5);
+	vb2ex_hwcrypto_digest_finalize(digest, VB2_SHA256_DIGEST_SIZE);
+	TEST_EQ(memcmp(digest, expect_multiple, sizeof(digest)), 0,
+		"SHA-256 multiple extends");
+
+	TEST_EQ(vb2_hash_block_size(VB2_HASH_SHA256), VB2_SHA256_BLOCK_SIZE,
+		"vb2_hash_block_size(VB2_HASH_SHA256)");
+
+}
+
+static void known_value_tests(void)
+{
+	const char sentinel[] = "keepme";
+	union {
+		struct vb2_hash hash;
+		char overflow[sizeof(struct vb2_hash) + 8];
+	} test;
+
+#define TEST_KNOWN_VALUE(algo, str, value) \
+	TEST_EQ(vb2_digest_size(algo), sizeof(value) - 1, \
+		"Known hash size " #algo ": " #str);			\
+	{								\
+		char *sent_base = test.overflow +			\
+			offsetof(struct vb2_hash, raw) + sizeof(value) - 1; \
+		strcpy(sent_base, sentinel);				\
+		strcpy(sent_base, sentinel);				\
+		TEST_SUCC(vb2_digest_buffer((const uint8_t *)str,	\
+					    sizeof(str) - 1,		\
+					    algo, test.hash.raw,	\
+					    vb2_digest_size(algo)),	\
+			  "Calculate known hash " #algo ": " #str);	\
+		TEST_EQ(memcmp(test.hash.raw, value, sizeof(value) - 1), 0, \
+			"Known hash " #algo ": " #str);			\
+		TEST_EQ(strcmp(sent_base, sentinel), 0,			\
+			"Overflow known hash " #algo ": " #str);	\
+	}
+
+	TEST_KNOWN_VALUE(VB2_HASH_SHA256, "",
+		"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9"
+		"\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52"
+		"\xb8\x55");
+
+	const char long_test_string[] = "abcdefghbcdefghicdefghijdefghijkefgh"
+		"ijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs"
+		"mnopqrstnopqrstu";
+	TEST_KNOWN_VALUE(VB2_HASH_SHA256, long_test_string,
+		"\xcf\x5b\x16\xa7\x78\xaf\x83\x80\x03\x6c\xe5\x9e\x7b\x04\x92"
+		"\x37\x0b\x24\x9b\x11\xe8\xf0\x7a\x51\xaf\xac\x45\x03\x7a\xfe"
+		"\xe9\xd1");
+
+	/* vim helper to escape hex: <Shift+V>:s/\([a-f0-9]\{2\}\)/\\x\1/g */
+#undef TEST_KNOWN_VALUE
+}
+
+int main(int argc, char *argv[])
+{
+	uint32_t a, b = 0, c, d;
+	/* EAX = 07H, sub-leaf 0 */
+	__get_cpuid_count(7, 0, &a, &b, &c, &d);
+	if ((b & bit_SHA) == 0) {
+		fprintf(stderr, "SHA-NI not supported.\n");
+		return 254;
+	}
+
+	/* Initialize long_msg with 'a' x 1,000,000 */
+	long_msg = (char *) malloc(1000001);
+	memset(long_msg, 'a', 1000000);
+	long_msg[1000000]=0;
+
+	sha256_tests();
+	known_value_tests();
+
+	free(long_msg);
+
+	return gTestSuccess ? 0 : 255;
+}
diff --git a/tests/vb2_sha_tests.c b/tests/vb2_sha_tests.c
index b4a4bd0..a14af65 100644
--- a/tests/vb2_sha_tests.c
+++ b/tests/vb2_sha_tests.c
@@ -172,21 +172,27 @@
 static void known_value_tests(void)
 {
 	const char sentinel[] = "keepme";
-	struct {
+	union {
 		struct vb2_hash hash;
-		uint8_t overflow[8];
+		char overflow[sizeof(struct vb2_hash) + 8];
 	} test;
 
+
 #define TEST_KNOWN_VALUE(algo, str, value) \
 	TEST_EQ(vb2_digest_size(algo), sizeof(value) - 1, \
 		"Known hash size " #algo ": " #str); \
-	strcpy((char *)&test.hash.raw[sizeof(value) - 1], sentinel); \
-	TEST_SUCC(vb2_hash_calculate(str, sizeof(str) - 1, algo, &test.hash), \
-		  "Calculate known hash " #algo ": " #str); \
-	TEST_EQ(memcmp(test.hash.raw, value, sizeof(value) - 1), 0, \
-		"Known hash " #algo ": " #str); \
-	TEST_EQ(strcmp((char *)&test.hash.raw[sizeof(value) - 1], sentinel), 0,\
-		"Overflow known hash " #algo ": " #str);
+	{								\
+		char *sent_base = test.overflow + \
+			offsetof(struct vb2_hash, raw) + sizeof(value) - 1; \
+		strcpy(sent_base, sentinel);				\
+		TEST_SUCC(vb2_hash_calculate(str, sizeof(str) - 1,	\
+					     algo, &test.hash),		\
+			  "Calculate known hash " #algo ": " #str);	\
+		TEST_EQ(memcmp(test.hash.raw, value, sizeof(value) - 1), 0, \
+			"Known hash " #algo ": " #str);			\
+		TEST_EQ(strcmp(sent_base, sentinel), 0,			\
+			"Overflow known hash " #algo ": " #str);	\
+	}
 
 	TEST_KNOWN_VALUE(VB2_HASH_SHA1, "",
 		"\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18"
diff --git a/tests/vb2_ui_action_tests.c b/tests/vb2_ui_action_tests.c
deleted file mode 100644
index 6db75bf..0000000
--- a/tests/vb2_ui_action_tests.c
+++ /dev/null
@@ -1,1085 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Tests for UI related actions.
- */
-
-#include "2api.h"
-#include "2common.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2ui.h"
-#include "2ui_private.h"
-#include "test_common.h"
-#include "vboot_kernel.h"
-
-/* Fixed value for ignoring some checks. */
-#define MOCK_IGNORE 0xffffu
-
-/* Mock screen index for testing screen utility functions. */
-#define MOCK_NO_SCREEN 0xef00
-#define MOCK_SCREEN_BLANK 0xef10
-#define MOCK_SCREEN_BASE 0xef11
-#define MOCK_SCREEN_MENU 0xef12
-#define MOCK_SCREEN_TARGET0 0xef20
-#define MOCK_SCREEN_TARGET1 0xef21
-#define MOCK_SCREEN_TARGET2 0xef22
-#define MOCK_SCREEN_ACTION 0xef30
-#define MOCK_SCREEN_ALL_ACTION 0xef32
-
-/* Mock data */
-/* TODO(b/156448738): Add tests for timer_disabled and error_code */
-struct display_call {
-	const struct vb2_screen_info *screen;
-	uint32_t locale_id;
-	uint32_t selected_item;
-	uint32_t disabled_item_mask;
-	uint32_t hidden_item_mask;
-	int timer_disabled;
-	uint32_t current_page;
-	enum vb2_ui_error error_code;
-} __attribute__((packed));
-
-static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
-	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
-static struct vb2_context *ctx;
-static struct vb2_shared_data *sd;
-static struct vb2_gbb_header gbb;
-
-static int mock_calls_until_shutdown;
-
-static struct vb2_ui_context mock_ui_context;
-
-static struct display_call mock_displayed[64];
-static int mock_displayed_count;
-static int mock_displayed_i;
-
-static uint32_t mock_key[64];
-static int mock_key_trusted[64];
-static int mock_key_count;
-static int mock_key_total;
-
-static int mock_get_screen_info_called;
-
-static vb2_error_t mock_vbtlk_retval;
-static uint32_t mock_vbtlk_expected_flag;
-
-static int mock_dev_boot_allowed;
-static int mock_dev_boot_altfw_allowed;
-
-static int mock_run_altfw_called;
-static uint32_t mock_altfw_last;
-static uint32_t mock_altfw_count;
-
-static uint32_t mock_time_ms;
-static const uint32_t mock_time_start_ms = 31ULL * VB2_MSEC_PER_SEC;
-
-/* Mock actions */
-static uint32_t mock_action_called;
-static uint32_t mock_action_countdown_limit;
-static vb2_error_t mock_action_countdown(struct vb2_ui_context *ui)
-{
-	if (++mock_action_called >= mock_action_countdown_limit)
-		return VB2_REQUEST_UI_EXIT;
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t mock_action_screen_change(struct vb2_ui_context *ui)
-{
-	return vb2_ui_screen_change(ui, MOCK_SCREEN_BASE);
-}
-
-static vb2_error_t mock_action_base(struct vb2_ui_context *ui)
-{
-	mock_action_called++;
-	return VB2_SUCCESS;
-}
-
-static int mock_action_flags;
-static vb2_error_t mock_action_flag0(struct vb2_ui_context *ui)
-{
-	if ((1 << 0) & mock_action_flags)
-		return VB2_REQUEST_UI_EXIT;
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t mock_action_flag1(struct vb2_ui_context *ui)
-{
-	if ((1 << 1) & mock_action_flags)
-		return VB2_REQUEST_UI_EXIT;
-	return VB2_SUCCESS;
-}
-
-static vb2_error_t mock_action_flag2(struct vb2_ui_context *ui)
-{
-	if ((1 << 2) & mock_action_flags)
-		return VB2_REQUEST_UI_EXIT;
-	return VB2_SUCCESS;
-}
-
-static uint32_t mock_action_delay_ms;
-static vb2_error_t mock_action_msleep(struct vb2_ui_context *ui)
-{
-	vb2ex_msleep(mock_action_delay_ms);
-	return VB2_SUCCESS;
-}
-
-/* Mock screens */
-struct vb2_screen_info mock_screen_temp;
-const struct vb2_screen_info mock_screen_blank = {
-	.id = MOCK_SCREEN_BLANK,
-	.name = "mock_screen_blank",
-};
-const struct vb2_screen_info mock_screen_base = {
-	.id = MOCK_SCREEN_BASE,
-	.name = "mock_screen_base: menuless screen",
-};
-const struct vb2_menu_item mock_screen_menu_items[] = {
-	{
-		.text = "item 0",
-		.target = MOCK_SCREEN_TARGET0,
-	},
-	{
-		.text = "item 1",
-		.target = MOCK_SCREEN_TARGET1,
-	},
-	{
-		.text = "item 2",
-		.target = MOCK_SCREEN_TARGET2,
-	},
-	{
-		.text = "item 3",
-		.action = mock_action_base,
-	},
-	{
-		.text = "item 4 (no target)",
-	},
-};
-const struct vb2_screen_info mock_screen_menu = {
-	.id = MOCK_SCREEN_MENU,
-	.name = "mock_screen_menu: screen with 5 items",
-	.menu = {
-		.num_items = ARRAY_SIZE(mock_screen_menu_items),
-		.items = mock_screen_menu_items,
-	},
-};
-const struct vb2_screen_info mock_screen_target0 = {
-	.id = MOCK_SCREEN_TARGET0,
-	.name = "mock_screen_target0",
-};
-const struct vb2_screen_info mock_screen_target1 = {
-	.id = MOCK_SCREEN_TARGET1,
-	.name = "mock_screen_target1",
-};
-const struct vb2_screen_info mock_screen_target2 = {
-	.id = MOCK_SCREEN_TARGET2,
-	.name = "mock_screen_target2",
-};
-const struct vb2_screen_info mock_screen_action = {
-	.id = MOCK_SCREEN_ACTION,
-	.name = "mock_screen_action",
-	.action = mock_action_countdown,
-};
-const struct vb2_menu_item mock_screen_all_action_items[] = {
-	{
-		.text = "all_action_screen_item",
-		.action = mock_action_flag1,
-	},
-};
-const struct vb2_screen_info mock_screen_all_action = {
-	.id = MOCK_SCREEN_ALL_ACTION,
-	.name = "mock_screen_all_action",
-	.action = mock_action_flag0,
-	.menu = {
-		.num_items = ARRAY_SIZE(mock_screen_all_action_items),
-		.items = mock_screen_all_action_items,
-	},
-};
-
-static void screen_state_eq(const struct vb2_screen_state *state,
-			    enum vb2_screen screen,
-			    uint32_t selected_item,
-			    uint32_t hidden_item_mask)
-{
-	if (screen != MOCK_IGNORE) {
-		if (state->screen == NULL)
-			TEST_TRUE(0, "  state.screen does not exist");
-		else
-			TEST_EQ(state->screen->id, screen, "  state.screen");
-	}
-	if (selected_item != MOCK_IGNORE)
-		TEST_EQ(state->selected_item,
-			selected_item, "  state.selected_item");
-	if (hidden_item_mask != MOCK_IGNORE)
-		TEST_EQ(state->hidden_item_mask,
-			hidden_item_mask, "  state.hidden_item_mask");
-}
-
-static void add_mock_key(uint32_t press, int trusted)
-{
-	if (mock_key_total >= ARRAY_SIZE(mock_key) ||
-	    mock_key_total >= ARRAY_SIZE(mock_key_trusted)) {
-		TEST_TRUE(0, "  mock_key ran out of entries!");
-		return;
-	}
-
-	mock_key[mock_key_total] = press;
-	mock_key_trusted[mock_key_total] = trusted;
-	mock_key_total++;
-}
-
-static void add_mock_keypress(uint32_t press)
-{
-	add_mock_key(press, 0);
-}
-
-
-static void set_mock_vbtlk(vb2_error_t retval, uint32_t disk_flags)
-{
-	mock_vbtlk_retval = retval;
-	mock_vbtlk_expected_flag = disk_flags;
-}
-
-static void displayed_eq(const char *text,
-			 enum vb2_screen screen,
-			 uint32_t locale_id,
-			 uint32_t selected_item,
-			 uint32_t hidden_item_mask,
-			 int line)
-{
-	char text_info[32], text_buf[128];
-
-	sprintf(text_info, "(line #%d, displayed #%d)", line, mock_displayed_i);
-
-	if (mock_displayed_i >= mock_displayed_count) {
-		sprintf(text_buf, "  %s missing screen %s",
-			text_info, text);
-		TEST_TRUE(0, text_buf);
-		return;
-	}
-
-	if (screen != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s screen of %s", text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].screen->id, screen,
-			text_buf);
-	}
-	if (locale_id != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s locale_id of %s", text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].locale_id, locale_id,
-			text_buf);
-	}
-	if (selected_item != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s selected_item of %s",
-			text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].selected_item,
-			selected_item, text_buf);
-	}
-	if (hidden_item_mask != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s hidden_item_mask of %s",
-			text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].hidden_item_mask,
-			hidden_item_mask, text_buf);
-	}
-	mock_displayed_i++;
-}
-
-static void displayed_no_extra(int line)
-{
-	char text_info[32], text_buf[128];
-
-	sprintf(text_info, "(line #%d)", line);
-
-	if (mock_displayed_i == 0)
-		sprintf(text_buf, "  %s no screen", text_info);
-	else
-		sprintf(text_buf, "  %s no extra screens", text_info);
-	TEST_EQ(mock_displayed_count, mock_displayed_i, text_buf);
-}
-
-#define DISPLAYED_EQ(...) displayed_eq(__VA_ARGS__, __LINE__)
-
-#define DISPLAYED_PASS() \
-	displayed_eq("", MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, \
-		     __LINE__)
-
-#define DISPLAYED_NO_EXTRA() displayed_no_extra(__LINE__)
-
-/* Reset mock data (for use before each test) */
-static void reset_common_data(void)
-{
-	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
-		  "vb2api_init failed");
-
-	memset(&gbb, 0, sizeof(gbb));
-
-	vb2_nv_init(ctx);
-
-	sd = vb2_get_sd(ctx);
-
-	/* For check_shutdown_request */
-	mock_calls_until_shutdown = 10;
-
-	/* Reset mock_screen_temp for test by test temporary screen_info */
-	mock_screen_temp = (struct vb2_screen_info){
-	      .id = MOCK_NO_SCREEN,
-	      .name = "mock_screen_temp",
-	};
-
-	/* Mock ui_context based on mock screens */
-	memset(&mock_ui_context, 0, sizeof(mock_ui_context));
-	mock_ui_context.ctx = ctx;
-
-	if (!mock_ui_context.state)
-		mock_ui_context.state = malloc(sizeof(*mock_ui_context.state));
-	memset(mock_ui_context.state, 0, sizeof(*mock_ui_context.state));
-	mock_ui_context.state->screen = &mock_screen_temp;
-
-	/* For vb2ex_display_ui */
-	memset(mock_displayed, 0, sizeof(mock_displayed));
-	mock_displayed_count = 0;
-	mock_displayed_i = 0;
-
-	/* For VbExKeyboardRead */
-	memset(mock_key, 0, sizeof(mock_key));
-	memset(mock_key_trusted, 0, sizeof(mock_key_trusted));
-	mock_key_count = 0;
-	mock_key_total = 0;
-
-	/* For mock actions */
-	mock_action_called = 0;
-	mock_action_countdown_limit = 1;
-	mock_action_flags = 0;
-	mock_action_delay_ms = 0;
-
-	/* For chagen_screen and vb2_get_screen_info */
-	mock_get_screen_info_called = 0;
-
-	/* For VbTryLoadKernel */
-	mock_vbtlk_retval = VB2_ERROR_MOCK;
-	mock_vbtlk_expected_flag = MOCK_IGNORE;
-
-	/* For dev_boot* in 2misc.h */
-	mock_dev_boot_allowed = 1;
-	mock_dev_boot_altfw_allowed = 0;
-
-	/* For vb2ex_run_altfw */
-	mock_run_altfw_called = 0;
-	mock_altfw_last = -100;
-	mock_altfw_count = 2;
-
-	/* For vb2ex_mtime and vb2ex_msleep  */
-	mock_time_ms = mock_time_start_ms;
-}
-
-/* Mock functions */
-struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
-{
-	return &gbb;
-}
-
-uint32_t VbExIsShutdownRequested(void)
-{
-	if (mock_calls_until_shutdown < 0)  /* Never request shutdown */
-		return 0;
-	if (mock_calls_until_shutdown == 0)
-		return 1;
-	mock_calls_until_shutdown--;
-
-	return 0;
-}
-
-const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen screen)
-{
-	mock_get_screen_info_called++;
-
-	switch ((int)screen) {
-	case MOCK_SCREEN_BLANK:
-		return &mock_screen_blank;
-	case MOCK_SCREEN_BASE:
-		return &mock_screen_base;
-	case MOCK_SCREEN_MENU:
-		return &mock_screen_menu;
-	case MOCK_SCREEN_TARGET0:
-		return &mock_screen_target0;
-	case MOCK_SCREEN_TARGET1:
-		return &mock_screen_target1;
-	case MOCK_SCREEN_TARGET2:
-		return &mock_screen_target2;
-	case MOCK_SCREEN_ACTION:
-		return &mock_screen_action;
-	case MOCK_SCREEN_ALL_ACTION:
-		return &mock_screen_all_action;
-	case MOCK_NO_SCREEN:
-		return NULL;
-	default:
-		mock_screen_temp.id = screen;
-		return &mock_screen_temp;
-	}
-}
-
-vb2_error_t vb2ex_display_ui(enum vb2_screen screen,
-			     uint32_t locale_id,
-			     uint32_t selected_item,
-			     uint32_t disabled_item_mask,
-			     uint32_t hidden_item_mask,
-			     int timer_disabled,
-			     uint32_t current_page,
-			     enum vb2_ui_error error_code)
-{
-	struct display_call displayed = (struct display_call){
-		.screen = vb2_get_screen_info(screen),
-		.locale_id = locale_id,
-		.selected_item = selected_item,
-		.disabled_item_mask = disabled_item_mask,
-		.hidden_item_mask = hidden_item_mask,
-		.timer_disabled = timer_disabled,
-		.current_page = current_page,
-		.error_code = error_code,
-	};
-
-	/* Ignore repeated calls with same arguments */
-	if (mock_displayed_count > 0 &&
-	    !memcmp(&mock_displayed[mock_displayed_count - 1], &displayed,
-		    sizeof(struct display_call)))
-		return VB2_SUCCESS;
-
-	VB2_DEBUG("displayed %d: screen=%#x, locale_id=%u, selected_item=%u, "
-		  "disabled_item_mask=%#x, hidden_item_mask=%#x, "
-		  "timer_disabled=%d, current_page=%u, error=%#x\n",
-		  mock_displayed_count, screen, locale_id, selected_item,
-		  disabled_item_mask, hidden_item_mask,
-		  timer_disabled, current_page, error_code);
-
-	if (mock_displayed_count >= ARRAY_SIZE(mock_displayed)) {
-		TEST_TRUE(0, "  mock vb2ex_display_ui ran out of entries!");
-		return VB2_ERROR_MOCK;
-	}
-
-	mock_displayed[mock_displayed_count++] = displayed;
-
-	return VB2_SUCCESS;
-}
-
-uint32_t VbExKeyboardRead(void)
-{
-	return VbExKeyboardReadWithFlags(NULL);
-}
-
-uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags)
-{
-	if (mock_key_count < mock_key_total) {
-		if (key_flags != NULL) {
-			if (mock_key_trusted[mock_key_count])
-				*key_flags = VB_KEY_FLAG_TRUSTED_KEYBOARD;
-			else
-				*key_flags = 0;
-		}
-		return mock_key[mock_key_count++];
-	}
-
-	return 0;
-}
-
-vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t disk_flags)
-{
-	TEST_EQ(mock_vbtlk_expected_flag, disk_flags,
-		"  unexpected disk_flags");
-	return mock_vbtlk_retval;
-}
-
-int vb2_dev_boot_allowed(struct vb2_context *c)
-{
-	return mock_dev_boot_allowed;
-}
-
-int vb2_dev_boot_altfw_allowed(struct vb2_context *c)
-{
-	return mock_dev_boot_altfw_allowed;
-}
-
-vb2_error_t vb2ex_run_altfw(uint32_t altfw_id)
-{
-	mock_run_altfw_called++;
-	mock_altfw_last = altfw_id;
-
-	if (altfw_id <= mock_altfw_count)
-		return VB2_SUCCESS;
-	else
-		return VB2_ERROR_UNKNOWN;
-}
-
-uint32_t vb2ex_get_altfw_count(void)
-{
-	return mock_altfw_count;
-}
-
-uint32_t vb2ex_mtime(void)
-{
-	return mock_time_ms;
-}
-
-void vb2ex_msleep(uint32_t msec)
-{
-	mock_time_ms += msec;
-}
-
-/* Tests */
-static void menu_prev_tests(void)
-{
-	VB2_DEBUG("Testing menu_prev...\n");
-
-	/* Valid action */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.key = VB_KEY_UP;
-	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_SUCCESS,
-		"valid action");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1,
-			MOCK_IGNORE);
-
-	/* Valid action with hidden mask */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->hidden_item_mask = 0x0a;  /* 0b01010 */
-	mock_ui_context.key = VB_KEY_UP;
-	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_SUCCESS,
-		"valid action with hidden mask");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 0,
-			MOCK_IGNORE);
-
-	/* Disabled mask does not affect menu_prev */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->disabled_item_mask = 0x0a;  /* 0b01010 */
-	mock_ui_context.key = VB_KEY_UP;
-	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_SUCCESS,
-		"valid action with disabled mask");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1,
-			MOCK_IGNORE);
-
-	/* Invalid action (blocked) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 0;
-	mock_ui_context.key = VB_KEY_UP;
-	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_SUCCESS,
-		"invalid action (blocked)");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 0,
-			MOCK_IGNORE);
-
-	/* Invalid action (blocked by mask) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->hidden_item_mask = 0x0b;  /* 0b01011 */
-	mock_ui_context.key = VB_KEY_UP;
-	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_SUCCESS,
-		"invalid action (blocked by mask)");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2,
-			MOCK_IGNORE);
-
-	/* Ignore volume-up when not DETACHABLE */
-	if (!DETACHABLE) {
-		reset_common_data();
-		mock_ui_context.state->screen = &mock_screen_menu;
-		mock_ui_context.state->selected_item = 2;
-		mock_ui_context.key = VB_BUTTON_VOL_UP_SHORT_PRESS;
-		TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_SUCCESS,
-			"ignore volume-up when not DETACHABLE");
-		screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2,
-				MOCK_IGNORE);
-	}
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void menu_next_tests(void)
-{
-	VB2_DEBUG("Testing menu_next...\n");
-
-	/* Valid action */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.key = VB_KEY_DOWN;
-	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_SUCCESS,
-		"valid action");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 3,
-			MOCK_IGNORE);
-
-	/* Valid action with hidden mask */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->hidden_item_mask = 0x0a;  /* 0b01010 */
-	mock_ui_context.key = VB_KEY_DOWN;
-	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_SUCCESS,
-		"valid action with hidden mask");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4,
-			MOCK_IGNORE);
-
-	/* Disabled mask does not affect menu_next */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->disabled_item_mask = 0x0a;  /* 0b01010 */
-	mock_ui_context.key = VB_KEY_DOWN;
-	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_SUCCESS,
-		"valid action with disabled mask");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 3,
-			MOCK_IGNORE);
-
-	/* Invalid action (blocked) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 4;
-	mock_ui_context.key = VB_KEY_DOWN;
-	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_SUCCESS,
-		"invalid action (blocked)");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4,
-			MOCK_IGNORE);
-
-	/* Invalid action (blocked by mask) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->hidden_item_mask = 0x1a;  /* 0b11010 */
-	mock_ui_context.key = VB_KEY_DOWN;
-	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_SUCCESS,
-		"invalid action (blocked by mask)");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2,
-			MOCK_IGNORE);
-
-	/* Ignore volume-down when not DETACHABLE */
-	if (!DETACHABLE) {
-		reset_common_data();
-		mock_ui_context.state->screen = &mock_screen_menu;
-		mock_ui_context.state->selected_item = 2;
-		mock_ui_context.key = VB_BUTTON_VOL_DOWN_SHORT_PRESS;
-		TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_SUCCESS,
-			"ignore volume-down when not DETACHABLE");
-		screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2,
-				MOCK_IGNORE);
-	}
-
-	VB2_DEBUG("...done.\n");
-}
-
-static vb2_error_t try_menu_select_helper(void)
-{
-	VB2_TRY(vb2_ui_menu_select(&mock_ui_context));
-	return VB2_ERROR_MOCK;
-}
-
-static void menu_select_tests(void)
-{
-	VB2_DEBUG("Testing menu_select...\n");
-
-	/* select action with no item screen */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_base;
-	mock_ui_context.key = VB_KEY_ENTER;
-	TEST_EQ(vb2_ui_menu_select(&mock_ui_context), VB2_SUCCESS,
-		"vb2_ui_menu_select with no item screen");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_BASE, 0,
-			MOCK_IGNORE);
-
-	/* VB2_TRY around item selection should return right away */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.key = VB_KEY_ENTER;
-	TEST_NEQ(try_menu_select_helper(), VB2_ERROR_MOCK,
-		"continued executing after VB2_TRY(menu_select)");
-
-	/* Try to select an item with a target (item 2) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.key = VB_KEY_ENTER;
-	TEST_EQ(vb2_ui_menu_select(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
-		"select an item with a target");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_TARGET2, 0,
-			MOCK_IGNORE);
-
-	/* Try to select an item with an action (item 3) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 3;
-	mock_ui_context.key = VB_KEY_ENTER;
-	TEST_EQ(vb2_ui_menu_select(&mock_ui_context),
-		VB2_SUCCESS, "select an item with an action");
-	TEST_EQ(mock_action_called, 1, "  action called once");
-
-	/* Try to select an item with neither targets nor actions (item 4) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 4;
-	mock_ui_context.key = VB_KEY_ENTER;
-	TEST_EQ(vb2_ui_menu_select(&mock_ui_context), VB2_SUCCESS,
-		"select an item with neither targets nor actions");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4,
-			MOCK_IGNORE);
-
-	/* Cannot select a disabled item (item 3) */
-	reset_common_data();
-	mock_ui_context.state->screen = &mock_screen_menu;
-	mock_ui_context.state->selected_item = 3;
-	mock_ui_context.state->disabled_item_mask = 0x08;  /* 0b01000 */
-	mock_ui_context.key = VB_KEY_ENTER;
-	TEST_EQ(vb2_ui_menu_select(&mock_ui_context), VB2_SUCCESS,
-		"cannot select a disabled item");
-	TEST_EQ(mock_action_called, 0, "  no action called");
-
-	/* Ignore power button short press when not DETACHABLE */
-	if (!DETACHABLE) {
-		reset_common_data();
-		mock_ui_context.state->screen = &mock_screen_menu;
-		mock_ui_context.state->selected_item = 1;
-		mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS;
-		TEST_EQ(vb2_ui_menu_select(&mock_ui_context), VB2_SUCCESS,
-			"ignore power button short press when not DETACHABLE");
-		screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1,
-				MOCK_IGNORE);
-	}
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void vb2_ui_developer_mode_boot_altfw_action_tests(void)
-{
-	VB2_DEBUG("Test developer mode boot alternate action...\n");
-
-	/* Not allowed: not in dev mode */
-	reset_common_data();
-	mock_dev_boot_altfw_allowed = 1;
-	TEST_EQ(vb2_ui_developer_mode_boot_altfw_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "not allowed: not in dev mode");
-	TEST_EQ(mock_ui_context.error_code, VB2_UI_ERROR_ALTFW_DISABLED,
-		"ui_error code is set");
-	TEST_EQ(mock_run_altfw_called, 0, "  vb2ex_run_altfw not called");
-
-	/* Not allowed: dev boot not allowed */
-	reset_common_data();
-	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
-	mock_dev_boot_allowed = 0;
-	mock_dev_boot_altfw_allowed = 1;
-	TEST_EQ(vb2_ui_developer_mode_boot_altfw_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "not allowed: dev boot not allowed");
-	TEST_EQ(mock_ui_context.error_code, VB2_UI_ERROR_ALTFW_DISABLED,
-		"ui_error code is set");
-	TEST_EQ(mock_run_altfw_called, 0, "  vb2ex_run_altfw not called");
-
-	/* Not allowed: boot altfw not allowed */
-	reset_common_data();
-	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
-	TEST_EQ(vb2_ui_developer_mode_boot_altfw_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "not allowed: boot altfw not allowed");
-	TEST_EQ(mock_ui_context.error_code, VB2_UI_ERROR_ALTFW_DISABLED,
-		"ui_error code is set");
-	TEST_EQ(mock_run_altfw_called, 0, "  vb2ex_run_altfw not called");
-
-	/* Allowed */
-	reset_common_data();
-	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
-	mock_dev_boot_altfw_allowed = 1;
-	mock_ui_context.state->selected_item = 2;
-	TEST_EQ(vb2_ui_developer_mode_boot_altfw_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "allowed");
-	TEST_EQ(mock_ui_context.error_code, VB2_UI_ERROR_ALTFW_FAILED,
-		"ui_error code is set");
-	TEST_EQ(mock_run_altfw_called, 1, "  vb2ex_run_altfw called once");
-	TEST_EQ(mock_altfw_last, 2, "  select bootloader #2");
-
-	/* CTRL+L = default bootloader */
-	reset_common_data();
-	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
-	mock_dev_boot_altfw_allowed = 1;
-	mock_ui_context.key = VB_KEY_CTRL('L');
-	mock_ui_context.state->selected_item = 4;  /* Ignored */
-	TEST_EQ(vb2_ui_developer_mode_boot_altfw_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "allowed: ctrl+l");
-	TEST_EQ(mock_ui_context.error_code, VB2_UI_ERROR_ALTFW_FAILED,
-		"ui_error code is set");
-	TEST_EQ(mock_run_altfw_called, 1, "  vb2ex_run_altfw called once");
-	TEST_EQ(mock_altfw_last, 0, "  select bootloader #0");
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void manual_recovery_action_tests(void)
-{
-	VB2_DEBUG("Testing manual recovery action...\n");
-
-	/* SUCCESS */
-	reset_common_data();
-	set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context), VB2_REQUEST_UI_EXIT,
-		"EXIT");
-	TEST_EQ(mock_get_screen_info_called, 0, "  no change_screen");
-
-	/* NO_DISK_FOUND */
-	reset_common_data();
-	set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "NO_DISK_FOUND");
-	screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_SELECT,
-			MOCK_IGNORE, MOCK_IGNORE);
-
-	/* NO_DISK_FOUND -> INVALID_KERNEL -> SUCCESS */
-	reset_common_data();
-	set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "NO_DISK_FOUND");
-	set_mock_vbtlk(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
-		       VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "INVALID_KERNEL");
-	set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context), VB2_REQUEST_UI_EXIT,
-		"EXIT");
-	screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_INVALID,
-			MOCK_IGNORE, MOCK_IGNORE);
-
-	/* INVALID_KERNEL */
-	reset_common_data();
-	set_mock_vbtlk(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
-		       VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "INVALID_KERNEL");
-	screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_INVALID,
-			MOCK_IGNORE, MOCK_IGNORE);
-
-	/* INVALID_KERNEL -> NO_DISK_FOUND -> SUCCESS */
-	reset_common_data();
-	set_mock_vbtlk(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
-		       VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "INVALID_KERNEL");
-	set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context),
-		VB2_REQUEST_UI_CONTINUE, "NO_DISK_FOUND");
-	set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(manual_recovery_action(&mock_ui_context), VB2_REQUEST_UI_EXIT,
-		"EXIT");
-	screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_SELECT,
-			MOCK_IGNORE, MOCK_IGNORE);
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void ui_loop_tests(void)
-{
-	int i;
-	const char *action_interfere_test_names[] = {
-		"hook all actions: screen action return SUCCESS",
-		"hook all actions: target action hooked return SUCCESS",
-		"hook all actions: global action return SUCCESS",
-	};
-
-	VB2_DEBUG("Testing ui_loop...\n");
-
-	/* Die if no root screen */
-	reset_common_data();
-	TEST_ABORT(ui_loop(ctx, MOCK_NO_SCREEN, NULL),
-		   "die if no root screen");
-	DISPLAYED_NO_EXTRA();
-
-	/* Shutdown if requested */
-	reset_common_data();
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, NULL),
-		VB2_REQUEST_SHUTDOWN, "shutdown if requested");
-	TEST_EQ(mock_calls_until_shutdown, 0, "  used up shutdown request");
-	DISPLAYED_EQ("mock_screen_base", MOCK_SCREEN_BASE, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Screen action */
-	reset_common_data();
-	mock_calls_until_shutdown = -1;
-	mock_action_countdown_limit = 10;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_ACTION, NULL),
-		VB2_SUCCESS, "screen action");
-	TEST_EQ(mock_action_called, 10, "  action called");
-
-	/* Global action */
-	reset_common_data();
-	mock_calls_until_shutdown = -1;
-	mock_action_countdown_limit = 10;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BLANK, mock_action_countdown),
-		VB2_SUCCESS, "global action");
-	TEST_EQ(mock_action_called, 10, "  action called");
-
-	/* Global action can change screen */
-	reset_common_data();
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BLANK, mock_action_screen_change),
-		VB2_REQUEST_SHUTDOWN, "global action can change screen");
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("change to mock_screen_base", MOCK_SCREEN_BASE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/*
-	 * Hook all actions, and receive SUCCESS from actions one by one
-	 * Action #0: screen action
-	 * Action #1: item target action
-	 * Action #2: global action
-	 */
-	for (i = 0; i <= 2; i++) {
-		reset_common_data();
-		add_mock_keypress(VB_KEY_ENTER);
-		mock_calls_until_shutdown = -1;
-		mock_action_flags |= (1 << i);
-		TEST_EQ(ui_loop(ctx, MOCK_SCREEN_ALL_ACTION, mock_action_flag2),
-			VB2_SUCCESS, action_interfere_test_names[i]);
-	}
-
-	/* KEY_UP, KEY_DOWN, and KEY_ENTER navigation */
-	reset_common_data();
-	add_mock_keypress(VB_KEY_UP);  /* (blocked) */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);  /* (blocked) */
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_MENU, NULL),
-		VB2_REQUEST_SHUTDOWN, "KEY_UP, KEY_DOWN, and KEY_ENTER");
-	DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 0,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 1,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 2,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 3,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 4,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 3,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 2,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("mock_screen_target_2", MOCK_SCREEN_TARGET2, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* For DETACHABLE */
-	if (DETACHABLE) {
-		reset_common_data();
-		add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS);
-		add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS);
-		TEST_EQ(ui_loop(ctx, MOCK_SCREEN_MENU, NULL),
-			VB2_REQUEST_SHUTDOWN, "DETACHABLE");
-		DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
-			     0, MOCK_IGNORE);
-		DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
-			     1, MOCK_IGNORE);
-		DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
-			     2, MOCK_IGNORE);
-		DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
-			     3, MOCK_IGNORE);
-		DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
-			     4, MOCK_IGNORE);
-		DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
-			     3, MOCK_IGNORE);
-		DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
-			     2, MOCK_IGNORE);
-		DISPLAYED_EQ("mock_screen_target_2", MOCK_SCREEN_TARGET2,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_NO_EXTRA();
-	}
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void ui_loop_delay_tests(void)
-{
-	VB2_DEBUG("Testing ui_loop delay...\n");
-
-	/* Sleep for 20 ms each iteration */
-	reset_common_data();
-	mock_calls_until_shutdown = 1;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep),
-		VB2_REQUEST_SHUTDOWN, "  sleep for 20 ms in each iteration");
-	TEST_EQ(mock_time_ms - mock_time_start_ms, KEY_DELAY_MS,
-		"  delay 20 ms in total");
-
-	/* Complement to 20 ms */
-	reset_common_data();
-	mock_calls_until_shutdown = 1;
-	mock_action_delay_ms = KEY_DELAY_MS / 2;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep),
-		VB2_REQUEST_SHUTDOWN, "  complement to 20 ms");
-	TEST_EQ(mock_time_ms - mock_time_start_ms, KEY_DELAY_MS,
-		"  delay 10 ms in total");
-
-	/* No extra sleep if an iteration takes longer than KEY_DELAY_MS */
-	reset_common_data();
-	mock_calls_until_shutdown = 1;
-	mock_action_delay_ms = 1234;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep),
-		VB2_REQUEST_SHUTDOWN, "  no extra sleep time");
-	TEST_EQ(mock_time_ms - mock_time_start_ms, mock_action_delay_ms,
-		"  no extra delay");
-
-	/* Integer overflow */
-	reset_common_data();
-	mock_calls_until_shutdown = 1;
-	mock_time_ms = UINT32_MAX;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep),
-		VB2_REQUEST_SHUTDOWN, "  integer overflow #1");
-	TEST_EQ(mock_time_ms - UINT32_MAX, KEY_DELAY_MS,
-		"  delay 20 ms in total");
-
-	reset_common_data();
-	mock_calls_until_shutdown = 1;
-	mock_time_ms = UINT32_MAX;
-	mock_action_delay_ms = KEY_DELAY_MS / 2;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep),
-		VB2_REQUEST_SHUTDOWN, "  integer overflow #2");
-	TEST_EQ(mock_time_ms - UINT32_MAX, KEY_DELAY_MS,
-		"  delay 10 ms in total");
-
-	reset_common_data();
-	mock_calls_until_shutdown = 1;
-	mock_time_ms = UINT32_MAX;
-	mock_action_delay_ms = 1234;
-	TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep),
-		VB2_REQUEST_SHUTDOWN, "  integer overflow #3");
-	TEST_EQ(mock_time_ms - UINT32_MAX, mock_action_delay_ms,
-		"  no extra delay");
-
-	VB2_DEBUG("...done.\n");
-}
-
-int main(void)
-{
-	/* Input actions */
-	menu_prev_tests();
-	menu_next_tests();
-	menu_select_tests();
-
-	/* Screen actions */
-	vb2_ui_developer_mode_boot_altfw_action_tests();
-
-	/* Global actions */
-	manual_recovery_action_tests();
-
-	/* Core UI loop */
-	ui_loop_tests();
-	ui_loop_delay_tests();
-
-	return gTestSuccess ? 0 : 255;
-}
diff --git a/tests/vb2_ui_tests.c b/tests/vb2_ui_tests.c
deleted file mode 100644
index 9a84a93..0000000
--- a/tests/vb2_ui_tests.c
+++ /dev/null
@@ -1,1922 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Tests for developer and recovery mode UIs.
- */
-
-#include "2api.h"
-#include "2common.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2struct.h"
-#include "2ui.h"
-#include "2ui_private.h"
-#include "test_common.h"
-#include "vboot_kernel.h"
-
-/* Fixed value for ignoring some checks */
-#define MOCK_IGNORE 0xffffu
-
-/* Fuzzy matches for check_time() */
-#define FUZZ_MS 200
-
-/* Mock data */
-/* TODO(b/156448738): Add tests for timer_disabled and error_code */
-struct display_call {
-	const struct vb2_screen_info *screen;
-	uint32_t locale_id;
-	uint32_t selected_item;
-	uint32_t disabled_item_mask;
-	uint32_t hidden_item_mask;
-	int timer_disabled;
-	uint32_t current_page;
-	enum vb2_ui_error error_code;
-} __attribute__((packed));
-
-struct beep_call {
-	uint32_t msec;
-	uint32_t frequency;
-	uint32_t time_expected;
-};
-
-static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
-	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
-static struct vb2_context *ctx;
-static struct vb2_shared_data *sd;
-static struct vb2_gbb_header gbb;
-
-static struct vb2_ui_context mock_ui_context;
-static struct vb2_screen_state mock_state;
-
-static struct display_call mock_displayed[64];
-static int mock_displayed_count;
-static int mock_displayed_i;
-
-static uint32_t mock_locale_count;
-
-static int mock_calls_until_shutdown;
-
-/* Iteration counter starts from 0
-   Mock inputs should response according to this */
-static int mock_iters;
-
-static uint32_t mock_key[64];
-static int mock_key_trusted[64];
-static int mock_key_total;
-
-static uint32_t mock_time_ms;
-static const uint32_t mock_time_start_ms = 31ULL * VB2_MSEC_PER_SEC;
-
-static struct beep_call mock_beep[8];
-static int mock_beep_count;
-static int mock_beep_total;
-
-static enum vb2_dev_default_boot_target mock_default_boot;
-static int mock_dev_boot_allowed;
-static int mock_dev_boot_altfw_allowed;
-static int mock_dev_boot_external_allowed;
-
-static int mock_run_altfw_called;
-static uint32_t mock_altfw_last;
-static uint32_t mock_altfw_count;
-
-static vb2_error_t mock_vbtlk_retval[32];
-static uint32_t mock_vbtlk_expected_flag[32];
-static int mock_vbtlk_total;
-
-static int mock_allow_recovery;
-
-/* mock_pp_* = mock data for physical presence button */
-static int mock_pp_pressed[64];
-static int mock_pp_pressed_total;
-
-static int mock_enable_dev_mode;
-
-#define MOCK_PREPARE_LOG_SIZE 32
-
-static int mock_snapshot_count;
-static char mock_prepare_log[64][MOCK_PREPARE_LOG_SIZE];
-static int mock_prepare_log_count;
-static uint32_t mock_log_page_count;
-
-static vb2_error_t mock_diag_storage_test_rv;
-
-static void add_mock_key(uint32_t press, int trusted)
-{
-	if (mock_key_total >= ARRAY_SIZE(mock_key) ||
-	    mock_key_total >= ARRAY_SIZE(mock_key_trusted)) {
-		TEST_TRUE(0, "  mock_key ran out of entries!");
-		return;
-	}
-
-	mock_key[mock_key_total] = press;
-	mock_key_trusted[mock_key_total] = trusted;
-	mock_key_total++;
-}
-
-static void add_mock_keypress(uint32_t press)
-{
-	add_mock_key(press, 0);
-}
-
-static void add_mock_vbtlk(vb2_error_t retval, uint32_t disk_flags)
-{
-	if (mock_vbtlk_total >= ARRAY_SIZE(mock_vbtlk_retval) ||
-	    mock_vbtlk_total >= ARRAY_SIZE(mock_vbtlk_expected_flag)) {
-		TEST_TRUE(0, "  mock_vbtlk ran out of entries!");
-		return;
-	}
-
-	mock_vbtlk_retval[mock_vbtlk_total] = retval;
-	mock_vbtlk_expected_flag[mock_vbtlk_total] = disk_flags;
-	mock_vbtlk_total++;
-}
-
-static void add_mock_pp_pressed(int pressed)
-{
-	if (mock_pp_pressed_total >= ARRAY_SIZE(mock_pp_pressed)) {
-		TEST_TRUE(0, "  mock_pp ran out of entries!");
-		return;
-	}
-
-	mock_pp_pressed[mock_pp_pressed_total++] = pressed;
-}
-
-static void extend_calls_until_shutdown(void)
-{
-	if (mock_calls_until_shutdown < mock_key_total)
-		mock_calls_until_shutdown = mock_key_total;
-	if (mock_calls_until_shutdown < mock_vbtlk_total)
-		mock_calls_until_shutdown = mock_vbtlk_total;
-	if (mock_calls_until_shutdown < mock_pp_pressed_total)
-		mock_calls_until_shutdown = mock_pp_pressed_total;
-	mock_calls_until_shutdown++;
-}
-
-static void displayed_eq(const char *text,
-			 enum vb2_screen screen,
-			 uint32_t locale_id,
-			 uint32_t selected_item,
-			 uint32_t disabled_item_mask,
-			 uint32_t hidden_item_mask,
-			 uint32_t current_page,
-			 int line)
-{
-	char text_info[32], text_buf[128];
-
-	sprintf(text_info, "(line #%d, displayed #%d)", line, mock_displayed_i);
-
-	if (mock_displayed_i >= mock_displayed_count) {
-		sprintf(text_buf, "  %s missing screen %s",
-			text_info, text);
-		TEST_TRUE(0, text_buf);
-		return;
-	}
-
-	if (screen != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s screen of %s", text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].screen->id, screen,
-			text_buf);
-	}
-	if (locale_id != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s locale_id of %s", text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].locale_id, locale_id,
-			text_buf);
-	}
-	if (selected_item != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s selected_item of %s",
-			text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].selected_item,
-			selected_item, text_buf);
-	}
-	if (disabled_item_mask != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s disabled_item_mask of %s",
-			text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].disabled_item_mask,
-			disabled_item_mask, text_buf);
-	}
-	if (hidden_item_mask != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s hidden_item_mask of %s",
-			text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].hidden_item_mask,
-			hidden_item_mask, text_buf);
-	}
-	if (current_page != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s current_page of %s",
-			text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].current_page,
-			current_page, text_buf);
-	}
-	mock_displayed_i++;
-}
-
-static void displayed_no_extra(int line)
-{
-	char text_info[32], text_buf[128];
-
-	sprintf(text_info, "(line #%d)", line);
-
-	if (mock_displayed_i == 0)
-		sprintf(text_buf, "  %s no screen", text_info);
-	else
-		sprintf(text_buf, "  %s no extra screens", text_info);
-	TEST_EQ(mock_displayed_count, mock_displayed_i, text_buf);
-}
-
-#define DISPLAYED_EQ(...) displayed_eq(__VA_ARGS__, __LINE__)
-
-#define DISPLAYED_PASS() \
-	displayed_eq("", MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, \
-		     MOCK_IGNORE, MOCK_IGNORE, __LINE__)
-
-#define DISPLAYED_NO_EXTRA() displayed_no_extra(__LINE__)
-
-static void expect_beep(uint32_t msec,
-			uint32_t frequency,
-			uint32_t time_expected)
-{
-	if (mock_beep_total >= ARRAY_SIZE(mock_beep)) {
-		TEST_TRUE(0, "  mock_beep ran out of entries!");
-		return;
-	}
-
-	mock_beep[mock_beep_total++] = (struct beep_call){
-		.msec = msec,
-		.frequency = frequency,
-		.time_expected = time_expected,
-	};
-}
-
-/* Check if the result time falls in range [expected, expected + FUZZ_MS) */
-static void check_time(uint32_t result, uint32_t expected, const char *desc)
-{
-	TEST_TRUE(result >= expected, desc);
-	TEST_TRUE(result - expected < FUZZ_MS, "  within FUZZ_MS");
-}
-
-/* Type of test to reset for */
-enum reset_type {
-	FOR_DEVELOPER,
-	FOR_BROKEN_RECOVERY,
-	FOR_MANUAL_RECOVERY,
-	FOR_DIAGNOSTICS,
-};
-
-/* Reset mock data (for use before each test) */
-static void reset_common_data(enum reset_type t)
-{
-	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
-		  "vb2api_init failed");
-
-	memset(&gbb, 0, sizeof(gbb));
-
-	vb2_nv_init(ctx);
-
-	sd = vb2_get_sd(ctx);
-	sd->status |= VB2_SD_STATUS_SECDATA_KERNEL_INIT;
-
-	if (t == FOR_DEVELOPER) {
-		ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
-		sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED;
-	}
-
-	/* Mock ui_context based on real screens */
-	memset(&mock_ui_context, 0, sizeof(mock_ui_context));
-	mock_ui_context.ctx = ctx;
-	mock_ui_context.state = &mock_state;
-
-	/* For vb2ex_display_ui */
-	memset(mock_displayed, 0, sizeof(mock_displayed));
-	mock_displayed_count = 0;
-	mock_displayed_i = 0;
-
-	/* For vb2ex_get_locale_count */
-	mock_locale_count = 1;
-
-	/* For check_shutdown_request */
-	if (t == FOR_DEVELOPER)
-		mock_calls_until_shutdown = 2000;  /* Larger than 30s */
-	else
-		mock_calls_until_shutdown = 10;
-
-	/* For iteration counter */
-	mock_iters = -1;  /* Accumulates at the beginning of iterations */
-
-	/* For VbExKeyboardRead */
-	memset(mock_key, 0, sizeof(mock_key));
-	memset(mock_key_trusted, 0, sizeof(mock_key_trusted));
-	mock_key_total = 0;
-
-	/* For vb2ex_mtime and vb2ex_msleep  */
-	mock_time_ms = mock_time_start_ms;
-
-	/* For vb2ex_beep */
-	memset(mock_beep, 0, sizeof(mock_beep));
-	mock_beep_count = 0;
-	mock_beep_total = 0;
-
-	/* For dev_boot* in 2misc.h */
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL;
-	mock_dev_boot_allowed = 1;
-	mock_dev_boot_altfw_allowed = 0;
-	mock_dev_boot_external_allowed = 1;
-
-	/* For vb2ex_run_altfw */
-	mock_run_altfw_called = 0;
-	mock_altfw_last = -100;
-	mock_altfw_count = 2;
-
-	/* For VbTryLoadKernel */
-	memset(mock_vbtlk_retval, 0, sizeof(mock_vbtlk_retval));
-	memset(mock_vbtlk_expected_flag, 0, sizeof(mock_vbtlk_expected_flag));
-	mock_vbtlk_total = 0;
-
-	/* For vb2_allow_recovery */
-	mock_allow_recovery = t == FOR_MANUAL_RECOVERY;
-
-	/* For vb2ex_physical_presence_pressed */
-	memset(mock_pp_pressed, 0, sizeof(mock_pp_pressed));
-	mock_pp_pressed_total = 0;
-
-	/* For vb2_enable_developer_mode */
-	mock_enable_dev_mode = 0;
-
-	/* For vb2ex_prepare_log_screen */
-	mock_snapshot_count = 0;
-	mock_prepare_log_count = 0;
-	mock_log_page_count = 1;
-
-	/* Avoid Iteration #0 */
-	add_mock_keypress(0);
-	if (t == FOR_MANUAL_RECOVERY)
-		add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND,
-			       VB_DISK_FLAG_REMOVABLE);
-	else
-		add_mock_vbtlk(VB2_ERROR_MOCK, 0);
-	add_mock_pp_pressed(0);
-
-	mock_diag_storage_test_rv = VB2_SUCCESS;
-}
-
-/* Mock functions */
-struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
-{
-	return &gbb;
-}
-
-vb2_error_t vb2ex_display_ui(enum vb2_screen screen,
-			     uint32_t locale_id,
-			     uint32_t selected_item,
-			     uint32_t disabled_item_mask,
-			     uint32_t hidden_item_mask,
-			     int timer_disabled,
-			     uint32_t current_page,
-			     enum vb2_ui_error error_code)
-{
-	struct display_call displayed = (struct display_call){
-		.screen = vb2_get_screen_info(screen),
-		.locale_id = locale_id,
-		.selected_item = selected_item,
-		.disabled_item_mask = disabled_item_mask,
-		.hidden_item_mask = hidden_item_mask,
-		.timer_disabled = timer_disabled,
-		.current_page = current_page,
-		.error_code = error_code,
-	};
-
-	/* Ignore repeated calls with same arguments */
-	if (mock_displayed_count > 0 &&
-	    !memcmp(&mock_displayed[mock_displayed_count - 1], &displayed,
-		    sizeof(struct display_call)))
-		return VB2_SUCCESS;
-
-	VB2_DEBUG("displayed %d: screen=%#x, locale_id=%u, selected_item=%u, "
-		  "disabled_item_mask=%#x, hidden_item_mask=%#x, "
-		  "timer_disabled=%d, current_page=%u, error=%#x\n",
-		  mock_displayed_count, screen, locale_id, selected_item,
-		  disabled_item_mask, hidden_item_mask,
-		  timer_disabled, current_page, error_code);
-
-	if (mock_displayed_count >= ARRAY_SIZE(mock_displayed)) {
-		TEST_TRUE(0, "  mock vb2ex_display_ui ran out of entries!");
-		return VB2_ERROR_MOCK;
-	}
-
-	mock_displayed[mock_displayed_count++] = displayed;
-
-	return VB2_SUCCESS;
-}
-
-uint32_t vb2ex_get_locale_count(void)
-{
-	return mock_locale_count;
-}
-
-uint32_t VbExIsShutdownRequested(void)
-{
-	if (mock_calls_until_shutdown < 0)  /* Never request shutdown */
-		return 0;
-	if (mock_calls_until_shutdown == 0)
-		return 1;
-	mock_calls_until_shutdown--;
-
-	return 0;
-}
-
-uint32_t VbExKeyboardRead(void)
-{
-	return VbExKeyboardReadWithFlags(NULL);
-}
-
-uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags)
-{
-	mock_iters++;
-	if (mock_iters < mock_key_total) {
-		if (key_flags != NULL) {
-			if (mock_key_trusted[mock_iters])
-				*key_flags = VB_KEY_FLAG_TRUSTED_KEYBOARD;
-			else
-				*key_flags = 0;
-		}
-		return mock_key[mock_iters];
-	}
-
-	return 0;
-}
-
-uint32_t vb2ex_mtime(void)
-{
-	return mock_time_ms;
-}
-
-void vb2ex_msleep(uint32_t msec)
-{
-	mock_time_ms += msec;
-}
-
-void vb2ex_beep(uint32_t msec, uint32_t frequency)
-{
-	struct beep_call *beep;
-	uint32_t cur_time = mock_time_ms - mock_time_start_ms;
-
-	VB2_DEBUG("beep %d: msec = %d, frequency = %d at %d msec\n",
-		  mock_beep_count, msec, frequency, cur_time);
-
-	if (mock_beep_total > 0) {
-		TEST_TRUE(mock_beep_count < mock_beep_total,
-			  "  too many beep calls!");
-
-		beep = &mock_beep[mock_beep_count];
-
-		VB2_DEBUG("beep expected: msec = %d, frequency = %d, "
-			  "at %d msec\n",
-			  beep->msec, beep->frequency, beep->time_expected);
-
-		TEST_EQ(msec, beep->msec, "  beep duration");
-		TEST_EQ(frequency, beep->frequency, "  beep frequency");
-		check_time(cur_time, beep->time_expected,
-			   "  beep started after expected time");
-	}
-
-	mock_time_ms += msec;
-	mock_beep_count++;
-}
-
-enum vb2_dev_default_boot_target vb2api_get_dev_default_boot_target(
-	struct vb2_context *c)
-{
-	return mock_default_boot;
-}
-
-int vb2_dev_boot_allowed(struct vb2_context *c)
-{
-	return mock_dev_boot_allowed;
-}
-
-int vb2_dev_boot_altfw_allowed(struct vb2_context *c)
-{
-	return mock_dev_boot_altfw_allowed;
-}
-
-int vb2_dev_boot_external_allowed(struct vb2_context *c)
-{
-	return mock_dev_boot_external_allowed;
-}
-
-vb2_error_t vb2ex_run_altfw(uint32_t altfw_id)
-{
-	mock_run_altfw_called++;
-	mock_altfw_last = altfw_id;
-
-	return VB2_SUCCESS;
-}
-
-uint32_t vb2ex_get_altfw_count(void)
-{
-	return mock_altfw_count;
-}
-
-vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t disk_flags)
-{
-	int i = mock_iters;
-
-	/* Return last entry if called too many times */
-	if (i >= mock_vbtlk_total)
-		i = mock_vbtlk_total - 1;
-
-	TEST_EQ(mock_vbtlk_expected_flag[i], disk_flags,
-		"  unexpected disk_flags");
-
-	return mock_vbtlk_retval[i];
-}
-
-int vb2_allow_recovery(struct vb2_context *c)
-{
-	return mock_allow_recovery;
-}
-
-int vb2ex_physical_presence_pressed(void)
-{
-	if (mock_iters >= mock_pp_pressed_total)
-		return 0;
-
-	return mock_pp_pressed[mock_iters];
-}
-
-void vb2_enable_developer_mode(struct vb2_context *c)
-{
-	mock_enable_dev_mode = 1;
-}
-
-const char *vb2ex_get_debug_info(struct vb2_context *c)
-{
-	return "mocked debug info";
-}
-
-const char *vb2ex_get_firmware_log(int reset)
-{
-	static char mock_firmware_log_buf[MOCK_PREPARE_LOG_SIZE];
-	if (reset)
-		mock_snapshot_count++;
-	snprintf(mock_firmware_log_buf, MOCK_PREPARE_LOG_SIZE,
-		 "%d", mock_snapshot_count);
-	return mock_firmware_log_buf;
-}
-
-uint32_t vb2ex_prepare_log_screen(enum vb2_screen screen, uint32_t locale_id,
-				  const char *str)
-{
-	if (mock_prepare_log_count < ARRAY_SIZE(mock_prepare_log))
-		strncpy(mock_prepare_log[mock_prepare_log_count],
-			str, MOCK_PREPARE_LOG_SIZE);
-	mock_prepare_log_count++;
-
-	return mock_log_page_count;
-}
-
-vb2_error_t vb2ex_diag_get_storage_test_log(const char **log)
-{
-	return mock_diag_storage_test_rv;
-}
-
-/* Tests */
-static void developer_tests(void)
-{
-	VB2_DEBUG("Testing developer mode...\n");
-
-	/* Power button short pressed = shutdown request */
-	if (!DETACHABLE) {
-		reset_common_data(FOR_DEVELOPER);
-		add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS);
-		mock_calls_until_shutdown = -1;
-		TEST_EQ(vb2_developer_menu(ctx),
-			VB2_REQUEST_SHUTDOWN,
-			"power button short pressed = shutdown");
-	}
-
-	/* Proceed to internal disk after timeout */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	expect_beep(250, 400, DEV_DELAY_BEEP1_MS);
-	expect_beep(250, 400, DEV_DELAY_BEEP2_MS);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"proceed to internal disk after timeout");
-	check_time(mock_time_ms - mock_time_start_ms, DEV_DELAY_NORMAL_MS,
-		   "  finished delay");
-	TEST_EQ(mock_beep_count, 2, "  beeped twice");
-	TEST_TRUE(mock_iters >= mock_vbtlk_total, "  used up mock_vbtlk");
-
-	/* Don't proceed to internal disk after timeout (dev mode disallowed) */
-	reset_common_data(FOR_DEVELOPER);
-	mock_dev_boot_allowed = 0;
-	TEST_EQ(ui_loop(ctx, VB2_SCREEN_DEVELOPER_MODE, NULL),
-		VB2_REQUEST_SHUTDOWN,
-		"do not proceed to internal disk after timeout "
-		"(dev mode disallowed)");
-
-	/* Use short delay */
-	reset_common_data(FOR_DEVELOPER);
-	gbb.flags |= VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY;
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"use short delay");
-	check_time(mock_time_ms - mock_time_start_ms, DEV_DELAY_SHORT_MS,
-		   "  finished delay");
-	TEST_EQ(mock_beep_count, 0, "  never beeped");
-
-	/* Stop timer on any user input: normal delay */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress('A');
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"stop timer on any user input: normal delay");
-	TEST_TRUE(mock_time_ms - mock_time_start_ms > DEV_DELAY_NORMAL_MS,
-		  "  delay aborted");
-	TEST_EQ(mock_calls_until_shutdown, 0, "  loop forever");
-	TEST_EQ(mock_beep_count, 0, "  never beeped");
-
-	/* Stop timer on any user input: short delay */
-	reset_common_data(FOR_DEVELOPER);
-	gbb.flags |= VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY;
-	add_mock_keypress('A');
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"stop timer on any user input: short delay");
-	TEST_TRUE(mock_time_ms - mock_time_start_ms > DEV_DELAY_SHORT_MS,
-		  "  delay aborted");
-	TEST_EQ(mock_calls_until_shutdown, 0, "  loop forever");
-	TEST_EQ(mock_beep_count, 0, "  never beeped");
-
-	/* If fail to load internal disk, don't boot */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_ERROR_LK_NO_DISK_FOUND,
-		"if fail to load internal disk, don't boot");
-
-	/* Select boot internal in dev menu */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"select boot internal in dev menu");
-
-	/* Ctrl+U = boot external */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_CTRL('U'));
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"ctrl+u = boot external");
-
-	/* Ctrl+D = boot internal */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_CTRL('D'));
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"ctrl+d = boot internal");
-
-	/* VB_BUTTON_VOL_DOWN_LONG_PRESS = boot internal */
-	if (DETACHABLE) {
-		reset_common_data(FOR_DEVELOPER);
-		add_mock_keypress(VB_BUTTON_VOL_DOWN_LONG_PRESS);
-		add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-		TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-			"VB_BUTTON_VOL_DOWN_LONG_PRESS = boot internal");
-	}
-
-	/* Proceed to external disk after timeout */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
-	expect_beep(250, 400, DEV_DELAY_BEEP1_MS);
-	expect_beep(250, 400, DEV_DELAY_BEEP2_MS);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"proceed to external disk after timeout");
-	check_time(mock_time_ms - mock_time_start_ms, DEV_DELAY_NORMAL_MS,
-		   "  finished delay");
-	TEST_EQ(mock_beep_count, 2, "  beeped twice");
-	TEST_TRUE(mock_iters >= mock_vbtlk_total, "  used up mock_vbtlk");
-
-	/* Default boot from external not allowed, don't boot */
-	reset_common_data(FOR_DEVELOPER);
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
-	mock_dev_boot_external_allowed = 0;
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"default boot from external disk not allowed, don't boot");
-
-	/* Don't proceed to external disk after timeout (dev mode disallowed) */
-	reset_common_data(FOR_DEVELOPER);
-	mock_dev_boot_allowed = 0;
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
-	TEST_EQ(ui_loop(ctx, VB2_SCREEN_DEVELOPER_MODE, NULL),
-		VB2_REQUEST_SHUTDOWN,
-		"do not proceed to external disk after timeout "
-		"(dev mode disallowed)");
-
-	/* If no external disk, don't boot */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"if no external disk, don't boot");
-
-	/* Select boot external in dev menu */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"select boot external in dev menu");
-
-	/* Ctrl+L = boot altfw (allowed) */
-	reset_common_data(FOR_DEVELOPER);
-	mock_dev_boot_altfw_allowed = 1;
-	add_mock_keypress(VB_KEY_CTRL('L'));
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"ctrl+l = boot altfw");
-	TEST_EQ(mock_run_altfw_called, 1, "  vb2ex_run_altfw called");
-
-	/* Ctrl+L = boot altfw (disallowed) */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_CTRL('L'));
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"ctrl+l = boot altfw");
-	TEST_EQ(mock_run_altfw_called, 0,
-		"  vb2ex_run_altfw not called");
-
-	/* VB_BUTTON_VOL_UP_LONG_PRESS = boot external */
-	if (DETACHABLE) {
-		reset_common_data(FOR_DEVELOPER);
-		add_mock_keypress(VB_BUTTON_VOL_UP_LONG_PRESS);
-		add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-		TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-			"VB_BUTTON_VOL_UP_LONG_PRESS = boot external");
-	}
-
-	/* Select to_norm in dev menu and confirm */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_REBOOT,
-		"select to_norm in dev menu and confirm");
-	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1,
-		"  disable dev request");
-
-	/* Select to_norm in dev menu and confirm (dev mode disallowed) */
-	reset_common_data(FOR_DEVELOPER);
-	mock_dev_boot_allowed = 0;
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(ui_loop(ctx, VB2_SCREEN_DEVELOPER_MODE, NULL),
-		VB2_REQUEST_REBOOT,
-		"select to_norm in dev menu and confirm (dev mode disallowed)");
-	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1,
-		"  disable dev request");
-
-	/* Select to_norm in dev menu and cancel */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"select to_norm in dev menu and cancel");
-	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 0,
-		"  disable dev request");
-
-	/* Ctrl+S = to_norm */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_CTRL('S'));
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_REBOOT,
-		"ctrl+s = to_norm");
-	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1,
-		"  disable dev request");
-
-	/* Dev mode forced by GBB flag */
-	reset_common_data(FOR_DEVELOPER);
-	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
-	add_mock_keypress(VB_KEY_CTRL('S'));
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"dev mode forced by GBB flag");
-	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 0,
-		"  disable dev request");
-
-	/* Power off */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	/* Navigate to the bottom most menu item */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"select power off");
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void broken_recovery_tests(void)
-{
-	VB2_DEBUG("Testing broken recovery mode...\n");
-
-	/* Power button short pressed = shutdown request */
-	if (!DETACHABLE) {
-		reset_common_data(FOR_BROKEN_RECOVERY);
-		add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS);
-		mock_calls_until_shutdown = -1;
-		TEST_EQ(vb2_broken_recovery_menu(ctx),
-			VB2_REQUEST_SHUTDOWN,
-			"power button short pressed = shutdown");
-	}
-
-	/* Shortcuts that are always ignored in BROKEN */
-	reset_common_data(FOR_BROKEN_RECOVERY);
-	add_mock_key(VB_KEY_CTRL('D'), 1);
-	add_mock_key(VB_KEY_CTRL('U'), 1);
-	add_mock_key(VB_KEY_CTRL('L'), 1);
-	add_mock_key(VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS, 1);
-	add_mock_key(VB_BUTTON_VOL_UP_LONG_PRESS, 1);
-	add_mock_key(VB_BUTTON_VOL_DOWN_LONG_PRESS, 1);
-	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"Shortcuts ignored in BROKEN");
-	TEST_EQ(mock_calls_until_shutdown, 0, "  loop forever");
-	TEST_EQ(mock_displayed_count, 1, "  root screen only");
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void manual_recovery_tests(void)
-{
-	VB2_DEBUG("Testing manual recovery mode...\n");
-
-	/* Timeout, shutdown */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"timeout, shutdown");
-	TEST_EQ(mock_displayed_count, 1, "  root screen only");
-
-	/* Power button short pressed = shutdown request */
-	if (!DETACHABLE) {
-		reset_common_data(FOR_MANUAL_RECOVERY);
-		add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS);
-		TEST_EQ(vb2_manual_recovery_menu(ctx),
-			VB2_REQUEST_SHUTDOWN,
-			"power button short pressed = shutdown");
-	}
-
-	/* Boots if we have a valid image on first try */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_SUCCESS,
-		"boots if valid on first try");
-
-	/* Boots eventually if we get a valid image later */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_SUCCESS,
-		"boots after valid image appears");
-
-	/* Invalid image, then remove, then valid image */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_SUCCESS,
-		"boots after valid image appears");
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("recovery invalid", VB2_SCREEN_RECOVERY_INVALID,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Ctrl+D = to_dev; space = cancel */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_key(VB_KEY_CTRL('D'), 1);
-	add_mock_keypress(' ');
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"ctrl+d = to_dev; space = cancel");
-	TEST_EQ(mock_enable_dev_mode, 0, "  dev mode not enabled");
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Cancel to_dev transition */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_key(VB_KEY_CTRL('D'), 1);
-	if (PHYSICAL_PRESENCE_KEYBOARD)
-		add_mock_key(VB_KEY_DOWN, 1);
-	add_mock_key(VB_KEY_ENTER, 1);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"cancel to_dev transition");
-	TEST_EQ(mock_enable_dev_mode, 0, "  dev mode not enabled");
-
-	/* Confirm to_dev transition */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_key(VB_KEY_CTRL('D'), 1);
-	if (PHYSICAL_PRESENCE_KEYBOARD) {
-		add_mock_key(VB_KEY_ENTER, 1);
-	} else {
-		add_mock_pp_pressed(0);
-		add_mock_pp_pressed(1);
-		add_mock_pp_pressed(1);
-		add_mock_pp_pressed(0);
-	}
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_REBOOT_EC_TO_RO,
-		"confirm to_dev transition");
-	if (!PHYSICAL_PRESENCE_KEYBOARD)
-		TEST_TRUE(mock_iters >= mock_pp_pressed_total - 1,
-			  "  used up mock_pp_pressed");
-	TEST_EQ(mock_enable_dev_mode, 1, "  dev mode enabled");
-
-	/* Cannot confirm physical presence by untrusted keyboard */
-	if (PHYSICAL_PRESENCE_KEYBOARD) {
-		reset_common_data(FOR_MANUAL_RECOVERY);
-		add_mock_key(VB_KEY_CTRL('D'), 1);
-		add_mock_key(VB_KEY_ENTER, 0);
-		TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-			"cannot confirm physical presence"
-			" by untrusted keyboard");
-		TEST_EQ(mock_enable_dev_mode, 0, "  dev mode not enabled");
-	}
-
-	/* Cannot enable dev mode if already enabled */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED;
-	add_mock_key(VB_KEY_CTRL('D'), 1);
-	if (PHYSICAL_PRESENCE_KEYBOARD) {
-		add_mock_key(VB_KEY_ENTER, 1);
-	} else {
-		add_mock_pp_pressed(0);
-		add_mock_pp_pressed(1);
-		add_mock_pp_pressed(0);
-	}
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"cannot enable dev mode if already enabled");
-	TEST_EQ(mock_enable_dev_mode, 0, "  dev mode already on");
-
-	/* Physical presence button tests */
-	if (!PHYSICAL_PRESENCE_KEYBOARD) {
-		/* Physical presence button stuck? */
-		reset_common_data(FOR_MANUAL_RECOVERY);
-		add_mock_key(VB_KEY_CTRL('D'), 1);
-		add_mock_pp_pressed(1);  /* Hold since boot */
-		add_mock_pp_pressed(0);
-		TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-			"physical presence button stuck?");
-		TEST_EQ(mock_enable_dev_mode, 0, "  dev mode not enabled");
-		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_NO_EXTRA();
-
-		/* Button stuck, enter to_dev again */
-		reset_common_data(FOR_MANUAL_RECOVERY);
-		add_mock_key(VB_KEY_CTRL('D'), 1);
-		add_mock_key(VB_KEY_CTRL('D'), 1);
-		add_mock_pp_pressed(1);  /* Hold since boot */
-		add_mock_pp_pressed(0);
-		add_mock_pp_pressed(1);  /* Press again */
-		add_mock_pp_pressed(0);
-		TEST_EQ(vb2_manual_recovery_menu(ctx),
-			VB2_REQUEST_REBOOT_EC_TO_RO,
-			"button stuck, enter to_dev again");
-		TEST_TRUE(mock_iters >= mock_pp_pressed_total - 1,
-			  "  used up mock_pp_pressed");
-		TEST_EQ(mock_enable_dev_mode, 1, "  dev mode enabled");
-		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_NO_EXTRA();
-
-		/* Cancel with holding pp button, enter again */
-		reset_common_data(FOR_MANUAL_RECOVERY);
-		/* Enter to_dev */
-		add_mock_key(VB_KEY_CTRL('D'), 1);
-		add_mock_pp_pressed(0);
-		/* Press pp button */
-		add_mock_keypress(0);
-		add_mock_pp_pressed(1);
-		/* Space = back */
-		add_mock_keypress(' ');
-		add_mock_pp_pressed(1);
-		/* Wait */
-		add_mock_keypress(0);
-		add_mock_pp_pressed(0);
-		/* Enter to_dev again */
-		add_mock_key(VB_KEY_CTRL('D'), 1);
-		add_mock_pp_pressed(0);
-		/* Press pp button again */
-		add_mock_pp_pressed(1);
-		/* Release */
-		add_mock_pp_pressed(0);
-		TEST_EQ(vb2_manual_recovery_menu(ctx),
-			VB2_REQUEST_REBOOT_EC_TO_RO,
-			"cancel with holding pp button, enter again");
-		TEST_TRUE(mock_iters >= mock_pp_pressed_total - 1,
-			  "  used up mock_pp_pressed");
-		TEST_EQ(mock_enable_dev_mode, 1, "  dev mode enabled");
-		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
-			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE, MOCK_IGNORE);
-		DISPLAYED_NO_EXTRA();
-	}
-
-	/* Enter diagnostics */
-	if (DIAGNOSTIC_UI) {
-		/* Launch diagnostics is inside manual recovery */
-		reset_common_data(FOR_MANUAL_RECOVERY);
-		add_mock_keypress(VB_KEY_DOWN);
-		add_mock_keypress(VB_KEY_DOWN);
-		add_mock_keypress(VB_KEY_ENTER);
-		TEST_EQ(vb2_manual_recovery_menu(ctx),
-			VB2_REQUEST_REBOOT,
-			"Reboot immediately after request diagnostics");
-		TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 1,
-			"VB2_NV_DIAG_REQUEST is set");
-	}
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void language_selection_tests(void)
-{
-	VB2_DEBUG("Testing language selection...\n");
-
-	/* Enter language menu and change language */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	mock_locale_count = 100;
-	vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, 23);
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);	/* select language */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);	/* select locale 24 */
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"change language");
-	DISPLAYED_EQ("RECOVERY_SELECT default", VB2_SCREEN_RECOVERY_SELECT,
-		     23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("RECOVERY_SELECT lang", VB2_SCREEN_RECOVERY_SELECT,
-		     23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("LANGUAGE_SELECT 23", VB2_SCREEN_LANGUAGE_SELECT,
-		     23, 23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("LANGUAGE_SELECT 24", VB2_SCREEN_LANGUAGE_SELECT,
-		     23, 24, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("RECOVERY_SELECT new locale", VB2_SCREEN_RECOVERY_SELECT,
-		     24, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-	TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 24,
-		"  locale 24 saved to nvdata");
-
-	/* Locale count = 0 */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	mock_locale_count = 0;
-	vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, 23);
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);	/* select language */
-	add_mock_keypress(VB_KEY_ENTER);	/* select locale 0 */
-	add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"enter language menu");
-	DISPLAYED_EQ("RECOVERY_SELECT default", VB2_SCREEN_RECOVERY_SELECT,
-		     23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("RECOVERY_SELECT lang", VB2_SCREEN_RECOVERY_SELECT,
-		     23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("LANGUAGE_SELECT index 0", VB2_SCREEN_LANGUAGE_SELECT,
-		     23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("RECOVERY_SELECT locale 0", VB2_SCREEN_RECOVERY_SELECT,
-		     0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void debug_info_tests(void)
-{
-	VB2_DEBUG("Testing debug info screen...\n");
-
-	/* Tab = debug info for all menus */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress('\t');
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"tab = debug info in dev mode");
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	reset_common_data(FOR_BROKEN_RECOVERY);
-	add_mock_keypress('\t');
-	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"tab = debug info in broken recovery mode");
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_keypress('\t');
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"tab = debug info in manual recovery mode");
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Failed to enter debug info */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	mock_log_page_count = 0;
-	add_mock_keypress('\t');
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"failed to enter debug info");
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();  /* error code */
-	DISPLAYED_NO_EXTRA();
-
-	/* Get a one-page debug info */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_keypress('\t');
-	add_mock_keypress(VB_KEY_ENTER);  /* back */
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"get a one-page debug info");
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 3, 0x6, 0x0, 0);
-	DISPLAYED_EQ("back to root screen", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Get a three-page debug info and navigate */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	mock_log_page_count = 3;
-	add_mock_keypress('\t');
-	add_mock_keypress(VB_KEY_ENTER);  /* page 0, select on page down */
-	add_mock_keypress(VB_KEY_ENTER);  /* page 1, select on page down */
-	add_mock_keypress(VB_KEY_UP);	  /* page 2, select on page down */
-	add_mock_keypress(VB_KEY_ENTER);  /* page 2, select on page up */
-	add_mock_keypress(VB_KEY_ENTER);  /* page 1, select on page up */
-	add_mock_keypress(VB_KEY_DOWN);	  /* page 0, select on page up */
-	add_mock_keypress(VB_KEY_ENTER);  /* page 0, select on page down */
-	add_mock_keypress(VB_KEY_DOWN);	  /* page 1, select on page down */
-	add_mock_keypress(VB_KEY_ENTER);  /* page 1, select on back */
-	extend_calls_until_shutdown();
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"get a three-page debug info and navigate");
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x2, 0x0, 0);
-	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x0, 0x0, 1);
-	DISPLAYED_EQ("debug info page #2", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x4, 0x0, 2);
-	DISPLAYED_EQ("debug info page #2", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 1, 0x4, 0x0, 2);
-	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 1, 0x0, 0x0, 1);
-	DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 1, 0x2, 0x0, 0);
-	DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x2, 0x0, 0);
-	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x0, 0x0, 1);
-	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 3, 0x0, 0x0, 1);
-	DISPLAYED_EQ("back to root screen", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void firmware_log_tests(void)
-{
-	VB2_DEBUG("Testing firmware log screens...\n");
-
-	/* Get firmware log */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	if (DIAGNOSTIC_UI)
-		add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"get firmware log");
-	TEST_EQ(mock_prepare_log_count, 1,
-		"  prepared firmware log once");
-	TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0,
-		"  got correct firmware log");
-
-	/* Enter firmware log screen again will reacquire a newer one */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	if (DIAGNOSTIC_UI)
-		add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"enter the screen again and reacquire a new log");
-	TEST_EQ(mock_prepare_log_count, 2,
-		"  prepared firmware log twice");
-	TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0,
-		"  got correct firmware log");
-	TEST_EQ(strcmp(mock_prepare_log[1], "2"), 0,
-		"  got a new firmware log");
-
-	/* Back to firmware log screen again will not reacquire a newer one */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	if (DIAGNOSTIC_UI)
-		add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress('\t');  /* enter debug info screen */
-	add_mock_keypress(VB_KEY_ESC);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"back to the screen and do not reacquire a new log");
-	TEST_EQ(mock_prepare_log_count, 3,
-		"  prepared firmware log three times");
-	TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0,
-		"  got correct firmware log");
-	/* Skip entry #1 which is for preparing debug info */
-	TEST_EQ(strcmp(mock_prepare_log[2], "1"), 0,
-		"  got the same firmware log");
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void developer_screen_tests(void)
-{
-	VB2_DEBUG("Testing developer mode screens...\n");
-
-	/* Dev mode: default selected item */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: set default selection to boot internal");
-	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: set default selection to boot external");
-	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-
-	/* Dev mode: disabled and hidden item mask */
-	reset_common_data(FOR_DEVELOPER);
-	mock_dev_boot_altfw_allowed = 1;
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: no disabled or hidden item");
-	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
-
-	reset_common_data(FOR_DEVELOPER);
-	mock_dev_boot_altfw_allowed = 1;
-	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: hide to_norm item");
-	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE);
-
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	mock_dev_boot_external_allowed = 0;
-	mock_dev_boot_altfw_allowed = 1;
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: hide boot external");
-	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x8, MOCK_IGNORE);
-
-	/* Dev mode screen */
-	reset_common_data(FOR_DEVELOPER);  /* Select #2 by default */
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	/* #0: Language menu */
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: Return to secure mode */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #2: Boot internal */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen");
-	/* #0: Language menu */
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #1: Return to secure mode */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#1: return to secure mode", VB2_SCREEN_DEVELOPER_TO_NORM,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #2: Boot internal */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	VB2_DEBUG("#2: boot internal (no extra screen)\n");
-	DISPLAYED_NO_EXTRA();
-
-	reset_common_data(FOR_DEVELOPER);  /* Select #3 by default */
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
-	mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
-	/* #3: Boot external */
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen");
-	/* #3: Boot external */
-	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	VB2_DEBUG("#3: boot external (no extra screen)\n");
-	DISPLAYED_NO_EXTRA();
-
-	reset_common_data(FOR_DEVELOPER);  /* Select #2 by default */
-	mock_dev_boot_altfw_allowed = 1;
-	/* #4: Alternate boot */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"dev mode screen");
-	TEST_EQ(mock_run_altfw_called, 1, "  vb2ex_run_altfw called");
-
-	reset_common_data(FOR_DEVELOPER);  /* Select #2 by default */
-	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
-	/* #5: Advanced options */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* End of menu */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);  /* Blocked */
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"dev mode screen");
-	/* #5: Advanced options */
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#4: advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* End of menu */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("end of menu", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 6, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Advanced options screen: disabled and hidden item mask */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"advanced options screen: hide to_dev");
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE);
-
-	/* Advanced options screen */
-	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #0: Language menu */
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: (Hidden) */
-	/* #2: Debug info */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #3: Firmware log */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #4: Back */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* End of menu */
-	add_mock_keypress(VB_KEY_ENTER);
-	extend_calls_until_shutdown();
-	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"advanced options screen");
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	/* #0: Language menu */
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #1: (Hidden) */
-	/* #2: Debug info */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #3: Firmware log */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #4: Back */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#4: back", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* End of menu */
-	DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void broken_recovery_screen_tests(void)
-{
-	/* Broken screen: disabled and hidden item mask */
-	reset_common_data(FOR_BROKEN_RECOVERY);
-	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"broken screen: no disabled and hidden item mask");
-	DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
-
-	/* Broken screen */
-	reset_common_data(FOR_BROKEN_RECOVERY);
-	/* #0: Language menu */
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: Advanced options */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* End of menu */
-	add_mock_keypress(VB_KEY_ESC);
-	extend_calls_until_shutdown();
-	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"broken screen");
-	/* #0: Language menu */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #1: Advanced options */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#1: advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* End of menu */
-	DISPLAYED_EQ("end of menu", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Advanced options screen: disabled and hidden item mask */
-	reset_common_data(FOR_BROKEN_RECOVERY);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"advanced options screen: hide to_dev item");
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE);
-
-	/* Advanced options screen */
-	reset_common_data(FOR_BROKEN_RECOVERY);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #0: Language menu */
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: (Hidden) */
-	/* #2: Debug info */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #3: Firmware log */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #4: Back */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* End of menu */
-	add_mock_keypress(VB_KEY_ENTER);
-	extend_calls_until_shutdown();
-	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"advanced options screen");
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	/* #0: Language menu */
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #1: (Hidden) */
-	/* #2: Debug info */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #3: Firmware log */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #4: Back */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#4: back", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* End of menu */
-	DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void manual_recovery_screen_tests(void)
-{
-	/* Recovery select screen: disabled and hidden item mask */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		DIAGNOSTIC_UI ?
-			"recovery select screen: no disabled or hidden item" :
-			"recovery select screen: hide `launch diag`");
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, DIAGNOSTIC_UI ? 0x0 : 0x8,
-		     MOCK_IGNORE);
-
-	/* Recovery select screen */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	/* #0: Language menu */
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: Phone recovery */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #2: External disk recovery */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	/* #3: Launch diagnostics */
-	if (DIAGNOSTIC_UI)
-		add_mock_keypress(VB_KEY_DOWN);
-	/* #4: Advanced options */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* End of menu */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);  /* Blocked */
-	extend_calls_until_shutdown();
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"recovery select screen");
-	/* #0: Language menu */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #1: Phone recovery */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#1: phone recovery", VB2_SCREEN_RECOVERY_PHONE_STEP1,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #2: External disk recovery */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#2: disk recovery", VB2_SCREEN_RECOVERY_DISK_STEP1,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	/* #3: Launch diagnostics */
-	if (DIAGNOSTIC_UI)
-		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-			MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	/* #4: Advanced options */
-	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-
-	DISPLAYED_EQ("#3: advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* End of menu */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("end of menu", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Advanced options screen: disabled and hidden item mask */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	if (DIAGNOSTIC_UI)
-		add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"advanced options screen: no disabled or hidden item");
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	if (DIAGNOSTIC_UI)
-		DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
-
-	/* Advanced options screen */
-	reset_common_data(FOR_MANUAL_RECOVERY);
-	/* #0: Language menu */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_DOWN);
-	if (DIAGNOSTIC_UI)
-		add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: Enable dev mode */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #2: Debug info */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #3: Firmware log */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* #4: Back */
-	add_mock_keypress(VB_KEY_ESC);
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	/* End of menu */
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_DOWN);
-	extend_calls_until_shutdown();
-	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"advanced options screen");
-	DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	if (DIAGNOSTIC_UI)
-		DISPLAYED_PASS();
-	DISPLAYED_PASS();
-	/* #0: Language menu */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #1: Enable dev mode */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#1: enable dev mode", VB2_SCREEN_RECOVERY_TO_DEV,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #2: Debug info */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #3: Firmware log */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* #4: Back */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#4: back", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	/* End of menu */
-	DISPLAYED_PASS();
-	DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void diagnostics_screen_tests(void)
-{
-	VB2_DEBUG("Testing diagnostic screens...\n");
-
-	/* Diagnostics screen: disabled and hidden item mask */
-	reset_common_data(FOR_DIAGNOSTICS);
-	TEST_EQ(vb2_diagnostic_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"diagnostic screen: no disabled or hidden item");
-	DISPLAYED_EQ("diagnostic menu", VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE,
-		     MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
-
-	/* Diagnostics screen */
-	reset_common_data(FOR_DIAGNOSTICS);
-
-	/* #0: Language menu */
-	add_mock_keypress(VB_KEY_UP);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	/* #1: Storage health screen */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	/* #2: Short storage self-test screen */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	/* #3: Extended storage self-test screen */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	/* #4: Quick memory test screen */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	/* #5: Full memory test screen */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	add_mock_keypress(VB_KEY_ESC);
-	/* #6: Power off (End of menu) */
-	add_mock_keypress(VB_KEY_DOWN);
-	add_mock_keypress(VB_KEY_ENTER);
-	mock_calls_until_shutdown = -1;
-	TEST_EQ(vb2_diagnostic_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"diagnostic screen");
-
-	DISPLAYED_EQ("default on first button of menu", VB2_SCREEN_DIAGNOSTICS,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	/* #0: Language menu */
-	DISPLAYED_EQ("language selection", VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE,
-		     0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-		     MOCK_IGNORE);
-	DISPLAYED_PASS();
-	/* #1: Storage health screen */
-	DISPLAYED_EQ("storage health button", VB2_SCREEN_DIAGNOSTICS,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#1: storage screen",
-		     VB2_SCREEN_DIAGNOSTICS_STORAGE_HEALTH, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_PASS();
-	/* #2: Short storage self-test screen */
-	DISPLAYED_EQ("short storage self-test button", VB2_SCREEN_DIAGNOSTICS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#2: short storage self-test screen",
-		     VB2_SCREEN_DIAGNOSTICS_STORAGE_TEST_SHORT, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_PASS();
-	/* #3: Extended storage self-test screen */
-	DISPLAYED_EQ("extended storage self-test button",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 3, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#3: extended storage self-test screen",
-		     VB2_SCREEN_DIAGNOSTICS_STORAGE_TEST_EXTENDED, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_PASS();
-	/* #4: Quick memory test screen */
-	DISPLAYED_EQ("quick memory test button", VB2_SCREEN_DIAGNOSTICS,
-		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#4: quick memory test screen",
-		     VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_PASS();
-	/* #5: Full memory test screen */
-	DISPLAYED_EQ("full memory test button", VB2_SCREEN_DIAGNOSTICS,
-		     MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_EQ("#5: full memory test screen",
-		     VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_PASS();
-	/* #6: Power of (End of menu) */
-	DISPLAYED_EQ("power off", VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 6,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_NO_EXTRA();
-
-	/* Diagnostics screen: no nvme */
-	reset_common_data(FOR_DIAGNOSTICS);
-	/* Non-nvme storage returns UNIMPLEMENTED. */
-	mock_diag_storage_test_rv = VB2_ERROR_EX_UNIMPLEMENTED;
-	TEST_EQ(vb2_diagnostic_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"diagnostic screen: check disabled item");
-	DISPLAYED_EQ("diagnostic menu: self-test disabled",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, MOCK_IGNORE, 0xc, 0x0,
-		     MOCK_IGNORE);
-
-	VB2_DEBUG("...done.\n");
-}
-
-int main(void)
-{
-	developer_tests();
-	broken_recovery_tests();
-	manual_recovery_tests();
-	language_selection_tests();
-	debug_info_tests();
-	firmware_log_tests();
-
-	/* Screen displayed */
-	developer_screen_tests();
-	broken_recovery_screen_tests();
-	manual_recovery_screen_tests();
-	diagnostics_screen_tests();
-
-	return gTestSuccess ? 0 : 255;
-}
diff --git a/tests/vb2_ui_utility_tests.c b/tests/vb2_ui_utility_tests.c
deleted file mode 100644
index 1a7b19e..0000000
--- a/tests/vb2_ui_utility_tests.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Tests for UI utility functions.
- */
-
-#include "2api.h"
-#include "2common.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2ui.h"
-#include "2ui_private.h"
-#include "test_common.h"
-#include "vboot_api.h"
-
-/* Fixed value for ignoring some checks. */
-#define MOCK_IGNORE 0xffffu
-
-/* Mock screen index for testing screen utility functions. */
-#define MOCK_NO_SCREEN 0xef00
-#define MOCK_SCREEN_BASE 0xef10
-#define MOCK_SCREEN_MENU 0xef11
-#define MOCK_SCREEN_ROOT 0xefff
-
-/* Mock data */
-static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
-	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
-static struct vb2_context *ctx;
-static struct vb2_gbb_header gbb;
-
-static uint32_t mock_locale_count;
-static int mock_shutdown_request;
-
-static struct vb2_ui_context mock_ui_context;
-
-/* Mock actions */
-static uint32_t mock_action_called;
-static vb2_error_t mock_action_base(struct vb2_ui_context *ui)
-{
-	mock_action_called++;
-	return VB2_SUCCESS;
-}
-
-/* Mock screens */
-struct vb2_screen_info mock_screen_base = {
-	.id = MOCK_SCREEN_BASE,
-	.name = "mock_screen_base: menuless screen",
-};
-struct vb2_menu_item mock_screen_menu_items[] = {
-	{
-		.text = "option 0: language selection",
-		.is_language_select = 1,
-	},
-	{
-		.text = "option 1",
-	},
-	{
-		.text = "option 2",
-	},
-	{
-		.text = "option 3",
-	},
-	{
-		.text = "option 4",
-	},
-};
-struct vb2_screen_info mock_screen_menu = {
-	.id = MOCK_SCREEN_MENU,
-	.name = "mock_screen_menu: screen with 5 options",
-	.menu = {
-		.num_items = ARRAY_SIZE(mock_screen_menu_items),
-		.items = mock_screen_menu_items,
-	},
-};
-struct vb2_screen_info mock_screen_root = {
-	.id = MOCK_SCREEN_ROOT,
-	.name = "mock_screen_root",
-};
-
-static void screen_state_eq(const struct vb2_screen_state *state,
-			    enum vb2_screen screen,
-			    uint32_t selected_item,
-			    uint32_t hidden_item_mask)
-{
-	if (screen != MOCK_IGNORE) {
-		if (state->screen == NULL)
-			TEST_TRUE(0, "  state.screen does not exist");
-		else
-			TEST_EQ(state->screen->id, screen, "  state.screen");
-	}
-	if (selected_item != MOCK_IGNORE)
-		TEST_EQ(state->selected_item,
-			selected_item, "  state.selected_item");
-	if (hidden_item_mask != MOCK_IGNORE)
-		TEST_EQ(state->hidden_item_mask,
-			hidden_item_mask, "  state.hidden_item_mask");
-}
-
-/* Reset mock data (for use before each test) */
-static void reset_common_data(void)
-{
-	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
-		  "vb2api_init failed");
-
-	memset(&gbb, 0, sizeof(gbb));
-
-	vb2_nv_init(ctx);
-
-	/* For vb2ex_get_locale_count */
-	mock_locale_count = 1;
-
-	/* For check_shutdown_request */
-	mock_shutdown_request = MOCK_IGNORE;
-
-	/* Mock ui_context based on mock screens */
-	memset(&mock_ui_context, 0, sizeof(mock_ui_context));
-	mock_ui_context.power_button = VB2_POWER_BUTTON_HELD_SINCE_BOOT;
-
-	/* For mock actions */
-	mock_action_called = 0;
-
-	/* Reset init and action functions */
-	mock_screen_base.init = NULL;
-	mock_screen_base.action = NULL;
-	mock_screen_menu.init = NULL;
-	mock_screen_menu.action = NULL;
-	mock_screen_root.init = NULL;
-	mock_screen_root.action = NULL;
-}
-
-/* Mock functions */
-struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
-{
-	return &gbb;
-}
-
-uint32_t vb2ex_get_locale_count(void)
-{
-	return mock_locale_count;
-}
-
-uint32_t VbExIsShutdownRequested(void)
-{
-	if (mock_shutdown_request != MOCK_IGNORE)
-		return mock_shutdown_request;
-
-	return 0;
-}
-
-const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen screen)
-{
-	switch ((int)screen) {
-	case MOCK_SCREEN_BASE:
-		return &mock_screen_base;
-	case MOCK_SCREEN_MENU:
-		return &mock_screen_menu;
-	case MOCK_SCREEN_ROOT:
-		return &mock_screen_root;
-	default:
-		return NULL;
-	}
-}
-
-/* Tests */
-static void check_shutdown_request_tests(void)
-{
-	VB2_DEBUG("Testing check_shutdown_request...\n");
-
-	/* Release, press, hold, and release */
-	if (!DETACHABLE) {
-		reset_common_data();
-		mock_shutdown_request = 0;
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"release, press, hold, and release");
-		mock_shutdown_request = VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"  press");
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"  hold");
-		mock_shutdown_request = 0;
-		TEST_EQ(check_shutdown_request(&mock_ui_context),
-			VB2_REQUEST_SHUTDOWN, "  release");
-	}
-
-	/* Press is ignored because we may held since boot */
-	if (!DETACHABLE) {
-		reset_common_data();
-		mock_shutdown_request = VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"press is ignored");
-	}
-
-	/* Power button short press from key */
-	if (!DETACHABLE) {
-		reset_common_data();
-		mock_shutdown_request = 0;
-		mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS;
-		TEST_EQ(check_shutdown_request(&mock_ui_context),
-			VB2_REQUEST_SHUTDOWN, "power button short press");
-	}
-
-	/* Lid closure = shutdown request anyway */
-	reset_common_data();
-	mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED;
-	TEST_EQ(check_shutdown_request(&mock_ui_context),
-		VB2_REQUEST_SHUTDOWN, "lid closure");
-	mock_ui_context.key = 'A';
-	TEST_EQ(check_shutdown_request(&mock_ui_context),
-		VB2_REQUEST_SHUTDOWN, "  lidsw + random key");
-
-	/* Lid ignored by GBB flags */
-	reset_common_data();
-	gbb.flags |= VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN;
-	mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED;
-	TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-		"lid ignored");
-	if (!DETACHABLE) {  /* Power button works for non DETACHABLE */
-		mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED |
-					VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"  lidsw + pwdsw");
-		mock_shutdown_request = 0;
-		TEST_EQ(check_shutdown_request(&mock_ui_context),
-			VB2_REQUEST_SHUTDOWN, "  pwdsw release");
-	}
-
-	/* Lid ignored; power button short pressed */
-	if (!DETACHABLE) {
-		reset_common_data();
-		gbb.flags |= VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN;
-		mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED;
-		mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS;
-		TEST_EQ(check_shutdown_request(&mock_ui_context),
-			VB2_REQUEST_SHUTDOWN,
-			"lid ignored; power button short pressed");
-	}
-
-	/* DETACHABLE ignore power button */
-	if (DETACHABLE) {
-		/* Flag pwdsw */
-		reset_common_data();
-		mock_shutdown_request = VB_SHUTDOWN_REQUEST_POWER_BUTTON;
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"DETACHABLE: ignore pwdsw");
-		mock_shutdown_request = 0;
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"  ignore on release");
-
-		/* Power button short press */
-		reset_common_data();
-		mock_shutdown_request = 0;
-		mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS;
-		TEST_EQ(check_shutdown_request(&mock_ui_context), VB2_SUCCESS,
-			"DETACHABLE: ignore power button short press");
-	}
-
-	VB2_DEBUG("...done.\n");
-}
-
-static vb2_error_t try_back_helper(void)
-{
-	VB2_TRY(vb2_ui_screen_back(&mock_ui_context));
-	return VB2_ERROR_MOCK;
-}
-
-static vb2_error_t try_screen_change_helper(enum vb2_screen screen_id)
-{
-	VB2_TRY(vb2_ui_screen_change(&mock_ui_context, screen_id));
-	return VB2_ERROR_MOCK;
-}
-
-static void screen_stack_tests(void)
-{
-	VB2_DEBUG("Testing screen stack functionality...\n");
-
-	/* Change to screen which does not exist */
-	reset_common_data();
-	TEST_EQ(vb2_ui_screen_change(&mock_ui_context, MOCK_NO_SCREEN),
-		VB2_REQUEST_UI_CONTINUE,
-		"change to screen which does not exist");
-	TEST_PTR_EQ(mock_ui_context.state, NULL, "  stack is empty");
-
-	/* Screen back with empty stack */
-	reset_common_data();
-	TEST_EQ(vb2_ui_screen_back(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
-		"screen back with empty stack");
-	TEST_PTR_EQ(mock_ui_context.state, NULL, "  stack is empty");
-
-	/* Back to previous screen, restoring the state */
-	reset_common_data();
-	mock_screen_base.init = mock_action_base;
-	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_ROOT);
-	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE);
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->hidden_item_mask = 0x10;
-	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU);
-	TEST_EQ(vb2_ui_screen_back(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
-		"back to previous screen");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_BASE, 2, 0x10);
-	TEST_EQ(mock_action_called, 1, "  action called once");
-
-	/* VB2_TRY around back should return right away */
-	reset_common_data();
-	TEST_NEQ(try_back_helper(), VB2_ERROR_MOCK,
-		 "continued executing after VB2_TRY(back)");
-
-	/* VB2_TRY around screen_change should return right away */
-	reset_common_data();
-	TEST_NEQ(try_screen_change_helper(MOCK_SCREEN_ROOT), VB2_ERROR_MOCK,
-		 "continued executing after VB2_TRY(screen_change)");
-
-	/* Change to target screen already in stack, restoring the state */
-	reset_common_data();
-	mock_screen_base.init = mock_action_base;
-	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_ROOT);
-	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE);
-	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->hidden_item_mask = 0x10;
-	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU);
-	TEST_EQ(vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE),
-		VB2_REQUEST_UI_CONTINUE, "change to target in stack");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_BASE, 2, 0x10);
-	TEST_EQ(mock_action_called, 1, "  action called once");
-
-	/* Change to screen without init; using default init() */
-	reset_common_data();
-	TEST_EQ(vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU),
-		VB2_REQUEST_UI_CONTINUE,
-		"change to screen with language selection");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU,
-			1,	/* Since index 0 is the language selection */
-			0);
-
-	VB2_DEBUG("...done.\n");
-}
-
-static void get_language_menu_tests(void)
-{
-	const struct vb2_menu *menu;
-	const struct vb2_menu_item *items;
-	VB2_DEBUG("Testing get_language_menu...\n");
-
-	/* Only allocate menu items once */
-	reset_common_data();
-	mock_locale_count = 7;
-	menu = get_language_menu(&mock_ui_context);
-	TEST_PTR_NEQ(menu, NULL, "get language menu");
-	TEST_EQ(menu->num_items, 7, "  correct locale count");
-	TEST_PTR_NEQ(menu->items, NULL, "  items not null");
-	items = menu->items;
-
-	menu = get_language_menu(&mock_ui_context);
-	TEST_PTR_NEQ(menu, NULL, "get language menu again");
-	TEST_EQ(menu->num_items, 7, "  correct locale count again");
-	TEST_PTR_EQ(menu->items, items, "  same pointer of items");
-
-	/* Locale count = 0 */
-	reset_common_data();
-	mock_locale_count = 0;
-	menu = get_language_menu(&mock_ui_context);
-	TEST_PTR_NEQ(menu, NULL, "menu not null");
-	TEST_EQ(menu->num_items, 1, "  locale count 1");
-
-	VB2_DEBUG("...done.\n");
-}
-
-int main(void)
-{
-	check_shutdown_request_tests();
-	screen_stack_tests();
-	get_language_menu_tests();
-
-	return gTestSuccess ? 0 : 255;
-}
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
index 32eaf02..f122eb3 100644
--- a/tests/vboot_api_kernel4_tests.c
+++ b/tests/vboot_api_kernel4_tests.c
@@ -11,13 +11,11 @@
 #include "2nvstorage.h"
 #include "2secdata.h"
 #include "2sysincludes.h"
-#include "2ui.h"
 #include "host_common.h"
 #include "load_kernel_fw.h"
 #include "test_common.h"
 #include "tlcl.h"
 #include "tss_constants.h"
-#include "vboot_kernel.h"
 #include "vboot_struct.h"
 #include "vboot_test.h"
 
@@ -138,7 +136,7 @@
 	return vbboot_retval;
 }
 
-vb2_error_t vb2_developer_menu(struct vb2_context *c)
+vb2_error_t vb2ex_developer_ui(struct vb2_context *c)
 {
 	return boot_dev(c);
 }
@@ -150,7 +148,7 @@
 	TEST_TRUE(commit_data_called, "  commit data");
 }
 
-vb2_error_t vb2_manual_recovery_menu(struct vb2_context *c)
+vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *c)
 {
 	rec_check(c);
 	if (vbboot_retval == -3)
@@ -158,7 +156,7 @@
 	return vbboot_retval;
 }
 
-vb2_error_t vb2_broken_recovery_menu(struct vb2_context *c)
+vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *c)
 {
 	rec_check(c);
 	if (vbboot_retval == -4)
@@ -166,7 +164,7 @@
 	return vbboot_retval;
 }
 
-vb2_error_t vb2_diagnostic_menu(struct vb2_context *c)
+vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *c)
 {
 	if (vbboot_retval == -5)
 		return VB2_ERROR_MOCK;
@@ -239,22 +237,19 @@
 	test_slk(VB2_ERROR_MOCK, 0, "Normal boot bad");
 
 	/* Check that NV_DIAG_REQUEST triggers diagnostic UI */
-	if (DIAGNOSTIC_UI) {
-		reset_common_data();
-		mock_diagnostic_ui_enabled = 1;
-		vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
-		vbboot_retval = -5;
-		test_slk(VB2_ERROR_MOCK, 0,
-			 "Normal boot with diag enabled");
-		TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
-			"  diag not requested");
+	reset_common_data();
+	mock_diagnostic_ui_enabled = 1;
+	vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
+	vbboot_retval = -5;
+	test_slk(VB2_ERROR_MOCK, 0,
+		 "Normal boot with diag enabled");
+	TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
+		"  diag not requested");
 
-		reset_common_data();
-		vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
-		test_slk(VB2_REQUEST_REBOOT, 0,
-			 "Normal boot with diag disabled (reboot to "
-			 "unset)");
-	}
+	reset_common_data();
+	vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
+	test_slk(VB2_REQUEST_REBOOT, 0,
+		 "Normal boot with diag disabled (reboot to unset)");
 
 	/* Boot normal - phase1 failure */
 	reset_common_data();
diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c
index 9294fd7..51f0ddb 100644
--- a/tests/vboot_api_kernel_tests.c
+++ b/tests/vboot_api_kernel_tests.c
@@ -12,7 +12,6 @@
 #include "load_kernel_fw.h"
 #include "test_common.h"
 #include "vboot_api.h"
-#include "vboot_kernel.h"
 #include "vboot_test.h"
 
 #define MAX_TEST_DISKS 10
@@ -51,7 +50,7 @@
 static const char pickme[] = "correct choice";
 #define DONT_CARE ((const char *)42)
 
-test_case_t test[] = {
+test_case_t normal_tests[] = {
 	{
 		.name = "first drive (removable)",
 		.ctx_flags = 0,
@@ -389,12 +388,52 @@
 	},
 };
 
+test_case_t minios_tests[] = {
+	{
+		.name = "pick first fixed drive",
+		.ctx_flags = 0,
+		.disks_to_provide = {
+			{4096, 100, VB_DISK_FLAG_REMOVABLE, 0},
+			{4096, 100, VB_DISK_FLAG_FIXED, pickme},
+			{4096, 100, VB_DISK_FLAG_FIXED, "holygrail"},
+		},
+		.disk_count_to_return = DEFAULT_COUNT,
+		.diskgetinfo_return_val = VB2_SUCCESS,
+		.loadkernel_return_val = {0},
+		.external_expected = {0},
+
+		.expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
+		.expected_to_find_disk = pickme,
+		.expected_to_load_disk = pickme,
+		.expected_return_val = VB2_SUCCESS
+	},
+	{
+		.name = "skip failed fixed drive",
+		.ctx_flags = 0,
+		.disks_to_provide = {
+			{4096, 100, VB_DISK_FLAG_FIXED, "holygrail"},
+			{4096, 100, VB_DISK_FLAG_FIXED, pickme},
+		},
+		.disk_count_to_return = DEFAULT_COUNT,
+		.diskgetinfo_return_val = VB2_SUCCESS,
+		.loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND, 0},
+		.external_expected = {0},
+
+		.expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
+		.expected_to_find_disk = pickme,
+		.expected_to_load_disk = pickme,
+		.expected_return_val = VB2_SUCCESS
+	},
+};
+
 /****************************************************************************/
 
 /* Mock data */
 static VbDiskInfo mock_disks[MAX_TEST_DISKS];
 static test_case_t *t;
 static int load_kernel_calls;
+static int lk_normal_calls;
+static int lk_minios_calls;
 static uint32_t got_recovery_request_val;
 static const char *got_find_disk;
 static const char *got_load_disk;
@@ -403,26 +442,31 @@
 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
 static struct vb2_context *ctx;
+static struct VbSelectAndLoadKernelParams kparams;
 
 /**
  * Reset mock data (for use before each test)
  */
-static void ResetMocks(int i)
+static void ResetMocks(test_case_t *test_case)
 {
 	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
 		  "vb2api_init failed");
 
-	memset(VbApiKernelGetParams(), 0, sizeof(VbSelectAndLoadKernelParams));
+	memset(&kparams, 0, sizeof(VbSelectAndLoadKernelParams));
+	*VbApiKernelGetParamsPtr() = &kparams;
+
 
 	memset(&mock_disks, 0, sizeof(mock_disks));
 	load_kernel_calls = 0;
+	lk_normal_calls = 0;
+	lk_minios_calls = 0;
 
 	got_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED;
 	got_find_disk = 0;
 	got_load_disk = 0;
 	got_return_val = 0xdeadbeef;
 
-	t = test + i;
+	t = test_case;
 }
 
 static int is_nonzero(const void *vptr, size_t count)
@@ -495,9 +539,9 @@
 	return VB2_SUCCESS;
 }
 
-vb2_error_t LoadKernel(struct vb2_context *c,
-		       VbSelectAndLoadKernelParams *params,
-		       VbDiskInfo *disk_info)
+static vb2_error_t LoadKernelImpl(struct vb2_context *c,
+				  VbSelectAndLoadKernelParams *params,
+				  VbDiskInfo *disk_info)
 {
 	got_find_disk = (const char *)params->disk_handle;
 	VB2_DEBUG("%s(%d): got_find_disk = %s\n", __FUNCTION__,
@@ -509,6 +553,22 @@
 	return t->loadkernel_return_val[load_kernel_calls++];
 }
 
+vb2_error_t LoadKernel(struct vb2_context *c,
+		       VbSelectAndLoadKernelParams *params,
+		       VbDiskInfo *disk_info)
+{
+	lk_normal_calls++;
+	return LoadKernelImpl(c, params, disk_info);
+}
+
+vb2_error_t LoadMiniOsKernel(struct vb2_context *c,
+			     VbSelectAndLoadKernelParams *params,
+			     VbDiskInfo *disk_info)
+{
+	lk_minios_calls++;
+	return LoadKernelImpl(c, params, disk_info);
+}
+
 void vb2_nv_set(struct vb2_context *c,
 		enum vb2_nv_param param,
 		uint32_t value)
@@ -525,11 +585,11 @@
 static void VbTryLoadKernelTest(void)
 {
 	int i;
-	int num_tests =  sizeof(test) / sizeof(test[0]);
+	int num_tests = ARRAY_SIZE(normal_tests);
 
 	for (i = 0; i < num_tests; i++) {
-		printf("Test case: %s ...\n", test[i].name);
-		ResetMocks(i);
+		printf("Test case: %s ...\n", normal_tests[i].name);
+		ResetMocks(&normal_tests[i]);
 		ctx->flags = t->ctx_flags;
 		TEST_EQ(VbTryLoadKernel(ctx, t->want_flags),
 			t->expected_return_val, "  return value");
@@ -543,11 +603,40 @@
 		}
 		TEST_EQ(got_external_mismatch, 0, "  external GPT errors");
 	}
+	TEST_EQ(lk_normal_calls, load_kernel_calls, "  LoadKernel called");
+	TEST_EQ(lk_minios_calls, 0, "  LoadMiniOsKernel not called");
+}
+
+static void VbTryLoadMiniOsKernelTest(void)
+{
+	int i;
+	int num_tests =  ARRAY_SIZE(minios_tests);
+
+	for (i = 0; i < num_tests; i++) {
+		printf("Test case: %s ...\n", minios_tests[i].name);
+		ResetMocks(&minios_tests[i]);
+		ctx->flags = t->ctx_flags;
+		TEST_EQ(VbTryLoadMiniOsKernel(ctx),
+			t->expected_return_val, "  return value");
+		TEST_EQ(got_recovery_request_val,
+			t->expected_recovery_request_val, "  recovery_request");
+		if (t->expected_to_find_disk != DONT_CARE) {
+			TEST_PTR_EQ(got_find_disk, t->expected_to_find_disk,
+				    "  find disk");
+			TEST_PTR_EQ(got_load_disk, t->expected_to_load_disk,
+				    "  load disk");
+		}
+		TEST_EQ(got_external_mismatch, 0, "  external GPT errors");
+	}
+	TEST_EQ(lk_normal_calls, 0, "  LoadKernel not called");
+	TEST_EQ(lk_minios_calls, load_kernel_calls,
+		"  LoadMiniOsKernel called");
 }
 
 int main(void)
 {
 	VbTryLoadKernelTest();
+	VbTryLoadMiniOsKernelTest();
 
 	return gTestSuccess ? 0 : 255;
 }
diff --git a/tests/vboot_kernel2_tests.c b/tests/vboot_kernel2_tests.c
new file mode 100644
index 0000000..5424e86
--- /dev/null
+++ b/tests/vboot_kernel2_tests.c
@@ -0,0 +1,434 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Tests for miniOS kernel selection, loading, verification, and booting.
+ */
+
+#include "2api.h"
+#include "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "2secdata.h"
+#include "load_kernel_fw.h"
+#include "test_common.h"
+#include "vboot_api.h"
+
+#define MAX_MOCK_KERNELS 10
+#define KBUF_SIZE 65536
+
+/* Internal struct to simulate a stream for sector-based disks */
+struct disk_stream {
+	/* Disk handle */
+	VbExDiskHandle_t handle;
+
+	/* Next sector to read */
+	uint64_t sector;
+
+	/* Number of sectors left */
+	uint64_t sectors_left;
+};
+
+/* Represent a "kernel" located on the disk */
+struct mock_kernel {
+	/* Sector where the kernel begins */
+	uint64_t sector;
+
+	/* Return value from vb2_load_partition */
+	vb2_error_t rv;
+
+	/* Number of times the sector was read */
+	int read_count;
+};
+
+/* Mock data */
+static struct vb2_context *ctx;
+static struct vb2_shared_data *sd;
+static struct vb2_workbuf wb;
+static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
+	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
+
+static VbSelectAndLoadKernelParams lkp;
+static VbDiskInfo disk_info;
+static struct vb2_keyblock kbh;
+static struct vb2_kernel_preamble kph;
+static uint8_t kernel_buffer[80000];
+
+static struct mock_kernel kernels[MAX_MOCK_KERNELS];
+static int kernel_count;
+static struct mock_kernel *cur_kernel;
+
+static int mock_tpm_set_mode_calls;
+
+static void add_mock_kernel(uint64_t sector, vb2_error_t rv)
+{
+	if (kernel_count >= ARRAY_SIZE(kernels)) {
+		TEST_TRUE(0, "  kernel_count ran out of entries!");
+		return;
+	}
+
+	kernels[kernel_count].sector = sector;
+	kernels[kernel_count].rv = rv;
+	kernel_count++;
+}
+
+static void reset_common_data(void)
+{
+	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
+		  "vb2api_init failed");
+	vb2_workbuf_from_ctx(ctx, &wb);
+	vb2_nv_init(ctx);
+	vb2api_secdata_kernel_create(ctx);
+	vb2_secdata_kernel_init(ctx);
+	ctx->flags = VB2_CONTEXT_RECOVERY_MODE;
+
+	sd = vb2_get_sd(ctx);
+	sd->kernel_version_secdata = 0xabcdef | (1 << 24);
+
+	memset(&lkp, 0, sizeof(lkp));
+	lkp.kernel_buffer = kernel_buffer;
+	lkp.kernel_buffer_size = sizeof(kernel_buffer);
+	lkp.disk_handle = (VbExDiskHandle_t)1;
+
+	memset(&disk_info, 0, sizeof(disk_info));
+	disk_info.bytes_per_lba = 512;
+	disk_info.lba_count = 1024;
+	disk_info.handle = lkp.disk_handle;
+
+	memset(&kbh, 0, sizeof(kbh));
+	kbh.data_key.key_version = 2;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_1
+		| VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_MINIOS_1;
+	kbh.keyblock_size = sizeof(kbh);
+
+	memset(&kph, 0, sizeof(kph));
+	kph.kernel_version = 1;
+	kph.preamble_size = 4096 - kbh.keyblock_size;
+	kph.body_signature.data_size = 0;
+	kph.bootloader_address = 0xbeadd008;
+	kph.bootloader_size = 0x1234;
+
+
+	memset(&kernels, 0, sizeof(kernels));
+	kernel_count = 0;
+	cur_kernel = NULL;
+
+	mock_tpm_set_mode_calls = 0;
+}
+
+/* Mocks */
+
+vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start,
+			   uint64_t lba_count, VbExStream_t *stream)
+{
+	struct disk_stream *s;
+	uint64_t i;
+
+	if (!handle) {
+		*stream = NULL;
+		return VB2_ERROR_UNKNOWN;
+	}
+
+	if (lba_start + lba_count > disk_info.lba_count)
+		return VB2_ERROR_UNKNOWN;
+
+	s = malloc(sizeof(*s));
+	s->handle = handle;
+	s->sector = lba_start;
+	s->sectors_left = lba_count;
+
+	*stream = (void *)s;
+
+	for (i = 0; i < kernel_count; i++) {
+		if (kernels[i].sector == lba_start)
+			cur_kernel = &kernels[i];
+	}
+
+	return VB2_SUCCESS;
+}
+
+vb2_error_t VbExStreamRead(VbExStream_t stream, uint32_t bytes, void *buffer)
+{
+	struct disk_stream *s = (struct disk_stream *)stream;
+	uint64_t sectors;
+	uint64_t i;
+
+	if (!s)
+		return VB2_ERROR_UNKNOWN;
+
+	/* For now, require reads to be a multiple of the LBA size */
+	if (bytes % disk_info.bytes_per_lba)
+		return VB2_ERROR_UNKNOWN;
+
+	/* Fail on overflow */
+	sectors = bytes / disk_info.bytes_per_lba;
+	if (sectors > s->sectors_left)
+		return VB2_ERROR_UNKNOWN;
+
+	memset(buffer, 0, bytes);
+	for (i = 0; i < kernel_count; i++) {
+		if (kernels[i].sector >= s->sector &&
+		    kernels[i].sector < s->sector + sectors) {
+			VB2_DEBUG("Simulating kernel %" PRIu64 " match\n", i);
+			uint64_t buf_offset = (kernels[i].sector - s->sector)
+				* disk_info.bytes_per_lba;
+			memcpy(buffer + buf_offset, VB2_KEYBLOCK_MAGIC,
+			       VB2_KEYBLOCK_MAGIC_SIZE);
+			kernels[i].read_count++;
+			TEST_TRUE(kernels[i].read_count <= 2,
+				  "  Max read count exceeded");
+		}
+	}
+
+	s->sector += sectors;
+	s->sectors_left -= sectors;
+
+	return VB2_SUCCESS;
+}
+
+void VbExStreamClose(VbExStream_t stream)
+{
+	free(stream);
+}
+
+vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key,
+				  const uint8_t *buf, uint32_t size)
+{
+	return cur_kernel->rv;
+}
+
+vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size,
+				const struct vb2_public_key *key,
+				const struct vb2_workbuf *w)
+{
+	/* Use this as an opportunity to override the keyblock */
+	memcpy((void *)block, &kbh, sizeof(kbh));
+
+	return cur_kernel->rv;
+}
+
+vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block,
+				     uint32_t size,
+				     const struct vb2_workbuf *w)
+{
+	/* Use this as an opportunity to override the keyblock */
+	memcpy((void *)block, &kbh, sizeof(kbh));
+
+	return cur_kernel->rv;
+}
+
+vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
+			       uint32_t size, const struct vb2_public_key *key,
+			       const struct vb2_workbuf *w)
+{
+	/* Use this as an opportunity to override the preamble */
+	memcpy((void *)preamble, &kph, sizeof(kph));
+
+	return cur_kernel->rv;
+}
+
+vb2_error_t vb2_verify_data(const uint8_t *data, uint32_t size,
+			    struct vb2_signature *sig,
+			    const struct vb2_public_key *key,
+			    const struct vb2_workbuf *w)
+{
+	return cur_kernel->rv;
+}
+
+vb2_error_t vb2_digest_buffer(const uint8_t *buf, uint32_t size,
+			      enum vb2_hash_algorithm hash_alg, uint8_t *digest,
+			      uint32_t digest_size)
+{
+	return cur_kernel->rv;
+}
+
+vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val)
+{
+	mock_tpm_set_mode_calls++;
+	return VB2_SUCCESS;
+}
+
+/* Make sure nothing tested here ever calls this directly. */
+void vb2api_fail(struct vb2_context *c, uint8_t reason, uint8_t subcode)
+{
+	TEST_TRUE(0, "  called vb2api_fail()");
+}
+
+/* Tests */
+
+static void load_minios_kernel_tests(void)
+{
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 1;
+	add_mock_kernel(0, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "{valid kernel}");
+	TEST_EQ(mock_tpm_set_mode_calls, 1,
+		"  TPM disabled");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 1;
+	TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		VB2_ERROR_LK_NO_KERNEL_FOUND, "{no kernel}");
+	TEST_EQ(mock_tpm_set_mode_calls, 0,
+		"  TPM not disabled");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(1, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "{no kernel, valid kernel}");
+	TEST_EQ(cur_kernel->sector, 1, "  select kernel");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_ERROR_MOCK);
+	add_mock_kernel(1, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "{invalid kernel, valid kernel}");
+	TEST_EQ(cur_kernel->sector, 1, "  select second kernel");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_ERROR_MOCK);
+	add_mock_kernel(1, VB2_ERROR_MOCK);
+	TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		VB2_ERROR_LK_NO_KERNEL_FOUND,
+		"{invalid kernel, invalid kernel}");
+	TEST_EQ(mock_tpm_set_mode_calls, 0,
+		"  TPM not disabled");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_SUCCESS);
+	add_mock_kernel(1, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "{valid kernel, valid kernel} minios_priority=0");
+	TEST_EQ(cur_kernel->sector, 0, "  select first kernel");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_SUCCESS);
+	add_mock_kernel(1, VB2_SUCCESS);
+	vb2_nv_set(ctx, VB2_NV_MINIOS_PRIORITY, 1);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "{valid kernel, valid kernel} minios_priority=1");
+	TEST_EQ(cur_kernel->sector, 1, "  select second kernel");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE;
+	disk_info.lba_count = 4;
+	add_mock_kernel(1, VB2_SUCCESS);
+	TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		VB2_ERROR_LK_NO_KERNEL_FOUND,
+		"valid kernel header near start of disk (disk too small)");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE;
+	disk_info.lba_count = 1000;
+	add_mock_kernel(999, VB2_SUCCESS);
+	TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		VB2_ERROR_LK_NO_KERNEL_FOUND,
+		"valid kernel header near end of disk");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = 1024;
+	disk_info.lba_count = 128;
+	add_mock_kernel(63, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "start/end overlap assuming >128 MB search range (start)");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = 1024;
+	disk_info.lba_count = 128;
+	add_mock_kernel(64, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "start/end overlap assuming >128 MB search range (end)");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = 128;
+	disk_info.lba_count = 1024;
+	add_mock_kernel(3, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "kernel at last sector in batch assuming 512 KB batches");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = 256;
+	disk_info.lba_count = 1024;
+	add_mock_kernel(3, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "kernel at last sector in batch assuming 1 MB batches");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = 512;
+	disk_info.lba_count = 1024;
+	add_mock_kernel(3, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "kernel at last sector in batch assuming 2 MB batches");
+
+	reset_common_data();
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_MINIOS_1;
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_SUCCESS);
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		  "kernel with minios keyblock flag");
+
+	reset_common_data();
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_SUCCESS);
+	TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		VB2_ERROR_LK_NO_KERNEL_FOUND,
+		"kernel with !minios keyblock flag");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_SUCCESS);
+	sd->kernel_version_secdata = 5 << 24;
+	kph.kernel_version = 4;
+	TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		VB2_ERROR_LK_NO_KERNEL_FOUND,
+		"kernel version too old");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_SUCCESS);
+	sd->kernel_version_secdata = 5 << 24;
+	kph.kernel_version = 0x100;
+	TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		VB2_ERROR_LK_NO_KERNEL_FOUND,
+		"kernel version greater than 0xff");
+
+	reset_common_data();
+	disk_info.bytes_per_lba = KBUF_SIZE;
+	disk_info.lba_count = 2;
+	add_mock_kernel(0, VB2_SUCCESS);
+	sd->kernel_version_secdata = 5 << 24;
+	kph.kernel_version = 6;
+	TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info),
+		 "newer kernel version");
+}
+
+int main(void)
+{
+	load_minios_kernel_tests();
+
+	return gTestSuccess ? 0 : 255;
+}
diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c
index 486602c..14e7e1f 100644
--- a/tests/vboot_kernel_tests.c
+++ b/tests/vboot_kernel_tests.c
@@ -11,23 +11,12 @@
 #include "2nvstorage.h"
 #include "2secdata.h"
 #include "2secdata_struct.h"
-#include "2sha.h"
-#include "2sysincludes.h"
 #include "cgptlib.h"
 #include "cgptlib_internal.h"
-#include "crc32.h"
 #include "gpt.h"
-#include "host_common.h"
 #include "load_kernel_fw.h"
 #include "test_common.h"
 #include "vboot_api.h"
-#include "vboot_kernel.h"
-
-#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args)
-#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, "  calls")
-
-#define MOCK_SECTOR_SIZE  512
-#define MOCK_SECTOR_COUNT 1024
 
 /* Mock kernel partition */
 struct mock_part {
@@ -41,10 +30,8 @@
 static int mock_part_next;
 
 /* Mock data */
-static char call_log[4096];
 static uint8_t kernel_buffer[80000];
 static int disk_read_to_fail;
-static int disk_write_to_fail;
 static int gpt_init_fail;
 static int keyblock_verify_fail;  /* 0=ok, 1=sig, 2=hash */
 static int preamble_verify_fail;
@@ -53,17 +40,11 @@
 static int gpt_flag_external;
 
 static struct vb2_gbb_header gbb;
-static VbExDiskHandle_t handle;
 static VbSelectAndLoadKernelParams lkp;
 static VbDiskInfo disk_info;
 static struct vb2_keyblock kbh;
 static struct vb2_kernel_preamble kph;
 static struct vb2_secdata_fwmp *fwmp;
-static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
-static GptHeader *mock_gpt_primary =
-	(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
-static GptHeader *mock_gpt_secondary =
-	(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)];
 static uint8_t mock_digest[VB2_SHA256_DIGEST_SIZE] = {12, 34, 56, 78};
 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
@@ -72,56 +53,11 @@
 static struct vb2_packed_key mock_key;
 
 /**
- * Prepare a valid GPT header that will pass CheckHeader() tests
- */
-static void SetupGptHeader(GptHeader *h, int is_secondary)
-{
-	memset(h, '\0', MOCK_SECTOR_SIZE);
-
-	/* "EFI PART" */
-	memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
-	h->revision = GPT_HEADER_REVISION;
-	h->size = MIN_SIZE_OF_HEADER;
-
-	/* 16KB: 128 entries of 128 bytes */
-	h->size_of_entry = sizeof(GptEntry);
-	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
-
-	/* Set LBA pointers for primary or secondary header */
-	if (is_secondary) {
-		h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS;
-		h->entries_lba = h->my_lba - CalculateEntriesSectors(h,
-							MOCK_SECTOR_SIZE);
-	} else {
-		h->my_lba = GPT_PMBR_SECTORS;
-		h->entries_lba = h->my_lba + 1;
-	}
-
-	h->first_usable_lba = 2 + CalculateEntriesSectors(h, MOCK_SECTOR_SIZE);
-	h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h,
-								MOCK_SECTOR_SIZE);
-
-	h->header_crc32 = HeaderCrc(h);
-}
-
-static void ResetCallLog(void)
-{
-	*call_log = 0;
-}
-
-/**
  * Reset mock data (for use before each test)
  */
 static void ResetMocks(void)
 {
-	ResetCallLog();
-
-	memset(&mock_disk, 0, sizeof(mock_disk));
-	SetupGptHeader(mock_gpt_primary, 0);
-	SetupGptHeader(mock_gpt_secondary, 1);
-
 	disk_read_to_fail = -1;
-	disk_write_to_fail = -1;
 
 	gpt_init_fail = 0;
 	keyblock_verify_fail = 0;
@@ -219,29 +155,15 @@
 vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
 			 uint64_t lba_count, void *buffer)
 {
-	LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count);
-
 	if ((int)lba_start == disk_read_to_fail)
 		return VB2_ERROR_MOCK;
 
-	memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE],
-	       lba_count * MOCK_SECTOR_SIZE);
-
 	return VB2_SUCCESS;
 }
 
-vb2_error_t VbExDiskWrite(VbExDiskHandle_t h, uint64_t lba_start,
-			  uint64_t lba_count, const void *buffer)
+int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
 {
-	LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count);
-
-	if ((int)lba_start == disk_write_to_fail)
-		return VB2_ERROR_MOCK;
-
-	memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer,
-	       lba_count * MOCK_SECTOR_SIZE);
-
-	return VB2_SUCCESS;
+	return GPT_SUCCESS;
 }
 
 int GptInit(GptData *gpt)
@@ -266,6 +188,16 @@
 	return GPT_SUCCESS;
 }
 
+int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type)
+{
+	return GPT_SUCCESS;
+}
+
+int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
+{
+	return GPT_SUCCESS;
+}
+
 void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
 {
 	static char fake_guid[] = "FakeGuid";
@@ -343,257 +275,6 @@
 	TEST_TRUE(0, "  called vb2api_fail()");
 }
 
-/**
- * Test reading/writing GPT
- */
-static void ReadWriteGptTest(void)
-{
-	GptData g;
-	GptHeader *h;
-
-	g.sector_bytes = MOCK_SECTOR_SIZE;
-	g.streaming_drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT;
-	g.valid_headers = g.valid_entries = MASK_BOTH;
-
-	ResetMocks();
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead");
-	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
-		   "VbExDiskRead(h, 2, 32)\n"
-		   "VbExDiskRead(h, 1023, 1)\n"
-		   "VbExDiskRead(h, 991, 32)\n");
-	ResetCallLog();
-	/*
-	 * Valgrind complains about access to uninitialized memory here, so
-	 * zero the primary header before each test.
-	 */
-	memset(g.primary_header, '\0', g.sector_bytes);
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
-	TEST_CALLS("");
-
-	/*
-	 * Invalidate primary GPT header,
-	 * check that AllocAndReadGptData still succeeds
-	 */
-	ResetMocks();
-	memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
-		"AllocAndRead primary invalid");
-	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		1, "Primary header is invalid");
-	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		0, "Secondary header is valid");
-	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
-		   "VbExDiskRead(h, 1023, 1)\n"
-		   "VbExDiskRead(h, 991, 32)\n");
-	WriteAndFreeGptData(handle, &g);
-
-	/*
-	 * Invalidate secondary GPT header,
-	 * check that AllocAndReadGptData still succeeds
-	 */
-	ResetMocks();
-	memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
-		"AllocAndRead secondary invalid");
-	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		0, "Primary header is valid");
-	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		1, "Secondary header is invalid");
-	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
-		   "VbExDiskRead(h, 2, 32)\n"
-		   "VbExDiskRead(h, 1023, 1)\n");
-	WriteAndFreeGptData(handle, &g);
-
-	/*
-	 * Invalidate primary AND secondary GPT header,
-	 * check that AllocAndReadGptData fails.
-	 */
-	ResetMocks();
-	memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
-	memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
-	TEST_EQ(AllocAndReadGptData(handle, &g), 1,
-		"AllocAndRead primary and secondary invalid");
-	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		1, "Primary header is invalid");
-	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		1, "Secondary header is invalid");
-	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
-		   "VbExDiskRead(h, 1023, 1)\n");
-	WriteAndFreeGptData(handle, &g);
-
-	/*
-	 * Invalidate primary GPT header and check that it is
-	 * repaired by GptRepair().
-	 *
-	 * This would normally be called by LoadKernel()->GptInit()
-	 * but this callback is mocked in these tests.
-	 */
-	ResetMocks();
-	memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
-		"Fix Primary GPT: AllocAndRead");
-	/* Call GptRepair() with input indicating secondary GPT is valid */
-	g.valid_headers = g.valid_entries = MASK_SECONDARY;
-	GptRepair(&g);
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
-		"Fix Primary GPT: WriteAndFreeGptData");
-	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
-		   "VbExDiskRead(h, 1023, 1)\n"
-		   "VbExDiskRead(h, 991, 32)\n"
-		   "VbExDiskWrite(h, 1, 1)\n"
-		   "VbExDiskWrite(h, 2, 32)\n");
-	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		0, "Fix Primary GPT: Primary header is valid");
-
-	/*
-	 * Invalidate secondary GPT header and check that it can be
-	 * repaired by GptRepair().
-	 *
-	 * This would normally be called by LoadKernel()->GptInit()
-	 * but this callback is mocked in these tests.
-	 */
-	ResetMocks();
-	memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
-		"Fix Secondary GPT: AllocAndRead");
-	/* Call GptRepair() with input indicating primary GPT is valid */
-	g.valid_headers = g.valid_entries = MASK_PRIMARY;
-	GptRepair(&g);
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
-		"Fix Secondary GPT: WriteAndFreeGptData");
-	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
-		   "VbExDiskRead(h, 2, 32)\n"
-		   "VbExDiskRead(h, 1023, 1)\n"
-		   "VbExDiskWrite(h, 1023, 1)\n"
-		   "VbExDiskWrite(h, 991, 32)\n");
-	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
-		g.gpt_drive_sectors, 0, g.sector_bytes),
-		0, "Fix Secondary GPT: Secondary header is valid");
-
-	/* Data which is changed is written */
-	ResetMocks();
-	AllocAndReadGptData(handle, &g);
-	g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
-	ResetCallLog();
-	memset(g.primary_header, '\0', g.sector_bytes);
-	h = (GptHeader*)g.primary_header;
-	h->entries_lba = 2;
-	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
-	h->size_of_entry = sizeof(GptEntry);
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
-	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
-		   "VbExDiskWrite(h, 2, 32)\n");
-
-	/* Data which is changed is written */
-	ResetMocks();
-	AllocAndReadGptData(handle, &g);
-	g.modified = -1;
-	ResetCallLog();
-	memset(g.primary_header, '\0', g.sector_bytes);
-	h = (GptHeader*)g.primary_header;
-	h->entries_lba = 2;
-	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
-	h->size_of_entry = sizeof(GptEntry);
-	h = (GptHeader*)g.secondary_header;
-	h->entries_lba = 991;
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
-	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
-		   "VbExDiskWrite(h, 2, 32)\n"
-		   "VbExDiskWrite(h, 1023, 1)\n"
-		   "VbExDiskWrite(h, 991, 32)\n");
-
-	/* If legacy signature, don't modify GPT header/entries 1 */
-	ResetMocks();
-	AllocAndReadGptData(handle, &g);
-	h = (GptHeader *)g.primary_header;
-	memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
-	g.modified = -1;
-	ResetCallLog();
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
-	TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
-		   "VbExDiskWrite(h, 991, 32)\n");
-
-	/* Error reading */
-	ResetMocks();
-	disk_read_to_fail = 1;
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
-	g.valid_headers = g.valid_entries = MASK_SECONDARY;
-	GptRepair(&g);
-	ResetCallLog();
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
-	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
-		   "VbExDiskWrite(h, 2, 32)\n");
-
-	ResetMocks();
-	disk_read_to_fail = 2;
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
-	g.valid_headers = MASK_BOTH;
-	g.valid_entries = MASK_SECONDARY;
-	GptRepair(&g);
-	ResetCallLog();
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
-	TEST_CALLS("VbExDiskWrite(h, 2, 32)\n");
-
-	ResetMocks();
-	disk_read_to_fail = 991;
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
-	g.valid_headers = MASK_BOTH;
-	g.valid_entries = MASK_PRIMARY;
-	GptRepair(&g);
-	ResetCallLog();
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2");
-	TEST_CALLS("VbExDiskWrite(h, 991, 32)\n");
-
-	ResetMocks();
-	disk_read_to_fail = 1023;
-	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
-	g.valid_headers = g.valid_entries = MASK_PRIMARY;
-	GptRepair(&g);
-	ResetCallLog();
-	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2");
-	TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
-		   "VbExDiskWrite(h, 991, 32)\n");
-
-	/* Error writing */
-	ResetMocks();
-	disk_write_to_fail = 1;
-	AllocAndReadGptData(handle, &g);
-	g.modified = -1;
-	memset(g.primary_header, '\0', g.sector_bytes);
-	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
-
-	ResetMocks();
-	disk_write_to_fail = 2;
-	AllocAndReadGptData(handle, &g);
-	g.modified = -1;
-	memset(g.primary_header, '\0', g.sector_bytes);
-	h = (GptHeader*)g.primary_header;
-	h->entries_lba = 2;
-	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
-
-	ResetMocks();
-	disk_write_to_fail = 991;
-	AllocAndReadGptData(handle, &g);
-	g.modified = -1;
-	memset(g.primary_header, '\0', g.sector_bytes);
-	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
-
-	ResetMocks();
-	disk_write_to_fail = 1023;
-	AllocAndReadGptData(handle, &g);
-	g.modified = -1;
-	memset(g.primary_header, '\0', g.sector_bytes);
-	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
-
-}
-
 static void TestLoadKernel(int expect_retval, const char *test_name)
 {
 	TEST_EQ(LoadKernel(ctx, &lkp, &disk_info), expect_retval, test_name);
@@ -682,50 +363,94 @@
 	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
 		       "Fail key block dev sig fwmp");
 
-	/* Check keyblock flag mismatches */
+	/* Check keyblock flags */
 	ResetMocks();
-	kbh.keyblock_flags =
-		VB2_KEYBLOCK_FLAG_RECOVERY_0 | VB2_KEYBLOCK_FLAG_DEVELOPER_1;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_1
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
 	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
 		       "Keyblock dev flag mismatch");
 
 	ResetMocks();
-	kbh.keyblock_flags =
-		VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_0;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
 	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
 		       "Keyblock rec flag mismatch");
 
 	ResetMocks();
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_MINIOS_1;
+	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+		       "Keyblock minios flag mismatch");
+
+	ResetMocks();
 	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
-	kbh.keyblock_flags =
-		VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_1;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_1
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
 	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
 		       "Keyblock recdev flag mismatch");
 
 	ResetMocks();
+	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
+	TestLoadKernel(0, "Keyblock rec flag okay");
+
+	ResetMocks();
 	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE;
-	kbh.keyblock_flags =
-		VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_0;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
 	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
 		       "Keyblock rec!dev flag mismatch");
 
-	/* Check keyblock flag mismatches (dev mode + signed kernel required) */
+	ResetMocks();
+	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_1
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
+	TestLoadKernel(0, "Keyblock recdev flag okay");
+
+	/* Check keyblock flags (dev mode + signed kernel required) */
 	ResetMocks();
 	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
-	kbh.keyblock_flags =
-		VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_0;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
 	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
 		       "Keyblock dev flag mismatch (signed kernel required)");
 
 	ResetMocks();
 	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
-	kbh.keyblock_flags =
-		VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_0;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
 	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
 		       "Keyblock dev flag mismatch (signed kernel required)");
 
+	ResetMocks();
+	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
+	fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
+		| VB2_KEYBLOCK_FLAG_MINIOS_1;
+	TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+		       "Keyblock dev flag mismatch (signed kernel required)");
+
+	ResetMocks();
+	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
+	vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
+	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
+		| VB2_KEYBLOCK_FLAG_DEVELOPER_1
+		| VB2_KEYBLOCK_FLAG_MINIOS_0;
+	TestLoadKernel(0, "Keyblock dev flag okay (signed kernel required)");
+
 	/* Check kernel key version */
 	ResetMocks();
 	kbh.data_key.key_version = 1;
@@ -878,7 +603,6 @@
 
 int main(void)
 {
-	ReadWriteGptTest();
 	InvalidParamsTest();
 	LoadKernelTest();
 
diff --git a/tests/verify_kernel.c b/tests/verify_kernel.c
index 8fe969e..a79f33a 100644
--- a/tests/verify_kernel.c
+++ b/tests/verify_kernel.c
@@ -14,7 +14,7 @@
 #include "host_common.h"
 #include "util_misc.h"
 #include "vboot_api.h"
-#include "vboot_kernel.h"
+#include "load_kernel_fw.h"
 
 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
diff --git a/utility/crossystem.c b/utility/crossystem.c
index 079bf32..7781e94 100644
--- a/utility/crossystem.c
+++ b/utility/crossystem.c
@@ -52,12 +52,12 @@
   {"ecfw_act", IS_STRING, "Active EC firmware"},
   {"post_ec_sync_delay", CAN_WRITE,
    "Short delay after EC software sync (persistent, writable, eve only)"},
-  {"fw_prev_result", IS_STRING, "Firmware result of previous boot (vboot2)"},
-  {"fw_prev_tried", IS_STRING, "Firmware tried on previous boot (vboot2)"},
-  {"fw_result", IS_STRING|CAN_WRITE, "Firmware result this boot (vboot2)"},
-  {"fw_tried", IS_STRING, "Firmware tried this boot (vboot2)"},
+  {"fw_prev_result", IS_STRING, "Firmware result of previous boot"},
+  {"fw_prev_tried", IS_STRING, "Firmware tried on previous boot (A or B)"},
+  {"fw_result", IS_STRING|CAN_WRITE, "Firmware result this boot"},
+  {"fw_tried", IS_STRING, "Firmware tried this boot (A or B)"},
   {"fw_try_count", CAN_WRITE, "Number of times to try fw_try_next"},
-  {"fw_try_next", IS_STRING|CAN_WRITE, "Firmware to try next (vboot2)"},
+  {"fw_try_next", IS_STRING|CAN_WRITE, "Firmware to try next (A or B)"},
   {"fw_vboot2", 0, "1 if firmware was selected by vboot2 or 0 otherwise"},
   {"fwb_tries", CAN_WRITE, "Try firmware B count"},
   {"fwid", IS_STRING, "Active firmware ID"},
@@ -72,6 +72,8 @@
   {"loc_idx", CAN_WRITE, "Localization index for firmware screens"},
   {"mainfw_act", IS_STRING, "Active main firmware"},
   {"mainfw_type", IS_STRING, "Active main firmware type"},
+  {"minios_priority", IS_STRING|CAN_WRITE,
+   "miniOS image to try first (A or B)"},
   {"nvram_cleared", CAN_WRITE, "Have NV settings been lost?  Write 0 to clear"},
   {"display_request", CAN_WRITE, "Should we initialize the display at boot?"},
   {"phase_enforcement", 0,
@@ -86,7 +88,7 @@
   {"tpm_attack", CAN_WRITE, "TPM was interrupted since this flag was cleared"},
   {"tpm_fwver", 0, "Firmware version stored in TPM", "0x%08x"},
   {"tpm_kernver", 0, "Kernel version stored in TPM", "0x%08x"},
-  {"tpm_rebooted", 0, "TPM requesting repeated reboot (vboot2)"},
+  {"tpm_rebooted", 0, "TPM requesting repeated reboot"},
   {"tried_fwb", 0, "Tried firmware B before A this boot"},
   {"try_ro_sync", 0, "try read only software sync"},
   {"vdat_flags", 0, "Flags from VbSharedData", "0x%08x"},
diff --git a/utility/load_kernel_test.c b/utility/load_kernel_test.c
index cad82fd..405fced 100644
--- a/utility/load_kernel_test.c
+++ b/utility/load_kernel_test.c
@@ -16,7 +16,6 @@
 #include "2sysincludes.h"
 #include "host_common.h"
 #include "load_kernel_fw.h"
-#include "vboot_kernel.h"
 
 #define LBA_BYTES 512
 #define KERNEL_BUFFER_SIZE 0xA00000