summaryrefslogtreecommitdiff
path: root/chip/g/system.c
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-06-20 15:14:47 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-06-21 18:48:05 -0700
commite7ebdfeefc4dfd38dfcb4ef57dbd5fd4e9029639 (patch)
tree09da97eccc5291a5e2021078eb14025da22b22e4 /chip/g/system.c
parentc6a8c03ac92f189aee428895f0c03eb23acd4566 (diff)
downloadchrome-ec-e7ebdfeefc4dfd38dfcb4ef57dbd5fd4e9029639.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>
Diffstat (limited to 'chip/g/system.c')
-rw-r--r--chip/g/system.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/chip/g/system.c b/chip/g/system.c
index b3ded8f963..4327a2c45b 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -565,20 +565,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.
@@ -612,12 +614,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. */
@@ -673,6 +679,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;