firmware: Remove LoadKernelParams from APIs

This cleans up the vboot functions which handle display so they don't
need to pass it around.  Eventually, it'll be absorbed by vb2_context.

BUG=chromium:611535
BRANCH=none
TEST=make runtests; build_packages --board=reef chromeos-firmware; boot reef

Change-Id: I58169dfd37abe657f9b9aa339cc72ffa398329e0
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/414288
Reviewed-by: Shelley Chen <shchen@chromium.org>
diff --git a/firmware/lib/ec_sync.c b/firmware/lib/ec_sync.c
index d263c28..77687a4 100644
--- a/firmware/lib/ec_sync.c
+++ b/firmware/lib/ec_sync.c
@@ -457,3 +457,25 @@
 
 	return VBERROR_SUCCESS;
 }
+
+VbError_t ec_sync_phase3(struct vb2_context *ctx, VbCommonParams *cparams)
+{
+	VbSharedDataHeader *shared =
+		(VbSharedDataHeader *)cparams->shared_data_blob;
+
+	/* EC verification (and possibly updating / jumping) is done */
+	VbError_t rv = VbExEcVbootDone(!!shared->recovery_reason);
+	if (rv)
+		return rv;
+
+	/* Check if we need to cut-off battery. This must be done after EC
+         * firmware updating and before kernel started. */
+	if (vb2_nv_get(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) {
+		VB2_DEBUG("Request to cut-off battery\n");
+		vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);
+		VbExEcBatteryCutOff();
+		return VBERROR_SHUTDOWN_REQUESTED;
+	}
+
+	return VBERROR_SUCCESS;
+}
diff --git a/firmware/lib/ec_sync_all.c b/firmware/lib/ec_sync_all.c
index 2ad6103..a32d34d 100644
--- a/firmware/lib/ec_sync_all.c
+++ b/firmware/lib/ec_sync_all.c
@@ -77,5 +77,10 @@
 		return VBERROR_VGA_OPROM_MISMATCH;
 	}
 
+	/* Do EC sync phase 3; this completes synd and handles battery cutoff */
+	rv = ec_sync_phase3(ctx, cparams);
+	if (rv)
+		return rv;
+
 	return VBERROR_SUCCESS;
 }
diff --git a/firmware/lib/include/ec_sync.h b/firmware/lib/include/ec_sync.h
index dd13392..b629b2d 100644
--- a/firmware/lib/include/ec_sync.h
+++ b/firmware/lib/include/ec_sync.h
@@ -60,6 +60,18 @@
 VbError_t ec_sync_phase2(struct vb2_context *ctx,
 			 struct VbCommonParams *cparams);
 
+
+/**
+ * EC sync, phase 3
+ *
+ * This completes EC sync and handles battery cutoff if needed.
+ *
+ * @param ctx		Vboot2 context
+ * @param cparams	Vboot common params
+ * @return VBERROR_SUCCESS or non-zero error code.
+ */
+VbError_t ec_sync_phase3(struct vb2_context *ctx, VbCommonParams *cparams);
+
 /**
  * Sync all EC devices to expected versions.
  *
diff --git a/firmware/lib/include/load_kernel_fw.h b/firmware/lib/include/load_kernel_fw.h
index aeecb44..ca49b3c 100644
--- a/firmware/lib/include/load_kernel_fw.h
+++ b/firmware/lib/include/load_kernel_fw.h
@@ -17,10 +17,6 @@
 /* Interface provided by verified boot library to BDS */
 
 /* Boot flags for LoadKernel().boot_flags */
-/* Developer switch is on */
-#define BOOT_FLAG_DEVELOPER    (0x01ULL)
-/* In recovery mode */
-#define BOOT_FLAG_RECOVERY     (0x02ULL)
 /* GPT is external */
 #define BOOT_FLAG_EXTERNAL_GPT (0x04ULL)
 
@@ -28,10 +24,6 @@
 
 typedef struct LoadKernelParams {
 	/* Inputs to LoadKernel() */
-	/* Pointer to GBB data */
-	void *gbb_data;
-	/* Size of GBB data in bytes */
-	uint64_t gbb_size;
 	/* Disk handle for current device */
 	VbExDiskHandle_t disk_handle;
 	/* Bytes per lba sector on current device */
diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h
index 1c9dafc..1c3221c 100644
--- a/firmware/lib/include/vboot_kernel.h
+++ b/firmware/lib/include/vboot_kernel.h
@@ -29,13 +29,11 @@
  *
  * @param ctx			Vboot context
  * @param cparams		Vboot common params
- * @param p			Parameters for loading kernel
  * @param get_info_flags	Flags to pass to VbExDiskGetInfo()
  * @return VBERROR_SUCCESS, VBERROR_NO_DISK_FOUND if no disks of the specified
  * type were found, or other non-zero VBERROR_ codes for other failures.
  */
 uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams,
-			 LoadKernelParams *p,
                          uint32_t get_info_flags);
 
 /* Flags for VbUserConfirms() */
@@ -62,19 +60,16 @@
 /**
  * Handle a normal boot.
  */
-VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams,
-		       LoadKernelParams *p);
+VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams);
 
 /**
  * Handle a developer-mode boot.
  */
-VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams,
-			  LoadKernelParams *p);
+VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams);
 
 /**
  * Handle a recovery-mode boot.
  */
-VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams,
-			 LoadKernelParams *p);
+VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams);
 
 #endif  /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 7e48daa..5dad3b8 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -30,6 +30,9 @@
 /* Global variables */
 static VbNvContext vnc;
 static struct RollbackSpaceFwmp fwmp;
+static LoadKernelParams lkp;
+static struct vb2_context ctx;
+static uint8_t *unaligned_workbuf;
 
 #ifdef CHROMEOS_ENVIRONMENT
 /* Global variable accessors for unit tests */
@@ -38,6 +41,12 @@
 {
 	return &fwmp;
 }
+
+struct LoadKernelParams *VbApiKernelGetParams(void)
+{
+	return &lkp;
+}
+
 #endif
 
 /**
@@ -122,7 +131,6 @@
  * type were found, or other non-zero VBERROR_ codes for other failures.
  */
 uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams,
-			 LoadKernelParams *p,
                          uint32_t get_info_flags)
 {
 	VbError_t retval = VBERROR_UNKNOWN;
@@ -133,7 +141,9 @@
 	VBDEBUG(("VbTryLoadKernel() start, get_info_flags=0x%x\n",
 		 (unsigned)get_info_flags));
 
-	p->disk_handle = NULL;
+	lkp.fwmp = &fwmp;
+	lkp.nv_context = &vnc;
+	lkp.disk_handle = NULL;
 
 	/* Find disks */
 	if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
@@ -168,14 +178,14 @@
 				 disk_info[i].flags));
 			continue;
 		}
-		p->disk_handle = disk_info[i].handle;
-		p->bytes_per_lba = disk_info[i].bytes_per_lba;
-		p->gpt_lba_count = disk_info[i].lba_count;
-		p->streaming_lba_count = disk_info[i].streaming_lba_count
-						?: p->gpt_lba_count;
-		p->boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT
+		lkp.disk_handle = disk_info[i].handle;
+		lkp.bytes_per_lba = disk_info[i].bytes_per_lba;
+		lkp.gpt_lba_count = disk_info[i].lba_count;
+		lkp.streaming_lba_count = disk_info[i].streaming_lba_count
+						?: lkp.gpt_lba_count;
+		lkp.boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT
 				? BOOT_FLAG_EXTERNAL_GPT : 0;
-		retval = LoadKernel(ctx, p, cparams);
+		retval = LoadKernel(ctx, &lkp, cparams);
 		VBDEBUG(("VbTryLoadKernel() LoadKernel() = %d\n", retval));
 
 		/*
@@ -192,10 +202,10 @@
 	/* If we didn't find any good kernels, don't return a disk handle. */
 	if (VBERROR_SUCCESS != retval) {
 		VbSetRecoveryRequest(ctx, VBNV_RECOVERY_RW_NO_KERNEL);
-		p->disk_handle = NULL;
+		lkp.disk_handle = NULL;
 	}
 
-	VbExDiskFreeInfo(disk_info, p->disk_handle);
+	VbExDiskFreeInfo(disk_info, lkp.disk_handle);
 
 	/*
 	 * Pass through return code.  Recovery reason (if any) has already been
@@ -204,11 +214,9 @@
 	return retval;
 }
 
-uint32_t VbTryUsb(struct vb2_context *ctx, VbCommonParams *cparams,
-		  LoadKernelParams *p)
+uint32_t VbTryUsb(struct vb2_context *ctx, VbCommonParams *cparams)
 {
-	uint32_t retval = VbTryLoadKernel(ctx, cparams, p,
-					  VB_DISK_FLAG_REMOVABLE);
+	uint32_t retval = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_REMOVABLE);
 	if (VBERROR_SUCCESS == retval) {
 		VBDEBUG(("VbBootDeveloper() - booting USB\n"));
 	} else {
@@ -295,13 +303,54 @@
 	return -1;
 }
 
-VbError_t test_mockable
-VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams,
-	     LoadKernelParams *p)
+VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams)
 {
+	VbSharedDataHeader *shared =
+		(VbSharedDataHeader *)cparams->shared_data_blob;
+
 	/* Boot from fixed disk only */
-	VBDEBUG(("Entering %s()\n", __func__));
-	return VbTryLoadKernel(ctx, cparams, p, VB_DISK_FLAG_FIXED);
+	VB2_DEBUG("Entering %s()\n", __func__);
+
+	VbError_t rv = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_FIXED);
+
+	VB2_DEBUG("Checking if TPM kernel version needs advancing\n");
+
+	if ((1 == shared->firmware_index) && (shared->flags & VBSD_FWB_TRIED)) {
+		/*
+		 * Special cases for when we're trying a new firmware B.  These
+		 * are needed because firmware updates also usually change the
+		 * kernel key, which means that the B firmware can only boot a
+		 * new kernel, and the old firmware in A can only boot the
+		 * previous kernel.
+		 *
+		 * Don't advance the TPM if we're trying a new firmware B,
+		 * because we don't yet know if the new kernel will
+		 * successfully boot.  We still want to be able to fall back to
+		 * the previous firmware+kernel if the new firmware+kernel
+		 * fails.
+		 *
+		 * If we found only invalid kernels, reboot and try again.
+		 * This allows us to fall back to the previous firmware+kernel
+		 * instead of giving up and going to recovery mode right away.
+		 * We'll still go to recovery mode if we run out of tries and
+		 * the old firmware can't find a kernel it likes.
+		 */
+		if (rv == VBERROR_INVALID_KERNEL_FOUND) {
+			VB2_DEBUG("Trying FW B; only found invalid kernels.\n");
+			VbSetRecoveryRequest(ctx, VBNV_RECOVERY_NOT_REQUESTED);
+		}
+
+		return rv;
+	}
+
+	if ((shared->kernel_version_tpm > shared->kernel_version_tpm_start) &&
+	    RollbackKernelWrite(shared->kernel_version_tpm)) {
+		VB2_DEBUG("Error writing kernel versions to TPM.\n");
+		VbSetRecoveryRequest(ctx, VBNV_RECOVERY_RW_TPM_W_ERROR);
+		return VBERROR_TPM_WRITE_KERNEL;
+	}
+
+	return rv;
 }
 
 static const char dev_disable_msg[] =
@@ -309,8 +358,7 @@
 	"For more information, see http://dev.chromium.org/chromium-os/fwmp\n"
 	"\n";
 
-VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams,
-			  LoadKernelParams *p)
+VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams)
 {
 	GoogleBinaryBlockHeader *gbb = cparams->gbb;
 	VbSharedDataHeader *shared =
@@ -519,7 +567,7 @@
 				VbDisplayScreen(ctx, cparams, VB_SCREEN_BLANK,
 						0);
 				if (VBERROR_SUCCESS ==
-				    VbTryUsb(ctx, cparams, p)) {
+				    VbTryUsb(ctx, cparams)) {
 					VbAudioClose(audio);
 					return VBERROR_SUCCESS;
 				} else {
@@ -547,7 +595,7 @@
 	}
 
 	if ((use_usb && !ctrl_d_pressed) && allow_usb) {
-		if (VBERROR_SUCCESS == VbTryUsb(ctx, cparams, p)) {
+		if (VBERROR_SUCCESS == VbTryUsb(ctx, cparams)) {
 			VbAudioClose(audio);
 			return VBERROR_SUCCESS;
 		}
@@ -556,7 +604,7 @@
 	/* Timeout or Ctrl+D; attempt loading from fixed disk */
 	VBDEBUG(("VbBootDeveloper() - trying fixed disk\n"));
 	VbAudioClose(audio);
-	return VbTryLoadKernel(ctx, cparams, p, VB_DISK_FLAG_FIXED);
+	return VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_FIXED);
 }
 
 /* Delay in recovery mode */
@@ -564,8 +612,7 @@
 #define REC_KEY_DELAY        20       /* Check keys every 20ms */
 #define REC_MEDIA_INIT_DELAY 500      /* Check removable media every 500ms */
 
-VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams,
-			 LoadKernelParams *p)
+VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams)
 {
 	VbSharedDataHeader *shared =
 		(VbSharedDataHeader *)cparams->shared_data_blob;
@@ -609,8 +656,7 @@
 	VBDEBUG(("VbBootRecovery() waiting for a recovery image\n"));
 	while (1) {
 		VBDEBUG(("VbBootRecovery() attempting to load kernel2\n"));
-		retval = VbTryLoadKernel(ctx, cparams, p,
-					 VB_DISK_FLAG_REMOVABLE);
+		retval = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_REMOVABLE);
 
 		/*
 		 * Clear recovery requests from failed kernel loading, since
@@ -724,60 +770,35 @@
 	}
 }
 
-VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
-                                VbSelectAndLoadKernelParams *kparams)
+static VbError_t vb2_kernel_setup(VbCommonParams *cparams,
+				  VbSelectAndLoadKernelParams *kparams)
 {
 	VbSharedDataHeader *shared =
 		(VbSharedDataHeader *)cparams->shared_data_blob;
-	VbError_t retval = VBERROR_SUCCESS;
-	LoadKernelParams p;
-	uint32_t tpm_status = 0;
 
 	/* Start timer */
 	shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer();
 
-	VbNvLoad();
-
-	/* Fill in params for calls to LoadKernel() */
-	memset(&p, 0, sizeof(p));
-	p.gbb_data = cparams->gbb_data;
-	p.gbb_size = cparams->gbb_size;
-	p.fwmp = &fwmp;
-	p.nv_context = &vnc;
-
-	/*
-	 * This could be set to NULL, in which case the vboot header
-	 * information about the load address and size will be used.
-	 */
-	p.kernel_buffer = kparams->kernel_buffer;
-	p.kernel_buffer_size = kparams->kernel_buffer_size;
-
-	/* Set up boot flags */
-	p.boot_flags = 0;
-	if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON)
-		p.boot_flags |= BOOT_FLAG_DEVELOPER;
-	if (shared->recovery_reason)
-		p.boot_flags |= BOOT_FLAG_RECOVERY;
-
 	/*
 	 * Set up vboot context.
 	 *
 	 * TODO: Propagate this up to higher API levels, and use more of the
 	 * context fields (e.g. secdatak) and flags.
 	 */
-	struct vb2_context ctx;
 	memset(&ctx, 0, sizeof(ctx));
+
+	VbNvLoad();
 	memcpy(ctx.nvdata, vnc.raw, VB2_NVDATA_SIZE);
 
-	if (p.boot_flags & BOOT_FLAG_RECOVERY)
+	if (shared->recovery_reason)
 		ctx.flags |= VB2_CONTEXT_RECOVERY_MODE;
-	if (p.boot_flags & BOOT_FLAG_DEVELOPER)
+	if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON)
 		ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 
 	ctx.workbuf_size = VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE +
 			VB2_WORKBUF_ALIGN;
 
