Blame view

cmd/tpm_test.c 15.1 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
e76cb9272   Simon Glass   dm: tpm: Add a 't...
2
3
  /*
   * Copyright (c) 2015 Google, Inc
e76cb9272   Simon Glass   dm: tpm: Add a 't...
4
5
6
7
8
   */
  
  #include <common.h>
  #include <command.h>
  #include <environment.h>
d677bfe2f   Miquel Raynal   tpm: disociate TP...
9
  #include <tpm-v1.h>
abdc7b8a2   Simon Glass   tpm: Convert to u...
10
  #include "tpm-user-utils.h"
e76cb9272   Simon Glass   dm: tpm: Add a 't...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
  /* Prints error and returns on failure */
  #define TPM_CHECK(tpm_command) do { \
  	uint32_t result; \
  	\
  	result = (tpm_command); \
  	if (result != TPM_SUCCESS) { \
  		printf("TEST FAILED: line %d: " #tpm_command ": 0x%x
  ", \
  			__LINE__, result); \
  		return result; \
  	} \
  } while (0)
  
  #define INDEX0			0xda70
  #define INDEX1			0xda71
  #define INDEX2			0xda72
  #define INDEX3			0xda73
  #define INDEX_INITIALISED	0xda80
  #define PHYS_PRESENCE		4
  #define PRESENCE		8
abdc7b8a2   Simon Glass   tpm: Convert to u...
32
  static uint32_t TlclStartupIfNeeded(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
33
  {
abdc7b8a2   Simon Glass   tpm: Convert to u...
34
  	uint32_t result = tpm_startup(dev, TPM_ST_CLEAR);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
35
36
37
  
  	return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
38
  static int test_timer(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
39
40
41
42
43
  {
  	printf("get_timer(0) = %lu
  ", get_timer(0));
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
44
45
  static uint32_t tpm_get_flags(struct udevice *dev, uint8_t *disable,
  			      uint8_t *deactivated, uint8_t *nvlocked)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
46
47
48
  {
  	struct tpm_permanent_flags pflags;
  	uint32_t result;
abdc7b8a2   Simon Glass   tpm: Convert to u...
49
  	result = tpm_get_permanent_flags(dev, &pflags);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  	if (result)
  		return result;
  	if (disable)
  		*disable = pflags.disable;
  	if (deactivated)
  		*deactivated = pflags.deactivated;
  	if (nvlocked)
  		*nvlocked = pflags.nv_locked;
  	debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d
  ",
  	      pflags.disable, pflags.deactivated, pflags.nv_locked);
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
64
  static uint32_t tpm_nv_write_value_lock(struct udevice *dev, uint32_t index)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
65
66
67
  {
  	debug("TPM: Write lock 0x%x
  ", index);
abdc7b8a2   Simon Glass   tpm: Convert to u...
68
  	return tpm_nv_write_value(dev, index, NULL, 0);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
69
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
70
  static int tpm_is_owned(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
71
72
73
  {
  	uint8_t response[TPM_PUBEK_SIZE];
  	uint32_t result;
abdc7b8a2   Simon Glass   tpm: Convert to u...
74
  	result = tpm_read_pubek(dev, response, sizeof(response));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
75
76
77
  
  	return result != TPM_SUCCESS;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
78
  static int test_early_extend(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
79
80
81
82
83
  {
  	uint8_t value_in[20];
  	uint8_t value_out[20];
  
  	printf("Testing earlyextend ...");
abdc7b8a2   Simon Glass   tpm: Convert to u...
84
85
86
87
  	tpm_init(dev);
  	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
  	TPM_CHECK(tpm_continue_self_test(dev));
  	TPM_CHECK(tpm_extend(dev, 1, value_in, value_out));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
88
89
90
91
  	printf("done
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
92
  static int test_early_nvram(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
93
94
95
96
  {
  	uint32_t x;
  
  	printf("Testing earlynvram ...");
abdc7b8a2   Simon Glass   tpm: Convert to u...
97
98
99
100
101
  	tpm_init(dev);
  	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
  	TPM_CHECK(tpm_continue_self_test(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
102
103
104
105
  	printf("done
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
106
  static int test_early_nvram2(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
107
108
109
110
  {
  	uint32_t x;
  
  	printf("Testing earlynvram2 ...");
abdc7b8a2   Simon Glass   tpm: Convert to u...
111
112
113
114
115
  	tpm_init(dev);
  	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
  	TPM_CHECK(tpm_continue_self_test(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
116
117
118
119
  	printf("done
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
120
  static int test_enable(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
121
122
123
124
125
  {
  	uint8_t disable = 0, deactivated = 0;
  
  	printf("Testing enable ...
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
126
127
128
129
130
  	tpm_init(dev);
  	TPM_CHECK(TlclStartupIfNeeded(dev));
  	TPM_CHECK(tpm_self_test_full(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
131
132
  	printf("\tdisable is %d, deactivated is %d
  ", disable, deactivated);
abdc7b8a2   Simon Glass   tpm: Convert to u...
133
134
135
  	TPM_CHECK(tpm_physical_enable(dev));
  	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
  	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  	printf("\tdisable is %d, deactivated is %d
  ", disable, deactivated);
  	if (disable == 1 || deactivated == 1)
  		printf("\tfailed to enable or activate
  ");
  	printf("\tdone
  ");
  	return 0;
  }
  
  #define reboot() do { \
  	printf("\trebooting...
  "); \
  	reset_cpu(0); \
  } while (0)
abdc7b8a2   Simon Glass   tpm: Convert to u...
151
  static int test_fast_enable(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
152
153
154
155
156
157
  {
  	uint8_t disable = 0, deactivated = 0;
  	int i;
  
  	printf("Testing fastenable ...
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
158
159
160
161
162
  	tpm_init(dev);
  	TPM_CHECK(TlclStartupIfNeeded(dev));
  	TPM_CHECK(tpm_self_test_full(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
163
164
165
  	printf("\tdisable is %d, deactivated is %d
  ", disable, deactivated);
  	for (i = 0; i < 2; i++) {
abdc7b8a2   Simon Glass   tpm: Convert to u...
166
167
  		TPM_CHECK(tpm_force_clear(dev));
  		TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
168
169
170
171
  		printf("\tdisable is %d, deactivated is %d
  ", disable,
  		       deactivated);
  		assert(disable == 1 && deactivated == 1);
abdc7b8a2   Simon Glass   tpm: Convert to u...
172
173
174
  		TPM_CHECK(tpm_physical_enable(dev));
  		TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
  		TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
175
176
177
178
179
180
181
182
183
  		printf("\tdisable is %d, deactivated is %d
  ", disable,
  		       deactivated);
  		assert(disable == 0 && deactivated == 0);
  	}
  	printf("\tdone
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
184
  static int test_global_lock(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
185
186
187
188
189
190
191
  {
  	uint32_t zero = 0;
  	uint32_t result;
  	uint32_t x;
  
  	printf("Testing globallock ...
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
192
193
194
195
196
197
  	tpm_init(dev);
  	TPM_CHECK(TlclStartupIfNeeded(dev));
  	TPM_CHECK(tpm_self_test_full(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
  	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero,
e76cb9272   Simon Glass   dm: tpm: Add a 't...
198
  				     sizeof(uint32_t)));
abdc7b8a2   Simon Glass   tpm: Convert to u...
199
200
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
  	TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero,
e76cb9272   Simon Glass   dm: tpm: Add a 't...
201
  				     sizeof(uint32_t)));
abdc7b8a2   Simon Glass   tpm: Convert to u...
202
  	TPM_CHECK(tpm_set_global_lock(dev));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
203
204
  	/* Verifies that write to index0 fails */
  	x = 1;
abdc7b8a2   Simon Glass   tpm: Convert to u...
205
  	result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
206
  	assert(result == TPM_AREA_LOCKED);
abdc7b8a2   Simon Glass   tpm: Convert to u...
207
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
208
209
210
  	assert(x == 0);
  	/* Verifies that write to index1 is still possible */
  	x = 2;
abdc7b8a2   Simon Glass   tpm: Convert to u...
211
212
  	TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
213
214
  	assert(x == 2);
  	/* Turns off PP */
abdc7b8a2   Simon Glass   tpm: Convert to u...
215
  	tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
216
217
  	/* Verifies that write to index1 fails */
  	x = 3;
abdc7b8a2   Simon Glass   tpm: Convert to u...
218
  	result = tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
219
  	assert(result == TPM_BAD_PRESENCE);
abdc7b8a2   Simon Glass   tpm: Convert to u...
220
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
221
222
223
224
225
  	assert(x == 2);
  	printf("\tdone
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
226
  static int test_lock(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
227
228
229
  {
  	printf("Testing lock ...
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
230
231
232
233
234
  	tpm_init(dev);
  	tpm_startup(dev, TPM_ST_CLEAR);
  	tpm_self_test_full(dev);
  	tpm_tsc_physical_presence(dev, PRESENCE);
  	tpm_nv_write_value_lock(dev, INDEX0);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
235
236
237
238
239
240
  	printf("\tLocked 0x%x
  ", INDEX0);
  	printf("\tdone
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
241
  static void initialise_spaces(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
242
243
244
245
246
247
  {
  	uint32_t zero = 0;
  	uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
  
  	printf("\tInitialising spaces
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
248
249
250
251
252
253
254
255
256
  	tpm_nv_set_locked(dev);  /* useful only the first time */
  	tpm_nv_define_space(dev, INDEX0, perm, 4);
  	tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4);
  	tpm_nv_define_space(dev, INDEX1, perm, 4);
  	tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4);
  	tpm_nv_define_space(dev, INDEX2, perm, 4);
  	tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4);
  	tpm_nv_define_space(dev, INDEX3, perm, 4);
  	tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
257
258
  	perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
  		TPM_NV_PER_PPWRITE;
abdc7b8a2   Simon Glass   tpm: Convert to u...
259
  	tpm_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
260
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
261
  static int test_readonly(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
262
263
264
265
266
267
268
  {
  	uint8_t c;
  	uint32_t index_0, index_1, index_2, index_3;
  	int read0, read1, read2, read3;
  
  	printf("Testing readonly ...
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
269
270
271
272
  	tpm_init(dev);
  	tpm_startup(dev, TPM_ST_CLEAR);
  	tpm_self_test_full(dev);
  	tpm_tsc_physical_presence(dev, PRESENCE);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
273
274
275
276
  	/*
  	 * Checks if initialisation has completed by trying to read-lock a
  	 * space that's created at the end of initialisation
  	 */
abdc7b8a2   Simon Glass   tpm: Convert to u...
277
  	if (tpm_nv_read_value(dev, INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
e76cb9272   Simon Glass   dm: tpm: Add a 't...
278
  		/* The initialisation did not complete */
abdc7b8a2   Simon Glass   tpm: Convert to u...
279
  		initialise_spaces(dev);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
280
281
282
  	}
  
  	/* Checks if spaces are OK or messed up */
abdc7b8a2   Simon Glass   tpm: Convert to u...
283
284
285
286
287
288
289
290
  	read0 = tpm_nv_read_value(dev, INDEX0, (uint8_t *)&index_0,
  				  sizeof(index_0));
  	read1 = tpm_nv_read_value(dev, INDEX1, (uint8_t *)&index_1,
  				  sizeof(index_1));
  	read2 = tpm_nv_read_value(dev, INDEX2, (uint8_t *)&index_2,
  				  sizeof(index_2));
  	read3 = tpm_nv_read_value(dev, INDEX3, (uint8_t *)&index_3,
  				  sizeof(index_3));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
291
292
293
294
295
296
297
298
299
300
301
  	if (read0 || read1 || read2 || read3) {
  		printf("Invalid contents
  ");
  		return 0;
  	}
  
  	/*
  	 * Writes space, and locks it.  Then attempts to write again.
  	 * I really wish I could use the imperative.
  	 */
  	index_0 += 1;
abdc7b8a2   Simon Glass   tpm: Convert to u...
302
303
  	if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
  			       sizeof(index_0) !=
e76cb9272   Simon Glass   dm: tpm: Add a 't...
304
  		TPM_SUCCESS)) {
9b643e312   Masahiro Yamada   treewide: replace...
305
306
  		pr_err("\tcould not write index 0
  ");
e76cb9272   Simon Glass   dm: tpm: Add a 't...
307
  	}
abdc7b8a2   Simon Glass   tpm: Convert to u...
308
309
310
  	tpm_nv_write_value_lock(dev, INDEX0);
  	if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
  			       sizeof(index_0)) ==
e76cb9272   Simon Glass   dm: tpm: Add a 't...
311
  			TPM_SUCCESS)
9b643e312   Masahiro Yamada   treewide: replace...
312
313
  		pr_err("\tindex 0 is not locked
  ");
e76cb9272   Simon Glass   dm: tpm: Add a 't...
314
315
316
317
318
  
  	printf("\tdone
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
319
  static int test_redefine_unowned(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
320
321
322
323
324
325
  {
  	uint32_t perm;
  	uint32_t result;
  	uint32_t x;
  
  	printf("Testing redefine_unowned ...");
abdc7b8a2   Simon Glass   tpm: Convert to u...
326
327
328
329
330
  	tpm_init(dev);
  	TPM_CHECK(TlclStartupIfNeeded(dev));
  	TPM_CHECK(tpm_self_test_full(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	assert(!tpm_is_owned(dev));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
331
332
  
  	/* Ensures spaces exist. */
abdc7b8a2   Simon Glass   tpm: Convert to u...
333
334
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
  	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
335
336
337
  
  	/* Redefines spaces a couple of times. */
  	perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
abdc7b8a2   Simon Glass   tpm: Convert to u...
338
339
  	TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, 2 * sizeof(uint32_t)));
  	TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
340
  	perm = TPM_NV_PER_PPWRITE;
abdc7b8a2   Simon Glass   tpm: Convert to u...
341
342
  	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
  	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
343
344
  
  	/* Sets the global lock */
abdc7b8a2   Simon Glass   tpm: Convert to u...
345
  	tpm_set_global_lock(dev);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
346
347
  
  	/* Verifies that index0 cannot be redefined */
abdc7b8a2   Simon Glass   tpm: Convert to u...
348
  	result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
349
350
351
  	assert(result == TPM_AREA_LOCKED);
  
  	/* Checks that index1 can */
abdc7b8a2   Simon Glass   tpm: Convert to u...
352
353
  	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
  	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
354
355
  
  	/* Turns off PP */
abdc7b8a2   Simon Glass   tpm: Convert to u...
356
  	tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
357
358
  
  	/* Verifies that neither index0 nor index1 can be redefined */
abdc7b8a2   Simon Glass   tpm: Convert to u...
359
  	result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
360
  	assert(result == TPM_BAD_PRESENCE);
abdc7b8a2   Simon Glass   tpm: Convert to u...
361
  	result = tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
362
363
364
365
366
367
368
369
370
  	assert(result == TPM_BAD_PRESENCE);
  
  	printf("done
  ");
  	return 0;
  }
  
  #define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
  #define PERMPP TPM_NV_PER_PPWRITE
abdc7b8a2   Simon Glass   tpm: Convert to u...
371
  static int test_space_perm(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
372
373
374
375
  {
  	uint32_t perm;
  
  	printf("Testing spaceperm ...");
abdc7b8a2   Simon Glass   tpm: Convert to u...
376
377
378
379
380
  	tpm_init(dev);
  	TPM_CHECK(TlclStartupIfNeeded(dev));
  	TPM_CHECK(tpm_continue_self_test(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	TPM_CHECK(tpm_get_permissions(dev, INDEX0, &perm));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
381
  	assert((perm & PERMPPGL) == PERMPPGL);
abdc7b8a2   Simon Glass   tpm: Convert to u...
382
  	TPM_CHECK(tpm_get_permissions(dev, INDEX1, &perm));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
383
384
385
386
387
  	assert((perm & PERMPP) == PERMPP);
  	printf("done
  ");
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
388
  static int test_startup(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
389
390
  {
  	uint32_t result;
abdc7b8a2   Simon Glass   tpm: Convert to u...
391

e76cb9272   Simon Glass   dm: tpm: Add a 't...
392
393
  	printf("Testing startup ...
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
394
395
  	tpm_init(dev);
  	result = tpm_startup(dev, TPM_ST_CLEAR);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
396
397
398
  	if (result != 0 && result != TPM_INVALID_POSTINIT)
  		printf("\ttpm startup failed with 0x%x
  ", result);
abdc7b8a2   Simon Glass   tpm: Convert to u...
399
  	result = tpm_get_flags(dev, NULL, NULL, NULL);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
400
401
402
403
404
  	if (result != 0)
  		printf("\ttpm getflags failed with 0x%x
  ", result);
  	printf("\texecuting SelfTestFull
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
405
406
  	tpm_self_test_full(dev);
  	result = tpm_get_flags(dev, NULL, NULL, NULL);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  	if (result != 0)
  		printf("\ttpm getflags failed with 0x%x
  ", result);
  	printf("\tdone
  ");
  	return 0;
  }
  
  /*
   * Runs [op] and ensures it returns success and doesn't run longer than
   * [time_limit] in milliseconds.
   */
  #define TTPM_CHECK(op, time_limit) do { \
  	ulong start, time; \
  	uint32_t __result; \
  	\
  	start = get_timer(0); \
  	__result = op; \
  	if (__result != TPM_SUCCESS) { \
  		printf("\t" #op ": error 0x%x
  ", __result); \
  		return -1; \
  	} \
  	time = get_timer(start); \
  	printf("\t" #op ": %lu ms
  ", time); \
  	if (time > (ulong)time_limit) { \
  		printf("\t" #op " exceeded " #time_limit " ms
  "); \
  	} \
  } while (0)
abdc7b8a2   Simon Glass   tpm: Convert to u...
438
  static int test_timing(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
439
  {
e76cb9272   Simon Glass   dm: tpm: Add a 't...
440
  	uint8_t in[20], out[20];
abdc7b8a2   Simon Glass   tpm: Convert to u...
441
  	uint32_t x;
e76cb9272   Simon Glass   dm: tpm: Add a 't...
442
443
  
  	printf("Testing timing ...");
abdc7b8a2   Simon Glass   tpm: Convert to u...
444
445
446
447
448
449
450
451
452
453
454
455
  	tpm_init(dev);
  	TTPM_CHECK(TlclStartupIfNeeded(dev), 50);
  	TTPM_CHECK(tpm_continue_self_test(dev), 100);
  	TTPM_CHECK(tpm_self_test_full(dev), 1000);
  	TTPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE), 100);
  	TTPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
  		   100);
  	TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
  		   100);
  	TTPM_CHECK(tpm_extend(dev, 0, in, out), 200);
  	TTPM_CHECK(tpm_set_global_lock(dev), 50);
  	TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
456
457
458
459
460
461
  	printf("done
  ");
  	return 0;
  }
  
  #define TPM_MAX_NV_WRITES_NOOWNER 64
abdc7b8a2   Simon Glass   tpm: Convert to u...
462
  static int test_write_limit(struct udevice *dev)
e76cb9272   Simon Glass   dm: tpm: Add a 't...
463
  {
e76cb9272   Simon Glass   dm: tpm: Add a 't...
464
  	uint32_t result;
abdc7b8a2   Simon Glass   tpm: Convert to u...
465
  	int i;
e76cb9272   Simon Glass   dm: tpm: Add a 't...
466

abdc7b8a2   Simon Glass   tpm: Convert to u...
467
468
469
470
471
472
473
474
475
  	printf("Testing writelimit ...
  ");
  	tpm_init(dev);
  	TPM_CHECK(TlclStartupIfNeeded(dev));
  	TPM_CHECK(tpm_self_test_full(dev));
  	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
  	TPM_CHECK(tpm_force_clear(dev));
  	TPM_CHECK(tpm_physical_enable(dev));
  	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
476
477
478
479
  
  	for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
  		printf("\twriting %d
  ", i);
abdc7b8a2   Simon Glass   tpm: Convert to u...
480
481
  		result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i,
  					    sizeof(i));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
482
483
484
485
486
487
  		switch (result) {
  		case TPM_SUCCESS:
  			break;
  		case TPM_MAXNVWRITES:
  			assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
  		default:
9b643e312   Masahiro Yamada   treewide: replace...
488
489
  			pr_err("\tunexpected error code %d (0x%x)
  ",
e76cb9272   Simon Glass   dm: tpm: Add a 't...
490
491
492
493
494
  			      result, result);
  		}
  	}
  
  	/* Reset write count */
abdc7b8a2   Simon Glass   tpm: Convert to u...
495
496
497
  	TPM_CHECK(tpm_force_clear(dev));
  	TPM_CHECK(tpm_physical_enable(dev));
  	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
498
499
  
  	/* Try writing again. */
abdc7b8a2   Simon Glass   tpm: Convert to u...
500
  	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i, sizeof(i)));
e76cb9272   Simon Glass   dm: tpm: Add a 't...
501
502
503
504
505
506
507
508
509
  	printf("\tdone
  ");
  	return 0;
  }
  
  #define VOIDTEST(XFUNC) \
  	int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \
  	char * const argv[]) \
  	{ \
abdc7b8a2   Simon Glass   tpm: Convert to u...
510
511
512
513
514
515
516
  		struct udevice *dev; \
  		int ret; \
  \
  		ret = get_tpm(&dev); \
  		if (ret) \
  			return ret; \
  		return test_##XFUNC(dev); \
e76cb9272   Simon Glass   dm: tpm: Add a 't...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
  	}
  
  #define VOIDENT(XNAME) \
  	U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
  
  VOIDTEST(early_extend)
  VOIDTEST(early_nvram)
  VOIDTEST(early_nvram2)
  VOIDTEST(enable)
  VOIDTEST(fast_enable)
  VOIDTEST(global_lock)
  VOIDTEST(lock)
  VOIDTEST(readonly)
  VOIDTEST(redefine_unowned)
  VOIDTEST(space_perm)
  VOIDTEST(startup)
  VOIDTEST(timing)
  VOIDTEST(write_limit)
  VOIDTEST(timer)
  
  static cmd_tbl_t cmd_cros_tpm_sub[] = {
  	VOIDENT(early_extend)
  	VOIDENT(early_nvram)
  	VOIDENT(early_nvram2)
  	VOIDENT(enable)
  	VOIDENT(fast_enable)
  	VOIDENT(global_lock)
  	VOIDENT(lock)
  	VOIDENT(readonly)
  	VOIDENT(redefine_unowned)
  	VOIDENT(space_perm)
  	VOIDENT(startup)
  	VOIDENT(timing)
  	VOIDENT(write_limit)
  	VOIDENT(timer)
  };
  
  static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	cmd_tbl_t *c;
0427b9c52   Stefan Brüns   cmd/tpm_test: Fix...
557
  	int i;
e76cb9272   Simon Glass   dm: tpm: Add a 't...
558
559
  
  	printf("argc = %d, argv = ", argc);
e76cb9272   Simon Glass   dm: tpm: Add a 't...
560

0427b9c52   Stefan Brüns   cmd/tpm_test: Fix...
561
562
563
564
565
566
  	for (i = 0; i < argc; i++)
  		printf(" %s", argv[i]);
  
  	printf("
  ------
  ");
e76cb9272   Simon Glass   dm: tpm: Add a 't...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
  	argc--;
  	argv++;
  	c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
  			 ARRAY_SIZE(cmd_cros_tpm_sub));
  	return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
  }
  
  U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
  	"
  \tearly_extend
  "
  	"\tearly_nvram
  "
  	"\tearly_nvram2
  "
  	"\tenable
  "
  	"\tfast_enable
  "
  	"\tglobal_lock
  "
  	"\tlock
  "
  	"\treadonly
  "
  	"\tredefine_unowned
  "
  	"\tspace_perm
  "
  	"\tstartup
  "
  	"\ttiming
  "
  	"\twrite_limit
  ");