2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2023 Beckhoff Automation GmbH & Co. KG
5 * Author: Corvin Köhne <corvink@FreeBSD.org>
17 #include "acpi_device.h"
19 #include "tpm_device.h"
23 #define TPM_ACPI_DEVICE_NAME "TPM"
24 #define TPM_ACPI_HARDWARE_ID "MSFT0101"
26 SET_DECLARE(tpm_emul_set, struct tpm_emul);
27 SET_DECLARE(tpm_intf_set, struct tpm_intf);
31 struct acpi_device *acpi_dev;
32 struct tpm_emul *emul;
34 struct tpm_intf *intf;
39 tpm_build_acpi_table(const struct acpi_device *const dev)
41 const struct tpm_device *const tpm = acpi_device_get_softc(dev);
43 if (tpm->intf->build_acpi_table == NULL) {
47 return (tpm->intf->build_acpi_table(tpm->intf_sc, tpm->vm_ctx));
50 static const struct acpi_device_emul tpm_acpi_device_emul = {
51 .name = TPM_ACPI_DEVICE_NAME,
52 .hid = TPM_ACPI_HARDWARE_ID,
53 .build_table = tpm_build_acpi_table,
57 tpm_device_destroy(struct tpm_device *const dev)
62 if (dev->intf != NULL && dev->intf->deinit != NULL)
63 dev->intf->deinit(dev->intf_sc);
64 if (dev->emul != NULL && dev->emul->deinit != NULL)
65 dev->emul->deinit(dev->emul_sc);
67 acpi_device_destroy(dev->acpi_dev);
72 tpm_device_create(struct tpm_device **const new_dev, struct vmctx *const vm_ctx,
75 struct tpm_device *dev = NULL;
76 struct tpm_emul **ppemul;
77 struct tpm_intf **ppintf;
81 if (new_dev == NULL || vm_ctx == NULL) {
86 set_config_value_node_if_unset(nvl, "intf", "crb");
88 value = get_config_value_node(nvl, "version");
89 assert(value != NULL);
90 if (strcmp(value, "2.0")) {
91 warnx("%s: unsupported tpm version %s", __func__, value);
96 dev = calloc(1, sizeof(*dev));
102 dev->vm_ctx = vm_ctx;
104 error = acpi_device_create(&dev->acpi_dev, dev, dev->vm_ctx,
105 &tpm_acpi_device_emul);
109 value = get_config_value_node(nvl, "type");
110 assert(value != NULL);
111 SET_FOREACH(ppemul, tpm_emul_set) {
112 if (strcmp(value, (*ppemul)->name))
117 if (dev->emul == NULL) {
118 warnx("TPM emulation \"%s\" not found", value);
123 if (dev->emul->init) {
124 error = dev->emul->init(&dev->emul_sc, nvl);
129 value = get_config_value_node(nvl, "intf");
130 SET_FOREACH(ppintf, tpm_intf_set) {
131 if (strcmp(value, (*ppintf)->name)) {
137 if (dev->intf == NULL) {
138 warnx("TPM interface \"%s\" not found", value);
143 if (dev->intf->init) {
144 error = dev->intf->init(&dev->intf_sc, dev->emul, dev->emul_sc);
154 tpm_device_destroy(dev);