-	uint8_t *unaligned_workbuf = ctx.workbuf = malloc(ctx.workbuf_size);
+	unaligned_workbuf = ctx.workbuf = malloc(ctx.workbuf_size);
 	if (!unaligned_workbuf) {
 		VB2_DEBUG("%s: Can't allocate work buffer\n", __func__);
 		VbSetRecoveryRequest(&ctx, VB2_RECOVERY_RW_SHARED_DATA);
@@ -802,6 +823,20 @@
 	struct vb2_shared_data *sd = vb2_get_sd(&ctx);
 	sd->recovery_reason = shared->recovery_reason;
 
+	/*
+	 * If we're in recovery mode just to do memory retraining, all we
+	 * need to do is reboot.
+	 */
+	if (shared->recovery_reason == VBNV_RECOVERY_TRAIN_AND_REBOOT) {
+		VB2_DEBUG("Reboot after retraining in recovery.\n");
+		return VBERROR_REBOOT_REQUIRED;
+	}
+
+	/* 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;
@@ -810,161 +845,73 @@
 	kparams->flags = 0;
 	memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));
 
+	/* Read GBB header, since we'll needs flags from it */
 	cparams->bmp = NULL;
 	cparams->gbb = malloc(sizeof(*cparams->gbb));
-	retval = VbGbbReadHeader_static(cparams, cparams->gbb);
-	if (VBERROR_SUCCESS != retval)
-		goto VbSelectAndLoadKernel_exit;
-
-	/* Do EC software sync if necessary */
-	retval = ec_sync_all(&ctx, cparams);
-	if (retval != VBERROR_SUCCESS)
-		goto VbSelectAndLoadKernel_exit;
-
-	/* EC verification (and possibily updating / jumping) is done */
-	retval = VbExEcVbootDone(!!shared->recovery_reason);
-	if (retval != VBERROR_SUCCESS)
-		goto VbSelectAndLoadKernel_exit;
-
-	/* Check if we need to cut-off battery. This must be done after EC
-         * firmware updating and before kernel started. */
-	if (vb2_nv_get(&ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) {
-		VBDEBUG(("Request to cut-off battery\n"));
-		vb2_nv_set(&ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);
-		VbExEcBatteryCutOff();
-		retval = VBERROR_SHUTDOWN_REQUESTED;
-		goto VbSelectAndLoadKernel_exit;
-	}
+	uint32_t retval = VbGbbReadHeader_static(cparams, cparams->gbb);
+	if (retval)
+		return retval;
 
 	/* Read kernel version from the TPM.  Ignore errors in recovery mode. */
-	tpm_status = RollbackKernelRead(&shared->kernel_version_tpm);
-	if (0 != tpm_status) {
-		VBDEBUG(("Unable to get kernel versions from TPM\n"));
+	if (RollbackKernelRead(&shared->kernel_version_tpm)) {
+		VB2_DEBUG("Unable to get kernel versions from TPM\n");
 		if (!shared->recovery_reason) {
 			VbSetRecoveryRequest(&ctx,
 					     VBNV_RECOVERY_RW_TPM_R_ERROR);
-			retval = VBERROR_TPM_READ_KERNEL;
-			goto VbSelectAndLoadKernel_exit;
+			return VBERROR_TPM_READ_KERNEL;
 		}
 	}
+
 	shared->kernel_version_tpm_start = shared->kernel_version_tpm;
 
 	/* Read FWMP.  Ignore errors in recovery mode. */
 	if (cparams->gbb->flags & GBB_FLAG_DISABLE_FWMP) {
 		memset(&fwmp, 0, sizeof(fwmp));
-		tpm_status = 0;
-	} else {
-		tpm_status = RollbackFwmpRead(&fwmp);
-	}
-	if (0 != tpm_status) {
-		VBDEBUG(("Unable to get FWMP from TPM\n"));
+	} else if (RollbackFwmpRead(&fwmp)) {
+		VB2_DEBUG("Unable to get FWMP from TPM\n");
 		if (!shared->recovery_reason) {
 			VbSetRecoveryRequest(&ctx,
 					     VBNV_RECOVERY_RW_TPM_R_ERROR);
-			retval = VBERROR_TPM_READ_FWMP;
-			goto VbSelectAndLoadKernel_exit;
+			return VBERROR_TPM_READ_FWMP;
 		}
 	}
 
-	/* Select boot path */
-	if (shared->recovery_reason == VBNV_RECOVERY_TRAIN_AND_REBOOT) {
-		/* Reboot requested by user recovery code. */
-		VBDEBUG(("Reboot requested by user (recovery_reason=%d).\n",
-			 shared->recovery_reason));
-		retval = VBERROR_REBOOT_REQUIRED;
-	} else if (shared->recovery_reason) {
-		/* Recovery boot */
-		retval = VbBootRecovery(&ctx, cparams, &p);
-		VbExEcEnteringMode(0, VB_EC_RECOVERY);
-		VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0);
+	return VBERROR_SUCCESS;
+}
 
-	} else if (p.boot_flags & BOOT_FLAG_DEVELOPER) {
-		/* Developer boot */
-		retval = VbBootDeveloper(&ctx, cparams, &p);
-		VbExEcEnteringMode(0, VB_EC_DEVELOPER);
-		VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0);
-
-	} else {
-		/* Normal boot */
-		VbExEcEnteringMode(0, VB_EC_NORMAL);
-		retval = VbBootNormal(&ctx, cparams, &p);
-
-		if ((1 == shared->firmware_index) &&
-		    (shared->flags & VBSD_FWB_TRIED)) {
-			/*
-			 * Special cases for when we're trying a new firmware
-			 * B.  These are needed because firmware updates also
-			 * usually change the kernel key, which means that the
-			 * B firmware can only boot a new kernel, and the old
-			 * firmware in A can only boot the previous kernel.
-			 *
-			 * Don't advance the TPM if we're trying a new firmware
-			 * B, because we don't yet know if the new kernel will
-			 * successfully boot.  We still want to be able to fall
-			 * back to the previous firmware+kernel if the new
-			 * firmware+kernel fails.
-			 *
-			 * If we found only invalid kernels, reboot and try
-			 * again.  This allows us to fall back to the previous
-			 * firmware+kernel instead of giving up and going to
-			 * recovery mode right away.  We'll still go to
-			 * recovery mode if we run out of tries and the old
-			 * firmware can't find a kernel it likes.
-			 */
-			if (VBERROR_INVALID_KERNEL_FOUND == retval) {
-				VBDEBUG(("Trying firmware B, "
-					 "and only found invalid kernels.\n"));
-				VbSetRecoveryRequest(&ctx,
-						VBNV_RECOVERY_NOT_REQUESTED);
-				goto VbSelectAndLoadKernel_exit;
-			}
-		} else {
-			/* Not trying a new firmware B. */
-
-			/* See if we need to update the TPM. */
-			VBDEBUG(("Checking if TPM kernel version needs "
-				 "advancing\n"));
-			if (shared->kernel_version_tpm >
-			    shared->kernel_version_tpm_start) {
-				tpm_status = RollbackKernelWrite(
-						shared->kernel_version_tpm);
-				if (0 != tpm_status) {
-					VBDEBUG(("Error writing kernel "
-						 "versions to TPM.\n"));
-					VbSetRecoveryRequest(&ctx,
-						VBNV_RECOVERY_RW_TPM_W_ERROR);
-					retval = VBERROR_TPM_WRITE_KERNEL;
-					goto VbSelectAndLoadKernel_exit;
-				}
-			}
-		}
-	}
-
-	if (VBERROR_SUCCESS != retval)
-		goto VbSelectAndLoadKernel_exit;
+static VbError_t vb2_kernel_phase4(VbCommonParams *cparams,
+				   VbSelectAndLoadKernelParams *kparams)
+{
+	VbSharedDataHeader *shared =
+		(VbSharedDataHeader *)cparams->shared_data_blob;
 
 	/* Save disk parameters */
-	kparams->disk_handle = p.disk_handle;
-	kparams->partition_number = p.partition_number;
-	kparams->bootloader_address = p.bootloader_address;
-	kparams->bootloader_size = p.bootloader_size;
-	kparams->flags = p.flags;
-	memcpy(kparams->partition_guid, p.partition_guid,
+	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));
 
-	/* Lock the kernel versions.  Ignore errors in recovery mode. */
-	tpm_status = RollbackKernelLock(shared->recovery_reason);
-	if (0 != tpm_status) {
-		VBDEBUG(("Error locking kernel versions.\n"));
-		if (!shared->recovery_reason) {
-			VbSetRecoveryRequest(&ctx,
-					     VBNV_RECOVERY_RW_TPM_L_ERROR);
-			retval = VBERROR_TPM_LOCK_KERNEL;
-			goto VbSelectAndLoadKernel_exit;
-		}
+	/* Lock the kernel versions if not in recovery mode */
+	if (!shared->recovery_reason &&
+	    RollbackKernelLock(shared->recovery_reason)) {
+		VB2_DEBUG("Error locking kernel versions.\n");
+		VbSetRecoveryRequest(&ctx, VBNV_RECOVERY_RW_TPM_L_ERROR);
+		return VBERROR_TPM_LOCK_KERNEL;
 	}
 
- VbSelectAndLoadKernel_exit:
+	return VBERROR_SUCCESS;
+}
+
+static void vb2_kernel_cleanup(VbCommonParams *cparams,
+			       VbSelectAndLoadKernelParams *kparams)
+{
+	VbSharedDataHeader *shared =
+			(VbSharedDataHeader *)cparams->shared_data_blob;
 
 	/*
 	 * Clean up vboot context.
@@ -986,13 +933,54 @@
 
 	/* Stop timer */
 	shared->timer_vb_select_and_load_kernel_exit = VbExGetTimer();
+}
 
