summaryrefslogtreecommitdiff
path: root/extra/usb_updater
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2019-04-26 18:59:31 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-04-30 14:13:02 -0700
commit7f55b1f708812d434119b38a23dcbe1e9f009b71 (patch)
tree26c2377ba1146a4b1457c8dd5517a3ddc8fd3640 /extra/usb_updater
parent4c82f6a3361e0683a735e504e6c78683d8e2d3de (diff)
downloadchrome-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/usb_updater')
-rw-r--r--extra/usb_updater/gsctool.c25
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");