summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/g/system.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/chip/g/system.c b/chip/g/system.c
index d68da094f2..2e464391db 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -610,6 +610,8 @@ static void update_rollback_mask(uint32_t addr_a, uint32_t addr_b,
#ifndef CR50_DEV
const struct SignedHeader *header_a;
const struct SignedHeader *header_b;
+ const struct SignedHeader *header_this;
+
int updated_words_count = 0;
int i;
int write_enabled = 0;
@@ -630,6 +632,29 @@ static void update_rollback_mask(uint32_t addr_a, uint32_t addr_b,
* (where those bits in the header are not zeroed) will fail, thus
* ensuring rollback protection.
*/
+ /*
+ * Due to build system quirks this code could creep in even into
+ * images which have all rollback bits in the header set to zero
+ * (usually such images are built with CR50_DEV=1). Let's explicitly
+ * check that the current running image does not have the rollback
+ * space completely zeroed.
+ *
+ * Note that this function is invoked to update both RO and RW INFO1
+ * rollback masks, but here we care only about the RW case, since we
+ * never build RO images with fully erased rollback map.
+ */
+ header_this = (const struct SignedHeader *)
+ get_program_memory_addr(system_get_image_copy());
+ if ((header_this == header_a) || (header_this == header_b)) {
+ for (i = 0; i < ARRAY_SIZE(header_this->infomap); i++) {
+ if (header_this->infomap[i])
+ break;
+ }
+ if (i == ARRAY_SIZE(header_this->infomap)) {
+ CPRINTS("Skipped updating INFO1 RW map");
+ return;
+ }
+ }
/* For each bit in the header infomap field of the running image. */
for (i = 0; i < INFO_MAX; i++) {
uint32_t bit;