-	kparams->kernel_buffer = p.kernel_buffer;
-	kparams->kernel_buffer_size = p.kernel_buffer_size;
+VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
+                                VbSelectAndLoadKernelParams *kparams)
+{
+	VbSharedDataHeader *shared =
+		(VbSharedDataHeader *)cparams->shared_data_blob;
 
-	VBDEBUG(("VbSelectAndLoadKernel() returning %d\n", (int)retval));
+	VbError_t retval = vb2_kernel_setup(cparams, kparams);
+	if (retval)
+		goto VbSelectAndLoadKernel_exit;
+
+	/*
+	 * Do EC software sync if necessary.  This has UI, but it's just a
+	 * single non-interactive WAIT screen.
+	 */
+	retval = ec_sync_all(&ctx, cparams);
+	if (retval)
+		goto VbSelectAndLoadKernel_exit;
+
+	/* Select boot path */
+	if (shared->recovery_reason) {
+		/* Recovery boot.  This has UI. */
+		retval = VbBootRecovery(&ctx, cparams);
+		VbExEcEnteringMode(0, VB_EC_RECOVERY);
+		VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0);
+
+	} else if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON) {
+		/* Developer boot.  This has UI. */
+		retval = VbBootDeveloper(&ctx, cparams);
+		VbExEcEnteringMode(0, VB_EC_DEVELOPER);
+		VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0);
+
+	} else {
+		/* Normal boot */
+		retval = VbBootNormal(&ctx, cparams);
+		VbExEcEnteringMode(0, VB_EC_NORMAL);
+	}
+
+ VbSelectAndLoadKernel_exit:
+
+	if (VBERROR_SUCCESS == retval)
+		retval = vb2_kernel_phase4(cparams, kparams);
+
+	vb2_kernel_cleanup(cparams, kparams);
 
 	/* Pass through return value from boot path */
+	VB2_DEBUG("%s returning %d\n", __func__, (int)retval);
 	return retval;
 }
 
diff --git a/tests/vboot_api_devmode_tests.c b/tests/vboot_api_devmode_tests.c
index 1d68096..271f342 100644
--- a/tests/vboot_api_devmode_tests.c
+++ b/tests/vboot_api_devmode_tests.c
@@ -134,7 +134,6 @@
 
 /* Mock data */
 static VbCommonParams cparams;
-static LoadKernelParams lkparams;
 static struct vb2_context ctx;
 static VbNvContext vnc;
 static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
@@ -159,7 +158,6 @@
   cparams.gbb_data = &gbb;
   cparams.gbb = &gbb;
 
-  memset(&lkparams, 0, sizeof(lkparams));
   memset(&ctx, 0, sizeof(ctx));
 
   memset(&vnc, 0, sizeof(vnc));
@@ -317,7 +315,7 @@
     kbd_fire_at = test[i].keypress_at_count;
     max_events = test[i].num_events;
     expected_event = test[i].notes;
-    (void) VbBootDeveloper(&ctx, &cparams, &lkparams);
+    (void) VbBootDeveloper(&ctx, &cparams);
     VBDEBUG(("INFO: matched %d total %d expected %d\n",
              matched_events, current_event, test[i].num_events));
     TEST_TRUE(matched_events == test[i].num_events &&
diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c
index 284d4a1..f6776e9 100644
--- a/tests/vboot_api_kernel2_tests.c
+++ b/tests/vboot_api_kernel2_tests.c
@@ -184,7 +184,7 @@
 }
 
 uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams,
-			 LoadKernelParams *p, uint32_t get_info_flags)
+			 uint32_t get_info_flags)
 {
 	return vbtlk_retval + get_info_flags;
 }
@@ -273,7 +273,7 @@
 {
 	ResetMocks();
 	VbExEcEnteringMode(0, VB_EC_NORMAL);
-	TEST_EQ(VbBootNormal(&ctx, &cparams, &lkp), 1002, "VbBootNormal()");
+	TEST_EQ(VbBootNormal(&ctx, &cparams), 1002, "VbBootNormal()");
 	TEST_EQ(VbGetMode(), VB_EC_NORMAL, "vboot_mode normal");
 }
 
@@ -284,7 +284,7 @@
 	/* Proceed after timeout */
 	ResetMocks();
 	VbExEcEnteringMode(0, VB_EC_DEVELOPER);
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
 	TEST_EQ(VbGetMode(), VB_EC_DEVELOPER, "vboot_mode developer");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
 		"  warning screen");
@@ -296,7 +296,7 @@
 	ResetMocks();
 	gbb.flags |= GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY |
 		     GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
 	TEST_EQ(vbexlegacy_called, 1, "  try legacy");
 
 	/* Proceed to legacy after timeout if boot legacy and default boot
@@ -305,14 +305,14 @@
 	vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VBNV_DEV_DEFAULT_BOOT_LEGACY);
 	vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
 	TEST_EQ(vbexlegacy_called, 1, "  try legacy");
 
 	/* Proceed to legacy boot mode only if enabled */
 	ResetMocks();
 	vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VBNV_DEV_DEFAULT_BOOT_LEGACY);
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
 	TEST_EQ(vbexlegacy_called, 0, "  not legacy");
 
 	/* Proceed to usb after timeout if boot usb and default boot
@@ -322,31 +322,31 @@
 		   VBNV_DEV_DEFAULT_BOOT_USB);
 	vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
 	vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U USB");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U USB");
 
 	/* Proceed to usb boot mode only if enabled */
 	ResetMocks();
 	vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VBNV_DEV_DEFAULT_BOOT_USB);
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout");
 
 	/* If no USB tries fixed disk */
 	ResetMocks();
 	vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
 	vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT,
 		   VBNV_DEV_DEFAULT_BOOT_USB);
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+U enabled");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U enabled");
 	TEST_EQ(vbexlegacy_called, 0, "  not legacy");
 
 	/* Up arrow is uninteresting / passed to VbCheckDisplayKey() */
 	ResetMocks();
 	mock_keypress[0] = VB_KEY_UP;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Up arrow");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Up arrow");
 
 	/* Shutdown requested in loop */
 	ResetMocks();
 	shutdown_request_calls_left = 2;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Shutdown requested");
 	TEST_NEQ(audio_looping_calls_left, 0, "  aborts audio");
