If linux,sml-log is available use it to get the TPM log rather than the
pointer found in linux,sml-base. This resolves an issue on PowerVM and KVM
on Power where after a kexec the memory pointed to by linux,sml-base may
have been corrupted. Also, linux,sml-log has replaced linux,sml-base and
linux,sml-size on these two platforms.

Signed-off-by: Stefan Berger <stef...@linux.ibm.com>
---
 drivers/char/tpm/eventlog/of.c | 36 +++++++++++-----------------------
 1 file changed, 11 insertions(+), 25 deletions(-)

diff --git a/drivers/char/tpm/eventlog/of.c b/drivers/char/tpm/eventlog/of.c
index 930fe43d5daf..e37196e64ef1 100644
--- a/drivers/char/tpm/eventlog/of.c
+++ b/drivers/char/tpm/eventlog/of.c
@@ -54,8 +54,8 @@ int tpm_read_log_of(struct tpm_chip *chip)
        const u32 *sizep;
        const u64 *basep;
        struct tpm_bios_log *log;
+       const void *logp;
        u32 size;
-       u64 base;
 
        log = &chip->log;
        if (chip->dev.parent && chip->dev.parent->of_node)
@@ -66,37 +66,23 @@ int tpm_read_log_of(struct tpm_chip *chip)
        if (of_property_read_bool(np, "powered-while-suspended"))
                chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
 
-       sizep = of_get_property(np, "linux,sml-size", NULL);
-       basep = of_get_property(np, "linux,sml-base", NULL);
-       if (sizep == NULL && basep == NULL)
-               return tpm_read_log_memory_region(chip);
-       if (sizep == NULL || basep == NULL)
-               return -EIO;
-
-       /*
-        * For both vtpm/tpm, firmware has log addr and log size in big
-        * endian format. But in case of vtpm, there is a method called
-        * sml-handover which is run during kernel init even before
-        * device tree is setup. This sml-handover function takes care
-        * of endianness and writes to sml-base and sml-size in little
-        * endian format. For this reason, vtpm doesn't need conversion
-        * but physical tpm needs the conversion.
-        */
-       if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0 &&
-           of_property_match_string(np, "compatible", "IBM,vtpm20") < 0) {
+       logp = of_get_property(np, "linux,sml-log", &size);
+       if (logp == NULL) {
+               sizep = of_get_property(np, "linux,sml-size", NULL);
+               basep = of_get_property(np, "linux,sml-base", NULL);
+               if (sizep == NULL && basep == NULL)
+                       return tpm_read_log_memory_region(chip);
+               if (sizep == NULL || basep == NULL)
+                       return -EIO;
+               logp = __va(be64_to_cpup((__force __be64 *)basep));
                size = be32_to_cpup((__force __be32 *)sizep);
-               base = be64_to_cpup((__force __be64 *)basep);
-       } else {
-               size = *sizep;
-               base = *basep;
        }
-
        if (size == 0) {
                dev_warn(&chip->dev, "%s: Event log area empty\n", __func__);
                return -EIO;
        }
 
-       log->bios_event_log = devm_kmemdup(&chip->dev, __va(base), size, 
GFP_KERNEL);
+       log->bios_event_log = devm_kmemdup(&chip->dev, logp, size, GFP_KERNEL);
        if (!log->bios_event_log)
                return -ENOMEM;
 
-- 
2.43.0

Reply via email to