12e192b24SSimon Glass /*
22e192b24SSimon Glass * Copyright (c) 2015 Google, Inc
32e192b24SSimon Glass *
42e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+
52e192b24SSimon Glass */
62e192b24SSimon Glass
72e192b24SSimon Glass #include <common.h>
82e192b24SSimon Glass #include <command.h>
92e192b24SSimon Glass #include <environment.h>
102e192b24SSimon Glass #include <tpm.h>
112e192b24SSimon Glass
122e192b24SSimon Glass /* Prints error and returns on failure */
132e192b24SSimon Glass #define TPM_CHECK(tpm_command) do { \
142e192b24SSimon Glass uint32_t result; \
152e192b24SSimon Glass \
162e192b24SSimon Glass result = (tpm_command); \
172e192b24SSimon Glass if (result != TPM_SUCCESS) { \
182e192b24SSimon Glass printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
192e192b24SSimon Glass __LINE__, result); \
202e192b24SSimon Glass return result; \
212e192b24SSimon Glass } \
222e192b24SSimon Glass } while (0)
232e192b24SSimon Glass
242e192b24SSimon Glass #define INDEX0 0xda70
252e192b24SSimon Glass #define INDEX1 0xda71
262e192b24SSimon Glass #define INDEX2 0xda72
272e192b24SSimon Glass #define INDEX3 0xda73
282e192b24SSimon Glass #define INDEX_INITIALISED 0xda80
292e192b24SSimon Glass #define PHYS_PRESENCE 4
302e192b24SSimon Glass #define PRESENCE 8
312e192b24SSimon Glass
TlclStartupIfNeeded(void)322e192b24SSimon Glass static uint32_t TlclStartupIfNeeded(void)
332e192b24SSimon Glass {
342e192b24SSimon Glass uint32_t result = tpm_startup(TPM_ST_CLEAR);
352e192b24SSimon Glass
362e192b24SSimon Glass return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
372e192b24SSimon Glass }
382e192b24SSimon Glass
test_timer(void)392e192b24SSimon Glass static int test_timer(void)
402e192b24SSimon Glass {
412e192b24SSimon Glass printf("get_timer(0) = %lu\n", get_timer(0));
422e192b24SSimon Glass return 0;
432e192b24SSimon Glass }
442e192b24SSimon Glass
tpm_get_flags(uint8_t * disable,uint8_t * deactivated,uint8_t * nvlocked)452e192b24SSimon Glass static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated,
462e192b24SSimon Glass uint8_t *nvlocked)
472e192b24SSimon Glass {
482e192b24SSimon Glass struct tpm_permanent_flags pflags;
492e192b24SSimon Glass uint32_t result;
502e192b24SSimon Glass
512e192b24SSimon Glass result = tpm_get_permanent_flags(&pflags);
522e192b24SSimon Glass if (result)
532e192b24SSimon Glass return result;
542e192b24SSimon Glass if (disable)
552e192b24SSimon Glass *disable = pflags.disable;
562e192b24SSimon Glass if (deactivated)
572e192b24SSimon Glass *deactivated = pflags.deactivated;
582e192b24SSimon Glass if (nvlocked)
592e192b24SSimon Glass *nvlocked = pflags.nv_locked;
602e192b24SSimon Glass debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
612e192b24SSimon Glass pflags.disable, pflags.deactivated, pflags.nv_locked);
622e192b24SSimon Glass
632e192b24SSimon Glass return 0;
642e192b24SSimon Glass }
652e192b24SSimon Glass
tpm_set_global_lock(void)662e192b24SSimon Glass static uint32_t tpm_set_global_lock(void)
672e192b24SSimon Glass {
682e192b24SSimon Glass uint32_t x;
692e192b24SSimon Glass
702e192b24SSimon Glass debug("TPM: Set global lock\n");
712e192b24SSimon Glass return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0);
722e192b24SSimon Glass }
732e192b24SSimon Glass
tpm_nv_write_value_lock(uint32_t index)742e192b24SSimon Glass static uint32_t tpm_nv_write_value_lock(uint32_t index)
752e192b24SSimon Glass {
762e192b24SSimon Glass debug("TPM: Write lock 0x%x\n", index);
772e192b24SSimon Glass
782e192b24SSimon Glass return tpm_nv_write_value(index, NULL, 0);
792e192b24SSimon Glass }
802e192b24SSimon Glass
tpm_nv_set_locked(void)812e192b24SSimon Glass static uint32_t tpm_nv_set_locked(void)
822e192b24SSimon Glass {
832e192b24SSimon Glass debug("TPM: Set NV locked\n");
842e192b24SSimon Glass
852e192b24SSimon Glass return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
862e192b24SSimon Glass }
872e192b24SSimon Glass
tpm_is_owned(void)882e192b24SSimon Glass static int tpm_is_owned(void)
892e192b24SSimon Glass {
902e192b24SSimon Glass uint8_t response[TPM_PUBEK_SIZE];
912e192b24SSimon Glass uint32_t result;
922e192b24SSimon Glass
932e192b24SSimon Glass result = tpm_read_pubek(response, sizeof(response));
942e192b24SSimon Glass
952e192b24SSimon Glass return result != TPM_SUCCESS;
962e192b24SSimon Glass }
972e192b24SSimon Glass
test_early_extend(void)982e192b24SSimon Glass static int test_early_extend(void)
992e192b24SSimon Glass {
1002e192b24SSimon Glass uint8_t value_in[20];
1012e192b24SSimon Glass uint8_t value_out[20];
1022e192b24SSimon Glass
1032e192b24SSimon Glass printf("Testing earlyextend ...");
1042e192b24SSimon Glass tpm_init();
1052e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
1062e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test());
1072e192b24SSimon Glass TPM_CHECK(tpm_extend(1, value_in, value_out));
1082e192b24SSimon Glass printf("done\n");
1092e192b24SSimon Glass return 0;
1102e192b24SSimon Glass }
1112e192b24SSimon Glass
test_early_nvram(void)1122e192b24SSimon Glass static int test_early_nvram(void)
1132e192b24SSimon Glass {
1142e192b24SSimon Glass uint32_t x;
1152e192b24SSimon Glass
1162e192b24SSimon Glass printf("Testing earlynvram ...");
1172e192b24SSimon Glass tpm_init();
1182e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
1192e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test());
1202e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
1212e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
1222e192b24SSimon Glass printf("done\n");
1232e192b24SSimon Glass return 0;
1242e192b24SSimon Glass }
1252e192b24SSimon Glass
test_early_nvram2(void)1262e192b24SSimon Glass static int test_early_nvram2(void)
1272e192b24SSimon Glass {
1282e192b24SSimon Glass uint32_t x;
1292e192b24SSimon Glass
1302e192b24SSimon Glass printf("Testing earlynvram2 ...");
1312e192b24SSimon Glass tpm_init();
1322e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
1332e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test());
1342e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
1352e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)));
1362e192b24SSimon Glass printf("done\n");
1372e192b24SSimon Glass return 0;
1382e192b24SSimon Glass }
1392e192b24SSimon Glass
test_enable(void)1402e192b24SSimon Glass static int test_enable(void)
1412e192b24SSimon Glass {
1422e192b24SSimon Glass uint8_t disable = 0, deactivated = 0;
1432e192b24SSimon Glass
1442e192b24SSimon Glass printf("Testing enable ...\n");
1452e192b24SSimon Glass tpm_init();
1462e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded());
1472e192b24SSimon Glass TPM_CHECK(tpm_self_test_full());
1482e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
1492e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
1502e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
1512e192b24SSimon Glass TPM_CHECK(tpm_physical_enable());
1522e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0));
1532e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
1542e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
1552e192b24SSimon Glass if (disable == 1 || deactivated == 1)
1562e192b24SSimon Glass printf("\tfailed to enable or activate\n");
1572e192b24SSimon Glass printf("\tdone\n");
1582e192b24SSimon Glass return 0;
1592e192b24SSimon Glass }
1602e192b24SSimon Glass
1612e192b24SSimon Glass #define reboot() do { \
1622e192b24SSimon Glass printf("\trebooting...\n"); \
1632e192b24SSimon Glass reset_cpu(0); \
1642e192b24SSimon Glass } while (0)
1652e192b24SSimon Glass
test_fast_enable(void)1662e192b24SSimon Glass static int test_fast_enable(void)
1672e192b24SSimon Glass {
1682e192b24SSimon Glass uint8_t disable = 0, deactivated = 0;
1692e192b24SSimon Glass int i;
1702e192b24SSimon Glass
1712e192b24SSimon Glass printf("Testing fastenable ...\n");
1722e192b24SSimon Glass tpm_init();
1732e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded());
1742e192b24SSimon Glass TPM_CHECK(tpm_self_test_full());
1752e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
1762e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
1772e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
1782e192b24SSimon Glass for (i = 0; i < 2; i++) {
1792e192b24SSimon Glass TPM_CHECK(tpm_force_clear());
1802e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
1812e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable,
1822e192b24SSimon Glass deactivated);
1832e192b24SSimon Glass assert(disable == 1 && deactivated == 1);
1842e192b24SSimon Glass TPM_CHECK(tpm_physical_enable());
1852e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0));
1862e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
1872e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable,
1882e192b24SSimon Glass deactivated);
1892e192b24SSimon Glass assert(disable == 0 && deactivated == 0);
1902e192b24SSimon Glass }
1912e192b24SSimon Glass printf("\tdone\n");
1922e192b24SSimon Glass return 0;
1932e192b24SSimon Glass }
1942e192b24SSimon Glass
test_global_lock(void)1952e192b24SSimon Glass static int test_global_lock(void)
1962e192b24SSimon Glass {
1972e192b24SSimon Glass uint32_t zero = 0;
1982e192b24SSimon Glass uint32_t result;
1992e192b24SSimon Glass uint32_t x;
2002e192b24SSimon Glass
2012e192b24SSimon Glass printf("Testing globallock ...\n");
2022e192b24SSimon Glass tpm_init();
2032e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded());
2042e192b24SSimon Glass TPM_CHECK(tpm_self_test_full());
2052e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
2062e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
2072e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero,
2082e192b24SSimon Glass sizeof(uint32_t)));
2092e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
2102e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero,
2112e192b24SSimon Glass sizeof(uint32_t)));
2122e192b24SSimon Glass TPM_CHECK(tpm_set_global_lock());
2132e192b24SSimon Glass /* Verifies that write to index0 fails */
2142e192b24SSimon Glass x = 1;
2152e192b24SSimon Glass result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x));
2162e192b24SSimon Glass assert(result == TPM_AREA_LOCKED);
2172e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
2182e192b24SSimon Glass assert(x == 0);
2192e192b24SSimon Glass /* Verifies that write to index1 is still possible */
2202e192b24SSimon Glass x = 2;
2212e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)));
2222e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
2232e192b24SSimon Glass assert(x == 2);
2242e192b24SSimon Glass /* Turns off PP */
2252e192b24SSimon Glass tpm_tsc_physical_presence(PHYS_PRESENCE);
2262e192b24SSimon Glass /* Verifies that write to index1 fails */
2272e192b24SSimon Glass x = 3;
2282e192b24SSimon Glass result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x));
2292e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE);
2302e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
2312e192b24SSimon Glass assert(x == 2);
2322e192b24SSimon Glass printf("\tdone\n");
2332e192b24SSimon Glass return 0;
2342e192b24SSimon Glass }
2352e192b24SSimon Glass
test_lock(void)2362e192b24SSimon Glass static int test_lock(void)
2372e192b24SSimon Glass {
2382e192b24SSimon Glass printf("Testing lock ...\n");
2392e192b24SSimon Glass tpm_init();
2402e192b24SSimon Glass tpm_startup(TPM_ST_CLEAR);
2412e192b24SSimon Glass tpm_self_test_full();
2422e192b24SSimon Glass tpm_tsc_physical_presence(PRESENCE);
2432e192b24SSimon Glass tpm_nv_write_value_lock(INDEX0);
2442e192b24SSimon Glass printf("\tLocked 0x%x\n", INDEX0);
2452e192b24SSimon Glass printf("\tdone\n");
2462e192b24SSimon Glass return 0;
2472e192b24SSimon Glass }
2482e192b24SSimon Glass
initialise_spaces(void)2492e192b24SSimon Glass static void initialise_spaces(void)
2502e192b24SSimon Glass {
2512e192b24SSimon Glass uint32_t zero = 0;
2522e192b24SSimon Glass uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
2532e192b24SSimon Glass
2542e192b24SSimon Glass printf("\tInitialising spaces\n");
2552e192b24SSimon Glass tpm_nv_set_locked(); /* useful only the first time */
2562e192b24SSimon Glass tpm_nv_define_space(INDEX0, perm, 4);
2572e192b24SSimon Glass tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4);
2582e192b24SSimon Glass tpm_nv_define_space(INDEX1, perm, 4);
2592e192b24SSimon Glass tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4);
2602e192b24SSimon Glass tpm_nv_define_space(INDEX2, perm, 4);
2612e192b24SSimon Glass tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4);
2622e192b24SSimon Glass tpm_nv_define_space(INDEX3, perm, 4);
2632e192b24SSimon Glass tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4);
2642e192b24SSimon Glass perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
2652e192b24SSimon Glass TPM_NV_PER_PPWRITE;
2662e192b24SSimon Glass tpm_nv_define_space(INDEX_INITIALISED, perm, 1);
2672e192b24SSimon Glass }
2682e192b24SSimon Glass
test_readonly(void)2692e192b24SSimon Glass static int test_readonly(void)
2702e192b24SSimon Glass {
2712e192b24SSimon Glass uint8_t c;
2722e192b24SSimon Glass uint32_t index_0, index_1, index_2, index_3;
2732e192b24SSimon Glass int read0, read1, read2, read3;
2742e192b24SSimon Glass
2752e192b24SSimon Glass printf("Testing readonly ...\n");
2762e192b24SSimon Glass tpm_init();
2772e192b24SSimon Glass tpm_startup(TPM_ST_CLEAR);
2782e192b24SSimon Glass tpm_self_test_full();
2792e192b24SSimon Glass tpm_tsc_physical_presence(PRESENCE);
2802e192b24SSimon Glass /*
2812e192b24SSimon Glass * Checks if initialisation has completed by trying to read-lock a
2822e192b24SSimon Glass * space that's created at the end of initialisation
2832e192b24SSimon Glass */
2842e192b24SSimon Glass if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
2852e192b24SSimon Glass /* The initialisation did not complete */
2862e192b24SSimon Glass initialise_spaces();
2872e192b24SSimon Glass }
2882e192b24SSimon Glass
2892e192b24SSimon Glass /* Checks if spaces are OK or messed up */
2902e192b24SSimon Glass read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0));
2912e192b24SSimon Glass read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1));
2922e192b24SSimon Glass read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2));
2932e192b24SSimon Glass read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3));
2942e192b24SSimon Glass if (read0 || read1 || read2 || read3) {
2952e192b24SSimon Glass printf("Invalid contents\n");
2962e192b24SSimon Glass return 0;
2972e192b24SSimon Glass }
2982e192b24SSimon Glass
2992e192b24SSimon Glass /*
3002e192b24SSimon Glass * Writes space, and locks it. Then attempts to write again.
3012e192b24SSimon Glass * I really wish I could use the imperative.
3022e192b24SSimon Glass */
3032e192b24SSimon Glass index_0 += 1;
3042e192b24SSimon Glass if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) !=
3052e192b24SSimon Glass TPM_SUCCESS)) {
306*90aa625cSMasahiro Yamada pr_err("\tcould not write index 0\n");
3072e192b24SSimon Glass }
3082e192b24SSimon Glass tpm_nv_write_value_lock(INDEX0);
3092e192b24SSimon Glass if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) ==
3102e192b24SSimon Glass TPM_SUCCESS)
311*90aa625cSMasahiro Yamada pr_err("\tindex 0 is not locked\n");
3122e192b24SSimon Glass
3132e192b24SSimon Glass printf("\tdone\n");
3142e192b24SSimon Glass return 0;
3152e192b24SSimon Glass }
3162e192b24SSimon Glass
test_redefine_unowned(void)3172e192b24SSimon Glass static int test_redefine_unowned(void)
3182e192b24SSimon Glass {
3192e192b24SSimon Glass uint32_t perm;
3202e192b24SSimon Glass uint32_t result;
3212e192b24SSimon Glass uint32_t x;
3222e192b24SSimon Glass
3232e192b24SSimon Glass printf("Testing redefine_unowned ...");
3242e192b24SSimon Glass tpm_init();
3252e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded());
3262e192b24SSimon Glass TPM_CHECK(tpm_self_test_full());
3272e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
3282e192b24SSimon Glass assert(!tpm_is_owned());
3292e192b24SSimon Glass
3302e192b24SSimon Glass /* Ensures spaces exist. */
3312e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
3322e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
3332e192b24SSimon Glass
3342e192b24SSimon Glass /* Redefines spaces a couple of times. */
3352e192b24SSimon Glass perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
3362e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t)));
3372e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)));
3382e192b24SSimon Glass perm = TPM_NV_PER_PPWRITE;
3392e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
3402e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
3412e192b24SSimon Glass
3422e192b24SSimon Glass /* Sets the global lock */
3432e192b24SSimon Glass tpm_set_global_lock();
3442e192b24SSimon Glass
3452e192b24SSimon Glass /* Verifies that index0 cannot be redefined */
3462e192b24SSimon Glass result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
3472e192b24SSimon Glass assert(result == TPM_AREA_LOCKED);
3482e192b24SSimon Glass
3492e192b24SSimon Glass /* Checks that index1 can */
3502e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
3512e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
3522e192b24SSimon Glass
3532e192b24SSimon Glass /* Turns off PP */
3542e192b24SSimon Glass tpm_tsc_physical_presence(PHYS_PRESENCE);
3552e192b24SSimon Glass
3562e192b24SSimon Glass /* Verifies that neither index0 nor index1 can be redefined */
3572e192b24SSimon Glass result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
3582e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE);
3592e192b24SSimon Glass result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t));
3602e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE);
3612e192b24SSimon Glass
3622e192b24SSimon Glass printf("done\n");
3632e192b24SSimon Glass return 0;
3642e192b24SSimon Glass }
3652e192b24SSimon Glass
3662e192b24SSimon Glass #define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
3672e192b24SSimon Glass #define PERMPP TPM_NV_PER_PPWRITE
3682e192b24SSimon Glass
test_space_perm(void)3692e192b24SSimon Glass static int test_space_perm(void)
3702e192b24SSimon Glass {
3712e192b24SSimon Glass uint32_t perm;
3722e192b24SSimon Glass
3732e192b24SSimon Glass printf("Testing spaceperm ...");
3742e192b24SSimon Glass tpm_init();
3752e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded());
3762e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test());
3772e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
3782e192b24SSimon Glass TPM_CHECK(tpm_get_permissions(INDEX0, &perm));
3792e192b24SSimon Glass assert((perm & PERMPPGL) == PERMPPGL);
3802e192b24SSimon Glass TPM_CHECK(tpm_get_permissions(INDEX1, &perm));
3812e192b24SSimon Glass assert((perm & PERMPP) == PERMPP);
3822e192b24SSimon Glass printf("done\n");
3832e192b24SSimon Glass return 0;
3842e192b24SSimon Glass }
3852e192b24SSimon Glass
test_startup(void)3862e192b24SSimon Glass static int test_startup(void)
3872e192b24SSimon Glass {
3882e192b24SSimon Glass uint32_t result;
3892e192b24SSimon Glass printf("Testing startup ...\n");
3902e192b24SSimon Glass
3912e192b24SSimon Glass tpm_init();
3922e192b24SSimon Glass result = tpm_startup(TPM_ST_CLEAR);
3932e192b24SSimon Glass if (result != 0 && result != TPM_INVALID_POSTINIT)
3942e192b24SSimon Glass printf("\ttpm startup failed with 0x%x\n", result);
3952e192b24SSimon Glass result = tpm_get_flags(NULL, NULL, NULL);
3962e192b24SSimon Glass if (result != 0)
3972e192b24SSimon Glass printf("\ttpm getflags failed with 0x%x\n", result);
3982e192b24SSimon Glass printf("\texecuting SelfTestFull\n");
3992e192b24SSimon Glass tpm_self_test_full();
4002e192b24SSimon Glass result = tpm_get_flags(NULL, NULL, NULL);
4012e192b24SSimon Glass if (result != 0)
4022e192b24SSimon Glass printf("\ttpm getflags failed with 0x%x\n", result);
4032e192b24SSimon Glass printf("\tdone\n");
4042e192b24SSimon Glass return 0;
4052e192b24SSimon Glass }
4062e192b24SSimon Glass
4072e192b24SSimon Glass /*
4082e192b24SSimon Glass * Runs [op] and ensures it returns success and doesn't run longer than
4092e192b24SSimon Glass * [time_limit] in milliseconds.
4102e192b24SSimon Glass */
4112e192b24SSimon Glass #define TTPM_CHECK(op, time_limit) do { \
4122e192b24SSimon Glass ulong start, time; \
4132e192b24SSimon Glass uint32_t __result; \
4142e192b24SSimon Glass \
4152e192b24SSimon Glass start = get_timer(0); \
4162e192b24SSimon Glass __result = op; \
4172e192b24SSimon Glass if (__result != TPM_SUCCESS) { \
4182e192b24SSimon Glass printf("\t" #op ": error 0x%x\n", __result); \
4192e192b24SSimon Glass return -1; \
4202e192b24SSimon Glass } \
4212e192b24SSimon Glass time = get_timer(start); \
4222e192b24SSimon Glass printf("\t" #op ": %lu ms\n", time); \
4232e192b24SSimon Glass if (time > (ulong)time_limit) { \
4242e192b24SSimon Glass printf("\t" #op " exceeded " #time_limit " ms\n"); \
4252e192b24SSimon Glass } \
4262e192b24SSimon Glass } while (0)
4272e192b24SSimon Glass
4282e192b24SSimon Glass
test_timing(void)4292e192b24SSimon Glass static int test_timing(void)
4302e192b24SSimon Glass {
4312e192b24SSimon Glass uint32_t x;
4322e192b24SSimon Glass uint8_t in[20], out[20];
4332e192b24SSimon Glass
4342e192b24SSimon Glass printf("Testing timing ...");
4352e192b24SSimon Glass tpm_init();
4362e192b24SSimon Glass TTPM_CHECK(TlclStartupIfNeeded(), 50);
4372e192b24SSimon Glass TTPM_CHECK(tpm_continue_self_test(), 100);
4382e192b24SSimon Glass TTPM_CHECK(tpm_self_test_full(), 1000);
4392e192b24SSimon Glass TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100);
4402e192b24SSimon Glass TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
4412e192b24SSimon Glass TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
4422e192b24SSimon Glass TTPM_CHECK(tpm_extend(0, in, out), 200);
4432e192b24SSimon Glass TTPM_CHECK(tpm_set_global_lock(), 50);
4442e192b24SSimon Glass TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100);
4452e192b24SSimon Glass printf("done\n");
4462e192b24SSimon Glass return 0;
4472e192b24SSimon Glass }
4482e192b24SSimon Glass
4492e192b24SSimon Glass #define TPM_MAX_NV_WRITES_NOOWNER 64
4502e192b24SSimon Glass
test_write_limit(void)4512e192b24SSimon Glass static int test_write_limit(void)
4522e192b24SSimon Glass {
4532e192b24SSimon Glass printf("Testing writelimit ...\n");
4542e192b24SSimon Glass int i;
4552e192b24SSimon Glass uint32_t result;
4562e192b24SSimon Glass
4572e192b24SSimon Glass tpm_init();
4582e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded());
4592e192b24SSimon Glass TPM_CHECK(tpm_self_test_full());
4602e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
4612e192b24SSimon Glass TPM_CHECK(tpm_force_clear());
4622e192b24SSimon Glass TPM_CHECK(tpm_physical_enable());
4632e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0));
4642e192b24SSimon Glass
4652e192b24SSimon Glass for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
4662e192b24SSimon Glass printf("\twriting %d\n", i);
4672e192b24SSimon Glass result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i));
4682e192b24SSimon Glass switch (result) {
4692e192b24SSimon Glass case TPM_SUCCESS:
4702e192b24SSimon Glass break;
4712e192b24SSimon Glass case TPM_MAXNVWRITES:
4722e192b24SSimon Glass assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
4732e192b24SSimon Glass default:
474*90aa625cSMasahiro Yamada pr_err("\tunexpected error code %d (0x%x)\n",
4752e192b24SSimon Glass result, result);
4762e192b24SSimon Glass }
4772e192b24SSimon Glass }
4782e192b24SSimon Glass
4792e192b24SSimon Glass /* Reset write count */
4802e192b24SSimon Glass TPM_CHECK(tpm_force_clear());
4812e192b24SSimon Glass TPM_CHECK(tpm_physical_enable());
4822e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0));
4832e192b24SSimon Glass
4842e192b24SSimon Glass /* Try writing again. */
4852e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)));
4862e192b24SSimon Glass printf("\tdone\n");
4872e192b24SSimon Glass return 0;
4882e192b24SSimon Glass }
4892e192b24SSimon Glass
4902e192b24SSimon Glass #define VOIDTEST(XFUNC) \
4912e192b24SSimon Glass int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \
4922e192b24SSimon Glass char * const argv[]) \
4932e192b24SSimon Glass { \
4942e192b24SSimon Glass return test_##XFUNC(); \
4952e192b24SSimon Glass }
4962e192b24SSimon Glass
4972e192b24SSimon Glass #define VOIDENT(XNAME) \
4982e192b24SSimon Glass U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
4992e192b24SSimon Glass
5002e192b24SSimon Glass VOIDTEST(early_extend)
5012e192b24SSimon Glass VOIDTEST(early_nvram)
5022e192b24SSimon Glass VOIDTEST(early_nvram2)
5032e192b24SSimon Glass VOIDTEST(enable)
5042e192b24SSimon Glass VOIDTEST(fast_enable)
5052e192b24SSimon Glass VOIDTEST(global_lock)
5062e192b24SSimon Glass VOIDTEST(lock)
5072e192b24SSimon Glass VOIDTEST(readonly)
5082e192b24SSimon Glass VOIDTEST(redefine_unowned)
5092e192b24SSimon Glass VOIDTEST(space_perm)
5102e192b24SSimon Glass VOIDTEST(startup)
5112e192b24SSimon Glass VOIDTEST(timing)
5122e192b24SSimon Glass VOIDTEST(write_limit)
5132e192b24SSimon Glass VOIDTEST(timer)
5142e192b24SSimon Glass
5152e192b24SSimon Glass static cmd_tbl_t cmd_cros_tpm_sub[] = {
5162e192b24SSimon Glass VOIDENT(early_extend)
5172e192b24SSimon Glass VOIDENT(early_nvram)
5182e192b24SSimon Glass VOIDENT(early_nvram2)
5192e192b24SSimon Glass VOIDENT(enable)
5202e192b24SSimon Glass VOIDENT(fast_enable)
5212e192b24SSimon Glass VOIDENT(global_lock)
5222e192b24SSimon Glass VOIDENT(lock)
5232e192b24SSimon Glass VOIDENT(readonly)
5242e192b24SSimon Glass VOIDENT(redefine_unowned)
5252e192b24SSimon Glass VOIDENT(space_perm)
5262e192b24SSimon Glass VOIDENT(startup)
5272e192b24SSimon Glass VOIDENT(timing)
5282e192b24SSimon Glass VOIDENT(write_limit)
5292e192b24SSimon Glass VOIDENT(timer)
5302e192b24SSimon Glass };
5312e192b24SSimon Glass
do_tpmtest(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])5322e192b24SSimon Glass static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5332e192b24SSimon Glass {
5342e192b24SSimon Glass cmd_tbl_t *c;
5350427b9c5SStefan Brüns int i;
5362e192b24SSimon Glass
5372e192b24SSimon Glass printf("argc = %d, argv = ", argc);
5382e192b24SSimon Glass
5392e192b24SSimon Glass for (i = 0; i < argc; i++)
5402e192b24SSimon Glass printf(" %s", argv[i]);
5410427b9c5SStefan Brüns
5422e192b24SSimon Glass printf("\n------\n");
5430427b9c5SStefan Brüns
5442e192b24SSimon Glass argc--;
5452e192b24SSimon Glass argv++;
5462e192b24SSimon Glass c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
5472e192b24SSimon Glass ARRAY_SIZE(cmd_cros_tpm_sub));
5482e192b24SSimon Glass return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
5492e192b24SSimon Glass }
5502e192b24SSimon Glass
5512e192b24SSimon Glass U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
5522e192b24SSimon Glass "\n\tearly_extend\n"
5532e192b24SSimon Glass "\tearly_nvram\n"
5542e192b24SSimon Glass "\tearly_nvram2\n"
5552e192b24SSimon Glass "\tenable\n"
5562e192b24SSimon Glass "\tfast_enable\n"
5572e192b24SSimon Glass "\tglobal_lock\n"
5582e192b24SSimon Glass "\tlock\n"
5592e192b24SSimon Glass "\treadonly\n"
5602e192b24SSimon Glass "\tredefine_unowned\n"
5612e192b24SSimon Glass "\tspace_perm\n"
5622e192b24SSimon Glass "\tstartup\n"
5632e192b24SSimon Glass "\ttiming\n"
5642e192b24SSimon Glass "\twrite_limit\n");
565