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