]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Smm / Tcg2Smm.c
index fa0b6e6ed9759f52d950975a0c3f2a175786a5ef..498fb626bd9c956b57f412a1cba0d7e9cb4c31eb 100644 (file)
@@ -9,88 +9,97 @@
 \r
   PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
 \r
-Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution.  The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) Microsoft Corporation.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "Tcg2Smm.h"\r
 \r
-typedef enum {\r
-  PtpInterfaceTis,\r
-  PtpInterfaceFifo,\r
-  PtpInterfaceCrb,\r
-  PtpInterfaceMax,\r
-} PTP_INTERFACE_TYPE;\r
+EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable = NULL;\r
+TCG_NVS                    *mTcgNvs      = NULL;\r
+UINTN                      mPpSoftwareSmi;\r
+UINTN                      mMcSoftwareSmi;\r
+EFI_HANDLE                 mReadyToLockHandle;\r
 \r
 /**\r
-  Return PTP interface type.\r
+  Communication service SMI Handler entry.\r
+\r
+  This handler takes requests to exchange Mmi channel and Nvs address between MM and DXE.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  Communicate buffer and buffer size are external input, so this function will do basic validation.\r
+\r
+  @param[in]      DispatchHandle    The unique handle assigned to this handler by SmiHandlerRegister().\r
+  @param[in]      RegisterContext   Points to an optional handler context which was specified when the\r
+                                    handler was registered.\r
+  @param[in, out] CommBuffer        A pointer to a collection of data in memory that will\r
+                                    be conveyed from a non-SMM environment into an SMM environment.\r
+  @param[in, out] CommBufferSize    The size of the CommBuffer.\r
 \r
-  @param[in] Register                Pointer to PTP register.\r
+  @retval EFI_SUCCESS               The interrupt was handled and quiesced. No other handlers\r
+                                    should still be called.\r
+  @retval EFI_UNSUPPORTED           An unknown test function was requested.\r
+  @retval EFI_ACCESS_DENIED         Part of the communication buffer lies in an invalid region.\r
 \r
-  @return PTP interface type.\r
 **/\r
