xref: /rk3399_rockchip-uboot/cmd/tpm_test.c (revision 2e192b245ed36a63bab0ef576999a95e23f60ecd)
1*2e192b24SSimon Glass /*
2*2e192b24SSimon Glass  * Copyright (c) 2015 Google, Inc
3*2e192b24SSimon Glass  *
4*2e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
5*2e192b24SSimon Glass  */
6*2e192b24SSimon Glass 
7*2e192b24SSimon Glass #include <common.h>
8*2e192b24SSimon Glass #include <command.h>
9*2e192b24SSimon Glass #include <environment.h>
10*2e192b24SSimon Glass #include <tpm.h>
11*2e192b24SSimon Glass 
12*2e192b24SSimon Glass /* Prints error and returns on failure */
13*2e192b24SSimon Glass #define TPM_CHECK(tpm_command) do { \
14*2e192b24SSimon Glass 	uint32_t result; \
15*2e192b24SSimon Glass 	\
16*2e192b24SSimon Glass 	result = (tpm_command); \
17*2e192b24SSimon Glass 	if (result != TPM_SUCCESS) { \
18*2e192b24SSimon Glass 		printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
19*2e192b24SSimon Glass 			__LINE__, result); \
20*2e192b24SSimon Glass 		return result; \
21*2e192b24SSimon Glass 	} \
22*2e192b24SSimon Glass } while (0)
23*2e192b24SSimon Glass 
24*2e192b24SSimon Glass #define INDEX0			0xda70
25*2e192b24SSimon Glass #define INDEX1			0xda71
26*2e192b24SSimon Glass #define INDEX2			0xda72
27*2e192b24SSimon Glass #define INDEX3			0xda73
28*2e192b24SSimon Glass #define INDEX_INITIALISED	0xda80
29*2e192b24SSimon Glass #define PHYS_PRESENCE		4
30*2e192b24SSimon Glass #define PRESENCE		8
31*2e192b24SSimon Glass 
32*2e192b24SSimon Glass static uint32_t TlclStartupIfNeeded(void)
33*2e192b24SSimon Glass {
34*2e192b24SSimon Glass 	uint32_t result = tpm_startup(TPM_ST_CLEAR);
35*2e192b24SSimon Glass 
36*2e192b24SSimon Glass 	return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
37*2e192b24SSimon Glass }
38*2e192b24SSimon Glass 
39*2e192b24SSimon Glass static int test_timer(void)
40*2e192b24SSimon Glass {
41*2e192b24SSimon Glass 	printf("get_timer(0) = %lu\n", get_timer(0));
42*2e192b24SSimon Glass 	return 0;
43*2e192b24SSimon Glass }
44*2e192b24SSimon Glass 
45*2e192b24SSimon Glass static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated,
46*2e192b24SSimon Glass 			      uint8_t *nvlocked)
47*2e192b24SSimon Glass {
48*2e192b24SSimon Glass 	struct tpm_permanent_flags pflags;
49*2e192b24SSimon Glass 	uint32_t result;
50*2e192b24SSimon Glass 
51*2e192b24SSimon Glass 	result = tpm_get_permanent_flags(&pflags);
52*2e192b24SSimon Glass 	if (result)
53*2e192b24SSimon Glass 		return result;
54*2e192b24SSimon Glass 	if (disable)
55*2e192b24SSimon Glass 		*disable = pflags.disable;
56*2e192b24SSimon Glass 	if (deactivated)
57*2e192b24SSimon Glass 		*deactivated = pflags.deactivated;
58*2e192b24SSimon Glass 	if (nvlocked)
59*2e192b24SSimon Glass 		*nvlocked = pflags.nv_locked;
60*2e192b24SSimon Glass 	debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
61*2e192b24SSimon Glass 	      pflags.disable, pflags.deactivated, pflags.nv_locked);
62*2e192b24SSimon Glass 
63*2e192b24SSimon Glass 	return 0;
64*2e192b24SSimon Glass }
65*2e192b24SSimon Glass 
66*2e192b24SSimon Glass static uint32_t tpm_set_global_lock(void)
67*2e192b24SSimon Glass {
68*2e192b24SSimon Glass 	uint32_t x;
69*2e192b24SSimon Glass 
70*2e192b24SSimon Glass 	debug("TPM: Set global lock\n");
71*2e192b24SSimon Glass 	return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0);
72*2e192b24SSimon Glass }
73*2e192b24SSimon Glass 
74*2e192b24SSimon Glass static uint32_t tpm_nv_write_value_lock(uint32_t index)
75*2e192b24SSimon Glass {
76*2e192b24SSimon Glass 	debug("TPM: Write lock 0x%x\n", index);
77*2e192b24SSimon Glass 
78*2e192b24SSimon Glass 	return tpm_nv_write_value(index, NULL, 0);
79*2e192b24SSimon Glass }
80*2e192b24SSimon Glass 
81*2e192b24SSimon Glass static uint32_t tpm_nv_set_locked(void)
82*2e192b24SSimon Glass {
83*2e192b24SSimon Glass 	debug("TPM: Set NV locked\n");
84*2e192b24SSimon Glass 
85*2e192b24SSimon Glass 	return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
86*2e192b24SSimon Glass }
87*2e192b24SSimon Glass 
88*2e192b24SSimon Glass static int tpm_is_owned(void)
89*2e192b24SSimon Glass {
90*2e192b24SSimon Glass 	uint8_t response[TPM_PUBEK_SIZE];
91*2e192b24SSimon Glass 	uint32_t result;
92*2e192b24SSimon Glass 
93*2e192b24SSimon Glass 	result = tpm_read_pubek(response, sizeof(response));
94*2e192b24SSimon Glass 
95*2e192b24SSimon Glass 	return result != TPM_SUCCESS;
96*2e192b24SSimon Glass }
97*2e192b24SSimon Glass 
98*2e192b24SSimon Glass static int test_early_extend(void)
99*2e192b24SSimon Glass {
100*2e192b24SSimon Glass 	uint8_t value_in[20];
101*2e192b24SSimon Glass 	uint8_t value_out[20];
102*2e192b24SSimon Glass 
103*2e192b24SSimon Glass 	printf("Testing earlyextend ...");
104*2e192b24SSimon Glass 	tpm_init();
105*2e192b24SSimon Glass 	TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
106*2e192b24SSimon Glass 	TPM_CHECK(tpm_continue_self_test());
107*2e192b24SSimon Glass 	TPM_CHECK(tpm_extend(1, value_in, value_out));
108*2e192b24SSimon Glass 	printf("done\n");
109*2e192b24SSimon Glass 	return 0;
110*2e192b24SSimon Glass }
111*2e192b24SSimon Glass 
112*2e192b24SSimon Glass static int test_early_nvram(void)
113*2e192b24SSimon Glass {
114*2e192b24SSimon Glass 	uint32_t x;
115*2e192b24SSimon Glass 
116*2e192b24SSimon Glass 	printf("Testing earlynvram ...");
117*2e192b24SSimon Glass 	tpm_init();
118*2e192b24SSimon Glass 	TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
119*2e192b24SSimon Glass 	TPM_CHECK(tpm_continue_self_test());
120*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
121*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
122*2e192b24SSimon Glass 	printf("done\n");
123*2e192b24SSimon Glass 	return 0;
124*2e192b24SSimon Glass }
125*2e192b24SSimon Glass 
126*2e192b24SSimon Glass static int test_early_nvram2(void)
127*2e192b24SSimon Glass {
128*2e192b24SSimon Glass 	uint32_t x;
129*2e192b24SSimon Glass 
130*2e192b24SSimon Glass 	printf("Testing earlynvram2 ...");
131*2e192b24SSimon Glass 	tpm_init();
132*2e192b24SSimon Glass 	TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
133*2e192b24SSimon Glass 	TPM_CHECK(tpm_continue_self_test());
134*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
135*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)));
136*2e192b24SSimon Glass 	printf("done\n");
137*2e192b24SSimon Glass 	return 0;
138*2e192b24SSimon Glass }
139*2e192b24SSimon Glass 
140*2e192b24SSimon Glass static int test_enable(void)
141*2e192b24SSimon Glass {
142*2e192b24SSimon Glass 	uint8_t disable = 0, deactivated = 0;
143*2e192b24SSimon Glass 
144*2e192b24SSimon Glass 	printf("Testing enable ...\n");
145*2e192b24SSimon Glass 	tpm_init();
146*2e192b24SSimon Glass 	TPM_CHECK(TlclStartupIfNeeded());
147*2e192b24SSimon Glass 	TPM_CHECK(tpm_self_test_full());
148*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
149*2e192b24SSimon Glass 	TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
150*2e192b24SSimon Glass 	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
151*2e192b24SSimon Glass 	TPM_CHECK(tpm_physical_enable());
152*2e192b24SSimon Glass 	TPM_CHECK(tpm_physical_set_deactivated(0));
153*2e192b24SSimon Glass 	TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
154*2e192b24SSimon Glass 	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
155*2e192b24SSimon Glass 	if (disable == 1 || deactivated == 1)
156*2e192b24SSimon Glass 		printf("\tfailed to enable or activate\n");
157*2e192b24SSimon Glass 	printf("\tdone\n");
158*2e192b24SSimon Glass 	return 0;
159*2e192b24SSimon Glass }
160*2e192b24SSimon Glass 
161*2e192b24SSimon Glass #define reboot() do { \
162*2e192b24SSimon Glass 	printf("\trebooting...\n"); \
163*2e192b24SSimon Glass 	reset_cpu(0); \
164*2e192b24SSimon Glass } while (0)
165*2e192b24SSimon Glass 
166*2e192b24SSimon Glass static int test_fast_enable(void)
167*2e192b24SSimon Glass {
168*2e192b24SSimon Glass 	uint8_t disable = 0, deactivated = 0;
169*2e192b24SSimon Glass 	int i;
170*2e192b24SSimon Glass 
171*2e192b24SSimon Glass 	printf("Testing fastenable ...\n");
172*2e192b24SSimon Glass 	tpm_init();
173*2e192b24SSimon Glass 	TPM_CHECK(TlclStartupIfNeeded());
174*2e192b24SSimon Glass 	TPM_CHECK(tpm_self_test_full());
175*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
176*2e192b24SSimon Glass 	TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
177*2e192b24SSimon Glass 	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
178*2e192b24SSimon Glass 	for (i = 0; i < 2; i++) {
179*2e192b24SSimon Glass 		TPM_CHECK(tpm_force_clear());
180*2e192b24SSimon Glass 		TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
181*2e192b24SSimon Glass 		printf("\tdisable is %d, deactivated is %d\n", disable,
182*2e192b24SSimon Glass 		       deactivated);
183*2e192b24SSimon Glass 		assert(disable == 1 && deactivated == 1);
184*2e192b24SSimon Glass 		TPM_CHECK(tpm_physical_enable());
185*2e192b24SSimon Glass 		TPM_CHECK(tpm_physical_set_deactivated(0));
186*2e192b24SSimon Glass 		TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
187*2e192b24SSimon Glass 		printf("\tdisable is %d, deactivated is %d\n", disable,
188*2e192b24SSimon Glass 		       deactivated);
189*2e192b24SSimon Glass 		assert(disable == 0 && deactivated == 0);
190*2e192b24SSimon Glass 	}
191*2e192b24SSimon Glass 	printf("\tdone\n");
192*2e192b24SSimon Glass 	return 0;
193*2e192b24SSimon Glass }
194*2e192b24SSimon Glass 
195*2e192b24SSimon Glass static int test_global_lock(void)
196*2e192b24SSimon Glass {
197*2e192b24SSimon Glass 	uint32_t zero = 0;
198*2e192b24SSimon Glass 	uint32_t result;
199*2e192b24SSimon Glass 	uint32_t x;
200*2e192b24SSimon Glass 
201*2e192b24SSimon Glass 	printf("Testing globallock ...\n");
202*2e192b24SSimon Glass 	tpm_init();
203*2e192b24SSimon Glass 	TPM_CHECK(TlclStartupIfNeeded());
204*2e192b24SSimon Glass 	TPM_CHECK(tpm_self_test_full());
205*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
206*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
207*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero,
208*2e192b24SSimon Glass 				     sizeof(uint32_t)));
209*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
210*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero,
211*2e192b24SSimon Glass 				     sizeof(uint32_t)));
212*2e192b24SSimon Glass 	TPM_CHECK(tpm_set_global_lock());
213*2e192b24SSimon Glass 	/* Verifies that write to index0 fails */
214*2e192b24SSimon Glass 	x = 1;
215*2e192b24SSimon Glass 	result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x));
216*2e192b24SSimon Glass 	assert(result == TPM_AREA_LOCKED);
217*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
218*2e192b24SSimon Glass 	assert(x == 0);
219*2e192b24SSimon Glass 	/* Verifies that write to index1 is still possible */
220*2e192b24SSimon Glass 	x = 2;
221*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)));
222*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
223*2e192b24SSimon Glass 	assert(x == 2);
224*2e192b24SSimon Glass 	/* Turns off PP */
225*2e192b24SSimon Glass 	tpm_tsc_physical_presence(PHYS_PRESENCE);
226*2e192b24SSimon Glass 	/* Verifies that write to index1 fails */
227*2e192b24SSimon Glass 	x = 3;
228*2e192b24SSimon Glass 	result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x));
229*2e192b24SSimon Glass 	assert(result == TPM_BAD_PRESENCE);
230*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
231*2e192b24SSimon Glass 	assert(x == 2);
232*2e192b24SSimon Glass 	printf("\tdone\n");
233*2e192b24SSimon Glass 	return 0;
234*2e192b24SSimon Glass }
235*2e192b24SSimon Glass 
236*2e192b24SSimon Glass static int test_lock(void)
237*2e192b24SSimon Glass {
238*2e192b24SSimon Glass 	printf("Testing lock ...\n");
239*2e192b24SSimon Glass 	tpm_init();
240*2e192b24SSimon Glass 	tpm_startup(TPM_ST_CLEAR);
241*2e192b24SSimon Glass 	tpm_self_test_full();
242*2e192b24SSimon Glass 	tpm_tsc_physical_presence(PRESENCE);
243*2e192b24SSimon Glass 	tpm_nv_write_value_lock(INDEX0);
244*2e192b24SSimon Glass 	printf("\tLocked 0x%x\n", INDEX0);
245*2e192b24SSimon Glass 	printf("\tdone\n");
246*2e192b24SSimon Glass 	return 0;
247*2e192b24SSimon Glass }
248*2e192b24SSimon Glass 
249*2e192b24SSimon Glass static void initialise_spaces(void)
250*2e192b24SSimon Glass {
251*2e192b24SSimon Glass 	uint32_t zero = 0;
252*2e192b24SSimon Glass 	uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
253*2e192b24SSimon Glass 
254*2e192b24SSimon Glass 	printf("\tInitialising spaces\n");
255*2e192b24SSimon Glass 	tpm_nv_set_locked();  /* useful only the first time */
256*2e192b24SSimon Glass 	tpm_nv_define_space(INDEX0, perm, 4);
257*2e192b24SSimon Glass 	tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4);
258*2e192b24SSimon Glass 	tpm_nv_define_space(INDEX1, perm, 4);
259*2e192b24SSimon Glass 	tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4);
260*2e192b24SSimon Glass 	tpm_nv_define_space(INDEX2, perm, 4);
261*2e192b24SSimon Glass 	tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4);
262*2e192b24SSimon Glass 	tpm_nv_define_space(INDEX3, perm, 4);
263*2e192b24SSimon Glass 	tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4);
264*2e192b24SSimon Glass 	perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
265*2e192b24SSimon Glass 		TPM_NV_PER_PPWRITE;
266*2e192b24SSimon Glass 	tpm_nv_define_space(INDEX_INITIALISED, perm, 1);
267*2e192b24SSimon Glass }
268*2e192b24SSimon Glass 
269*2e192b24SSimon Glass static int test_readonly(void)
270*2e192b24SSimon Glass {
271*2e192b24SSimon Glass 	uint8_t c;
272*2e192b24SSimon Glass 	uint32_t index_0, index_1, index_2, index_3;
273*2e192b24SSimon Glass 	int read0, read1, read2, read3;
274*2e192b24SSimon Glass 
275*2e192b24SSimon Glass 	printf("Testing readonly ...\n");
276*2e192b24SSimon Glass 	tpm_init();
277*2e192b24SSimon Glass 	tpm_startup(TPM_ST_CLEAR);
278*2e192b24SSimon Glass 	tpm_self_test_full();
279*2e192b24SSimon Glass 	tpm_tsc_physical_presence(PRESENCE);
280*2e192b24SSimon Glass 	/*
281*2e192b24SSimon Glass 	 * Checks if initialisation has completed by trying to read-lock a
282*2e192b24SSimon Glass 	 * space that's created at the end of initialisation
283*2e192b24SSimon Glass 	 */
284*2e192b24SSimon Glass 	if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
285*2e192b24SSimon Glass 		/* The initialisation did not complete */
286*2e192b24SSimon Glass 		initialise_spaces();
287*2e192b24SSimon Glass 	}
288*2e192b24SSimon Glass 
289*2e192b24SSimon Glass 	/* Checks if spaces are OK or messed up */
290*2e192b24SSimon Glass 	read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0));
291*2e192b24SSimon Glass 	read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1));
292*2e192b24SSimon Glass 	read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2));
293*2e192b24SSimon Glass 	read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3));
294*2e192b24SSimon Glass 	if (read0 || read1 || read2 || read3) {
295*2e192b24SSimon Glass 		printf("Invalid contents\n");
296*2e192b24SSimon Glass 		return 0;
297*2e192b24SSimon Glass 	}
298*2e192b24SSimon Glass 
299*2e192b24SSimon Glass 	/*
300*2e192b24SSimon Glass 	 * Writes space, and locks it.  Then attempts to write again.
301*2e192b24SSimon Glass 	 * I really wish I could use the imperative.
302*2e192b24SSimon Glass 	 */
303*2e192b24SSimon Glass 	index_0 += 1;
304*2e192b24SSimon Glass 	if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) !=
305*2e192b24SSimon Glass 		TPM_SUCCESS)) {
306*2e192b24SSimon Glass 		error("\tcould not write index 0\n");
307*2e192b24SSimon Glass 	}
308*2e192b24SSimon Glass 	tpm_nv_write_value_lock(INDEX0);
309*2e192b24SSimon Glass 	if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) ==
310*2e192b24SSimon Glass 			TPM_SUCCESS)
311*2e192b24SSimon Glass 		error("\tindex 0 is not locked\n");
312*2e192b24SSimon Glass 
313*2e192b24SSimon Glass 	printf("\tdone\n");
314*2e192b24SSimon Glass 	return 0;
315*2e192b24SSimon Glass }
316*2e192b24SSimon Glass 
317*2e192b24SSimon Glass static int test_redefine_unowned(void)
318*2e192b24SSimon Glass {
319*2e192b24SSimon Glass 	uint32_t perm;
320*2e192b24SSimon Glass 	uint32_t result;
321*2e192b24SSimon Glass 	uint32_t x;
322*2e192b24SSimon Glass 
323*2e192b24SSimon Glass 	printf("Testing redefine_unowned ...");
324*2e192b24SSimon Glass 	tpm_init();
325*2e192b24SSimon Glass 	TPM_CHECK(TlclStartupIfNeeded());
326*2e192b24SSimon Glass 	TPM_CHECK(tpm_self_test_full());
327*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
328*2e192b24SSimon Glass 	assert(!tpm_is_owned());
329*2e192b24SSimon Glass 
330*2e192b24SSimon Glass 	/* Ensures spaces exist. */
331*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
332*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
333*2e192b24SSimon Glass 
334*2e192b24SSimon Glass 	/* Redefines spaces a couple of times. */
335*2e192b24SSimon Glass 	perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
336*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t)));
337*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)));
338*2e192b24SSimon Glass 	perm = TPM_NV_PER_PPWRITE;
339*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
340*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
341*2e192b24SSimon Glass 
342*2e192b24SSimon Glass 	/* Sets the global lock */
343*2e192b24SSimon Glass 	tpm_set_global_lock();
344*2e192b24SSimon Glass 
345*2e192b24SSimon Glass 	/* Verifies that index0 cannot be redefined */
346*2e192b24SSimon Glass 	result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
347*2e192b24SSimon Glass 	assert(result == TPM_AREA_LOCKED);
348*2e192b24SSimon Glass 
349*2e192b24SSimon Glass 	/* Checks that index1 can */
350*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
351*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
352*2e192b24SSimon Glass 
353*2e192b24SSimon Glass 	/* Turns off PP */
354*2e192b24SSimon Glass 	tpm_tsc_physical_presence(PHYS_PRESENCE);
355*2e192b24SSimon Glass 
356*2e192b24SSimon Glass 	/* Verifies that neither index0 nor index1 can be redefined */
357*2e192b24SSimon Glass 	result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
358*2e192b24SSimon Glass 	assert(result == TPM_BAD_PRESENCE);
359*2e192b24SSimon Glass 	result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t));
360*2e192b24SSimon Glass 	assert(result == TPM_BAD_PRESENCE);
361*2e192b24SSimon Glass 
362*2e192b24SSimon Glass 	printf("done\n");
363*2e192b24SSimon Glass 	return 0;
364*2e192b24SSimon Glass }
365*2e192b24SSimon Glass 
366*2e192b24SSimon Glass #define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
367*2e192b24SSimon Glass #define PERMPP TPM_NV_PER_PPWRITE
368*2e192b24SSimon Glass 
369*2e192b24SSimon Glass static int test_space_perm(void)
370*2e192b24SSimon Glass {
371*2e192b24SSimon Glass 	uint32_t perm;
372*2e192b24SSimon Glass 
373*2e192b24SSimon Glass 	printf("Testing spaceperm ...");
374*2e192b24SSimon Glass 	tpm_init();
375*2e192b24SSimon Glass 	TPM_CHECK(TlclStartupIfNeeded());
376*2e192b24SSimon Glass 	TPM_CHECK(tpm_continue_self_test());
377*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
378*2e192b24SSimon Glass 	TPM_CHECK(tpm_get_permissions(INDEX0, &perm));
379*2e192b24SSimon Glass 	assert((perm & PERMPPGL) == PERMPPGL);
380*2e192b24SSimon Glass 	TPM_CHECK(tpm_get_permissions(INDEX1, &perm));
381*2e192b24SSimon Glass 	assert((perm & PERMPP) == PERMPP);
382*2e192b24SSimon Glass 	printf("done\n");
383*2e192b24SSimon Glass 	return 0;
384*2e192b24SSimon Glass }
385*2e192b24SSimon Glass 
386*2e192b24SSimon Glass static int test_startup(void)
387*2e192b24SSimon Glass {
388*2e192b24SSimon Glass 	uint32_t result;
389*2e192b24SSimon Glass 	printf("Testing startup ...\n");
390*2e192b24SSimon Glass 
391*2e192b24SSimon Glass 	tpm_init();
392*2e192b24SSimon Glass 	result = tpm_startup(TPM_ST_CLEAR);
393*2e192b24SSimon Glass 	if (result != 0 && result != TPM_INVALID_POSTINIT)
394*2e192b24SSimon Glass 		printf("\ttpm startup failed with 0x%x\n", result);
395*2e192b24SSimon Glass 	result = tpm_get_flags(NULL, NULL, NULL);
396*2e192b24SSimon Glass 	if (result != 0)
397*2e192b24SSimon Glass 		printf("\ttpm getflags failed with 0x%x\n", result);
398*2e192b24SSimon Glass 	printf("\texecuting SelfTestFull\n");
399*2e192b24SSimon Glass 	tpm_self_test_full();
400*2e192b24SSimon Glass 	result = tpm_get_flags(NULL, NULL, NULL);
401*2e192b24SSimon Glass 	if (result != 0)
402*2e192b24SSimon Glass 		printf("\ttpm getflags failed with 0x%x\n", result);
403*2e192b24SSimon Glass 	printf("\tdone\n");
404*2e192b24SSimon Glass 	return 0;
405*2e192b24SSimon Glass }
406*2e192b24SSimon Glass 
407*2e192b24SSimon Glass /*
408*2e192b24SSimon Glass  * Runs [op] and ensures it returns success and doesn't run longer than
409*2e192b24SSimon Glass  * [time_limit] in milliseconds.
410*2e192b24SSimon Glass  */
411*2e192b24SSimon Glass #define TTPM_CHECK(op, time_limit) do { \
412*2e192b24SSimon Glass 	ulong start, time; \
413*2e192b24SSimon Glass 	uint32_t __result; \
414*2e192b24SSimon Glass 	\
415*2e192b24SSimon Glass 	start = get_timer(0); \
416*2e192b24SSimon Glass 	__result = op; \
417*2e192b24SSimon Glass 	if (__result != TPM_SUCCESS) { \
418*2e192b24SSimon Glass 		printf("\t" #op ": error 0x%x\n", __result); \
419*2e192b24SSimon Glass 		return -1; \
420*2e192b24SSimon Glass 	} \
421*2e192b24SSimon Glass 	time = get_timer(start); \
422*2e192b24SSimon Glass 	printf("\t" #op ": %lu ms\n", time); \
423*2e192b24SSimon Glass 	if (time > (ulong)time_limit) { \
424*2e192b24SSimon Glass 		printf("\t" #op " exceeded " #time_limit " ms\n"); \
425*2e192b24SSimon Glass 	} \
426*2e192b24SSimon Glass } while (0)
427*2e192b24SSimon Glass 
428*2e192b24SSimon Glass 
429*2e192b24SSimon Glass static int test_timing(void)
430*2e192b24SSimon Glass {
431*2e192b24SSimon Glass 	uint32_t x;
432*2e192b24SSimon Glass 	uint8_t in[20], out[20];
433*2e192b24SSimon Glass 
434*2e192b24SSimon Glass 	printf("Testing timing ...");
435*2e192b24SSimon Glass 	tpm_init();
436*2e192b24SSimon Glass 	TTPM_CHECK(TlclStartupIfNeeded(), 50);
437*2e192b24SSimon Glass 	TTPM_CHECK(tpm_continue_self_test(), 100);
438*2e192b24SSimon Glass 	TTPM_CHECK(tpm_self_test_full(), 1000);
439*2e192b24SSimon Glass 	TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100);
440*2e192b24SSimon Glass 	TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
441*2e192b24SSimon Glass 	TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
442*2e192b24SSimon Glass 	TTPM_CHECK(tpm_extend(0, in, out), 200);
443*2e192b24SSimon Glass 	TTPM_CHECK(tpm_set_global_lock(), 50);
444*2e192b24SSimon Glass 	TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100);
445*2e192b24SSimon Glass 	printf("done\n");
446*2e192b24SSimon Glass 	return 0;
447*2e192b24SSimon Glass }
448*2e192b24SSimon Glass 
449*2e192b24SSimon Glass #define TPM_MAX_NV_WRITES_NOOWNER 64
450*2e192b24SSimon Glass 
451*2e192b24SSimon Glass static int test_write_limit(void)
452*2e192b24SSimon Glass {
453*2e192b24SSimon Glass 	printf("Testing writelimit ...\n");
454*2e192b24SSimon Glass 	int i;
455*2e192b24SSimon Glass 	uint32_t result;
456*2e192b24SSimon Glass 
457*2e192b24SSimon Glass 	tpm_init();
458*2e192b24SSimon Glass 	TPM_CHECK(TlclStartupIfNeeded());
459*2e192b24SSimon Glass 	TPM_CHECK(tpm_self_test_full());
460*2e192b24SSimon Glass 	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
461*2e192b24SSimon Glass 	TPM_CHECK(tpm_force_clear());
462*2e192b24SSimon Glass 	TPM_CHECK(tpm_physical_enable());
463*2e192b24SSimon Glass 	TPM_CHECK(tpm_physical_set_deactivated(0));
464*2e192b24SSimon Glass 
465*2e192b24SSimon Glass 	for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
466*2e192b24SSimon Glass 		printf("\twriting %d\n", i);
467*2e192b24SSimon Glass 		result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i));
468*2e192b24SSimon Glass 		switch (result) {
469*2e192b24SSimon Glass 		case TPM_SUCCESS:
470*2e192b24SSimon Glass 			break;
471*2e192b24SSimon Glass 		case TPM_MAXNVWRITES:
472*2e192b24SSimon Glass 			assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
473*2e192b24SSimon Glass 		default:
474*2e192b24SSimon Glass 			error("\tunexpected error code %d (0x%x)\n",
475*2e192b24SSimon Glass 			      result, result);
476*2e192b24SSimon Glass 		}
477*2e192b24SSimon Glass 	}
478*2e192b24SSimon Glass 
479*2e192b24SSimon Glass 	/* Reset write count */
480*2e192b24SSimon Glass 	TPM_CHECK(tpm_force_clear());
481*2e192b24SSimon Glass 	TPM_CHECK(tpm_physical_enable());
482*2e192b24SSimon Glass 	TPM_CHECK(tpm_physical_set_deactivated(0));
483*2e192b24SSimon Glass 
484*2e192b24SSimon Glass 	/* Try writing again. */
485*2e192b24SSimon Glass 	TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)));
486*2e192b24SSimon Glass 	printf("\tdone\n");
487*2e192b24SSimon Glass 	return 0;
488*2e192b24SSimon Glass }
489*2e192b24SSimon Glass 
490*2e192b24SSimon Glass #define VOIDTEST(XFUNC) \
491*2e192b24SSimon Glass 	int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \
492*2e192b24SSimon Glass 	char * const argv[]) \
493*2e192b24SSimon Glass 	{ \
494*2e192b24SSimon Glass 		return test_##XFUNC(); \
495*2e192b24SSimon Glass 	}
496*2e192b24SSimon Glass 
497*2e192b24SSimon Glass #define VOIDENT(XNAME) \
498*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
499*2e192b24SSimon Glass 
500*2e192b24SSimon Glass VOIDTEST(early_extend)
501*2e192b24SSimon Glass VOIDTEST(early_nvram)
502*2e192b24SSimon Glass VOIDTEST(early_nvram2)
503*2e192b24SSimon Glass VOIDTEST(enable)
504*2e192b24SSimon Glass VOIDTEST(fast_enable)
505*2e192b24SSimon Glass VOIDTEST(global_lock)
506*2e192b24SSimon Glass VOIDTEST(lock)
507*2e192b24SSimon Glass VOIDTEST(readonly)
508*2e192b24SSimon Glass VOIDTEST(redefine_unowned)
509*2e192b24SSimon Glass VOIDTEST(space_perm)
510*2e192b24SSimon Glass VOIDTEST(startup)
511*2e192b24SSimon Glass VOIDTEST(timing)
512*2e192b24SSimon Glass VOIDTEST(write_limit)
513*2e192b24SSimon Glass VOIDTEST(timer)
514*2e192b24SSimon Glass 
515*2e192b24SSimon Glass static cmd_tbl_t cmd_cros_tpm_sub[] = {
516*2e192b24SSimon Glass 	VOIDENT(early_extend)
517*2e192b24SSimon Glass 	VOIDENT(early_nvram)
518*2e192b24SSimon Glass 	VOIDENT(early_nvram2)
519*2e192b24SSimon Glass 	VOIDENT(enable)
520*2e192b24SSimon Glass 	VOIDENT(fast_enable)
521*2e192b24SSimon Glass 	VOIDENT(global_lock)
522*2e192b24SSimon Glass 	VOIDENT(lock)
523*2e192b24SSimon Glass 	VOIDENT(readonly)
524*2e192b24SSimon Glass 	VOIDENT(redefine_unowned)
525*2e192b24SSimon Glass 	VOIDENT(space_perm)
526*2e192b24SSimon Glass 	VOIDENT(startup)
527*2e192b24SSimon Glass 	VOIDENT(timing)
528*2e192b24SSimon Glass 	VOIDENT(write_limit)
529*2e192b24SSimon Glass 	VOIDENT(timer)
530*2e192b24SSimon Glass };
531*2e192b24SSimon Glass 
532*2e192b24SSimon Glass static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
533*2e192b24SSimon Glass {
534*2e192b24SSimon Glass 	cmd_tbl_t *c;
535*2e192b24SSimon Glass 
536*2e192b24SSimon Glass 	printf("argc = %d, argv = ", argc);
537*2e192b24SSimon Glass 	do {
538*2e192b24SSimon Glass 		int i = 0;
539*2e192b24SSimon Glass 
540*2e192b24SSimon Glass 		for (i = 0; i < argc; i++)
541*2e192b24SSimon Glass 			printf(" %s", argv[i]);
542*2e192b24SSimon Glass 			printf("\n------\n");
543*2e192b24SSimon Glass 		} while (0);
544*2e192b24SSimon Glass 	argc--;
545*2e192b24SSimon Glass 	argv++;
546*2e192b24SSimon Glass 	c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
547*2e192b24SSimon Glass 			 ARRAY_SIZE(cmd_cros_tpm_sub));
548*2e192b24SSimon Glass 	return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
549*2e192b24SSimon Glass }
550*2e192b24SSimon Glass 
551*2e192b24SSimon Glass U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
552*2e192b24SSimon Glass 	"\n\tearly_extend\n"
553*2e192b24SSimon Glass 	"\tearly_nvram\n"
554*2e192b24SSimon Glass 	"\tearly_nvram2\n"
555*2e192b24SSimon Glass 	"\tenable\n"
556*2e192b24SSimon Glass 	"\tfast_enable\n"
557*2e192b24SSimon Glass 	"\tglobal_lock\n"
558*2e192b24SSimon Glass 	"\tlock\n"
559*2e192b24SSimon Glass 	"\treadonly\n"
560*2e192b24SSimon Glass 	"\tredefine_unowned\n"
561*2e192b24SSimon Glass 	"\tspace_perm\n"
562*2e192b24SSimon Glass 	"\tstartup\n"
563*2e192b24SSimon Glass 	"\ttiming\n"
564*2e192b24SSimon Glass 	"\twrite_limit\n");
565