summaryrefslogtreecommitdiff
path: root/firmware/2lib/2ec_sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/2lib/2ec_sync.c')
-rw-r--r--firmware/2lib/2ec_sync.c208
1 files changed, 96 insertions, 112 deletions
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);
}