[edk2] [PATCH] SecurityPkg: Tcg2Smm: Enable TPM2.0 interrupt support

Zhang, Chao B posted 1 patch 6 years, 9 months ago
Failed in applying to current master (apply log)
SecurityPkg/SecurityPkg.dec         |  12 +-
SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c   | 268 +++++++++++++++++++++++++++++++++++-
SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h   |  24 +++-
SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf |   5 +-
SecurityPkg/Tcg/Tcg2Smm/Tpm.asl     |  96 ++++++++++---
5 files changed, 383 insertions(+), 22 deletions(-)
[edk2] [PATCH] SecurityPkg: Tcg2Smm: Enable TPM2.0 interrupt support
Posted by Zhang, Chao B 6 years, 9 months ago
1. Expose _CRS, _SRS, _PRS control method to support TPM interrupt
2. Provide 2 PCDs to configure _CRS and _PRS returned data

Cc: Yao Jiewen <jiewen.yao@intel.com>
Cc: Ronald Aigner <Ronald.Aigner@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
---
 SecurityPkg/SecurityPkg.dec         |  12 +-
 SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c   | 268 +++++++++++++++++++++++++++++++++++-
 SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h   |  24 +++-
 SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf |   5 +-
 SecurityPkg/Tcg/Tcg2Smm/Tpm.asl     |  96 ++++++++++---
 5 files changed, 383 insertions(+), 22 deletions(-)

diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index 50dbe95..a2b3191 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -5,7 +5,7 @@
 #  It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and library classes)
 #  and libraries instances, which are used for those features.
 #
-# Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
 # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
 # Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 # This program and the accompanying materials are licensed and made available under
@@ -450,6 +450,16 @@
   # @Prompt Initial setting of TCG2 Persistent Firmware Management Flags
   gEfiSecurityPkgTokenSpaceGuid.PcdTcg2PhysicalPresenceFlags|0x300E2|UINT32|0x0001001B
 
+  ## Indicate current TPM2 Interrupt Number reported by _CRS control method.<BR><BR>
+  # TPM2 Interrupt feature is disabled If the pcd is set to 0.<BR>
+  # @Prompt Current TPM2 Interrupt Number
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2IrqNum|0x12|UINT32|0x0001001C
+
+  ## Indicate platform possible TPM2 Interrupt Number reported by _PRS control method.<BR><BR>
+  # Possible TPM2 Interrupt Number Buffer will not be reported if TPM2 Interrupt feature is disabled.<BR>
+  # @Prompt Possible TPM2 Interrupt Number buffer
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf|{0x12, 0x00, 0x00, 0x00}|VOID*|0x0001001D
+
 [PcdsDynamic, PcdsDynamicEx]
 
   ## This PCD indicates Hash mask for TPM 2.0. Bit definition strictly follows TCG Algorithm Registry.<BR><BR>
diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
index 5a1fd3e..5ad042e 100644
--- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
+++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
@@ -9,7 +9,7 @@
 
   PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
 
-Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials 
 are licensed and made available under the terms and conditions of the BSD License 
 which accompanies this distribution.  The full text of the license may be found at 
