diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2016-04-30 14:06:07 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-05-02 17:35:46 -0700 |
commit | acaec8810146196b432e3fcc3f6b8ba0161ff747 (patch) | |
tree | 7609fe3d06b02e43c745fc3bb41454cef78f5c09 /chip | |
parent | de3a96c47126938302ef1da54f1de6153075e8bd (diff) | |
download | chrome-ec-acaec8810146196b432e3fcc3f6b8ba0161ff747.tar.gz |
g: enhance upgrade protocol to allow upgrade block restarts
With this new protocol version the target watches the size of the
received messages while reassembling an upgrade block.
If a message of the header size arrives and it is not the last message
of the block, the target considers it a re-start of the block transfer
by the host (presumably because a chunk was lost and the host did not
receive a confirmation of the block transfer in the preceding block
transfer attempt.)
BRANCH=none
BUG=chrome-os-partner:52586
TEST=the upgrade command on the host reports target running protocol
version 2, upgrades on B1 board still run smoothly.
Change-Id: I2e16c1be5135c0b5a4f09ea293f09ecabf59ecb3
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/341630
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/g/usb_upgrade.c | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/chip/g/usb_upgrade.c b/chip/g/usb_upgrade.c index 2c416b5334..45cf06e87c 100644 --- a/chip/g/usb_upgrade.c +++ b/chip/g/usb_upgrade.c @@ -131,7 +131,7 @@ static int valid_transfer_start(struct consumer const *consumer, size_t count, */ static uint64_t prev_activity_timestamp; -#define UPGRADE_PROTOCOL_VERSION 1 +#define UPGRADE_PROTOCOL_VERSION 2 /* Called to deal with data from the host */ static void upgrade_out_handler(struct consumer const *consumer, size_t count) @@ -286,11 +286,46 @@ static void upgrade_out_handler(struct consumer const *consumer, size_t count) block_index += count; block_size -= count; - if (block_size) + if (block_size) { + if (count == sizeof(updu)) { + /* + * A block header size instead of chunk size message + * has been received. There must have been some packet + * loss and the host is restarting this block. + * + * Let's copy its contents into the header structure. + */ + memcpy(&updu, block_buffer + block_index - count, + count); + + + /* And re-allocate a large enough buffer. */ + shared_mem_release(block_buffer); + block_size = be32toh(updu.block_size) - + offsetof(struct update_pdu_header, cmd); + if (shared_mem_acquire(block_size, + (char **)&block_buffer) + != EC_SUCCESS) { + /* TODO:(vbendeb) report out of memory here. */ + CPRINTS("FW update: error: failed to alloc " + "%d bytes.", block_size); + return; + } + + /* + * Copy the rest of the message into the block buffer + * to pass to the upgrader. + */ + block_index = sizeof(updu) - + offsetof(struct update_pdu_header, cmd); + memcpy(block_buffer, &updu.cmd, block_index); + block_size -= block_index; + } return; /* More to come. */ + } /* - * Ok, the enter block has been received and reassembled, pass it to + * Ok, the entire block has been received and reassembled, pass it to * the updater for verification and programming. */ fw_upgrade_command_handler(block_buffer, block_index, &resp_size); |