summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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"