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.c103
1 files changed, 71 insertions, 32 deletions
diff --git a/firmware/2lib/2ec_sync.c b/firmware/2lib/2ec_sync.c
index cba6782e..1871b50c 100644
--- a/firmware/2lib/2ec_sync.c
+++ b/firmware/2lib/2ec_sync.c
@@ -9,10 +9,12 @@
#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
+#include "2secdata.h"
#include "2sysincludes.h"
#include "vboot_api.h"
#include "vboot_display.h"
#include "vboot_kernel.h"
+#include "vboot_test.h"
#define SYNC_FLAG(select) \
((select) == VB_SELECT_FIRMWARE_READONLY ? \
@@ -61,12 +63,9 @@ static vb2_error_t protect_ec(struct vb2_context *ctx,
* @param hash_size Size of the hash in bytes
* @param desc Description of what's being hashed
*/
-static void print_hash(const uint8_t *hash, uint32_t hash_size,
- const char *desc)
+static void print_hash(const uint8_t *hash, uint32_t hash_size)
{
int i;
-
- VB2_DEBUG("%s hash: ", desc);
for (i = 0; i < hash_size; i++)
VB2_DEBUG_RAW("%02x", hash[i]);
VB2_DEBUG_RAW("\n");
@@ -97,36 +96,70 @@ static vb2_error_t check_ec_hash(struct vb2_context *ctx,
enum vb2_firmware_selection select)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ const uint8_t *hexp = NULL;
+ const uint8_t *hmir = NULL;
+ const uint8_t *heff = NULL;
+ int hexp_len, heff_len;
+ const int hmir_len = VB2_SHA256_DIGEST_SIZE;
+ vb2_error_t rv;
- /* Get current EC hash. */
- const uint8_t *ec_hash = NULL;
- int ec_hash_size;
- vb2_error_t rv = vb2ex_ec_hash_image(select, &ec_hash, &ec_hash_size);
+ /*
+ * Get expected EC hash and length.
+ */
+ rv = vb2ex_ec_get_expected_image_hash(select, &hexp, &hexp_len);
+ if (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;
+ }
+ VB2_DEBUG("Hexp %10s: ", image_name_to_string(select));
+ print_hash(hexp, hexp_len);
+
+ /*
+ * Get mirrored EC hash. This returns NULL on old systems. On new
+ * systems without EFS2, Hmir will be updated but unused.
+ *
+ * If it's called from update_ec, Hmir and Hexp are already synced.
+ */
+ hmir = vb2_secdata_kernel_get_ec_hash(ctx);
+ if (hmir && select == VB_SELECT_FIRMWARE_EC_ACTIVE) {
+ VB2_DEBUG(" %10s: ", "Hmir");
+ print_hash(hmir, hmir_len);
+ if (hmir_len != hexp_len) {
+ VB2_DEBUG("Hmir size (%d) != Hexp size (%d)\n",
+ hmir_len, hexp_len);
+ request_recovery(ctx, VB2_RECOVERY_EC_HASH_SIZE);
+ return VB2_ERROR_EC_HASH_SIZE;
+ }
+ if (vb2_safe_memcmp(hmir, hexp, hexp_len)) {
+ VB2_DEBUG("Hmir != Hexp. Update Hmir.\n");
+ vb2_secdata_kernel_set_ec_hash(ctx, hexp);
+ }
+ }
+
+ /*
+ * Get effective EC hash and length.
+ */
+ rv = vb2ex_ec_hash_image(select, &heff, &heff_len);
if (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;
}
- print_hash(ec_hash, ec_hash_size, image_name_to_string(select));
+ VB2_DEBUG("Heff %10s: ", image_name_to_string(select));
+ print_hash(heff, heff_len);
- /* Get expected EC hash. */
- const uint8_t *hash = NULL;
- 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 %#x\n", rv);
- request_recovery(ctx, VB2_RECOVERY_EC_EXPECTED_HASH);
- return VB2_ERROR_EC_HASH_EXPECTED;
- }
- if (ec_hash_size != hash_size) {
- VB2_DEBUG("EC uses %d-byte hash, but AP-RW contains %d bytes\n",
- ec_hash_size, hash_size);
+ /* Lengths should match. */
+ if (heff_len != hexp_len) {
+ VB2_DEBUG("EC uses %d-byte hash but AP-RW contains %d bytes\n",
+ heff_len, hexp_len);
request_recovery(ctx, VB2_RECOVERY_EC_HASH_SIZE);
return VB2_ERROR_EC_HASH_SIZE;
}
- if (vb2_safe_memcmp(ec_hash, hash, hash_size)) {
- print_hash(hash, hash_size, "Expected");
+ if (vb2_safe_memcmp(heff, hexp, hexp_len)) {
+ VB2_DEBUG("Heff != Hexp. Schedule update\n");
sd->flags |= SYNC_FLAG(select);
}
@@ -177,6 +210,8 @@ static vb2_error_t update_ec(struct vb2_context *ctx,
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
+ VB2_DEBUG("Updated %s successfully\n", image_name_to_string(select));
+
return VB2_SUCCESS;
}
@@ -226,21 +261,23 @@ static vb2_error_t sync_ec(struct vb2_context *ctx)
const enum vb2_firmware_selection select_rw = EC_EFS ?
VB_SELECT_FIRMWARE_EC_UPDATE :
VB_SELECT_FIRMWARE_EC_ACTIVE;
- VB2_DEBUG("select_rw=%d\n", select_rw);
+ VB2_DEBUG("select_rw=%s\n", image_name_to_string(select_rw));
/* Update the RW Image */
if (sd->flags & SYNC_FLAG(select_rw)) {
if (VB2_SUCCESS != update_ec(ctx, select_rw))
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- /* Updated successfully. Cold reboot to switch to the new RW.
- * TODO: Switch slot and proceed if EC is still in RO. */
- if (EC_EFS) {
+ /* Updated successfully. Cold reboot to switch to the new RW. */
+ if (ctx->flags & VB2_CONTEXT_NO_BOOT) {
VB2_DEBUG("Rebooting to jump to new EC-RW\n");
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+ } else if (EC_EFS) {
+ VB2_DEBUG("Rebooting to switch to new EC-RW\n");
return VBERROR_EC_REBOOT_TO_SWITCH_RW;
}
}
- /* Tell EC to jump to its RW image */
+ /* Tell EC to jump to RW. It should already be in RW for EFS2. */
if (!(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW)) {
VB2_DEBUG("jumping to EC-RW\n");
rv = vb2ex_ec_jump_to_rw();
@@ -344,9 +381,10 @@ static vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
if (check_ec_active(ctx))
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- /* Check if we need to update RW. Failures trigger recovery mode. */
+ /* Check if we need to update RW. Failures trigger recovery mode. */
if (check_ec_hash(ctx, VB_SELECT_FIRMWARE_EC_ACTIVE))
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+
/* See if we need to update EC-RO. */
if (vb2_nv_get(ctx, VB2_NV_TRY_RO_SYNC) &&
check_ec_hash(ctx, VB_SELECT_FIRMWARE_READONLY)) {
@@ -360,7 +398,7 @@ static vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
* If EC supports RW-A/B slots, we can proceed but we need
* to jump to the new RW version later.
*/
- if ((sd->flags & VB2_SD_FLAG_ECSYNC_EC_RW) &&
+ if ((sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_EC_ACTIVE)) &&
(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW) && !EC_EFS) {
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
@@ -382,8 +420,9 @@ static int ec_will_update_slowly(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
- return (((sd->flags & VB2_SD_FLAG_ECSYNC_EC_RO) ||
- (sd->flags & VB2_SD_FLAG_ECSYNC_EC_RW)) && EC_SLOW_UPDATE);
+ return (((sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_READONLY)) ||
+ (sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_EC_ACTIVE)))
+ && EC_SLOW_UPDATE);
}
/**