2ec_sync: Reactivate VB2_CONTEXT_EC_SYNC_SLOW
With EFS2, the boot flow for EC sync is usually:
Boot 0: Initial boot with EC in RW. AP requests EC reset for EC sync.
Boot 1: EC reboots to RO. AP wants to perform EC sync, but display isn't
initialized. Therefore, AP sets VB2_NV_DISPLAY_REQUEST and
reboot.
Boot 2: EC is still in RO. AP sees VB2_NV_DISPLAY_REQUEST and
initializes display. Then, AP shows EC sync screen and performs
EC sync.
The reboot for VB2_NV_DISPLAY_REQUEST can actually be avoided, because
in boot 0 above it's already known that we're going to do EC sync in the
next boot.
To save us one reboot, reactivate the VB2_CONTEXT_EC_SYNC_SLOW flag.
When the flag is set, VB2_NV_DISPLAY_REQUEST will be set at the end of
boot 0, right before EC reset.
BUG=b:350885214
TEST=make run2tests
TEST=emerge-geralt libpayload depthcharge
BRANCH=none
Change-Id: I1eaae4a7219f4e755e83e3478684b74f894cbfc2
Signed-off-by: Yu-Ping Wu <[email protected]>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/5676957
Reviewed-by: Julius Werner <[email protected]>
diff --git a/firmware/2lib/2ec_sync.c b/firmware/2lib/2ec_sync.c
index d04bc9c..6475dc4 100644
--- a/firmware/2lib/2ec_sync.c
+++ b/firmware/2lib/2ec_sync.c
@@ -287,6 +287,10 @@
*/
if ((sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_EC_ACTIVE)) &&
(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW) && !EC_EFS) {
+ if (ctx->flags & VB2_CONTEXT_EC_SYNC_SLOW) {
+ /* Ignore the return value. */
+ vb2api_need_reboot_for_display(ctx);
+ }
return VB2_REQUEST_REBOOT_EC_TO_RO;
}
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index 807ffbc..77ff399 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -492,6 +492,7 @@
}
}
+test_mockable
int vb2api_need_reboot_for_display(struct vb2_context *ctx)
{
if (!(vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE)) {
diff --git a/firmware/2lib/include/2context.h b/firmware/2lib/include/2context.h
index eee45b8..4d36585 100644
--- a/firmware/2lib/include/2context.h
+++ b/firmware/2lib/include/2context.h
@@ -107,9 +107,9 @@
/*
* EC software sync is slow to update; warning screen should be
* displayed. Caller may set this flag at any time before calling
- * vb2api_kernel_phase2(). Deprecated as part of chromium:1038259.
+ * vb2api_kernel_phase2().
*/
- VB2_CONTEXT_DEPRECATED_EC_SYNC_SLOW = (1 << 16),
+ VB2_CONTEXT_EC_SYNC_SLOW = (1 << 16),
/*
* EC firmware supports early firmware selection; two EC images exist,
diff --git a/tests/vb2_ec_sync_tests.c b/tests/vb2_ec_sync_tests.c
index c3a9d2c..a60f93a 100644
--- a/tests/vb2_ec_sync_tests.c
+++ b/tests/vb2_ec_sync_tests.c
@@ -30,6 +30,7 @@
static int ec_vboot_done_calls;
static int mock_display_available;
+static int need_display_called;
static uint8_t mock_ec_ro_hash[32];
static uint8_t mock_ec_rw_hash[32];
static uint8_t hmir[32];
@@ -58,6 +59,7 @@
memset(&gbb, 0, sizeof(gbb));
mock_display_available = 1;
+ need_display_called = 0;
ec_ro_updated = 0;
ec_rw_updated = 0;
@@ -108,6 +110,12 @@
return &gbb;
}
+int vb2api_need_reboot_for_display(struct vb2_context *c)
+{
+ need_display_called = 1;
+ return !mock_display_available;
+}
+
vb2_error_t vb2ex_ec_running_rw(int *in_rw)
{
*in_rw = ec_run_image;
@@ -161,8 +169,9 @@
if (update_retval)
return update_retval;
- if (!mock_display_available)
- return VB2_REQUEST_REBOOT;
+ if (ctx->flags & VB2_CONTEXT_EC_SYNC_SLOW)
+ if (vb2api_need_reboot_for_display(ctx))
+ return VB2_REQUEST_REBOOT;
if (select == VB_SELECT_FIRMWARE_READONLY) {
ec_ro_updated = 1;
@@ -335,6 +344,22 @@
TEST_EQ(ec_rw_protected, 0, " ec rw protected");
TEST_EQ(ec_run_image, 1, " ec run image");
+ /* Hexp != Hmir == Heff (display not available) */
+ ResetMocks();
+ hmir[0] = 43;
+ vb2_secdata_kernel_set_ec_hash(ctx, hmir);
+ ec_run_image = 1;
+ mock_ec_rw_hash[0] = 43;
+ mock_display_available = 0;
+ ctx->flags |= VB2_CONTEXT_EC_SYNC_SLOW;
+ test_ssync(VB2_REQUEST_REBOOT_EC_TO_RO,
+ 0, "Reboot after synching Hmir (display not available)");
+ TEST_EQ(ec_ro_updated, 0, " ec ro updated");
+ TEST_EQ(ec_rw_updated, 0, " ec rw updated");
+ TEST_EQ(ec_rw_protected, 0, " ec rw protected");
+ TEST_EQ(ec_run_image, 1, " ec run image");
+ TEST_TRUE(need_display_called, " need display");
+
/* Hexp == Hmir != Heff */
ResetMocks();
ec_run_image = 0;
@@ -448,24 +473,28 @@
ResetMocks();
mock_ec_rw_hash[0]++;
mock_display_available = 0;
+ ctx->flags |= VB2_CONTEXT_EC_SYNC_SLOW;
test_ssync(VB2_REQUEST_REBOOT, 0,
"Reboot for display - ec rw");
TEST_EQ(ec_ro_updated, 0, " ec ro updated");
TEST_EQ(ec_rw_updated, 0, " ec rw updated");
TEST_EQ(ec_rw_protected, 0, " ec rw protected");
TEST_EQ(ec_run_image, 0, " ec run image");
+ TEST_TRUE(need_display_called, " need display");
/* Display not available - RO */
ResetMocks();
vb2_nv_set(ctx, VB2_NV_TRY_RO_SYNC, 1);
mock_ec_ro_hash[0]++;
mock_display_available = 0;
+ ctx->flags |= VB2_CONTEXT_EC_SYNC_SLOW;
test_ssync(VB2_REQUEST_REBOOT, 0,
"Reboot for display - ec ro");
TEST_EQ(ec_ro_updated, 0, " ec ro updated");
TEST_EQ(ec_rw_updated, 0, " ec rw updated");
TEST_EQ(ec_rw_protected, 0, " ec rw protected");
TEST_EQ(ec_run_image, 1, " ec run image");
+ TEST_TRUE(need_display_called, " need display");
/* RW cases, no update */
ResetMocks();