Add a cli command to test the TPM device.
authorVadim Bendebury <vbendeb@chromium.org>
Sat, 15 Oct 2011 15:13:34 +0000 (15:13 +0000)
committerWolfgang Denk <wd@denx.de>
Tue, 6 Dec 2011 20:30:03 +0000 (21:30 +0100)
The command gets an arbitrary number of arguments (up to 30), which
are interpreted as byte values and are feed into the TPM device after
proper initialization. Then the return value and data of the TPM
driver is examined.

TPM commands are described in the TCG specification.

For instance, the following sequence is the 'TPM Startup' command, it
is processed by the TPM and a response is generated:

boot > tpm 0x0 0xc1 0x0 0x0 0x0 0xc 0x0 0x0 0x0 0x99 0x0 0x1
Found TPM SLB9635 TT 1.2 by Infineon
Got TPM response:
 00 c4 00 00 00 0a 00 00 00 00

If the command is corrupted (fed one byte short), an error is reported:
boot > tpm 0x0 0xc1 0x0 0x0 0x0 0xc 0x0 0x0 0x0 0x99 0x0
generic_lpc_tpm.c:311 unexpected TPM status 0xff000888
generic_lpc_tpm.c:516 failed sending data to TPM
tpm command failed
boot >

Change-Id: I3f3c5bfec8b852e208c4e99ba37b0f2b875140b0
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
CC: Wolfgang Denk <wd@denx.de>
common/Makefile
common/cmd_tpm.c [new file with mode: 0644]

index 1b672ad..1be7236 100644 (file)
@@ -152,6 +152,7 @@ COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o
 COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o
 COBJS-$(CONFIG_CMD_TIME) += cmd_time.o
 COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o
+COBJS-$(CONFIG_CMD_TPM) += cmd_tpm.o
 COBJS-$(CONFIG_CMD_TSI148) += cmd_tsi148.o
 COBJS-$(CONFIG_CMD_UBI) += cmd_ubi.o
 COBJS-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c
new file mode 100644 (file)
index 0000000..6f5cd48
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <tpm.h>
+
+#define MAX_TRANSACTION_SIZE 30
+
+/*
+ * tpm_write() expects a variable number of parameters: the internal address
+ * followed by data to write, byte by byte.
+ *
+ * Returns 0 on success or -1 on errors (wrong arguments or TPM failure).
+ */
+static int tpm_process(int argc, char * const argv[], cmd_tbl_t *cmdtp)
+{
+       u8 tpm_buffer[MAX_TRANSACTION_SIZE];
+       u32 write_size, read_size;
+       char *p;
+       int rv = -1;
+
+       for (write_size = 0; write_size < argc; write_size++) {
+               u32 datum = simple_strtoul(argv[write_size], &p, 0);
+               if (*p || (datum > 0xff)) {
+                       printf("\n%s: bad data value\n\n", argv[write_size]);
+                       cmd_usage(cmdtp);
+                       return rv;
+               }
+               tpm_buffer[write_size] = (u8)datum;
+       }
+
+       read_size = sizeof(tpm_buffer);
+       if (!tis_sendrecv(tpm_buffer, write_size, tpm_buffer, &read_size)) {
+               int i;
+               puts("Got TPM response:\n");
+               for (i = 0; i < read_size; i++)
+                       printf(" %2.2x", tpm_buffer[i]);
+               puts("\n");
+               rv = 0;
+       } else {
+               puts("tpm command failed\n");
+       }
+       return rv;
+}
+
+static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int rv = 0;
+
+       /*
+        * Verify that in case it is present, the first argument, it is
+        * exactly one character in size.
+        */
+       if (argc < 7) {
+               puts("command should be at least six bytes in size\n");
+               return -1;
+       }
+
+       if (tis_init()) {
+               puts("tis_init() failed!\n");
+               return -1;
+       }
+
+       if (tis_open()) {
+               puts("tis_open() failed!\n");
+               return -1;
+       }
+
+       rv = tpm_process(argc - 1, argv + 1, cmdtp);
+
+       if (tis_close()) {
+               puts("tis_close() failed!\n");
+               rv = -1;
+       }
+
+       return rv;
+}
+
+U_BOOT_CMD(tpm, MAX_TRANSACTION_SIZE, 1, do_tpm,
+          "<byte> [<byte> ...]   - write data and read response",
+          "send arbitrary data (at least 6 bytes) to the TPM "
+          "device and read the response"
+);