-PTP_INTERFACE_TYPE\r
-GetPtpInterface (\r
-  IN VOID *Register\r
+EFI_STATUS\r
+EFIAPI\r
+TpmNvsCommunciate (\r
+  IN     EFI_HANDLE  DispatchHandle,\r
+  IN     CONST VOID  *RegisterContext,\r
+  IN OUT VOID        *CommBuffer,\r
+  IN OUT UINTN       *CommBufferSize\r
   )\r
 {\r
-  PTP_CRB_INTERFACE_IDENTIFIER  InterfaceId;\r
-  PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;\r
+  EFI_STATUS              Status;\r
+  UINTN                   TempCommBufferSize;\r
+  TPM_NVS_MM_COMM_BUFFER  *CommParams;\r
+\r
+  DEBUG ((DEBUG_VERBOSE, "%a()\n", __FUNCTION__));\r
 \r
   //\r
-  // Check interface id\r
+  // If input is invalid, stop processing this SMI\r
   //\r
-  InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);\r
-  InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);\r
-\r
-  if (InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) {\r
-    return PtpInterfaceTis;\r
+  if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {\r
+    return EFI_SUCCESS;\r
   }\r
 \r
-  if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB) &&\r
-      (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB) &&\r
-      (InterfaceId.Bits.CapCRB != 0)) {\r
-    return PtpInterfaceCrb;\r
+  TempCommBufferSize = *CommBufferSize;\r
+\r
+  if (TempCommBufferSize != sizeof (TPM_NVS_MM_COMM_BUFFER)) {\r
+    DEBUG ((DEBUG_ERROR, "[%a] MM Communication buffer size is invalid for this handler!\n", __FUNCTION__));\r
+    return EFI_ACCESS_DENIED;\r
   }\r
 \r
-  if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO) &&\r
-      (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO) &&\r
-      (InterfaceId.Bits.CapFIFO != 0) &&\r
-      (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP)) {\r
-    return PtpInterfaceFifo;\r
+  if (!IsBufferOutsideMmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+    DEBUG ((DEBUG_ERROR, "[%a] - MM Communication buffer in invalid location!\n", __FUNCTION__));\r
+    return EFI_ACCESS_DENIED;\r
   }\r
 \r
   //\r
-  // No Ptp interface available\r
+  // Farm out the job to individual functions based on what was requested.\r
   //\r
-  return PtpInterfaceMax;\r
-}\r
+  CommParams = (TPM_NVS_MM_COMM_BUFFER *)CommBuffer;\r
+  Status     = EFI_SUCCESS;\r
+  switch (CommParams->Function) {\r
+    case TpmNvsMmExchangeInfo:\r
+      DEBUG ((DEBUG_VERBOSE, "[%a] - Function requested: MM_EXCHANGE_NVS_INFO\n", __FUNCTION__));\r
+      CommParams->RegisteredPpSwiValue = mPpSoftwareSmi;\r
+      CommParams->RegisteredMcSwiValue = mMcSoftwareSmi;\r
+      mTcgNvs                          = (TCG_NVS *)(UINTN)CommParams->TargetAddress;\r
+      break;\r
 \r
-EFI_TPM2_ACPI_TABLE  mTpm2AcpiTemplate = {\r
-  {\r
-    EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,\r
-    sizeof (mTpm2AcpiTemplate),\r
-    EFI_TPM2_ACPI_TABLE_REVISION_4,\r
-    //\r
-    // Compiler initializes the remaining bytes to 0\r
-    // These fields should be filled in in production\r
-    //\r
-  },\r
-  0, // 16-bit PlatformClass\r
-  0, // 16-bit Reserved\r
-  0, // Control Area\r
-  EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod\r
-};\r
-\r
-EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable;\r
-TCG_NVS                    *mTcgNvs;\r
+    default:\r
+      DEBUG ((DEBUG_INFO, "[%a] - Unknown function %d!\n", __FUNCTION__, CommParams->Function));\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
+  }\r
+\r
+  CommParams->ReturnStatus = (UINT64)Status;\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Software SMI callback for TPM physical presence which is called from ACPI method.\r
@@ -112,17 +121,16 @@ TCG_NVS                    *mTcgNvs;
 EFI_STATUS\r
 EFIAPI\r
 PhysicalPresenceCallback (\r
-  IN EFI_HANDLE                  DispatchHandle,\r
-  IN CONST VOID                  *Context,\r
-  IN OUT VOID                    *CommBuffer,\r
-  IN OUT UINTN                   *CommBufferSize\r
+  IN EFI_HANDLE  DispatchHandle,\r
+  IN CONST VOID  *Context,\r
+  IN OUT VOID    *CommBuffer,\r
+  IN OUT UINTN   *CommBufferSize\r
   )\r
 {\r
-  UINT32                MostRecentRequest;\r
-  UINT32                Response;\r
-  UINT32                OperationRequest;\r
-  UINT32                RequestParameter;\r
-\r
+  UINT32  MostRecentRequest;\r
+  UINT32  Response;\r
+  UINT32  OperationRequest;\r
+  UINT32  RequestParameter;\r
 \r
   if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {\r
     mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (\r
@@ -130,18 +138,18 @@ PhysicalPresenceCallback (
                                              &Response\r
                                              );\r
     mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;\r
-    mTcgNvs->PhysicalPresence.Response = Response;\r
+    mTcgNvs->PhysicalPresence.Response    = Response;\r
     return EFI_SUCCESS;\r
-  } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) \r
-          || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {\r
-\r
-    OperationRequest = mTcgNvs->PhysicalPresence.Request;\r
-    RequestParameter = mTcgNvs->PhysicalPresence.RequestParameter;\r
+  } else if (  (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS)\r
+            || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2))\r
+  {\r
+    OperationRequest                     = mTcgNvs->PhysicalPresence.Request;\r
+    RequestParameter                     = mTcgNvs->PhysicalPresence.RequestParameter;\r
     mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (\r
                                              &OperationRequest,\r
                                              &RequestParameter\r
                                              );\r
-    mTcgNvs->PhysicalPresence.Request = OperationRequest;\r
+    mTcgNvs->PhysicalPresence.Request          = OperationRequest;\r
     mTcgNvs->PhysicalPresence.RequestParameter = RequestParameter;\r
   } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
     mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PPRequestUserConfirm);\r
