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