]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/char/tpm/tpm2-cmd.c
Merge git://www.linux-watchdog.org/linux-watchdog
[mirror_ubuntu-bionic-kernel.git] / drivers / char / tpm / tpm2-cmd.c
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);