summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-06-20 15:14:47 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-09-15 22:29:04 +0000
commit0b227569bd8e497817db2113cf38b8121d0868bb (patch)
treeb58e8d57480b31a5e2b9587b36a61b0ae24b632b
parenta47188021ca76c59abe2a3fb979d0f708c081481 (diff)
downloadchrome-ec-0b227569bd8e497817db2113cf38b8121d0868bb.tar.gz
g: cr50: update INFO1 mask when corrupting the second image
The INFO1 mask field contents serves as input for the rollback protection mechanism, when the RO decides if an RW is allowed to run on the device. The existing code updates INFO1 mask to match the lowest rollback priority of the two images (RW_A and RW_B) present on the device. INFO1 mask should be also updated when the current image is endorsed by the host. In this case the alternative RW is destroyed, so the INFO1 mask could be set based solely on the currently running image. This patch refactors the code to allow setting INFO1 mask based on one or both RW headers' contents. BRANCH=cr50 BUG=b:62138152 TEST=verified that "normal" INFO1 mask updates still work as before, the mask is modified to match the image with the lowest rollback priority. Also verified that when the VENDOR_CC_INVALIDATE_INACTIVE_RW command is received the INFO1 mask is updated based on the currently running image. Change-Id: I23172388674e1f3a4c2489e139dd197a84029f54 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/541738 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Mary Ruthven <mruthven@chromium.org> (cherry picked from commit e7ebdfeefc4dfd38dfcb4ef57dbd5fd4e9029639) Reviewed-on: https://chromium-review.googlesource.com/556238 (cherry picked from commit 77b0e4d34ddb8913c68c246d71a757c6c11028d9) Reviewed-on: https://chromium-review.googlesource.com/669044
-rw-r--r--board/cr50/board.c5
-rw-r--r--chip/g/system.c47
-rw-r--r--chip/g/system_chip.h7
3 files changed, 42 insertions, 17 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 87908815b0..79df1e43d7 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -598,7 +598,7 @@ static void board_init(void)
/* Initialize the persistent storage. */
initvars();
- system_update_rollback_mask();
+ system_update_rollback_mask_with_both_imgs();
/* Indication that firmware is running, for debug purposes. */
GREG32(PMU, PWRDN_SCRATCH16) = 0xCAFECAFE;
@@ -1456,6 +1456,9 @@ static enum vendor_cmd_rc vc_invalidate_inactive_rw(enum vendor_cmd_cc code,
*response_size = 0;
+ /* Update INFO1 mask based on the currently active image. */
+ system_update_rollback_mask_with_active_img();
+
if (other_rw_is_inactive()) {
CPRINTS("%s: Inactive region is disabled", __func__);
return VENDOR_RC_SUCCESS;
diff --git a/chip/g/system.c b/chip/g/system.c
index 4d9f9e7e67..dcc58e2c8d 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -539,20 +539,22 @@ const char *system_get_build_info(void)
return combined_build_info;
}
-void system_update_rollback_mask(void)
+/**
+ * Modify info1 RW rollback mask to match the passed in header(s).
+ *
+ * If both headers' addressses are passed in, the INFO1 rollback mask field is
+ * erased in case both headers have a zero in the appropriate bit. If only one
+ * header address is passed (the other one is set to zero), only the valid
+ * header is considered when updating INFO1.
+ */
+static void update_rollback_mask(const struct SignedHeader *header_a,
+ const struct SignedHeader *header_b)
{
#ifndef CR50_DEV
int updated_words_count = 0;
int i;
int write_enabled = 0;
uint32_t header_mask = 0;
- const struct SignedHeader *header_a;
- const struct SignedHeader *header_b;
-
- header_a = (const struct SignedHeader *)
- get_program_memory_addr(SYSTEM_IMAGE_RW);
- header_b = (const struct SignedHeader *)
- get_program_memory_addr(SYSTEM_IMAGE_RW_B);
/*
* Make sure INFO1 RW map space is readable.
@@ -586,12 +588,16 @@ void system_update_rollback_mask(void)
if (!(i % 32)) {
/*
* Not to shoot ourselves in the foot, let's zero only
- * those words in the INFO1 space which have both A
- * and B header's infomap bit set to zero.
+ * those words in the INFO1 space which are set to
+ * zero in all headers we are supposed to look at.
*/
- header_mask =
- header_a->infomap[i/32] |
- header_b->infomap[i/32];
+ header_mask = 0;
+
+ if (header_a)
+ header_mask |= header_a->infomap[i/32];
+
+ if (header_b)
+ header_mask |= header_b->infomap[i/32];
}
/* Get the next bit value. */
@@ -647,6 +653,21 @@ void system_update_rollback_mask(void)
#endif /* CR50_DEV ^^^^^^^^ NOT defined. */
}
+void system_update_rollback_mask_with_active_img(void)
+{
+ update_rollback_mask((const struct SignedHeader *)
+ get_program_memory_addr(system_get_image_copy()),
+ 0);
+}
+
+void system_update_rollback_mask_with_both_imgs(void)
+{
+ update_rollback_mask((const struct SignedHeader *)
+ get_program_memory_addr(SYSTEM_IMAGE_RW),
+ (const struct SignedHeader *)
+ get_program_memory_addr(SYSTEM_IMAGE_RW_B));
+}
+
void system_get_rollback_bits(char *value, size_t value_size)
{
int info_count;
diff --git a/chip/g/system_chip.h b/chip/g/system_chip.h
index ce63f3eab8..3f72b81611 100644
--- a/chip/g/system_chip.h
+++ b/chip/g/system_chip.h
@@ -52,10 +52,11 @@ int system_rollback_detected(void);
int system_battery_cutoff_support_required(void);
/**
- * Modify info1 RW rollback mask to match currently executing RW image's
- * header.
+ * Functions to update INFO1 rollback mask based on one or both RW image
+ * headers.
*/
-void system_update_rollback_mask(void);
+void system_update_rollback_mask_with_active_img(void);
+void system_update_rollback_mask_with_both_imgs(void);
/**
* Scan INFO1 rollback map and infomap fields of both RW and RW_B image