xref: /rk3399_rockchip-uboot/cmd/tpm_test.c (revision 90aa625c9a9e1fb7a2f001fd8e50099bacaf92b8)
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