@@ -150,7 +158,6 @@ PhysicalPresenceCallback (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Software SMI callback for MemoryClear which is called from ACPI method.\r
 \r
@@ -171,469 +178,203 @@ PhysicalPresenceCallback (
 EFI_STATUS\r
 EFIAPI\r
 MemoryClearCallback (\r
-  IN EFI_HANDLE                  DispatchHandle,\r
-  IN CONST VOID                  *Context,\r
-  IN OUT VOID                    *CommBuffer,\r
-  IN OUT UINTN                   *CommBufferSize\r
+  IN EFI_HANDLE  DispatchHandle,\r
+  IN CONST VOID  *Context,\r
+  IN OUT VOID    *CommBuffer,\r
+  IN OUT UINTN   *CommBufferSize\r
   )\r
 {\r
-  EFI_STATUS                     Status;\r
-  UINTN                          DataSize;\r
-  UINT8                          MorControl;\r
+  EFI_STATUS  Status;\r
+  UINTN       DataSize;\r
+  UINT8       MorControl;\r
 \r
   mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;\r
   if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {\r
-    MorControl = (UINT8) mTcgNvs->MemoryClear.Request;\r
+    MorControl = (UINT8)mTcgNvs->MemoryClear.Request;\r
   } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {\r
     DataSize = sizeof (UINT8);\r
-    Status = mSmmVariable->SmmGetVariable (\r
-                             MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
-                             &gEfiMemoryOverwriteControlDataGuid,\r
-                             NULL,\r
-                             &DataSize,\r
-                             &MorControl\r
-                             );\r
+    Status   = mSmmVariable->SmmGetVariable (\r
+                               MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+                               &gEfiMemoryOverwriteControlDataGuid,\r
+                               NULL,\r
+                               &DataSize,\r
+                               &MorControl\r
+                               );\r
     if (EFI_ERROR (Status)) {\r
       mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
-      DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));\r
       return EFI_SUCCESS;\r
     }\r
 \r
     if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {\r
       return EFI_SUCCESS;\r
     }\r
+\r
     MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;\r
+  } else {\r
+    mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
+    DEBUG ((DEBUG_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs->MemoryClear.Parameter));\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   DataSize = sizeof (UINT8);\r
-  Status = mSmmVariable->SmmSetVariable (\r
-                           MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
-                           &gEfiMemoryOverwriteControlDataGuid,\r
-                           EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
-                           DataSize,\r
-                           &MorControl\r
-                           );\r
-  if (EFI_ERROR (Status)) { \r
+  Status   = mSmmVariable->SmmSetVariable (\r
+                             MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+                             &gEfiMemoryOverwriteControlDataGuid,\r
+                             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                             DataSize,\r
+                             &MorControl\r
+                             );\r
+  if (EFI_ERROR (Status)) {\r
     mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
-    DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Find the operation region in TCG ACPI table by given Name and Size,\r
-  and initialize it if the region is found.\r
+  Notification for SMM ReadyToLock protocol.\r
 \r
-  @param[in, out] Table          The TPM item in ACPI table.\r
-  @param[in]      Name           The name string to find in TPM table.\r
-  @param[in]      Size           The size of the region to find.\r
+  @param[in] Protocol   Points to the protocol's unique identifier.\r
+  @param[in] Interface  Points to the interface instance.\r
+  @param[in] Handle     The handle on which the interface was installed.\r
 \r
-  @return                        The allocated address for the found region.\r
-\r
-**/\r
-VOID *\r
-AssignOpRegion (\r
-  EFI_ACPI_DESCRIPTION_HEADER    *Table,\r
-  UINT32                         Name,\r
-  UINT16                         Size\r
-  )\r
-{\r
-  EFI_STATUS                     Status;\r
-  AML_OP_REGION_32_8             *OpRegion;\r
-  EFI_PHYSICAL_ADDRESS           MemoryAddress;\r
-\r
-  MemoryAddress = SIZE_4GB - 1;\r
-\r
-  //\r
-  // Patch some pointers for the ASL code before loading the SSDT.\r
-  //\r
-  for (OpRegion  = (AML_OP_REGION_32_8 *) (Table + 1);\r
-       OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);\r
-       OpRegion  = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {\r
-    if ((OpRegion->OpRegionOp  == AML_EXT_REGION_OP) && \r
-        (OpRegion->NameString  == Name) &&\r
-        (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&\r
-        (OpRegion->BytePrefix  == AML_BYTE_PREFIX)) {\r
-\r
-      Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);\r
-      ASSERT_EFI_ERROR (Status);\r
-      ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);\r
-      OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;\r
-      OpRegion->RegionLen    = (UINT8) Size;\r
-      break;\r
-    }\r
-  }\r
-\r
-  return (VOID *) (UINTN) MemoryAddress;\r
-}\r
-\r
-/**\r
-  Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM \r
-ACPI table is "$PV".\r
-\r
-  @param[in, out] Table          The TPM item in ACPI table.\r
-  @param[in]      PPVer          Version string of Physical Presence interface supported by platform.\r
-\r
-  @return                        The allocated address for the found region.\r
-\r
-**/\r
-EFI_STATUS\r
-UpdatePPVersion (\r
-  EFI_ACPI_DESCRIPTION_HEADER    *Table,\r
-  CHAR8                          *PPVer\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT8       *DataPtr;\r
-\r
-  //\r
-  // Patch some pointers for the ASL code before loading the SSDT.\r
-  //\r
-  for (DataPtr  = (UINT8 *)(Table + 1);\r
-       DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);\r
-       DataPtr += 1) {\r
-    if (AsciiStrCmp((CHAR8 *)DataPtr,  PHYSICAL_PRESENCE_VERSION_TAG) == 0) {\r
-      Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);\r
-      DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  Patch TPM2 device HID string.  The initial string tag in TPM2 ACPI table is "NNN0000".\r
-\r
-  @param[in, out] Table          The TPM2 SSDT ACPI table.\r
-\r
-  @return                               HID Update status.\r
+  @retval EFI_SUCCESS   Notification runs successfully.\r
 \r
 **/\r
 EFI_STATUS\r
-UpdateHID (\r
-  EFI_ACPI_DESCRIPTION_HEADER    *Table\r
+EFIAPI\r
+TcgMmReadyToLock (\r
+  IN CONST EFI_GUID  *Protocol,\r
+  IN VOID            *Interface,\r
+  IN EFI_HANDLE      Handle\r
   )\r
 {\r
   EFI_STATUS  Status;\r
-  UINT8       *DataPtr;\r
-  CHAR8       Hid[TPM_HID_ACPI_SIZE];\r
-  UINT32      ManufacturerID;\r
-  UINT32      FirmwareVersion1;\r
-  UINT32      FirmwareVersion2;\r
-  BOOLEAN     PnpHID;\r
-\r
-  PnpHID = TRUE;\r
-\r
-  //\r
-  // Initialize HID with Default PNP string\r
-  //\r
-  ZeroMem(Hid, TPM_HID_ACPI_SIZE);\r
-\r
-  //\r
-  // Get Manufacturer ID\r
-  //\r
-  Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);\r
-  if (!EFI_ERROR(Status)) {\r
-    DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));\r
-    //\r
-    // ManufacturerID defined in TCG Vendor ID Registry \r
-    // may tailed with 0x00 or 0x20\r
-    //\r
-    if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {\r
-      //\r
-      //  HID containing PNP ID "NNN####"\r
-      //   NNN is uppercase letter for Vendor ID specified by manufacturer\r
-      //\r
-      CopyMem(Hid, &ManufacturerID, 3);\r
-    } else {\r
-      //\r
-      //  HID containing ACP ID "NNNN####"\r
-      //   NNNN is uppercase letter for Vendor ID specified by manufacturer\r
-      //\r
-      CopyMem(Hid, &ManufacturerID, 4);\r
-      PnpHID = FALSE;\r
-    }\r
-  } else {\r
-    DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));\r
-    ASSERT(FALSE);\r
-    return Status;\r
-  }\r
-\r
-  Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);\r
-  if (!EFI_ERROR(Status)) {\r
-    DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));\r
-    DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));\r
-    //\r
-    //   #### is Firmware Version 1\r
-    //\r
-    if (PnpHID) {\r
-      AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));\r
-    } else {\r
-      AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));\r
-    }\r
-    \r
-  } else {\r
-    DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));\r
-    ASSERT(FALSE);\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Patch HID in ASL code before loading the SSDT.\r
-  //\r
-  for (DataPtr  = (UINT8 *)(Table + 1);\r
-       DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);\r
-       DataPtr += 1) {\r
-    if (AsciiStrCmp((CHAR8 *)DataPtr,  TPM_HID_TAG) == 0) {\r
-      if (PnpHID) {\r
-        CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);\r
-        //\r
-        // if HID is PNP ID, patch the last byte in HID TAG to Noop\r
-        //\r
-        *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;\r
-      } else {\r
-\r
-        CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);\r
-      }\r
-      DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));\r
-\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));\r
-  return EFI_NOT_FOUND;\r
-}\r
 \r
