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-14 16:55:45 +0000
commitb08369765e27e25b4adc380ac5006b3c4c170ca9 (patch)
tree078bfaadcf8607cc38b26597810b6c3848efebe9
parent210000a4917ca8a5a2583e38f4abad8c3c5e47c6 (diff)
downloadchrome-ec-b08369765e27e25b4adc380ac5006b3c4c170ca9.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/666524
-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 38f5ff40d1..4537f2aab9 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 8495c43e6c..46eac4bb84 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -521,20 +521,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.
@@ -568,12 +570,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. */
@@ -629,6 +635,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