@@ -354,7 +354,7 @@
 	/* Space goes straight to recovery if no virtual dev switch */
 	ResetMocks();
 	mock_keypress[0] = ' ';
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams),
 		VBERROR_LOAD_KERNEL_RECOVERY,
 		"Space = recovery");
 	TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST),
@@ -365,7 +365,7 @@
 	shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
 	mock_keypress[0] = ' ';
 	mock_keypress[1] = '\r';
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED,
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
 		"Space = tonorm");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
 		"  warning screen");
@@ -382,7 +382,7 @@
 	mock_keypress[0] = ' ';
 	mock_keypress[1] = ' ';
 	mock_keypress[2] = 0x1b;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Space-space");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Space-space");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
 		"  warning screen");
 	TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM,
@@ -395,7 +395,7 @@
 	shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
 	mock_keypress[0] = '\r';
 	mock_keypress[1] = '\r';
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Enter ignored");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Enter ignored");
 
 	/* Enter does if GBB flag set */
 	ResetMocks();
@@ -403,7 +403,7 @@
 	gbb.flags |= GBB_FLAG_ENTER_TRIGGERS_TONORM;
 	mock_keypress[0] = '\r';
 	mock_keypress[1] = '\r';
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED,
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
 		"Enter = tonorm");
 
 	/* Tonorm ignored if GBB forces dev switch on */
@@ -412,7 +412,7 @@
 	gbb.flags |= GBB_FLAG_FORCE_DEV_SWITCH_ON;
 	mock_keypress[0] = ' ';
 	mock_keypress[1] = '\r';
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002,
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
 		"Can't tonorm gbb-dev");
 
 	/* Shutdown requested at tonorm screen */
@@ -420,7 +420,7 @@
 	shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
 	mock_keypress[0] = ' ';
 	shutdown_request_calls_left = 2;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Shutdown requested at tonorm");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING,
@@ -431,7 +431,7 @@
 	/* Ctrl+D dismisses warning */
 	ResetMocks();
 	mock_keypress[0] = 0x04;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+D");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+D");
 	TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0,
 		"  recovery reason");
 	TEST_NEQ(audio_looping_calls_left, 0, "  aborts audio");
@@ -441,67 +441,67 @@
 	ResetMocks();
 	mock_keypress[0] = 0x04;
 	gbb.flags |= GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+D");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+D");
 	TEST_EQ(vbexlegacy_called, 0, "  not legacy");
 
 	/* Ctrl+L tries legacy boot mode only if enabled */
 	ResetMocks();
 	mock_keypress[0] = 0x0c;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+L normal");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+L normal");
 	TEST_EQ(vbexlegacy_called, 0, "  not legacy");
 
 	ResetMocks();
 	gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_LEGACY;
 	mock_keypress[0] = 0x0c;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002,
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
 		"Ctrl+L force legacy");
 	TEST_EQ(vbexlegacy_called, 1, "  try legacy");
 
 	ResetMocks();
 	vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1);
 	mock_keypress[0] = 0x0c;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002,
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
 		"Ctrl+L nv legacy");
 	TEST_EQ(vbexlegacy_called, 1, "  try legacy");
 
 	ResetMocks();
 	VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_LEGACY;
 	mock_keypress[0] = 0x0c;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002,
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002,
 		"Ctrl+L fwmp legacy");
 	TEST_EQ(vbexlegacy_called, 1, "  fwmp legacy");
 
 	/* Ctrl+U boots USB only if enabled */
 	ResetMocks();
 	mock_keypress[0] = 0x15;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+U normal");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U normal");
 
 	/* Ctrl+U enabled, with good USB boot */
 	ResetMocks();
 	vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
 	mock_keypress[0] = 0x15;
 	vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U USB");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U USB");
 
 	/* Ctrl+U enabled via GBB */
 	ResetMocks();
 	gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_USB;
 	mock_keypress[0] = 0x15;
 	vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U force USB");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U force USB");
 
 	/* Ctrl+U enabled via FWMP */
 	ResetMocks();
 	VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_USB;
 	mock_keypress[0] = 0x15;
 	vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U force USB");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U force USB");
 
 	/* If no USB, eventually times out and tries fixed disk */
 	ResetMocks();
 	vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1);
 	mock_keypress[0] = 0x15;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+U enabled");
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U enabled");
 	TEST_EQ(vbexlegacy_called, 0, "  not legacy");
 	TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0,
 		"  recovery reason");
@@ -512,7 +512,7 @@
 	VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT;
 	mock_keypress[0] = '\x1b';  /* Just causes TONORM again */
 	mock_keypress[1] = '\r';
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED,
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
 		"FWMP dev disabled");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
 		"  tonorm screen");
@@ -528,7 +528,7 @@
 	shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
 	VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT;
 	shutdown_request_calls_left = 1;
-	TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootDeveloper(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Shutdown requested when dev disabled");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
@@ -545,7 +545,7 @@
 	ResetMocks();
 	shutdown_request_calls_left = 10;
 	VbExEcEnteringMode(0, VB_EC_RECOVERY);
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Shutdown requested");
 	TEST_EQ(VbGetMode(), VB_EC_RECOVERY, "vboot_mode recovery");
@@ -562,7 +562,7 @@
 	mock_num_disks[1] = 1;
 	mock_num_disks[2] = 1;
 	vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Remove");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
@@ -575,7 +575,7 @@
 	mock_num_disks[1] = 1;
 	shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
 	vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"No remove in dev");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
@@ -588,7 +588,7 @@
 	mock_num_disks[1] = 1;
 	shared->flags |= VBSD_BOOT_REC_SWITCH_ON;
 	vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"No remove in rec");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
@@ -600,7 +600,7 @@
 	mock_num_disks[0] = 0;
 	mock_num_disks[1] = 1;
 	vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Remove");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
@@ -612,7 +612,7 @@
 	mock_num_disks[0] = -1;
 	vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE;
 	shutdown_request_calls_left = 10;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Bad disk count");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN,
@@ -624,7 +624,7 @@
 	shutdown_request_calls_left = 100;
 	mock_keypress[0] = 0x04;
 	trust_ec = 0;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Ctrl+D ignored if EC not trusted");
 	TEST_EQ(virtdev_set, 0, "  virtual dev mode off");
@@ -637,7 +637,7 @@
 	trust_ec = 1;
 	shutdown_request_calls_left = 100;
 	mock_keypress[0] = 0x04;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Ctrl+D ignored if already in dev mode");
 	TEST_EQ(virtdev_set, 0, "  virtual dev mode off");
