summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-04-30 13:39:23 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-05-02 17:35:46 -0700
commitde3a96c47126938302ef1da54f1de6153075e8bd (patch)
treef9896cd5bb7be985f6d8af8703954d4f10db6de5 /chip
parent2b326b446192c51755442ef3cd34df09847e3b7a (diff)
downloadchrome-ec-de3a96c47126938302ef1da54f1de6153075e8bd.tar.gz
g: verify that first message of each upgrade block is right
When a new upgrade block starts, the host sends first a 12 byte message including the block size and header. The target must verify that the message is of the proper size and the contents make sense (the header is not all zeros). It also should drain the USB queue completely in case it holds a message of a different size. BRANCH=none BUG=chrome-os-partner:52856 TEST=upgrade still works fine on B1 Change-Id: I80538a3a1a5d507a84bd21b868a3db626bc6a4b0 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/341619 Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/g/usb_upgrade.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/chip/g/usb_upgrade.c b/chip/g/usb_upgrade.c
index 182c40d7d2..2c416b5334 100644
--- a/chip/g/usb_upgrade.c
+++ b/chip/g/usb_upgrade.c
@@ -243,14 +243,20 @@ static void upgrade_out_handler(struct consumer const *consumer, size_t count)
}
}
- if (count < sizeof(updu)) {
- CPRINTS("FW update: error: first chunk of %d bytes",
- count);
- rx_state_ = rx_idle;
+ /*
+ * At this point we expect a block start message. It is
+ * sizeof(updu) bytes in size, but is not the transfer start
+ * message, which also is of that size AND has the command
+ * field of all zeros.
+ */
+ if (valid_transfer_start(consumer, count, &updu) ||
+ (count != sizeof(updu)))
+ /*
+ * Instead of a block start message we received either
+ * a transfer start message or a chunk. We must have
+ * gotten out of sync with the host.
+ */
return;
- }
-
- QUEUE_REMOVE_UNITS(consumer->queue, &updu, sizeof(updu));
/* Let's allocate a large enough buffer. */
block_size = be32toh(updu.block_size) -
@@ -270,10 +276,6 @@ static void upgrade_out_handler(struct consumer const *consumer, size_t count)
block_index = sizeof(updu) -
offsetof(struct update_pdu_header, cmd);
memcpy(block_buffer, &updu.cmd, block_index);
- QUEUE_REMOVE_UNITS(consumer->queue,
- block_buffer + block_index,
- count - sizeof(updu));
- block_index += count - sizeof(updu);
block_size -= block_index;
rx_state_ = rx_inside_block;
return;