Skip to contentSkip to conversation

tpm: Add reserved memory event log

PATCH In review Eddie James 2 participants 5 messages Jan 26, 2023

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v3 cover tpm: Add reserved memory event log

Some platforms may desire to pass the event log up to Linux in the form of a reserved memory region. In particular, this is desirable for embedded systems or baseboard management controllers (BMCs) booting with U-Boot. IBM OpenBMC BMCs will be the first user. Add support for the reserved memory in the TPM core to find the region and map it.
Since the memory is mapped, not allocated, change all the event log allocation functions to managed allocations so that the memory can be either automatically freed or unmapped.

Changes since v2:
- Improve commit message for patch 2

Changes since v1:
- Use managed memory

Eddie James (2):
tpm: Use managed allocation for bios event log
tpm: Add reserved memory event log

 drivers/char/tpm/eventlog/acpi.c |  5 ++--
 drivers/char/tpm/eventlog/efi.c  | 13 +++++-----
 drivers/char/tpm/eventlog/of.c   | 41 ++++++++++++++++++++++++++++++--
 drivers/char/tpm/tpm-chip.c      |  1 -
 4 files changed, 49 insertions(+), 11 deletions(-)
Signature · 1 line
2.31.1
#1 lore raw

PATCH v3 1/2 tpm: Use managed allocation for bios event log

Since the bios event log is freed in the device release function, let devres handle the deallocation. This will allow other memory allocation/mapping functions to be used for the bios event log.

---
 drivers/char/tpm/eventlog/acpi.c |  5 +++--
 drivers/char/tpm/eventlog/efi.c  | 13 +++++++------
 drivers/char/tpm/eventlog/of.c   |  3 ++-
 drivers/char/tpm/tpm-chip.c      |  1 -
 4 files changed, 12 insertions(+), 10 deletions(-)
drivers/char/tpm/eventlog/acpi.c +3 -2
index 0913d3eb8d51..40360e599bc3 100644
@@ -14,6 +14,7 @@
  * Access to the event log extended by the TCG BIOS of PC platform
  */
 
+#include <linux/device.h>
 #include <linux/seq_file.h>
 #include <linux/fs.h>
 #include <linux/security.h>
@@ -135,7 +136,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
 	}
 
 	/* malloc EventLog space */
-	log->bios_event_log = kmalloc(len, GFP_KERNEL);
+	log->bios_event_log = devm_kmalloc(&chip->dev, len, GFP_KERNEL);
 	if (!log->bios_event_log)
 		return -ENOMEM;
 
@@ -160,7 +161,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
 	return format;
 
 err:
-	kfree(log->bios_event_log);
+	devm_kfree(&chip->dev, log->bios_event_log);
 	log->bios_event_log = NULL;
 	return ret;
 }
drivers/char/tpm/eventlog/efi.c +7 -6
index e6cb9d525e30..4e9d7c2bf32e 100644
@@ -6,6 +6,7 @@
  *      Thiebaud Weksteen <[email protected]>
  */
 
+#include <linux/device.h>
 #include <linux/efi.h>
 #include <linux/tpm_eventlog.h>
 
@@ -55,7 +56,7 @@ int tpm_read_log_efi(struct tpm_chip *chip)
 	}
 
 	/* malloc EventLog space */
-	log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL);
+	log->bios_event_log = devm_kmemdup(&chip->dev, log_tbl->log, log_size, GFP_KERNEL);
 	if (!log->bios_event_log) {
 		ret = -ENOMEM;
 		goto out;
@@ -76,7 +77,7 @@ int tpm_read_log_efi(struct tpm_chip *chip)
 			     MEMREMAP_WB);
 	if (!final_tbl) {
 		pr_err("Could not map UEFI TPM final log\n");
-		kfree(log->bios_event_log);
+		devm_kfree(&chip->dev, log->bios_event_log);
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -91,11 +92,11 @@ int tpm_read_log_efi(struct tpm_chip *chip)
 	 * Allocate memory for the 'combined log' where we will append the
 	 * 'final events log' to.
 	 */
-	tmp = krealloc(log->bios_event_log,
-		       log_size + final_events_log_size,
-		       GFP_KERNEL);
+	tmp = devm_krealloc(&chip->dev, log->bios_event_log,
+			    log_size + final_events_log_size,
+			    GFP_KERNEL);
 	if (!tmp) {
-		kfree(log->bios_event_log);
+		devm_kfree(&chip->dev, log->bios_event_log);
 		ret = -ENOMEM;
 		goto out;
 	}
drivers/char/tpm/eventlog/of.c +2 -1
index a9ce66d09a75..741ab2204b11 100644
@@ -10,6 +10,7 @@
  * Read the event log created by the firmware on PPC64
  */
 
+#include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/tpm_eventlog.h>
@@ -65,7 +66,7 @@ int tpm_read_log_of(struct tpm_chip *chip)
 		return -EIO;
 	}
 
