[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 3/6] Support Physical Presence Interface Spec
From: |
Stefan Berger |
Subject: |
[Qemu-devel] [PATCH v2 3/6] Support Physical Presence Interface Spec |
Date: |
Fri, 8 May 2015 12:15:17 -0400 |
For automated management of a TPM device, implement the TCG Physical Presence
Interface Specification that allows a root user on Linux (for example) to set
an opcode for a sequence of TPM operations that the BIOS is supposed to execute
upon reboot of the physical or virtual machine. A sequence of operations may for
example involve giving up ownership of the TPM and activating and enabling the
device.
The sequences of operations are defined in table 2 in the specs to be found
at the following link:
http://www.trustedcomputinggroup.org/resources/tcg_physical_presence_interface_specification
As an example, in recent versions of Linux the opcode (5) can be set as
follows:
cd /sys/devices/pnp0/00\:04/ppi
echo 5 > request
This ACPI implementation assumes that the underlying firmware (SeaBIOS)
has 'thrown an anchor' into the f-segment. The anchor is identified by
two signatures (TCG_MAGIC) surrounding a 64bit pointer. The structure
in the f-segment is write-protected and holds a pointer to a structure
in high memmory area where the ACPI code writes the opcode into and
where it can read the last response from the BIOS.
The supported opcodes are 1-11, 14, and 21-22. (see table 2 in spec)
Also '0' is supported to 'clear' an intention.
Signed-off-by: Stefan Berger <address@hidden>
Cc: Michael Tsirkin <address@hidden>
Cc: Kevin O'Connor <address@hidden>
---
hw/i386/ssdt-tpm.dsl | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/acpi/tpm.h | 20 ++++++
2 files changed, 209 insertions(+)
diff --git a/hw/i386/ssdt-tpm.dsl b/hw/i386/ssdt-tpm.dsl
index 75d9691..7d28899 100644
--- a/hw/i386/ssdt-tpm.dsl
+++ b/hw/i386/ssdt-tpm.dsl
@@ -38,6 +38,195 @@ DefinitionBlock (
Method (_STA, 0, NotSerialized) {
Return (0x0F)
}
+
+ OperationRegion (TTIS, SystemMemory,
+ TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
+
+ // Define TPM Debug register
+ Field(TTIS, AnyAcc, NoLock, Preserve) {
+ Offset (0xf90),
+ TDBG, 32 // QEMU TIS Debug
+ }
+
+ // Last accepted opcode
+ NAME(OP, Zero)
+
+ // The base address in TIS 'RAM' where we exchange
+ // data with the BIOS
+ Name(ADDR, 0xfed40fa0)
+
+ // Write given opcode into 'RAM'
+ Method (WRAM, 1, NotSerialized) {
+ // Write to high memory pointed to by ADDR
+ OperationRegion (HIGH, SystemMemory, ADDR, TPM_PPI_STRUCT_SIZE)
+ Field(HIGH, AnyAcc, NoLock, Preserve) {
+ SIG1, 32,
+ SIZE, 16,
+ CODE, 8
+ }
+ If (LAnd(
+ LEqual(SIG1, TCG_MAGIC),
+ LGreaterEqual(SIZE, 1))
+ ) {
+ // Write opcode for BIOS to find
+ Store(Arg0, CODE)
+ // Remember last opcode in CODE
+ Store(Arg0, OP)
+ Return ( 0 )
+ }
+ Return ( 1 )
+ }
+
+ // read data from 'RAM'
+ Method (RRAM, 0, NotSerialized) {
+ Name (OPRE, Package(3) { 1, 0, 0})
+ // Read from memory pointed to by ADDR
+ OperationRegion (HIGH, SystemMemory, ADDR, TPM_PPI_STRUCT_SIZE)
+ Field(HIGH, AnyAcc, NoLock, Preserve) {
+ SIG1, 32,
+ SIZE, 16,
+ CODE, 8,
+ SUCC, 8,
+ CODO, 8,
+ RESP, 32
+ }
+ // Check signature and sufficient space
+ If (LAnd(
+ LEqual(SIG1, TCG_MAGIC),
+ LGreaterEqual(SIZE, 7)
+ )) {
+ Store(SUCC, Index(OPRE, 0))
+ Store(CODO, Index(OPRE, 1))
+ Store(RESP, Index(OPRE, 2))
+ }
+ return (OPRE)
+ }
+
+ Method (_DSM, 4, NotSerialized) {
+ If (LEqual (Arg0,
ToUUID("3DDDFAA6-361B-4EB4-A424-8D10089D1653"))) {
+
+ // only supporting API revision 1
+ If (LNotEqual (Arg1, 1)) {
+ Return (Buffer (1) {0})
+ }
+
+ Store(ToInteger(Arg2), Local0)
+ // standard DSM query function
+ If (LEqual (Local0, 0)) {
+ Return (Buffer () {0xFF, 0x01})
+ }
+
+ // interface version
+ If (LEqual (Local0, 1)) {
+ Return ("1.2")
+ }
+
+ // submit TPM operation
+ If (LEqual (Local0, 2)) {
+ // get opcode from package
+ Store(DerefOf(Index(Arg3, 0)), Local0)
+ // check for supported opcode
+ // supported opcodes: 0, 1-11, 14, 21-22
+ If (LOr(
+ LOr(
+ LAnd(
+ LGreaterEqual(Local0, 0),
+ LLessEqual(Local0, 11)
+ ),
+ LEqual(Local0, 14)
+ ),
+ LAnd(
+ LGreaterEqual(Local0, 21),
+ LLessEqual(Local0, 22)
+ )
+ ))
+ {
+ // Write the OP into TPM NVRAM
+ Store(WRAM ( Local0 ), Local1)
+ return (Local1)
+ } else {
+ Return (1)
+ }
+ }
+
+ // get pending TPM operation
+ If (LEqual (Local0, 3)) {
+ NAME(PEOP, Package(2) { 0, 0 })
+
+ Store ( 0 , Index(PEOP, 0))
+ Store ( OP, Index(PEOP, 1))
+
+ Return (PEOP)
+ }
+
+ // action to transition to pre-OS env.
+ If (LEqual (Local0, 4)) {
+ return (2) // Requiring reboot
+ }
+
+ // get pre-OS TPM operation response
+ If (LEqual (Local0, 5)) {
+ Store (RRAM(), Local0)
+ return ( Local0 )
+ }
+
+ // preferred user language
+ If (LEqual (Local0, 6)) {
+ return (3) // Not implemented
+ }
+
+ // submit TPM operation v2
+ If (LEqual (Local0, 7)) {
+ Store(DerefOf(Index(Arg3, 0)), Local0)
+ // supported opcodes: 0, 1-11, 14, 21-22
+ If (LOr(
+ LOr(
+ LAnd(
+ LGreaterEqual(Local0, 0),
+ LLessEqual(Local0, 11)
+ ),
+ LEqual(Local0, 14)
+ ),
+ LAnd(
+ LGreaterEqual(Local0, 21),
+ LLessEqual(Local0, 22)
+ )
+ ))
+ {
+ // Write the OP into TPM NVRAM
+ Store(WRAM ( Local0 ), Local1)
+ return (Local1)
+ } else {
+ Return (1)
+ }
+ }
+
+ // get user confirmation status
+ If (LEqual (Local0, 8)) {
+ Store(DerefOf(Index(Arg3,0)), Local0)
+ // supported opcodes: 0, 1-11, 14, 21-22
+ If (LOr(
+ LOr(
+ LAnd(
+ LGreaterEqual(Local0, 0),
+ LLessEqual(Local0, 11)
+ ),
+ LEqual(Local0, 14)
+ ),
+ LAnd(
+ LGreaterEqual(Local0, 21),
+ LLessEqual(Local0, 22)
+ )
+ ))
+ {
+ Return (4) // allowed, no user required
+ } else {
+ Return (0) // not implemented
+ }
+ }
+ }
+ return (Buffer() { 0x0 })
+ }
}
}
}
diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 6d516c6..8d9c8dc 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -31,4 +31,24 @@
#define TPM2_START_METHOD_MMIO 6
+/*
+ * Physical Presence Interface -- shared with the BIOS
+ */
+#define TCG_MAGIC 0x41504354
+
+#if 0
+struct tpm_ppi {
+ uint32_t sign1; // TCG_MAGIC
+ uint16_t size; // number of subsequent bytes for ACPI to access
+ uint8_t opcode; // set by ACPI
+ uint8_t failure; // set by BIOS (0 = success)
+ uint8_t recent_opcode; // set by BIOS
+ uint32_t response; // set by BIOS
+ uint8_t next_step; // BIOS only
+ uint32_t sign2; // TCG_MAGIC
+} QEMU_PACKED;
+#endif
+
+#define TPM_PPI_STRUCT_SIZE 18
+
#endif /* HW_ACPI_TPM_H */
--
1.9.3
- [Qemu-devel] [PATCH v2 0/6] Extend TPM support with a QEMU-external TPM, Stefan Berger, 2015/05/08
- [Qemu-devel] [PATCH v2 4/6] Introduce condition to notifiy waiters of completed command, Stefan Berger, 2015/05/08
- [Qemu-devel] [PATCH v2 2/6] Introduce RAM location in vendor specific area in TIS, Stefan Berger, 2015/05/08
- [Qemu-devel] [PATCH v2 5/6] Introduce condition in TPM backend for notification, Stefan Berger, 2015/05/08
- [Qemu-devel] [PATCH v2 1/6] Provide support for the CUSE TPM, Stefan Berger, 2015/05/08
- [Qemu-devel] [PATCH v2 6/6] Add support for VM suspend/resume for TPM TIS, Stefan Berger, 2015/05/08
- [Qemu-devel] [PATCH v2 3/6] Support Physical Presence Interface Spec,
Stefan Berger <=