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 * 0 is returned when the operation is successful. If a negative number is 461 * returned it remarks a POSIX error code. If a positive number is returned 462 * it remarks a TPM error. 463 */ 464 int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) 465 { 466 struct tpm2_cmd cmd; 467 468 cmd.header.in = tpm2_shutdown_header; 469 470 cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); 471 return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 472 "stopping the TPM"); 473 } 474 EXPORT_SYMBOL_GPL(tpm2_shutdown); 475 476 /* 477 * tpm2_calc_ordinal_duration() - maximum duration for a command 478 * @chip: TPM chip to use. 479 * @ordinal: command code number. 480 * 481 * 0 is returned when the operation is successful. If a negative number is 482 * returned it remarks a POSIX error code. If a positive number is returned 483 * it remarks a TPM error. 484 */ 485 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) 486 { 487 int index = TPM_UNDEFINED; 488 int duration = 0; 489 490 if (ordinal >= TPM2_CC_FIRST && ordinal <= TPM2_CC_LAST) 491 index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST]; 492 493 if (index != TPM_UNDEFINED) 494 duration = chip->vendor.duration[index]; 495 496 if (duration <= 0) 497 duration = 2 * 60 * HZ; 498 499 return duration; 500 } 501 EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); 502 503 #define TPM2_SELF_TEST_IN_SIZE \ 504 (sizeof(struct tpm_input_header) + \ 505 sizeof(struct tpm2_self_test_in)) 506 507 static const struct tpm_input_header tpm2_selftest_header = { 508 .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), 509 .length = cpu_to_be32(TPM2_SELF_TEST_IN_SIZE), 510 .ordinal = cpu_to_be32(TPM2_CC_SELF_TEST) 511 }; 512 513 /** 514 * tpm2_continue_selftest() - start a self test 515 * @chip: TPM chip to use 516 * @full: test all commands instead of testing only those that were not 517 * previously tested. 518 * 519 * 0 is returned when the operation is successful. If a negative number is 520 * returned it remarks a POSIX error code. If a positive number is returned 521 * it remarks a TPM error. 522 */ 523 static int tpm2_start_selftest(struct tpm_chip *chip, bool full) 524 { 525 int rc; 526 struct tpm2_cmd cmd; 527 528 cmd.header.in = tpm2_selftest_header; 529 cmd.params.selftest_in.full_test = full; 530 531 rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 532 "continue selftest"); 533 534 /* At least some prototype chips seem to give RC_TESTING error 535 * immediately. This is a workaround for that. 536 */ 537 if (rc == TPM2_RC_TESTING) { 538 dev_warn(chip->pdev, "Got RC_TESTING, ignoring\n"); 539 rc = 0; 540 } 541 542 return rc; 543 } 544 545 /** 546 * tpm2_do_selftest() - run a full self test 547 * @chip: TPM chip to use 548 * 549 * During the self test TPM2 commands return with the error code RC_TESTING. 550 * Waiting is done by issuing PCR read until it executes successfully. 551 * 552 * 0 is returned when the operation is successful. If a negative number is 553 * returned it remarks a POSIX error code. If a positive number is returned 554 * it remarks a TPM error. 555 */ 556 int tpm2_do_selftest(struct tpm_chip *chip) 557 { 558 int rc; 559 unsigned int loops; 560 unsigned int delay_msec = 100; 561 unsigned long duration; 562 struct tpm2_cmd cmd; 563 int i; 564 565 duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST); 566 567 loops = jiffies_to_msecs(duration) / delay_msec; 568 569 rc = tpm2_start_selftest(chip, true); 570 if (rc) 571 return rc; 572 573 for (i = 0; i < loops; i++) { 574 /* Attempt to read a PCR value */ 575 cmd.header.in = tpm2_pcrread_header; 576 cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1); 577 cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); 578 cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN; 579 cmd.params.pcrread_in.pcr_select[0] = 0x01; 580 cmd.params.pcrread_in.pcr_select[1] = 0x00; 581 cmd.params.pcrread_in.pcr_select[2] = 0x00; 582 583 rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL); 584 if (rc < 0) 585 break; 586 587 rc = be32_to_cpu(cmd.header.out.return_code); 588 if (rc != TPM2_RC_TESTING) 589 break; 590 591 msleep(delay_msec); 592 } 593 594 return rc; 595 } 596 EXPORT_SYMBOL_GPL(tpm2_do_selftest); 597 598 /** 599 * tpm2_gen_interrupt() - generate an interrupt 600 * @chip: TPM chip to use 601 * @quiet: surpress the error message 602 * 603 * 0 is returned when the operation is successful. If a negative number is 604 * returned it remarks a POSIX error code. If a positive number is returned 605 * it remarks a TPM error. 606 */ 607 int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet) 608 { 609 const char *desc = NULL; 610 u32 dummy; 611 612 if (!quiet) 613 desc = "attempting to generate an interrupt"; 614 615 return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc); 616 } 617 EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); 618