-/**\r
-  Initialize and publish TPM items in ACPI table.\r
-\r
-  @retval   EFI_SUCCESS     The TCG ACPI table is published successfully.\r
-  @retval   Others          The TCG ACPI table is not published.\r
+  Status = EFI_SUCCESS;\r
 \r
-**/\r
-EFI_STATUS\r
-PublishAcpiTable (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                     Status;\r
-  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;\r
-  UINTN                          TableKey;\r
-  EFI_ACPI_DESCRIPTION_HEADER    *Table;\r
-  UINTN                          TableSize;\r
-\r
-  Status = GetSectionFromFv (\r
-             &gEfiCallerIdGuid,\r
-             EFI_SECTION_RAW,\r
-             0,\r
-             (VOID **) &Table,\r
-             &TableSize\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Update Table version before measuring it to PCR\r
-  //\r
-  Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  DEBUG ((\r
-    DEBUG_INFO,\r
-    "Current physical presence interface version - %a\n",\r
-    (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)\r
-    ));\r
-\r
-  //\r
-  // Update TPM2 HID before measuring it to PCR\r
-  //\r
-  Status = UpdateHID(Table);\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
+  if (mReadyToLockHandle != NULL) {\r
+    Status             = gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+    mReadyToLockHandle = NULL;\r
   }\r
 \r
-  //\r
-  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
-  //\r
-  TpmMeasureAndLogData(\r
-    0,\r
-    EV_POST_CODE,\r
-    EV_POSTCODE_INFO_ACPI_DATA,\r
-    ACPI_DATA_LEN,\r
-    Table,\r
-    TableSize\r
-    );\r
-\r
-\r
-  ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));\r
-  CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );\r
-  mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
-  ASSERT (mTcgNvs != NULL);\r
-\r
-  //\r
-  // Publish the TPM ACPI table. Table is re-checksumed.\r
-  //\r
-  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  TableKey = 0;\r
-  Status = AcpiTable->InstallAcpiTable (\r
-                        AcpiTable,\r
-                        Table,\r
-                        TableSize,\r
-                        &TableKey\r
-                        );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
   return Status;\r
 }\r
 \r
 /**\r
-  Publish TPM2 ACPI table\r
+  The driver's common initialization routine.\r
 \r
-  @retval   EFI_SUCCESS     The TPM2 ACPI table is published successfully.\r
-  @retval   Others          The TPM2 ACPI table is not published.\r
-\r
-**/\r
-EFI_STATUS\r
-PublishTpm2 (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                     Status;\r
-  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;\r
-  UINTN                          TableKey;\r
-  UINT64                         OemTableId;\r
-  EFI_TPM2_ACPI_CONTROL_AREA     *ControlArea;\r
-  PTP_INTERFACE_TYPE             InterfaceType;\r
-\r
-  mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);\r
-  DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));\r
-\r
-  //\r
-  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
-  //\r
-  TpmMeasureAndLogData(\r
-    0,\r
-    EV_POST_CODE,\r
-    EV_POSTCODE_INFO_ACPI_DATA,\r
-    ACPI_DATA_LEN,\r
-    &mTpm2AcpiTemplate,\r
-    sizeof(mTpm2AcpiTemplate)\r
-    );\r
-\r
-  InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
-  switch (InterfaceType) {\r
-  case PtpInterfaceCrb:\r
-    mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;\r
-    mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;\r
-    ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;\r
-    ControlArea->CommandSize  = 0xF80;\r
-    ControlArea->ResponseSize = 0xF80;\r
-    ControlArea->Command      = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
-    ControlArea->Response     = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
-    break;\r
-  case PtpInterfaceFifo:\r
-  case PtpInterfaceTis:\r
-    break;\r
-  default:\r
-    DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));\r
-    break;\r
-  }\r
-\r
-  CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));\r
-  OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
-  CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
-  mTpm2AcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);\r
-  mTpm2AcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);\r
-  mTpm2AcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
-\r
-  //\r
-  // Construct ACPI table\r
-  //\r
-  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = AcpiTable->InstallAcpiTable (\r
-                        AcpiTable,\r
-                        &mTpm2AcpiTemplate,\r
-                        sizeof(mTpm2AcpiTemplate),\r
-                        &TableKey\r
-                        );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  The driver's entry point.\r
-\r
-  It install callbacks for TPM physical presence and MemoryClear, and locate \r
+  It install callbacks for TPM physical presence and MemoryClear, and locate\r
   SMM variable to be used in the callback function.\r
 \r
