From acaec8810146196b432e3fcc3f6b8ba0161ff747 Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Sat, 30 Apr 2016 14:06:07 -0700 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/341630 Reviewed-by: Mary Ruthven --- chip/g/usb_upgrade.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file 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); -- cgit v1.2.1