@@ -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 })
+ }
}
}
}