From: Stefan Berger <stefanb@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org, mst@redhat.com
Cc: imammedo@redhat.com, kevin@koconnor.net, stefanb@us.ibm.com,
quan.xu@intel.com, Stefan Berger <stefanb@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH v2 3/6] Support Physical Presence Interface Spec
Date: Fri, 8 May 2015 12:15:17 -0400 [thread overview]
Message-ID: <1431101720-701152-4-git-send-email-stefanb@linux.vnet.ibm.com> (raw)
In-Reply-To: <1431101720-701152-1-git-send-email-stefanb@linux.vnet.ibm.com>
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 <stefanb@linux.vnet.ibm.com>
Cc: Michael Tsirkin <mst@redhat.com>
Cc: Kevin O'Connor <kevin@koconnor.net>
---
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
next prev parent reply other threads:[~2015-05-08 16:15 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-08 16:15 [Qemu-devel] [PATCH v2 0/6] Extend TPM support with a QEMU-external TPM Stefan Berger
2015-05-08 16:15 ` [Qemu-devel] [PATCH v2 1/6] Provide support for the CUSE TPM Stefan Berger
2015-05-08 16:15 ` [Qemu-devel] [PATCH v2 2/6] Introduce RAM location in vendor specific area in TIS Stefan Berger
2015-05-08 16:15 ` Stefan Berger [this message]
2015-05-08 18:02 ` [Qemu-devel] [PATCH v2 3/6] Support Physical Presence Interface Spec Stefan Berger
2015-05-15 15:13 ` Igor Mammedov
2015-05-15 18:24 ` Stefan Berger
2015-05-22 0:20 ` Stefan Berger
2015-05-08 16:15 ` [Qemu-devel] [PATCH v2 4/6] Introduce condition to notifiy waiters of completed command Stefan Berger
2015-05-08 16:15 ` [Qemu-devel] [PATCH v2 5/6] Introduce condition in TPM backend for notification Stefan Berger
2015-05-08 16:15 ` [Qemu-devel] [PATCH v2 6/6] Add support for VM suspend/resume for TPM TIS Stefan Berger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1431101720-701152-4-git-send-email-stefanb@linux.vnet.ibm.com \
--to=stefanb@linux.vnet.ibm.com \
--cc=imammedo@redhat.com \
--cc=kevin@koconnor.net \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quan.xu@intel.com \
--cc=stefanb@us.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).