diff options
Diffstat (limited to 'firmware/lib/ec_sync.c')
-rw-r--r-- | firmware/lib/ec_sync.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/firmware/lib/ec_sync.c b/firmware/lib/ec_sync.c index baf3cfc2..35fae2de 100644 --- a/firmware/lib/ec_sync.c +++ b/firmware/lib/ec_sync.c @@ -202,11 +202,29 @@ static VbError_t update_ec(struct vb2_context *ctx, int devidx, * @param ctx Vboot2 context * @param devidx Which device (EC=0, PD=1) */ -static void check_ec_active(struct vb2_context *ctx, int devidx) +static VbError_t check_ec_active(struct vb2_context *ctx, int devidx) { struct vb2_shared_data *sd = vb2_get_sd(ctx); - if (!VbExTrustEC(devidx)) + int in_rw = 0; + /* + * We don't use VbExTrustEC, which checks EC_IN_RW. It is controlled by + * cr50 but on some platforms, cr50 can't know when a EC resets. So, we + * trust what EC-RW says. If it lies it's in RO, we'll flash RW while + * it's in RW. + */ + int rv = VbExEcRunningRW(devidx, &in_rw); + + /* If we couldn't determine where the EC was, reboot to recovery. */ + if (rv != VBERROR_SUCCESS) { + VB2_DEBUG("VbExEcRunningRW() returned %d\n", rv); + request_recovery(ctx, VB2_RECOVERY_EC_UNKNOWN_IMAGE); + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; + } + + if (in_rw) sd->flags |= IN_RW(devidx); + + return VBERROR_SUCCESS; } #define RO_RETRIES 2 /* Maximum times to retry flashing RO */ @@ -341,9 +359,10 @@ VbError_t ec_sync_phase1(struct vb2_context *ctx, VbCommonParams *cparams) #endif /* Set IN_RW flags */ - check_ec_active(ctx, 0); - if (do_pd_sync) - check_ec_active(ctx, 1); + if (check_ec_active(ctx, 0)) + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; + if (do_pd_sync && check_ec_active(ctx, 1)) + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; /* Check if we need to update RW. Failures trigger recovery mode. */ if (check_ec_hash(ctx, 0, VB_SELECT_FIRMWARE_EC_ACTIVE)) |