summaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm
diff options
context:
space:
mode:
authorNayna Jain <nayna@linux.vnet.ibm.com>2017-01-23 02:26:26 -0500
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2017-02-03 15:03:14 -0500
commite46e22f12b19f0068b02afcf6edb716b4f49934f (patch)
treee56538bada035a1d05b6ca606f3ea07184b314b8 /drivers/char/tpm
parentc1f92b4b04ad7006bdcbd1d5bb63f2864b06b7f8 (diff)
tpm: enhance read_log_of() to support Physical TPM event log
Physical TPMs use Open Firmware Device Tree bindings that are similar to the IBM Power virtual TPM to support event log. However, these properties store the values in different endianness for Physical and Virtual TPM. This patch fixes the endianness issue by doing appropriate conversion based on Physical or Virtual TPM. Signed-off-by: Nayna Jain <nayna@linux.vnet.ibm.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Kenneth Goldman <kgold@linux.vnet.ibm.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Diffstat (limited to 'drivers/char/tpm')
-rw-r--r--drivers/char/tpm/tpm_of.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c
index 7dee42d7b5e0..de57d4ac8901 100644
--- a/drivers/char/tpm/tpm_of.c
+++ b/drivers/char/tpm/tpm_of.c
@@ -27,6 +27,8 @@ int tpm_read_log_of(struct tpm_chip *chip)
27 const u32 *sizep; 27 const u32 *sizep;
28 const u64 *basep; 28 const u64 *basep;
29 struct tpm_bios_log *log; 29 struct tpm_bios_log *log;
30 u32 size;
31 u64 base;
30 32
31 log = &chip->log; 33 log = &chip->log;
32 if (chip->dev.parent && chip->dev.parent->of_node) 34 if (chip->dev.parent && chip->dev.parent->of_node)
@@ -41,18 +43,35 @@ int tpm_read_log_of(struct tpm_chip *chip)
41 if (sizep == NULL || basep == NULL) 43 if (sizep == NULL || basep == NULL)
42 return -EIO; 44 return -EIO;
43 45
44 if (*sizep == 0) { 46 /*
47 * For both vtpm/tpm, firmware has log addr and log size in big
48 * endian format. But in case of vtpm, there is a method called
49 * sml-handover which is run during kernel init even before
50 * device tree is setup. This sml-handover function takes care
51 * of endianness and writes to sml-base and sml-size in little
52 * endian format. For this reason, vtpm doesn't need conversion
53 * but physical tpm needs the conversion.
54 */
55 if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0) {
56 size = be32_to_cpup(sizep);
57 base = be64_to_cpup(basep);
58 } else {
59 size = *sizep;
60 base = *basep;
61 }
62
63 if (size == 0) {
45 dev_warn(&chip->dev, "%s: Event log area empty\n", __func__); 64 dev_warn(&chip->dev, "%s: Event log area empty\n", __func__);
46 return -EIO; 65 return -EIO;
47 } 66 }
48 67
49 log->bios_event_log = kmalloc(*sizep, GFP_KERNEL); 68 log->bios_event_log = kmalloc(size, GFP_KERNEL);
50 if (!log->bios_event_log) 69 if (!log->bios_event_log)
51 return -ENOMEM; 70 return -ENOMEM;
52 71
53 log->bios_event_log_end = log->bios_event_log + *sizep; 72 log->bios_event_log_end = log->bios_event_log + size;
54 73
55 memcpy(log->bios_event_log, __va(*basep), *sizep); 74 memcpy(log->bios_event_log, __va(base), size);
56 75
57 return 0; 76 return 0;
58} 77}