aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Berger <stefanb@linux.vnet.ibm.com>2015-05-26 16:51:07 -0400
committerMichael S. Tsirkin <mst@redhat.com>2015-06-01 14:18:54 +0200
commit5cb18b3d7bff2a83275ee98af2a14eb9e21c93ab (patch)
tree57e9bea68329809b1caeba263351b3d550a8c911
parent56a3c24ffc11955ddc7bb21362ca8069a3fc8c55 (diff)
TPM2 ACPI table support
Add a TPM2 ACPI table if a TPM 2 is used in the backend. Also add an SSDT for the TPM 2. Rename tpm_find() to tpm_get_version() and have this function return the version of the TPM found, TPMVersion_Unspec if no TPM is found. Use the version number to build version specific ACPI tables. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/i386/Makefile.objs2
-rw-r--r--hw/i386/acpi-build.c38
-rw-r--r--hw/i386/ssdt-tpm.dsl16
-rw-r--r--hw/i386/ssdt-tpm.hex.generated26
-rw-r--r--hw/i386/ssdt-tpm2.dsl29
-rw-r--r--hw/i386/ssdt-tpm2.hex.generated109
-rw-r--r--hw/tpm/tpm_tis.c11
-rw-r--r--include/hw/acpi/acpi-defs.h18
-rw-r--r--include/hw/acpi/tpm.h5
-rw-r--r--include/sysemu/tpm.h11
10 files changed, 237 insertions, 28 deletions
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index e058a39147..0be5d97c59 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -9,7 +9,7 @@ obj-y += kvmvapic.o
obj-y += acpi-build.o
hw/i386/acpi-build.o: hw/i386/acpi-build.c \
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
- hw/i386/ssdt-tpm.hex
+ hw/i386/ssdt-tpm.hex hw/i386/ssdt-tpm2.hex
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 283d02e7a7..2c7399b9db 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -41,6 +41,7 @@
#include "hw/acpi/memory_hotplug.h"
#include "sysemu/tpm.h"
#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
/* Supported chipsets: */
#include "hw/acpi/piix4.h"
@@ -106,7 +107,7 @@ typedef struct AcpiPmInfo {
typedef struct AcpiMiscInfo {
bool has_hpet;
- bool has_tpm;
+ TPMVersion tpm_version;
const unsigned char *dsdt_code;
unsigned dsdt_size;
uint16_t pvpanic_port;
@@ -234,7 +235,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
static void acpi_get_misc_info(AcpiMiscInfo *info)
{
info->has_hpet = hpet_find();
- info->has_tpm = tpm_find();
+ info->tpm_version = tpm_get_version();
info->pvpanic_port = pvpanic_port();
info->applesmc_io_base = applesmc_port();
}
@@ -414,6 +415,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
}
#include "hw/i386/ssdt-tpm.hex"
+#include "hw/i386/ssdt-tpm2.hex"
/* Assign BSEL property to all buses. In the future, this can be changed
* to only assign to buses that support hotplug.
@@ -1029,6 +1031,25 @@ build_tpm_ssdt(GArray *table_data, GArray *linker)
memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
}
+static void
+build_tpm2(GArray *table_data, GArray *linker)
+{
+ Acpi20TPM2 *tpm2_ptr;
+ void *tpm_ptr;
+
+ tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm2_aml));
+ memcpy(tpm_ptr, ssdt_tpm2_aml, sizeof(ssdt_tpm2_aml));
+
+ tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr);
+
+ tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT);
+ tpm2_ptr->control_area_address = cpu_to_le64(0);
+ tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
+
+ build_header(linker, table_data,
+ (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4);
+}
+
typedef enum {
MEM_AFFINITY_NOFLAGS = 0,
MEM_AFFINITY_ENABLED = (1 << 0),
@@ -1343,12 +1364,21 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob);
build_hpet(tables_blob, tables->linker);
}
- if (misc.has_tpm) {
+ if (misc.tpm_version != TPM_VERSION_UNSPEC) {
acpi_add_table(table_offsets, tables_blob);
build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog);
acpi_add_table(table_offsets, tables_blob);
- build_tpm_ssdt(tables_blob, tables->linker);
+ switch (misc.tpm_version) {
+ case TPM_VERSION_1_2:
+ build_tpm_ssdt(tables_blob, tables->linker);
+ break;
+ case TPM_VERSION_2_0:
+ build_tpm2(tables_blob, tables->linker);
+ break;
+ default:
+ assert(false);
+ }
}
if (guest_info->numa_nodes) {
acpi_add_table(table_offsets, tables_blob);
diff --git a/hw/i386/ssdt-tpm.dsl b/hw/i386/ssdt-tpm.dsl
index 75d96910bf..d81478c1b5 100644
--- a/hw/i386/ssdt-tpm.dsl
+++ b/hw/i386/ssdt-tpm.dsl
@@ -25,19 +25,5 @@ DefinitionBlock (
0x1 // OEM Revision
)
{
- Scope(\_SB) {
- /* TPM with emulated TPM TIS interface */
- Device (TPM) {
- Name (_HID, EisaID ("PNP0C31"))
- Name (_CRS, ResourceTemplate ()
- {
- Memory32Fixed (ReadWrite, TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
- // older Linux tpm_tis drivers do not work with IRQ
- //IRQNoFlags () {TPM_TIS_IRQ}
- })
- Method (_STA, 0, NotSerialized) {
- Return (0x0F)
- }
- }
- }
+#include "ssdt-tpm-common.dsl"
}
diff --git a/hw/i386/ssdt-tpm.hex.generated b/hw/i386/ssdt-tpm.hex.generated
index e84dc6cfc0..874418c946 100644
--- a/hw/i386/ssdt-tpm.hex.generated
+++ b/hw/i386/ssdt-tpm.hex.generated
@@ -3,12 +3,12 @@ static unsigned char ssdt_tpm_aml[] = {
0x53,
0x44,
0x54,
-0x5d,
+0x6b,
0x0,
0x0,
0x0,
0x1,
-0x1c,
+0x37,
0x42,
0x58,
0x50,
@@ -36,15 +36,26 @@ static unsigned char ssdt_tpm_aml[] = {
0x14,
0x20,
0x10,
-0x38,
+0x46,
+0x4,
0x5c,
+0x2f,
+0x3,
0x5f,
0x53,
0x42,
0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x49,
+0x53,
+0x41,
+0x5f,
0x5b,
0x82,
-0x30,
+0x33,
0x54,
0x50,
0x4d,
@@ -65,9 +76,9 @@ static unsigned char ssdt_tpm_aml[] = {
0x52,
0x53,
0x11,
-0x11,
+0x14,
0xa,
-0xe,
+0x11,
0x86,
0x9,
0x0,
@@ -80,6 +91,9 @@ static unsigned char ssdt_tpm_aml[] = {
0x50,
0x0,
0x0,
+0x22,
+0x20,
+0x0,
0x79,
0x0,
0x14,
diff --git a/hw/i386/ssdt-tpm2.dsl b/hw/i386/ssdt-tpm2.dsl
new file mode 100644
index 0000000000..58bbbf806d
--- /dev/null
+++ b/hw/i386/ssdt-tpm2.dsl
@@ -0,0 +1,29 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw/acpi/tpm.h"
+
+ACPI_EXTRACT_ALL_CODE ssdt_tpm2_aml
+
+DefinitionBlock (
+ "ssdt-tpm2.aml", // Output Filename
+ "SSDT", // Signature
+ 0x01, // SSDT Compliance Revision
+ "BXPC", // OEMID
+ "BXSSDT", // TABLE ID
+ 0x1 // OEM Revision
+ )
+{
+#include "ssdt-tpm-common.dsl"
+}
diff --git a/hw/i386/ssdt-tpm2.hex.generated b/hw/i386/ssdt-tpm2.hex.generated
new file mode 100644
index 0000000000..9ea827151a
--- /dev/null
+++ b/hw/i386/ssdt-tpm2.hex.generated
@@ -0,0 +1,109 @@
+static unsigned char ssdt_tpm2_aml[] = {
+0x53,
+0x53,
+0x44,
+0x54,
+0x6b,
+0x0,
+0x0,
+0x0,
+0x1,
+0x37,
+0x42,
+0x58,
+0x50,
+0x43,
+0x0,
+0x0,
+0x42,
+0x58,
+0x53,
+0x53,
+0x44,
+0x54,
+0x0,
+0x0,
+0x1,
+0x0,
+0x0,
+0x0,
+0x49,
+0x4e,
+0x54,
+0x4c,
+0x7,
+0x11,
+0x14,
+0x20,
+0x10,
+0x46,
+0x4,
+0x5c,
+0x2f,
+0x3,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x5b,
+0x82,
+0x33,
+0x54,
+0x50,
+0x4d,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0x31,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x14,
+0xa,
+0x11,
+0x86,
+0x9,
+0x0,
+0x1,
+0x0,
+0x0,
+0xd4,
+0xfe,
+0x0,
+0x50,
+0x0,
+0x0,
+0x22,
+0x20,
+0x0,
+0x79,
+0x0,
+0x14,
+0x9,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0xa,
+0xf
+};
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index e8047571c1..0806b5f82e 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -32,6 +32,7 @@
#include "tpm_tis.h"
#include "qemu-common.h"
#include "qemu/main-loop.h"
+#include "sysemu/tpm_backend.h"
#define DEBUG_TIS 0
@@ -962,6 +963,16 @@ static int tpm_tis_do_startup_tpm(TPMState *s)
}
/*
+ * Get the TPMVersion of the backend device being used
+ */
+TPMVersion tpm_tis_get_tpm_version(Object *obj)
+{
+ TPMState *s = TPM(obj);
+
+ return tpm_backend_get_tpm_version(s->be_driver);
+}
+
+/*
* This function is called when the machine starts, resets or due to
* S3 resume.
*/
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index f503ec4a97..59cf277434 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -450,6 +450,9 @@ typedef struct AcpiTableMcfg AcpiTableMcfg;
/*
* TCPA Description Table
+ *
+ * Following Level 00, Rev 00.37 of specs:
+ * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
*/
struct Acpi20Tcpa {
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
@@ -459,6 +462,21 @@ struct Acpi20Tcpa {
} QEMU_PACKED;
typedef struct Acpi20Tcpa Acpi20Tcpa;
+/*
+ * TPM2
+ *
+ * Following Level 00, Rev 00.37 of specs:
+ * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
+ */
+struct Acpi20TPM2 {
+ ACPI_TABLE_HEADER_DEF
+ uint16_t platform_class;
+ uint16_t reserved;
+ uint64_t control_area_address;
+ uint32_t start_method;
+} QEMU_PACKED;
+typedef struct Acpi20TPM2 Acpi20TPM2;
+
/* DMAR - DMA Remapping table r2.2 */
struct AcpiTableDmar {
ACPI_TABLE_HEADER_DEF
diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 792fcbf5b1..6d516c6a7f 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -26,4 +26,9 @@
#define TPM_TCPA_ACPI_CLASS_CLIENT 0
#define TPM_TCPA_ACPI_CLASS_SERVER 1
+#define TPM2_ACPI_CLASS_CLIENT 0
+#define TPM2_ACPI_CLASS_SERVER 1
+
+#define TPM2_START_METHOD_MMIO 6
+
#endif /* HW_ACPI_TPM_H */
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 848df412db..c1438907de 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -26,11 +26,18 @@ typedef enum TPMVersion {
TPM_VERSION_2_0 = 2,
} TPMVersion;
+TPMVersion tpm_tis_get_tpm_version(Object *obj);
+
#define TYPE_TPM_TIS "tpm-tis"
-static inline bool tpm_find(void)
+static inline TPMVersion tpm_get_version(void)
{
- return object_resolve_path_type("", TYPE_TPM_TIS, NULL);
+ Object *obj = object_resolve_path_type("", TYPE_TPM_TIS, NULL);
+
+ if (obj) {
+ return tpm_tis_get_tpm_version(obj);
+ }
+ return TPM_VERSION_UNSPEC;
}
#endif /* QEMU_TPM_H */