diff mbox

[v2,3/6] Support Physical Presence Interface Spec

Message ID 1431101720-701152-4-git-send-email-stefanb@linux.vnet.ibm.com
State New
Headers show

Commit Message

Stefan Berger May 8, 2015, 4:15 p.m. UTC
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(+)

Comments

Stefan Berger May 8, 2015, 6:02 p.m. UTC | #1
Stefan Berger <stefanb@linux.vnet.ibm.com> wrote on 05/08/2015 12:15:17 
PM:

> From: Stefan Berger <stefanb@linux.vnet.ibm.com>
> To: qemu-devel@nongnu.org, mst@redhat.com
> Cc: imammedo@redhat.com, quan.xu@intel.com, Stefan Berger/Watson/
> IBM@IBMUS, kevin@koconnor.net, Stefan Berger 
<stefanb@linux.vnet.ibm.com>
> Date: 05/08/2015 12:15 PM
> Subject: [PATCH v2 3/6] Support Physical Presence Interface Spec
> 
> 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 supposedto 
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.
> 


The SeaBIOS part is now here:

http://www.seabios.org/pipermail/seabios/2015-May/009135.html


   Stefan
Igor Mammedov May 15, 2015, 3:13 p.m. UTC | #2
On Fri,  8 May 2015 12:15:17 -0400
Stefan Berger <stefanb@linux.vnet.ibm.com> wrote:

> 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(+)
> 

Ditto, please redo below ASL using C AML API.
API might not have all ASL ops you've used here but you can
reuse some from following series
 "Generate ACPI v5.1 tables and expose them to guest over fw_cfg on ARM"
and add missing ones.


> 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
I don't see it being used here,
What do you need it for?

> +            }
> +
> +            // 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)
dynamic OperationRegion-s are better to be avoided, Windows can't/doesn't check
its correctness at table load time.
Put it at device scope so that guest OS would notice address collisions
if there would be any.

> +                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)
with OperationRegion at device scope you can drop this.

> +                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),
using SIG1 seems to be redundant now, the same goes for BIOS part.
Why just not drop it?

> +                    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
check looks like the same as above, split out into a separate function?

> +                        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
ditto

> +                        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 */
Stefan Berger May 15, 2015, 6:24 p.m. UTC | #3
On 05/15/2015 11:13 AM, Igor Mammedov wrote:
> On Fri,  8 May 2015 12:15:17 -0400
> Stefan Berger <stefanb@linux.vnet.ibm.com> wrote:
>
>> 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(+)
>>
> Ditto, please redo below ASL using C AML API.
> API might not have all ASL ops you've used here but you can
> reuse some from following series
>   "Generate ACPI v5.1 tables and expose them to guest over fw_cfg on ARM"
> and add missing ones.
>
>
>> 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
> I don't see it being used here,
> What do you need it for?

I used it for debugging. Removed it.


>
>> +            }
>> +
>> +            // 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)
> dynamic OperationRegion-s are better to be avoided, Windows can't/doesn't check
> its correctness at table load time.
> Put it at device scope so that guest OS would notice address collisions
> if there would be any.


Done.

>
>> +                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)
> with OperationRegion at device scope you can drop this.

Ok.

>
>> +                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),
> using SIG1 seems to be redundant now, the same goes for BIOS part.
> Why just not drop it?


As a marker that the memory was initialized by the TPM?



>> +                    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
> check looks like the same as above, split out into a separate function?

Split out into CKOP().

>
>> +                        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
> ditto


Fixed.
Stefan Berger May 22, 2015, 12:20 a.m. UTC | #4
On 05/15/2015 11:13 AM, Igor Mammedov wrote:
>
>> +                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),
> using SIG1 seems to be redundant now, the same goes for BIOS part.
> Why just not drop it?


I would like to keep the signature as an indicator that the BIOS has 
initialized the memory. Would that be acceptable ? QEMU provides the 
ACPI, the BIOS is indep. of it and the OS only sees what QEMU has 
provided. The OS  wouldn't know whether there's a BIOS that supports it 
what the ACPI indicates.


>
>   }
> 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

I removed sign2 from the SeaBIOS code, so only 1 signature.

    Stefan
diff mbox

Patch

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 */