diff mbox

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

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

Commit Message

Stefan Berger May 26, 2015, 9:33 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>

---

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

Comments

Michael S. Tsirkin May 31, 2015, 6:11 p.m. UTC | #1
On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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

memory

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

No need for 2 empty spaces.

> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Cc: Kevin O'Connor <kevin@koconnor.net>

All this seems somewhat messy.  Is this FSEG trick what the spec says,
or is this a QEMU specific protocol?
Would DataTableRegion not be a better way to locate things in
memory?



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

coding style violation.

> +    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
>
Stefan Berger June 2, 2015, 3:11 a.m. UTC | #2
On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
> On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
> memory
>
>> 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.
>>
>>
> No need for 2 empty spaces.
>
>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>> Cc: Michael Tsirkin <mst@redhat.com>
>> Cc: Kevin O'Connor <kevin@koconnor.net>
> All this seems somewhat messy.  Is this FSEG trick what the spec says,
> or is this a QEMU specific protocol?

Actually, the text in the patch is outdated. We now moved the area where 
the data are exchanged between ACPI and BIOS into registers provided by 
the TIS -- custom registers in an area that is vendor-specific, so yes, 
this is a QEMU specific solution. The address range for this is fixed 
and known to SeaBIOS and QEMU. Those registers also won't reset upon 
machine reboot.

> Would DataTableRegion not be a better way to locate things in
> memory?

As I said, we now move that into a memory region provide by the TIS.. 
Otherwise I am not very familiar with DataTableRegion.

Thanks for the comments!

     Stefan


