ec_sync: Ignore NO_BOOT when GBB says DISABLE_EC_SOFTWARE_SYNC

Currently, there is a final guard in VbSelectAndLoadKernel to
enforce NO_BOOT unconditionally.

This makes a board with VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC
unable to boot if Hmir != Heff because Hmir will never be synced.
If a system doesn't boot, set_gbb_flags.sh can't be used to enable
software sync.

This patch skips the final guard if
VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC is set.

Signed-off-by: dnojiri <dnojiri@chromium.org>

BUG=chromium:1045217
BRANCH=none
TEST=make runtests

Change-Id: I0c7f8c90cb0a6bb54ce30ef42e4d62554decb872
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2129107
Reviewed-by: Julius Werner <jwerner@chromium.org>
Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
Commit-Queue: Daisuke Nojiri <dnojiri@chromium.org>
Auto-Submit: Daisuke Nojiri <dnojiri@chromium.org>
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 6111eee..ff13a25 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -176,6 +176,7 @@
 				  VbSelectAndLoadKernelParams *kparams)
 {
 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
+	vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
 
 	/* Init nvstorage space. TODO(kitching): Remove once we add assertions
 	   to vb2_nv_get and vb2_nv_set. */
@@ -185,7 +186,7 @@
 
 	VB2_TRY(vb2api_kernel_phase1(ctx));
 
-	VB2_DEBUG("GBB flags are %#x\n", vb2_get_gbb(ctx)->flags);
+	VB2_DEBUG("GBB flags are %#x\n", gbb_flags);
 
 	/*
 	 * Do EC and Aux FW software sync unless we're in recovery mode. This
@@ -262,10 +263,14 @@
 		VB2_TRY(vb2_normal_boot(ctx));
 	}
 
-	if (ctx->flags & VB2_CONTEXT_NO_BOOT) {
-		/* Stop all cases returning SUCCESS against NO_BOOT flag. */
-		VB2_DEBUG("Blocking boot in NO_BOOT mode.\n");
-		vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, 0);
+	/*
+	 * Stop all cases returning SUCCESS against NO_BOOT flag except when
+	 * GBB flag disables software sync.
+	 */
+	if (!(gbb_flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
+	    && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
+		VB2_DEBUG("Blocking escape from NO_BOOT mode.\n");
+		vb2api_fail(ctx, VB2_RECOVERY_ESCAPE_NO_BOOT, 0);
 		return VB2_ERROR_ESCAPE_NO_BOOT;
 	}
 
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
index 38d7055..de4688b 100644
--- a/tests/vboot_api_kernel4_tests.c
+++ b/tests/vboot_api_kernel4_tests.c
@@ -248,6 +248,18 @@
 	kernel_phase1_retval = VB2_ERROR_MOCK;
 	test_slk(VB2_ERROR_MOCK, 0, "Normal phase1 failure");
 
+	/* Recovery - VB2_ERROR_ESCAPE_NO_BOOT */
+	reset_common_data();
+	ctx->flags |= VB2_CONTEXT_NO_BOOT;
+	test_slk(VB2_ERROR_ESCAPE_NO_BOOT,
+		 VB2_RECOVERY_ESCAPE_NO_BOOT, "Recovery for NO_BOOT escape");
+
+	/* Boot normal - VB2_ERROR_ESCAPE_NO_BOOT */
+	reset_common_data();
+	ctx->flags |= VB2_CONTEXT_NO_BOOT;
+	gbb.flags |= VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC;
+	test_slk(VB2_SUCCESS, 0, "DISABLE_EC_SOFTWARE_SYNC ignores NO_BOOT");
+
 	/* Boot dev */
 	reset_common_data();
 	ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;