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 <stef...@linux.vnet.ibm.com> Cc: Michael Tsirkin <m...@redhat.com> Cc: Kevin O'Connor <ke...@koconnor.net> --- v3->v4: - consolidated code following Igor's suggestions - marked functions as Serialized - added .hex.generated files --- hw/i386/ssdt-tpm-common.dsl | 182 ++++++++++++++ hw/i386/ssdt-tpm.dsl | 1 + hw/i386/ssdt-tpm.hex.generated | 540 +++++++++++++++++++++++++++++++++++++++- hw/i386/ssdt-tpm2.dsl | 1 + hw/i386/ssdt-tpm2.hex.generated | 516 +++++++++++++++++++++++++++++++++++++- include/hw/acpi/tpm.h | 19 ++ 6 files changed, 1245 insertions(+), 14 deletions(-) diff --git a/hw/i386/ssdt-tpm-common.dsl b/hw/i386/ssdt-tpm-common.dsl index 9da4970..81d6757 100644 --- a/hw/i386/ssdt-tpm-common.dsl +++ b/hw/i386/ssdt-tpm-common.dsl @@ -32,5 +32,187 @@ 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 lies at 0xfed40fa0 + OperationRegion (HIGH, SystemMemory, 0xfed40fa0, TPM_PPI_STRUCT_SIZE) + + // Write given opcode into 'RAM' + Method (WRAM, 1, Serialized) { + 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, Serialized) { + Name (OPRE, Package(3) { 1, 0, 0}) + + 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) + } + +#ifdef TPM_1_2 + // check for supported opcode + // supported opcodes: 0, 1-11, 14, 21-22 + Method (CKOP, 1, NotSerialized) { + If (LOr( + LOr( + LAnd( + LGreaterEqual(Arg0, 0), + LLessEqual(Arg0, 11) + ), + LEqual(Arg0, 14) + ), + LAnd( + LGreaterEqual(Arg0, 21), + LLessEqual(Arg0, 22) + ) + )) { + return (1) + } else { + return (0) + } + } +#else +# ifdef TPM_2_0 + // check for supported opcode + // supported opcodes: 0 + Method (CKOP, 1, NotSerialized) { + If (LEqual(Arg0, 0)) { + return (1) + } else { + return (0) + } + } +# endif +#endif + + Method (_DSM, 4, Serialized) { + 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) + + If (CKOP( Local0 ) ) { + // 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) + + If (CKOP( Local0 )) { + // 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) + + if (CKOP( Local0 )) { + Return (4) // allowed, no user required + } else { + Return (0) // not implemented + } + } + } + return (Buffer() { 0x0 }) + } } } diff --git a/hw/i386/ssdt-tpm.dsl b/hw/i386/ssdt-tpm.dsl index d81478c..48bf112 100644 --- a/hw/i386/ssdt-tpm.dsl +++ b/hw/i386/ssdt-tpm.dsl @@ -25,5 +25,6 @@ DefinitionBlock ( 0x1 // OEM Revision ) { +#define TPM_1_2 #include "ssdt-tpm-common.dsl" } diff --git a/hw/i386/ssdt-tpm.hex.generated b/hw/i386/ssdt-tpm.hex.generated index 874418c..db1d31d 100644 --- a/hw/i386/ssdt-tpm.hex.generated +++ b/hw/i386/ssdt-tpm.hex.generated @@ -3,12 +3,12 @@ static unsigned char ssdt_tpm_aml[] = { 0x53, 0x44, 0x54, -0x6b, -0x0, +0x79, +0x2, 0x0, 0x0, 0x1, -0x37, +0xea, 0x42, 0x58, 0x50, @@ -36,8 +36,8 @@ static unsigned char ssdt_tpm_aml[] = { 0x14, 0x20, 0x10, -0x46, -0x4, +0x44, +0x25, 0x5c, 0x2f, 0x3, @@ -55,7 +55,8 @@ static unsigned char ssdt_tpm_aml[] = { 0x5f, 0x5b, 0x82, -0x33, +0x41, +0x24, 0x54, 0x50, 0x4d, @@ -105,5 +106,530 @@ static unsigned char ssdt_tpm_aml[] = { 0x0, 0xa4, 0xa, -0xf +0xf, +0x5b, +0x80, +0x54, +0x54, +0x49, +0x53, +0x0, +0xc, +0x0, +0x0, +0xd4, +0xfe, +0xb, +0x0, +0x50, +0x5b, +0x81, +0xf, +0x54, +0x54, +0x49, +0x53, +0x0, +0x0, +0x80, +0xc8, +0x7, +0x54, +0x44, +0x42, +0x47, +0x20, +0x8, +0x4f, +0x50, +0x5f, +0x5f, +0x0, +0x5b, +0x80, +0x48, +0x49, +0x47, +0x48, +0x0, +0xc, +0xa0, +0xf, +0xd4, +0xfe, +0xa, +0xe, +0x14, +0x42, +0x4, +0x57, +0x52, +0x41, +0x4d, +0x9, +0x5b, +0x81, +0x15, +0x48, +0x49, +0x47, +0x48, +0x0, +0x53, +0x49, +0x47, +0x31, +0x20, +0x53, +0x49, +0x5a, +0x45, +0x10, +0x43, +0x4f, +0x44, +0x45, +0x8, +0xa0, +0x21, +0x90, +0x93, +0x53, +0x49, +0x47, +0x31, +0xc, +0x54, +0x43, +0x50, +0x41, +0x92, +0x95, +0x53, +0x49, +0x5a, +0x45, +0x1, +0x70, +0x68, +0x43, +0x4f, +0x44, +0x45, +0x70, +0x68, +0x4f, +0x50, +0x5f, +0x5f, +0xa4, +0x0, +0xa4, +0x1, +0x14, +0x47, +0x7, +0x52, +0x52, +0x41, +0x4d, +0x8, +0x8, +0x4f, +0x50, +0x52, +0x45, +0x12, +0x5, +0x3, +0x1, +0x0, +0x0, +0x5b, +0x81, +0x24, +0x48, +0x49, +0x47, +0x48, +0x0, +0x53, +0x49, +0x47, +0x31, +0x20, +0x53, +0x49, +0x5a, +0x45, +0x10, +0x43, +0x4f, +0x44, +0x45, +0x8, +0x53, +0x55, +0x43, +0x43, +0x8, +0x43, +0x4f, +0x44, +0x4f, +0x8, +0x52, +0x45, +0x53, +0x50, +0x20, +0xa0, +0x39, +0x90, +0x93, +0x53, +0x49, +0x47, +0x31, +0xc, +0x54, +0x43, +0x50, +0x41, +0x92, +0x95, +0x53, +0x49, +0x5a, +0x45, +0xa, +0x7, +0x70, +0x53, +0x55, +0x43, +0x43, +0x88, +0x4f, +0x50, +0x52, +0x45, +0x0, +0x0, +0x70, +0x43, +0x4f, +0x44, +0x4f, +0x88, +0x4f, +0x50, +0x52, +0x45, +0x1, +0x0, +0x70, +0x52, +0x45, +0x53, +0x50, +0x88, +0x4f, +0x50, +0x52, +0x45, +0xa, +0x2, +0x0, +0xa4, +0x4f, +0x50, +0x52, +0x45, +0x14, +0x29, +0x43, +0x4b, +0x4f, +0x50, +0x1, +0xa0, +0x1e, +0x91, +0x91, +0x90, +0x92, +0x95, +0x68, +0x0, +0x92, +0x94, +0x68, +0xa, +0xb, +0x93, +0x68, +0xa, +0xe, +0x90, +0x92, +0x95, +0x68, +0xa, +0x15, +0x92, +0x94, +0x68, +0xa, +0x16, +0xa4, +0x1, +0xa1, +0x3, +0xa4, +0x0, +0x14, +0x43, +0xf, +0x5f, +0x44, +0x53, +0x4d, +0xc, +0xa0, +0x46, +0xe, +0x93, +0x68, +0x11, +0x13, +0xa, +0x10, +0xa6, +0xfa, +0xdd, +0x3d, +0x1b, +0x36, +0xb4, +0x4e, +0xa4, +0x24, +0x8d, +0x10, +0x8, +0x9d, +0x16, +0x53, +0xa0, +0xa, +0x92, +0x93, +0x69, +0x1, +0xa4, +0x11, +0x3, +0x1, +0x0, +0x70, +0x99, +0x6a, +0x0, +0x60, +0xa0, +0xb, +0x93, +0x60, +0x0, +0xa4, +0x11, +0x5, +0xa, +0x2, +0xff, +0x1, +0xa0, +0xa, +0x93, +0x60, +0x1, +0xa4, +0xd, +0x31, +0x2e, +0x32, +0x0, +0xa0, +0x20, +0x93, +0x60, +0xa, +0x2, +0x70, +0x83, +0x88, +0x6b, +0x0, +0x0, +0x60, +0xa0, +0xf, +0x43, +0x4b, +0x4f, +0x50, +0x60, +0x70, +0x57, +0x52, +0x41, +0x4d, +0x60, +0x61, +0xa4, +0x61, +0xa1, +0x3, +0xa4, +0x1, +0xa0, +0x29, +0x93, +0x60, +0xa, +0x3, +0x8, +0x50, +0x45, +0x4f, +0x50, +0x12, +0x4, +0x2, +0x0, +0x0, +0x70, +0x0, +0x88, +0x50, +0x45, +0x4f, +0x50, +0x0, +0x0, +0x70, +0x4f, +0x50, +0x5f, +0x5f, +0x88, +0x50, +0x45, +0x4f, +0x50, +0x1, +0x0, +0xa4, +0x50, +0x45, +0x4f, +0x50, +0xa0, +0x8, +0x93, +0x60, +0xa, +0x4, +0xa4, +0xa, +0x2, +0xa0, +0xd, +0x93, +0x60, +0xa, +0x5, +0x70, +0x52, +0x52, +0x41, +0x4d, +0x60, +0xa4, +0x60, +0xa0, +0x8, +0x93, +0x60, +0xa, +0x6, +0xa4, +0xa, +0x3, +0xa0, +0x20, +0x93, +0x60, +0xa, +0x7, +0x70, +0x83, +0x88, +0x6b, +0x0, +0x0, +0x60, +0xa0, +0xf, +0x43, +0x4b, +0x4f, +0x50, +0x60, +0x70, +0x57, +0x52, +0x41, +0x4d, +0x60, +0x61, +0xa4, +0x61, +0xa1, +0x3, +0xa4, +0x1, +0xa0, +0x1a, +0x93, +0x60, +0xa, +0x8, +0x70, +0x83, +0x88, +0x6b, +0x0, +0x0, +0x60, +0xa0, +0x9, +0x43, +0x4b, +0x4f, +0x50, +0x60, +0xa4, +0xa, +0x4, +0xa1, +0x3, +0xa4, +0x0, +0xa4, +0x11, +0x3, +0x1, +0x0 }; diff --git a/hw/i386/ssdt-tpm2.dsl b/hw/i386/ssdt-tpm2.dsl index 58bbbf8..29228a0 100644 --- a/hw/i386/ssdt-tpm2.dsl +++ b/hw/i386/ssdt-tpm2.dsl @@ -25,5 +25,6 @@ DefinitionBlock ( 0x1 // OEM Revision ) { +#define TPM_2_0 #include "ssdt-tpm-common.dsl" } diff --git a/hw/i386/ssdt-tpm2.hex.generated b/hw/i386/ssdt-tpm2.hex.generated index 9ea8271..a685533 100644 --- a/hw/i386/ssdt-tpm2.hex.generated +++ b/hw/i386/ssdt-tpm2.hex.generated @@ -3,12 +3,12 @@ static unsigned char ssdt_tpm2_aml[] = { 0x53, 0x44, 0x54, -0x6b, -0x0, +0x61, +0x2, 0x0, 0x0, 0x1, -0x37, +0xe, 0x42, 0x58, 0x50, @@ -36,8 +36,8 @@ static unsigned char ssdt_tpm2_aml[] = { 0x14, 0x20, 0x10, -0x46, -0x4, +0x4c, +0x23, 0x5c, 0x2f, 0x3, @@ -55,7 +55,8 @@ static unsigned char ssdt_tpm2_aml[] = { 0x5f, 0x5b, 0x82, -0x33, +0x49, +0x22, 0x54, 0x50, 0x4d, @@ -105,5 +106,506 @@ static unsigned char ssdt_tpm2_aml[] = { 0x0, 0xa4, 0xa, -0xf +0xf, +0x5b, +0x80, +0x54, +0x54, +0x49, +0x53, +0x0, +0xc, +0x0, +0x0, +0xd4, +0xfe, +0xb, +0x0, +0x50, +0x5b, +0x81, +0xf, +0x54, +0x54, +0x49, +0x53, +0x0, +0x0, +0x80, +0xc8, +0x7, +0x54, +0x44, +0x42, +0x47, +0x20, +0x8, +0x4f, +0x50, +0x5f, +0x5f, +0x0, +0x5b, +0x80, +0x48, +0x49, +0x47, +0x48, +0x0, +0xc, +0xa0, +0xf, +0xd4, +0xfe, +0xa, +0xe, +0x14, +0x42, +0x4, +0x57, +0x52, +0x41, +0x4d, +0x9, +0x5b, +0x81, +0x15, +0x48, +0x49, +0x47, +0x48, +0x0, +0x53, +0x49, +0x47, +0x31, +0x20, +0x53, +0x49, +0x5a, +0x45, +0x10, +0x43, +0x4f, +0x44, +0x45, +0x8, +0xa0, +0x21, +0x90, +0x93, +0x53, +0x49, +0x47, +0x31, +0xc, +0x54, +0x43, +0x50, +0x41, +0x92, +0x95, +0x53, +0x49, +0x5a, +0x45, +0x1, +0x70, +0x68, +0x43, +0x4f, +0x44, +0x45, +0x70, +0x68, +0x4f, +0x50, +0x5f, +0x5f, +0xa4, +0x0, +0xa4, +0x1, +0x14, +0x47, +0x7, +0x52, +0x52, +0x41, +0x4d, +0x8, +0x8, +0x4f, +0x50, +0x52, +0x45, +0x12, +0x5, +0x3, +0x1, +0x0, +0x0, +0x5b, +0x81, +0x24, +0x48, +0x49, +0x47, +0x48, +0x0, +0x53, +0x49, +0x47, +0x31, +0x20, +0x53, +0x49, +0x5a, +0x45, +0x10, +0x43, +0x4f, +0x44, +0x45, +0x8, +0x53, +0x55, +0x43, +0x43, +0x8, +0x43, +0x4f, +0x44, +0x4f, +0x8, +0x52, +0x45, +0x53, +0x50, +0x20, +0xa0, +0x39, +0x90, +0x93, +0x53, +0x49, +0x47, +0x31, +0xc, +0x54, +0x43, +0x50, +0x41, +0x92, +0x95, +0x53, +0x49, +0x5a, +0x45, +0xa, +0x7, +0x70, +0x53, +0x55, +0x43, +0x43, +0x88, +0x4f, +0x50, +0x52, +0x45, +0x0, +0x0, +0x70, +0x43, +0x4f, +0x44, +0x4f, +0x88, +0x4f, +0x50, +0x52, +0x45, +0x1, +0x0, +0x70, +0x52, +0x45, +0x53, +0x50, +0x88, +0x4f, +0x50, +0x52, +0x45, +0xa, +0x2, +0x0, +0xa4, +0x4f, +0x50, +0x52, +0x45, +0x14, +0x11, +0x43, +0x4b, +0x4f, +0x50, +0x1, +0xa0, +0x6, +0x93, +0x68, +0x0, +0xa4, +0x1, +0xa1, +0x3, +0xa4, +0x0, +0x14, +0x43, +0xf, +0x5f, +0x44, +0x53, +0x4d, +0xc, +0xa0, +0x46, +0xe, +0x93, +0x68, +0x11, +0x13, +0xa, +0x10, +0xa6, +0xfa, +0xdd, +0x3d, +0x1b, +0x36, +0xb4, +0x4e, +0xa4, +0x24, +0x8d, +0x10, +0x8, +0x9d, +0x16, +0x53, +0xa0, +0xa, +0x92, +0x93, +0x69, +0x1, +0xa4, +0x11, +0x3, +0x1, +0x0, +0x70, +0x99, +0x6a, +0x0, +0x60, +0xa0, +0xb, +0x93, +0x60, +0x0, +0xa4, +0x11, +0x5, +0xa, +0x2, +0xff, +0x1, +0xa0, +0xa, +0x93, +0x60, +0x1, +0xa4, +0xd, +0x31, +0x2e, +0x32, +0x0, +0xa0, +0x20, +0x93, +0x60, +0xa, +0x2, +0x70, +0x83, +0x88, +0x6b, +0x0, +0x0, +0x60, +0xa0, +0xf, +0x43, +0x4b, +0x4f, +0x50, +0x60, +0x70, +0x57, +0x52, +0x41, +0x4d, +0x60, +0x61, +0xa4, +0x61, +0xa1, +0x3, +0xa4, +0x1, +0xa0, +0x29, +0x93, +0x60, +0xa, +0x3, +0x8, +0x50, +0x45, +0x4f, +0x50, +0x12, +0x4, +0x2, +0x0, +0x0, +0x70, +0x0, +0x88, +0x50, +0x45, +0x4f, +0x50, +0x0, +0x0, +0x70, +0x4f, +0x50, +0x5f, +0x5f, +0x88, +0x50, +0x45, +0x4f, +0x50, +0x1, +0x0, +0xa4, +0x50, +0x45, +0x4f, +0x50, +0xa0, +0x8, +0x93, +0x60, +0xa, +0x4, +0xa4, +0xa, +0x2, +0xa0, +0xd, +0x93, +0x60, +0xa, +0x5, +0x70, +0x52, +0x52, +0x41, +0x4d, +0x60, +0xa4, +0x60, +0xa0, +0x8, +0x93, +0x60, +0xa, +0x6, +0xa4, +0xa, +0x3, +0xa0, +0x20, +0x93, +0x60, +0xa, +0x7, +0x70, +0x83, +0x88, +0x6b, +0x0, +0x0, +0x60, +0xa0, +0xf, +0x43, +0x4b, +0x4f, +0x50, +0x60, +0x70, +0x57, +0x52, +0x41, +0x4d, +0x60, +0x61, +0xa4, +0x61, +0xa1, +0x3, +0xa4, +0x1, +0xa0, +0x1a, +0x93, +0x60, +0xa, +0x8, +0x70, +0x83, +0x88, +0x6b, +0x0, +0x0, +0x60, +0xa0, +0x9, +0x43, +0x4b, +0x4f, +0x50, +0x60, +0xa4, +0xa, +0x4, +0xa1, +0x3, +0xa4, +0x0, +0xa4, +0x11, +0x3, +0x1, +0x0 }; diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h index 6d516c6..4437543 100644 --- a/include/hw/acpi/tpm.h +++ b/include/hw/acpi/tpm.h @@ -31,4 +31,23 @@ #define TPM2_START_METHOD_MMIO 6 +/* + * Physical Presence Interface -- shared with the BIOS + */ +#define TCG_MAGIC 0x41504354 + +#if 0 +struct tpm_ppi { + uint32_t sign; // 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 +} QEMU_PACKED; +#endif + +#define TPM_PPI_STRUCT_SIZE 14 + #endif /* HW_ACPI_TPM_H */ -- 1.9.3