Some platforms may desire to pass the event log up to linux in the form of a reserved memory region. Add support for this in the TPM core to find the reserved memory region and map it. Signed-off-by: Eddie James <eajames@xxxxxxxxxxxxx> --- drivers/char/tpm/eventlog/of.c | 38 +++++++++++++++++++++++++++++++++- drivers/char/tpm/tpm-chip.c | 3 ++- include/linux/tpm.h | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/char/tpm/eventlog/of.c b/drivers/char/tpm/eventlog/of.c index a9ce66d09a75..0455d7f61c10 100644 --- a/drivers/char/tpm/eventlog/of.c +++ b/drivers/char/tpm/eventlog/of.c @@ -11,12 +11,48 @@ */ #include <linux/slab.h> +#include <linux/io.h> +#include <linux/ioport.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_reserved_mem.h> #include <linux/tpm_eventlog.h> #include "../tpm.h" #include "common.h" +static int tpm_read_log_memory_region(struct tpm_chip *chip) +{ + struct device_node *node; + struct resource res; + int rc; + + node = of_parse_phandle(chip->dev.parent->of_node, "memory-region", 0); + if (!node) { + dev_info(&chip->dev, "no phandle\n"); + return -ENODEV; + } + + rc = of_address_to_resource(node, 0, &res); + of_node_put(node); + if (rc) { + dev_info(&chip->dev, "no mem\n"); + return rc; + } + + chip->log.bios_event_log = memremap(res.start, resource_size(&res), MEMREMAP_WB); + if (!chip->log.bios_event_log) { + dev_info(&chip->dev, "err memremap\n"); + return -ENOMEM; + } + + chip->log.release = memunmap; + chip->log.bios_event_log_end = chip->log.bios_event_log + resource_size(&res); + + return chip->flags & TPM_CHIP_FLAG_TPM2 ? EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 : + EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; +} + int tpm_read_log_of(struct tpm_chip *chip) { struct device_node *np; @@ -38,7 +74,7 @@ int tpm_read_log_of(struct tpm_chip *chip) sizep = of_get_property(np, "linux,sml-size", NULL); basep = of_get_property(np, "linux,sml-base", NULL); if (sizep == NULL && basep == NULL) - return -ENODEV; + return tpm_read_log_memory_region(chip); if (sizep == NULL || basep == NULL) return -EIO; diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 741d8f3e8fb3..09ea8145d7c6 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -267,7 +267,7 @@ static void tpm_dev_release(struct device *dev) idr_remove(&dev_nums_idr, chip->dev_num); mutex_unlock(&idr_lock); - kfree(chip->log.bios_event_log); + chip->log.release(chip->log.bios_event_log); kfree(chip->work_space.context_buf); kfree(chip->work_space.session_buf); kfree(chip->allocated_banks); @@ -324,6 +324,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, init_rwsem(&chip->ops_sem); chip->ops = ops; + chip->log.release = (void(*)(void *))kfree; mutex_lock(&idr_lock); rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL); diff --git a/include/linux/tpm.h b/include/linux/tpm.h index dfeb25a0362d..f1c0b0eb20a5 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -109,6 +109,7 @@ struct tpm_space { struct tpm_bios_log { void *bios_event_log; void *bios_event_log_end; + void (*release)(void *ptr); }; struct tpm_chip_seqops { -- 2.31.1