diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2019-04-26 18:59:31 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-04-30 14:13:02 -0700 |
commit | 7f55b1f708812d434119b38a23dcbe1e9f009b71 (patch) | |
tree | 26c2377ba1146a4b1457c8dd5517a3ddc8fd3640 /extra | |
parent | 4c82f6a3361e0683a735e504e6c78683d8e2d3de (diff) | |
download | chrome-ec-7f55b1f708812d434119b38a23dcbe1e9f009b71.tar.gz |
gsctool: enforce order of Cr50 section updates
When both RO and RW updates are required, and the RO includes a new RW
signing key, to ensure recovery from failed updates, the RW section of
the image needs to be updated before the RO section,
In this case interrupted RO or RW update will result in the H1
rebooting still using the original RO and original RW.
If the RO was updated first and the RW update was interrupted, the
chip could end up with the newer RO with no RW to verify with the new
key.
BRANCH=none
BUG=b:74100307
TEST=created an image with fake RO_B version number of 0.0.106, and
then tried to update to this image. Observed that RW_B was
transferred before RO_B
[1067.694175 FW update: starting...]
at 0x84000
at 0x84400
at 0x84800
...
at 0xbb400
at 0x80000
at 0x80400
at 0x80800
at 0x80c00
at 0x81000
at 0x81400
at 0x81800
at 0x81c00
at 0x82000
at 0x82400
Change-Id: Ie5240c14c6b7d73c00baac693be724fab4636992
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1586590
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Diffstat (limited to 'extra')
-rw-r--r-- | extra/usb_updater/gsctool.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/extra/usb_updater/gsctool.c b/extra/usb_updater/gsctool.c index cfb94afbeb..0fd07d38f8 100644 --- a/extra/usb_updater/gsctool.c +++ b/extra/usb_updater/gsctool.c @@ -1107,17 +1107,36 @@ static void send_done(struct usb_endpoint *uep) static int transfer_image(struct transfer_descriptor *td, uint8_t *data, size_t data_len) { - size_t i; + size_t j; int num_txed_sections = 0; - for (i = 0; i < ARRAY_SIZE(sections); i++) - if (sections[i].ustatus == needed) { + /* + * In case both RO and RW updates are required, make sure the RW + * section is updated before the RO. The array below keeps sections + * offsets in the required order. + */ + const size_t update_order[] = {CONFIG_RW_MEM_OFF, + CONFIG_RW_B_MEM_OFF, + CONFIG_RO_MEM_OFF, + CHIP_RO_B_MEM_OFF}; + + for (j = 0; j < ARRAY_SIZE(update_order); j++) { + size_t i; + + for (i = 0; i < ARRAY_SIZE(sections); i++) { + if (sections[i].offset != update_order[j]) + continue; + + if (sections[i].ustatus != needed) + break; + transfer_section(td, data + sections[i].offset, sections[i].offset, sections[i].size); num_txed_sections++; } + } if (!num_txed_sections) printf("nothing to do\n"); |