[U-Boot] [PATCH v2 26/28] dm: tpm: Add a 'tpmtest' command
Christophe Ricard
christophe.ricard at gmail.com
Mon Aug 24 22:23:35 CEST 2015
Hi Simon,
Acked-by: Christophe Ricard<christophe-h.ricard at st.com>
I will try those tpm tests.
Best Regards
Christophe
On 23/08/2015 02:31, Simon Glass wrote:
> These tests come from Chrome OS code. They are not particularly tidy but can
> be useful for checking that the TPM is behaving correctly. Some knowledge of
> TPM operation is required to use these.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> Changes in v2:
> - Add new patch with a 'tpmtest' command
>
> common/Kconfig | 10 +
> common/Makefile | 1 +
> common/cmd_tpm_test.c | 565 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 576 insertions(+)
> create mode 100644 common/cmd_tpm_test.c
>
> diff --git a/common/Kconfig b/common/Kconfig
> index bacc4e0..2c42b8e 100644
> --- a/common/Kconfig
> +++ b/common/Kconfig
> @@ -635,6 +635,16 @@ config CMD_TPM
> command requires a suitable TPM on your board and the correct driver
> must be enabled.
>
> +config CMD_TPM_TEST
> + bool "Enable the 'tpm test' command"
> + depends on CMD_TPM
> + help
> + This provides a a series of tests to confirm that the TPM is working
> + correctly. The tests cover initialisation, non-volatile RAM, extend,
> + global lock and checking that timing is within expectations. The
> + tests pass correctly on Infineon TPMs but may need to be adjusted
> + for other devices.
> +
> endmenu
>
> endmenu
> diff --git a/common/Makefile b/common/Makefile
> index dc82433..f4ba878 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -169,6 +169,7 @@ obj-$(CONFIG_CMD_TIME) += cmd_time.o
> obj-$(CONFIG_CMD_TRACE) += cmd_trace.o
> obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o
> obj-$(CONFIG_CMD_TPM) += cmd_tpm.o
> +obj-$(CONFIG_CMD_TPM_TEST) += cmd_tpm_test.o
> obj-$(CONFIG_CMD_TSI148) += cmd_tsi148.o
> obj-$(CONFIG_CMD_UBI) += cmd_ubi.o
> obj-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o
> diff --git a/common/cmd_tpm_test.c b/common/cmd_tpm_test.c
> new file mode 100644
> index 0000000..2bef5a1
> --- /dev/null
> +++ b/common/cmd_tpm_test.c
> @@ -0,0 +1,565 @@
> +/*
> + * Copyright (c) 2015 Google, Inc
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <environment.h>
> +#include <tpm.h>
> +
> +/* Prints error and returns on failure */
> +#define TPM_CHECK(tpm_command) do { \
> + uint32_t result; \
> + \
> + result = (tpm_command); \
> + if (result != TPM_SUCCESS) { \
> + printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
> + __LINE__, result); \
> + return result; \
> + } \
> +} while (0)
> +
> +#define INDEX0 0xda70
> +#define INDEX1 0xda71
> +#define INDEX2 0xda72
> +#define INDEX3 0xda73
> +#define INDEX_INITIALISED 0xda80
> +#define PHYS_PRESENCE 4
> +#define PRESENCE 8
> +
> +static uint32_t TlclStartupIfNeeded(void)
> +{
> + uint32_t result = tpm_startup(TPM_ST_CLEAR);
> +
> + return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
> +}
> +
> +static int test_timer(void)
> +{
> + printf("get_timer(0) = %lu\n", get_timer(0));
> + return 0;
> +}
> +
> +static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated,
> + uint8_t *nvlocked)
> +{
> + struct tpm_permanent_flags pflags;
> + uint32_t result;
> +
> + result = tpm_get_permanent_flags(&pflags);
> + if (result)
> + return result;
> + if (disable)
> + *disable = pflags.disable;
> + if (deactivated)
> + *deactivated = pflags.deactivated;
> + if (nvlocked)
> + *nvlocked = pflags.nv_locked;
> + debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
> + pflags.disable, pflags.deactivated, pflags.nv_locked);
> +
> + return 0;
> +}
> +
> +static uint32_t tpm_set_global_lock(void)
> +{
> + uint32_t x;
> +
> + debug("TPM: Set global lock\n");
> + return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0);
> +}
> +
> +static uint32_t tpm_nv_write_value_lock(uint32_t index)
> +{
> + debug("TPM: Write lock 0x%x\n", index);
> +
> + return tpm_nv_write_value(index, NULL, 0);
> +}
> +
> +static uint32_t tpm_nv_set_locked(void)
> +{
> + debug("TPM: Set NV locked\n");
> +
> + return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
> +}
> +
> +static int tpm_is_owned(void)
> +{
> + uint8_t response[TPM_PUBEK_SIZE];
> + uint32_t result;
> +
> + result = tpm_read_pubek(response, sizeof(response));
> +
> + return result != TPM_SUCCESS;
> +}
> +
> +static int test_early_extend(void)
> +{
> + uint8_t value_in[20];
> + uint8_t value_out[20];
> +
> + printf("Testing earlyextend ...");
> + tpm_init();
> + TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
> + TPM_CHECK(tpm_continue_self_test());
> + TPM_CHECK(tpm_extend(1, value_in, value_out));
> + printf("done\n");
> + return 0;
> +}
> +
> +static int test_early_nvram(void)
> +{
> + uint32_t x;
> +
> + printf("Testing earlynvram ...");
> + tpm_init();
> + TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
> + TPM_CHECK(tpm_continue_self_test());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
> + printf("done\n");
> + return 0;
> +}
> +
> +static int test_early_nvram2(void)
> +{
> + uint32_t x;
> +
> + printf("Testing earlynvram2 ...");
> + tpm_init();
> + TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
> + TPM_CHECK(tpm_continue_self_test());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)));
> + printf("done\n");
> + return 0;
> +}
> +
> +static int test_enable(void)
> +{
> + uint8_t disable = 0, deactivated = 0;
> +
> + printf("Testing enable ...\n");
> + tpm_init();
> + TPM_CHECK(TlclStartupIfNeeded());
> + TPM_CHECK(tpm_self_test_full());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
> + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
> + TPM_CHECK(tpm_physical_enable());
> + TPM_CHECK(tpm_physical_set_deactivated(0));
> + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
> + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
> + if (disable == 1 || deactivated == 1)
> + printf("\tfailed to enable or activate\n");
> + printf("\tdone\n");
> + return 0;
> +}
> +
> +#define reboot() do { \
> + printf("\trebooting...\n"); \
> + reset_cpu(0); \
> +} while (0)
> +
> +static int test_fast_enable(void)
> +{
> + uint8_t disable = 0, deactivated = 0;
> + int i;
> +
> + printf("Testing fastenable ...\n");
> + tpm_init();
> + TPM_CHECK(TlclStartupIfNeeded());
> + TPM_CHECK(tpm_self_test_full());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
> + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
> + for (i = 0; i < 2; i++) {
> + TPM_CHECK(tpm_force_clear());
> + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
> + printf("\tdisable is %d, deactivated is %d\n", disable,
> + deactivated);
> + assert(disable == 1 && deactivated == 1);
> + TPM_CHECK(tpm_physical_enable());
> + TPM_CHECK(tpm_physical_set_deactivated(0));
> + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
> + printf("\tdisable is %d, deactivated is %d\n", disable,
> + deactivated);
> + assert(disable == 0 && deactivated == 0);
> + }
> + printf("\tdone\n");
> + return 0;
> +}
> +
> +static int test_global_lock(void)
> +{
> + uint32_t zero = 0;
> + uint32_t result;
> + uint32_t x;
> +
> + printf("Testing globallock ...\n");
> + tpm_init();
> + TPM_CHECK(TlclStartupIfNeeded());
> + TPM_CHECK(tpm_self_test_full());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
> + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero,
> + sizeof(uint32_t)));
> + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
> + TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero,
> + sizeof(uint32_t)));
> + TPM_CHECK(tpm_set_global_lock());
> + /* Verifies that write to index0 fails */
> + x = 1;
> + result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x));
> + assert(result == TPM_AREA_LOCKED);
> + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
> + assert(x == 0);
> + /* Verifies that write to index1 is still possible */
> + x = 2;
> + TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)));
> + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
> + assert(x == 2);
> + /* Turns off PP */
> + tpm_tsc_physical_presence(PHYS_PRESENCE);
> + /* Verifies that write to index1 fails */
> + x = 3;
> + result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x));
> + assert(result == TPM_BAD_PRESENCE);
> + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
> + assert(x == 2);
> + printf("\tdone\n");
> + return 0;
> +}
> +
> +static int test_lock(void)
> +{
> + printf("Testing lock ...\n");
> + tpm_init();
> + tpm_startup(TPM_ST_CLEAR);
> + tpm_self_test_full();
> + tpm_tsc_physical_presence(PRESENCE);
> + tpm_nv_write_value_lock(INDEX0);
> + printf("\tLocked 0x%x\n", INDEX0);
> + printf("\tdone\n");
> + return 0;
> +}
> +
> +static void initialise_spaces(void)
> +{
> + uint32_t zero = 0;
> + uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
> +
> + printf("\tInitialising spaces\n");
> + tpm_nv_set_locked(); /* useful only the first time */
> + tpm_nv_define_space(INDEX0, perm, 4);
> + tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4);
> + tpm_nv_define_space(INDEX1, perm, 4);
> + tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4);
> + tpm_nv_define_space(INDEX2, perm, 4);
> + tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4);
> + tpm_nv_define_space(INDEX3, perm, 4);
> + tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4);
> + perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
> + TPM_NV_PER_PPWRITE;
> + tpm_nv_define_space(INDEX_INITIALISED, perm, 1);
> +}
> +
> +static int test_readonly(void)
> +{
> + uint8_t c;
> + uint32_t index_0, index_1, index_2, index_3;
> + int read0, read1, read2, read3;
> +
> + printf("Testing readonly ...\n");
> + tpm_init();
> + tpm_startup(TPM_ST_CLEAR);
> + tpm_self_test_full();
> + tpm_tsc_physical_presence(PRESENCE);
> + /*
> + * Checks if initialisation has completed by trying to read-lock a
> + * space that's created at the end of initialisation
> + */
> + if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
> + /* The initialisation did not complete */
> + initialise_spaces();
> + }
> +
> + /* Checks if spaces are OK or messed up */
> + read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0));
> + read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1));
> + read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2));
> + read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3));
> + if (read0 || read1 || read2 || read3) {
> + printf("Invalid contents\n");
> + return 0;
> + }
> +
> + /*
> + * Writes space, and locks it. Then attempts to write again.
> + * I really wish I could use the imperative.
> + */
> + index_0 += 1;
> + if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) !=
> + TPM_SUCCESS)) {
> + error("\tcould not write index 0\n");
> + }
> + tpm_nv_write_value_lock(INDEX0);
> + if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) ==
> + TPM_SUCCESS)
> + error("\tindex 0 is not locked\n");
> +
> + printf("\tdone\n");
> + return 0;
> +}
> +
> +static int test_redefine_unowned(void)
> +{
> + uint32_t perm;
> + uint32_t result;
> + uint32_t x;
> +
> + printf("Testing redefine_unowned ...");
> + tpm_init();
> + TPM_CHECK(TlclStartupIfNeeded());
> + TPM_CHECK(tpm_self_test_full());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + assert(!tpm_is_owned());
> +
> + /* Ensures spaces exist. */
> + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
> + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
> +
> + /* Redefines spaces a couple of times. */
> + perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
> + TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t)));
> + TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)));
> + perm = TPM_NV_PER_PPWRITE;
> + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
> + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
> +
> + /* Sets the global lock */
> + tpm_set_global_lock();
> +
> + /* Verifies that index0 cannot be redefined */
> + result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
> + assert(result == TPM_AREA_LOCKED);
> +
> + /* Checks that index1 can */
> + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
> + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
> +
> + /* Turns off PP */
> + tpm_tsc_physical_presence(PHYS_PRESENCE);
> +
> + /* Verifies that neither index0 nor index1 can be redefined */
> + result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
> + assert(result == TPM_BAD_PRESENCE);
> + result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t));
> + assert(result == TPM_BAD_PRESENCE);
> +
> + printf("done\n");
> + return 0;
> +}
> +
> +#define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
> +#define PERMPP TPM_NV_PER_PPWRITE
> +
> +static int test_space_perm(void)
> +{
> + uint32_t perm;
> +
> + printf("Testing spaceperm ...");
> + tpm_init();
> + TPM_CHECK(TlclStartupIfNeeded());
> + TPM_CHECK(tpm_continue_self_test());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + TPM_CHECK(tpm_get_permissions(INDEX0, &perm));
> + assert((perm & PERMPPGL) == PERMPPGL);
> + TPM_CHECK(tpm_get_permissions(INDEX1, &perm));
> + assert((perm & PERMPP) == PERMPP);
> + printf("done\n");
> + return 0;
> +}
> +
> +static int test_startup(void)
> +{
> + uint32_t result;
> + printf("Testing startup ...\n");
> +
> + tpm_init();
> + result = tpm_startup(TPM_ST_CLEAR);
> + if (result != 0 && result != TPM_INVALID_POSTINIT)
> + printf("\ttpm startup failed with 0x%x\n", result);
> + result = tpm_get_flags(NULL, NULL, NULL);
> + if (result != 0)
> + printf("\ttpm getflags failed with 0x%x\n", result);
> + printf("\texecuting SelfTestFull\n");
> + tpm_self_test_full();
> + result = tpm_get_flags(NULL, NULL, NULL);
> + if (result != 0)
> + printf("\ttpm getflags failed with 0x%x\n", result);
> + printf("\tdone\n");
> + return 0;
> +}
> +
> +/*
> + * Runs [op] and ensures it returns success and doesn't run longer than
> + * [time_limit] in milliseconds.
> + */
> +#define TTPM_CHECK(op, time_limit) do { \
> + ulong start, time; \
> + uint32_t __result; \
> + \
> + start = get_timer(0); \
> + __result = op; \
> + if (__result != TPM_SUCCESS) { \
> + printf("\t" #op ": error 0x%x\n", __result); \
> + return -1; \
> + } \
> + time = get_timer(start); \
> + printf("\t" #op ": %lu ms\n", time); \
> + if (time > (ulong)time_limit) { \
> + printf("\t" #op " exceeded " #time_limit " ms\n"); \
> + } \
> +} while (0)
> +
> +
> +static int test_timing(void)
> +{
> + uint32_t x;
> + uint8_t in[20], out[20];
> +
> + printf("Testing timing ...");
> + tpm_init();
> + TTPM_CHECK(TlclStartupIfNeeded(), 50);
> + TTPM_CHECK(tpm_continue_self_test(), 100);
> + TTPM_CHECK(tpm_self_test_full(), 1000);
> + TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100);
> + TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
> + TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
> + TTPM_CHECK(tpm_extend(0, in, out), 200);
> + TTPM_CHECK(tpm_set_global_lock(), 50);
> + TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100);
> + printf("done\n");
> + return 0;
> +}
> +
> +#define TPM_MAX_NV_WRITES_NOOWNER 64
> +
> +static int test_write_limit(void)
> +{
> + printf("Testing writelimit ...\n");
> + int i;
> + uint32_t result;
> +
> + tpm_init();
> + TPM_CHECK(TlclStartupIfNeeded());
> + TPM_CHECK(tpm_self_test_full());
> + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
> + TPM_CHECK(tpm_force_clear());
> + TPM_CHECK(tpm_physical_enable());
> + TPM_CHECK(tpm_physical_set_deactivated(0));
> +
> + for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
> + printf("\twriting %d\n", i);
> + result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i));
> + switch (result) {
> + case TPM_SUCCESS:
> + break;
> + case TPM_MAXNVWRITES:
> + assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
> + default:
> + error("\tunexpected error code %d (0x%x)\n",
> + result, result);
> + }
> + }
> +
> + /* Reset write count */
> + TPM_CHECK(tpm_force_clear());
> + TPM_CHECK(tpm_physical_enable());
> + TPM_CHECK(tpm_physical_set_deactivated(0));
> +
> + /* Try writing again. */
> + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)));
> + printf("\tdone\n");
> + return 0;
> +}
> +
> +#define VOIDTEST(XFUNC) \
> + int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \
> + char * const argv[]) \
> + { \
> + return test_##XFUNC(); \
> + }
> +
> +#define VOIDENT(XNAME) \
> + U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
> +
> +VOIDTEST(early_extend)
> +VOIDTEST(early_nvram)
> +VOIDTEST(early_nvram2)
> +VOIDTEST(enable)
> +VOIDTEST(fast_enable)
> +VOIDTEST(global_lock)
> +VOIDTEST(lock)
> +VOIDTEST(readonly)
> +VOIDTEST(redefine_unowned)
> +VOIDTEST(space_perm)
> +VOIDTEST(startup)
> +VOIDTEST(timing)
> +VOIDTEST(write_limit)
> +VOIDTEST(timer)
> +
> +static cmd_tbl_t cmd_cros_tpm_sub[] = {
> + VOIDENT(early_extend)
> + VOIDENT(early_nvram)
> + VOIDENT(early_nvram2)
> + VOIDENT(enable)
> + VOIDENT(fast_enable)
> + VOIDENT(global_lock)
> + VOIDENT(lock)
> + VOIDENT(readonly)
> + VOIDENT(redefine_unowned)
> + VOIDENT(space_perm)
> + VOIDENT(startup)
> + VOIDENT(timing)
> + VOIDENT(write_limit)
> + VOIDENT(timer)
> +};
> +
> +static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> + cmd_tbl_t *c;
> +
> + printf("argc = %d, argv = ", argc);
> + do {
> + int i = 0;
> +
> + for (i = 0; i < argc; i++)
> + printf(" %s", argv[i]);
> + printf("\n------\n");
> + } while (0);
> + argc--;
> + argv++;
> + c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
> + ARRAY_SIZE(cmd_cros_tpm_sub));
> + return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
> +}
> +
> +U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
> + "\n\tearly_extend\n"
> + "\tearly_nvram\n"
> + "\tearly_nvram2\n"
> + "\tenable\n"
> + "\tfast_enable\n"
> + "\tglobal_lock\n"
> + "\tlock\n"
> + "\treadonly\n"
> + "\tredefine_unowned\n"
> + "\tspace_perm\n"
> + "\tstartup\n"
> + "\ttiming\n"
> + "\twrite_limit\n");
> +
More information about the U-Boot
mailing list