diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-07-23 16:24:43 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-07-25 18:07:20 -0700 |
commit | 241de33babbb13eec2ca2d1f7bc86964f7b3258f (patch) | |
tree | 976648a115a10c54c8f913ae78de856620cef59e /firmware | |
parent | 6008fb4d318ecf6737efc90f6b9757c0abeacab0 (diff) | |
download | vboot-241de33babbb13eec2ca2d1f7bc86964f7b3258f.tar.gz |
EC software sync now updates RW firmware if necessary.
BUG=chrome-os-partner:11087
TEST=manual
1. Update EC to a new version
2. Rebuild EC code and chromeos-bootimage
3. Update BIOS (AP) RW firmware
4. Reboot. EC should get updated to the version in the BIOS iamge.
CQ-DEPEND=28414
Change-Id: I227d9bf7cc1f4984d6eb13b5372bcf4181ad0df5
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/28415
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 109 |
1 files changed, 81 insertions, 28 deletions
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 359c6366..c87a05af 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -355,6 +355,9 @@ VbError_t VbEcSoftwareSync(VbSharedDataHeader *shared) { int ec_hash_size; const uint8_t *expected; int expected_size; + uint8_t expected_hash[SHA256_DIGEST_SIZE]; + int need_update; + int i; if (shared->recovery_reason) { /* Recovery mode; just verify the EC is in RO code */ @@ -407,9 +410,12 @@ VbError_t VbEcSoftwareSync(VbSharedDataHeader *shared) { VBDEBUG(("VbEcSoftwareSync() in RO-Normal; EC-RO\n")); - /* TODO: If EC-RW wasn't protected when we started, then this boot was - * simply to verify the EC. Shut down instead of continuing. */ - + /* TODO: If there was no wake event from the EC (such as power button or + * lid-open), shut down. The AP was powered on simply to verify the EC. + * + * Make sure this doesn't shut down when we're leaving recovery mode and + * jumping back to RW code, though. EC can't currently track that, + * though that could be passed as an additional reboot flag to the EC. */ return VBERROR_SUCCESS; } @@ -420,7 +426,17 @@ VbError_t VbEcSoftwareSync(VbSharedDataHeader *shared) { VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC); return VBERROR_EC_REBOOT_TO_RO_REQUIRED; } - VBDEBUG(("VbEcSoftwareSync() - hash len = %d\n", ec_hash_size)); + if (ec_hash_size != SHA256_DIGEST_SIZE) { + VBDEBUG(("VbEcSoftwareSync() - VbExEcHashRW() returned wrong size %d\n", + ec_hash_size)); + VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC); + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; + } + + VBDEBUG(("EC hash:")); + for (i = 0; i < SHA256_DIGEST_SIZE; i++) + VBDEBUG(("%02x", ec_hash[i])); + VBDEBUG(("\n")); /* Get expected EC-RW code. Note that we've already checked for RO_NORMAL, * so we know that the BIOS must be RW-A or RW-B, and therefore the EC must @@ -429,45 +445,82 @@ VbError_t VbEcSoftwareSync(VbSharedDataHeader *shared) { 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_SOFTWARE_SYNC); - return VBERROR_EC_REBOOT_TO_RO_REQUIRED; + VBDEBUG(("VbEcSoftwareSync() - VbExEcGetExpectedRW() returned %d\n", rv)); + VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC); + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; } VBDEBUG(("VbEcSoftwareSync() - expected len = %d\n", expected_size)); - /* TODO: verify EC-RW hash vs. expected code */ + /* 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")); - if (in_rw) { - /* TODO: if hash doesn't verify, reboot EC so we can reflash it - * with the expected code. */ - VBDEBUG(("VbEcSoftwareSync() in RW; EC-RW\n")); - return VBERROR_SUCCESS; + need_update = SafeMemcmp(ec_hash, expected_hash, SHA256_DIGEST_SIZE); - } else { - /* TODO: if hash doesn't verify, reflash it with expected code. */ + /* TODO: GBB flag to override whether we need update; needed for EC + * development */ - /* Protect EC-RW flash */ - rv = VbExEcProtectRW(); - if (rv != VBERROR_SUCCESS) { - VBDEBUG(("VbEcSoftwareSync() - VbExEcProtectRW() returned %d\n", rv)); - VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC); + if (in_rw) { + if (need_update) { + /* EC is running the wrong RW code. Reboot the EC to RO so we can update + * it on the next boot. */ + VBDEBUG(("VbEcSoftwareSync() - in RW, need to update RW, so reboot\n")); return VBERROR_EC_REBOOT_TO_RO_REQUIRED; } - /* Tell EC to jump to its RW code */ - VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n")); - rv = VbExEcJumpToRW(); + VBDEBUG(("VbEcSoftwareSync() in EC-RW and it matches\n")); + return VBERROR_SUCCESS; + } + + /* Update EC if necessary */ + if (need_update) { + VBDEBUG(("VbEcSoftwareSync() updating EC-RW...\n")); + + /* + * TODO: need flag passed into VbInit that EC update is slow; if it is, + * display an "updating" screen while the update happens. + */ + + rv = VbExEcUpdateRW(expected, expected_size); if (rv != VBERROR_SUCCESS) { - VBDEBUG(("VbEcSoftwareSync() - VbExEcJumpToRW() returned %d\n", rv)); + VBDEBUG(("VbEcSoftwareSync() - VbExEcUpdateRW() returned %d\n", rv)); VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC); return VBERROR_EC_REBOOT_TO_RO_REQUIRED; } - /* TODO: If there was no wake event from the EC (such as power button or - * lid-open), shut down. The AP was powered on simply to verify the EC. */ - VBDEBUG(("VbEcSoftwareSync() in RW; done jumping to EC-RW\n")); - return VBERROR_SUCCESS; + /* + * TODO: should ask EC to recompute its hash to verify it's correct + * before continuing? + */ + } + + /* Protect EC-RW flash */ + rv = VbExEcProtectRW(); + if (rv != VBERROR_SUCCESS) { + VBDEBUG(("VbEcSoftwareSync() - VbExEcProtectRW() returned %d\n", rv)); + VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC); + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; } + + /* Tell EC to jump to its RW code */ + VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n")); + rv = VbExEcJumpToRW(); + if (rv != VBERROR_SUCCESS) { + VBDEBUG(("VbEcSoftwareSync() - VbExEcJumpToRW() returned %d\n", rv)); + VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC); + return VBERROR_EC_REBOOT_TO_RO_REQUIRED; + } + + /* TODO: If there was no wake event from the EC (such as power button or + * lid-open), shut down. The AP was powered on simply to verify the EC. + * + * Make sure this doesn't shut down when we're leaving recovery mode and + * jumping back to RW code, though. */ + VBDEBUG(("VbEcSoftwareSync() in RW; done\n")); + return VBERROR_SUCCESS; } |