diff mbox series

[106/108] acpi: tpm: Add a TPM2 table

Message ID 20200126220508.106.I01fe3266661295f6b3a4f1aebefb75d3838bdb32@changeid
State Accepted
Commit 9179c3571ce587e96b957d0da8f0e4dcabc8d293
Headers show
Series RFC: dm: Add programatic generation of ACPI tables | expand

Commit Message

Simon Glass Jan. 27, 2020, 5:06 a.m. UTC
This provides information about a v2 TPM in the system. Generate this
table if the TPM is present.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 arch/x86/lib/acpi_table.c | 74 +++++++++++++++++++++++++++++++++++++++
 include/acpi_table.h      | 11 ++++++
 include/bloblist.h        |  1 +
 3 files changed, 86 insertions(+)
diff mbox series

Patch

diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index e757dc419a..1d12e58508 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -10,6 +10,7 @@ 
 #include <acpigen.h>
 #include <acpi_device.h>
 #include <acpi_table.h>
+#include <bloblist.h>
 #include <cpu.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
@@ -276,6 +277,64 @@  static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
 	header->checksum = table_compute_checksum((void *)mcfg, header->length);
 }
 
+static int get_tpm2_log(void **ptrp, int *sizep)
+{
+	const int tpm2_default_log_len = 0x10000;
+	int size;
+	int ret;
+
+	*sizep = 0;
+	size = tpm2_default_log_len;
+	ret = bloblist_ensure_size_ret(BLOBLISTT_TPM2_TCG_LOG, &size, ptrp);
+	if (ret)
+		return log_msg_ret("blob", ret);
+	*sizep = size;
+
+	return 0;
+}
+
+static int acpi_create_tpm2(struct acpi_tpm2 *tpm2)
+{
+	struct acpi_table_header *header = &tpm2->header;
+	int tpm2_log_len;
+	void *lasa;
+	int ret;
+
+	memset((void *)tpm2, 0, sizeof(struct acpi_tpm2));
+
+	/*
+	 * Some payloads like SeaBIOS depend on log area to use TPM2.
+	 * Get the memory size and address of TPM2 log area or initialize it.
+	 */
+	ret = get_tpm2_log(&lasa, &tpm2_log_len);
+	if (ret)
+		return ret;
+
+	/* Fill out header fields. */
+	acpi_fill_header(header, "TPM2");
+	memcpy(header->aslc_id, ASLC_ID, 4);
+
+	header->length = sizeof(struct acpi_tpm2);
+	header->revision = acpi_get_table_revision(ACPITAB_TPM2);
+
+	/* Hard to detect for coreboot. Just set it to 0 */
+	tpm2->platform_class = 0;
+
+	/* Must be set to 0 for FIFO-interface support */
+	tpm2->control_area = 0;
+	tpm2->start_method = 6;
+	memset(tpm2->msp, 0, sizeof(tpm2->msp));
+
+	/* Fill the log area size and start address fields. */
+	tpm2->laml = tpm2_log_len;
+	tpm2->lasa = (uintptr_t)lasa;
+
+	/* Calculate checksum. */
+	header->checksum = table_compute_checksum((void *)tpm2, header->length);
+
+	return 0;
+}
+
 __weak u32 acpi_fill_csrt(u32 current)
 {
 	return current;
@@ -768,6 +827,21 @@  ulong write_acpi_tables(ulong start_addr)
 	acpi_inc_align(ctx, mcfg->header.length);
 	acpi_add_table(ctx, mcfg);
 
+	if (IS_ENABLED(CONFIG_TPM_V2)) {
+		struct acpi_tpm2 *tpm2;
+		int ret;
+
+		debug("ACPI:    * TPM2\n");
+		tpm2 = (struct acpi_tpm2 *)ctx->current;
+		ret = acpi_create_tpm2(tpm2);
+		if (!ret) {
+			acpi_inc_align(ctx, tpm2->header.length);
+			acpi_add_table(ctx, tpm2);
+		} else {
+			log_warning("TPM2 table creation failed\n");
+		}
+	}
+
 	debug("ACPI:    * MADT\n");
 	madt = ctx->current;
 	acpi_create_madt(madt);
diff --git a/include/acpi_table.h b/include/acpi_table.h
index 17f2a90af9..3d51942d32 100644
--- a/include/acpi_table.h
+++ b/include/acpi_table.h
@@ -104,6 +104,17 @@  struct __packed acpi_hpet {
 	u8 attributes;
 };
 
+struct __packed acpi_tpm2 {
+	struct acpi_table_header header;
+	u16 platform_class;
+	u8  reserved[2];
+	u64 control_area;
+	u32 start_method;
+	u8  msp[12];
+	u32 laml;
+	u64 lasa;
+};
+
 /* FADT Preferred Power Management Profile */
 enum acpi_pm_profile {
 	ACPI_PM_UNSPECIFIED = 0,
diff --git a/include/bloblist.h b/include/bloblist.h
index 7c5b93be4c..d8dccf91fc 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -33,6 +33,7 @@  enum bloblist_tag_t {
 	 * Sleeping table. This forms part of the ACPI tables passed to Linux.
 	 */
 	BLOBLISTT_ACPI_GNVS,
+	BLOBLISTT_TPM2_TCG_LOG,		/* TPM v2 log space */
 };
 
 /**