xref: /openbmc/linux/drivers/char/tpm/tpm2-cmd.c (revision e0bf6c5c)
1 /*
2  * Copyright (C) 2014 Intel Corporation
3  *
4  * Authors:
5  * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
6  *
7  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
8  *
9  * This file contains TPM2 protocol implementations of the commands
10  * used by the kernel internally.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; version 2
15  * of the License.
16  */
17 
18 #include "tpm.h"
19 
20 struct tpm2_startup_in {
21 	__be16	startup_type;
22 } __packed;
23 
24 struct tpm2_self_test_in {
25 	u8	full_test;
26 } __packed;
27 
28 struct tpm2_pcr_read_in {
29 	__be32	pcr_selects_cnt;
30 	__be16	hash_alg;
31 	u8	pcr_select_size;
32 	u8	pcr_select[TPM2_PCR_SELECT_MIN];
33 } __packed;
34 
35 struct tpm2_pcr_read_out {
36 	__be32	update_cnt;
37 	__be32	pcr_selects_cnt;
38 	__be16	hash_alg;
39 	u8	pcr_select_size;
40 	u8	pcr_select[TPM2_PCR_SELECT_MIN];
41 	__be32	digests_cnt;
42 	__be16	digest_size;
43 	u8	digest[TPM_DIGEST_SIZE];
44 } __packed;
45 
46 struct tpm2_null_auth_area {
47 	__be32			handle;
48 	__be16			nonce_size;
49 	u8			attributes;
50 	__be16			auth_size;
51 } __packed;
52 
53 struct tpm2_pcr_extend_in {
54 	__be32				pcr_idx;
55 	__be32				auth_area_size;
56 	struct tpm2_null_auth_area	auth_area;
57 	__be32				digest_cnt;
58 	__be16				hash_alg;
59 	u8				digest[TPM_DIGEST_SIZE];
60 } __packed;
61 
62 struct tpm2_get_tpm_pt_in {
63 	__be32	cap_id;
64 	__be32	property_id;
65 	__be32	property_cnt;
66 } __packed;
67 
68 struct tpm2_get_tpm_pt_out {
69 	u8	more_data;
70 	__be32	subcap_id;
71 	__be32	property_cnt;
72 	__be32	property_id;
73 	__be32	value;
74 } __packed;
75 
76 struct tpm2_get_random_in {
77 	__be16	size;
78 } __packed;
79 
80 struct tpm2_get_random_out {
81 	__be16	size;
82 	u8	buffer[TPM_MAX_RNG_DATA];
83 } __packed;
84 
85 union tpm2_cmd_params {
86 	struct	tpm2_startup_in		startup_in;
87 	struct	tpm2_self_test_in	selftest_in;
88 	struct	tpm2_pcr_read_in	pcrread_in;
89 	struct	tpm2_pcr_read_out	pcrread_out;
90 	struct	tpm2_pcr_extend_in	pcrextend_in;
91 	struct	tpm2_get_tpm_pt_in	get_tpm_pt_in;
92 	struct	tpm2_get_tpm_pt_out	get_tpm_pt_out;
93 	struct	tpm2_get_random_in	getrandom_in;
94 	struct	tpm2_get_random_out	getrandom_out;
95 };
96 
97 struct tpm2_cmd {
98 	tpm_cmd_header		header;
99 	union tpm2_cmd_params	params;
100 } __packed;
101 
102 /*
103  * Array with one entry per ordinal defining the maximum amount
104  * of time the chip could take to return the result. The values
105  * of the SHORT, MEDIUM, and LONG durations are taken from the
106  * PC Client Profile (PTP) specification.
107  */
108 static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
109 	TPM_UNDEFINED,		/* 11F */
110 	TPM_UNDEFINED,		/* 120 */
111 	TPM_LONG,		/* 121 */
112 	TPM_UNDEFINED,		/* 122 */
113 	TPM_UNDEFINED,		/* 123 */
114 	TPM_UNDEFINED,		/* 124 */
115 	TPM_UNDEFINED,		/* 125 */
116 	TPM_UNDEFINED,		/* 126 */
117 	TPM_UNDEFINED,		/* 127 */
118 	TPM_UNDEFINED,		/* 128 */
119 	TPM_LONG,		/* 129 */
120 	TPM_UNDEFINED,		/* 12a */
121 	TPM_UNDEFINED,		/* 12b */
122 	TPM_UNDEFINED,		/* 12c */
123 	TPM_UNDEFINED,		/* 12d */
124 	TPM_UNDEFINED,		/* 12e */
125 	TPM_UNDEFINED,		/* 12f */
126 	TPM_UNDEFINED,		/* 130 */
127 	TPM_UNDEFINED,		/* 131 */
128 	TPM_UNDEFINED,		/* 132 */
129 	TPM_UNDEFINED,		/* 133 */
130 	TPM_UNDEFINED,		/* 134 */
131 	TPM_UNDEFINED,		/* 135 */
132 	TPM_UNDEFINED,		/* 136 */
133 	TPM_UNDEFINED,		/* 137 */
134 	TPM_UNDEFINED,		/* 138 */
135 	TPM_UNDEFINED,		/* 139 */
136 	TPM_UNDEFINED,		/* 13a */
137 	TPM_UNDEFINED,		/* 13b */
138 	TPM_UNDEFINED,		/* 13c */
139 	TPM_UNDEFINED,		/* 13d */
140 	TPM_MEDIUM,		/* 13e */
141 	TPM_UNDEFINED,		/* 13f */
142 	TPM_UNDEFINED,		/* 140 */
143 	TPM_UNDEFINED,		/* 141 */
144 	TPM_UNDEFINED,		/* 142 */
145 	TPM_LONG,		/* 143 */
146 	TPM_MEDIUM,		/* 144 */
147 	TPM_UNDEFINED,		/* 145 */
148 	TPM_UNDEFINED,		/* 146 */
149 	TPM_UNDEFINED,		/* 147 */
150 	TPM_UNDEFINED,		/* 148 */
151 	TPM_UNDEFINED,		/* 149 */
152 	TPM_UNDEFINED,		/* 14a */
153 	TPM_UNDEFINED,		/* 14b */
154 	TPM_UNDEFINED,		/* 14c */
155 	TPM_UNDEFINED,		/* 14d */
156 	TPM_LONG,		/* 14e */
157 	TPM_UNDEFINED,		/* 14f */
158 	TPM_UNDEFINED,		/* 150 */
159 	TPM_UNDEFINED,		/* 151 */
160 	TPM_UNDEFINED,		/* 152 */
161 	TPM_UNDEFINED,		/* 153 */
162 	TPM_UNDEFINED,		/* 154 */
163 	TPM_UNDEFINED,		/* 155 */
164 	TPM_UNDEFINED,		/* 156 */
165 	TPM_UNDEFINED,		/* 157 */
166 	TPM_UNDEFINED,		/* 158 */
167 	TPM_UNDEFINED,		/* 159 */
168 	TPM_UNDEFINED,		/* 15a */
169 	TPM_UNDEFINED,		/* 15b */
170 	TPM_MEDIUM,		/* 15c */
171 	TPM_UNDEFINED,		/* 15d */
172 	TPM_UNDEFINED,		/* 15e */
173 	TPM_UNDEFINED,		/* 15f */
174 	TPM_UNDEFINED,		/* 160 */
175 	TPM_UNDEFINED,		/* 161 */
176 	TPM_UNDEFINED,		/* 162 */
177 	TPM_UNDEFINED,		/* 163 */
178 	TPM_UNDEFINED,		/* 164 */
179 	TPM_UNDEFINED,		/* 165 */
180 	TPM_UNDEFINED,		/* 166 */
181 	TPM_UNDEFINED,		/* 167 */
182 	TPM_UNDEFINED,		/* 168 */
183 	TPM_UNDEFINED,		/* 169 */
184 	TPM_UNDEFINED,		/* 16a */
185 	TPM_UNDEFINED,		/* 16b */
186 	TPM_UNDEFINED,		/* 16c */
187 	TPM_UNDEFINED,		/* 16d */
188 	TPM_UNDEFINED,		/* 16e */
189 	TPM_UNDEFINED,		/* 16f */
190 	TPM_UNDEFINED,		/* 170 */
191 	TPM_UNDEFINED,		/* 171 */
192 	TPM_UNDEFINED,		/* 172 */
193 	TPM_UNDEFINED,		/* 173 */
194 	TPM_UNDEFINED,		/* 174 */
195 	TPM_UNDEFINED,		/* 175 */
196 	TPM_UNDEFINED,		/* 176 */
197 	TPM_LONG,		/* 177 */
198 	TPM_UNDEFINED,		/* 178 */
199 	TPM_UNDEFINED,		/* 179 */
200 	TPM_MEDIUM,		/* 17a */
201 	TPM_LONG,		/* 17b */
202 	TPM_UNDEFINED,		/* 17c */
203 	TPM_UNDEFINED,		/* 17d */
204 	TPM_UNDEFINED,		/* 17e */
205 	TPM_UNDEFINED,		/* 17f */
206 	TPM_UNDEFINED,		/* 180 */
207 	TPM_UNDEFINED,		/* 181 */
208 	TPM_MEDIUM,		/* 182 */
209 	TPM_UNDEFINED,		/* 183 */
210 	TPM_UNDEFINED,		/* 184 */
211 	TPM_MEDIUM,		/* 185 */
212 	TPM_MEDIUM,		/* 186 */
213 	TPM_UNDEFINED,		/* 187 */
214 	TPM_UNDEFINED,		/* 188 */
215 	TPM_UNDEFINED,		/* 189 */
216 	TPM_UNDEFINED,		/* 18a */
217 	TPM_UNDEFINED,		/* 18b */
218 	TPM_UNDEFINED,		/* 18c */
219 	TPM_UNDEFINED,		/* 18d */
220 	TPM_UNDEFINED,		/* 18e */
221 	TPM_UNDEFINED		/* 18f */
222 };
223 
224 #define TPM2_PCR_READ_IN_SIZE \
225 	(sizeof(struct tpm_input_header) + \
226 	 sizeof(struct tpm2_pcr_read_in))
227 
228 static const struct tpm_input_header tpm2_pcrread_header = {
229 	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
230 	.length = cpu_to_be32(TPM2_PCR_READ_IN_SIZE),
231 	.ordinal = cpu_to_be32(TPM2_CC_PCR_READ)
232 };
233 
234 /**
235  * tpm2_pcr_read() - read a PCR value
236  * @chip:	TPM chip to use.
237  * @pcr_idx:	index of the PCR to read.
238  * @ref_buf:	buffer to store the resulting hash,
239  *
240  * 0 is returned when the operation is successful. If a negative number is
241  * returned it remarks a POSIX error code. If a positive number is returned
242  * it remarks a TPM error.
243  */
244 int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
245 {
246 	int rc;
247 	struct tpm2_cmd cmd;
248 	u8 *buf;
249 
250 	if (pcr_idx >= TPM2_PLATFORM_PCR)
251 		return -EINVAL;
252 
253 	cmd.header.in = tpm2_pcrread_header;
254 	cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1);
255 	cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
256 	cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
257 
258 	memset(cmd.params.pcrread_in.pcr_select, 0,
259 	       sizeof(cmd.params.pcrread_in.pcr_select));
260 	cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
261 
262 	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
263 			      "attempting to read a pcr value");
264 	if (rc == 0) {
265 		buf = cmd.params.pcrread_out.digest;
266 		memcpy(res_buf, buf, TPM_DIGEST_SIZE);
267 	}
268 
269 	return rc;
270 }
271 
272 #define TPM2_GET_PCREXTEND_IN_SIZE \
273 	(sizeof(struct tpm_input_header) + \
274 	 sizeof(struct tpm2_pcr_extend_in))
275 
276 static const struct tpm_input_header tpm2_pcrextend_header = {
277 	.tag = cpu_to_be16(TPM2_ST_SESSIONS),
278 	.length = cpu_to_be32(TPM2_GET_PCREXTEND_IN_SIZE),
279 	.ordinal = cpu_to_be32(TPM2_CC_PCR_EXTEND)
280 };
281 
282 /**
283  * tpm2_pcr_extend() - extend a PCR value
284  * @chip:	TPM chip to use.
285  * @pcr_idx:	index of the PCR.
286  * @hash:	hash value to use for the extend operation.
287  *
288  * 0 is returned when the operation is successful. If a negative number is
289  * returned it remarks a POSIX error code. If a positive number is returned
290  * it remarks a TPM error.
291  */
292 int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
293 {
294 	struct tpm2_cmd cmd;
295 	int rc;
296 
297 	cmd.header.in = tpm2_pcrextend_header;
298 	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
299 	cmd.params.pcrextend_in.auth_area_size =
300 		cpu_to_be32(sizeof(struct tpm2_null_auth_area));
301 	cmd.params.pcrextend_in.auth_area.handle =
302 		cpu_to_be32(TPM2_RS_PW);
303 	cmd.params.pcrextend_in.auth_area.nonce_size = 0;
304 	cmd.params.pcrextend_in.auth_area.attributes = 0;
305 	cmd.params.pcrextend_in.auth_area.auth_size = 0;
306 	cmd.params.pcrextend_in.digest_cnt = cpu_to_be32(1);
307 	cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
308 	memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE);
309 
310 	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
311 			      "attempting extend a PCR value");
312 
313 	return rc;
314 }
315 
316 #define TPM2_GETRANDOM_IN_SIZE \
317 	(sizeof(struct tpm_input_header) + \
318 	 sizeof(struct tpm2_get_random_in))
319 
320 static const struct tpm_input_header tpm2_getrandom_header = {
321 	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
322 	.length = cpu_to_be32(TPM2_GETRANDOM_IN_SIZE),
323 	.ordinal = cpu_to_be32(TPM2_CC_GET_RANDOM)
324 };
325 
326 /**
327  * tpm2_get_random() - get random bytes from the TPM RNG
328  * @chip: TPM chip to use
329  * @out: destination buffer for the random bytes
330  * @max: the max number of bytes to write to @out
331  *
332  * 0 is returned when the operation is successful. If a negative number is
333  * returned it remarks a POSIX error code. If a positive number is returned
334  * it remarks a TPM error.
335  */
336 int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
337 {
338 	struct tpm2_cmd cmd;
339 	u32 recd;
340 	u32 num_bytes;
341 	int err;
342 	int total = 0;
343 	int retries = 5;
344 	u8 *dest = out;
345 
346 	num_bytes = min_t(u32, max, sizeof(cmd.params.getrandom_out.buffer));
347 
348 	if (!out || !num_bytes ||
349 	    max > sizeof(cmd.params.getrandom_out.buffer))
350 		return -EINVAL;
351 
352 	do {
353 		cmd.header.in = tpm2_getrandom_header;
354 		cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
355 
356 		err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
357 				       "attempting get random");
358 		if (err)
359 			break;
360 
361 		recd = min_t(u32, be16_to_cpu(cmd.params.getrandom_out.size),
362 			     num_bytes);
363 		memcpy(dest, cmd.params.getrandom_out.buffer, recd);
364 
365 		dest += recd;
366 		total += recd;
367 		num_bytes -= recd;
368 	} while (retries-- && total < max);
369 
370 	return total ? total : -EIO;
371 }
372 
373 #define TPM2_GET_TPM_PT_IN_SIZE \
374 	(sizeof(struct tpm_input_header) + \
375 	 sizeof(struct tpm2_get_tpm_pt_in))
376 
377 static const struct tpm_input_header tpm2_get_tpm_pt_header = {
378 	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
379 	.length = cpu_to_be32(TPM2_GET_TPM_PT_IN_SIZE),
380 	.ordinal = cpu_to_be32(TPM2_CC_GET_CAPABILITY)
381 };
382 
383 /**
384  * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
385  * @chip:		TPM chip to use.
386  * @property_id:	property ID.
387  * @value:		output variable.
388  * @desc:		passed to tpm_transmit_cmd()
389  *
390  * 0 is returned when the operation is successful. If a negative number is
391  * returned it remarks a POSIX error code. If a positive number is returned
392  * it remarks a TPM error.
393  */
394 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
395 			const char *desc)
396 {
397 	struct tpm2_cmd cmd;
398 	int rc;
399 
400 	cmd.header.in = tpm2_get_tpm_pt_header;
401 	cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
402 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
403 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
404 
405 	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc);
406 	if (!rc)
407 		*value = cmd.params.get_tpm_pt_out.value;
408 
409 	return rc;
410 }
411 
412 #define TPM2_STARTUP_IN_SIZE \
413 	(sizeof(struct tpm_input_header) + \
414 	 sizeof(struct tpm2_startup_in))
415 
416 static const struct tpm_input_header tpm2_startup_header = {
417 	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
418 	.length = cpu_to_be32(TPM2_STARTUP_IN_SIZE),
419 	.ordinal = cpu_to_be32(TPM2_CC_STARTUP)
420 };
421 
422 /**
423  * tpm2_startup() - send startup command to the TPM chip
424  * @chip:		TPM chip to use.
425  * @startup_type	startup type. The value is either
426  *			TPM_SU_CLEAR or TPM_SU_STATE.
427  *
428  * 0 is returned when the operation is successful. If a negative number is
429  * returned it remarks a POSIX error code. If a positive number is returned
430  * it remarks a TPM error.
431  */
432 int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
433 {
434 	struct tpm2_cmd cmd;
435 
436 	cmd.header.in = tpm2_startup_header;
437 
438 	cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
439 	return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
440 				"attempting to start the TPM");
441 }
442 EXPORT_SYMBOL_GPL(tpm2_startup);
443 
444 #define TPM2_SHUTDOWN_IN_SIZE \
445 	(sizeof(struct tpm_input_header) + \
446 	 sizeof(struct tpm2_startup_in))
447 
448 static const struct tpm_input_header tpm2_shutdown_header = {
449 	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
450 	.length = cpu_to_be32(TPM2_SHUTDOWN_IN_SIZE),
451 	.ordinal = cpu_to_be32(TPM2_CC_SHUTDOWN)
452 };
453 
454 /**
455  * tpm2_shutdown() - send shutdown command to the TPM chip
456  * @chip:		TPM chip to use.
457  * @shutdown_type	shutdown type. The value is either
458  *			TPM_SU_CLEAR or TPM_SU_STATE.
459  */
460 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
461 {
462 	struct tpm2_cmd cmd;
463 	int rc;
464 
465 	cmd.header.in = tpm2_shutdown_header;
466 	cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
467 
468 	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM");
469 
470 	/* In places where shutdown command is sent there's no much we can do
471 	 * except print the error code on a system failure.
472 	 */
473 	if (rc < 0)
474 		dev_warn(chip->pdev, "transmit returned %d while stopping the TPM",
475 			 rc);
476 }
477 EXPORT_SYMBOL_GPL(tpm2_shutdown);
478 
479 /*
480  * tpm2_calc_ordinal_duration() - maximum duration for a command
481  * @chip:	TPM chip to use.
482  * @ordinal:	command code number.
483  *
484  * 0 is returned when the operation is successful. If a negative number is
485  * returned it remarks a POSIX error code. If a positive number is returned
486  * it remarks a TPM error.
487  */
488 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
489 {
490 	int index = TPM_UNDEFINED;
491 	int duration = 0;
492 
493 	if (ordinal >= TPM2_CC_FIRST && ordinal <= TPM2_CC_LAST)
494 		index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST];
495 
496 	if (index != TPM_UNDEFINED)
497 		duration = chip->vendor.duration[index];
498 
499 	if (duration <= 0)
500 		duration = 2 * 60 * HZ;
501 
502 	return duration;
503 }
504 EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);
505 
506 #define TPM2_SELF_TEST_IN_SIZE \
507 	(sizeof(struct tpm_input_header) + \
508 	 sizeof(struct tpm2_self_test_in))
509 
510 static const struct tpm_input_header tpm2_selftest_header = {
511 	.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
512 	.length = cpu_to_be32(TPM2_SELF_TEST_IN_SIZE),
513 	.ordinal = cpu_to_be32(TPM2_CC_SELF_TEST)
514 };
515 
516 /**
517  * tpm2_continue_selftest() - start a self test
518  * @chip: TPM chip to use
519  * @full: test all commands instead of testing only those that were not
520  *        previously tested.
521  *
522  * 0 is returned when the operation is successful. If a negative number is
523  * returned it remarks a POSIX error code. If a positive number is returned
524  * it remarks a TPM error.
525  */
526 static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
527 {
528 	int rc;
529 	struct tpm2_cmd cmd;
530 
531 	cmd.header.in = tpm2_selftest_header;
532 	cmd.params.selftest_in.full_test = full;
533 
534 	rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE,
535 			      "continue selftest");
536 
537 	/* At least some prototype chips seem to give RC_TESTING error
538 	 * immediately. This is a workaround for that.
539 	 */
540 	if (rc == TPM2_RC_TESTING) {
541 		dev_warn(chip->pdev, "Got RC_TESTING, ignoring\n");
542 		rc = 0;
543 	}
544 
545 	return rc;
546 }
547 
548 /**
549  * tpm2_do_selftest() - run a full self test
550  * @chip: TPM chip to use
551  *
552  * During the self test TPM2 commands return with the error code RC_TESTING.
553  * Waiting is done by issuing PCR read until it executes successfully.
554  *
555  * 0 is returned when the operation is successful. If a negative number is
556  * returned it remarks a POSIX error code. If a positive number is returned
557  * it remarks a TPM error.
558  */
559 int tpm2_do_selftest(struct tpm_chip *chip)
560 {
561 	int rc;
562 	unsigned int loops;
563 	unsigned int delay_msec = 100;
564 	unsigned long duration;
565 	struct tpm2_cmd cmd;
566 	int i;
567 
568 	duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST);
569 
570 	loops = jiffies_to_msecs(duration) / delay_msec;
571 
572 	rc = tpm2_start_selftest(chip, true);
573 	if (rc)
574 		return rc;
575 
576 	for (i = 0; i < loops; i++) {
577 		/* Attempt to read a PCR value */
578 		cmd.header.in = tpm2_pcrread_header;
579 		cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1);
580 		cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
581 		cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
582 		cmd.params.pcrread_in.pcr_select[0] = 0x01;
583 		cmd.params.pcrread_in.pcr_select[1] = 0x00;
584 		cmd.params.pcrread_in.pcr_select[2] = 0x00;
585 
586 		rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL);
587 		if (rc < 0)
588 			break;
589 
590 		rc = be32_to_cpu(cmd.header.out.return_code);
591 		if (rc != TPM2_RC_TESTING)
592 			break;
593 
594 		msleep(delay_msec);
595 	}
596 
597 	return rc;
598 }
599 EXPORT_SYMBOL_GPL(tpm2_do_selftest);
600 
601 /**
602  * tpm2_gen_interrupt() - generate an interrupt
603  * @chip: TPM chip to use
604  *
605  * 0 is returned when the operation is successful. If a negative number is
606  * returned it remarks a POSIX error code. If a positive number is returned
607  * it remarks a TPM error.
608  */
609 int tpm2_gen_interrupt(struct tpm_chip *chip)
610 {
611 	u32 dummy;
612 
613 	return tpm2_get_tpm_pt(chip, 0x100, &dummy,
614 			       "attempting to generate an interrupt");
615 }
616 EXPORT_SYMBOL_GPL(tpm2_gen_interrupt);
617 
618 /**
619  * tpm2_probe() - probe TPM 2.0
620  * @chip: TPM chip to use
621  *
622  * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on
623  * the reply tag.
624  */
625 int tpm2_probe(struct tpm_chip *chip)
626 {
627 	struct tpm2_cmd cmd;
628 	int rc;
629 
630 	cmd.header.in = tpm2_get_tpm_pt_header;
631 	cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
632 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
633 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
634 
635 	rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
636 	if (rc <  0)
637 		return rc;
638 	else if (rc < TPM_HEADER_SIZE)
639 		return -EFAULT;
640 
641 	if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
642 		chip->flags |= TPM_CHIP_FLAG_TPM2;
643 
644 	return 0;
645 }
646 EXPORT_SYMBOL_GPL(tpm2_probe);
647