>> ---
>>
>> 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 {
> coding style violation.
>
>> +    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
>>
Michael S. Tsirkin June 2, 2015, 9:15 a.m. UTC | #3
On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
> On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
> >On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
> >memory
> >
> >>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.
> >>
> >>
> >No need for 2 empty spaces.
> >
> >>Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >>Cc: Michael Tsirkin <mst@redhat.com>
> >>Cc: Kevin O'Connor <kevin@koconnor.net>
> >All this seems somewhat messy.  Is this FSEG trick what the spec says,
> >or is this a QEMU specific protocol?
> 
> Actually, the text in the patch is outdated. We now moved the area where the
> data are exchanged between ACPI and BIOS into registers provided by the TIS
> -- custom registers in an area that is vendor-specific, so yes, this is a
> QEMU specific solution. The address range for this is fixed and known to
> SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.

Hmm. One way to do a machine reboot is to exit QEMU
then restart it. Where do these registers persist?

> >Would DataTableRegion not be a better way to locate things in
> >memory?
> 
> As I said, we now move that into a memory region provide by the TIS..
> Otherwise I am not very familiar with DataTableRegion.
> 
> Thanks for the comments!
> 
>     Stefan

A data table is a structure that you define (as opposed to code).
Using linker you can allocate some memory and put a pointer
there, then use DataTableRegion to read that pointer value.
Stefan Berger June 2, 2015, 1:22 p.m. UTC | #4
On 06/02/2015 05:15 AM, Michael S. Tsirkin wrote:
> On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
>> On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
>>> On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
>>> memory
>>>
>>>> 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.
>>>>
>>>>
>>> No need for 2 empty spaces.
>>>
>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>> Cc: Michael Tsirkin <mst@redhat.com>
>>>> Cc: Kevin O'Connor <kevin@koconnor.net>
>>> All this seems somewhat messy.  Is this FSEG trick what the spec says,
>>> or is this a QEMU specific protocol?
>> Actually, the text in the patch is outdated. We now moved the area where the
>> data are exchanged between ACPI and BIOS into registers provided by the TIS
>> -- custom registers in an area that is vendor-specific, so yes, this is a
>> QEMU specific solution. The address range for this is fixed and known to
>> SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.
> Hmm. One way to do a machine reboot is to exit QEMU
> then restart it. Where do these registers persist?


They won't persist. If one powers down the physical machine, this won't 
work or not that I would know of that it would have to work.


>
>>> Would DataTableRegion not be a better way to locate things in
>>> memory?
>> As I said, we now move that into a memory region provide by the TIS..
>> Otherwise I am not very familiar with DataTableRegion.
>>
>> Thanks for the comments!
>>
>>      Stefan
> A data table is a structure that you define (as opposed to code).
> Using linker you can allocate some memory and put a pointer
> there, then use DataTableRegion to read that pointer value.
>

How would the BIOS then find that memory (so it can read the command 
code and act on it)? Would it need to walk ACPI tables or how would it 
find the base address?

     Stefan
Michael S. Tsirkin June 2, 2015, 1:30 p.m. UTC | #5
On Tue, Jun 02, 2015 at 09:22:40AM -0400, Stefan Berger wrote:
> On 06/02/2015 05:15 AM, Michael S. Tsirkin wrote:
> >On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
> >>On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
> >>>On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
> >>>memory
> >>>
> >>>>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.
> >>>>
> >>>>
> >>>No need for 2 empty spaces.
> >>>
> >>>>Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >>>>Cc: Michael Tsirkin <mst@redhat.com>
> >>>>Cc: Kevin O'Connor <kevin@koconnor.net>
> >>>All this seems somewhat messy.  Is this FSEG trick what the spec says,
> >>>or is this a QEMU specific protocol?
> >>Actually, the text in the patch is outdated. We now moved the area where the
> >>data are exchanged between ACPI and BIOS into registers provided by the TIS
> >>-- custom registers in an area that is vendor-specific, so yes, this is a
> >>QEMU specific solution. The address range for this is fixed and known to
> >>SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.
> >Hmm. One way to do a machine reboot is to exit QEMU
> >then restart it. Where do these registers persist?
> 
> 
> They won't persist. If one powers down the physical machine, this won't work
> or not that I would know of that it would have to work.
> 
> 
> >
> >>>Would DataTableRegion not be a better way to locate things in
> >>>memory?
> >>As I said, we now move that into a memory region provide by the TIS..
> >>Otherwise I am not very familiar with DataTableRegion.
> >>
> >>Thanks for the comments!
> >>
> >>     Stefan
> >A data table is a structure that you define (as opposed to code).
> >Using linker you can allocate some memory and put a pointer
> >there, then use DataTableRegion to read that pointer value.
> >
> 
> How would the BIOS then find that memory (so it can read the command code
> and act on it)? Would it need to walk ACPI tables or how would it find the
> base address?
> 
>     Stefan

This is similar to things like suspend/resume.

The bios walks the list of the tables RSDP->XSDT, and locates the
data table either by triple signature/vendorid/vendortableid,
or by detecting a UEFI signature and locating the matching GUID
(second option is preferable given current OVMF code).
Stefan Berger June 2, 2015, 2:28 p.m. UTC | #6
On 06/02/2015 09:30 AM, Michael S. Tsirkin wrote:
> On Tue, Jun 02, 2015 at 09:22:40AM -0400, Stefan Berger wrote:
>> On 06/02/2015 05:15 AM, Michael S. Tsirkin wrote:
>>> On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
>>>> On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
>>>>> On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
>>>>> memory
>>>>>
>>>>>> 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.
>>>>>>
>>>>>>
>>>>> No need for 2 empty spaces.
>>>>>
>>>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>>>> Cc: Michael Tsirkin <mst@redhat.com>
>>>>>> Cc: Kevin O'Connor <kevin@koconnor.net>
>>>>> All this seems somewhat messy.  Is this FSEG trick what the spec says,
>>>>> or is this a QEMU specific protocol?
>>>> Actually, the text in the patch is outdated. We now moved the area where the
>>>> data are exchanged between ACPI and BIOS into registers provided by the TIS
>>>> -- custom registers in an area that is vendor-specific, so yes, this is a
>>>> QEMU specific solution. The address range for this is fixed and known to
>>>> SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.
>>> Hmm. One way to do a machine reboot is to exit QEMU
>>> then restart it. Where do these registers persist?
>>
>> They won't persist. If one powers down the physical machine, this won't work
>> or not that I would know of that it would have to work.
>>
>>
>>>>> Would DataTableRegion not be a better way to locate things in
>>>>> memory?
>>>> As I said, we now move that into a memory region provide by the TIS..
>>>> Otherwise I am not very familiar with DataTableRegion.
>>>>
>>>> Thanks for the comments!
>>>>
>>>>      Stefan
>>> A data table is a structure that you define (as opposed to code).
>>> Using linker you can allocate some memory and put a pointer
>>> there, then use DataTableRegion to read that pointer value.
>>>
>> How would the BIOS then find that memory (so it can read the command code
>> and act on it)? Would it need to walk ACPI tables or how would it find the
>> base address?
>>
>>      Stefan
> This is similar to things like suspend/resume.
>
> The bios walks the list of the tables RSDP->XSDT, and locates the
> data table either by triple signature/vendorid/vendortableid,
> or by detecting a UEFI signature and locating the matching GUID
> (second option is preferable given current OVMF code).

We would need to create an XSDT with at least two entries, one pointing 
to the existing FADT (per spec) and one to this new table with what 
signature? Do you have a pointer to a table structure identifiable by 
UEFI signature and GUID to see how this looks like? ACPI will identify 
it by triple signature, though, right ?  Should the XSDT always be there 
or only if we have a TPM?

How would I mark the DataTableRegion as AddressRangeReserved or would it 
automatically be?

Would the ACPI code then internally walk the list of tables attached to 
the XSDT and find the address of that table and make it available so 
that we can define a Field() on it. Assuming the DataTableRegion is 
called AAAA, would we then define a Field(AAAA, AnyAcc,...) on it?

Well, I am not sure how involved this is going to be, so maybe I would 
defer this ACPI support for now unless we could live with the proposed 
solution and UEFI could use it as well when run on QEMU. And I am glad 
that I haven't converted the ASL to C code, because this would make it a 
lot more difficult to develop and debug...

      Stefan
Michael S. Tsirkin June 2, 2015, 2:46 p.m. UTC | #7
On Tue, Jun 02, 2015 at 10:28:52AM -0400, Stefan Berger wrote:
> On 06/02/2015 09:30 AM, Michael S. Tsirkin wrote:
> >On Tue, Jun 02, 2015 at 09:22:40AM -0400, Stefan Berger wrote:
> >>On 06/02/2015 05:15 AM, Michael S. Tsirkin wrote:
> >>>On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
> >>>>On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
> >>>>>On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
> >>>>>memory
> >>>>>
> >>>>>>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.
> >>>>>>
> >>>>>>
> >>>>>No need for 2 empty spaces.
> >>>>>
> >>>>>>Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >>>>>>Cc: Michael Tsirkin <mst@redhat.com>
> >>>>>>Cc: Kevin O'Connor <kevin@koconnor.net>
> >>>>>All this seems somewhat messy.  Is this FSEG trick what the spec says,
> >>>>>or is this a QEMU specific protocol?
> >>>>Actually, the text in the patch is outdated. We now moved the area where the
> >>>>data are exchanged between ACPI and BIOS into registers provided by the TIS
> >>>>-- custom registers in an area that is vendor-specific, so yes, this is a
> >>>>QEMU specific solution. The address range for this is fixed and known to
> >>>>SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.
> >>>Hmm. One way to do a machine reboot is to exit QEMU
> >>>then restart it. Where do these registers persist?
> >>
> >>They won't persist. If one powers down the physical machine, this won't work
> >>or not that I would know of that it would have to work.
> >>
> >>
> >>>>>Would DataTableRegion not be a better way to locate things in
> >>>>>memory?
> >>>>As I said, we now move that into a memory region provide by the TIS..
> >>>>Otherwise I am not very familiar with DataTableRegion.
> >>>>
> >>>>Thanks for the comments!
> >>>>
> >>>>     Stefan
> >>>A data table is a structure that you define (as opposed to code).
> >>>Using linker you can allocate some memory and put a pointer
> >>>there, then use DataTableRegion to read that pointer value.
> >>>
> >>How would the BIOS then find that memory (so it can read the command code
> >>and act on it)? Would it need to walk ACPI tables or how would it find the
> >>base address?
> >>
> >>     Stefan
> >This is similar to things like suspend/resume.
> >
> >The bios walks the list of the tables RSDP->XSDT, and locates the
> >data table either by triple signature/vendorid/vendortableid,
> >or by detecting a UEFI signature and locating the matching GUID
> >(second option is preferable given current OVMF code).
> 
> We would need to create an XSDT with at least two entries, one pointing to
> the existing FADT (per spec) and one to this new table with what signature?

I think XSDT has same content as RSDT + new tables from ACPI 2 spec.

> Do you have a pointer to a table structure identifiable by UEFI signature
> and GUID to see how this looks like?

Look it up in Appendix O (that a letter O, not zero) in the UEFI spec.

> ACPI will identify it by triple
> signature, though, right ?  Should the XSDT always be there or only if we
> have a TPM?

I'm looking at adding it unconditionally, this let us use ACPI 2
funcitonality without crashing XP guests.

> How would I mark the DataTableRegion as AddressRangeReserved or would it
> automatically be?

It's automatically either AddressRangeReserved or AddressRangeNVS.
It doesn't look like you have control over which it is.
seabios makes it reserved, nvs makes it 

> Would the ACPI code then internally walk the list of tables attached to the
> XSDT and find the address of that table and make it available so that we can
> define a Field() on it.

Yes.

> Assuming the DataTableRegion is called AAAA, would
> we then define a Field(AAAA, AnyAcc,...) on it?

Exactly.

> Well, I am not sure how involved this is going to be, so maybe I would defer
> this ACPI support for now unless we could live with the proposed solution
> and UEFI could use it as well when run on QEMU. And I am glad that I haven't
> converted the ASL to C code, because this would make it a lot more difficult
> to develop and debug...
> 
>      Stefan
Michael S. Tsirkin June 2, 2015, 3 p.m. UTC | #8
On Tue, Jun 02, 2015 at 10:28:52AM -0400, Stefan Berger wrote:
> And I am glad that I haven't
> converted the ASL to C code, because this would make it a lot more difficult
> to develop and debug...
> 
>      Stefan

Let's avoid hyperbole.  Mostly there's a bunch of aml_append calls
sprinkled on each line of ASL code.

It's harder to develop since there's no compiler catching mistakes
statically, that's true.
Debugging is more or less the same since you can always
dump the tables and disassemble them with iasl.
Stefan Berger June 2, 2015, 3:06 p.m. UTC | #9
On 06/02/2015 10:46 AM, Michael S. Tsirkin wrote:
> On Tue, Jun 02, 2015 at 10:28:52AM -0400, Stefan Berger wrote:
>> On 06/02/2015 09:30 AM, Michael S. Tsirkin wrote:
>>> On Tue, Jun 02, 2015 at 09:22:40AM -0400, Stefan Berger wrote:
>>>> On 06/02/2015 05:15 AM, Michael S. Tsirkin wrote:
>>>>> On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
>>>>>> On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
>>>>>>> On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
>>>>>>> memory
>>>>>>>
>>>>>>>> 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.
>>>>>>>>
>>>>>>>>
>>>>>>> No need for 2 empty spaces.
>>>>>>>
>>>>>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>>>>>> Cc: Michael Tsirkin <mst@redhat.com>
>>>>>>>> Cc: Kevin O'Connor <kevin@koconnor.net>
>>>>>>> All this seems somewhat messy.  Is this FSEG trick what the spec says,
>>>>>>> or is this a QEMU specific protocol?
>>>>>> Actually, the text in the patch is outdated. We now moved the area where the
>>>>>> data are exchanged between ACPI and BIOS into registers provided by the TIS
>>>>>> -- custom registers in an area that is vendor-specific, so yes, this is a
>>>>>> QEMU specific solution. The address range for this is fixed and known to
>>>>>> SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.
>>>>> Hmm. One way to do a machine reboot is to exit QEMU
>>>>> then restart it. Where do these registers persist?
>>>> They won't persist. If one powers down the physical machine, this won't work
>>>> or not that I would know of that it would have to work.
>>>>
>>>>
>>>>>>> Would DataTableRegion not be a better way to locate things in
>>>>>>> memory?
>>>>>> As I said, we now move that into a memory region provide by the TIS..
>>>>>> Otherwise I am not very familiar with DataTableRegion.
>>>>>>
>>>>>> Thanks for the comments!
>>>>>>
>>>>>>      Stefan
>>>>> A data table is a structure that you define (as opposed to code).
>>>>> Using linker you can allocate some memory and put a pointer
>>>>> there, then use DataTableRegion to read that pointer value.
>>>>>
>>>> How would the BIOS then find that memory (so it can read the command code
>>>> and act on it)? Would it need to walk ACPI tables or how would it find the
>>>> base address?
>>>>
>>>>      Stefan
>>> This is similar to things like suspend/resume.
>>>
>>> The bios walks the list of the tables RSDP->XSDT, and locates the
>>> data table either by triple signature/vendorid/vendortableid,
>>> or by detecting a UEFI signature and locating the matching GUID
>>> (second option is preferable given current OVMF code).
>> We would need to create an XSDT with at least two entries, one pointing to
>> the existing FADT (per spec) and one to this new table with what signature?
> I think XSDT has same content as RSDT + new tables from ACPI 2 spec.



>
>> Do you have a pointer to a table structure identifiable by UEFI signature
>> and GUID to see how this looks like?
> Look it up in Appendix O (that a letter O, not zero) in the UEFI spec.

Thanks. UEFI is the signature. OemTableIDString would have to be the 
unique part. I don't see a GUID  -- so not sure how to weave this in 
unless it goes into the Data area.



>> ACPI will identify it by triple
>> signature, though, right ?  Should the XSDT always be there or only if we
>> have a TPM?
> I'm looking at adding it unconditionally, this let us use ACPI 2
> funcitonality without crashing XP guests.

So you'll add that then? Then let me defer the ACPI support for now.


>
>> How would I mark the DataTableRegion as AddressRangeReserved or would it
>> automatically be?
> It's automatically either AddressRangeReserved or AddressRangeNVS.
> It doesn't look like you have control over which it is.
> seabios makes it reserved, nvs makes it


just by being marked as reserved via e820 ?

>
>> Would the ACPI code then internally walk the list of tables attached to the
>> XSDT and find the address of that table and make it available so that we can
>> define a Field() on it.
> Yes.
>
>> Assuming the DataTableRegion is called AAAA, would
>> we then define a Field(AAAA, AnyAcc,...) on it?
> Exactly.

Ok, so it looks like the offset where the stuff then goes would be at 
offset 54.
Michael S. Tsirkin June 2, 2015, 3:11 p.m. UTC | #10
On Tue, Jun 02, 2015 at 11:06:54AM -0400, Stefan Berger wrote:
> On 06/02/2015 10:46 AM, Michael S. Tsirkin wrote:
> >On Tue, Jun 02, 2015 at 10:28:52AM -0400, Stefan Berger wrote:
> >>On 06/02/2015 09:30 AM, Michael S. Tsirkin wrote:
> >>>On Tue, Jun 02, 2015 at 09:22:40AM -0400, Stefan Berger wrote:
> >>>>On 06/02/2015 05:15 AM, Michael S. Tsirkin wrote:
> >>>>>On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
> >>>>>>On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
> >>>>>>>On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
> >>>>>>>memory
> >>>>>>>
> >>>>>>>>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.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>No need for 2 empty spaces.
> >>>>>>>
> >>>>>>>>Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >>>>>>>>Cc: Michael Tsirkin <mst@redhat.com>
> >>>>>>>>Cc: Kevin O'Connor <kevin@koconnor.net>
> >>>>>>>All this seems somewhat messy.  Is this FSEG trick what the spec says,
> >>>>>>>or is this a QEMU specific protocol?
> >>>>>>Actually, the text in the patch is outdated. We now moved the area where the
> >>>>>>data are exchanged between ACPI and BIOS into registers provided by the TIS
> >>>>>>-- custom registers in an area that is vendor-specific, so yes, this is a
> >>>>>>QEMU specific solution. The address range for this is fixed and known to
> >>>>>>SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.
> >>>>>Hmm. One way to do a machine reboot is to exit QEMU
> >>>>>then restart it. Where do these registers persist?
> >>>>They won't persist. If one powers down the physical machine, this won't work
> >>>>or not that I would know of that it would have to work.
> >>>>
> >>>>
> >>>>>>>Would DataTableRegion not be a better way to locate things in
> >>>>>>>memory?
> >>>>>>As I said, we now move that into a memory region provide by the TIS..
> >>>>>>Otherwise I am not very familiar with DataTableRegion.
> >>>>>>
> >>>>>>Thanks for the comments!
> >>>>>>
> >>>>>>     Stefan
> >>>>>A data table is a structure that you define (as opposed to code).
> >>>>>Using linker you can allocate some memory and put a pointer
> >>>>>there, then use DataTableRegion to read that pointer value.
> >>>>>
> >>>>How would the BIOS then find that memory (so it can read the command code
> >>>>and act on it)? Would it need to walk ACPI tables or how would it find the
> >>>>base address?
> >>>>
> >>>>     Stefan
> >>>This is similar to things like suspend/resume.
> >>>
> >>>The bios walks the list of the tables RSDP->XSDT, and locates the
> >>>data table either by triple signature/vendorid/vendortableid,
> >>>or by detecting a UEFI signature and locating the matching GUID
> >>>(second option is preferable given current OVMF code).
> >>We would need to create an XSDT with at least two entries, one pointing to
> >>the existing FADT (per spec) and one to this new table with what signature?
> >I think XSDT has same content as RSDT + new tables from ACPI 2 spec.
> 
> 
> 
> >
> >>Do you have a pointer to a table structure identifiable by UEFI signature
> >>and GUID to see how this looks like?
> >Look it up in Appendix O (that a letter O, not zero) in the UEFI spec.
> 
> Thanks. UEFI is the signature. OemTableIDString would have to be the unique
> part. I don't see a GUID  -- so not sure how to weave this in unless it goes
> into the Data area.
> 
> 
> 
> >>ACPI will identify it by triple
> >>signature, though, right ?  Should the XSDT always be there or only if we
> >>have a TPM?
> >I'm looking at adding it unconditionally, this let us use ACPI 2
> >funcitonality without crashing XP guests.
> 
> So you'll add that then? Then let me defer the ACPI support for now.
> 
> 
> >
> >>How would I mark the DataTableRegion as AddressRangeReserved or would it
> >>automatically be?
> >It's automatically either AddressRangeReserved or AddressRangeNVS.
> >It doesn't look like you have control over which it is.
> >seabios makes it reserved, nvs makes it
> 
> 
> just by being marked as reserved via e820 ?

bios allocates it and marks it reserved in e820, efi allocates
it and marks it nvs in e820.

> >
> >>Would the ACPI code then internally walk the list of tables attached to the
> >>XSDT and find the address of that table and make it available so that we can
> >>define a Field() on it.
> >Yes.
> >
> >>Assuming the DataTableRegion is called AAAA, would
> >>we then define a Field(AAAA, AnyAcc,...) on it?
> >Exactly.
> 
> Ok, so it looks like the offset where the stuff then goes would be at offset
> 54.

Is the stuff read-only? Or does qemu modify it while guest runs?
If readonly, you can just stick it there, right.
If qemu has to modify it, that would breaks checksum,
so it's better to allocate a blob and put the *pointer*
to blob in the data table.

All problems in computer science can be solved by another level of
indirection.
Kevin O'Connor June 2, 2015, 3:18 p.m. UTC | #11
On Tue, Jun 02, 2015 at 04:46:06PM +0200, Michael S. Tsirkin wrote:
> On Tue, Jun 02, 2015 at 10:28:52AM -0400, Stefan Berger wrote:
> > How would I mark the DataTableRegion as AddressRangeReserved or would it
> > automatically be?
> 
> It's automatically either AddressRangeReserved or AddressRangeNVS.
> It doesn't look like you have control over which it is.
> seabios makes it reserved, nvs makes it 

As I understand it, Stefan wants to do something a little unusual
here.  The goal is to allow the guest OS to send a signal to the BIOS
on the next boot, because the TPM stuff only allows the BIOS to change
certain settings immediately after the machine has booted (or
rebooted).  So, the idea is to allow the guest OS to put some code in
reserved memory that is at a consistent address so that on a reboot
seabios can find that code and take the corresponding action.  The
memory has to be non-volatile across reboots, and it must be someplace
that can be found prior to it being zero'd or overwritten by any init
process.

Did I understand this correctly?

If so, I don't see how the normal QEMU <-> seabios ACPI table
deployment mechanism will help here.  SeaBIOS does reserve the space,
but nothing prevents SeaBIOS from overwriting it before extracting any
updates from a previous boot.

As an aside, I thought putting the updates in a "reserved area" of the
TPM chip was a simple solution to this problem.  That way, it's easy
for the guest OS and SeaBIOS to know where the codes will be stored,
and no chance any init process will overwrite it by accident.

For reference, the original solution was for SeaBIOS to declare an
area of reserved memory and do it in such a way that the address would
be consistent across reboots and would not be overwritten by any init
process.  The problem with this approach was that the guest OS didn't
implicitly know where that area of memory was, and it had to "table
scan" to find the address - that was deemed too ugly.

-Kevin
Stefan Berger June 2, 2015, 4:18 p.m. UTC | #12
On 06/02/2015 11:18 AM, Kevin O'Connor wrote:
> On Tue, Jun 02, 2015 at 04:46:06PM +0200, Michael S. Tsirkin wrote:
>> On Tue, Jun 02, 2015 at 10:28:52AM -0400, Stefan Berger wrote:
>>> How would I mark the DataTableRegion as AddressRangeReserved or would it
>>> automatically be?
>> It's automatically either AddressRangeReserved or AddressRangeNVS.
>> It doesn't look like you have control over which it is.
>> seabios makes it reserved, nvs makes it
> As I understand it, Stefan wants to do something a little unusual
> here.  The goal is to allow the guest OS to send a signal to the BIOS
> on the next boot, because the TPM stuff only allows the BIOS to change
> certain settings immediately after the machine has booted (or
> rebooted).  So, the idea is to allow the guest OS to put some code in
> reserved memory that is at a consistent address so that on a reboot
> seabios can find that code and take the corresponding action.  The
> memory has to be non-volatile across reboots, and it must be someplace
> that can be found prior to it being zero'd or overwritten by any init
> process.
>
> Did I understand this correctly?

Correct.

>
> If so, I don't see how the normal QEMU <-> seabios ACPI table
> deployment mechanism will help here.  SeaBIOS does reserve the space,
> but nothing prevents SeaBIOS from overwriting it before extracting any
> updates from a previous boot.
>
> As an aside, I thought putting the updates in a "reserved area" of the
> TPM chip was a simple solution to this problem.  That way, it's easy
> for the guest OS and SeaBIOS to know where the codes will be stored,
> and no chance any init process will overwrite it by accident.
>
> For reference, the original solution was for SeaBIOS to declare an
> area of reserved memory and do it in such a way that the address would
> be consistent across reboots and would not be overwritten by any init
> process.  The problem with this approach was that the guest OS didn't
> implicitly know where that area of memory was, and it had to "table
> scan" to find the address - that was deemed too ugly.
>
> -Kevin
>
Stefan Berger June 2, 2015, 4:28 p.m. UTC | #13
On 06/02/2015 11:11 AM, Michael S. Tsirkin wrote:
> On Tue, Jun 02, 2015 at 11:06:54AM -0400, Stefan Berger wrote:
>> On 06/02/2015 10:46 AM, Michael S. Tsirkin wrote:
>>> On Tue, Jun 02, 2015 at 10:28:52AM -0400, Stefan Berger wrote:
>>>> On 06/02/2015 09:30 AM, Michael S. Tsirkin wrote:
>>>>> On Tue, Jun 02, 2015 at 09:22:40AM -0400, Stefan Berger wrote:
>>>>>> On 06/02/2015 05:15 AM, Michael S. Tsirkin wrote:
>>>>>>> On Mon, Jun 01, 2015 at 11:11:26PM -0400, Stefan Berger wrote:
>>>>>>>> On 05/31/2015 02:11 PM, Michael S. Tsirkin wrote:
>>>>>>>>> On Tue, May 26, 2015 at 05:33:41PM -0400, Stefan Berger 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
>>>>>>>>> memory
>>>>>>>>>
>>>>>>>>>> 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.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>> No need for 2 empty spaces.
>>>>>>>>>
>>>>>>>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>>>>>>>> Cc: Michael Tsirkin <mst@redhat.com>
>>>>>>>>>> Cc: Kevin O'Connor <kevin@koconnor.net>
>>>>>>>>> All this seems somewhat messy.  Is this FSEG trick what the spec says,
>>>>>>>>> or is this a QEMU specific protocol?
>>>>>>>> Actually, the text in the patch is outdated. We now moved the area where the
>>>>>>>> data are exchanged between ACPI and BIOS into registers provided by the TIS
>>>>>>>> -- custom registers in an area that is vendor-specific, so yes, this is a
>>>>>>>> QEMU specific solution. The address range for this is fixed and known to
>>>>>>>> SeaBIOS and QEMU. Those registers also won't reset upon machine reboot.
>>>>>>> Hmm. One way to do a machine reboot is to exit QEMU
>>>>>>> then restart it. Where do these registers persist?
>>>>>> They won't persist. If one powers down the physical machine, this won't work
>>>>>> or not that I would know of that it would have to work.
>>>>>>
>>>>>>
>>>>>>>>> Would DataTableRegion not be a better way to locate things in
>>>>>>>>> memory?
>>>>>>>> As I said, we now move that into a memory region provide by the TIS..
>>>>>>>> Otherwise I am not very familiar with DataTableRegion.
>>>>>>>>
>>>>>>>> Thanks for the comments!
>>>>>>>>
>>>>>>>>      Stefan
>>>>>>> A data table is a structure that you define (as opposed to code).
>>>>>>> Using linker you can allocate some memory and put a pointer
>>>>>>> there, then use DataTableRegion to read that pointer value.
>>>>>>>
>>>>>> How would the BIOS then find that memory (so it can read the command code
>>>>>> and act on it)? Would it need to walk ACPI tables or how would it find the
>>>>>> base address?
>>>>>>
>>>>>>      Stefan
>>>>> This is similar to things like suspend/resume.
>>>>>
>>>>> The bios walks the list of the tables RSDP->XSDT, and locates the
>>>>> data table either by triple signature/vendorid/vendortableid,
>>>>> or by detecting a UEFI signature and locating the matching GUID
>>>>> (second option is preferable given current OVMF code).
>>>> We would need to create an XSDT with at least two entries, one pointing to
>>>> the existing FADT (per spec) and one to this new table with what signature?
>>> I think XSDT has same content as RSDT + new tables from ACPI 2 spec.
>>
>>
>>>> Do you have a pointer to a table structure identifiable by UEFI signature
>>>> and GUID to see how this looks like?
>>> Look it up in Appendix O (that a letter O, not zero) in the UEFI spec.
>> Thanks. UEFI is the signature. OemTableIDString would have to be the unique
>> part. I don't see a GUID  -- so not sure how to weave this in unless it goes
>> into the Data area.
>>
>>
>>
>>>> ACPI will identify it by triple
>>>> signature, though, right ?  Should the XSDT always be there or only if we
>>>> have a TPM?
>>> I'm looking at adding it unconditionally, this let us use ACPI 2
>>> funcitonality without crashing XP guests.
>> So you'll add that then? Then let me defer the ACPI support for now.
>>
>>
>>>> How would I mark the DataTableRegion as AddressRangeReserved or would it
>>>> automatically be?
>>> It's automatically either AddressRangeReserved or AddressRangeNVS.
>>> It doesn't look like you have control over which it is.
>>> seabios makes it reserved, nvs makes it
>>
>> just by being marked as reserved via e820 ?
> bios allocates it and marks it reserved in e820, efi allocates
> it and marks it nvs in e820.
>
>>>> Would the ACPI code then internally walk the list of tables attached to the
>>>> XSDT and find the address of that table and make it available so that we can
>>>> define a Field() on it.
>>> Yes.
>>>
>>>> Assuming the DataTableRegion is called AAAA, would
>>>> we then define a Field(AAAA, AnyAcc,...) on it?
>>> Exactly.
>> Ok, so it looks like the offset where the stuff then goes would be at offset
>> 54.
> Is the stuff read-only? Or does qemu modify it while guest runs?

QEMU does not modify it. The stuff is read-write, at least some parts of 
it. The ACPI code writes the opcode that the user writes into a sysfs 
file into a location in  memory . The ACPI code also reads the result 
code from the last TPM operation (executed by the BIOS) from that memory 
area.


> If readonly, you can just stick it there, right.
> If qemu has to modify it, that would breaks checksum,
> so it's better to allocate a blob and put the *pointer*
> to blob in the data table.

Right, the checksum. So we need to declare the base address of our 
memory area using OperationRegion() where the address is found in that 
UEFI table using DataTableRegion() and at a certain offset declared via 
Field() -- just thinking out loud here.

>
> All problems in computer science can be solved by another level of
> indirection.

True.
diff mbox

Patch

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