-  @param[in] ImageHandle  The firmware allocated handle for the EFI image.  \r
-  @param[in] SystemTable  A pointer to the EFI System Table.\r
-  \r
   @retval EFI_SUCCESS     The entry point is executed successfully.\r
   @retval Others          Some error occurs when executing this entry point.\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-InitializeTcgSmm (\r
-  IN EFI_HANDLE                  ImageHandle,\r
-  IN EFI_SYSTEM_TABLE            *SystemTable\r
+InitializeTcgCommon (\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS                     Status;\r
   EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;\r
   EFI_SMM_SW_REGISTER_CONTEXT    SwContext;\r
-  EFI_HANDLE                     SwHandle;\r
+  EFI_HANDLE                     PpSwHandle;\r
+  EFI_HANDLE                     McSwHandle;\r
+  EFI_HANDLE                     NotifyHandle;\r
 \r
-  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){\r
-    DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));\r
+  if (!CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)) {\r
+    DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Status = PublishAcpiTable ();\r
+  // Initialize variables first\r
+  mReadyToLockHandle = NULL;\r
+  SwDispatch         = NULL;\r
+  PpSwHandle         = NULL;\r
+  McSwHandle         = NULL;\r
+  NotifyHandle       = NULL;\r
+\r
+  // Register a root handler to communicate the NVS region and SMI channel between MM and DXE\r
+  Status = gMmst->MmiHandlerRegister (TpmNvsCommunciate, &gTpmNvsMmGuid, &mReadyToLockHandle);\r
   ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "[%a] Failed to register NVS communicate as root MM handler - %r!\n", __FUNCTION__, Status));\r
