@@ -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);
@@ -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,
@@ -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 */
};
/**
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(+)