diff options
-rw-r--r-- | board/cr50/board.c | 5 | ||||
-rw-r--r-- | chip/g/system.c | 47 | ||||
-rw-r--r-- | chip/g/system_chip.h | 7 |
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 |