+    goto Cleanup;\r
+  }\r
 \r
   //\r
   // Get the Sw dispatch protocol and register SMI callback functions.\r
   //\r
-  Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);\r
+  Status = gMmst->MmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID **)&SwDispatch);\r
   ASSERT_EFI_ERROR (Status);\r
-  SwContext.SwSmiInputValue = (UINTN) -1;\r
-  Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "[%a] Failed to locate Sw dispatch protocol - %r!\n", __FUNCTION__, Status));\r
+    goto Cleanup;\r
+  }\r
+\r
+  SwContext.SwSmiInputValue = (UINTN)-1;\r
+  Status                    = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &PpSwHandle);\r
   ASSERT_EFI_ERROR (Status);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    DEBUG ((DEBUG_ERROR, "[%a] Failed to register PP callback as SW MM handler - %r!\n", __FUNCTION__, Status));\r
+    goto Cleanup;\r
   }\r
-  mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
 \r
-  SwContext.SwSmiInputValue = (UINTN) -1;\r
-  Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\r
+  mPpSoftwareSmi = SwContext.SwSmiInputValue;\r
+\r
+  SwContext.SwSmiInputValue = (UINTN)-1;\r
+  Status                    = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &McSwHandle);\r
   ASSERT_EFI_ERROR (Status);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    DEBUG ((DEBUG_ERROR, "[%a] Failed to register MC callback as SW MM handler - %r!\n", __FUNCTION__, Status));\r
+    goto Cleanup;\r
   }\r
-  mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
-  \r
+\r
+  mMcSoftwareSmi = SwContext.SwSmiInputValue;\r
+\r
   //\r
   // Locate SmmVariableProtocol.\r
   //\r
-  Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);\r
+  Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);\r
   ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    // Should not happen\r
+    DEBUG ((DEBUG_ERROR, "[%a] Failed to locate SMM variable protocol - %r!\n", __FUNCTION__, Status));\r
+    goto Cleanup;\r
+  }\r
 \r
-  //\r
-  // Set TPM2 ACPI table\r
-  //\r
-  Status = PublishTpm2 ();\r
+  // Turn off the light before leaving the room... at least, take a remote...\r
+  Status = gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, TcgMmReadyToLock, &NotifyHandle);\r
   ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "[%a] Failed to register ready to lock notification - %r!\n", __FUNCTION__, Status));\r
+    goto Cleanup;\r
+  }\r
 \r
+  Tcg2NotifyMmReady ();\r
 \r
-  return EFI_SUCCESS;\r
-}\r
+Cleanup:\r
+  if (EFI_ERROR (Status)) {\r
+    // Something is whacked, clean up the mess...\r
+    if (NotifyHandle != NULL) {\r
+      gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, NULL, &NotifyHandle);\r
+    }\r
+\r
+    if ((McSwHandle != NULL) && (SwDispatch != NULL)) {\r
+      SwDispatch->UnRegister (SwDispatch, McSwHandle);\r
+    }\r
+\r
+    if ((PpSwHandle != NULL) && (SwDispatch != NULL)) {\r
+      SwDispatch->UnRegister (SwDispatch, PpSwHandle);\r
+    }\r
 \r
+    if (mReadyToLockHandle != NULL) {\r
+      gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r