summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Wawrzynczak <twawrzynczak@chromium.org>2019-10-22 15:36:59 -0600
committerCommit Bot <commit-bot@chromium.org>2019-11-20 06:33:35 +0000
commit651f9c423c87c8dd6c55f7eecc05f85e73ed03fb (patch)
tree74db1c55665f0c2a07d3368f3745b3cbee4d6343
parentff4aa00ced6013ad31da9d877c66152cac2e96c6 (diff)
downloadvboot-651f9c423c87c8dd6c55f7eecc05f85e73ed03fb.tar.gz
EC software sync: Split up EC and auxfw sync
Currently, the logic for updating auxfw is entangled with the logic for performing EC software sync. This patch attempts to split them apart, so that they can be used separately. VbSelectAndLoadKernel() currently still performs both, EC first and then auxfw. The intended use-case for this functionality is to perform EC software sync only in coreboot's romstage. Unit tests were updated to ensure functionality is effectively unchanged. BUG=b:143094352, chromium:1016688 BRANCH=none TEST=make clean && make runtests Change-Id: I7bdf38694cfed83b18dd8189b8516780184ecc8e Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/1867314 Reviewed-by: Julius Werner <jwerner@chromium.org> (cherry picked from commit 5d874c2f45c991651a3c66be64e4139f56c69d25) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/1924292 Reviewed-by: Shelley Chen <shchen@chromium.org> Commit-Queue: Shelley Chen <shchen@chromium.org> Tested-by: Shelley Chen <shchen@chromium.org>
-rw-r--r--Makefile1
-rw-r--r--firmware/2lib/2auxfw_sync.c147
-rw-r--r--firmware/2lib/2ec_sync.c208
-rw-r--r--firmware/2lib/2stub.c19
-rw-r--r--firmware/2lib/include/2api.h79
-rw-r--r--firmware/2lib/include/2ec_sync.h93
-rw-r--r--firmware/include/vboot_api.h40
-rw-r--r--firmware/lib/vboot_api_kernel.c8
-rw-r--r--firmware/lib/vboot_ui.c1
-rw-r--r--firmware/lib/vboot_ui_menu.c1
-rw-r--r--tests/vb2_ec_sync_tests.c131
-rw-r--r--tests/vboot_api_kernel4_tests.c1
12 files changed, 424 insertions, 305 deletions
diff --git a/Makefile b/Makefile
index 36934203..4751336c 100644
--- a/Makefile
+++ b/Makefile
@@ -349,6 +349,7 @@ FWLIB_SRCS = \
# Code common to both vboot 2.0 (old structs) and 2.1 (new structs)
FWLIB2X_SRCS = \
firmware/2lib/2api.c \
+ firmware/2lib/2auxfw_sync.c \
firmware/2lib/2common.c \
firmware/2lib/2crc8.c \
firmware/2lib/2ec_sync.c \
diff --git a/firmware/2lib/2auxfw_sync.c b/firmware/2lib/2auxfw_sync.c
new file mode 100644
index 00000000..7c6c2ba4
--- /dev/null
+++ b/firmware/2lib/2auxfw_sync.c
@@ -0,0 +1,147 @@
+/* Copyright 2019 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.
+ *
+ * Auxiliary firmware sync routines for vboot
+ */
+
+#include "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "2sysincludes.h"
+#include "vboot_api.h"
+#include "vboot_common.h"
+#include "vboot_display.h"
+
+/**
+ * If no display is available, set DISPLAY_REQUEST in NV space
+ */
+static int check_reboot_for_display(struct vb2_context *ctx)
+{
+ if (!(vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE)) {
+ VB2_DEBUG("Reboot to initialize display\n");
+ vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Display the WAIT screen
+ */
+static void display_wait_screen(struct vb2_context *ctx)
+{
+ VB2_DEBUG("AUX FW update is slow. Show WAIT screen.\n");
+ VbDisplayScreen(ctx, VB_SCREEN_WAIT, 0, NULL);
+}
+
+/**
+ * Determine if we are allowed to update auxfw
+ *
+ * @param ctx Vboot2 context
+ * @return boolean (true iff we can update auxfw)
+ */
+static int auxfw_sync_allowed(struct vb2_context *ctx)
+{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
+
+ /* Reasons not to do sync at all */
+ if (!(ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED))
+ return 0;
+ if (gbb->flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
+ return 0;
+ if (gbb->flags & VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC)
+ return 0;
+ if (sd->recovery_reason)
+ return 0;
+ return 1;
+}
+
+/**
+ * Update the specified Aux FW and verify the update succeeded
+ *
+ * @param ctx Vboot2 context
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+static vb2_error_t update_auxfw(struct vb2_context *ctx)
+{
+ vb2_error_t rv;
+
+ VB2_DEBUG("Updating auxfw\n");
+
+ /*
+ * The underlying platform is expected to know how and where to find the
+ * firmware image for all auxfw devices.
+ */
+ rv = vb2ex_auxfw_update();
+ if (rv != VB2_SUCCESS) {
+ VB2_DEBUG("vb2ex_auxfw_update() returned %d\n", rv);
+
+ /*
+ * The device may need a reboot. It may need to unprotect the
+ * region before updating, or may need to reboot after updating.
+ * Either way, it's not an error requiring recovery mode.
+ *
+ * If we fail for any other reason, trigger recovery mode.
+ */
+ if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
+ vb2api_fail(ctx, VB2_RECOVERY_AUX_FW_UPDATE, rv);
+ }
+
+ return rv;
+}
+
+/**
+ * Decides if auxfw sync is allowed to be performed
+ *
+ * If sync is allowed, invokes the external callback,
+ * vb2ex_auxfw_check() to allow the client to decide on the auxfw
+ * update severity.
+ *
+ * @param ctx Vboot2 context
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+static vb2_error_t auxfw_sync_check_update(struct vb2_context *ctx,
+ enum vb2_auxfw_update_severity *severity)
+{
+ if (!auxfw_sync_allowed(ctx)) {
+ *severity = VB_AUX_FW_NO_UPDATE;
+ return VB2_SUCCESS;
+ }
+
+ return vb2ex_auxfw_check(severity);
+}
+
+vb2_error_t vb2api_auxfw_sync(struct vb2_context *ctx)
+{
+ enum vb2_auxfw_update_severity fw_update = VB_AUX_FW_NO_UPDATE;
+ vb2_error_t rv;
+
+ /* Check for update severity */
+ rv = auxfw_sync_check_update(ctx, &fw_update);
+ if (rv)
+ return rv;
+
+ /* If AUX FW update is slow display the wait screen */
+ if (fw_update == VB_AUX_FW_SLOW_UPDATE) {
+ /* Display should be available, but better check again */
+ if (check_reboot_for_display(ctx))
+ return VBERROR_REBOOT_REQUIRED;
+ display_wait_screen(ctx);
+ }
+
+ if (fw_update > VB_AUX_FW_NO_UPDATE) {
+ rv = update_auxfw(ctx);
+ if (rv)
+ return rv;
+ /*
+ * AUX FW Update is applied successfully. Request EC reboot to
+ * RO, so that the chips that had FW update get reset to a
+ * clean state.
+ */
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+ }
+
+ return vb2ex_auxfw_finalize(ctx);
+}
diff --git a/firmware/2lib/2ec_sync.c b/firmware/2lib/2ec_sync.c
index 897ddfd2..89a3c1a2 100644
--- a/firmware/2lib/2ec_sync.c
+++ b/firmware/2lib/2ec_sync.c
@@ -5,8 +5,8 @@
* EC software sync routines for vboot
*/
+#include "2api.h"
#include "2common.h"
-#include "2ec_sync.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2sysincludes.h"
@@ -15,10 +15,35 @@
#include "vboot_display.h"
#include "vboot_kernel.h"
-#define SYNC_FLAG(select) \
- ((select) == VB_SELECT_FIRMWARE_READONLY ? \
+#define SYNC_FLAG(select) \
+ ((select) == VB_SELECT_FIRMWARE_READONLY ? \
VB2_SD_FLAG_ECSYNC_EC_RO : VB2_SD_FLAG_ECSYNC_EC_RW)
+/**
+ * If no display is available, set DISPLAY_REQUEST in NV space
+ */
+static int check_reboot_for_display(struct vb2_context *ctx)
+{
+ if (!(vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE)) {
+ VB2_DEBUG("Reboot to initialize display\n");
+ vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Display the WAIT screen
+ */
+static void display_wait_screen(struct vb2_context *ctx)
+{
+ VB2_DEBUG("EC FW update is slow. Show WAIT screen.\n");
+ VbDisplayScreen(ctx, VB_SCREEN_WAIT, 0, NULL);
+}
+
+/**
+ * Set the RECOVERY_REQUEST flag in NV space
+ */
static void request_recovery(struct vb2_context *ctx, uint32_t recovery_request)
{
VB2_DEBUG("request_recovery(%u)\n", recovery_request);
@@ -37,7 +62,7 @@ static vb2_error_t protect_ec(struct vb2_context *ctx,
if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
VB2_DEBUG("vb2ex_ec_protect() needs reboot\n");
} else if (rv != VB2_SUCCESS) {
- VB2_DEBUG("vb2ex_ec_protect() returned %d\n", rv);
+ VB2_DEBUG("vb2ex_ec_protect() returned %#x\n", rv);
request_recovery(ctx, VB2_RECOVERY_EC_PROTECT);
}
return rv;
@@ -92,7 +117,7 @@ static vb2_error_t check_ec_hash(struct vb2_context *ctx,
int ec_hash_size;
vb2_error_t rv = vb2ex_ec_hash_image(select, &ec_hash, &ec_hash_size);
if (rv) {
- VB2_DEBUG("vb2ex_ec_hash_image() returned %d\n", rv);
+ VB2_DEBUG("vb2ex_ec_hash_image() returned %#x\n", rv);
request_recovery(ctx, VB2_RECOVERY_EC_HASH_FAILED);
return VB2_ERROR_EC_HASH_IMAGE;
}
@@ -103,7 +128,7 @@ static vb2_error_t check_ec_hash(struct vb2_context *ctx,
int hash_size;
rv = vb2ex_ec_get_expected_image_hash(select, &hash, &hash_size);
if (rv) {
- VB2_DEBUG("vb2ex_ec_get_expected_image_hash() returned %d\n", rv);
+ VB2_DEBUG("vb2ex_ec_get_expected_image_hash() returned %#x\n", rv);
request_recovery(ctx, VB2_RECOVERY_EC_EXPECTED_HASH);
return VB2_ERROR_EC_HASH_EXPECTED;
}
@@ -141,7 +166,7 @@ static vb2_error_t update_ec(struct vb2_context *ctx,
int want_size;
vb2_error_t rv = vb2ex_ec_get_expected_image(select, &want, &want_size);
if (rv) {
- VB2_DEBUG("vb2ex_ec_get_expected_image() returned %d\n", rv);
+ VB2_DEBUG("vb2ex_ec_get_expected_image() returned %#x\n", rv);
request_recovery(ctx, VB2_RECOVERY_EC_EXPECTED_IMAGE);
return rv;
}
@@ -149,7 +174,7 @@ static vb2_error_t update_ec(struct vb2_context *ctx,
rv = vb2ex_ec_update_image(select, want, want_size);
if (rv != VB2_SUCCESS) {
- VB2_DEBUG("vb2ex_ec_update_image() returned %d\n", rv);
+ VB2_DEBUG("vb2ex_ec_update_image() returned %#x\n", rv);
/*
* The EC may know it needs a reboot. It may need to
@@ -180,7 +205,7 @@ static vb2_error_t update_ec(struct vb2_context *ctx,
}
/**
- * Set VB2_SD_FLAG_ECSYNC_EC_IN_RW flag for a EC
+ * Set VB2_SD_FLAG_ECSYNC_EC_IN_RW flag for the EC
*
* @param ctx Vboot2 context
* @return VB2_SUCCESS, or non-zero if error.
@@ -198,7 +223,7 @@ static vb2_error_t check_ec_active(struct vb2_context *ctx)
vb2_error_t rv = vb2ex_ec_running_rw(&in_rw);
/* If we couldn't determine where the EC was, reboot to recovery. */
if (rv != VB2_SUCCESS) {
- VB2_DEBUG("vb2ex_ec_running_rw() returned %d\n", rv);
+ VB2_DEBUG("vb2ex_ec_running_rw() returned %#x\n", rv);
request_recovery(ctx, VB2_RECOVERY_EC_UNKNOWN_IMAGE);
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
@@ -224,8 +249,8 @@ static vb2_error_t sync_ec(struct vb2_context *ctx)
vb2_error_t rv;
const enum vb2_firmware_selection select_rw = is_rw_ab ?
- VB_SELECT_FIRMWARE_EC_UPDATE :
- VB_SELECT_FIRMWARE_EC_ACTIVE;
+ VB_SELECT_FIRMWARE_EC_UPDATE :
+ VB_SELECT_FIRMWARE_EC_ACTIVE;
VB2_DEBUG("select_rw=%d\n", select_rw);
/* Update the RW Image */
@@ -276,7 +301,7 @@ static vb2_error_t sync_ec(struct vb2_context *ctx)
* sync did eventually succeed.
*/
uint32_t recovery_request =
- vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
+ vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
/* Update the RO Image. */
int num_tries;
@@ -307,9 +332,10 @@ static vb2_error_t sync_ec(struct vb2_context *ctx)
if (rv != VB2_SUCCESS)
return rv;
+ /* Disable further sysjumps */
rv = vb2ex_ec_disable_jump();
if (rv != VB2_SUCCESS) {
- VB2_DEBUG("vb2ex_ec_disable_jump() returned %d\n", rv);
+ VB2_DEBUG("vb2ex_ec_disable_jump() returned %#x\n", rv);
request_recovery(ctx, VB2_RECOVERY_EC_SOFTWARE_SYNC);
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
@@ -317,7 +343,18 @@ static vb2_error_t sync_ec(struct vb2_context *ctx)
return rv;
}
-vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
+/**
+ * EC sync, phase 1
+ *
+ * This checks whether the EC is running the correct image to do EC sync, and
+ * whether any updates are necessary.
+ *
+ * @param ctx Vboot2 context
+ * @return VB2_SUCCESS, VBERROR_EC_REBOOT_TO_RO_REQUIRED if the EC must
+ * reboot back to its RO code to continue EC sync, or other non-zero error
+ * code.
+ */
+static vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
@@ -357,7 +394,17 @@ vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
return VB2_SUCCESS;
}
-int ec_will_update_slowly(struct vb2_context *ctx)
+/**
+ * Returns non-zero if the EC will perform a slow update.
+ *
+ * This is only valid after calling ec_sync_phase1(), before calling
+ * sync_ec().
+ *
+ * @param ctx Vboot2 context
+ * @return non-zero if a slow update will be done; zero if no update or a
+ * fast update.
+ */
+static int ec_will_update_slowly(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
@@ -388,36 +435,21 @@ static int ec_sync_allowed(struct vb2_context *ctx)
return 1;
}
-vb2_error_t ec_sync_check_aux_fw(struct vb2_context *ctx,
- enum vb2_auxfw_update_severity *severity)
-{
- struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
-
- /* If we're not updating the EC, skip aux fw syncs as well */
- if (!ec_sync_allowed(ctx) ||
- (gbb->flags & VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC)) {
- *severity = VB_AUX_FW_NO_UPDATE;
- return VB2_SUCCESS;
- }
-
- return vb2ex_auxfw_check(severity);
-}
-
-vb2_error_t ec_sync_update_aux_fw(struct vb2_context *ctx)
-{
- vb2_error_t rv = vb2ex_auxfw_update();
- if (rv) {
- if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
- VB2_DEBUG("AUX firmware update requires RO reboot.\n");
- } else {
- VB2_DEBUG("AUX firmware update/protect failed.\n");
- request_recovery(ctx, VB2_RECOVERY_AUX_FW_UPDATE);
- }
- }
- return rv;
-}
-
-vb2_error_t ec_sync_phase2(struct vb2_context *ctx)
+/**
+ * EC sync, phase 2
+ *
+ * This updates the EC if necessary, makes sure it has protected its image(s),
+ * and makes sure it has jumped to the correct image.
+ *
+ * If ec_will_update_slowly(), it is suggested that the caller display a
+ * warning screen before calling phase 2.
+ *
+ * @param ctx Vboot2 context
+ * @return VB2_SUCCESS, VBERROR_EC_REBOOT_TO_RO_REQUIRED if the EC must
+ * reboot back to its RO code to continue EC sync, or other non-zero error
+ * code.
+ */
+static vb2_error_t ec_sync_phase2(struct vb2_context *ctx)
{
if (!ec_sync_allowed(ctx))
return VB2_SUCCESS;
@@ -426,7 +458,15 @@ vb2_error_t ec_sync_phase2(struct vb2_context *ctx)
return sync_ec(ctx);
}
-vb2_error_t ec_sync_phase3(struct vb2_context *ctx)
+/**
+ * EC sync, phase 3
+ *
+ * This completes EC sync and handles battery cutoff if needed.
+ *
+ * @param ctx Vboot2 context
+ * @return VB2_SUCCESS or non-zero error code.
+ */
+static vb2_error_t ec_sync_phase3(struct vb2_context *ctx)
{
/* EC verification (and possibly updating / jumping) is done */
vb2_error_t rv = vb2ex_ec_vboot_done(ctx);
@@ -447,84 +487,28 @@ vb2_error_t ec_sync_phase3(struct vb2_context *ctx)
return VB2_SUCCESS;
}
-static int check_reboot_for_display(struct vb2_context *ctx)
-{
- if (!(vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE)) {
- VB2_DEBUG("Reboot to initialize display\n");
- vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1);
- return 1;
- }
- return 0;
-}
-
-static void display_wait_screen(struct vb2_context *ctx, const char *fw_name)
+vb2_error_t vb2api_ec_sync(struct vb2_context *ctx)
{
- VB2_DEBUG("%s update is slow. Show WAIT screen.\n", fw_name);
- VbDisplayScreen(ctx, VB_SCREEN_WAIT, 0, NULL);
-}
-
-vb2_error_t ec_sync_all(struct vb2_context *ctx)
-{
- enum vb2_auxfw_update_severity fw_update = VB_AUX_FW_NO_UPDATE;
vb2_error_t rv;
/* Phase 1; this determines if we need an update */
vb2_error_t phase1_rv = ec_sync_phase1(ctx);
int need_wait_screen = ec_will_update_slowly(ctx);
- /* Check if EC SW Sync Phase1 needs reboot */
- if (phase1_rv) {
- ec_sync_check_aux_fw(ctx, &fw_update);
- /* It does -- speculatively check if we need display as well */
- if (need_wait_screen || fw_update == VB_AUX_FW_SLOW_UPDATE)
- check_reboot_for_display(ctx);
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
+ if (need_wait_screen && check_reboot_for_display(ctx))
+ return VBERROR_REBOOT_REQUIRED;
- /* Is EC already in RO and needs slow update? */
- if (need_wait_screen) {
- /* Might still need display in that case */
- if (check_reboot_for_display(ctx))
- return VBERROR_REBOOT_REQUIRED;
- /* Display is available, so pop up the wait screen */
- display_wait_screen(ctx, "EC FW");
- }
+ if (phase1_rv)
+ return phase1_rv;
+
+ if (need_wait_screen)
+ display_wait_screen(ctx);
/* Phase 2; Applies update and/or jumps to the correct EC image */
rv = ec_sync_phase2(ctx);
if (rv)
return rv;
- /* EC in RW, now we can check the severity of the AUX FW update */
- rv = ec_sync_check_aux_fw(ctx, &fw_update);
- if (rv)
- return rv;
-
- /* If AUX FW update is slow display the wait screen */
- if (fw_update == VB_AUX_FW_SLOW_UPDATE) {
- /* Display should be available, but better check again */
- if (check_reboot_for_display(ctx))
- return VBERROR_REBOOT_REQUIRED;
- display_wait_screen(ctx, "AUX FW");
- }
-
- if (fw_update > VB_AUX_FW_NO_UPDATE) {
- /* Do Aux FW software sync */
- rv = ec_sync_update_aux_fw(ctx);
- if (rv)
- return rv;
- /*
- * AUX FW Update is applied successfully. Request EC reboot to
- * RO, so that the chips that had FW update gets reset to a
- * clean state.
- */
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
-
/* Phase 3; Completes sync and handles battery cutoff */
- rv = ec_sync_phase3(ctx);
- if (rv)
- return rv;
-
- return VB2_SUCCESS;
+ return ec_sync_phase3(ctx);
}
diff --git a/firmware/2lib/2stub.c b/firmware/2lib/2stub.c
index f7e680d6..69873393 100644
--- a/firmware/2lib/2stub.c
+++ b/firmware/2lib/2stub.c
@@ -68,6 +68,25 @@ vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val)
}
__attribute__((weak))
+vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity)
+{
+ *severity = VB_AUX_FW_NO_UPDATE;
+ return VB2_SUCCESS;
+}
+
+__attribute__((weak))
+vb2_error_t vb2ex_auxfw_update(void)
+{
+ return VB2_SUCCESS;
+}
+
+__attribute__((weak))
+vb2_error_t vb2ex_auxfw_finalize(struct vb2_context *ctx)
+{
+ return VB2_SUCCESS;
+}
+
+__attribute__((weak))
void vb2ex_abort(void)
{
/* Stub simply exits. */
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 0a713265..43595c84 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -755,6 +755,36 @@ vb2_error_t vb2api_gbb_read_hwid(struct vb2_context *ctx, char *hwid,
*/
vb2_gbb_flags_t vb2api_gbb_get_flags(struct vb2_context *ctx);
+/**
+ * Sync the Embedded Controller device to the expected version.
+ *
+ * This function will check if EC software sync is allowed, and if it
+ * is, it will compare the expected image hash to the actual image
+ * hash. If they are the same, the EC will simply jump to its RW
+ * firwmare. Otherwise, the specified flash image will be updated to
+ * the new version, and the EC will reboot into its new firmware.
+ *
+ * @param ctx Vboot context
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+vb2_error_t vb2api_ec_sync(struct vb2_context *ctx);
+
+/**
+ * Sync all auxiliary firmware to the expected versions
+ *
+ * This function will first check if an auxfw update is needed and
+ * what the "severity" of that update is (i.e., if any auxfw devices
+ * exist and the relative quickness of updating it. If the update is
+ * deemed slow, it may display a screen to notify the user. The
+ * platform is then instructed to perform the update. Finally, an EC
+ * reboot to its RO section is performed to ensure that auxfw devices
+ * are also reset and running the new firmware.
+ *
+ * @param ctx Vboot2 context
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+vb2_error_t vb2api_auxfw_sync(struct vb2_context *ctx);
+
/*****************************************************************************/
/* APIs provided by the caller to verified boot */
@@ -839,6 +869,55 @@ vb2_error_t vb2ex_hwcrypto_digest_finalize(uint8_t *digest,
vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val);
/*
+ * severity levels for an auxiliary firmware update request
+ */
+enum vb2_auxfw_update_severity {
+ /* no update needed and no protection needed */
+ VB_AUX_FW_NO_DEVICE = 0,
+ /* no update needed */
+ VB_AUX_FW_NO_UPDATE = 1,
+ /* update needed, can be done quickly */
+ VB_AUX_FW_FAST_UPDATE = 2,
+ /* update needed, "this would take a while..." */
+ VB_AUX_FW_SLOW_UPDATE = 3,
+};
+
+/*
+ * Check if any auxiliary firmware needs updating.
+ *
+ * This is called after the EC has been updated and is intended to
+ * version-check additional firmware blobs such as TCPCs.
+ *
+ * @param severity return parameter for health of auxiliary firmware
+ * (see vb2_auxfw_update_severity above)
+ * @return VBERROR_... error, VB2_SUCCESS on success.
+ */
+vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity);
+
+/*
+ * Perform auxiliary firmware update(s).
+ *
+ * This is called after the EC has been updated and is intended to
+ * update additional firmware blobs such as TCPCs.
+ *
+ * @return VBERROR_... error, VB2_SUCCESS on success.
+ */
+vb2_error_t vb2ex_auxfw_update(void);
+
+/*
+ * Notify client that vboot is done with Aux FW.
+ *
+ * If Aux FW sync was successful, this will be called at the end so that
+ * the client may perform actions that require the Aux FW to be in its
+ * final state. This may include protecting the communcations tunnels that
+ * allow auxiliary firmware updates from the OS.
+ *
+ * @param ctx Vboot context
+ * @return VBERROR_... error, VB2_SUCCESS on success.
+ */
+vb2_error_t vb2ex_auxfw_finalize(struct vb2_context *ctx);
+
+/*
* Abort vboot flow due to a failed assertion or broken assumption.
*
* Likely due to caller misusing vboot (e.g. calling API functions
diff --git a/firmware/2lib/include/2ec_sync.h b/firmware/2lib/include/2ec_sync.h
deleted file mode 100644
index 69ca2154..00000000
--- a/firmware/2lib/include/2ec_sync.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Copyright 2016 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.
- *
- * EC software sync for verified boot
- */
-
-#ifndef VBOOT_REFERENCE_2EC_SYNC_H_
-#define VBOOT_REFERENCE_2EC_SYNC_H_
-
-#include "2api.h"
-#include "vboot_api.h"
-
-/**
- * EC sync, phase 1
- *
- * This checks whether the EC is running the correct image to do EC sync, and
- * whether any updates are necessary.
- *
- * @param ctx Vboot2 context
- * @return VB2_SUCCESS, VBERROR_EC_REBOOT_TO_RO_REQUIRED if the EC must
- * reboot back to its RO code to continue EC sync, or other non-zero error
- * code.
- */
-vb2_error_t ec_sync_phase1(struct vb2_context *ctx);
-
-/**
- * Returns non-zero if the EC will perform a slow update during phase 2.
- *
- * This is only valid after calling ec_sync_phase1(), before calling
- * ec_sync_phase2().
- *
- * @param ctx Vboot2 context
- * @return non-zero if a slow update will be done; zero if no update or a
- * fast update.
- */
-int ec_will_update_slowly(struct vb2_context *ctx);
-
-/**
- * Check if auxiliary firmware blobs need to be updated.
- *
- * @param ctx Vboot2 context
- * @param severity VB_AUX_FW_{NO,FAST,SLOW}_UPDATE
- * @return VB2_SUCCESS or non-zero error code.
- */
-vb2_error_t ec_sync_check_aux_fw(struct vb2_context *ctx,
- enum vb2_auxfw_update_severity *severity);
-
-/**
- * Update and protect auxiliary firmware.
- *
- * @param ctx Vboot2 context
- * @return VB2_SUCCESS or non-zero error code.
- */
-vb2_error_t ec_sync_update_aux_fw(struct vb2_context *ctx);
-
-/**
- * EC sync, phase 2
- *
- * This updates the EC if necessary, makes sure it has protected its image(s),
- * and makes sure it has jumped to the correct image.
- *
- * If ec_will_update_slowly(), it is suggested that the caller display a
- * warning screen before calling phase 2.
- *
- * @param ctx Vboot2 context
- * @return VB2_SUCCESS, VBERROR_EC_REBOOT_TO_RO_REQUIRED if the EC must
- * reboot back to its RO code to continue EC sync, or other non-zero error
- * code.
- */
-vb2_error_t ec_sync_phase2(struct vb2_context *ctx);
-
-/**
- * EC sync, phase 3
- *
- * This completes EC sync and handles battery cutoff if needed.
- *
- * @param ctx Vboot2 context
- * @return VB2_SUCCESS or non-zero error code.
- */
-vb2_error_t ec_sync_phase3(struct vb2_context *ctx);
-
-/**
- * Sync all EC devices to expected versions.
- *
- * This is a high-level function which calls the functions above.
- *
- * @param ctx Vboot context
- * @return VB2_SUCCESS, or non-zero if error.
- */
-vb2_error_t ec_sync_all(struct vb2_context *ctx);
-
-#endif /* VBOOT_REFERENCE_2EC_SYNC_H_ */
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index 374bf85b..a1282974 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -720,46 +720,6 @@ vb2_error_t vb2ex_ec_vboot_done(struct vb2_context *ctx);
*/
vb2_error_t vb2ex_ec_battery_cutoff(void);
-/*
- * severity levels for an auxiliary firmware update request
- */
-enum vb2_auxfw_update_severity {
- /* no update needed and no protection needed */
- VB_AUX_FW_NO_DEVICE = 0,
- /* no update needed */
- VB_AUX_FW_NO_UPDATE = 1,
- /* update needed, can be done quickly */
- VB_AUX_FW_FAST_UPDATE = 2,
- /* update needed, "this would take a while..." */
- VB_AUX_FW_SLOW_UPDATE = 3,
-};
-
-/**
- * Perform auxiliary firmware checks.
- *
- * This is called after the EC has been updated and is intended to
- * version-check additional firmware blobs such as TCPCs.
- *
- * @param severity return parameter for health of auxiliary firmware
- * 0: no update needed
- * 1: fast update needed
- * 2: slow update needed
- * @return VB2_SUCCESS, or error code on error.
- */
-
-vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity);
-
-/**
- * Perform auxiliary firmware update(s).
- *
- * This is called after the EC has been updated and is intended to
- * update additional firmware blobs such as TCPCs.
- *
- * @return VB2_SUCCESS, or error code on error.
- */
-
-vb2_error_t vb2ex_auxfw_update(void);
-
/*****************************************************************************/
/* Misc */
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 52a5dcd0..facd1fea 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -5,8 +5,8 @@
* High-level firmware wrapper API - entry points for kernel selection
*/
+#include "2api.h"
#include "2common.h"
-#include "2ec_sync.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
@@ -371,7 +371,11 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
* it's just a single non-interactive WAIT screen.
*/
if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
- rv = ec_sync_all(ctx);
+ rv = vb2api_ec_sync(ctx);
+ if (rv)
+ goto VbSelectAndLoadKernel_exit;
+
+ rv = vb2api_auxfw_sync(ctx);
if (rv)
goto VbSelectAndLoadKernel_exit;
}
diff --git a/firmware/lib/vboot_ui.c b/firmware/lib/vboot_ui.c
index c8ef8cdc..642f149e 100644
--- a/firmware/lib/vboot_ui.c
+++ b/firmware/lib/vboot_ui.c
@@ -6,7 +6,6 @@
*/
#include "2common.h"
-#include "2ec_sync.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
diff --git a/firmware/lib/vboot_ui_menu.c b/firmware/lib/vboot_ui_menu.c
index 15859c23..89ac6323 100644
--- a/firmware/lib/vboot_ui_menu.c
+++ b/firmware/lib/vboot_ui_menu.c
@@ -6,7 +6,6 @@
*/
#include "2common.h"
-#include "2ec_sync.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
diff --git a/tests/vb2_ec_sync_tests.c b/tests/vb2_ec_sync_tests.c
index e668480c..241a1206 100644
--- a/tests/vb2_ec_sync_tests.c
+++ b/tests/vb2_ec_sync_tests.c
@@ -5,12 +5,7 @@
* Tests for vboot_api_kernel, part 3 - software sync
*/
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
#include "2common.h"
-#include "2ec_sync.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2sysincludes.h"
@@ -53,15 +48,17 @@ static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
static struct vb2_context *ctx;
static struct vb2_shared_data *sd;
static struct vb2_gbb_header gbb;
+static vb2_error_t ec_vboot_done_retval;
static uint32_t screens_displayed[8];
static uint32_t screens_count = 0;
-static vb2_error_t ec_aux_fw_retval;
-static int ec_aux_fw_update_req;
-static enum vb2_auxfw_update_severity ec_aux_fw_mock_severity;
-static enum vb2_auxfw_update_severity ec_aux_fw_update_severity;
-static int ec_aux_fw_protected;
+static vb2_error_t auxfw_retval;
+static int auxfw_update_req;
+static enum vb2_auxfw_update_severity auxfw_mock_severity;
+static enum vb2_auxfw_update_severity auxfw_update_severity;
+static int auxfw_protected;
+static vb2_error_t auxfw_done_retval;
/* Reset mock data (for use before each test) */
static void ResetMocks(void)
@@ -113,11 +110,12 @@ static void ResetMocks(void)
memset(screens_displayed, 0, sizeof(screens_displayed));
screens_count = 0;
- ec_aux_fw_retval = VB2_SUCCESS;
- ec_aux_fw_mock_severity = VB_AUX_FW_NO_UPDATE;
- ec_aux_fw_update_severity = VB_AUX_FW_NO_UPDATE;
- ec_aux_fw_update_req = 0;
- ec_aux_fw_protected = 0;
+ auxfw_retval = VB2_SUCCESS;
+ auxfw_mock_severity = VB_AUX_FW_NO_UPDATE;
+ auxfw_update_severity = VB_AUX_FW_NO_UPDATE;
+ auxfw_update_req = 0;
+ auxfw_protected = 0;
+ auxfw_done_retval = VB2_SUCCESS;
}
/* Mock functions */
@@ -218,31 +216,44 @@ vb2_error_t VbDisplayScreen(struct vb2_context *c, uint32_t screen, int force,
return VB2_SUCCESS;
}
+vb2_error_t vb2ex_ec_vboot_done(struct vb2_context *c)
+{
+ return ec_vboot_done_retval;
+}
+
vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity)
{
- *severity = ec_aux_fw_mock_severity;
- ec_aux_fw_update_severity = ec_aux_fw_mock_severity;
+ *severity = auxfw_mock_severity;
+ auxfw_update_severity = auxfw_mock_severity;
return VB2_SUCCESS;
}
-vb2_error_t vb2ex_auxfw_update()
+vb2_error_t vb2ex_auxfw_update(void)
{
- if (ec_aux_fw_update_severity != VB_AUX_FW_NO_DEVICE &&
- ec_aux_fw_update_severity != VB_AUX_FW_NO_UPDATE)
- ec_aux_fw_update_req = 1;
- return ec_aux_fw_retval;
+ if (auxfw_update_severity != VB_AUX_FW_NO_DEVICE &&
+ auxfw_update_severity != VB_AUX_FW_NO_UPDATE)
+ auxfw_update_req = 1;
+ return auxfw_retval;
}
-vb2_error_t vb2ex_ec_vboot_done(struct vb2_context *c)
+vb2_error_t vb2ex_auxfw_finalize(struct vb2_context *c)
{
- ec_aux_fw_protected = ec_aux_fw_update_severity != VB_AUX_FW_NO_DEVICE;
- return ec_aux_fw_retval;
+ auxfw_protected = auxfw_update_severity != VB_AUX_FW_NO_DEVICE;
+ return auxfw_done_retval;
}
static void test_ssync(vb2_error_t retval, int recovery_reason,
const char *desc)
{
- TEST_EQ(ec_sync_all(ctx), retval, desc);
+ TEST_EQ(vb2api_ec_sync(ctx), retval, desc);
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
+ recovery_reason, " recovery reason");
+}
+
+static void test_auxsync(vb2_error_t retval, int recovery_reason,
+ const char *desc)
+{
+ TEST_EQ(vb2api_auxfw_sync(ctx), retval, desc);
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
recovery_reason, " recovery reason");
}
@@ -434,69 +445,79 @@ static void VbSoftwareSyncTest(void)
ResetMocks();
gbb.flags |= VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC;
- ec_aux_fw_mock_severity = VB_AUX_FW_FAST_UPDATE;
+ auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE;
test_ssync(VB2_SUCCESS, 0,
"VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC"
" disables auxiliary FW update request");
- TEST_EQ(ec_aux_fw_update_req, 0, " aux fw update disabled");
- TEST_EQ(ec_aux_fw_protected, 1, " aux fw protected");
+ test_auxsync(VB2_SUCCESS, 0,
+ "VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC"
+ " disables auxiliary FW update request");
+ TEST_EQ(auxfw_update_req, 0, " aux fw update disabled");
+ TEST_EQ(auxfw_protected, 1, " aux fw protected");
ResetMocks();
gbb.flags |= VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC;
- ec_aux_fw_mock_severity = VB_AUX_FW_FAST_UPDATE;
+ auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE;
test_ssync(VB2_SUCCESS, 0,
"VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC"
" disables auxiliary FW update request");
- TEST_EQ(ec_aux_fw_update_req, 0, " aux fw update disabled");
- TEST_EQ(ec_aux_fw_protected, 1, " aux fw protected");
+ test_auxsync(VB2_SUCCESS, 0,
+ "VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC"
+ " disables auxiliary FW update request");
+ TEST_EQ(auxfw_update_req, 0, " aux fw update disabled");
+ TEST_EQ(auxfw_protected, 1, " aux fw protected");
ResetMocks();
- ec_aux_fw_mock_severity = VB_AUX_FW_NO_DEVICE;
+ auxfw_mock_severity = VB_AUX_FW_NO_DEVICE;
test_ssync(VB2_SUCCESS, 0,
"No auxiliary FW update needed");
TEST_EQ(screens_count, 0,
" wait screen skipped");
- TEST_EQ(ec_aux_fw_update_req, 0, " no aux fw update requested");
- TEST_EQ(ec_aux_fw_protected, 0, " no aux fw protected");
+ test_auxsync(VB2_SUCCESS, 0,
+ "No auxiliary FW update needed");
+ TEST_EQ(auxfw_update_req, 0, " no aux fw update requested");
+ TEST_EQ(auxfw_protected, 0, " aux fw protected");
ResetMocks();
- ec_aux_fw_mock_severity = VB_AUX_FW_NO_UPDATE;
+ auxfw_mock_severity = VB_AUX_FW_NO_UPDATE;
test_ssync(VB2_SUCCESS, 0,
"No auxiliary FW update needed");
TEST_EQ(screens_count, 0,
" wait screen skipped");
- TEST_EQ(ec_aux_fw_update_req, 0, " no aux fw update requested");
- TEST_EQ(ec_aux_fw_protected, 1, " aux fw protected");
+ test_auxsync(VB2_SUCCESS, 0,
+ "No auxiliary FW update needed");
+ TEST_EQ(auxfw_update_req, 0, " no aux fw update requested");
+ TEST_EQ(auxfw_protected, 1, " aux fw protected");
ResetMocks();
- ec_aux_fw_mock_severity = VB_AUX_FW_FAST_UPDATE;
- test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 0,
- "Fast auxiliary FW update needed");
+ auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE;
+ test_auxsync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 0,
+ "Fast auxiliary FW update needed");
TEST_EQ(screens_count, 0,
" wait screen skipped");
- TEST_EQ(ec_aux_fw_update_req, 1, " aux fw update requested");
- TEST_EQ(ec_aux_fw_protected, 0, " aux fw protected");
+ TEST_EQ(auxfw_update_req, 1, " aux fw update requested");
+ TEST_EQ(auxfw_protected, 0, " aux fw protected");
ResetMocks();
- ec_aux_fw_mock_severity = VB_AUX_FW_SLOW_UPDATE;
+ auxfw_mock_severity = VB_AUX_FW_SLOW_UPDATE;
sd->flags &= ~VB2_SD_FLAG_DISPLAY_AVAILABLE;
- test_ssync(VBERROR_REBOOT_REQUIRED, 0,
- "Slow auxiliary FW update needed - reboot for display");
+ test_auxsync(VBERROR_REBOOT_REQUIRED, 0,
+ "Slow auxiliary FW update needed - reboot for display");
ResetMocks();
- ec_aux_fw_mock_severity = VB_AUX_FW_SLOW_UPDATE;
- test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 0,
- "Slow auxiliary FW update needed");
- TEST_EQ(ec_aux_fw_update_req, 1, " aux fw update requested");
- TEST_EQ(ec_aux_fw_protected, 0, " aux fw protected");
+ auxfw_mock_severity = VB_AUX_FW_SLOW_UPDATE;
+ test_auxsync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 0,
+ "Slow auxiliary FW update needed");
+ TEST_EQ(auxfw_update_req, 1, " aux fw update requested");
+ TEST_EQ(auxfw_protected, 0, " aux fw protected");
TEST_EQ(screens_displayed[0], VB_SCREEN_WAIT,
" wait screen forced");
ResetMocks();
- ec_aux_fw_mock_severity = VB_AUX_FW_FAST_UPDATE;
- ec_aux_fw_retval = VB2_ERROR_UNKNOWN;
- test_ssync(VB2_ERROR_UNKNOWN, VB2_RECOVERY_AUX_FW_UPDATE,
- "Error updating AUX firmware");
+ auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE;
+ auxfw_retval = VB2_ERROR_UNKNOWN;
+ test_auxsync(VB2_ERROR_UNKNOWN, VB2_RECOVERY_AUX_FW_UPDATE,
+ "Error updating AUX firmware");
}
int main(void)
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
index 584a134e..c168f82d 100644
--- a/tests/vboot_api_kernel4_tests.c
+++ b/tests/vboot_api_kernel4_tests.c
@@ -7,7 +7,6 @@
#include "2api.h"
#include "2common.h"
-#include "2ec_sync.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2secdata.h"