summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 4097833662..8a60949eb7 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -634,7 +634,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;
@@ -1505,6 +1505,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 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;
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