diff options
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 158 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 32 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 62 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 113 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 4 | ||||
-rw-r--r-- | include/linux/tpm.h | 2 |
6 files changed, 250 insertions, 121 deletions
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 9e80a953d693..c43a9e28995e 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -369,20 +369,40 @@ err_len: | |||
369 | return -EINVAL; | 369 | return -EINVAL; |
370 | } | 370 | } |
371 | 371 | ||
372 | /** | 372 | static int tpm_request_locality(struct tpm_chip *chip) |
373 | * tmp_transmit - Internal kernel interface to transmit TPM commands. | 373 | { |
374 | * | 374 | int rc; |
375 | * @chip: TPM chip to use | 375 | |
376 | * @buf: TPM command buffer | 376 | if (!chip->ops->request_locality) |
377 | * @bufsiz: length of the TPM command buffer | 377 | return 0; |
378 | * @flags: tpm transmit flags - bitmap | 378 | |
379 | * | 379 | rc = chip->ops->request_locality(chip, 0); |
380 | * Return: | 380 | if (rc < 0) |
381 | * 0 when the operation is successful. | 381 | return rc; |
382 | * A negative number for system errors (errno). | 382 | |
383 | */ | 383 | chip->locality = rc; |
384 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | 384 | |
385 | u8 *buf, size_t bufsiz, unsigned int flags) | 385 | return 0; |
386 | } | ||
387 | |||
388 | static void tpm_relinquish_locality(struct tpm_chip *chip) | ||
389 | { | ||
390 | int rc; | ||
391 | |||
392 | if (!chip->ops->relinquish_locality) | ||
393 | return; | ||
394 | |||
395 | rc = chip->ops->relinquish_locality(chip, chip->locality); | ||
396 | if (rc) | ||
397 | dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); | ||
398 | |||
399 | chip->locality = -1; | ||
400 | } | ||
401 | |||
402 | static ssize_t tpm_try_transmit(struct tpm_chip *chip, | ||
403 | struct tpm_space *space, | ||
404 | u8 *buf, size_t bufsiz, | ||
405 | unsigned int flags) | ||
386 | { | 406 | { |
387 | struct tpm_output_header *header = (void *)buf; | 407 | struct tpm_output_header *header = (void *)buf; |
388 | int rc; | 408 | int rc; |
@@ -422,8 +442,6 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | |||
422 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) | 442 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) |
423 | mutex_lock(&chip->tpm_mutex); | 443 | mutex_lock(&chip->tpm_mutex); |
424 | 444 | ||
425 | if (chip->dev.parent) | ||
426 | pm_runtime_get_sync(chip->dev.parent); | ||
427 | 445 | ||
428 | if (chip->ops->clk_enable != NULL) | 446 | if (chip->ops->clk_enable != NULL) |
429 | chip->ops->clk_enable(chip, true); | 447 | chip->ops->clk_enable(chip, true); |
@@ -431,19 +449,20 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | |||
431 | /* Store the decision as chip->locality will be changed. */ | 449 | /* Store the decision as chip->locality will be changed. */ |
432 | need_locality = chip->locality == -1; | 450 | need_locality = chip->locality == -1; |
433 | 451 | ||
434 | if (!(flags & TPM_TRANSMIT_RAW) && | 452 | if (!(flags & TPM_TRANSMIT_RAW) && need_locality) { |
435 | need_locality && chip->ops->request_locality) { | 453 | rc = tpm_request_locality(chip); |
436 | rc = chip->ops->request_locality(chip, 0); | ||
437 | if (rc < 0) | 454 | if (rc < 0) |
438 | goto out_no_locality; | 455 | goto out_no_locality; |
439 | chip->locality = rc; | ||
440 | } | 456 | } |
441 | 457 | ||
458 | if (chip->dev.parent) | ||
459 | pm_runtime_get_sync(chip->dev.parent); | ||
460 | |||
442 | rc = tpm2_prepare_space(chip, space, ordinal, buf); | 461 | rc = tpm2_prepare_space(chip, space, ordinal, buf); |
443 | if (rc) | 462 | if (rc) |
444 | goto out; | 463 | goto out; |
445 | 464 | ||
446 | rc = chip->ops->send(chip, (u8 *) buf, count); | 465 | rc = chip->ops->send(chip, buf, count); |
447 | if (rc < 0) { | 466 | if (rc < 0) { |
448 | if (rc != -EPIPE) | 467 | if (rc != -EPIPE) |
449 | dev_err(&chip->dev, | 468 | dev_err(&chip->dev, |
@@ -480,7 +499,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | |||
480 | goto out; | 499 | goto out; |
481 | 500 | ||
482 | out_recv: | 501 | out_recv: |
483 | len = chip->ops->recv(chip, (u8 *) buf, bufsiz); | 502 | len = chip->ops->recv(chip, buf, bufsiz); |
484 | if (len < 0) { | 503 | if (len < 0) { |
485 | rc = len; | 504 | rc = len; |
486 | dev_err(&chip->dev, | 505 | dev_err(&chip->dev, |
@@ -499,27 +518,95 @@ out_recv: | |||
499 | rc = tpm2_commit_space(chip, space, ordinal, buf, &len); | 518 | rc = tpm2_commit_space(chip, space, ordinal, buf, &len); |
500 | 519 | ||
501 | out: | 520 | out: |
502 | if (need_locality && chip->ops->relinquish_locality) { | 521 | if (chip->dev.parent) |
503 | chip->ops->relinquish_locality(chip, chip->locality); | 522 | pm_runtime_put_sync(chip->dev.parent); |
504 | chip->locality = -1; | 523 | |
505 | } | 524 | if (need_locality) |
525 | tpm_relinquish_locality(chip); | ||
526 | |||
506 | out_no_locality: | 527 | out_no_locality: |
507 | if (chip->ops->clk_enable != NULL) | 528 | if (chip->ops->clk_enable != NULL) |
508 | chip->ops->clk_enable(chip, false); | 529 | chip->ops->clk_enable(chip, false); |
509 | 530 | ||
510 | if (chip->dev.parent) | ||
511 | pm_runtime_put_sync(chip->dev.parent); | ||
512 | |||
513 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) | 531 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) |
514 | mutex_unlock(&chip->tpm_mutex); | 532 | mutex_unlock(&chip->tpm_mutex); |
515 | return rc ? rc : len; | 533 | return rc ? rc : len; |
516 | } | 534 | } |
517 | 535 | ||
518 | /** | 536 | /** |
519 | * tmp_transmit_cmd - send a tpm command to the device | 537 | * tpm_transmit - Internal kernel interface to transmit TPM commands. |
538 | * | ||
539 | * @chip: TPM chip to use | ||
540 | * @space: tpm space | ||
541 | * @buf: TPM command buffer | ||
542 | * @bufsiz: length of the TPM command buffer | ||
543 | * @flags: tpm transmit flags - bitmap | ||
544 | * | ||
545 | * A wrapper around tpm_try_transmit that handles TPM2_RC_RETRY | ||
546 | * returns from the TPM and retransmits the command after a delay up | ||
547 | * to a maximum wait of TPM2_DURATION_LONG. | ||
548 | * | ||
549 | * Note: TPM1 never returns TPM2_RC_RETRY so the retry logic is TPM2 | ||
550 | * only | ||
551 | * | ||
552 | * Return: | ||
553 | * the length of the return when the operation is successful. | ||
554 | * A negative number for system errors (errno). | ||
555 | */ | ||
556 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | ||
557 | u8 *buf, size_t bufsiz, unsigned int flags) | ||
558 | { | ||
559 | struct tpm_output_header *header = (struct tpm_output_header *)buf; | ||
560 | /* space for header and handles */ | ||
561 | u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; | ||
562 | unsigned int delay_msec = TPM2_DURATION_SHORT; | ||
563 | u32 rc = 0; | ||
564 | ssize_t ret; | ||
565 | const size_t save_size = min(space ? sizeof(save) : TPM_HEADER_SIZE, | ||
566 | bufsiz); | ||
567 | /* the command code is where the return code will be */ | ||
568 | u32 cc = be32_to_cpu(header->return_code); | ||
569 | |||
570 | /* | ||
571 | * Subtlety here: if we have a space, the handles will be | ||
572 | * transformed, so when we restore the header we also have to | ||
573 | * restore the handles. | ||
574 | */ | ||
575 | memcpy(save, buf, save_size); | ||
576 | |||
577 | for (;;) { | ||
578 | ret = tpm_try_transmit(chip, space, buf, bufsiz, flags); | ||
579 | if (ret < 0) | ||
580 | break; | ||
581 | rc = be32_to_cpu(header->return_code); | ||
582 | if (rc != TPM2_RC_RETRY && rc != TPM2_RC_TESTING) | ||
583 | break; | ||
584 | /* | ||
585 | * return immediately if self test returns test | ||
586 | * still running to shorten boot time. | ||
587 | */ | ||
588 | if (rc == TPM2_RC_TESTING && cc == TPM2_CC_SELF_TEST) | ||
589 | break; | ||
590 | delay_msec *= 2; | ||
591 | if (delay_msec > TPM2_DURATION_LONG) { | ||
592 | if (rc == TPM2_RC_RETRY) | ||
593 | dev_err(&chip->dev, "in retry loop\n"); | ||
594 | else | ||
595 | dev_err(&chip->dev, | ||
596 | "self test is still running\n"); | ||
597 | break; | ||
598 | } | ||
599 | tpm_msleep(delay_msec); | ||
600 | memcpy(buf, save, save_size); | ||
601 | } | ||
602 | return ret; | ||
603 | } | ||
604 | /** | ||
605 | * tpm_transmit_cmd - send a tpm command to the device | ||
520 | * The function extracts tpm out header return code | 606 | * The function extracts tpm out header return code |
521 | * | 607 | * |
522 | * @chip: TPM chip to use | 608 | * @chip: TPM chip to use |
609 | * @space: tpm space | ||
523 | * @buf: TPM command buffer | 610 | * @buf: TPM command buffer |
524 | * @bufsiz: length of the buffer | 611 | * @bufsiz: length of the buffer |
525 | * @min_rsp_body_length: minimum expected length of response body | 612 | * @min_rsp_body_length: minimum expected length of response body |
@@ -532,7 +619,7 @@ out_no_locality: | |||
532 | * A positive number for a TPM error. | 619 | * A positive number for a TPM error. |
533 | */ | 620 | */ |
534 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | 621 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, |
535 | const void *buf, size_t bufsiz, | 622 | void *buf, size_t bufsiz, |
536 | size_t min_rsp_body_length, unsigned int flags, | 623 | size_t min_rsp_body_length, unsigned int flags, |
537 | const char *desc) | 624 | const char *desc) |
538 | { | 625 | { |
@@ -540,7 +627,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | |||
540 | int err; | 627 | int err; |
541 | ssize_t len; | 628 | ssize_t len; |
542 | 629 | ||
543 | len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags); | 630 | len = tpm_transmit(chip, space, buf, bufsiz, flags); |
544 | if (len < 0) | 631 | if (len < 0) |
545 | return len; | 632 | return len; |
546 | 633 | ||
@@ -666,6 +753,8 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
666 | msecs_to_jiffies(TPM2_DURATION_MEDIUM); | 753 | msecs_to_jiffies(TPM2_DURATION_MEDIUM); |
667 | chip->duration[TPM_LONG] = | 754 | chip->duration[TPM_LONG] = |
668 | msecs_to_jiffies(TPM2_DURATION_LONG); | 755 | msecs_to_jiffies(TPM2_DURATION_LONG); |
756 | chip->duration[TPM_LONG_LONG] = | ||
757 | msecs_to_jiffies(TPM2_DURATION_LONG_LONG); | ||
669 | 758 | ||
670 | chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; | 759 | chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; |
671 | return 0; | 760 | return 0; |
@@ -754,6 +843,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
754 | usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); | 843 | usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); |
755 | chip->duration[TPM_LONG] = | 844 | chip->duration[TPM_LONG] = |
756 | usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); | 845 | usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); |
846 | chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ | ||
757 | 847 | ||
758 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above | 848 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above |
759 | * value wrong and apparently reports msecs rather than usecs. So we | 849 | * value wrong and apparently reports msecs rather than usecs. So we |
@@ -969,6 +1059,10 @@ int tpm_do_selftest(struct tpm_chip *chip) | |||
969 | loops = jiffies_to_msecs(duration) / delay_msec; | 1059 | loops = jiffies_to_msecs(duration) / delay_msec; |
970 | 1060 | ||
971 | rc = tpm_continue_selftest(chip); | 1061 | rc = tpm_continue_selftest(chip); |
1062 | if (rc == TPM_ERR_INVALID_POSTINIT) { | ||
1063 | chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; | ||
1064 | dev_info(&chip->dev, "TPM not ready (%d)\n", rc); | ||
1065 | } | ||
972 | /* This may fail if there was no TPM driver during a suspend/resume | 1066 | /* This may fail if there was no TPM driver during a suspend/resume |
973 | * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) | 1067 | * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) |
974 | */ | 1068 | */ |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f895fba4e20d..7f2d0f489e9c 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -67,7 +67,9 @@ enum tpm_duration { | |||
67 | TPM_SHORT = 0, | 67 | TPM_SHORT = 0, |
68 | TPM_MEDIUM = 1, | 68 | TPM_MEDIUM = 1, |
69 | TPM_LONG = 2, | 69 | TPM_LONG = 2, |
70 | TPM_LONG_LONG = 3, | ||
70 | TPM_UNDEFINED, | 71 | TPM_UNDEFINED, |
72 | TPM_NUM_DURATIONS = TPM_UNDEFINED, | ||
71 | }; | 73 | }; |
72 | 74 | ||
73 | #define TPM_WARN_RETRY 0x800 | 75 | #define TPM_WARN_RETRY 0x800 |
@@ -79,15 +81,20 @@ enum tpm_duration { | |||
79 | #define TPM_HEADER_SIZE 10 | 81 | #define TPM_HEADER_SIZE 10 |
80 | 82 | ||
81 | enum tpm2_const { | 83 | enum tpm2_const { |
82 | TPM2_PLATFORM_PCR = 24, | 84 | TPM2_PLATFORM_PCR = 24, |
83 | TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), | 85 | TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), |
84 | TPM2_TIMEOUT_A = 750, | 86 | }; |
85 | TPM2_TIMEOUT_B = 2000, | 87 | |
86 | TPM2_TIMEOUT_C = 200, | 88 | enum tpm2_timeouts { |
87 | TPM2_TIMEOUT_D = 30, | 89 | TPM2_TIMEOUT_A = 750, |
88 | TPM2_DURATION_SHORT = 20, | 90 | TPM2_TIMEOUT_B = 2000, |
89 | TPM2_DURATION_MEDIUM = 750, | 91 | TPM2_TIMEOUT_C = 200, |
90 | TPM2_DURATION_LONG = 2000, | 92 | TPM2_TIMEOUT_D = 30, |
93 | TPM2_DURATION_SHORT = 20, | ||
94 | TPM2_DURATION_MEDIUM = 750, | ||
95 | TPM2_DURATION_LONG = 2000, | ||
96 | TPM2_DURATION_LONG_LONG = 300000, | ||
97 | TPM2_DURATION_DEFAULT = 120000, | ||
91 | }; | 98 | }; |
92 | 99 | ||
93 | enum tpm2_structures { | 100 | enum tpm2_structures { |
@@ -104,10 +111,12 @@ enum tpm2_return_codes { | |||
104 | TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ | 111 | TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ |
105 | TPM2_RC_HANDLE = 0x008B, | 112 | TPM2_RC_HANDLE = 0x008B, |
106 | TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ | 113 | TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ |
114 | TPM2_RC_FAILURE = 0x0101, | ||
107 | TPM2_RC_DISABLED = 0x0120, | 115 | TPM2_RC_DISABLED = 0x0120, |
108 | TPM2_RC_COMMAND_CODE = 0x0143, | 116 | TPM2_RC_COMMAND_CODE = 0x0143, |
109 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ | 117 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ |
110 | TPM2_RC_REFERENCE_H0 = 0x0910, | 118 | TPM2_RC_REFERENCE_H0 = 0x0910, |
119 | TPM2_RC_RETRY = 0x0922, | ||
111 | }; | 120 | }; |
112 | 121 | ||
113 | enum tpm2_algorithms { | 122 | enum tpm2_algorithms { |
@@ -123,6 +132,7 @@ enum tpm2_algorithms { | |||
123 | 132 | ||
124 | enum tpm2_command_codes { | 133 | enum tpm2_command_codes { |
125 | TPM2_CC_FIRST = 0x011F, | 134 | TPM2_CC_FIRST = 0x011F, |
135 | TPM2_CC_CREATE_PRIMARY = 0x0131, | ||
126 | TPM2_CC_SELF_TEST = 0x0143, | 136 | TPM2_CC_SELF_TEST = 0x0143, |
127 | TPM2_CC_STARTUP = 0x0144, | 137 | TPM2_CC_STARTUP = 0x0144, |
128 | TPM2_CC_SHUTDOWN = 0x0145, | 138 | TPM2_CC_SHUTDOWN = 0x0145, |
@@ -227,7 +237,7 @@ struct tpm_chip { | |||
227 | unsigned long timeout_c; /* jiffies */ | 237 | unsigned long timeout_c; /* jiffies */ |
228 | unsigned long timeout_d; /* jiffies */ | 238 | unsigned long timeout_d; /* jiffies */ |
229 | bool timeout_adjusted; | 239 | bool timeout_adjusted; |
230 | unsigned long duration[3]; /* jiffies */ | 240 | unsigned long duration[TPM_NUM_DURATIONS]; /* jiffies */ |
231 | bool duration_adjusted; | 241 | bool duration_adjusted; |
232 | 242 | ||
233 | struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES]; | 243 | struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES]; |
@@ -506,7 +516,7 @@ enum tpm_transmit_flags { | |||
506 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | 516 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, |
507 | u8 *buf, size_t bufsiz, unsigned int flags); | 517 | u8 *buf, size_t bufsiz, unsigned int flags); |
508 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | 518 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, |
509 | const void *buf, size_t bufsiz, | 519 | void *buf, size_t bufsiz, |
510 | size_t min_rsp_body_length, unsigned int flags, | 520 | size_t min_rsp_body_length, unsigned int flags, |
511 | const char *desc); | 521 | const char *desc); |
512 | int tpm_startup(struct tpm_chip *chip); | 522 | int tpm_startup(struct tpm_chip *chip); |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index a700f8f9ead7..96c77c8e7f40 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -31,10 +31,6 @@ struct tpm2_startup_in { | |||
31 | __be16 startup_type; | 31 | __be16 startup_type; |
32 | } __packed; | 32 | } __packed; |
33 | 33 | ||
34 | struct tpm2_self_test_in { | ||
35 | u8 full_test; | ||
36 | } __packed; | ||
37 | |||
38 | struct tpm2_get_tpm_pt_in { | 34 | struct tpm2_get_tpm_pt_in { |
39 | __be32 cap_id; | 35 | __be32 cap_id; |
40 | __be32 property_id; | 36 | __be32 property_id; |
@@ -60,7 +56,6 @@ struct tpm2_get_random_out { | |||
60 | 56 | ||
61 | union tpm2_cmd_params { | 57 | union tpm2_cmd_params { |
62 | struct tpm2_startup_in startup_in; | 58 | struct tpm2_startup_in startup_in; |
63 | struct tpm2_self_test_in selftest_in; | ||
64 | struct tpm2_get_tpm_pt_in get_tpm_pt_in; | 59 | struct tpm2_get_tpm_pt_in get_tpm_pt_in; |
65 | struct tpm2_get_tpm_pt_out get_tpm_pt_out; | 60 | struct tpm2_get_tpm_pt_out get_tpm_pt_out; |
66 | struct tpm2_get_random_in getrandom_in; | 61 | struct tpm2_get_random_in getrandom_in; |
@@ -90,6 +85,8 @@ static struct tpm2_hash tpm2_hash_map[] = { | |||
90 | * of time the chip could take to return the result. The values | 85 | * of time the chip could take to return the result. The values |
91 | * of the SHORT, MEDIUM, and LONG durations are taken from the | 86 | * of the SHORT, MEDIUM, and LONG durations are taken from the |
92 | * PC Client Profile (PTP) specification. | 87 | * PC Client Profile (PTP) specification. |
88 | * LONG_LONG is for commands that generates keys which empirically | ||
89 | * takes longer time on some systems. | ||
93 | */ | 90 | */ |
94 | static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { | 91 | static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { |
95 | TPM_UNDEFINED, /* 11F */ | 92 | TPM_UNDEFINED, /* 11F */ |
@@ -110,7 +107,7 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { | |||
110 | TPM_UNDEFINED, /* 12e */ | 107 | TPM_UNDEFINED, /* 12e */ |
111 | TPM_UNDEFINED, /* 12f */ | 108 | TPM_UNDEFINED, /* 12f */ |
112 | TPM_UNDEFINED, /* 130 */ | 109 | TPM_UNDEFINED, /* 130 */ |
113 | TPM_UNDEFINED, /* 131 */ | 110 | TPM_LONG_LONG, /* 131 */ |
114 | TPM_UNDEFINED, /* 132 */ | 111 | TPM_UNDEFINED, /* 132 */ |
115 | TPM_UNDEFINED, /* 133 */ | 112 | TPM_UNDEFINED, /* 133 */ |
116 | TPM_UNDEFINED, /* 134 */ | 113 | TPM_UNDEFINED, /* 134 */ |
@@ -144,7 +141,7 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { | |||
144 | TPM_UNDEFINED, /* 150 */ | 141 | TPM_UNDEFINED, /* 150 */ |
145 | TPM_UNDEFINED, /* 151 */ | 142 | TPM_UNDEFINED, /* 151 */ |
146 | TPM_UNDEFINED, /* 152 */ | 143 | TPM_UNDEFINED, /* 152 */ |
147 | TPM_UNDEFINED, /* 153 */ | 144 | TPM_LONG_LONG, /* 153 */ |
148 | TPM_UNDEFINED, /* 154 */ | 145 | TPM_UNDEFINED, /* 154 */ |
149 | TPM_UNDEFINED, /* 155 */ | 146 | TPM_UNDEFINED, /* 155 */ |
150 | TPM_UNDEFINED, /* 156 */ | 147 | TPM_UNDEFINED, /* 156 */ |
@@ -821,22 +818,12 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) | |||
821 | duration = chip->duration[index]; | 818 | duration = chip->duration[index]; |
822 | 819 | ||
823 | if (duration <= 0) | 820 | if (duration <= 0) |
824 | duration = 2 * 60 * HZ; | 821 | duration = msecs_to_jiffies(TPM2_DURATION_DEFAULT); |
825 | 822 | ||
826 | return duration; | 823 | return duration; |
827 | } | 824 | } |
828 | EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); | 825 | EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); |
829 | 826 | ||
830 | #define TPM2_SELF_TEST_IN_SIZE \ | ||
831 | (sizeof(struct tpm_input_header) + \ | ||
832 | sizeof(struct tpm2_self_test_in)) | ||
833 | |||
834 | static const struct tpm_input_header tpm2_selftest_header = { | ||
835 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
836 | .length = cpu_to_be32(TPM2_SELF_TEST_IN_SIZE), | ||
837 | .ordinal = cpu_to_be32(TPM2_CC_SELF_TEST) | ||
838 | }; | ||
839 | |||
840 | /** | 827 | /** |
841 | * tpm2_do_selftest() - ensure that all self tests have passed | 828 | * tpm2_do_selftest() - ensure that all self tests have passed |
842 | * | 829 | * |
@@ -852,27 +839,24 @@ static const struct tpm_input_header tpm2_selftest_header = { | |||
852 | */ | 839 | */ |
853 | static int tpm2_do_selftest(struct tpm_chip *chip) | 840 | static int tpm2_do_selftest(struct tpm_chip *chip) |
854 | { | 841 | { |
842 | struct tpm_buf buf; | ||
843 | int full; | ||
855 | int rc; | 844 | int rc; |
856 | unsigned int delay_msec = 10; | ||
857 | long duration; | ||
858 | struct tpm2_cmd cmd; | ||
859 | 845 | ||
860 | duration = jiffies_to_msecs( | 846 | for (full = 0; full < 2; full++) { |
861 | tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); | 847 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); |
862 | 848 | if (rc) | |
863 | while (1) { | 849 | return rc; |
864 | cmd.header.in = tpm2_selftest_header; | ||
865 | cmd.params.selftest_in.full_test = 0; | ||
866 | |||
867 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, | ||
868 | 0, 0, "continue selftest"); | ||
869 | 850 | ||
870 | if (rc != TPM2_RC_TESTING || delay_msec >= duration) | 851 | tpm_buf_append_u8(&buf, full); |
871 | break; | 852 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, |
853 | "attempting the self test"); | ||
854 | tpm_buf_destroy(&buf); | ||
872 | 855 | ||
873 | /* wait longer than before */ | 856 | if (rc == TPM2_RC_TESTING) |
874 | delay_msec *= 2; | 857 | rc = TPM2_RC_SUCCESS; |
875 | tpm_msleep(delay_msec); | 858 | if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS) |
859 | return rc; | ||
876 | } | 860 | } |
877 | 861 | ||
878 | return rc; | 862 | return rc; |
@@ -1058,10 +1042,8 @@ int tpm2_auto_startup(struct tpm_chip *chip) | |||
1058 | goto out; | 1042 | goto out; |
1059 | 1043 | ||
1060 | rc = tpm2_do_selftest(chip); | 1044 | rc = tpm2_do_selftest(chip); |
1061 | if (rc != 0 && rc != TPM2_RC_INITIALIZE) { | 1045 | if (rc && rc != TPM2_RC_INITIALIZE) |
1062 | dev_err(&chip->dev, "TPM self test failed\n"); | ||
1063 | goto out; | 1046 | goto out; |
1064 | } | ||
1065 | 1047 | ||
1066 | if (rc == TPM2_RC_INITIALIZE) { | 1048 | if (rc == TPM2_RC_INITIALIZE) { |
1067 | rc = tpm_startup(chip); | 1049 | rc = tpm_startup(chip); |
@@ -1069,10 +1051,8 @@ int tpm2_auto_startup(struct tpm_chip *chip) | |||
1069 | goto out; | 1051 | goto out; |
1070 | 1052 | ||
1071 | rc = tpm2_do_selftest(chip); | 1053 | rc = tpm2_do_selftest(chip); |
1072 | if (rc) { | 1054 | if (rc) |
1073 | dev_err(&chip->dev, "TPM self test failed\n"); | ||
1074 | goto out; | 1055 | goto out; |
1075 | } | ||
1076 | } | 1056 | } |
1077 | 1057 | ||
1078 | rc = tpm2_get_pcr_allocation(chip); | 1058 | rc = tpm2_get_pcr_allocation(chip); |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 7b3c2a8aa9de..7f78482cd157 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -112,6 +112,25 @@ struct tpm2_crb_smc { | |||
112 | u32 smc_func_id; | 112 | u32 smc_func_id; |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, | ||
116 | unsigned long timeout) | ||
117 | { | ||
118 | ktime_t start; | ||
119 | ktime_t stop; | ||
120 | |||
121 | start = ktime_get(); | ||
122 | stop = ktime_add(start, ms_to_ktime(timeout)); | ||
123 | |||
124 | do { | ||
125 | if ((ioread32(reg) & mask) == value) | ||
126 | return true; | ||
127 | |||
128 | usleep_range(50, 100); | ||
129 | } while (ktime_before(ktime_get(), stop)); | ||
130 | |||
131 | return ((ioread32(reg) & mask) == value); | ||
132 | } | ||
133 | |||
115 | /** | 134 | /** |
116 | * crb_go_idle - request tpm crb device to go the idle state | 135 | * crb_go_idle - request tpm crb device to go the idle state |
117 | * | 136 | * |
@@ -128,7 +147,7 @@ struct tpm2_crb_smc { | |||
128 | * | 147 | * |
129 | * Return: 0 always | 148 | * Return: 0 always |
130 | */ | 149 | */ |
131 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) | 150 | static int crb_go_idle(struct device *dev, struct crb_priv *priv) |
132 | { | 151 | { |
133 | if ((priv->sm == ACPI_TPM2_START_METHOD) || | 152 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
134 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || | 153 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
@@ -136,30 +155,17 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) | |||
136 | return 0; | 155 | return 0; |
137 | 156 | ||
138 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); | 157 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); |
139 | /* we don't really care when this settles */ | ||
140 | 158 | ||
159 | if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, | ||
160 | CRB_CTRL_REQ_GO_IDLE/* mask */, | ||
161 | 0, /* value */ | ||
162 | TPM2_TIMEOUT_C)) { | ||
163 | dev_warn(dev, "goIdle timed out\n"); | ||
164 | return -ETIME; | ||
165 | } | ||
141 | return 0; | 166 | return 0; |
142 | } | 167 | } |
143 | 168 | ||
144 | static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, | ||
145 | unsigned long timeout) | ||
146 | { | ||
147 | ktime_t start; | ||
148 | ktime_t stop; | ||
149 | |||
150 | start = ktime_get(); | ||
151 | stop = ktime_add(start, ms_to_ktime(timeout)); | ||
152 | |||
153 | do { | ||
154 | if ((ioread32(reg) & mask) == value) | ||
155 | return true; | ||
156 | |||
157 | usleep_range(50, 100); | ||
158 | } while (ktime_before(ktime_get(), stop)); | ||
159 | |||
160 | return false; | ||
161 | } | ||
162 | |||
163 | /** | 169 | /** |
164 | * crb_cmd_ready - request tpm crb device to enter ready state | 170 | * crb_cmd_ready - request tpm crb device to enter ready state |
165 | * | 171 | * |
@@ -175,8 +181,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, | |||
175 | * | 181 | * |
176 | * Return: 0 on success -ETIME on timeout; | 182 | * Return: 0 on success -ETIME on timeout; |
177 | */ | 183 | */ |
178 | static int __maybe_unused crb_cmd_ready(struct device *dev, | 184 | static int crb_cmd_ready(struct device *dev, struct crb_priv *priv) |
179 | struct crb_priv *priv) | ||
180 | { | 185 | { |
181 | if ((priv->sm == ACPI_TPM2_START_METHOD) || | 186 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
182 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || | 187 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
@@ -195,11 +200,11 @@ static int __maybe_unused crb_cmd_ready(struct device *dev, | |||
195 | return 0; | 200 | return 0; |
196 | } | 201 | } |
197 | 202 | ||
198 | static int crb_request_locality(struct tpm_chip *chip, int loc) | 203 | static int __crb_request_locality(struct device *dev, |
204 | struct crb_priv *priv, int loc) | ||
199 | { | 205 | { |
200 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | ||
201 | u32 value = CRB_LOC_STATE_LOC_ASSIGNED | | 206 | u32 value = CRB_LOC_STATE_LOC_ASSIGNED | |
202 | CRB_LOC_STATE_TPM_REG_VALID_STS; | 207 | CRB_LOC_STATE_TPM_REG_VALID_STS; |
203 | 208 | ||
204 | if (!priv->regs_h) | 209 | if (!priv->regs_h) |
205 | return 0; | 210 | return 0; |
@@ -207,21 +212,45 @@ static int crb_request_locality(struct tpm_chip *chip, int loc) | |||
207 | iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl); | 212 | iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl); |
208 | if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value, | 213 | if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value, |
209 | TPM2_TIMEOUT_C)) { | 214 | TPM2_TIMEOUT_C)) { |
210 | dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); | 215 | dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); |
211 | return -ETIME; | 216 | return -ETIME; |
212 | } | 217 | } |
213 | 218 | ||
214 | return 0; | 219 | return 0; |
215 | } | 220 | } |
216 | 221 | ||
217 | static void crb_relinquish_locality(struct tpm_chip *chip, int loc) | 222 | static int crb_request_locality(struct tpm_chip *chip, int loc) |
218 | { | 223 | { |
219 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 224 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
220 | 225 | ||
226 | return __crb_request_locality(&chip->dev, priv, loc); | ||
227 | } | ||
228 | |||
229 | static int __crb_relinquish_locality(struct device *dev, | ||
230 | struct crb_priv *priv, int loc) | ||
231 | { | ||
232 | u32 mask = CRB_LOC_STATE_LOC_ASSIGNED | | ||
233 | CRB_LOC_STATE_TPM_REG_VALID_STS; | ||
234 | u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS; | ||
235 | |||
221 | if (!priv->regs_h) | 236 | if (!priv->regs_h) |
222 | return; | 237 | return 0; |
223 | 238 | ||
224 | iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); | 239 | iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); |
240 | if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value, | ||
241 | TPM2_TIMEOUT_C)) { | ||
242 | dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); | ||
243 | return -ETIME; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int crb_relinquish_locality(struct tpm_chip *chip, int loc) | ||
250 | { | ||
251 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | ||
252 | |||
253 | return __crb_relinquish_locality(&chip->dev, priv, loc); | ||
225 | } | 254 | } |
226 | 255 | ||
227 | static u8 crb_status(struct tpm_chip *chip) | 256 | static u8 crb_status(struct tpm_chip *chip) |
@@ -442,6 +471,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
442 | u32 pa_high, pa_low; | 471 | u32 pa_high, pa_low; |
443 | u64 cmd_pa; | 472 | u64 cmd_pa; |
444 | u32 cmd_size; | 473 | u32 cmd_size; |
474 | __le64 __rsp_pa; | ||
445 | u64 rsp_pa; | 475 | u64 rsp_pa; |
446 | u32 rsp_size; | 476 | u32 rsp_size; |
447 | int ret; | 477 | int ret; |
@@ -475,6 +505,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
475 | dev_warn(dev, FW_BUG "Bad ACPI memory layout"); | 505 | dev_warn(dev, FW_BUG "Bad ACPI memory layout"); |
476 | } | 506 | } |
477 | 507 | ||
508 | ret = __crb_request_locality(dev, priv, 0); | ||
509 | if (ret) | ||
510 | return ret; | ||
511 | |||
478 | priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address, | 512 | priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address, |
479 | sizeof(struct crb_regs_tail)); | 513 | sizeof(struct crb_regs_tail)); |
480 | if (IS_ERR(priv->regs_t)) | 514 | if (IS_ERR(priv->regs_t)) |
@@ -503,8 +537,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
503 | goto out; | 537 | goto out; |
504 | } | 538 | } |
505 | 539 | ||
506 | memcpy_fromio(&rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8); | 540 | memcpy_fromio(&__rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8); |
507 | rsp_pa = le64_to_cpu(rsp_pa); | 541 | rsp_pa = le64_to_cpu(__rsp_pa); |
508 | rsp_size = crb_fixup_cmd_size(dev, &io_res, rsp_pa, | 542 | rsp_size = crb_fixup_cmd_size(dev, &io_res, rsp_pa, |
509 | ioread32(&priv->regs_t->ctrl_rsp_size)); | 543 | ioread32(&priv->regs_t->ctrl_rsp_size)); |
510 | 544 | ||
@@ -531,6 +565,8 @@ out: | |||
531 | 565 | ||
532 | crb_go_idle(dev, priv); | 566 | crb_go_idle(dev, priv); |
533 | 567 | ||
568 | __crb_relinquish_locality(dev, priv, 0); | ||
569 | |||
534 | return ret; | 570 | return ret; |
535 | } | 571 | } |
536 | 572 | ||
@@ -588,10 +624,14 @@ static int crb_acpi_add(struct acpi_device *device) | |||
588 | chip->acpi_dev_handle = device->handle; | 624 | chip->acpi_dev_handle = device->handle; |
589 | chip->flags = TPM_CHIP_FLAG_TPM2; | 625 | chip->flags = TPM_CHIP_FLAG_TPM2; |
590 | 626 | ||
591 | rc = crb_cmd_ready(dev, priv); | 627 | rc = __crb_request_locality(dev, priv, 0); |
592 | if (rc) | 628 | if (rc) |
593 | return rc; | 629 | return rc; |
594 | 630 | ||
631 | rc = crb_cmd_ready(dev, priv); | ||
632 | if (rc) | ||
633 | goto out; | ||
634 | |||
595 | pm_runtime_get_noresume(dev); | 635 | pm_runtime_get_noresume(dev); |
596 | pm_runtime_set_active(dev); | 636 | pm_runtime_set_active(dev); |
597 | pm_runtime_enable(dev); | 637 | pm_runtime_enable(dev); |
@@ -601,12 +641,15 @@ static int crb_acpi_add(struct acpi_device *device) | |||
601 | crb_go_idle(dev, priv); | 641 | crb_go_idle(dev, priv); |
602 | pm_runtime_put_noidle(dev); | 642 | pm_runtime_put_noidle(dev); |
603 | pm_runtime_disable(dev); | 643 | pm_runtime_disable(dev); |
604 | return rc; | 644 | goto out; |
605 | } | 645 | } |
606 | 646 | ||
607 | pm_runtime_put(dev); | 647 | pm_runtime_put_sync(dev); |
608 | 648 | ||
609 | return 0; | 649 | out: |
650 | __crb_relinquish_locality(dev, priv, 0); | ||
651 | |||
652 | return rc; | ||
610 | } | 653 | } |
611 | 654 | ||
612 | static int crb_acpi_remove(struct acpi_device *device) | 655 | static int crb_acpi_remove(struct acpi_device *device) |
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index da074e3db19b..5a1f47b43947 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c | |||
@@ -143,11 +143,13 @@ static bool check_locality(struct tpm_chip *chip, int l) | |||
143 | return false; | 143 | return false; |
144 | } | 144 | } |
145 | 145 | ||
146 | static void release_locality(struct tpm_chip *chip, int l) | 146 | static int release_locality(struct tpm_chip *chip, int l) |
147 | { | 147 | { |
148 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 148 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
149 | 149 | ||
150 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); | 150 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); |
151 | |||
152 | return 0; | ||
151 | } | 153 | } |
152 | 154 | ||
153 | static int request_locality(struct tpm_chip *chip, int l) | 155 | static int request_locality(struct tpm_chip *chip, int l) |
diff --git a/include/linux/tpm.h b/include/linux/tpm.h index bcdd3790e94d..06639fb6ab85 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h | |||
@@ -44,7 +44,7 @@ struct tpm_class_ops { | |||
44 | bool (*update_timeouts)(struct tpm_chip *chip, | 44 | bool (*update_timeouts)(struct tpm_chip *chip, |
45 | unsigned long *timeout_cap); | 45 | unsigned long *timeout_cap); |
46 | int (*request_locality)(struct tpm_chip *chip, int loc); | 46 | int (*request_locality)(struct tpm_chip *chip, int loc); |
47 | void (*relinquish_locality)(struct tpm_chip *chip, int loc); | 47 | int (*relinquish_locality)(struct tpm_chip *chip, int loc); |
48 | void (*clk_enable)(struct tpm_chip *chip, bool value); | 48 | void (*clk_enable)(struct tpm_chip *chip, bool value); |
49 | }; | 49 | }; |
50 | 50 | ||