mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-23 16:27:21 +00:00
EC software sync uses precomputed hash if available
This removes the need to load the EC code at all when the precomputed hash matches. BUG=chrome-os-partner:17606 BRANCH=spring TEST=wouldn't that be nice Change-Id: If4438b9db8b1449b8fd4d90ef3acb3bbec5e09a0 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/42567
This commit is contained in:
committed by
ChromeBot
parent
9a8e79cc26
commit
5ca4ea087a
@@ -142,6 +142,10 @@ typedef enum VbNvParam {
|
|||||||
#define VBNV_RECOVERY_EC_JUMP_RW 0x27
|
#define VBNV_RECOVERY_EC_JUMP_RW 0x27
|
||||||
/* EC software sync - unable to protect / unprotect EC-RW */
|
/* EC software sync - unable to protect / unprotect EC-RW */
|
||||||
#define VBNV_RECOVERY_EC_PROTECT 0x28
|
#define VBNV_RECOVERY_EC_PROTECT 0x28
|
||||||
|
/* EC software sync - error obtaining expected EC hash */
|
||||||
|
#define VBNV_RECOVERY_EC_EXPECTED_HASH 0x29
|
||||||
|
/* EC software sync - expected EC image doesn't match hash */
|
||||||
|
#define VBNV_RECOVERY_EC_HASH_MISMATCH 0x2A
|
||||||
/* Unspecified/unknown error in read-only firmware */
|
/* Unspecified/unknown error in read-only firmware */
|
||||||
#define VBNV_RECOVERY_RO_UNSPECIFIED 0x3F
|
#define VBNV_RECOVERY_RO_UNSPECIFIED 0x3F
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -555,12 +555,14 @@ VbError_t VbEcSoftwareSync(VbCommonParams *cparams)
|
|||||||
(VbSharedDataHeader *)cparams->shared_data_blob;
|
(VbSharedDataHeader *)cparams->shared_data_blob;
|
||||||
int in_rw = 0;
|
int in_rw = 0;
|
||||||
int rv;
|
int rv;
|
||||||
const uint8_t *ec_hash;
|
const uint8_t *ec_hash = NULL;
|
||||||
int ec_hash_size;
|
int ec_hash_size;
|
||||||
const uint8_t *expected;
|
const uint8_t *rw_hash = NULL;
|
||||||
|
int rw_hash_size;
|
||||||
|
const uint8_t *expected = NULL;
|
||||||
int expected_size;
|
int expected_size;
|
||||||
uint8_t expected_hash[SHA256_DIGEST_SIZE];
|
uint8_t expected_hash[SHA256_DIGEST_SIZE];
|
||||||
int need_update;
|
int need_update = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Determine whether the EC is in RO or RW */
|
/* Determine whether the EC is in RO or RW */
|
||||||
@@ -660,29 +662,87 @@ VbError_t VbEcSoftwareSync(VbCommonParams *cparams)
|
|||||||
VBDEBUG(("\n"));
|
VBDEBUG(("\n"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get expected EC-RW code. Note that we've already checked for
|
* Get expected EC-RW hash. Note that we've already checked for
|
||||||
* RO_NORMAL, so we know that the BIOS must be RW-A or RW-B, and
|
* RO_NORMAL, so we know that the BIOS must be RW-A or RW-B, and
|
||||||
* therefore the EC must match.
|
* therefore the EC must match.
|
||||||
*/
|
*/
|
||||||
rv = VbExEcGetExpectedRW(shared->firmware_index ?
|
rv = VbExEcGetExpectedRWHash(shared->firmware_index ?
|
||||||
VB_SELECT_FIRMWARE_B : VB_SELECT_FIRMWARE_A,
|
VB_SELECT_FIRMWARE_B : VB_SELECT_FIRMWARE_A,
|
||||||
&expected, &expected_size);
|
&rw_hash, &rw_hash_size);
|
||||||
if (rv) {
|
|
||||||
|
if (rv == VBERROR_EC_GET_EXPECTED_HASH_FROM_IMAGE) {
|
||||||
|
/*
|
||||||
|
* BIOS has verified EC image but doesn't have a precomputed
|
||||||
|
* hash for it, so we must compute the hash ourselves.
|
||||||
|
*/
|
||||||
|
rw_hash = NULL;
|
||||||
|
} else if (rv) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"VbExEcGetExpectedRWHash() returned %d\n", rv));
|
||||||
|
VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
} else if (rw_hash_size != SHA256_DIGEST_SIZE) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"VbExEcGetExpectedRWHash() says size %d, not %d\n",
|
||||||
|
rw_hash_size, SHA256_DIGEST_SIZE));
|
||||||
|
VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
} else {
|
||||||
|
VBDEBUG(("Expected hash:"));
|
||||||
|
for (i = 0; i < SHA256_DIGEST_SIZE; i++)
|
||||||
|
VBDEBUG(("%02x", rw_hash[i]));
|
||||||
|
VBDEBUG(("\n"));
|
||||||
|
|
||||||
|
need_update = SafeMemcmp(ec_hash, rw_hash, SHA256_DIGEST_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get expected EC-RW image if we're sure we need to update (because the
|
||||||
|
* expected hash didn't match the EC) or we still don't know (because
|
||||||
|
* there was no expected hash and we need the image to compute one
|
||||||
|
* ourselves).
|
||||||
|
*/
|
||||||
|
if (need_update || !rw_hash) {
|
||||||
|
/* Get expected EC-RW image */
|
||||||
|
rv = VbExEcGetExpectedRW(shared->firmware_index ?
|
||||||
|
VB_SELECT_FIRMWARE_B :
|
||||||
|
VB_SELECT_FIRMWARE_A,
|
||||||
|
&expected, &expected_size);
|
||||||
|
if (rv) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"VbExEcGetExpectedRW() returned %d\n", rv));
|
||||||
|
VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - expected len = %d\n",
|
||||||
|
expected_size));
|
||||||
|
|
||||||
|
/* Hash expected image */
|
||||||
|
internal_SHA256(expected, expected_size, expected_hash);
|
||||||
|
VBDEBUG(("Computed hash of expected image:"));
|
||||||
|
for (i = 0; i < SHA256_DIGEST_SIZE; i++)
|
||||||
|
VBDEBUG(("%02x", expected_hash[i]));
|
||||||
|
VBDEBUG(("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rw_hash) {
|
||||||
|
/*
|
||||||
|
* BIOS didn't have expected EC hash, so check if we need
|
||||||
|
* update by comparing EC hash to the one we just computed.
|
||||||
|
*/
|
||||||
|
need_update = SafeMemcmp(ec_hash, expected_hash,
|
||||||
|
SHA256_DIGEST_SIZE);
|
||||||
|
} else if (need_update &&
|
||||||
|
SafeMemcmp(rw_hash, expected_hash, SHA256_DIGEST_SIZE)) {
|
||||||
|
/*
|
||||||
|
* We need to update, but the expected EC image doesn't match
|
||||||
|
* the expected EC hash we were given.
|
||||||
|
*/
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
"VbExEcGetExpectedRW() returned %d\n", rv));
|
"VbExEcGetExpectedRW() returned %d\n", rv));
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
|
VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_MISMATCH);
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
}
|
}
|
||||||
VBDEBUG(("VbEcSoftwareSync() - expected len = %d\n", expected_size));
|
|
||||||
|
|
||||||
/* Hash expected code */
|
|
||||||
internal_SHA256(expected, expected_size, expected_hash);
|
|
||||||
VBDEBUG(("Expected hash:"));
|
|
||||||
for (i = 0; i < SHA256_DIGEST_SIZE; i++)
|
|
||||||
VBDEBUG(("%02x", expected_hash[i]));
|
|
||||||
VBDEBUG(("\n"));
|
|
||||||
|
|
||||||
need_update = SafeMemcmp(ec_hash, expected_hash, SHA256_DIGEST_SIZE);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: GBB flag to override whether we need update; needed for EC
|
* TODO: GBB flag to override whether we need update; needed for EC
|
||||||
@@ -692,7 +752,7 @@ VbError_t VbEcSoftwareSync(VbCommonParams *cparams)
|
|||||||
if (in_rw) {
|
if (in_rw) {
|
||||||
if (need_update) {
|
if (need_update) {
|
||||||
/*
|
/*
|
||||||
* EC is running the wrong RW code. Reboot the EC to
|
* EC is running the wrong RW image. Reboot the EC to
|
||||||
* RO so we can update it on the next boot.
|
* RO so we can update it on the next boot.
|
||||||
*/
|
*/
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
@@ -747,7 +807,7 @@ VbError_t VbEcSoftwareSync(VbCommonParams *cparams)
|
|||||||
if (rv != VBERROR_SUCCESS)
|
if (rv != VBERROR_SUCCESS)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
/* Tell EC to jump to its RW code */
|
/* Tell EC to jump to its RW image */
|
||||||
VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n"));
|
VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n"));
|
||||||
rv = VbExEcJumpToRW();
|
rv = VbExEcJumpToRW();
|
||||||
if (rv != VBERROR_SUCCESS) {
|
if (rv != VBERROR_SUCCESS) {
|
||||||
|
|||||||
@@ -497,6 +497,12 @@ const char *RecoveryReasonString(uint8_t code)
|
|||||||
case VBNV_RECOVERY_EC_EXPECTED_IMAGE:
|
case VBNV_RECOVERY_EC_EXPECTED_IMAGE:
|
||||||
return "EC software sync error "
|
return "EC software sync error "
|
||||||
"obtaining expected EC image from BIOS";
|
"obtaining expected EC image from BIOS";
|
||||||
|
case VBNV_RECOVERY_EC_EXPECTED_HASH:
|
||||||
|
return "EC software sync error "
|
||||||
|
"obtaining expected EC hash from BIOS";
|
||||||
|
case VBNV_RECOVERY_EC_HASH_MISMATCH:
|
||||||
|
return "EC software sync error "
|
||||||
|
"comparing expected EC hash and image";
|
||||||
case VBNV_RECOVERY_EC_UPDATE:
|
case VBNV_RECOVERY_EC_UPDATE:
|
||||||
return "EC software sync error updating EC";
|
return "EC software sync error updating EC";
|
||||||
case VBNV_RECOVERY_EC_JUMP_RW:
|
case VBNV_RECOVERY_EC_JUMP_RW:
|
||||||
|
|||||||
@@ -181,6 +181,19 @@ VbError_t VbExEcGetExpectedRW(enum VbSelectFirmware_t select,
|
|||||||
return VBERROR_SUCCESS;
|
return VBERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the SHA-256 hash of the expected contents of the EC image associated
|
||||||
|
* with the main firmware specified by the "select" argument.
|
||||||
|
*/
|
||||||
|
VbError_t VbExEcGetExpectedRWHash(enum VbSelectFirmware_t select,
|
||||||
|
const uint8_t **hash, int *hash_size) {
|
||||||
|
static const uint8_t fake_hash[32] = {1, 2, 3, 4};
|
||||||
|
|
||||||
|
*hash = fake_hash;
|
||||||
|
*hash_size = sizeof(fake_hash);
|
||||||
|
return VBERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
VbError_t VbExEcUpdateRW(const uint8_t *image, int image_size) {
|
VbError_t VbExEcUpdateRW(const uint8_t *image, int image_size) {
|
||||||
return VBERROR_SUCCESS;
|
return VBERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user