Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tpm: Factor out common startup code

The TCG standard startup sequence (get timeouts, tpm startup, etc) for
TPM and TPM2 chips is being open coded in many drivers, move it into
the core code.

tpm_tis and tpm_crb are used as the basis for the core code
implementation and the easy drivers are converted. In the process
several small drivers bugs relating to error handling this flow
are fixed.

For now the flag TPM_OPS_AUTO_STARTUP is optional to allow a staged
driver roll out, but ultimately all drivers should use this flow and
the flag removed. Some drivers still do not implement the startup
sequence at all and will need to be tested with it enabled.

Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Tested-by: Andrew Zamansky <andrew.zamansky@nuvoton.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

authored by

Jason Gunthorpe and committed by
Jarkko Sakkinen
cae8b441 2b88cd96

+92 -63
+1 -3
drivers/char/tpm/st33zp24/st33zp24.c
··· 505 505 } 506 506 507 507 static const struct tpm_class_ops st33zp24_tpm = { 508 + .flags = TPM_OPS_AUTO_STARTUP, 508 509 .send = st33zp24_send, 509 510 .recv = st33zp24_recv, 510 511 .cancel = st33zp24_cancel, ··· 592 591 593 592 tpm_gen_interrupt(chip); 594 593 } 595 - 596 - tpm_get_timeouts(chip); 597 - tpm_do_selftest(chip); 598 594 599 595 return tpm_chip_register(chip); 600 596 _tpm_clean_answer:
+9
drivers/char/tpm/tpm-chip.c
··· 354 354 { 355 355 int rc; 356 356 357 + if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) { 358 + if (chip->flags & TPM_CHIP_FLAG_TPM2) 359 + rc = tpm2_auto_startup(chip); 360 + else 361 + rc = tpm1_auto_startup(chip); 362 + if (rc) 363 + return rc; 364 + } 365 + 357 366 rc = tpm1_chip_register(chip); 358 367 if (rc) 359 368 return rc;
+27
drivers/char/tpm/tpm-interface.c
··· 843 843 } 844 844 EXPORT_SYMBOL_GPL(tpm_do_selftest); 845 845 846 + /** 847 + * tpm1_auto_startup - Perform the standard automatic TPM initialization 848 + * sequence 849 + * @chip: TPM chip to use 850 + * 851 + * Returns 0 on success, < 0 in case of fatal error. 852 + */ 853 + int tpm1_auto_startup(struct tpm_chip *chip) 854 + { 855 + int rc; 856 + 857 + rc = tpm_get_timeouts(chip); 858 + if (rc) 859 + goto out; 860 + rc = tpm_do_selftest(chip); 861 + if (rc) { 862 + dev_err(&chip->dev, "TPM self test failed\n"); 863 + goto out; 864 + } 865 + 866 + return rc; 867 + out: 868 + if (rc > 0) 869 + rc = -ENODEV; 870 + return rc; 871 + } 872 + 846 873 int tpm_send(u32 chip_num, void *cmd, size_t buflen) 847 874 { 848 875 struct tpm_chip *chip;
+2 -2
drivers/char/tpm/tpm.h
··· 484 484 const char *desc); 485 485 extern int tpm_get_timeouts(struct tpm_chip *); 486 486 extern void tpm_gen_interrupt(struct tpm_chip *); 487 + int tpm1_auto_startup(struct tpm_chip *chip); 487 488 extern int tpm_do_selftest(struct tpm_chip *); 488 489 extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); 489 490 extern int tpm_pm_suspend(struct device *); ··· 527 526 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, 528 527 u32 *value, const char *desc); 529 528 530 - extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); 529 + int tpm2_auto_startup(struct tpm_chip *chip); 531 530 extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); 532 531 extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); 533 - extern int tpm2_do_selftest(struct tpm_chip *chip); 534 532 extern int tpm2_gen_interrupt(struct tpm_chip *chip); 535 533 extern int tpm2_probe(struct tpm_chip *chip); 536 534 #endif
+42 -4
drivers/char/tpm/tpm2-cmd.c
··· 728 728 * returned it remarks a POSIX error code. If a positive number is returned 729 729 * it remarks a TPM error. 730 730 */ 731 - int tpm2_startup(struct tpm_chip *chip, u16 startup_type) 731 + static int tpm2_startup(struct tpm_chip *chip, u16 startup_type) 732 732 { 733 733 struct tpm2_cmd cmd; 734 734 ··· 738 738 return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 739 739 "attempting to start the TPM"); 740 740 } 741 - EXPORT_SYMBOL_GPL(tpm2_startup); 742 741 743 742 #define TPM2_SHUTDOWN_IN_SIZE \ 744 743 (sizeof(struct tpm_input_header) + \ ··· 853 854 * returned it remarks a POSIX error code. If a positive number is returned 854 855 * it remarks a TPM error. 855 856 */ 856 - int tpm2_do_selftest(struct tpm_chip *chip) 857 + static int tpm2_do_selftest(struct tpm_chip *chip) 857 858 { 858 859 int rc; 859 860 unsigned int loops; ··· 893 894 894 895 return rc; 895 896 } 896 - EXPORT_SYMBOL_GPL(tpm2_do_selftest); 897 897 898 898 /** 899 899 * tpm2_gen_interrupt() - generate an interrupt ··· 940 942 return 0; 941 943 } 942 944 EXPORT_SYMBOL_GPL(tpm2_probe); 945 + 946 + /** 947 + * tpm2_auto_startup - Perform the standard automatic TPM initialization 948 + * sequence 949 + * @chip: TPM chip to use 950 + * 951 + * Returns 0 on success, < 0 in case of fatal error. 952 + */ 953 + int tpm2_auto_startup(struct tpm_chip *chip) 954 + { 955 + int rc; 956 + 957 + rc = tpm_get_timeouts(chip); 958 + if (rc) 959 + goto out; 960 + 961 + rc = tpm2_do_selftest(chip); 962 + if (rc != TPM2_RC_INITIALIZE) { 963 + dev_err(&chip->dev, "TPM self test failed\n"); 964 + goto out; 965 + } 966 + 967 + if (rc == TPM2_RC_INITIALIZE) { 968 + rc = tpm2_startup(chip, TPM2_SU_CLEAR); 969 + if (rc) 970 + goto out; 971 + 972 + rc = tpm2_do_selftest(chip); 973 + if (rc) { 974 + dev_err(&chip->dev, "TPM self test failed\n"); 975 + goto out; 976 + } 977 + } 978 + 979 + return rc; 980 + out: 981 + if (rc > 0) 982 + rc = -ENODEV; 983 + return rc; 984 + }
+1 -9
drivers/char/tpm/tpm_crb.c
··· 188 188 } 189 189 190 190 static const struct tpm_class_ops tpm_crb = { 191 + .flags = TPM_OPS_AUTO_STARTUP, 191 192 .status = crb_status, 192 193 .recv = crb_recv, 193 194 .send = crb_send, ··· 201 200 static int crb_init(struct acpi_device *device, struct crb_priv *priv) 202 201 { 203 202 struct tpm_chip *chip; 204 - int rc; 205 203 206 204 chip = tpmm_chip_alloc(&device->dev, &tpm_crb); 207 205 if (IS_ERR(chip)) ··· 209 209 dev_set_drvdata(&chip->dev, priv); 210 210 chip->acpi_dev_handle = device->handle; 211 211 chip->flags = TPM_CHIP_FLAG_TPM2; 212 - 213 - rc = tpm_get_timeouts(chip); 214 - if (rc) 215 - return rc; 216 - 217 - rc = tpm2_do_selftest(chip); 218 - if (rc) 219 - return rc; 220 212 221 213 return tpm_chip_register(chip); 222 214 }
+1 -5
drivers/char/tpm/tpm_i2c_atmel.c
··· 141 141 } 142 142 143 143 static const struct tpm_class_ops i2c_atmel = { 144 + .flags = TPM_OPS_AUTO_STARTUP, 144 145 .status = i2c_atmel_read_status, 145 146 .recv = i2c_atmel_recv, 146 147 .send = i2c_atmel_send, ··· 180 179 /* There is no known way to probe for this device, and all version 181 180 * information seems to be read via TPM commands. Thus we rely on the 182 181 * TPM startup process in the common code to detect the device. */ 183 - if (tpm_get_timeouts(chip)) 184 - return -ENODEV; 185 - 186 - if (tpm_do_selftest(chip)) 187 - return -ENODEV; 188 182 189 183 return tpm_chip_register(chip); 190 184 }
+1 -3
drivers/char/tpm/tpm_i2c_infineon.c
··· 567 567 } 568 568 569 569 static const struct tpm_class_ops tpm_tis_i2c = { 570 + .flags = TPM_OPS_AUTO_STARTUP, 570 571 .status = tpm_tis_i2c_status, 571 572 .recv = tpm_tis_i2c_recv, 572 573 .send = tpm_tis_i2c_send, ··· 619 618 dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); 620 619 621 620 tpm_dev.chip = chip; 622 - 623 - tpm_get_timeouts(chip); 624 - tpm_do_selftest(chip); 625 621 626 622 return tpm_chip_register(chip); 627 623 out_release:
+1 -6
drivers/char/tpm/tpm_i2c_nuvoton.c
··· 461 461 } 462 462 463 463 static const struct tpm_class_ops tpm_i2c = { 464 + .flags = TPM_OPS_AUTO_STARTUP, 464 465 .status = i2c_nuvoton_read_status, 465 466 .recv = i2c_nuvoton_recv, 466 467 .send = i2c_nuvoton_send, ··· 607 606 } 608 607 } 609 608 } 610 - 611 - if (tpm_get_timeouts(chip)) 612 - return -ENODEV; 613 - 614 - if (tpm_do_selftest(chip)) 615 - return -ENODEV; 616 609 617 610 return tpm_chip_register(chip); 618 611 }
+1 -23
drivers/char/tpm/tpm_tis_core.c
··· 638 638 EXPORT_SYMBOL_GPL(tpm_tis_remove); 639 639 640 640 static const struct tpm_class_ops tpm_tis = { 641 + .flags = TPM_OPS_AUTO_STARTUP, 641 642 .status = tpm_tis_status, 642 643 .recv = tpm_tis_recv, 643 644 .send = tpm_tis_send, ··· 771 770 "TPM interrupt not working, polling instead\n"); 772 771 } else { 773 772 tpm_tis_probe_irq(chip, intmask); 774 - } 775 - } 776 - 777 - if (chip->flags & TPM_CHIP_FLAG_TPM2) { 778 - rc = tpm2_do_selftest(chip); 779 - if (rc == TPM2_RC_INITIALIZE) { 780 - dev_warn(dev, "Firmware has not started TPM\n"); 781 - rc = tpm2_startup(chip, TPM2_SU_CLEAR); 782 - if (!rc) 783 - rc = tpm2_do_selftest(chip); 784 - } 785 - 786 - if (rc) { 787 - dev_err(dev, "TPM self test failed\n"); 788 - if (rc > 0) 789 - rc = -ENODEV; 790 - goto out_err; 791 - } 792 - } else { 793 - if (tpm_do_selftest(chip)) { 794 - dev_err(dev, "TPM self test failed\n"); 795 - rc = -ENODEV; 796 - goto out_err; 797 773 } 798 774 } 799 775
+1 -8
drivers/char/tpm/tpm_vtpm_proxy.c
··· 346 346 } 347 347 348 348 static const struct tpm_class_ops vtpm_proxy_tpm_ops = { 349 + .flags = TPM_OPS_AUTO_STARTUP, 349 350 .recv = vtpm_proxy_tpm_op_recv, 350 351 .send = vtpm_proxy_tpm_op_send, 351 352 .cancel = vtpm_proxy_tpm_op_cancel, ··· 366 365 struct proxy_dev *proxy_dev = container_of(work, struct proxy_dev, 367 366 work); 368 367 int rc; 369 - 370 - if (proxy_dev->flags & VTPM_PROXY_FLAG_TPM2) 371 - rc = tpm2_startup(proxy_dev->chip, TPM2_SU_CLEAR); 372 - else 373 - rc = tpm_get_timeouts(proxy_dev->chip); 374 - 375 - if (rc) 376 - goto err; 377 368 378 369 rc = tpm_chip_register(proxy_dev->chip); 379 370 if (rc)
+5
include/linux/tpm.h
··· 33 33 struct trusted_key_payload; 34 34 struct trusted_key_options; 35 35 36 + enum TPM_OPS_FLAGS { 37 + TPM_OPS_AUTO_STARTUP = BIT(0), 38 + }; 39 + 36 40 struct tpm_class_ops { 41 + unsigned int flags; 37 42 const u8 req_complete_mask; 38 43 const u8 req_complete_val; 39 44 bool (*req_canceled)(struct tpm_chip *chip, u8 status);