From: Stefan Berger <stefanb@us.ibm.com>
To: kevin@koconnor.net, seabios@seabios.org, mst@redhat.com,
qemu-devel@nongnu.org
Cc: Stefan Berger <stefanb@linux.vnet.ibm.com>,
stefan.reinauer@coreboot.org, coreboot@coreboot.org
Subject: [Qemu-devel] [RFC PATCH 1/1] TPM: Support Physical Presence Interface Spec
Date: Tue, 2 Sep 2014 10:27:44 -0400 [thread overview]
Message-ID: <1409668064-14371-1-git-send-email-stefanb@us.ibm.com> (raw)
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
To (try to) avoid SeaBIOS from having to implement a menu for managing the
various states of a TPM device, implement the TCG Physical Presence Interface
Specification that allows a root user on Linux (for example) to set the 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 operation 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 > ppi
This ACPI implementation writes the opcode into the TPM's NVRAM at index
0x5001 0000 (to be adapted), which SeaBIOS can then read and react to.
An alernative would be to have ACPI write the byte into a memory area that
SeaBIOS would have to be able to find upon reboot.
More than a single byte of persistent memory will be needed once SeaBIOS
supports this since it must store a status byte about the last operation,
the opcode that was acted on, and the return code that the TPM gave
(see ACPI function 5).
Only a subset of the defined opcodes will be supported. Tentatively opcodes
1-11, 14 will be supported.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
hw/i386/ssdt-tpm.dsl | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 208 insertions(+)
diff --git a/hw/i386/ssdt-tpm.dsl b/hw/i386/ssdt-tpm.dsl
index 75d9691..678b212 100644
--- a/hw/i386/ssdt-tpm.dsl
+++ b/hw/i386/ssdt-tpm.dsl
@@ -12,6 +12,14 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+
+/*
+ * Note: This implementation follows the TCG specification
+ * 'TCG Physical Presence Interface Specification' of which the latest
+ * version can be found here:
+ * http://www.trustedcomputinggroup.org/resources/tcg_physical_presence_interface_specification
+ */
+
#include "hw/acpi/tpm.h"
ACPI_EXTRACT_ALL_CODE ssdt_tpm_aml
@@ -38,6 +46,206 @@ DefinitionBlock (
Method (_STA, 0, NotSerialized) {
Return (0x0F)
}
+ // Last accepted opcode
+ NAME(OP, Zero)
+ OperationRegion (TTIS, SystemMemory,
+ TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
+
+ // Define TIS registers
+ Field(TTIS, AnyAcc, NoLock, Preserve) {
+ Offset (0x00),
+ TACC, 8, // Access register
+ Offset (0x18),
+ TSTS, 8, // Status register
+ Offset (0x24),
+ TDAT, 8, // Data register
+ Offset (0xf90),
+ TDBG, 32 // QEMU TIS Debug
+ }
+ // TPM_NV_WriteValue for writing 1 byte to a NVRAM index
+ Name (NVWR, Package() {
+ 0x00, 0xc1,
+ 0x00, 0x00, 0x00, 0x17, // total length
+ 0x00, 0x00, 0x00, 0xcd, // opcode
+ 0x50, 0x01, 0x00, 0x00, // index
+ 0x00, 0x00, 0x00, 0x00, // offset
+ 0x00, 0x00, 0x00, 0x01, // payload length
+ 0x00
+ })
+ // Buffer to read TPM responses into
+ Name (BUFF, Buffer(0xa){})
+ // Last TPM return code from writing to TPM NVRAM
+ Name (WRET, 0)
+
+ // Write into NVRAM of TPM
+ Method ( _WNV, 1, NotSerialized) {
+ // Any early return will indicate a failed execution
+ Store(0xffffffff, WRET)
+
+ // Request access to locty 0
+ Store(0x02, TACC)
+
+ // Make sure we are active
+ Store(TACC, Local0)
+ If (LNotEqual(And(Local0, 0xa0), 0xa0)) {
+ return (16) // EBUSY
+ }
+
+ // Set the Command Ready Flag
+ Store(0x40, TSTS)
+
+ // Make sure we are ready
+ Store(TSTS, Local0)
+ If (LNotEqual(And(Local0, 0x40), 0x40)) {
+ return (14) // EFAULT
+ }
+
+ // Write the user-requested op-code into the NVRAM command
+ Store(Arg0, Index(NVWR, 0x16))
+
+ // Write the TPM_NV_WriteValue into the data buffer
+ Store(0x0, Local0)
+ While (LLess(Local0, SizeOf(NVWR))) {
+ Store(DerefOf(Index(NVWR, Local0)), TDAT)
+ Increment(Local0)
+ }
+
+ // Go: have TPM process the command
+ Store(0x20, TSTS)
+
+ // Wait for response to be ready
+ Store(0, Local0)
+ While (LLess(local0, 0x30)) {
+ Store(TSTS, Local1)
+ if (LEqual(And(Local1, 0x10), 0x10)) {
+ break
+ }
+ Sleep(10)
+ Increment(Local0)
+ }
+
+ // Read the result into BUFF
+ Store(0, Local0)
+ While (LLess(Local0, SizeOf(BUFF))) {
+ Store(TDAT, Index(BUFF, Local0))
+ Increment(Local0)
+ }
+
+ // Extract return code from response
+ Mid(BUFF, 6, 4, WRET)
+
+ Return (0)
+ }
+ 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: 1-11, 14
+ If (LOr(LAnd(LGreaterEqual(Local0, 1), LLessEqual(Local0, 11)), LEqual(Local0, 14))) {
+ // Write the OP into TPM NVRAM
+ Store(_WNV ( Local0 ), Local1)
+ if (LNotEqual(Local1, 0)) {
+ return (Local1)
+ }
+ // Check for error during NVRAM write
+ if (LEqual(WRET, 0)) {
+ Store(Local0, OP)
+ Return (0)
+ } else {
+ Return (1)
+ }
+ } else {
+ Return (1)
+ }
+ }
+
+ // get pending TPM operation
+ If (LEqual (Local0, 3)) {
+ NAME(PEOP, Package(2) { 0, 0 })
+
+ // Check for error during NVRAM write
+ if (LEqual(WRET, 0)) {
+ Store ( 0, Index(PEOP, 0))
+ } else {
+ Store ( 1, 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)) {
+ // missing BIOS support
+ Name (OPRE, Package(3) { 1, 0, 0})
+ return (OPRE)
+ }
+
+ // 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: 1-11, 14
+ If (LOr(LAnd(LGreaterEqual(Local0, 1), LLessEqual(Local0, 11)), LEqual(Local0, 14))) {
+ // Write the OP into TPM NVRAM
+ Store(_WNV ( Local0 ), Local1)
+ if (LNotEqual(Local1, 0)) {
+ return (Local1)
+ }
+ // Check for error during NVRAM write
+ if (LEqual(WRET, 0)) {
+ // Remember opcode locally
+ Store(Local0, OP)
+ Return (0)
+ } else {
+ Return (1)
+ }
+ } else {
+ Return (1)
+ }
+ }
+
+ // get user confirmation status
+ If (LEqual (Local0, 8)) {
+ Store(DerefOf(Index(Arg3,0)), Local0)
+ If (LLessEqual(Local0, 22)) {
+ Return (4) // allowed, no user required
+ } else {
+ Return (0) // not implemented
+ }
+ }
+ }
+ return (Buffer() { 0x0 })
+ }
}
}
}
--
1.9.3
next reply other threads:[~2014-09-02 14:28 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-02 14:27 Stefan Berger [this message]
2014-09-11 14:52 ` [Qemu-devel] [RFC PATCH 1/1] TPM: Support Physical Presence Interface Spec 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=1409668064-14371-1-git-send-email-stefanb@us.ibm.com \
--to=stefanb@us.ibm.com \
--cc=coreboot@coreboot.org \
--cc=kevin@koconnor.net \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=seabios@seabios.org \
--cc=stefan.reinauer@coreboot.org \
--cc=stefanb@linux.vnet.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).