git: 5ea98d326830 - main - bhyve/tpm: build TPM2 table by tpm interface

From: Corvin Köhne <corvink_at_FreeBSD.org>
Date: Tue, 20 Jun 2023 09:01:00 UTC
The branch main has been updated by corvink:

URL: https://cgit.FreeBSD.org/src/commit/?id=5ea98d326830f25fdeb6fc6ef46a8bccb829b13c

commit 5ea98d326830f25fdeb6fc6ef46a8bccb829b13c
Author:     Corvin Köhne <corvink@FreeBSD.org>
AuthorDate: 2022-08-29 10:10:43 +0000
Commit:     Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-06-20 08:58:55 +0000

    bhyve/tpm: build TPM2 table by tpm interface
    
    Each tpm has a device specific table. Which table a tpm uses depends on
    the tpm interface.
    
    Reviewed by:            markj
    MFC after:              1 week
    Sponsored by:           Beckhoff Automation GmbH & Co. KG
    Differential Revision:  https://reviews.freebsd.org/D40457
---
 usr.sbin/bhyve/tpm_device.c   | 13 +++++++++++
 usr.sbin/bhyve/tpm_intf.h     |  4 +++-
 usr.sbin/bhyve/tpm_intf_crb.c | 51 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/usr.sbin/bhyve/tpm_device.c b/usr.sbin/bhyve/tpm_device.c
index e1db0bab1ee9..94e9f1ffdc27 100644
--- a/usr.sbin/bhyve/tpm_device.c
+++ b/usr.sbin/bhyve/tpm_device.c
@@ -35,9 +35,22 @@ struct tpm_device {
 	void *intf_sc;
 };
 
+static int
+tpm_build_acpi_table(const struct acpi_device *const dev)
+{
+	const struct tpm_device *const tpm = acpi_device_get_softc(dev);
+
+	if (tpm->intf->build_acpi_table == NULL) {
+		return (0);
+	}
+
+	return (tpm->intf->build_acpi_table(tpm->intf_sc, tpm->vm_ctx));
+}
+
 static const struct acpi_device_emul tpm_acpi_device_emul = {
 	.name = TPM_ACPI_DEVICE_NAME,
 	.hid = TPM_ACPI_HARDWARE_ID,
+	.build_table = tpm_build_acpi_table,
 };
 
 void
diff --git a/usr.sbin/bhyve/tpm_intf.h b/usr.sbin/bhyve/tpm_intf.h
index 7de7bc6d4435..3003d8fbd754 100644
--- a/usr.sbin/bhyve/tpm_intf.h
+++ b/usr.sbin/bhyve/tpm_intf.h
@@ -7,6 +7,8 @@
 
 #pragma once
 
+#include <vmmapi.h>
+
 #include "config.h"
 #include "tpm_device.h"
 
@@ -30,6 +32,6 @@ struct tpm_intf {
 
 	int (*init)(void **sc);
 	void (*deinit)(void *sc);
-	int (*build_acpi_table)(void *sc);
+	int (*build_acpi_table)(void *sc, struct vmctx *vm_ctx);
 };
 #define TPM_INTF_SET(x) DATA_SET(tpm_intf_set, x)
diff --git a/usr.sbin/bhyve/tpm_intf_crb.c b/usr.sbin/bhyve/tpm_intf_crb.c
index 5fd640b2d5c9..b8ae33c5ec0a 100644
--- a/usr.sbin/bhyve/tpm_intf_crb.c
+++ b/usr.sbin/bhyve/tpm_intf_crb.c
@@ -31,12 +31,20 @@
 #define TPM_CRB_ADDRESS 0xFED40000
 #define TPM_CRB_REGS_SIZE 0x1000
 
+#define TPM_CRB_CONTROL_AREA_ADDRESS \
+	(TPM_CRB_ADDRESS + offsetof(struct tpm_crb_regs, ctrl_req))
+#define TPM_CRB_CONTROL_AREA_SIZE TPM_CRB_REGS_SIZE
+
 #define TPM_CRB_DATA_BUFFER_ADDRESS \
 	(TPM_CRB_ADDRESS + offsetof(struct tpm_crb_regs, data_buffer))
 #define TPM_CRB_DATA_BUFFER_SIZE 0xF80
 
 #define TPM_CRB_LOCALITIES_MAX 5
 
+#define TPM_CRB_LOG_AREA_MINIMUM_SIZE (64 * 1024)
+
+#define TPM_CRB_LOG_AREA_FWCFG_NAME "etc/tpm/log"
+
 struct tpm_crb_regs {
 	union tpm_crb_reg_loc_state {
 		struct {
@@ -156,6 +164,7 @@ static_assert(sizeof(struct tpm_crb_regs) == TPM_CRB_REGS_SIZE,
 	} while (0)
 
 struct tpm_crb {
+	uint8_t tpm_log_area[TPM_CRB_LOG_AREA_MINIMUM_SIZE];
 	struct tpm_crb_regs regs;
 };
 
@@ -200,6 +209,13 @@ tpm_crb_init(void **sc)
 	CRB_RSP_SIZE_WRITE(crb->regs, TPM_CRB_DATA_BUFFER_SIZE);
 	CRB_RSP_ADDR_WRITE(crb->regs, TPM_CRB_DATA_BUFFER_ADDRESS);
 
+	error = qemu_fwcfg_add_file(TPM_CRB_LOG_AREA_FWCFG_NAME,
+	    TPM_CRB_LOG_AREA_MINIMUM_SIZE, crb->tpm_log_area);
+	if (error) {
+		warnx("%s: failed to add fwcfg file", __func__);
+		goto err_out;
+	}
+
 	*sc = crb;
 
 	return (0);
@@ -224,9 +240,44 @@ tpm_crb_deinit(void *sc)
 	free(crb);
 }
 
+static int
+tpm_crb_build_acpi_table(void *sc __unused, struct vmctx *vm_ctx)
+{
+	struct basl_table *table;
+
+	BASL_EXEC(basl_table_create(&table, vm_ctx, ACPI_SIG_TPM2,
+	    BASL_TABLE_ALIGNMENT));
+
+	/* Header */
+	BASL_EXEC(basl_table_append_header(table, ACPI_SIG_TPM2, 4, 1));
+	/* Platform Class */
+	BASL_EXEC(basl_table_append_int(table, 0, 2));
+	/* Reserved */
+	BASL_EXEC(basl_table_append_int(table, 0, 2));
+	/* Control Address */
+	BASL_EXEC(
+	    basl_table_append_int(table, TPM_CRB_CONTROL_AREA_ADDRESS, 8));
+	/* Start Method == (7) Command Response Buffer */
+	BASL_EXEC(basl_table_append_int(table, 7, 4));
+	/* Start Method Specific Parameters */
+	uint8_t parameters[12] = { 0 };
+	BASL_EXEC(basl_table_append_bytes(table, parameters, 12));
+	/* Log Area Minimum Length */
+	BASL_EXEC(
+	    basl_table_append_int(table, TPM_CRB_LOG_AREA_MINIMUM_SIZE, 4));
+	/* Log Area Start Address */
+	BASL_EXEC(
+	    basl_table_append_fwcfg(table, TPM_CRB_LOG_AREA_FWCFG_NAME, 1, 8));
+
+	BASL_EXEC(basl_table_register_to_rsdt(table));
+
+	return (0);
+}
+
 static struct tpm_intf tpm_intf_crb = {
 	.name = "crb",
 	.init = tpm_crb_init,
 	.deinit = tpm_crb_deinit,
+	.build_acpi_table = tpm_crb_build_acpi_table,
 };
 TPM_INTF_SET(tpm_intf_crb);