ec_sync: Reset EC after updating Hmir

This patch makes vb2api_sync_ec reset EC whenever Hmir is update because
the verification result should be revoked.

When Hmir is corrupted, the system enters NO_BOOT mode (and EC stays
in RO). Since Heff == Hexp, EC RW won't be updated but we need to
reset EC so that EC can jump to RW by EFS2.

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

BUG=chromium:1045217
BRANCH=none
TEST=Verify firmware_SoftwareSync passes.

Change-Id: I21887e212cfefedeadf4c146ecec290022bb2b34
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2122587
Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Commit-Queue: Daisuke Nojiri <dnojiri@chromium.org>
Auto-Submit: Daisuke Nojiri <dnojiri@chromium.org>
diff --git a/firmware/2lib/2ec_sync.c b/firmware/2lib/2ec_sync.c
index e82366d..e464216 100644
--- a/firmware/2lib/2ec_sync.c
+++ b/firmware/2lib/2ec_sync.c
@@ -135,6 +135,7 @@
 		if (vb2_safe_memcmp(hmir, hexp, hexp_len)) {
 			VB2_DEBUG("Hmir != Hexp. Update Hmir.\n");
 			vb2_secdata_kernel_set_ec_hash(ctx, hexp);
+			sd->flags |= VB2_SD_FLAG_ECSYNC_HMIR_UPDATED;
 		}
 	}
 
@@ -277,6 +278,15 @@
 		}
 	}
 
+	if (sd->flags & VB2_SD_FLAG_ECSYNC_HMIR_UPDATED) {
+		/*
+		 * After Hmir is updated, EFS needs to be retried since the
+		 * verification result is revoked.
+		 */
+		VB2_DEBUG("Reset EC after Hmir update\n");
+		return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+	}
+
 	/* 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/include/2struct.h b/firmware/2lib/include/2struct.h
index 0bfa02d..1202563 100644
--- a/firmware/2lib/include/2struct.h
+++ b/firmware/2lib/include/2struct.h
@@ -57,6 +57,9 @@
 
 	/* Display is available on this boot */
 	VB2_SD_FLAG_DISPLAY_AVAILABLE = (1 << 8),
+
+	/* Mirrored hash (Hmir) is updated. */
+	VB2_SD_FLAG_ECSYNC_HMIR_UPDATED = (1 << 9),
 };
 
 /* Flags for vb2_shared_data.status */
diff --git a/tests/vb2_ec_sync_tests.c b/tests/vb2_ec_sync_tests.c
index 26be9ba..80b4890 100644
--- a/tests/vb2_ec_sync_tests.c
+++ b/tests/vb2_ec_sync_tests.c
@@ -403,6 +403,20 @@
 	TEST_EQ(ec_rw_protected, 0, "  ec rw protected");
 	TEST_EQ(ec_run_image, 0, "  ec run image");
 
+	/* Hexp == Heff != Hmir */
+	ResetMocks();
+	hmir[0] = 44;
+	vb2_secdata_kernel_set_ec_hash(ctx, hmir);
+	ec_run_image = 0;
+	ctx->flags |= VB2_CONTEXT_NO_BOOT;
+	test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
+		   0, "Reboot after synching Hmir");
+	TEST_EQ(ec_ro_updated, 0, "  ec ro updated");
+	TEST_EQ(ec_rw_updated, 0, "  ec rw updated");
+	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");
+
 	ResetMocks();
 	mock_ec_rw_hash[0]++;
 	vb2_nv_set(ctx, VB2_NV_TRY_RO_SYNC, 1);