-	log->bios_event_log = kmemdup(__va(base), size, GFP_KERNEL);
+	log->bios_event_log = devm_kmemdup(&chip->dev, __va(base), size, GFP_KERNEL);
 	if (!log->bios_event_log)
 		return -ENOMEM;
 
drivers/char/tpm/tpm-chip.c +0 -1
index 741d8f3e8fb3..b99f55f2d4fd 100644
@@ -267,7 +267,6 @@ 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);
 	kfree(chip->work_space.context_buf);
 	kfree(chip->work_space.session_buf);
 	kfree(chip->allocated_banks);
Signature · 1 line
2.31.1
#2 lore raw

PATCH v3 2/2 tpm: Add reserved memory event log

In reply to Eddie James

Some platforms may desire to pass the event log up to Linux in the form of a reserved memory region. In particular, this is desirable for embedded systems or baseboard management controllers (BMCs) booting with U-Boot. IBM OpenBMC BMCs will be the first user. Add support for the reserved memory in the TPM core to find the region and map it.

---
 drivers/char/tpm/eventlog/of.c | 38 +++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)
drivers/char/tpm/eventlog/of.c +37 -1
index 741ab2204b11..c815cadf00a4 100644
@@ -12,12 +12,48 @@
 
 #include <linux/device.h>
 #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 = devm_memremap(&chip->dev, res.start, resource_size(&res),
+						 MEMREMAP_WB);
+	if (!chip->log.bios_event_log) {
+		dev_info(&chip->dev, "err memremap\n");
+		return -ENOMEM;
+	}
+
+	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;
@@ -39,7 +75,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;
 
Signature · 1 line
2.31.1
maintainer Reviewed-by on v3 2/2
#3 lore raw
Quoted 77 lines · Eddie James

Some platforms may desire to pass the event log up to Linux in the form of a reserved memory region. In particular, this is desirable for embedded systems or baseboard management controllers (BMCs) booting with U-Boot. IBM OpenBMC BMCs will be the first user. Add support for the reserved memory in the TPM core to find the region and map it.

---
 drivers/char/tpm/eventlog/of.c | 38 +++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)
drivers/char/tpm/eventlog/of.c +37 -1
index 741ab2204b11..c815cadf00a4 100644
@@ -12,12 +12,48 @@
 
 #include <linux/device.h>
 #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 = devm_memremap(&chip->dev, res.start, resource_size(&res),
+						 MEMREMAP_WB);
+	if (!chip->log.bios_event_log) {
+		dev_info(&chip->dev, "err memremap\n");
+		return -ENOMEM;
+	}
+
+	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;
@@ -39,7 +75,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;
 
Signature · 1 line
2.31.1

BR, Jarkko

maintainer
#4 lore raw
Quoted 75 lines · Jarkko Sakkinen
Quoted 74 lines · Eddie James

Some platforms may desire to pass the event log up to Linux in the form of a reserved memory region. In particular, this is desirable for embedded systems or baseboard management controllers (BMCs) booting with U-Boot. IBM OpenBMC BMCs will be the first user. Add support for the reserved memory in the TPM core to find the region and map it.

---
 drivers/char/tpm/eventlog/of.c | 38 +++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)
drivers/char/tpm/eventlog/of.c +37 -1
index 741ab2204b11..c815cadf00a4 100644
@@ -12,12 +12,48 @@
 
 #include <linux/device.h>
 #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 = devm_memremap(&chip->dev, res.start, resource_size(&res),
+						 MEMREMAP_WB);
+	if (!chip->log.bios_event_log) {
+		dev_info(&chip->dev, "err memremap\n");
+		return -ENOMEM;
+	}
+
+	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;
@@ -39,7 +75,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;
 
Quoted 5 lines
Quoted 3 lines
Signature · 1 line
2.31.1

I applied the patches.

BR, Jarkko