diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2017-06-20 15:14:47 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2017-09-14 16:55:45 +0000 |
commit | b08369765e27e25b4adc380ac5006b3c4c170ca9 (patch) | |
tree | 078bfaadcf8607cc38b26597810b6c3848efebe9 | |
parent | 210000a4917ca8a5a2583e38f4abad8c3c5e47c6 (diff) | |
download | chrome-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.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 |