On Tue, 23 Aug 2022 at 20:13, Simon Glass <s...@chromium.org> wrote: > > 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 <s...@chromium.org> > --- > > (no changes since v1) > > cmd/tpm-common.c | 20 ++++++++++++++++++++ > cmd/tpm-user-utils.h | 2 ++ > cmd/tpm-v2.c | 3 +++ > drivers/tpm/tpm-uclass.c | 10 ++++++++++ > drivers/tpm/tpm2_tis_sandbox.c | 11 +++++++++++ > include/tpm-common.h | 20 ++++++++++++++++++++ > test/dm/Makefile | 1 + > test/dm/tpm.c | 34 ++++++++++++++++++++++++++++++++++ > 8 files changed, 101 insertions(+) > create mode 100644 test/dm/tpm.c > > diff --git a/cmd/tpm-common.c b/cmd/tpm-common.c > index 47adaffd184..d0c63cadf41 100644 > --- a/cmd/tpm-common.c > +++ b/cmd/tpm-common.c > @@ -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; > diff --git a/cmd/tpm-user-utils.h b/cmd/tpm-user-utils.h > index 358ddff5761..de4a934aab6 100644 > --- a/cmd/tpm-user-utils.h > +++ b/cmd/tpm-user-utils.h > @@ -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 */ > diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c > index 4ea5f9f094f..d93b83ada93 100644 > --- a/cmd/tpm-v2.c > +++ b/cmd/tpm-v2.c > @@ -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" > diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c > index 0eb35f50c4e..5ff0cd3958c 100644 > --- a/drivers/tpm/tpm-uclass.c > +++ b/drivers/tpm/tpm-uclass.c > @@ -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) > diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c > index c26f5d35abf..dd94bdc31fb 100644 > --- a/drivers/tpm/tpm2_tis_sandbox.c > +++ b/drivers/tpm/tpm2_tis_sandbox.c > @@ -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, > }; > > diff --git a/include/tpm-common.h b/include/tpm-common.h > index a28629e7013..b2c5404430f 100644 > --- a/include/tpm-common.h > +++ b/include/tpm-common.h > @@ -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 > * > diff --git a/test/dm/Makefile b/test/dm/Makefile > index 52fe178a828..7543df8823c 100644 > --- a/test/dm/Makefile > +++ b/test/dm/Makefile > @@ -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 > index 00000000000..0b46f799591 > --- /dev/null > +++ b/test/dm/tpm.c > @@ -0,0 +1,34 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright 2022 Google LLC > + * Written by Simon Glass <s...@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); > -- > 2.37.2.609.g9ff673ca1a-goog >
Reviewed-by: Ilias Apalodimas <ilias.apalodi...@linaro.org>