diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2016-04-29 19:08:14 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-05-02 17:35:45 -0700 |
commit | b81afce806907714baa05dcd649e3f2a5d7d2a4e (patch) | |
tree | ee261bed495bcbd4225063be9a3fe862ff8e3cc3 /extra | |
parent | 65118b7f7afc361426852f72024cb8d135cec6c2 (diff) | |
download | chrome-ec-b81afce806907714baa05dcd649e3f2a5d7d2a4e.tar.gz |
g: introduce versioning and backwards compatibility of usb_upgrade
The original version of usb_upgrade does not provide for any error
recovery and also does not support any protocol version notion.
Real life experience has shown that error recovery is essential, it
needs to be introduced as a protocol enhancement. We want to stay
backwards compatible though, so there is a need for protocol
versioning.
In the original version of the protocol target response is always the
same: a 4 byte number which is the error code (and zero means no
error). This patch modifies response to the very first packet from the
host, the startup packet. The startup response is 8 bytes long. The
first 4 bytes is still the same as before, the second 4 bytes carry
the protocol version supported by the target, an integer in network
byte order.
Thus, receiving a 4 byte reply to the startup message tells the host
that the target is running protocol version zero, 8 byte reply carries
the actual version number in the last 4 bytes.
The USB transfer function on the host is enhanced to accept responses
shorter then expected, when allowed.
BRANCH=none
BUG=chrome-os-partner:52856
TEST=usb_updater can successfully update both old and new cr50 images,
properly reporting protocol version as 0 or 1 respectively.
Change-Id: I9920d2708b21f29615282161fc0eb027018f9378
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/341617
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Diffstat (limited to 'extra')
-rw-r--r-- | extra/usb_updater/usb_updater.c | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/extra/usb_updater/usb_updater.c b/extra/usb_updater/usb_updater.c index 588a176a27..808c042e87 100644 --- a/extra/usb_updater/usb_updater.c +++ b/extra/usb_updater/usb_updater.c @@ -113,8 +113,15 @@ static uint8_t *get_file_or_die(const char *filename, uint32_t *len_ptr) fprintf(stderr, "%s:%d, %s returned %d (%s)\n", __FILE__, __LINE__, \ m, r, libusb_strerror(r)) -static void xfer(struct usb_endpoint *uep, void *outbuf, - int outlen, void *inbuf, int inlen) +/* + * Actual USB transfer function, the 'allow_less' flag indicates that the + * valid response could be shortef than allotted memory, the 'rxed_count' + * pointer, if provided along with 'allow_less' lets the caller know how mavy + * bytes were received. + */ +static void do_xfer(struct usb_endpoint *uep, void *outbuf, int outlen, + void *inbuf, int inlen, int allow_less, + int *rxed_count) { int r, actual; @@ -147,14 +154,22 @@ static void xfer(struct usb_endpoint *uep, void *outbuf, USB_ERROR("libusb_bulk_transfer", r); exit(1); } - if (actual != inlen) { + if ((actual != inlen) && !allow_less) { fprintf(stderr, "%s:%d, only received %d/%d bytes\n", __FILE__, __LINE__, actual, inlen); shut_down(uep); } + + if (rxed_count) + *rxed_count = actual; } } +static void xfer(struct usb_endpoint *uep, void *outbuf, + int outlen, void *inbuf, int inlen) +{ + do_xfer(uep, outbuf, outlen, inbuf, inlen, 0, NULL); +} /* Return 0 on error, since it's never gonna be EP 0 */ static int find_endpoint(const struct libusb_interface_descriptor *iface, @@ -288,6 +303,25 @@ struct update_pdu { }; #define FLASH_BASE 0x40000 +/* + * When responding to the very first packet of the upgrade sequence, the + * original implementation was responding with a four byte value, just as to + * any other block of the transfer sequence. + * + * It became clear that there is a need to be able to enhance the upgrade + * protocol, while stayng backwards compatible. To achieve that a new startup + * response option was introduced, 8 bytes in size. The first 4 bytes the same + * as before, the second 4 bytes - the protocol version number. + * + * So, receiving of a four byte value in response to the startup packet is an + * indication of the 'legacy' protocol, version 0. Receiving of an 8 byte + * value communicates the protocol version in the second 4 bytes. + */ + +struct startup_resp { + uint32_t value; + uint32_t version; +}; static void transfer_and_reboot(struct usb_endpoint *uep, uint8_t *data, uint32_t data_len) @@ -297,15 +331,34 @@ static void transfer_and_reboot(struct usb_endpoint *uep, uint8_t *data_ptr; uint32_t next_offset; struct update_pdu updu; + struct startup_resp first_resp; + int rxed_size; + uint32_t protocol_version; /* Send start/erase request */ printf("erase\n"); memset(&updu, 0, sizeof(updu)); updu.block_size = htobe32(sizeof(updu)); - xfer(uep, &updu, sizeof(updu), &reply, sizeof(reply)); -/* check the offset here. */ - next_offset = be32toh(reply) - FLASH_BASE; + + do_xfer(uep, &updu, sizeof(updu), &first_resp, sizeof(first_resp), + 1, &rxed_size); + + if (rxed_size == sizeof(uint32_t)) + protocol_version = 0; + else + protocol_version = be32toh(first_resp.version); + + printf("Target running protocol version %d\n", protocol_version); + + reply = be32toh(first_resp.value); + + if (reply < 256) { + fprintf(stderr, "Target reports error %d\n", reply); + shut_down(uep); + } + + next_offset = reply - FLASH_BASE; printf("Updating at offset 0x%08x\n", next_offset); data_ptr = data + next_offset; |