diff options
author | James Morris <jmorris@namei.org> | 2010-05-17 18:57:00 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-05-17 18:57:00 -0400 |
commit | 539c99fd7fc28f8db257c713c10fb4aceadf8887 (patch) | |
tree | e603e48ac816cde56e4872e0f7bcdfe7bd33f3b3 /drivers/char | |
parent | ba2e1c5f25a99dec3873745031ad23ce3fd79bff (diff) | |
parent | 4d09ec0f705cf88a12add029c058b53f288cfaa2 (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/Kconfig | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.c | 47 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 40 |
3 files changed, 65 insertions, 28 deletions
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index f5fc64f89c5c..4dc338f3d1aa 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -17,14 +17,16 @@ menuconfig TCG_TPM | |||
17 | obtained at: <http://sourceforge.net/projects/trousers>. To | 17 | obtained at: <http://sourceforge.net/projects/trousers>. To |
18 | compile this driver as a module, choose M here; the module | 18 | compile this driver as a module, choose M here; the module |
19 | will be called tpm. If unsure, say N. | 19 | will be called tpm. If unsure, say N. |
20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | 20 | Notes: |
21 | 1) For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | ||
21 | and CONFIG_PNPACPI. | 22 | and CONFIG_PNPACPI. |
23 | 2) Without ACPI enabled, the BIOS event log won't be accessible, | ||
24 | which is required to validate the PCR 0-7 values. | ||
22 | 25 | ||
23 | if TCG_TPM | 26 | if TCG_TPM |
24 | 27 | ||
25 | config TCG_TIS | 28 | config TCG_TIS |
26 | tristate "TPM Interface Specification 1.2 Interface" | 29 | tristate "TPM Interface Specification 1.2 Interface" |
27 | depends on PNP | ||
28 | ---help--- | 30 | ---help--- |
29 | If you have a TPM security chip that is compliant with the | 31 | If you have a TPM security chip that is compliant with the |
30 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | 32 | TCG TIS 1.2 TPM specification say Yes and it will be accessible |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 068c816e6942..05ad4a17a28f 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1068,6 +1068,27 @@ void tpm_remove_hardware(struct device *dev) | |||
1068 | } | 1068 | } |
1069 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); | 1069 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); |
1070 | 1070 | ||
1071 | #define TPM_ORD_SAVESTATE cpu_to_be32(152) | ||
1072 | #define SAVESTATE_RESULT_SIZE 10 | ||
1073 | |||
1074 | static struct tpm_input_header savestate_header = { | ||
1075 | .tag = TPM_TAG_RQU_COMMAND, | ||
1076 | .length = cpu_to_be32(10), | ||
1077 | .ordinal = TPM_ORD_SAVESTATE | ||
1078 | }; | ||
1079 | |||
1080 | /* Bug workaround - some TPM's don't flush the most | ||
1081 | * recently changed pcr on suspend, so force the flush | ||
1082 | * with an extend to the selected _unused_ non-volatile pcr. | ||
1083 | */ | ||
1084 | static int tpm_suspend_pcr; | ||
1085 | static int __init tpm_suspend_setup(char *str) | ||
1086 | { | ||
1087 | get_option(&str, &tpm_suspend_pcr); | ||
1088 | return 1; | ||
1089 | } | ||
1090 | __setup("tpm_suspend_pcr=", tpm_suspend_setup); | ||
1091 | |||
1071 | /* | 1092 | /* |
1072 | * We are about to suspend. Save the TPM state | 1093 | * We are about to suspend. Save the TPM state |
1073 | * so that it can be restored. | 1094 | * so that it can be restored. |
@@ -1075,17 +1096,29 @@ EXPORT_SYMBOL_GPL(tpm_remove_hardware); | |||
1075 | int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) | 1096 | int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) |
1076 | { | 1097 | { |
1077 | struct tpm_chip *chip = dev_get_drvdata(dev); | 1098 | struct tpm_chip *chip = dev_get_drvdata(dev); |
1078 | u8 savestate[] = { | 1099 | struct tpm_cmd_t cmd; |
1079 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 1100 | int rc; |
1080 | 0, 0, 0, 10, /* blob length (in bytes) */ | 1101 | |
1081 | 0, 0, 0, 152 /* TPM_ORD_SaveState */ | 1102 | u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; |
1082 | }; | ||
1083 | 1103 | ||
1084 | if (chip == NULL) | 1104 | if (chip == NULL) |
1085 | return -ENODEV; | 1105 | return -ENODEV; |
1086 | 1106 | ||
1087 | tpm_transmit(chip, savestate, sizeof(savestate)); | 1107 | /* for buggy tpm, flush pcrs with extend to selected dummy */ |
1088 | return 0; | 1108 | if (tpm_suspend_pcr) { |
1109 | cmd.header.in = pcrextend_header; | ||
1110 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); | ||
1111 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, | ||
1112 | TPM_DIGEST_SIZE); | ||
1113 | rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | ||
1114 | "extending dummy pcr before suspend"); | ||
1115 | } | ||
1116 | |||
1117 | /* now do the actual savestate */ | ||
1118 | cmd.header.in = savestate_header; | ||
1119 | rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, | ||
1120 | "sending savestate before suspend"); | ||
1121 | return rc; | ||
1089 | } | 1122 | } |
1090 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); | 1123 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); |
1091 | 1124 | ||
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 94345994f8a6..24314a9cffe8 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -598,7 +598,7 @@ out_err: | |||
598 | tpm_remove_hardware(chip->dev); | 598 | tpm_remove_hardware(chip->dev); |
599 | return rc; | 599 | return rc; |
600 | } | 600 | } |
601 | 601 | #ifdef CONFIG_PNP | |
602 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | 602 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, |
603 | const struct pnp_device_id *pnp_id) | 603 | const struct pnp_device_id *pnp_id) |
604 | { | 604 | { |
@@ -663,7 +663,7 @@ static struct pnp_driver tis_pnp_driver = { | |||
663 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | 663 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, |
664 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 664 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
665 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 665 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
666 | 666 | #endif | |
667 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) | 667 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) |
668 | { | 668 | { |
669 | return tpm_pm_suspend(&dev->dev, msg); | 669 | return tpm_pm_suspend(&dev->dev, msg); |
@@ -690,21 +690,21 @@ MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); | |||
690 | static int __init init_tis(void) | 690 | static int __init init_tis(void) |
691 | { | 691 | { |
692 | int rc; | 692 | int rc; |
693 | #ifdef CONFIG_PNP | ||
694 | if (!force) | ||
695 | return pnp_register_driver(&tis_pnp_driver); | ||
696 | #endif | ||
693 | 697 | ||
694 | if (force) { | 698 | rc = platform_driver_register(&tis_drv); |
695 | rc = platform_driver_register(&tis_drv); | 699 | if (rc < 0) |
696 | if (rc < 0) | ||
697 | return rc; | ||
698 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | ||
699 | return PTR_ERR(pdev); | ||
700 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | ||
701 | platform_device_unregister(pdev); | ||
702 | platform_driver_unregister(&tis_drv); | ||
703 | } | ||
704 | return rc; | 700 | return rc; |
701 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | ||
702 | return PTR_ERR(pdev); | ||
703 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | ||
704 | platform_device_unregister(pdev); | ||
705 | platform_driver_unregister(&tis_drv); | ||
705 | } | 706 | } |
706 | 707 | return rc; | |
707 | return pnp_register_driver(&tis_pnp_driver); | ||
708 | } | 708 | } |
709 | 709 | ||
710 | static void __exit cleanup_tis(void) | 710 | static void __exit cleanup_tis(void) |
@@ -728,12 +728,14 @@ static void __exit cleanup_tis(void) | |||
728 | list_del(&i->list); | 728 | list_del(&i->list); |
729 | } | 729 | } |
730 | spin_unlock(&tis_lock); | 730 | spin_unlock(&tis_lock); |
731 | 731 | #ifdef CONFIG_PNP | |
732 | if (force) { | 732 | if (!force) { |
733 | platform_device_unregister(pdev); | ||
734 | platform_driver_unregister(&tis_drv); | ||
735 | } else | ||
736 | pnp_unregister_driver(&tis_pnp_driver); | 733 | pnp_unregister_driver(&tis_pnp_driver); |
734 | return; | ||
735 | } | ||
736 | #endif | ||
737 | platform_device_unregister(pdev); | ||
738 | platform_driver_unregister(&tis_drv); | ||
737 | } | 739 | } |
738 | 740 | ||
739 | module_init(init_tis); | 741 | module_init(init_tis); |