From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56331) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YtKHa-0001wA-Rw for qemu-devel@nongnu.org; Fri, 15 May 2015 14:24:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YtKHX-0001DS-57 for qemu-devel@nongnu.org; Fri, 15 May 2015 14:24:26 -0400 Received: from e31.co.us.ibm.com ([32.97.110.149]:41760) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YtKHW-0001DN-US for qemu-devel@nongnu.org; Fri, 15 May 2015 14:24:23 -0400 Received: from /spool/local by e31.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 15 May 2015 12:24:22 -0600 Received: from b03cxnp08026.gho.boulder.ibm.com (b03cxnp08026.gho.boulder.ibm.com [9.17.130.18]) by d03dlp01.boulder.ibm.com (Postfix) with ESMTP id 5637C1FF0045 for ; Fri, 15 May 2015 12:15:30 -0600 (MDT) Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t4FIOAYa49610854 for ; Fri, 15 May 2015 11:24:10 -0700 Received: from d03av02.boulder.ibm.com (localhost [127.0.0.1]) by d03av02.boulder.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t4FIOJ7i003042 for ; Fri, 15 May 2015 12:24:19 -0600 Message-ID: <555639D2.3070608@linux.vnet.ibm.com> Date: Fri, 15 May 2015 14:24:18 -0400 From: Stefan Berger MIME-Version: 1.0 References: <1431101720-701152-1-git-send-email-stefanb@linux.vnet.ibm.com> <1431101720-701152-4-git-send-email-stefanb@linux.vnet.ibm.com> <20150515171332.7ae7813f@nial.brq.redhat.com> In-Reply-To: <20150515171332.7ae7813f@nial.brq.redhat.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v2 3/6] Support Physical Presence Interface Spec List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Igor Mammedov Cc: kevin@koconnor.net, stefanb@us.ibm.com, qemu-devel@nongnu.org, quan.xu@intel.com, mst@redhat.com On 05/15/2015 11:13 AM, Igor Mammedov wrote: > On Fri, 8 May 2015 12:15:17 -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 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 >> Cc: Michael Tsirkin >> Cc: Kevin O'Connor >> --- >> hw/i386/ssdt-tpm.dsl | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++ >> include/hw/acpi/tpm.h | 20 ++++++ >> 2 files changed, 209 insertions(+) >> > Ditto, please redo below ASL using C AML API. > API might not have all ASL ops you've used here but you can > reuse some from following series > "Generate ACPI v5.1 tables and expose them to guest over fw_cfg on ARM" > and add missing ones. > > >> diff --git a/hw/i386/ssdt-tpm.dsl b/hw/i386/ssdt-tpm.dsl >> index 75d9691..7d28899 100644 >> --- a/hw/i386/ssdt-tpm.dsl >> +++ b/hw/i386/ssdt-tpm.dsl >> @@ -38,6 +38,195 @@ DefinitionBlock ( >> Method (_STA, 0, NotSerialized) { >> Return (0x0F) >> } >> + >> + OperationRegion (TTIS, SystemMemory, >> + TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE) >> + >> + // Define TPM Debug register >> + Field(TTIS, AnyAcc, NoLock, Preserve) { >> + Offset (0xf90), >> + TDBG, 32 // QEMU TIS Debug > I don't see it being used here, > What do you need it for? I used it for debugging. Removed it. > >> + } >> + >> + // Last accepted opcode >> + NAME(OP, Zero) >> + >> + // The base address in TIS 'RAM' where we exchange >> + // data with the BIOS >> + Name(ADDR, 0xfed40fa0) >> + >> + // Write given opcode into 'RAM' >> + Method (WRAM, 1, NotSerialized) { >> + // Write to high memory pointed to by ADDR >> + OperationRegion (HIGH, SystemMemory, ADDR, TPM_PPI_STRUCT_SIZE) > dynamic OperationRegion-s are better to be avoided, Windows can't/doesn't check > its correctness at table load time. > Put it at device scope so that guest OS would notice address collisions > if there would be any. Done. > >> + Field(HIGH, AnyAcc, NoLock, Preserve) { >> + SIG1, 32, >> + SIZE, 16, >> + CODE, 8 >> + } >> + If (LAnd( >> + LEqual(SIG1, TCG_MAGIC), >> + LGreaterEqual(SIZE, 1)) >> + ) { >> + // Write opcode for BIOS to find >> + Store(Arg0, CODE) >> + // Remember last opcode in CODE >> + Store(Arg0, OP) >> + Return ( 0 ) >> + } >> + Return ( 1 ) >> + } >> + >> + // read data from 'RAM' >> + Method (RRAM, 0, NotSerialized) { >> + Name (OPRE, Package(3) { 1, 0, 0}) >> + // Read from memory pointed to by ADDR >> + OperationRegion (HIGH, SystemMemory, ADDR, TPM_PPI_STRUCT_SIZE) > with OperationRegion at device scope you can drop this. Ok. > >> + Field(HIGH, AnyAcc, NoLock, Preserve) { >> + SIG1, 32, >> + SIZE, 16, >> + CODE, 8, >> + SUCC, 8, >> + CODO, 8, >> + RESP, 32 >> + } >> + // Check signature and sufficient space >> + If (LAnd( >> + LEqual(SIG1, TCG_MAGIC), > using SIG1 seems to be redundant now, the same goes for BIOS part. > Why just not drop it? As a marker that the memory was initialized by the TPM? >> + LGreaterEqual(SIZE, 7) >> + )) { >> + Store(SUCC, Index(OPRE, 0)) >> + Store(CODO, Index(OPRE, 1)) >> + Store(RESP, Index(OPRE, 2)) >> + } >> + return (OPRE) >> + } >> + >> + Method (_DSM, 4, NotSerialized) { >> + If (LEqual (Arg0, ToUUID("3DDDFAA6-361B-4EB4-A424-8D10089D1653"))) { >> + >> + // only supporting API revision 1 >> + If (LNotEqual (Arg1, 1)) { >> + Return (Buffer (1) {0}) >> + } >> + >> + Store(ToInteger(Arg2), Local0) >> + // standard DSM query function >> + If (LEqual (Local0, 0)) { >> + Return (Buffer () {0xFF, 0x01}) >> + } >> + >> + // interface version >> + If (LEqual (Local0, 1)) { >> + Return ("1.2") >> + } >> + >> + // submit TPM operation >> + If (LEqual (Local0, 2)) { >> + // get opcode from package >> + Store(DerefOf(Index(Arg3, 0)), Local0) >> + // check for supported opcode >> + // supported opcodes: 0, 1-11, 14, 21-22 >> + If (LOr( >> + LOr( >> + LAnd( >> + LGreaterEqual(Local0, 0), >> + LLessEqual(Local0, 11) >> + ), >> + LEqual(Local0, 14) >> + ), >> + LAnd( >> + LGreaterEqual(Local0, 21), >> + LLessEqual(Local0, 22) >> + ) >> + )) >> + { >> + // Write the OP into TPM NVRAM >> + Store(WRAM ( Local0 ), Local1) >> + return (Local1) >> + } else { >> + Return (1) >> + } >> + } >> + >> + // get pending TPM operation >> + If (LEqual (Local0, 3)) { >> + NAME(PEOP, Package(2) { 0, 0 }) >> + >> + Store ( 0 , Index(PEOP, 0)) >> + Store ( OP, Index(PEOP, 1)) >> + >> + Return (PEOP) >> + } >> + >> + // action to transition to pre-OS env. >> + If (LEqual (Local0, 4)) { >> + return (2) // Requiring reboot >> + } >> + >> + // get pre-OS TPM operation response >> + If (LEqual (Local0, 5)) { >> + Store (RRAM(), Local0) >> + return ( Local0 ) >> + } >> + >> + // preferred user language >> + If (LEqual (Local0, 6)) { >> + return (3) // Not implemented >> + } >> + >> + // submit TPM operation v2 >> + If (LEqual (Local0, 7)) { >> + Store(DerefOf(Index(Arg3, 0)), Local0) >> + // supported opcodes: 0, 1-11, 14, 21-22 > check looks like the same as above, split out into a separate function? Split out into CKOP(). > >> + If (LOr( >> + LOr( >> + LAnd( >> + LGreaterEqual(Local0, 0), >> + LLessEqual(Local0, 11) >> + ), >> + LEqual(Local0, 14) >> + ), >> + LAnd( >> + LGreaterEqual(Local0, 21), >> + LLessEqual(Local0, 22) >> + ) >> + )) >> + { >> + // Write the OP into TPM NVRAM >> + Store(WRAM ( Local0 ), Local1) >> + return (Local1) >> + } else { >> + Return (1) >> + } >> + } >> + >> + // get user confirmation status >> + If (LEqual (Local0, 8)) { >> + Store(DerefOf(Index(Arg3,0)), Local0) >> + // supported opcodes: 0, 1-11, 14, 21-22 > ditto Fixed.