summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-04-30 14:06:07 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-05-02 17:35:46 -0700
commitacaec8810146196b432e3fcc3f6b8ba0161ff747 (patch)
tree7609fe3d06b02e43c745fc3bb41454cef78f5c09
parentde3a96c47126938302ef1da54f1de6153075e8bd (diff)
downloadchrome-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>
-rw-r--r--chip/g/usb_upgrade.c41
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);