summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2019-04-26 18:59:31 -0700
committerCommit Bot <commit-bot@chromium.org>2020-01-09 06:55:47 +0000
commit6219b5b51817a16cd5ba2321db729046662cb46b (patch)
tree9c0c7e17b58a7c340e9b7cb78c6df0fdd5d25b37
parent469750fdd47be95b9d29ace6d87b22ec5db66025 (diff)
downloadchrome-ec-6219b5b51817a16cd5ba2321db729046662cb46b.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> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1993060 Reviewed-by: Cheng-Han Yang <chenghan@chromium.org> Commit-Queue: Cheng-Han Yang <chenghan@chromium.org> Tested-by: Cheng-Han Yang <chenghan@chromium.org>
-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 2cd5e24476..6e0be6a0b0 100644
--- a/extra/usb_updater/gsctool.c
+++ b/extra/usb_updater/gsctool.c
@@ -1072,17 +1072,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");