summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-05-26 17:16:51 -0700
committerVadim Bendebury <vbendeb@chromium.org>2017-06-28 02:35:06 +0000
commit7cc70e54917077829bdbb6998ed58b1c78a6ad86 (patch)
tree441061fd2e5959d6047ee4645199e41eba90d4d1
parent8933269fd14c58b722a5006d7e794ad8a8036bb4 (diff)
downloadchrome-ec-7cc70e54917077829bdbb6998ed58b1c78a6ad86.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/551360
-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 ?