summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-05-26 17:16:51 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-09-08 22:38:47 +0000
commitdafa55ca300eb431ed75c708dff268829dea5bc8 (patch)
tree441af47bf480ba2f2fc100a3167b86e797b26363
parentecd32c4703638dea28431f303d043fe7cc1a2955 (diff)
downloadchrome-ec-dafa55ca300eb431ed75c708dff268829dea5bc8.tar.gz
usb_updater: when communicating over tpm treat upgrades differently
All extension and vendor commands' payloads need to be passed to the processing functions the same way, whether they arrive over /dev/tpm0 or over USB. The upgrade PDUs sent over USB need to include two additional fields which are stripped off by the reassembly layer on the Cr50. This patch makes sure that none of other than EXTENSION_FW_UPGRADE commands sent over /dev/tpm0 by usb_updater have the extra encapsulation. BRANCH=cr50 BUG=b:62106898 TEST=verified that updates work the same way over TPM and USB (which includes sending the 'turn_update_on' commands. Before this patch the turn_update_on command sent by usb_updater over TPM was not processed properly (the timeout value was wrong). Change-Id: I3f4ab7330037f6eb1ce8bac7c63faa5d7c309c94 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/517416 Reviewed-by: Andrey Pronin <apronin@chromium.org> (cherry picked from commit bd0f74a6f49cd3dcbed81738e376a8b05868b4f5) Reviewed-on: https://chromium-review.googlesource.com/658348 Reviewed-by: Philip Chen <philipchen@chromium.org> Commit-Queue: Philip Chen <philipchen@chromium.org> Tested-by: Philip Chen <philipchen@chromium.org>
-rw-r--r--extra/usb_updater/usb_updater.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/extra/usb_updater/usb_updater.c b/extra/usb_updater/usb_updater.c
index 951b26507b..c39673535a 100644
--- a/extra/usb_updater/usb_updater.c
+++ b/extra/usb_updater/usb_updater.c
@@ -176,9 +176,20 @@ struct upgrade_pkt {
__be32 length;
__be32 ordinal;
__be16 subcmd;
- __be32 digest;
- __be32 address;
- char data[0];
+ union {
+ /*
+ * Upgrade PDUs as opposed to all other vendor and extension
+ * commands include two additional fields in the header.
+ */
+ struct {
+ __be32 digest;
+ __be32 address;
+ char data[0];
+ } upgrade;
+ struct {
+ char data[0];
+ } command;
+ };
} __packed;
#define MAX_BUF_SIZE (SIGNED_TRANSFER_SIZE + sizeof(struct upgrade_pkt))
@@ -241,26 +252,37 @@ static int tpm_send_pkt(int fd, unsigned int digest, unsigned int addr,
{
/* Used by transfer to /dev/tpm0 */
static uint8_t outbuf[MAX_BUF_SIZE];
-
struct upgrade_pkt *out = (struct upgrade_pkt *)outbuf;
/* Use the same structure, it will not be filled completely. */
int len, done;
- int response_offset = offsetof(struct upgrade_pkt, digest);
+ int response_offset = offsetof(struct upgrade_pkt, command.data);
+ void *payload;
+ size_t header_size;
debug("%s: sending to %#x %d bytes\n", __func__, addr, size);
- len = size + sizeof(struct upgrade_pkt);
-
out->tag = htobe16(0x8001);
- out->length = htobe32(len);
+ out->subcmd = htobe16(subcmd);
+
if (subcmd <= LAST_EXTENSION_COMMAND)
out->ordinal = htobe32(CONFIG_EXTENSION_COMMAND);
else
out->ordinal = htobe32(TPM_CC_VENDOR_BIT_MASK);
- out->subcmd = htobe16(subcmd);
- out->digest = digest;
- out->address = htobe32(addr);
- memcpy(out->data, data, size);
+
+ if (subcmd == EXTENSION_FW_UPGRADE) {
+ /* FW Upgrade PDU header includes a couple of extra fields. */
+ out->upgrade.digest = digest;
+ out->upgrade.address = htobe32(addr);
+ header_size = offsetof(struct upgrade_pkt, upgrade.data);
+ } else {
+ header_size = offsetof(struct upgrade_pkt, command.data);
+ }
+
+ payload = outbuf + header_size;
+ len = size + header_size;
+
+ out->length = htobe32(len);
+ memcpy(payload, data, size);
#ifdef DEBUG
{
int i;
@@ -1113,7 +1135,6 @@ static void generate_reset_request(struct transfer_descriptor *td)
fprintf(stderr, "Failed to request posted reboot\n");
exit(update_error);
}
-
}
printf("reboot %s\n", subcommand == EXTENSION_POST_RESET ?