qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]