tpm: Allow reporting the internal state
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>
This commit is contained in:
parent
6694c997b2
commit
3bb4db4c38
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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)
|
||||
|
34
test/dm/tpm.c
Normal file
34
test/dm/tpm.c
Normal file
@ -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);
|
Loading…
Reference in New Issue
Block a user