diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2016-04-30 13:39:23 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-05-02 17:35:46 -0700 |
commit | de3a96c47126938302ef1da54f1de6153075e8bd (patch) | |
tree | f9896cd5bb7be985f6d8af8703954d4f10db6de5 /chip | |
parent | 2b326b446192c51755442ef3cd34df09847e3b7a (diff) | |
download | chrome-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.c | 24 |
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; |