@@ -649,7 +649,7 @@
 	trust_ec = 1;
 	shutdown_request_calls_left = 100;
 	mock_keypress[0] = 0x04;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Ctrl+D ignored if recovery not manually triggered");
 	TEST_EQ(virtdev_set, 0, "  virtual dev mode off");
@@ -661,7 +661,7 @@
 	trust_ec = 1;
 	shutdown_request_calls_left = 100;
 	mock_keypress[0] = 0x04;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Ctrl+D ignored if no virtual dev switch");
 	TEST_EQ(virtdev_set, 0, "  virtual dev mode off");
@@ -677,7 +677,7 @@
 	shutdown_request_calls_left = 100;
 	mock_keypress[0] = 0x04;
 	mock_switches[0] = VB_INIT_FLAG_REC_BUTTON_PRESSED;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Ctrl+D ignored if phys rec button is still pressed");
 	TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV,
@@ -691,7 +691,7 @@
 	trust_ec = 1;
 	mock_keypress[0] = 0x04;
 	mock_keypress[1] = ' ';
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_SHUTDOWN_REQUESTED,
 		"Ctrl+D todev abort");
 	TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT,
@@ -711,7 +711,7 @@
 	mock_keypress[0] = 0x04;
 	mock_keypress[1] = '\r';
 	mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED,
+	TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_REBOOT_REQUIRED,
 		"Ctrl+D todev confirm");
 	TEST_EQ(virtdev_set, 1, "  virtual dev mode on");
 
@@ -725,7 +725,7 @@
 	mock_keypress[1] = '\r';
 	mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD;
 	virtdev_retval = VBERROR_SIMULATED;
-	TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp),
+	TEST_EQ(VbBootRecovery(&ctx, &cparams),
 		VBERROR_TPM_SET_BOOT_MODE_STATE,
 		"Ctrl+D todev failure");
 
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
index 0b1223d..41e58c8 100644
--- a/tests/vboot_api_kernel4_tests.c
+++ b/tests/vboot_api_kernel4_tests.c
@@ -111,8 +111,8 @@
 	return rfr_retval;
 }
 
-VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams,
-		       LoadKernelParams *p)
+uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams,
+                         uint32_t get_info_flags)
 {
 	shared->kernel_version_tpm = new_version;
 
@@ -122,8 +122,7 @@
 	return vbboot_retval;
 }
 
-VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams,
-			  LoadKernelParams *p)
+VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams)
 {
 	shared->kernel_version_tpm = new_version;
 
@@ -133,8 +132,7 @@
 	return vbboot_retval;
 }
 
-VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams,
-			 LoadKernelParams *p)
+VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams)
 {
 	shared->kernel_version_tpm = new_version;
 
diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c
index 0a59160..1d80dc4 100644
--- a/tests/vboot_api_kernel_tests.c
+++ b/tests/vboot_api_kernel_tests.c
@@ -21,6 +21,8 @@
 #include "vboot_api.h"
 #include "vboot_kernel.h"
 
+struct LoadKernelParams *VbApiKernelGetParams(void);
+
 #define MAX_TEST_DISKS 10
 #define DEFAULT_COUNT -1
 
@@ -181,7 +183,6 @@
 /****************************************************************************/
 
 /* Mock data */
-static LoadKernelParams lkparams;
 static VbDiskInfo mock_disks[MAX_TEST_DISKS];
 static test_case_t *t;
 static int load_kernel_calls;
@@ -190,7 +191,6 @@
 static const char *got_load_disk;
 static uint32_t got_return_val;
 static uint32_t got_external_mismatch;
-static VbNvContext vnc;
 static struct vb2_context ctx;
 
 /**
@@ -198,10 +198,12 @@
  */
 static void ResetMocks(int i)
 {
-	memset(&lkparams, 0, sizeof(lkparams));
+	memset(&ctx, 0, sizeof(ctx));
+
+	memset(VbApiKernelGetParams(), 0, sizeof(LoadKernelParams));
+
 	memset(&mock_disks, 0, sizeof(mock_disks));
 	load_kernel_calls = 0;
-	memset(&vnc, 0, sizeof(vnc));
 
 	got_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED;
 	got_find_disk = 0;
@@ -313,7 +315,7 @@
 	for (i = 0; i < num_tests; i++) {
 		printf("Test case: %s ...\n", test[i].name);
 		ResetMocks(i);
-		TEST_EQ(VbTryLoadKernel(&ctx, 0, &lkparams, test[i].want_flags),
+		TEST_EQ(VbTryLoadKernel(&ctx, 0, test[i].want_flags),
 			t->expected_return_val, "  return value");
 		TEST_EQ(got_recovery_request_val,
 			t->expected_recovery_request_val, "  recovery_request");
diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c
index 2a472d3..b1e1635 100644
--- a/tests/vboot_kernel_tests.c
+++ b/tests/vboot_kernel_tests.c
@@ -158,8 +158,6 @@
 
 	memset(&lkp, 0, sizeof(lkp));
 	lkp.nv_context = &vnc;
-	lkp.gbb_data = gbb;
-	lkp.gbb_size = sizeof(gbb_data);
 	lkp.bytes_per_lba = 512;
 	lkp.streaming_lba_count = 1024;
 	lkp.gpt_lba_count = 1024;
@@ -577,10 +575,6 @@
 static void TestLoadKernel(int expect_retval, char *test_name)
 {
 	memcpy(ctx.nvdata, vnc.raw, VB2_NVDATA_SIZE);
-	if (lkp.boot_flags & BOOT_FLAG_RECOVERY)
-		ctx.flags |= VB2_CONTEXT_RECOVERY_MODE;
-	if (lkp.boot_flags & BOOT_FLAG_DEVELOPER)
-		ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 
 	TEST_EQ(LoadKernel(&ctx, &lkp, &cparams), expect_retval, test_name);
 
@@ -653,26 +647,26 @@
 
 	/* In dev mode, fail if hash is bad too */
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	key_block_verify_fail = 2;
 	TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND, "Fail key block dev hash");
 
 	/* But just bad sig is ok */
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	key_block_verify_fail = 1;
 	TestLoadKernel(0, "Succeed key block dev sig");
 
 	/* In dev mode and requiring signed kernel, fail if sig is bad */
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
 	VbNvTeardown(&vnc);
 	key_block_verify_fail = 1;
 	TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND, "Fail key block dev sig");
 
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	lkp.fwmp = &fwmp;
 	fwmp.flags |= FWMP_DEV_ENABLE_OFFICIAL_ONLY;
 	key_block_verify_fail = 1;
@@ -693,14 +687,14 @@
 		       "Key block rec flag mismatch");
 
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
+	ctx.flags |= VB2_CONTEXT_RECOVERY_MODE;
 	kbh.key_block_flags =
 		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
 	TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND,
 		       "Key block recdev flag mismatch");
 
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE;
 	kbh.key_block_flags =
 		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
 	TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND,
@@ -731,12 +725,12 @@
 
 	ResetMocks();
 	kbh.data_key.key_version = 1;
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	TestLoadKernel(0, "Key version ignored in dev mode");
 
 	ResetMocks();
 	kbh.data_key.key_version = 1;
-	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
+	ctx.flags |= VB2_CONTEXT_RECOVERY_MODE;
 	TestLoadKernel(0, "Key version ignored in rec mode");
 
 	ResetMocks();
@@ -753,17 +747,17 @@
 
 	ResetMocks();
 	kph.kernel_version = 0;
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	TestLoadKernel(0, "Kernel version ignored in dev mode");
 
 	ResetMocks();
 	kph.kernel_version = 0;
-	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
+	ctx.flags |= VB2_CONTEXT_RECOVERY_MODE;
 	TestLoadKernel(0, "Kernel version ignored in rec mode");
 
 	/* Check developer key hash - bad */
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	lkp.fwmp = &fwmp;
 	fwmp.flags |= FWMP_DEV_USE_KEY_HASH;
 	fwmp.dev_key_hash[0]++;
@@ -772,7 +766,7 @@
 
 	/* Check developer key hash - good */
 	ResetMocks();
-	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
+	ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
 	lkp.fwmp = &fwmp;
 	fwmp.flags |= FWMP_DEV_USE_KEY_HASH;
 	TestLoadKernel(0, "Good key block dev fwmp hash");
diff --git a/tests/verify_kernel.c b/tests/verify_kernel.c
index 9a7ee1e..5c48781 100644
--- a/tests/verify_kernel.c
+++ b/tests/verify_kernel.c
@@ -107,10 +107,6 @@
 		return 1;
 	}
 
