]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
tpm: Allow reporting the internal state
authorSimon Glass <sjg@chromium.org>
Wed, 31 Aug 2022 03:05:36 +0000 (21:05 -0600)
committerIlias Apalodimas <ilias.apalodimas@linaro.org>
Sat, 3 Sep 2022 13:59:05 +0000 (16:59 +0300)
It is useful to read information about the current TPM state, where
supported, e.g. for debugging purposes when verified boot fails.

Add support for this to the TPM interface as well as Cr50. Add a simple
sandbox test.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
cmd/tpm-common.c
cmd/tpm-user-utils.h
cmd/tpm-v2.c
drivers/tpm/tpm-uclass.c
drivers/tpm/tpm2_tis_sandbox.c
include/tpm-common.h
test/dm/Makefile
test/dm/tpm.c [new file with mode: 0644]

index 47adaffd18490c690afc2d7deffc2667399032fc..d0c63cadf413f0695450d2377b096c8d8d7a04c6 100644 (file)
@@ -333,6 +333,26 @@ int do_tpm_info(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        return 0;
 }
 
+int do_tpm_report_state(struct cmd_tbl *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       struct udevice *dev;
+       char buf[80];
+       int rc;
+
+       rc = get_tpm(&dev);
+       if (rc)
+               return rc;
+       rc = tpm_report_state(dev, buf, sizeof(buf));
+       if (rc < 0) {
+               printf("Couldn't get TPM state (%d)\n", rc);
+               return CMD_RET_FAILURE;
+       }
+       printf("%s\n", buf);
+
+       return 0;
+}
+
 int do_tpm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
        struct udevice *dev;
index 358ddff5761079c789d1dc9c76d0fe24815d6fe5..de4a934aab6cf2b0295eee4fa1dbd3838650b40d 100644 (file)
@@ -21,6 +21,8 @@ int do_tpm_device(struct cmd_tbl *cmdtp, int flag, int argc,
                  char *const argv[]);
 int do_tpm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tpm_info(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_tpm_report_state(struct cmd_tbl *cmdtp, int flag, int argc,
+                       char *const argv[]);
 int do_tpm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
 #endif /* __TPM_USER_UTILS_H */
index 4ea5f9f094f6002ae94745ef220b163c437899ec..d93b83ada934af164a9fdd129a8f12fd05c0928b 100644 (file)
@@ -359,6 +359,7 @@ static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
 static struct cmd_tbl tpm2_commands[] = {
        U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
        U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
+       U_BOOT_CMD_MKENT(state, 0, 1, do_tpm_report_state, "", ""),
        U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
        U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""),
        U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""),
@@ -389,6 +390,8 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
 "    Show all devices or set the specified device\n"
 "info\n"
 "    Show information about the TPM.\n"
+"state\n"
+"    Show internal state from the TPM (if available)\n"
 "init\n"
 "    Initialize the software stack. Always the first command to issue.\n"
 "startup <mode>\n"
index 0eb35f50c4e6a5185bb917c25d0b5f2033f90940..5ff0cd3958cde3d521e710dc8e841d6105094277 100644 (file)
@@ -49,6 +49,16 @@ int tpm_get_desc(struct udevice *dev, char *buf, int size)
        return ops->get_desc(dev, buf, size);
 }
 
+int tpm_report_state(struct udevice *dev, char *buf, int size)
+{
+       struct tpm_ops *ops = tpm_get_ops(dev);
+
+       if (!ops->report_state)
+               return -ENOSYS;
+
+       return ops->report_state(dev, buf, size);
+}
+
 /* Returns max number of milliseconds to wait */
 static ulong tpm_tis_i2c_calc_ordinal_duration(struct tpm_chip_priv *priv,
                                               u32 ordinal)
index c26f5d35abf10777f7887fbe1708a33fff151f90..dd94bdc31fb79252a5c72b496b7fc733ec5d66b9 100644 (file)
@@ -795,6 +795,16 @@ static int sandbox_tpm2_get_desc(struct udevice *dev, char *buf, int size)
        return snprintf(buf, size, "Sandbox TPM2.x");
 }
 
+static int sandbox_tpm2_report_state(struct udevice *dev, char *buf, int size)
+{
+       struct sandbox_tpm2 *priv = dev_get_priv(dev);
+
+       if (size < 40)
+               return -ENOSPC;
+
+       return snprintf(buf, size, "init_done=%d", priv->init_done);
+}
+
 static int sandbox_tpm2_open(struct udevice *dev)
 {
        struct sandbox_tpm2 *tpm = dev_get_priv(dev);
@@ -834,6 +844,7 @@ static const struct tpm_ops sandbox_tpm2_ops = {
        .open           = sandbox_tpm2_open,
        .close          = sandbox_tpm2_close,
        .get_desc       = sandbox_tpm2_get_desc,
+       .report_state   = sandbox_tpm2_report_state,
        .xfer           = sandbox_tpm2_xfer,
 };
 
index a28629e7013a3a11a36f718ba7203ddf8937bc30..b2c5404430f5ce22f4b97659b046527798cbb064 100644 (file)
@@ -119,6 +119,16 @@ struct tpm_ops {
         */
        int (*get_desc)(struct udevice *dev, char *buf, int size);
 
+       /**
+        * report_state() - Collect information about the current TPM state
+        *
+        * @dev:        Device to check
+        * @buf:        Buffer to put the string
+        * @size:       Maximum size of buffer
+        * Return: return code of the operation (0 = success)
+        */
+       int (*report_state)(struct udevice *dev, char *buf, int size);
+
        /**
         * send() - send data to the TPM
         *
@@ -234,6 +244,16 @@ u32 tpm_clear_and_reenable(struct udevice *dev);
  */
 int tpm_get_desc(struct udevice *dev, char *buf, int size);
 
+/**
+ * tpm_report_state() - Collect information about the current TPM state
+ *
+ * @dev:       Device to check
+ * @buf:       Buffer to put the string
+ * @size:      Maximum size of buffer
+ * Return: return code of the operation (0 = success)
+ */
+int tpm_report_state(struct udevice *dev, char *buf, int size);
+
 /**
  * tpm_xfer() - send data to the TPM and get response
  *
index 52fe178a828d5ae3f637a53d17af921089e63794..7543df8823caf967ea15a333e82bdf080a937dc8 100644 (file)
@@ -107,6 +107,7 @@ obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
 obj-$(CONFIG_UT_DM) += tag.o
 obj-$(CONFIG_TEE) += tee.o
 obj-$(CONFIG_TIMER) += timer.o
+obj-$(CONFIG_TPM_V2) += tpm.o
 obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_VIDEO) += video.o
 ifeq ($(CONFIG_VIRTIO_SANDBOX),y)
diff --git a/test/dm/tpm.c b/test/dm/tpm.c
new file mode 100644 (file)
index 0000000..0b46f79
--- /dev/null
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <tpm_api.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of the TPM uclass */
+static int dm_test_tpm(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+       char buf[50];
+
+       /* check probe success */
+       ut_assertok(uclass_first_device_err(UCLASS_TPM, &dev));
+       ut_assert(tpm_is_v2(dev));
+
+       ut_assert(tpm_report_state(dev, buf, sizeof(buf)));
+       ut_asserteq_str("init_done=0", buf);
+
+       ut_assertok(tpm_init(dev));
+
+       ut_assert(tpm_report_state(dev, buf, sizeof(buf)));
+       ut_asserteq_str("init_done=1", buf);
+
+       return 0;
+}
+DM_TEST(dm_test_tpm, UT_TESTF_SCAN_FDT);