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
This commit is contained in:
Corvin Köhne 2022-08-29 12:10:43 +02:00
parent 24a0fef9dc
commit 5ea98d3268
No known key found for this signature in database
GPG Key ID: D854DA56315E026A
3 changed files with 67 additions and 1 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);