2022-08-31 03:05:36 +00:00
|
|
|
// 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>
|
|
|
|
|
2023-02-21 13:24:51 +00:00
|
|
|
/*
|
|
|
|
* get_tpm_version() - Get a TPM of the given version
|
|
|
|
*
|
|
|
|
* @version: Version to get
|
|
|
|
* @devp: Returns the TPM device
|
|
|
|
* Returns: 0 if OK, -ENODEV if not found
|
|
|
|
*/
|
|
|
|
static int get_tpm_version(enum tpm_version version, struct udevice **devp)
|
|
|
|
{
|
|
|
|
struct udevice *dev;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For now we have to probe each TPM, since the version is set up in
|
|
|
|
* of_to_plat(). We could require TPMs to declare their version when
|
|
|
|
* probed, to avoid this
|
|
|
|
*/
|
|
|
|
uclass_foreach_dev_probe(UCLASS_TPM, dev) {
|
|
|
|
if (tpm_get_version(dev) == version) {
|
|
|
|
*devp = dev;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Basic test of initing a TPM */
|
|
|
|
static int test_tpm_init(struct unit_test_state *uts, enum tpm_version version)
|
|
|
|
{
|
|
|
|
struct udevice *dev;
|
|
|
|
|
|
|
|
/* check probe success */
|
|
|
|
ut_assertok(get_tpm_version(version, &dev));
|
|
|
|
|
|
|
|
ut_assertok(tpm_init(dev));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-31 03:05:36 +00:00
|
|
|
static int dm_test_tpm(struct unit_test_state *uts)
|
2023-02-21 13:24:51 +00:00
|
|
|
{
|
|
|
|
ut_assertok(test_tpm_init(uts, TPM_V1));
|
|
|
|
ut_assertok(test_tpm_init(uts, TPM_V2));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
DM_TEST(dm_test_tpm, UT_TESTF_SCAN_FDT);
|
|
|
|
|
|
|
|
/* Test report_state */
|
|
|
|
static int dm_test_tpm_report_state(struct unit_test_state *uts)
|
2022-08-31 03:05:36 +00:00
|
|
|
{
|
|
|
|
struct udevice *dev;
|
|
|
|
char buf[50];
|
|
|
|
|
|
|
|
/* check probe success */
|
2023-02-21 13:24:51 +00:00
|
|
|
ut_assertok(get_tpm_version(TPM_V2, &dev));
|
2022-08-31 03:05:36 +00:00
|
|
|
|
|
|
|
ut_assert(tpm_report_state(dev, buf, sizeof(buf)));
|
|
|
|
ut_asserteq_str("init_done=0", buf);
|
|
|
|
|
2023-02-18 15:21:22 +00:00
|
|
|
ut_assertok(tpm_auto_start(dev));
|
2022-08-31 03:05:36 +00:00
|
|
|
|
|
|
|
ut_assert(tpm_report_state(dev, buf, sizeof(buf)));
|
|
|
|
ut_asserteq_str("init_done=1", buf);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2023-02-21 13:24:51 +00:00
|
|
|
DM_TEST(dm_test_tpm_report_state, UT_TESTF_SCAN_FDT);
|
2023-02-21 13:24:52 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* test_tpm_autostart() - check the tpm_auto_start() call
|
|
|
|
*
|
|
|
|
* @uts: Unit test state
|
|
|
|
* @version: TPM version to use
|
|
|
|
* @reinit: true to call tpm_init() first
|
|
|
|
* Returns 0 if OK, non-zero on failure
|
|
|
|
*/
|
|
|
|
static int test_tpm_autostart(struct unit_test_state *uts,
|
|
|
|
enum tpm_version version, bool reinit)
|
|
|
|
{
|
|
|
|
struct udevice *dev;
|
|
|
|
|
|
|
|
/* check probe success */
|
|
|
|
ut_assertok(get_tpm_version(version, &dev));
|
|
|
|
|
|
|
|
if (reinit)
|
|
|
|
ut_assertok(tpm_init(dev));
|
|
|
|
/*
|
|
|
|
* tpm_auto_start will rerun tpm_init() if reinit, but handles the
|
|
|
|
* -EBUSY return code internally.
|
|
|
|
*/
|
|
|
|
ut_assertok(tpm_auto_start(dev));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dm_test_tpm_autostart(struct unit_test_state *uts)
|
|
|
|
{
|
|
|
|
ut_assertok(test_tpm_autostart(uts, TPM_V1, false));
|
|
|
|
ut_assertok(test_tpm_autostart(uts, TPM_V2, false));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
DM_TEST(dm_test_tpm_autostart, UT_TESTF_SCAN_FDT);
|
|
|
|
|
|
|
|
static int dm_test_tpm_autostart_reinit(struct unit_test_state *uts)
|
|
|
|
{
|
|
|
|
ut_assertok(test_tpm_autostart(uts, TPM_V1, true));
|
|
|
|
ut_assertok(test_tpm_autostart(uts, TPM_V2, true));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
DM_TEST(dm_test_tpm_autostart_reinit, UT_TESTF_SCAN_FDT);
|