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
20struct tpm2_startup_in {
21	__be16	startup_type;
22} __packed;
23
24struct tpm2_self_test_in {
25	u8	full_test;
26} __packed;
27
28struct 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
35struct 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
46struct tpm2_null_auth_area {
47	__be32			handle;
48	__be16			nonce_size;
49	u8			attributes;
50	__be16			auth_size;
51} __packed;
52
53struct 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
62struct tpm2_get_tpm_pt_in {
63	__be32	cap_id;
64	__be32	property_id;
65	__be32	property_cnt;
66} __packed;
67
68struct 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
76struct tpm2_get_random_in {
77	__be16	size;
78} __packed;
79
80struct tpm2_get_random_out {
81	__be16	size;
82	u8	buffer[TPM_MAX_RNG_DATA];
83} __packed;
84
85union 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
97struct 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 */
108static 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
228static 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 */
244int 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
276static 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 */
292int 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
320static 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 */
336int 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
377static 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 */
394ssize_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
416static 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 */
432int 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}
442EXPORT_SYMBOL_GPL(tpm2_startup);
443
444#define TPM2_SHUTDOWN_IN_SIZE \
445	(sizeof(struct tpm_input_header) + \
446	 sizeof(struct tpm2_startup_in))
447
448static 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 */
460void 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}
477EXPORT_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 */
488unsigned 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}
504EXPORT_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
510static 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 */
526static 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 */
559int 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}
599EXPORT_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 */
609int 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}
616EXPORT_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 */
625int 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}
646EXPORT_SYMBOL_GPL(tpm2_probe);
647