For TPM2-based systems, retrieve the TCG log from the TPM2 ACPI table. Signed-off-by: Jordan Hand <jordanhan...@gmail.com> --- drivers/char/tpm/eventlog/acpi.c | 67 +++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 19 deletions(-)
diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c index 63ada5e53f13..942d282e2738 100644 --- a/drivers/char/tpm/eventlog/acpi.c +++ b/drivers/char/tpm/eventlog/acpi.c @@ -41,17 +41,31 @@ struct acpi_tcpa { }; }; +struct acpi_tpm2 { + struct acpi_table_header hdr; + u16 platform_class; + u16 reserved; + u64 control_area_addr; + u32 start_method; + u8 start_method_params[12]; + u32 log_max_len; + u64 log_start_addr; +} __packed; + /* read binary bios log */ int tpm_read_log_acpi(struct tpm_chip *chip) { - struct acpi_tcpa *buff; + struct acpi_table_header *buff; + struct acpi_tcpa *tcpa; + struct acpi_tpm2 *tpm2; + acpi_status status; void __iomem *virt; u64 len, start; + int log_type; struct tpm_bios_log *log; - - if (chip->flags & TPM_CHIP_FLAG_TPM2) - return -ENODEV; + bool is_tpm2 = chip->flags & TPM_CHIP_FLAG_TPM2; + acpi_string table_sig; log = &chip->log; @@ -61,26 +75,41 @@ int tpm_read_log_acpi(struct tpm_chip *chip) if (!chip->acpi_dev_handle) return -ENODEV; - /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ - status = acpi_get_table(ACPI_SIG_TCPA, 1, - (struct acpi_table_header **)&buff); + /* Find TCPA or TPM2 entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ + table_sig = is_tpm2 ? ACPI_SIG_TPM2 : ACPI_SIG_TCPA; + status = acpi_get_table(table_sig, 1, &buff); if (ACPI_FAILURE(status)) return -ENODEV; - switch(buff->platform_class) { - case BIOS_SERVER: - len = buff->server.log_max_len; - start = buff->server.log_start_addr; - break; - case BIOS_CLIENT: - default: - len = buff->client.log_max_len; - start = buff->client.log_start_addr; - break; + /* If log_max_len and log_start_addr are set, start_method_params will + * be 12 bytes, according to TCG ACPI spec. If start_method_params is + * fewer than 12 bytes, the TCG log is not available + */ + if (is_tpm2 && (buff->length == sizeof(acpi_tpm2))) { + tpm2 = (struct acpi_tpm2 *)buff; + len = tpm2->log_max_len; + start = tpm2->log_start_addr; + log_type = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; + } else { + tcpa = (struct acpi_tcpa *)buff; + switch (tcpa->platform_class) { + case BIOS_SERVER: + len = tcpa->server.log_max_len; + start = tcpa->server.log_start_addr; + break; + case BIOS_CLIENT: + default: + len = tcpa->client.log_max_len; + start = tcpa->client.log_start_addr; + break; + } + log_type = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; } + if (!len) { - dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__); + dev_warn(&chip->dev, "%s: %s log area empty\n", + table_sig, __func__); return -EIO; } @@ -98,7 +127,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip) memcpy_fromio(log->bios_event_log, virt, len); acpi_os_unmap_iomem(virt, len); - return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; + return log_type; err: kfree(log->bios_event_log); -- 2.20.1