diff --git a/usr.sbin/bhyve/tpm_device.c b/usr.sbin/bhyve/tpm_device.c --- a/usr.sbin/bhyve/tpm_device.c +++ b/usr.sbin/bhyve/tpm_device.c @@ -35,9 +35,22 @@ 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 --- a/usr.sbin/bhyve/tpm_intf.h +++ b/usr.sbin/bhyve/tpm_intf.h @@ -7,6 +7,8 @@ #pragma once +#include + #include "config.h" #include "tpm_device.h" @@ -30,6 +32,6 @@ 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 --- 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 @@ } 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 @@ 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 @@ 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);