Signed-off-by: Andreas Niederl <andreas.nied...@iaik.tugraz.at> --- Makefile.target | 3 +++ hw/acpi.c | 28 ++++++++++++++++++++++++++++ hw/pc.h | 1 + hw/tpm.h | 2 ++ hw/tpm_acpi.c | 40 ++++++++++++++++++++++++++++++++++++++++ hw/tpm_ssdt.dsl | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/tpm_ssdt.hex | 41 +++++++++++++++++++++++++++++++++++++++++ hw/tpm_tis.c | 1 + rules.mak | 7 ++++++- vl.c | 23 +++++++++++++++++++++++ 10 files changed, 200 insertions(+), 1 deletions(-) create mode 100644 hw/tpm_acpi.c create mode 100644 hw/tpm_ssdt.dsl create mode 100644 hw/tpm_ssdt.hex
diff --git a/Makefile.target b/Makefile.target index 5a0fd40..33ffe19 100644 --- a/Makefile.target +++ b/Makefile.target @@ -211,6 +211,9 @@ obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o # Inter-VM PCI shared memory obj-$(CONFIG_KVM) += ivshmem.o +# TPM acpi support +obj-$(CONFIG_TPM) += tpm_acpi.o + # Hardware support obj-i386-y += vga.o obj-i386-y += mc146818rtc.o i8259.o pc.o diff --git a/hw/acpi.c b/hw/acpi.c index 8071e7b..93656c5 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -35,6 +35,34 @@ struct acpi_table_header char *acpi_tables; size_t acpi_tables_len; + +/* + * add a table directly (e.g. iasl C source output) + */ +int acpi_table_add_raw(const char *t, uint32_t length) +{ + char *p; + + if (!acpi_tables) { + acpi_tables_len = sizeof(uint16_t); + acpi_tables = qemu_mallocz(acpi_tables_len); + } + acpi_tables = qemu_realloc(acpi_tables, + acpi_tables_len + sizeof(uint16_t) + length); + p = acpi_tables + acpi_tables_len; + acpi_tables_len += sizeof(uint16_t) + length; + + *(uint16_t*)p = cpu_to_le32(length); + p += sizeof(uint16_t); + + memcpy(p, t, length); + + /* increase number of tables */ + (*(uint16_t*)acpi_tables) = + cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1); + return 0; +} + static int acpi_checksum(const uint8_t *data, int len) { int sum, i; diff --git a/hw/pc.h b/hw/pc.h index d5d2f42..56ba5fc 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -118,6 +118,7 @@ extern size_t acpi_tables_len; void acpi_bios_init(void); int acpi_table_add(const char *table_desc); +int acpi_table_add_raw(const char *table, uint32_t length); /* acpi_piix.c */ diff --git a/hw/tpm.h b/hw/tpm.h index f3e1395..5dd40c8 100644 --- a/hw/tpm.h +++ b/hw/tpm.h @@ -19,4 +19,6 @@ int qemu_tpm_add(QemuOpts *opts); +int qemu_tpm_acpi_init(void); + #endif /* TPM_H */ diff --git a/hw/tpm_acpi.c b/hw/tpm_acpi.c new file mode 100644 index 0000000..8cfa98f --- /dev/null +++ b/hw/tpm_acpi.c @@ -0,0 +1,40 @@ +/* + * tpm_acpi.c - ACPI integration for TPM device emulation + * + * Copyright (C) 2011 IAIK, Graz University of Technology + * + * Author: Andreas Niederl <andreas.nied...@iaik.tugraz.at> + * + * 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, version 2 of the + * License. + * + */ + +#include "hw/pc.h" +#include "hw/tpm.h" + +/* + * Add SSDT entry for TPM device + * + * Only one such entry is possible because it specifies a fixed MMIO address + * as required by the TIS 1.2 specification. + */ +int qemu_tpm_acpi_init(void) +{ + int ret = 0; +#ifdef TARGET_I386 + static int init = 0; + +#include "hw/tpm_ssdt.hex" + + if (!init) { + ret = acpi_table_add_raw((char*)AmlCode, sizeof(AmlCode)); + init = 1; + } +#endif + + return ret; +} + diff --git a/hw/tpm_ssdt.dsl b/hw/tpm_ssdt.dsl new file mode 100644 index 0000000..d9a48a7 --- /dev/null +++ b/hw/tpm_ssdt.dsl @@ -0,0 +1,55 @@ +/* + * ACPI SSDT ASL definition for TPM device emulation + * + * Copyright (C) 2011 IAIK, Graz University of Technology + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +DefinitionBlock ( + "tpm-ssdt.aml", // Output Filename + "SSDT", // Signature + 0x01, // DSDT Compliance Revision + "BXPC", // OEMID + "TPM-SSDT", // TABLE ID + 0x1 // OEM Revision + ) +{ + + Scope(\_SB) { + /* Pass-through TPM device with emulated TPM TIS interface */ + Device (TPM) { + Name (_HID, EisaID ("ATM1200")) + Name (_CID, EisaId ("PNP0C31")) + Name (_STR, Unicode ("Emulated TPM TIS pass-through device")) + Name (BUF1, ResourceTemplate () + { + Memory32Fixed (ReadOnly, + 0xFED40000, // Address Base + 0x00005000, // Address Length + ) + IRQNoFlags () {11} + }) + Method (_CRS, 0, Serialized) + { + Return (BUF1) + } + Method (_STA, 0) + { + Return (0x0F) + } + } + + } +} + diff --git a/hw/tpm_ssdt.hex b/hw/tpm_ssdt.hex new file mode 100644 index 0000000..da1d4c3 --- /dev/null +++ b/hw/tpm_ssdt.hex @@ -0,0 +1,41 @@ +/* + * + * Intel ACPI Component Architecture + * ASL Optimizing Compiler version 20090123 [Jun 3 2009] + * Copyright (C) 2000 - 2009 Intel Corporation + * Supports ACPI Specification Revision 3.0a + * + * Compilation of "hw/tpm_ssdt.dsl" - Wed Feb 2 17:49:34 2011 + * + * C source code output + * + */ +unsigned char AmlCode[] = +{ + 0x53,0x53,0x44,0x54,0xCC,0x00,0x00,0x00, /* 00000000 "SSDT...." */ + 0x01,0xEC,0x42,0x58,0x50,0x43,0x00,0x00, /* 00000008 "..BXPC.." */ + 0x54,0x50,0x4D,0x2D,0x53,0x53,0x44,0x54, /* 00000010 "TPM-SSDT" */ + 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x23,0x01,0x09,0x20,0x10,0x47,0x0A,0x5C, /* 00000020 "#.. .G.\" */ + 0x5F,0x53,0x42,0x5F,0x5B,0x82,0x4E,0x09, /* 00000028 "_SB_[.N." */ + 0x54,0x50,0x4D,0x5F,0x08,0x5F,0x48,0x49, /* 00000030 "TPM_._HI" */ + 0x44,0x0C,0x06,0x8D,0x12,0x00,0x08,0x5F, /* 00000038 "D......_" */ + 0x43,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x31, /* 00000040 "CID.A..1" */ + 0x08,0x5F,0x53,0x54,0x52,0x11,0x4E,0x04, /* 00000048 "._STR.N." */ + 0x0A,0x4A,0x45,0x00,0x6D,0x00,0x75,0x00, /* 00000050 ".JE.m.u." */ + 0x6C,0x00,0x61,0x00,0x74,0x00,0x65,0x00, /* 00000058 "l.a.t.e." */ + 0x64,0x00,0x20,0x00,0x54,0x00,0x50,0x00, /* 00000060 "d. .T.P." */ + 0x4D,0x00,0x20,0x00,0x54,0x00,0x49,0x00, /* 00000068 "M. .T.I." */ + 0x53,0x00,0x20,0x00,0x70,0x00,0x61,0x00, /* 00000070 "S. .p.a." */ + 0x73,0x00,0x73,0x00,0x2D,0x00,0x74,0x00, /* 00000078 "s.s.-.t." */ + 0x68,0x00,0x72,0x00,0x6F,0x00,0x75,0x00, /* 00000080 "h.r.o.u." */ + 0x67,0x00,0x68,0x00,0x20,0x00,0x64,0x00, /* 00000088 "g.h. .d." */ + 0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00, /* 00000090 "e.v.i.c." */ + 0x65,0x00,0x00,0x00,0x08,0x42,0x55,0x46, /* 00000098 "e....BUF" */ + 0x31,0x11,0x14,0x0A,0x11,0x86,0x09,0x00, /* 000000A0 "1......." */ + 0x00,0x00,0x00,0xD4,0xFE,0x00,0x50,0x00, /* 000000A8 "......P." */ + 0x00,0x22,0x00,0x08,0x79,0x00,0x14,0x0B, /* 000000B0 "."..y..." */ + 0x5F,0x43,0x52,0x53,0x08,0xA4,0x42,0x55, /* 000000B8 "_CRS..BU" */ + 0x46,0x31,0x14,0x09,0x5F,0x53,0x54,0x41, /* 000000C0 "F1.._STA" */ + 0x00,0xA4,0x0A,0x0F, +}; diff --git a/hw/tpm_tis.c b/hw/tpm_tis.c index a4c2a4e..589add6 100644 --- a/hw/tpm_tis.c +++ b/hw/tpm_tis.c @@ -635,6 +635,7 @@ static const VMStateDescription vmstate_tpm = { } }; + /* * initialize TIS interface */ diff --git a/rules.mak b/rules.mak index ed59c9e..3c5cdc5 100644 --- a/rules.mak +++ b/rules.mak @@ -31,6 +31,11 @@ LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(1) %.a: $(call quiet-command,rm -f $@ && $(AR) rcs $@ $^," AR $(TARGET_DIR)$@") +# ACPI table build rule +%.hex: %.dsl + $(call quiet-command,iasl -tc -p $@ $<," GEN $(TARGET_DIR)$@") + + quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) # cc-option @@ -39,7 +44,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ >/dev/null 2>&1 && echo OK), $2, $3) -VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi +VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.dsl set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) # find-in-path diff --git a/vl.c b/vl.c index b436952..f74f37a 100644 --- a/vl.c +++ b/vl.c @@ -151,6 +151,9 @@ int main(int argc, char **argv) #ifdef CONFIG_VIRTFS #include "fsdev/qemu-fsdev.h" #endif +#ifdef CONFIG_TPM +#include "hw/tpm.h" +#endif #include "disas.h" @@ -1647,6 +1650,19 @@ static int fsdev_init_func(QemuOpts *opts, void *opaque) } #endif +#ifdef CONFIG_TPM +static int tpm_acpi_init_func(QemuOpts *opts, void *opaque) +{ + int ret = 0; + + if (strcmp(qemu_opt_get(opts, "driver"), "tpm") == 0) { + ret = qemu_tpm_acpi_init(); + } + + return ret; +} +#endif + static int mon_init_func(QemuOpts *opts, void *opaque) { CharDriverState *chr; @@ -2864,6 +2880,13 @@ int main(int argc, char **argv, char **envp) } #endif +#ifdef CONFIG_TPM + /* register TPM acpi table before machine->init is called */ + if (qemu_opts_foreach(qemu_find_opts("device"), tpm_acpi_init_func, NULL, 1) != 0) { + exit(1); + } +#endif + os_daemonize(); if (pid_file && qemu_create_pidfile(pid_file) != 0) { -- 1.7.4.1