-	/* GBB and cparams only needed by LoadKernel() in recovery mode */
-	params.gbb_data = NULL;
-	params.gbb_size = 0;
-
 	/* TODO(chromium:441893): support dev-mode flag and external gpt flag */
 	params.boot_flags = 0;
 
diff --git a/utility/load_kernel_test.c b/utility/load_kernel_test.c
index 4ca061e..769c24c 100644
--- a/utility/load_kernel_test.c
+++ b/utility/load_kernel_test.c
@@ -78,6 +78,9 @@
 }
 
 
+#define BOOT_FLAG_DEVELOPER (1 << 0)
+#define BOOT_FLAG_RECOVERY (1 << 1)
+
 /* Main routine */
 int main(int argc, char* argv[]) {
 
@@ -93,7 +96,7 @@
 
   memset(&lkp, 0, sizeof(LoadKernelParams));
   lkp.bytes_per_lba = LBA_BYTES;
-  lkp.boot_flags = BOOT_FLAG_RECOVERY;
+  int boot_flags = BOOT_FLAG_RECOVERY;
   memset(&vnc, 0, sizeof(VbNvContext));
   VbNvSetup(&vnc);
   lkp.nv_context = &vnc;
@@ -106,7 +109,7 @@
     switch (c)
     {
     case 'b':
-      lkp.boot_flags = strtoull(optarg, &e, 0);
+      boot_flags = strtoull(optarg, &e, 0);
       if (!*optarg || (e && *e))
       {
         fprintf(stderr, "Invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -136,12 +139,12 @@
             argv[0]);
     fprintf(stderr, "\noptions:\n");
     /* These cases are because uint64_t isn't necessarily the same as ULL. */
-    fprintf(stderr, "  -b NUM     boot flag bits (default %" PRIu64 "):\n",
-            (uint64_t)BOOT_FLAG_RECOVERY);
-    fprintf(stderr, "               %" PRIu64 " = developer mode on\n",
-            (uint64_t)BOOT_FLAG_DEVELOPER);
-    fprintf(stderr, "               %" PRIu64 " = recovery mode on\n",
-            (uint64_t)BOOT_FLAG_RECOVERY);
+    fprintf(stderr, "  -b NUM     boot flag bits (default %d):\n",
+            BOOT_FLAG_RECOVERY);
+    fprintf(stderr, "               %d = developer mode on\n",
+            BOOT_FLAG_DEVELOPER);
+    fprintf(stderr, "               %d = recovery mode on\n",
+	    BOOT_FLAG_RECOVERY);
     return 1;
   }
 
@@ -163,11 +166,9 @@
   }
 
   /* Initialize the GBB */
-  lkp.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size;
-  lkp.gbb_data = (void*)malloc(lkp.gbb_size);
-  gbb = (GoogleBinaryBlockHeader*)lkp.gbb_data;
-  cparams.gbb = gbb;
-  memset(gbb, 0, lkp.gbb_size);
+  cparams.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size;
+  cparams.gbb = gbb = (GoogleBinaryBlockHeader*)malloc(cparams.gbb_size);
+  memset(gbb, 0, cparams.gbb_size);
   memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
   gbb->major_version = GBB_MAJOR_VER;
   gbb->minor_version = GBB_MINOR_VER;
@@ -201,7 +202,8 @@
   /* Free the key blob, now that we're done with it */
   free(key_blob);
 
-  printf("bootflags = %" PRIu64 "\n", lkp.boot_flags);
+  printf("bootflags = %d\n", boot_flags);
+  lkp.boot_flags = boot_flags;
 
   /* Get image size */
   printf("Reading from image: %s\n", image_name);
@@ -239,9 +241,9 @@
 	  return 1;
   }
   ctx.workbuf_size = VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE;
-  if (lkp.boot_flags & BOOT_FLAG_RECOVERY)
+  if (boot_flags & BOOT_FLAG_RECOVERY)
 	  ctx.flags |= VB2_CONTEXT_RECOVERY_MODE;
-  if (lkp.boot_flags & BOOT_FLAG_DEVELOPER)
+  if (boot_flags & BOOT_FLAG_DEVELOPER)
 	  ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE;
   if (VB2_SUCCESS != vb2_init_context(&ctx)) {
 	  free(ctx.workbuf);