diff mbox series

[v4] tpm: Parse event log from TPM2 ACPI table

Message ID 20190831051027.11544-1-jorhand@linux.microsoft.com (mailing list archive)
State New, archived
Headers show
Series [v4] tpm: Parse event log from TPM2 ACPI table | expand

Commit Message

Jordan Hand Aug. 31, 2019, 5:10 a.m. UTC
For systems with a TPM2 chip which use ACPI to expose event logs, retrieve the
crypto-agile event log from the TPM2 ACPI table. The TPM2 table is defined
in section 7.3 of the TCG ACPI Specification (see link).

The TPM2 table is used by SeaBIOS in place of the TCPA table when the system's
TPM is version 2.0 to denote (among other metadata) the location of the
crypto-agile log.

Link: https://trustedcomputinggroup.org/resource/tcg-acpi-specification/
Signed-off-by: Jordan Hand <jorhand@linux.microsoft.com>
---
 drivers/char/tpm/eventlog/acpi.c | 60 ++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 19 deletions(-)

Comments

Jarkko Sakkinen Sept. 2, 2019, 1:46 p.m. UTC | #1
On Fri, Aug 30, 2019 at 10:10:27PM -0700, Jordan Hand wrote:
> For systems with a TPM2 chip which use ACPI to expose event logs, retrieve the
> crypto-agile event log from the TPM2 ACPI table. The TPM2 table is defined
> in section 7.3 of the TCG ACPI Specification (see link).
> 
> The TPM2 table is used by SeaBIOS in place of the TCPA table when the system's
> TPM is version 2.0 to denote (among other metadata) the location of the
> crypto-agile log.
> 
> Link: https://trustedcomputinggroup.org/resource/tcg-acpi-specification/
> Signed-off-by: Jordan Hand <jorhand@linux.microsoft.com>

Where is the changelog for v2 and v3 i.e. what happened in those
updates?

/Jarkko
Jerry Snitselaar Sept. 3, 2019, 6:27 p.m. UTC | #2
On Fri Aug 30 19, Jordan Hand wrote:
>For systems with a TPM2 chip which use ACPI to expose event logs, retrieve the
>crypto-agile event log from the TPM2 ACPI table. The TPM2 table is defined
>in section 7.3 of the TCG ACPI Specification (see link).
>
>The TPM2 table is used by SeaBIOS in place of the TCPA table when the system's
>TPM is version 2.0 to denote (among other metadata) the location of the
>crypto-agile log.
>
>Link: https://trustedcomputinggroup.org/resource/tcg-acpi-specification/
>Signed-off-by: Jordan Hand <jorhand@linux.microsoft.com>
>---
> drivers/char/tpm/eventlog/acpi.c | 60 ++++++++++++++++++++++----------
> 1 file changed, 41 insertions(+), 19 deletions(-)
>
>diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c
>index 63ada5e53f13..38a8bcec1dd5 100644
>--- a/drivers/char/tpm/eventlog/acpi.c
>+++ b/drivers/char/tpm/eventlog/acpi.c
>@@ -41,17 +41,23 @@ struct acpi_tcpa {
> 	};
> };
>
>+/* If an event log is present, the TPM2 ACPI table will contain the full
>+ * trailer
>+ */
>+
> /* 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_trailer *tpm2_trailer;
> 	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 +67,42 @@ 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 (!is_tpm2) {
>+		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;
>+	} else if (buff->length ==
>+		   sizeof(struct acpi_table_tpm2) +
>+		   sizeof(struct acpi_tpm2_trailer)) {
>+		tpm2_trailer = (struct acpi_tpm2_trailer *)buff;
>+
>+		len = tpm2_trailer.minimum_log_length;
>+		start = tpm2_trailer.log_address;

Are your builds not failing here? Both v3 and v4 have this.

>+		log_type = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
>+	} else {
>+		return -ENODEV;
> 	}
>+
> 	if (!len) {
>-		dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
>+		dev_warn(&chip->dev, "%s: %s log area empty\n",
>+			 __func__, table_sig);
> 		return -EIO;
> 	}
>
>@@ -98,7 +120,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
>
Jordan Hand Sept. 3, 2019, 7:15 p.m. UTC | #3
On 9/3/19 11:27 AM, Jerry Snitselaar wrote:
>> +        len = tpm2_trailer.minimum_log_length;
>> +        start = tpm2_trailer.log_address;
> 
> Are your builds not failing here? Both v3 and v4 have this.
> 

Ya, I saw the kbuild bot failure and fixed in v5. I'm not entirely sure
why I didn't catch it locally. Maybe a was compiling against the wrong
tree or something silly like that.

Thanks,
Jordan
diff mbox series

Patch

diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c
index 63ada5e53f13..38a8bcec1dd5 100644
--- a/drivers/char/tpm/eventlog/acpi.c
+++ b/drivers/char/tpm/eventlog/acpi.c
@@ -41,17 +41,23 @@  struct acpi_tcpa {
 	};
 };
 
+/* If an event log is present, the TPM2 ACPI table will contain the full
+ * trailer
+ */
+
 /* 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_trailer *tpm2_trailer;
 	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 +67,42 @@  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 (!is_tpm2) {
+		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;
+	} else if (buff->length ==
+		   sizeof(struct acpi_table_tpm2) +
+		   sizeof(struct acpi_tpm2_trailer)) {
+		tpm2_trailer = (struct acpi_tpm2_trailer *)buff;
+
+		len = tpm2_trailer.minimum_log_length;
+		start = tpm2_trailer.log_address;
+		log_type = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
+	} else {
+		return -ENODEV;
 	}
+
 	if (!len) {
-		dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
+		dev_warn(&chip->dev, "%s: %s log area empty\n",
+			 __func__, table_sig);
 		return -EIO;
 	}
 
@@ -98,7 +120,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);