@@ -304,6 +304,251 @@ UpdatePPVersion (
 }
 
 /**
+  Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input
+  interrupt buffer size. BufferSize, PkgLength and interrupt descirptor in ByteList need to be patched
+
+  @param[in, out] Table            The TPM item in ACPI table.
+  @param[in]      IrqBuffer        Input new IRQ buffer.
+  @param[in]      IrqBuffserSize   Input new IRQ buffer size.
+
+  @return                          patch status.
+
+**/
+EFI_STATUS
+UpdatePossibleResource (
+  EFI_ACPI_DESCRIPTION_HEADER    *Table,
+  UINT32                         *IrqBuffer,
+  UINT32                         IrqBuffserSize
+  )
+{
+  UINT8       *DataPtr;
+  UINT8       *DataEndPtr;
+  UINT32      NewPkgLength;
+  UINT32      OrignalPkgLength;
+
+  NewPkgLength     = 0;
+  OrignalPkgLength = 0;
+  DataEndPtr       = NULL;
+
+  //
+  // Follow ACPI spec
+  //           6.4.3   Extend Interrupt Descriptor.
+  //           19.3.3 ASL Resource Template
+  //           20      AML specification
+  // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag
+  //
+  //  AML data is organized by following rule.
+  //  Code need to patch BufferSize and PkgLength and interrupt descirptor in ByteList
+  //
+  // =============  Buffer ====================
+  //           DefBuffer := BufferOp PkgLength BufferSize ByteList
+  //            BufferOp := 0x11
+  //
+  // ==============PkgLength==================
+  //          PkgLength := PkgLeadByte |
+  //                              <PkgLeadByte ByteData> |
+  //                              <PkgLeadByte ByteData ByteData> |
+  //                              <PkgLeadByte ByteData ByteData ByteData>
+  //
+  //       PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
+  //                               <bit 5-4: Only used if PkgLength <= 63 >
+  //                               <bit 3-0: Least significant package length nybble>
+  //
+  //==============BufferSize==================
+  //        BufferSize := Integar
+  //           Integar := ByteConst|WordConst|DwordConst....
+  //
+  //           ByteConst := BytePrefix ByteData
+  //
+  //==============ByteList===================
+  //          ByteList := ByteData ByteList
+  //
+  //=========================================
+
+  //
+  // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
+  //
+  for (DataPtr  = (UINT8 *)(Table + 1);
+       DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+       DataPtr += 1) {
+    if (CompareMem(DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {
+      //
+      // Jump over object name & BufferOp
+      //
+      DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+      if ((*DataPtr & (BIT7|BIT6)) == 0) {
+        OrignalPkgLength = (UINT32)*DataPtr;
+        DataEndPtr       = DataPtr + OrignalPkgLength;
+
+        //
+        // Jump over PkgLength = PkgLeadByte only
+        //
+        NewPkgLength++;
+
+        //
+        // Jump over BufferSize
+        //
+        if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
+          NewPkgLength += 2;
+        } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
+          NewPkgLength += 3;
+        } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
+          NewPkgLength += 5;
+        } else {
+          ASSERT(FALSE);
+          return EFI_UNSUPPORTED;
+        }
+      } else {
+        ASSERT(FALSE);
+        return EFI_UNSUPPORTED;
+      }
+
+      //
+      // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
+      //
+      NewPkgLength += 19 + IrqBuffserSize;
+      if (NewPkgLength > 63) {
+        break;
+      }
+
+      if (NewPkgLength > OrignalPkgLength) {
+        ASSERT(FALSE);
+        return EFI_INVALID_PARAMETER;
+      }
+
+      //
+      // 1.1 Patch PkgLength
+      //
+      *DataPtr = (UINT8)NewPkgLength;
+
+      //
+      // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
+      //      It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
+      //
+      *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
+
+      //
+      // Notify _PRS to report short formed ResourceTemplate
+      //
+      mTcgNvs->IsShortFormPkgLength = TRUE;
+
+      break;
+    }
+  }
+
+  //
+  // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
+  //
+  if (NewPkgLength > 63) {
+    NewPkgLength     = 0;
+    OrignalPkgLength = 0;
+    for (DataPtr  = (UINT8 *)(Table + 1);
+         DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+         DataPtr += 1) {
+      if (CompareMem(DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {
+        //
+        // Jump over object name & BufferOp
+        //
+        DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+        if ((*DataPtr & (BIT7|BIT6)) != 0) {
+          OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);
+          DataEndPtr       = DataPtr + OrignalPkgLength;
+          //
+          // Jump over PkgLength = PkgLeadByte + ByteData length
+          //
+          NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
+
+          //
+          // Jump over BufferSize
+          //
+          if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
+            NewPkgLength += 2;
+          } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
+            NewPkgLength += 3;
+          } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
+            NewPkgLength += 5;
+          } else {
+            ASSERT(FALSE);
+            return EFI_UNSUPPORTED;
+          }
+        } else {
+          ASSERT(FALSE);
+          return EFI_UNSUPPORTED;
+        }
+
+        //
+        // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2  Bytes)
+        //
+        NewPkgLength += 19 + IrqBuffserSize;
+
+        if (NewPkgLength > OrignalPkgLength) {
+          ASSERT(FALSE);
+          return EFI_INVALID_PARAMETER;
+        }
+
+        //
+        // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
+        //
+        *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
+        *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
+
+        //
+        // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
+        //     It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
+        //
+        *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);
+
+        //
+        // Notify _PRS to report short formed ResourceTemplate
+        //
+        mTcgNvs->IsShortFormPkgLength = FALSE;
+        break;
+      }
+    }
+  }
+
+  if (DataPtr >= (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.
+  //     5 bytes for interrupt descriptor header, 2 bytes for End Tag
+  //
+  DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);
+  //
+  //   3.1 Patch Length bit[7:0] of Interrupt descirptor patch interrupt descriptor
+  //
+  *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);
+  //
+  //   3.2 Patch Interrupt Table Length
+  //
+  *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof(UINT32));
+  //
+  //   3.3 Copy patched InterruptNumBuffer
+  //
+  CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);
+
+  //
+  // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field to 0
+  //
+  DataPtr       += 5 + IrqBuffserSize;
+  *DataPtr       = ACPI_END_TAG_DESCRIPTOR;
+  *(DataPtr + 1) = 0;
+
+  //
+  // 5. Jump over whole ResourceTemplate. Stuff rest bytes to NOOP
+  //
+  for (DataPtr += 2; DataPtr < DataEndPtr; DataPtr++) {
+    *DataPtr = AML_NOOP_OP;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
   Patch TPM2 device HID string.  The initial string tag in TPM2 ACPI table is "NNN0000".
 
   @param[in, out] Table          The TPM2 SSDT ACPI table.
@@ -424,6 +669,8 @@ PublishAcpiTable (
   UINTN                          TableKey;
   EFI_ACPI_DESCRIPTION_HEADER    *Table;
   UINTN                          TableSize;
+  UINT32                         *PossibleIrqNumBuf;
+  UINT32                         PossibleIrqNumBufSize;
 
   Status = GetSectionFromFv (
              &gEfiCallerIdGuid,
@@ -454,6 +701,23 @@ PublishAcpiTable (
     return Status;
   }
 
+  if (PcdGet32(PcdTpm2IrqNum) != 0) {
+    //
+    // Patch _PRS interrupt resource only when TPM interrupt is supported
+    //
+    PossibleIrqNumBuf     = (UINT32 *)PcdGetPtr(PcdTpm2PossibleIrqNumBuf);
+    PossibleIrqNumBufSize = (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);
+
+    if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE && (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {
+      Status = UpdatePossibleResource(Table, PossibleIrqNumBuf, PossibleIrqNumBufSize);
+      DEBUG ((
+        DEBUG_INFO,
+        "UpdatePossibleResource status - %x\n",
+        Status
+        ));
+      }
+  }
+
   //
   // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
   //
@@ -471,6 +735,8 @@ PublishAcpiTable (
   CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );
   mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));
   ASSERT (mTcgNvs != NULL);
+  mTcgNvs->TpmIrqNum            = PcdGet32(PcdTpm2IrqNum);
+  mTcgNvs->IsShortFormPkgLength = FALSE;
 
   //
   // Publish the TPM ACPI table. Table is re-checksumed.
diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
index 100804c..732452c 100644
--- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
+++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
@@ -1,7 +1,7 @@
 /** @file
   The header file for Tcg2 SMM driver.
   
-Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials 
 are licensed and made available under the terms and conditions of the BSD License 
 which accompanies this distribution.  The full text of the license may be found at 
@@ -39,6 +39,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/Tcg2PhysicalPresenceLib.h>
 #include <Library/IoLib.h>
 #include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
 
 #include <IndustryStandard/TpmPtp.h>
 
@@ -64,6 +65,8 @@ typedef struct {
   PHYSICAL_PRESENCE_NVS  PhysicalPresence;
   MEMORY_CLEAR_NVS       MemoryClear;
   UINT32                 PPRequestUserConfirm;
+  UINT32                 TpmIrqNum;
+  BOOLEAN                IsShortFormPkgLength;
 } TCG_NVS;
 
 typedef struct {
@@ -102,4 +105,23 @@ typedef struct {
 #define TPM_HID_PNP_SIZE                                           8
 #define TPM_HID_ACPI_SIZE                                          9
 
+#define TPM_PRS_RESL                                               "RESL"
+#define TPM_PRS_RESS                                               "RESS"
+#define TPM_PRS_RES_NAME_SIZE                                      4
+//
+// Minimum PRS resource template size
+//  1 byte    for  BufferOp
+//  1 byte    for  PkgLength
+//  2 bytes   for  BufferSize
+//  12 bytes  for  Memory32Fixed descriptor
+//  5 bytes   for  Interrupt descriptor
+//  2 bytes   for  END Tag
+//
+#define TPM_POS_RES_TEMPLATE_MIN_SIZE                              (1 + 1 + 2 + 12 + 5 + 2)
+
+//
+// Max Interrupt buffer size for PRS interrupt resource
+// Now support 15 interrupts in maxmum
+//
+#define MAX_PRS_INT_BUF_SIZE                                       (15*4)
 #endif  // __TCG_SMM_H__
diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
index c709743..86e1816 100644
--- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
+++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
@@ -16,7 +16,7 @@
 #  This driver will have external input - variable and ACPINvs data in SMM mode.
 #  This external input must be validated carefully to avoid security issue.
 #
-# Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
 # This program and the accompanying materials
 # are licensed and made available under the terms and conditions of the BSD License
 # which accompanies this distribution. The full text of the license may be found at
@@ -58,6 +58,7 @@
   Tpm2CommandLib
   Tcg2PhysicalPresenceLib
   IoLib
+  PcdLib
 
 [Guids]
   ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"
@@ -82,6 +83,8 @@
   gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer  ## CONSUMES
   gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev                 ## CONSUMES
   gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass                 ## SOMETIMES_CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2IrqNum                   ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf        ## CONSUMES
 
 [Depex]
   gEfiAcpiTableProtocolGuid AND
diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
index f528305..f58efca 100644
--- a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
+++ b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
@@ -2,7 +2,7 @@
   The TPM2 definition block in ACPI table for TCG2 physical presence  
   and MemoryClear.
 
-Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
 (c)Copyright 2016 HP Development Company, L.P.<BR>
 Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 This program and the accompanying materials 
@@ -92,20 +92,59 @@ DefinitionBlock (
         MCIP,   32, //   Used for save the Mor paramter
         MORD,   32, //   Memory Overwrite Request Data
         MRET,   32, //   Memory Overwrite function return code
-        UCRQ,   32  //   Phyical Presence request operation to Get User Confirmation Status 
+        UCRQ,   32, //   Phyical Presence request operation to Get User Confirmation Status
+        IRQN,   32, //   IRQ Number for _CRS
+        SFRB,   8   //   Is shortformed Pkglength for resource buffer
       }
 
-      Name(RESO, ResourceTemplate () {
-        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REGS)
+      //
+      // Possible resource settings returned by  _PRS method
+      //   RESS : ResourceTemplate with PkgLength <=63
+      //   RESL : ResourceTemplate with PkgLength > 63
+      //
+      // The format of the data has to follow the same format as
+      // _CRS (according to ACPI spec).
+      //
+      Name (RESS, ResourceTemplate() {
+        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
+        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {1,2,3,4,5,6,7,8,9,10}
+      })
+
+      Name (RESL, ResourceTemplate() {
+        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
+        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
+      })
+
+      //
+      // Current resource settings for _CRS method
+      //
+      Name(RES0, ResourceTemplate () {
+        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG0)
         Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , INTR) {12}
       })
 
+      Name(RES1, ResourceTemplate () {
+        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG1)
+      })
+
+
       //
       // Return the resource consumed by TPM device.
       //
       Method(_CRS,0,Serialized)
       {
-        Return(RESO)
+        //
+        // IRQNum = 0 means disable IRQ support
+        //
+        If (LEqual(IRQN, 0)) {
+          Return (RES1)
+        }
+        Else
+        {
+          CreateDWordField(RES0, ^INTR._INT, LIRQ)
+          Store(IRQN, LIRQ)
+          Return (RES0)
+        }
       }
 
       //
@@ -113,23 +152,34 @@ DefinitionBlock (
       // assign an interrupt number to the device. The input byte stream
       // has to be the same as returned by _CRS (according to ACPI spec).
       //
+      // Platform may choose to override this function with specific interrupt
+      // programing logic to replace FIFO/TIS SIRQ registers programing
+      //
       Method(_SRS,1,Serialized)
       {
         //
+        // Do not configure Interrupt if IRQ Num is configured 0 by default
+        //
+        If (LEqual(IRQN, 0)) {
+          Return (0)
+        }
+
+        //
         // Update resource descriptor
         // Use the field name to identify the offsets in the argument
-        // buffer and RESO buffer.
+        // buffer and RES0 buffer.
         //
         CreateDWordField(Arg0, ^INTR._INT, IRQ0)
-        CreateDWordField(RESO, ^INTR._INT, LIRQ)
+        CreateDWordField(RES0, ^INTR._INT, LIRQ)
         Store(IRQ0, LIRQ)
+        Store(IRQ0, IRQN)
 
         CreateBitField(Arg0, ^INTR._HE, ITRG)
-        CreateBitField(RESO, ^INTR._HE, LTRG)
+        CreateBitField(RES0, ^INTR._HE, LTRG)
         Store(ITRG, LTRG)
 
         CreateBitField(Arg0, ^INTR._LL, ILVL)
-        CreateBitField(RESO, ^INTR._LL, LLVL)
+        CreateBitField(RES0, ^INTR._LL, LLVL)
         Store(ILVL, LLVL)
 
         //
@@ -176,15 +226,25 @@ DefinitionBlock (
         }
       }
 
-      //
-      // Possible resource settings.
-      // The format of the data has to follow the same format as
-      // _CRS (according to ACPI spec).
-      //
-      Name (_PRS, ResourceTemplate() {
-        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
-        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , SIRQ) {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
-      })
+      Method(_PRS,0,Serialized)
+      {
+        //
+        // IRQNum = 0 means disable IRQ support
+        //
+        If (LEqual(IRQN, 0)) {
+          Return (RES1)
+        } ElseIf(LEqual(SFRB, 0)) {
+          //
+          // Long format. Possible resources PkgLength > 63
+          //
+          Return (RESL)
+        } Else {
+          //
+          // Short format. Possible resources PkgLength <=63
+          //
+          Return (RESS)
+        }
+      }
 
       Method (PTS, 1, Serialized)
       {  
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] SecurityPkg: Tcg2Smm: Enable TPM2.0 interrupt support
Posted by Yao, Jiewen 6 years, 9 months ago
Thanks Chao.
In general this patch is good.

Some minor suggestion for your consideration:
1) Can we rename PcdTpm2IrqNum to PcdTpm2CurrentIrqNum ? (To match PcdTpm2PossibleIrqNumBuf)

2) I suggest we output debug message if below condition is NOT satisfied. As such people know what happens.
Silence failure is not the best way.

> +    if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE &&
> (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {
> +      Status = UpdatePossibleResource(Table, PossibleIrqNumBuf,
> PossibleIrqNumBufSize);
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "UpdatePossibleResource status - %x\n",
> +        Status
> +        ));
> +      }

3) Do we use UINT32 to IrqNumber? If so, you can use {(UINT32)0x12} for that.

> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf|{0x12, 0x00,
> 0x00, 0x00}|VOID*|0x0001001D

4) Would you please clarify what test has been done for the PCD patch?
Since you support flexible format (short v.s. long), please make sure all path is covered.



Thank you
Yao Jiewen


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Zhang,
> Chao B
> Sent: Thursday, January 25, 2018 2:25 PM
> To: edk2-devel@lists.01.org
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Ronald Aigner <Ronald.Aigner@microsoft.com>
> Subject: [edk2] [PATCH] SecurityPkg: Tcg2Smm: Enable TPM2.0 interrupt
> support
> 
> 1. Expose _CRS, _SRS, _PRS control method to support TPM interrupt
> 2. Provide 2 PCDs to configure _CRS and _PRS returned data
> 
> Cc: Yao Jiewen <jiewen.yao@intel.com>
> Cc: Ronald Aigner <Ronald.Aigner@microsoft.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
> ---
>  SecurityPkg/SecurityPkg.dec         |  12 +-
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c   | 268
> +++++++++++++++++++++++++++++++++++-
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h   |  24 +++-
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf |   5 +-
>  SecurityPkg/Tcg/Tcg2Smm/Tpm.asl     |  96 ++++++++++---
>  5 files changed, 383 insertions(+), 22 deletions(-)
> 
> diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
> index 50dbe95..a2b3191 100644
> --- a/SecurityPkg/SecurityPkg.dec
> +++ b/SecurityPkg/SecurityPkg.dec
> @@ -5,7 +5,7 @@
>  #  It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and library
> classes)
>  #  and libraries instances, which are used for those features.
>  #
> -# Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
>  # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
>  # Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
>  # This program and the accompanying materials are licensed and made
> available under
> @@ -450,6 +450,16 @@
>    # @Prompt Initial setting of TCG2 Persistent Firmware Management Flags
> 
> gEfiSecurityPkgTokenSpaceGuid.PcdTcg2PhysicalPresenceFlags|0x300E2|UINT3
> 2|0x0001001B
> 
> +  ## Indicate current TPM2 Interrupt Number reported by _CRS control
> method.<BR><BR>
> +  # TPM2 Interrupt feature is disabled If the pcd is set to 0.<BR>
> +  # @Prompt Current TPM2 Interrupt Number
> +
> gEfiSecurityPkgTokenSpaceGuid.PcdTpm2IrqNum|0x12|UINT32|0x0001001C
> +
> +  ## Indicate platform possible TPM2 Interrupt Number reported by _PRS
> control method.<BR><BR>
> +  # Possible TPM2 Interrupt Number Buffer will not be reported if TPM2
> Interrupt feature is disabled.<BR>
> +  # @Prompt Possible TPM2 Interrupt Number buffer
> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf|{0x12, 0x00,
> 0x00, 0x00}|VOID*|0x0001001D
> +
>  [PcdsDynamic, PcdsDynamicEx]
> 
>    ## This PCD indicates Hash mask for TPM 2.0. Bit definition strictly follows
> TCG Algorithm Registry.<BR><BR>
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> index 5a1fd3e..5ad042e 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> @@ -9,7 +9,7 @@
> 
>    PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted
> input and do some check.
> 
> -Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
>  which accompanies this distribution.  The full text of the license may be found
> at
> @@ -304,6 +304,251 @@ UpdatePPVersion (
>  }
> 
>  /**
> +  Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch
> is determined by input
> +  interrupt buffer size. BufferSize, PkgLength and interrupt descirptor in
> ByteList need to be patched
> +
> +  @param[in, out] Table            The TPM item in ACPI table.
> +  @param[in]      IrqBuffer        Input new IRQ buffer.
> +  @param[in]      IrqBuffserSize   Input new IRQ buffer size.
> +
> +  @return                          patch status.
> +
> +**/
> +EFI_STATUS
> +UpdatePossibleResource (
> +  EFI_ACPI_DESCRIPTION_HEADER    *Table,
> +  UINT32                         *IrqBuffer,
> +  UINT32                         IrqBuffserSize
> +  )
> +{
> +  UINT8       *DataPtr;
> +  UINT8       *DataEndPtr;
> +  UINT32      NewPkgLength;
> +  UINT32      OrignalPkgLength;
> +
> +  NewPkgLength     = 0;
> +  OrignalPkgLength = 0;
> +  DataEndPtr       = NULL;
> +
> +  //
> +  // Follow ACPI spec
> +  //           6.4.3   Extend Interrupt Descriptor.
> +  //           19.3.3 ASL Resource Template
> +  //           20      AML specification
> +  // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2
> resource descriptors and an auto appended End Tag
> +  //
> +  //  AML data is organized by following rule.
> +  //  Code need to patch BufferSize and PkgLength and interrupt descirptor in
> ByteList
> +  //
> +  // =============  Buffer ====================
> +  //           DefBuffer := BufferOp PkgLength BufferSize ByteList
> +  //            BufferOp := 0x11
> +  //
> +  // ==============PkgLength==================
> +  //          PkgLength := PkgLeadByte |
> +  //                              <PkgLeadByte ByteData> |
> +  //                              <PkgLeadByte ByteData ByteData> |
> +  //                              <PkgLeadByte ByteData ByteData
> ByteData>
> +  //
> +  //       PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
> +  //                               <bit 5-4: Only used if PkgLength <=
> 63 >
> +  //                               <bit 3-0: Least significant package
> length nybble>
> +  //
> +  //==============BufferSize==================
> +  //        BufferSize := Integar
> +  //           Integar := ByteConst|WordConst|DwordConst....
> +  //
> +  //           ByteConst := BytePrefix ByteData
> +  //
> +  //==============ByteList===================
> +  //          ByteList := ByteData ByteList
> +  //
> +  //=========================================
> +
> +  //
> +  // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt
> number buffer for patching
> +  //
> +  for (DataPtr  = (UINT8 *)(Table + 1);
> +       DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length -
> (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
> +       DataPtr += 1) {
> +    if (CompareMem(DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE)
> == 0) {
> +      //
> +      // Jump over object name & BufferOp
> +      //
> +      DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
> +
> +      if ((*DataPtr & (BIT7|BIT6)) == 0) {
> +        OrignalPkgLength = (UINT32)*DataPtr;
> +        DataEndPtr       = DataPtr + OrignalPkgLength;
> +
> +        //
> +        // Jump over PkgLength = PkgLeadByte only
> +        //
> +        NewPkgLength++;
> +
> +        //
> +        // Jump over BufferSize
> +        //
> +        if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
> +          NewPkgLength += 2;
> +        } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
> +          NewPkgLength += 3;
> +        } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
> +          NewPkgLength += 5;
> +        } else {
> +          ASSERT(FALSE);
> +          return EFI_UNSUPPORTED;
> +        }
> +      } else {
> +        ASSERT(FALSE);
> +        return EFI_UNSUPPORTED;
> +      }
> +
> +      //
> +      // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor
> header(5 Bytes) + End Tag(2 Bytes)
> +      //
> +      NewPkgLength += 19 + IrqBuffserSize;
> +      if (NewPkgLength > 63) {
> +        break;
> +      }
> +
> +      if (NewPkgLength > OrignalPkgLength) {
> +        ASSERT(FALSE);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +
> +      //
> +      // 1.1 Patch PkgLength
> +      //
> +      *DataPtr = (UINT8)NewPkgLength;
> +
> +      //
> +      // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt
> Descriptor + End Tag).
> +      //      It is Little endian. So only patch lowest byte of BufferSize due to
> current interrupt number limit.
> +      //
> +      *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
> +
> +      //
> +      // Notify _PRS to report short formed ResourceTemplate
> +      //
> +      mTcgNvs->IsShortFormPkgLength = TRUE;
> +
> +      break;
> +    }
> +  }
> +
> +  //
> +  // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt
> number buffer for patching
> +  //
> +  if (NewPkgLength > 63) {
> +    NewPkgLength     = 0;
> +    OrignalPkgLength = 0;
> +    for (DataPtr  = (UINT8 *)(Table + 1);
> +         DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length -
> (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
> +         DataPtr += 1) {
> +      if (CompareMem(DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE)
> == 0) {
> +        //
> +        // Jump over object name & BufferOp
> +        //
> +        DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
> +
> +        if ((*DataPtr & (BIT7|BIT6)) != 0) {
> +          OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr &
> 0x0F);
> +          DataEndPtr       = DataPtr + OrignalPkgLength;
> +          //
> +          // Jump over PkgLength = PkgLeadByte + ByteData length
> +          //
> +          NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
> +
> +          //
> +          // Jump over BufferSize
> +          //
> +          if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
> +            NewPkgLength += 2;
> +          } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
> +            NewPkgLength += 3;
> +          } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
> +            NewPkgLength += 5;
> +          } else {
> +            ASSERT(FALSE);
> +            return EFI_UNSUPPORTED;
> +          }
> +        } else {
> +          ASSERT(FALSE);
> +          return EFI_UNSUPPORTED;
> +        }
> +
> +        //
> +        // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor
> header(5 Bytes) + End Tag(2  Bytes)
> +        //
> +        NewPkgLength += 19 + IrqBuffserSize;
> +
> +        if (NewPkgLength > OrignalPkgLength) {
> +          ASSERT(FALSE);
> +          return EFI_INVALID_PARAMETER;
> +        }
> +
> +        //
> +        // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
> +        //
> +        *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
> +        *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
> +
> +        //
> +        // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt
> Descriptor + End Tag).
> +        //     It is Little endian. Only patch lowest byte of BufferSize due to
> current interrupt number limit.
> +        //
> +        *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) =
> (UINT8)(IrqBuffserSize + 19);
> +
> +        //
> +        // Notify _PRS to report short formed ResourceTemplate
> +        //
> +        mTcgNvs->IsShortFormPkgLength = FALSE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (DataPtr >= (UINT8 *) ((UINT8 *) Table + Table->Length -
> (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // 3. Move DataPtr to Interrupt descriptor header and patch interrupt
> descriptor.
> +  //     5 bytes for interrupt descriptor header, 2 bytes for End Tag
> +  //
> +  DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);
> +  //
> +  //   3.1 Patch Length bit[7:0] of Interrupt descirptor patch interrupt
> descriptor
> +  //
> +  *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);
> +  //
> +  //   3.2 Patch Interrupt Table Length
> +  //
> +  *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof(UINT32));
> +  //
> +  //   3.3 Copy patched InterruptNumBuffer
> +  //
> +  CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);
> +
> +  //
> +  // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field
> to 0
> +  //
> +  DataPtr       += 5 + IrqBuffserSize;
> +  *DataPtr       = ACPI_END_TAG_DESCRIPTOR;
> +  *(DataPtr + 1) = 0;
> +
> +  //
> +  // 5. Jump over whole ResourceTemplate. Stuff rest bytes to NOOP
> +  //
> +  for (DataPtr += 2; DataPtr < DataEndPtr; DataPtr++) {
> +    *DataPtr = AML_NOOP_OP;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Patch TPM2 device HID string.  The initial string tag in TPM2 ACPI table is
> "NNN0000".
> 
>    @param[in, out] Table          The TPM2 SSDT ACPI table.
> @@ -424,6 +669,8 @@ PublishAcpiTable (
>    UINTN                          TableKey;
>    EFI_ACPI_DESCRIPTION_HEADER    *Table;
>    UINTN                          TableSize;
> +  UINT32                         *PossibleIrqNumBuf;
> +  UINT32                         PossibleIrqNumBufSize;
> 
>    Status = GetSectionFromFv (
>               &gEfiCallerIdGuid,
> @@ -454,6 +701,23 @@ PublishAcpiTable (
>      return Status;
>    }
> 
> +  if (PcdGet32(PcdTpm2IrqNum) != 0) {
> +    //
> +    // Patch _PRS interrupt resource only when TPM interrupt is supported
> +    //
> +    PossibleIrqNumBuf     = (UINT32
> *)PcdGetPtr(PcdTpm2PossibleIrqNumBuf);
> +    PossibleIrqNumBufSize =
> (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);
> +
> +    if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE &&
> (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {
> +      Status = UpdatePossibleResource(Table, PossibleIrqNumBuf,
> PossibleIrqNumBufSize);
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "UpdatePossibleResource status - %x\n",
> +        Status
> +        ));
> +      }
> +  }
> +
>    //
>    // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
>    //
> @@ -471,6 +735,8 @@ PublishAcpiTable (
>    CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof
> (Table->OemId) );
>    mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16)
> sizeof (TCG_NVS));
>    ASSERT (mTcgNvs != NULL);
> +  mTcgNvs->TpmIrqNum            = PcdGet32(PcdTpm2IrqNum);
> +  mTcgNvs->IsShortFormPkgLength = FALSE;
> 
>    //
>    // Publish the TPM ACPI table. Table is re-checksumed.
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> index 100804c..732452c 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> @@ -1,7 +1,7 @@
>  /** @file
>    The header file for Tcg2 SMM driver.
> 
> -Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
>  which accompanies this distribution.  The full text of the license may be found
> at
> @@ -39,6 +39,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> KIND, EITHER EXPRESS OR IMPLIED.
>  #include <Library/Tcg2PhysicalPresenceLib.h>
>  #include <Library/IoLib.h>
>  #include <Library/PrintLib.h>
> +#include <Library/PcdLib.h>
> 
>  #include <IndustryStandard/TpmPtp.h>
> 
> @@ -64,6 +65,8 @@ typedef struct {
>    PHYSICAL_PRESENCE_NVS  PhysicalPresence;
>    MEMORY_CLEAR_NVS       MemoryClear;
>    UINT32                 PPRequestUserConfirm;
> +  UINT32                 TpmIrqNum;
> +  BOOLEAN                IsShortFormPkgLength;
>  } TCG_NVS;
> 
>  typedef struct {
> @@ -102,4 +105,23 @@ typedef struct {
>  #define TPM_HID_PNP_SIZE
> 8
>  #define TPM_HID_ACPI_SIZE
> 9
> 
> +#define TPM_PRS_RESL
> "RESL"
> +#define TPM_PRS_RESS
> "RESS"
> +#define TPM_PRS_RES_NAME_SIZE
> 4
> +//
> +// Minimum PRS resource template size
> +//  1 byte    for  BufferOp
> +//  1 byte    for  PkgLength
> +//  2 bytes   for  BufferSize
> +//  12 bytes  for  Memory32Fixed descriptor
> +//  5 bytes   for  Interrupt descriptor
> +//  2 bytes   for  END Tag
> +//
> +#define TPM_POS_RES_TEMPLATE_MIN_SIZE
> (1 + 1 + 2 + 12 + 5 + 2)
> +
> +//
> +// Max Interrupt buffer size for PRS interrupt resource
> +// Now support 15 interrupts in maxmum
> +//
> +#define MAX_PRS_INT_BUF_SIZE
> (15*4)
>  #endif  // __TCG_SMM_H__
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> index c709743..86e1816 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> @@ -16,7 +16,7 @@
>  #  This driver will have external input - variable and ACPINvs data in SMM
> mode.
>  #  This external input must be validated carefully to avoid security issue.
>  #
> -# Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  # This program and the accompanying materials
>  # are licensed and made available under the terms and conditions of the BSD
> License
>  # which accompanies this distribution. The full text of the license may be found
> at
> @@ -58,6 +58,7 @@
>    Tpm2CommandLib
>    Tcg2PhysicalPresenceLib
>    IoLib
> +  PcdLib
> 
>  [Guids]
>    ## SOMETIMES_PRODUCES ##
> Variable:L"MemoryOverwriteRequestControl"
> @@ -82,6 +83,8 @@
>    gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer  ##
> CONSUMES
>    gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev
> ## CONSUMES
>    gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass                 ##
> SOMETIMES_CONSUMES
> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2IrqNum                   ##
> CONSUMES
> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf        ##
> CONSUMES
> 
>  [Depex]
>    gEfiAcpiTableProtocolGuid AND
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> index f528305..f58efca 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> @@ -2,7 +2,7 @@
>    The TPM2 definition block in ACPI table for TCG2 physical presence
>    and MemoryClear.
> 
> -Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  (c)Copyright 2016 HP Development Company, L.P.<BR>
>  Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
>  This program and the accompanying materials
> @@ -92,20 +92,59 @@ DefinitionBlock (
>          MCIP,   32, //   Used for save the Mor paramter
>          MORD,   32, //   Memory Overwrite Request Data
>          MRET,   32, //   Memory Overwrite function return code
> -        UCRQ,   32  //   Phyical Presence request operation to Get User
> Confirmation Status
> +        UCRQ,   32, //   Phyical Presence request operation to Get User
> Confirmation Status
> +        IRQN,   32, //   IRQ Number for _CRS
> +        SFRB,   8   //   Is shortformed Pkglength for resource buffer
>        }
> 
> -      Name(RESO, ResourceTemplate () {
> -        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REGS)
> +      //
> +      // Possible resource settings returned by  _PRS method
> +      //   RESS : ResourceTemplate with PkgLength <=63
> +      //   RESL : ResourceTemplate with PkgLength > 63
> +      //
> +      // The format of the data has to follow the same format as
> +      // _CRS (according to ACPI spec).
> +      //
> +      Name (RESS, ResourceTemplate() {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
> +        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , )
> {1,2,3,4,5,6,7,8,9,10}
> +      })
> +
> +      Name (RESL, ResourceTemplate() {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
> +        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , )
> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
> +      })
> +
> +      //
> +      // Current resource settings for _CRS method
> +      //
> +      Name(RES0, ResourceTemplate () {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG0)
>          Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , INTR) {12}
>        })
> 
> +      Name(RES1, ResourceTemplate () {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG1)
> +      })
> +
> +
>        //
>        // Return the resource consumed by TPM device.
>        //
>        Method(_CRS,0,Serialized)
>        {
> -        Return(RESO)
> +        //
> +        // IRQNum = 0 means disable IRQ support
> +        //
> +        If (LEqual(IRQN, 0)) {
> +          Return (RES1)
> +        }
> +        Else
> +        {
> +          CreateDWordField(RES0, ^INTR._INT, LIRQ)
> +          Store(IRQN, LIRQ)
> +          Return (RES0)
> +        }
>        }
> 
>        //
> @@ -113,23 +152,34 @@ DefinitionBlock (
>        // assign an interrupt number to the device. The input byte stream
>        // has to be the same as returned by _CRS (according to ACPI spec).
>        //
> +      // Platform may choose to override this function with specific interrupt
> +      // programing logic to replace FIFO/TIS SIRQ registers programing
> +      //
>        Method(_SRS,1,Serialized)
>        {
>          //
> +        // Do not configure Interrupt if IRQ Num is configured 0 by default
> +        //
> +        If (LEqual(IRQN, 0)) {
> +          Return (0)
> +        }
> +
> +        //
>          // Update resource descriptor
>          // Use the field name to identify the offsets in the argument
> -        // buffer and RESO buffer.
> +        // buffer and RES0 buffer.
>          //
>          CreateDWordField(Arg0, ^INTR._INT, IRQ0)
> -        CreateDWordField(RESO, ^INTR._INT, LIRQ)
> +        CreateDWordField(RES0, ^INTR._INT, LIRQ)
>          Store(IRQ0, LIRQ)
> +        Store(IRQ0, IRQN)
> 
>          CreateBitField(Arg0, ^INTR._HE, ITRG)
> -        CreateBitField(RESO, ^INTR._HE, LTRG)
> +        CreateBitField(RES0, ^INTR._HE, LTRG)
>          Store(ITRG, LTRG)
> 
>          CreateBitField(Arg0, ^INTR._LL, ILVL)
> -        CreateBitField(RESO, ^INTR._LL, LLVL)
> +        CreateBitField(RES0, ^INTR._LL, LLVL)
>          Store(ILVL, LLVL)
> 
>          //
> @@ -176,15 +226,25 @@ DefinitionBlock (
>          }
>        }
> 
> -      //
> -      // Possible resource settings.
> -      // The format of the data has to follow the same format as
> -      // _CRS (according to ACPI spec).
> -      //
> -      Name (_PRS, ResourceTemplate() {
> -        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
> -        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , SIRQ)
> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
> -      })
> +      Method(_PRS,0,Serialized)
> +      {
> +        //
> +        // IRQNum = 0 means disable IRQ support
> +        //
> +        If (LEqual(IRQN, 0)) {
> +          Return (RES1)
> +        } ElseIf(LEqual(SFRB, 0)) {
> +          //
> +          // Long format. Possible resources PkgLength > 63
> +          //
> +          Return (RESL)
> +        } Else {
> +          //
> +          // Short format. Possible resources PkgLength <=63
> +          //
> +          Return (RESS)
> +        }
> +      }
> 
>        Method (PTS, 1, Serialized)
>        {
> --
> 1.9.5.msysgit.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] SecurityPkg: Tcg2Smm: Enable TPM2.0 interrupt support
Posted by Zhang, Chao B 6 years, 9 months ago
Jiewen: 
  Thank you for the comment.
  I agree with 1〜3. Will update patch accordingly 
  For 4. We verified short format Possible Interrupt with PcdTpm2PossibleIrqNumBuf set to
           {(UINT32) 0x01}            Short formed resource buffer 
           {(UINT32)0x01, ~ (UINT32)0x0A}       Short formed resource buffer
           {UINT32)0x01 ~  (UINT32) 0x0B}        long formed resource buffer
           { UINT32)0x01 ~  (UINT32) 0x0F}        long formed resource buffer
   All of them can be patched successfully.

-----Original Message-----
From: Yao, Jiewen 
Sent: Thursday, January 25, 2018 2:39 PM
To: Zhang, Chao B <chao.b.zhang@intel.com>; edk2-devel@lists.01.org
Cc: Zhang, Chao B <chao.b.zhang@intel.com>; Ronald Aigner <Ronald.Aigner@microsoft.com>
Subject: RE: [edk2] [PATCH] SecurityPkg: Tcg2Smm: Enable TPM2.0 interrupt support

Thanks Chao.
In general this patch is good.

Some minor suggestion for your consideration:
1) Can we rename PcdTpm2IrqNum to PcdTpm2CurrentIrqNum ? (To match PcdTpm2PossibleIrqNumBuf)

2) I suggest we output debug message if below condition is NOT satisfied. As such people know what happens.
Silence failure is not the best way.

> +    if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE &&
> (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {
> +      Status = UpdatePossibleResource(Table, PossibleIrqNumBuf,
> PossibleIrqNumBufSize);
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "UpdatePossibleResource status - %x\n",
> +        Status
> +        ));
> +      }

3) Do we use UINT32 to IrqNumber? If so, you can use {(UINT32)0x12} for that.

> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf|{0x12, 0x00,
> 0x00, 0x00}|VOID*|0x0001001D

4) Would you please clarify what test has been done for the PCD patch?
Since you support flexible format (short v.s. long), please make sure all path is covered.



Thank you
Yao Jiewen


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of 
> Zhang, Chao B
> Sent: Thursday, January 25, 2018 2:25 PM
> To: edk2-devel@lists.01.org
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B 
> <chao.b.zhang@intel.com>; Ronald Aigner <Ronald.Aigner@microsoft.com>
> Subject: [edk2] [PATCH] SecurityPkg: Tcg2Smm: Enable TPM2.0 interrupt 
> support
> 
> 1. Expose _CRS, _SRS, _PRS control method to support TPM interrupt 2. 
> Provide 2 PCDs to configure _CRS and _PRS returned data
> 
> Cc: Yao Jiewen <jiewen.yao@intel.com>
> Cc: Ronald Aigner <Ronald.Aigner@microsoft.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
> ---
>  SecurityPkg/SecurityPkg.dec         |  12 +-
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c   | 268
> +++++++++++++++++++++++++++++++++++-
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h   |  24 +++-
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf |   5 +-
>  SecurityPkg/Tcg/Tcg2Smm/Tpm.asl     |  96 ++++++++++---
>  5 files changed, 383 insertions(+), 22 deletions(-)
> 
> diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec 
> index 50dbe95..a2b3191 100644
> --- a/SecurityPkg/SecurityPkg.dec
> +++ b/SecurityPkg/SecurityPkg.dec
> @@ -5,7 +5,7 @@
>  #  It also provides the definitions(including PPIs/PROTOCOLs/GUIDs 
> and library
> classes)
>  #  and libraries instances, which are used for those features.
>  #
> -# Copyright (c) 2009 - 2017, Intel Corporation. All rights 
> reserved.<BR>
> +# Copyright (c) 2009 - 2018, Intel Corporation. All rights 
> +reserved.<BR>
>  # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>  
> # Copyright (c) 2017, Microsoft Corporation.  All rights reserved. 
> <BR>  # This program and the accompanying materials are licensed and 
> made available under @@ -450,6 +450,16 @@
>    # @Prompt Initial setting of TCG2 Persistent Firmware Management 
> Flags
> 
> gEfiSecurityPkgTokenSpaceGuid.PcdTcg2PhysicalPresenceFlags|0x300E2|UIN
> T3
> 2|0x0001001B
> 
> +  ## Indicate current TPM2 Interrupt Number reported by _CRS control
> method.<BR><BR>
> +  # TPM2 Interrupt feature is disabled If the pcd is set to 0.<BR>  # 
> + @Prompt Current TPM2 Interrupt Number
> +
> gEfiSecurityPkgTokenSpaceGuid.PcdTpm2IrqNum|0x12|UINT32|0x0001001C
> +
> +  ## Indicate platform possible TPM2 Interrupt Number reported by 
> + _PRS
> control method.<BR><BR>
> +  # Possible TPM2 Interrupt Number Buffer will not be reported if 
> + TPM2
> Interrupt feature is disabled.<BR>
> +  # @Prompt Possible TPM2 Interrupt Number buffer  
> + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf|{0x12, 0x00,
> 0x00, 0x00}|VOID*|0x0001001D
> +
>  [PcdsDynamic, PcdsDynamicEx]
> 
>    ## This PCD indicates Hash mask for TPM 2.0. Bit definition 
> strictly follows TCG Algorithm Registry.<BR><BR> diff --git 
> a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> index 5a1fd3e..5ad042e 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> @@ -9,7 +9,7 @@
> 
>    PhysicalPresenceCallback() and MemoryClearCallback() will receive 
> untrusted input and do some check.
> 
> -Copyright (c) 2015 - 2017, Intel Corporation. All rights 
> reserved.<BR>
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights 
> +reserved.<BR>
>  This program and the accompanying materials  are licensed and made 
> available under the terms and conditions of the BSD License  which 
> accompanies this distribution.  The full text of the license may be 
> found at @@ -304,6 +304,251 @@ UpdatePPVersion (  }
> 
>  /**
> +  Patch interrupt resources returned by TPM _PRS. ResourceTemplate to 
> + patch
> is determined by input
> +  interrupt buffer size. BufferSize, PkgLength and interrupt 
> + descirptor in
> ByteList need to be patched
> +
> +  @param[in, out] Table            The TPM item in ACPI table.
> +  @param[in]      IrqBuffer        Input new IRQ buffer.
> +  @param[in]      IrqBuffserSize   Input new IRQ buffer size.
> +
> +  @return                          patch status.
> +
> +**/
> +EFI_STATUS
> +UpdatePossibleResource (
> +  EFI_ACPI_DESCRIPTION_HEADER    *Table,
> +  UINT32                         *IrqBuffer,
> +  UINT32                         IrqBuffserSize
> +  )
> +{
> +  UINT8       *DataPtr;
> +  UINT8       *DataEndPtr;
> +  UINT32      NewPkgLength;
> +  UINT32      OrignalPkgLength;
> +
> +  NewPkgLength     = 0;
> +  OrignalPkgLength = 0;
> +  DataEndPtr       = NULL;
> +
> +  //
> +  // Follow ACPI spec
> +  //           6.4.3   Extend Interrupt Descriptor.
> +  //           19.3.3 ASL Resource Template
> +  //           20      AML specification
> +  // to patch TPM ACPI object _PRS returned ResourceTemplate() 
> + containing 2
> resource descriptors and an auto appended End Tag
> +  //
> +  //  AML data is organized by following rule.
> +  //  Code need to patch BufferSize and PkgLength and interrupt 
> + descirptor in
> ByteList
> +  //
> +  // =============  Buffer ====================
> +  //           DefBuffer := BufferOp PkgLength BufferSize ByteList
> +  //            BufferOp := 0x11
> +  //
> +  // ==============PkgLength==================
> +  //          PkgLength := PkgLeadByte |
> +  //                              <PkgLeadByte ByteData> |
> +  //                              <PkgLeadByte ByteData ByteData> |
> +  //                              <PkgLeadByte ByteData ByteData
> ByteData>
> +  //
> +  //       PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
> +  //                               <bit 5-4: Only used if PkgLength <=
> 63 >
> +  //                               <bit 3-0: Least significant package
> length nybble>
> +  //
> +  //==============BufferSize==================
> +  //        BufferSize := Integar
> +  //           Integar := ByteConst|WordConst|DwordConst....
> +  //
> +  //           ByteConst := BytePrefix ByteData
> +  //
> +  //==============ByteList===================
> +  //          ByteList := ByteData ByteList
> +  //
> +  //=========================================
> +
> +  //
> +  // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input 
> + interrupt
> number buffer for patching
> +  //
> +  for (DataPtr  = (UINT8 *)(Table + 1);
> +       DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length -
> (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
> +       DataPtr += 1) {
> +    if (CompareMem(DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE)
> == 0) {
> +      //
> +      // Jump over object name & BufferOp
> +      //
> +      DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
> +
> +      if ((*DataPtr & (BIT7|BIT6)) == 0) {
> +        OrignalPkgLength = (UINT32)*DataPtr;
> +        DataEndPtr       = DataPtr + OrignalPkgLength;
> +
> +        //
> +        // Jump over PkgLength = PkgLeadByte only
> +        //
> +        NewPkgLength++;
> +
> +        //
> +        // Jump over BufferSize
> +        //
> +        if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
> +          NewPkgLength += 2;
> +        } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
> +          NewPkgLength += 3;
> +        } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
> +          NewPkgLength += 5;
> +        } else {
> +          ASSERT(FALSE);
> +          return EFI_UNSUPPORTED;
> +        }
> +      } else {
> +        ASSERT(FALSE);
> +        return EFI_UNSUPPORTED;
> +      }
> +
> +      //
> +      // Include Memory32Fixed Descritor (12 Bytes) + Interrupt 
> + Descriptor
> header(5 Bytes) + End Tag(2 Bytes)
> +      //
> +      NewPkgLength += 19 + IrqBuffserSize;
> +      if (NewPkgLength > 63) {
> +        break;
> +      }
> +
> +      if (NewPkgLength > OrignalPkgLength) {
> +        ASSERT(FALSE);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +
> +      //
> +      // 1.1 Patch PkgLength
> +      //
> +      *DataPtr = (UINT8)NewPkgLength;
> +
> +      //
> +      // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + 
> + Interrupt
> Descriptor + End Tag).
> +      //      It is Little endian. So only patch lowest byte of BufferSize due to
> current interrupt number limit.
> +      //
> +      *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
> +
> +      //
> +      // Notify _PRS to report short formed ResourceTemplate
> +      //
> +      mTcgNvs->IsShortFormPkgLength = TRUE;
> +
> +      break;
> +    }
> +  }
> +
> +  //
> +  // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input 
> + interrupt
> number buffer for patching
> +  //
> +  if (NewPkgLength > 63) {
> +    NewPkgLength     = 0;
> +    OrignalPkgLength = 0;
> +    for (DataPtr  = (UINT8 *)(Table + 1);
> +         DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length -
> (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
> +         DataPtr += 1) {
> +      if (CompareMem(DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE)
> == 0) {
> +        //
> +        // Jump over object name & BufferOp
> +        //
> +        DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
> +
> +        if ((*DataPtr & (BIT7|BIT6)) != 0) {
> +          OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + 
> + (*DataPtr &
> 0x0F);
> +          DataEndPtr       = DataPtr + OrignalPkgLength;
> +          //
> +          // Jump over PkgLength = PkgLeadByte + ByteData length
> +          //
> +          NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
> +
> +          //
> +          // Jump over BufferSize
> +          //
> +          if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
> +            NewPkgLength += 2;
> +          } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
> +            NewPkgLength += 3;
> +          } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
> +            NewPkgLength += 5;
> +          } else {
> +            ASSERT(FALSE);
> +            return EFI_UNSUPPORTED;
> +          }
> +        } else {
> +          ASSERT(FALSE);
> +          return EFI_UNSUPPORTED;
> +        }
> +
> +        //
> +        // Include Memory32Fixed Descritor (12 Bytes) + Interrupt 
> + Descriptor
> header(5 Bytes) + End Tag(2  Bytes)
> +        //
> +        NewPkgLength += 19 + IrqBuffserSize;
> +
> +        if (NewPkgLength > OrignalPkgLength) {
> +          ASSERT(FALSE);
> +          return EFI_INVALID_PARAMETER;
> +        }
> +
> +        //
> +        // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
> +        //
> +        *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
> +        *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
> +
> +        //
> +        // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + 
> + Interrupt
> Descriptor + End Tag).
> +        //     It is Little endian. Only patch lowest byte of BufferSize due to
> current interrupt number limit.
> +        //
> +        *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) =
> (UINT8)(IrqBuffserSize + 19);
> +
> +        //
> +        // Notify _PRS to report short formed ResourceTemplate
> +        //
> +        mTcgNvs->IsShortFormPkgLength = FALSE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (DataPtr >= (UINT8 *) ((UINT8 *) Table + Table->Length -
> (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // 3. Move DataPtr to Interrupt descriptor header and patch 
> + interrupt
> descriptor.
> +  //     5 bytes for interrupt descriptor header, 2 bytes for End Tag
> +  //
> +  DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);  //
> +  //   3.1 Patch Length bit[7:0] of Interrupt descirptor patch interrupt
> descriptor
> +  //
> +  *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);  //
> +  //   3.2 Patch Interrupt Table Length
> +  //
> +  *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof(UINT32));  //
> +  //   3.3 Copy patched InterruptNumBuffer
> +  //
> +  CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);
> +
> +  //
> +  // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field
> to 0
> +  //
> +  DataPtr       += 5 + IrqBuffserSize;
> +  *DataPtr       = ACPI_END_TAG_DESCRIPTOR;
> +  *(DataPtr + 1) = 0;
> +
> +  //
> +  // 5. Jump over whole ResourceTemplate. Stuff rest bytes to NOOP
> +  //
> +  for (DataPtr += 2; DataPtr < DataEndPtr; DataPtr++) {
> +    *DataPtr = AML_NOOP_OP;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Patch TPM2 device HID string.  The initial string tag in TPM2 ACPI table is
> "NNN0000".
> 
>    @param[in, out] Table          The TPM2 SSDT ACPI table.
> @@ -424,6 +669,8 @@ PublishAcpiTable (
>    UINTN                          TableKey;
>    EFI_ACPI_DESCRIPTION_HEADER    *Table;
>    UINTN                          TableSize;
> +  UINT32                         *PossibleIrqNumBuf;
> +  UINT32                         PossibleIrqNumBufSize;
> 
>    Status = GetSectionFromFv (
>               &gEfiCallerIdGuid,
> @@ -454,6 +701,23 @@ PublishAcpiTable (
>      return Status;
>    }
> 
> +  if (PcdGet32(PcdTpm2IrqNum) != 0) {
> +    //
> +    // Patch _PRS interrupt resource only when TPM interrupt is supported
> +    //
> +    PossibleIrqNumBuf     = (UINT32
> *)PcdGetPtr(PcdTpm2PossibleIrqNumBuf);
> +    PossibleIrqNumBufSize =
> (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);
> +
> +    if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE &&
> (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {
> +      Status = UpdatePossibleResource(Table, PossibleIrqNumBuf,
> PossibleIrqNumBufSize);
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "UpdatePossibleResource status - %x\n",
> +        Status
> +        ));
> +      }
> +  }
> +
>    //
>    // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
>    //
> @@ -471,6 +735,8 @@ PublishAcpiTable (
>    CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof
> (Table->OemId) );
>    mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16)
> sizeof (TCG_NVS));
>    ASSERT (mTcgNvs != NULL);
> +  mTcgNvs->TpmIrqNum            = PcdGet32(PcdTpm2IrqNum);
> +  mTcgNvs->IsShortFormPkgLength = FALSE;
> 
>    //
>    // Publish the TPM ACPI table. Table is re-checksumed.
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> index 100804c..732452c 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> @@ -1,7 +1,7 @@
>  /** @file
>    The header file for Tcg2 SMM driver.
> 
> -Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
>  which accompanies this distribution.  The full text of the license may be found
> at
> @@ -39,6 +39,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> KIND, EITHER EXPRESS OR IMPLIED.
>  #include <Library/Tcg2PhysicalPresenceLib.h>
>  #include <Library/IoLib.h>
>  #include <Library/PrintLib.h>
> +#include <Library/PcdLib.h>
> 
>  #include <IndustryStandard/TpmPtp.h>
> 
> @@ -64,6 +65,8 @@ typedef struct {
>    PHYSICAL_PRESENCE_NVS  PhysicalPresence;
>    MEMORY_CLEAR_NVS       MemoryClear;
>    UINT32                 PPRequestUserConfirm;
> +  UINT32                 TpmIrqNum;
> +  BOOLEAN                IsShortFormPkgLength;
>  } TCG_NVS;
> 
>  typedef struct {
> @@ -102,4 +105,23 @@ typedef struct {
>  #define TPM_HID_PNP_SIZE
> 8
>  #define TPM_HID_ACPI_SIZE
> 9
> 
> +#define TPM_PRS_RESL
> "RESL"
> +#define TPM_PRS_RESS
> "RESS"
> +#define TPM_PRS_RES_NAME_SIZE
> 4
> +//
> +// Minimum PRS resource template size
> +//  1 byte    for  BufferOp
> +//  1 byte    for  PkgLength
> +//  2 bytes   for  BufferSize
> +//  12 bytes  for  Memory32Fixed descriptor
> +//  5 bytes   for  Interrupt descriptor
> +//  2 bytes   for  END Tag
> +//
> +#define TPM_POS_RES_TEMPLATE_MIN_SIZE
> (1 + 1 + 2 + 12 + 5 + 2)
> +
> +//
> +// Max Interrupt buffer size for PRS interrupt resource
> +// Now support 15 interrupts in maxmum
> +//
> +#define MAX_PRS_INT_BUF_SIZE
> (15*4)
>  #endif  // __TCG_SMM_H__
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> index c709743..86e1816 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> @@ -16,7 +16,7 @@
>  #  This driver will have external input - variable and ACPINvs data in SMM
> mode.
>  #  This external input must be validated carefully to avoid security issue.
>  #
> -# Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  # This program and the accompanying materials
>  # are licensed and made available under the terms and conditions of the BSD
> License
>  # which accompanies this distribution. The full text of the license may be found
> at
> @@ -58,6 +58,7 @@
>    Tpm2CommandLib
>    Tcg2PhysicalPresenceLib
>    IoLib
> +  PcdLib
> 
>  [Guids]
>    ## SOMETIMES_PRODUCES ##
> Variable:L"MemoryOverwriteRequestControl"
> @@ -82,6 +83,8 @@
>    gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer  ##
> CONSUMES
>    gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev
> ## CONSUMES
>    gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass                 ##
> SOMETIMES_CONSUMES
> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2IrqNum                   ##
> CONSUMES
> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf        ##
> CONSUMES
> 
>  [Depex]
>    gEfiAcpiTableProtocolGuid AND
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> index f528305..f58efca 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> @@ -2,7 +2,7 @@
>    The TPM2 definition block in ACPI table for TCG2 physical presence
>    and MemoryClear.
> 
> -Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  (c)Copyright 2016 HP Development Company, L.P.<BR>
>  Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
>  This program and the accompanying materials
> @@ -92,20 +92,59 @@ DefinitionBlock (
>          MCIP,   32, //   Used for save the Mor paramter
>          MORD,   32, //   Memory Overwrite Request Data
>          MRET,   32, //   Memory Overwrite function return code
> -        UCRQ,   32  //   Phyical Presence request operation to Get User
> Confirmation Status
> +        UCRQ,   32, //   Phyical Presence request operation to Get User
> Confirmation Status
> +        IRQN,   32, //   IRQ Number for _CRS
> +        SFRB,   8   //   Is shortformed Pkglength for resource buffer
>        }
> 
> -      Name(RESO, ResourceTemplate () {
> -        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REGS)
> +      //
> +      // Possible resource settings returned by  _PRS method
> +      //   RESS : ResourceTemplate with PkgLength <=63
> +      //   RESL : ResourceTemplate with PkgLength > 63
> +      //
> +      // The format of the data has to follow the same format as
> +      // _CRS (according to ACPI spec).
> +      //
> +      Name (RESS, ResourceTemplate() {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
> +        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , )
> {1,2,3,4,5,6,7,8,9,10}
> +      })
> +
> +      Name (RESL, ResourceTemplate() {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
> +        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , )
> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
> +      })
> +
> +      //
> +      // Current resource settings for _CRS method
> +      //
> +      Name(RES0, ResourceTemplate () {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG0)
>          Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , INTR) {12}
>        })
> 
> +      Name(RES1, ResourceTemplate () {
> +        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG1)
> +      })
> +
> +
>        //
>        // Return the resource consumed by TPM device.
>        //
>        Method(_CRS,0,Serialized)
>        {
> -        Return(RESO)
> +        //
> +        // IRQNum = 0 means disable IRQ support
> +        //
> +        If (LEqual(IRQN, 0)) {
> +          Return (RES1)
> +        }
> +        Else
> +        {
> +          CreateDWordField(RES0, ^INTR._INT, LIRQ)
> +          Store(IRQN, LIRQ)
> +          Return (RES0)
> +        }
>        }
> 
>        //
> @@ -113,23 +152,34 @@ DefinitionBlock (
>        // assign an interrupt number to the device. The input byte stream
>        // has to be the same as returned by _CRS (according to ACPI spec).
>        //
> +      // Platform may choose to override this function with specific interrupt
> +      // programing logic to replace FIFO/TIS SIRQ registers programing
> +      //
>        Method(_SRS,1,Serialized)
>        {
>          //
> +        // Do not configure Interrupt if IRQ Num is configured 0 by default
> +        //
> +        If (LEqual(IRQN, 0)) {
> +          Return (0)
> +        }
> +
> +        //
>          // Update resource descriptor
>          // Use the field name to identify the offsets in the argument
> -        // buffer and RESO buffer.
> +        // buffer and RES0 buffer.
>          //
>          CreateDWordField(Arg0, ^INTR._INT, IRQ0)
> -        CreateDWordField(RESO, ^INTR._INT, LIRQ)
> +        CreateDWordField(RES0, ^INTR._INT, LIRQ)
>          Store(IRQ0, LIRQ)
> +        Store(IRQ0, IRQN)
> 
>          CreateBitField(Arg0, ^INTR._HE, ITRG)
> -        CreateBitField(RESO, ^INTR._HE, LTRG)
> +        CreateBitField(RES0, ^INTR._HE, LTRG)
>          Store(ITRG, LTRG)
> 
>          CreateBitField(Arg0, ^INTR._LL, ILVL)
> -        CreateBitField(RESO, ^INTR._LL, LLVL)
> +        CreateBitField(RES0, ^INTR._LL, LLVL)
>          Store(ILVL, LLVL)
> 
>          //
> @@ -176,15 +226,25 @@ DefinitionBlock (
>          }
>        }
> 
> -      //
> -      // Possible resource settings.
> -      // The format of the data has to follow the same format as
> -      // _CRS (according to ACPI spec).
> -      //
> -      Name (_PRS, ResourceTemplate() {
> -        Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
> -        Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , SIRQ)
> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
> -      })
> +      Method(_PRS,0,Serialized)
> +      {
> +        //
> +        // IRQNum = 0 means disable IRQ support
> +        //
> +        If (LEqual(IRQN, 0)) {
> +          Return (RES1)
> +        } ElseIf(LEqual(SFRB, 0)) {
> +          //
> +          // Long format. Possible resources PkgLength > 63
> +          //
> +          Return (RESL)
> +        } Else {
> +          //
> +          // Short format. Possible resources PkgLength <=63
> +          //
> +          Return (RESS)
> +        }
> +      }
> 
>        Method (PTS, 1, Serialized)
>        {
> --
> 1.9.5.msysgit.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel