]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
SecurityPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Smm / Tcg2Smm.c
index 19d9b489fe522e17bc537469372acf52b9f9ae9c..9f5111552b82309fbaddeb0f38058751f8120cfe 100644 (file)
@@ -9,87 +9,96 @@
 \r
   PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
 \r
-Copyright (c) 2015 - 2016, 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] Register                Pointer to PTP register.\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
+  @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
-  }\r
+  TempCommBufferSize = *CommBufferSize;\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(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
+  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
+    default:\r
+      DEBUG ((DEBUG_INFO, "[%a] - Unknown function %d!\n", __FUNCTION__, CommParams->Function));\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
+  }\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,\r
-    //\r
-    // Compiler initializes the remaining bytes to 0\r
-    // These fields should be filled in in production\r
-    //\r
-  },\r
-  0, // Flags\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
+  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
@@ -119,6 +128,9 @@ PhysicalPresenceCallback (
 {\r
   UINT32                MostRecentRequest;\r
   UINT32                Response;\r
+  UINT32                OperationRequest;\r
+  UINT32                RequestParameter;\r
+\r
 \r
   if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {\r
     mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (\r
@@ -128,15 +140,20 @@ PhysicalPresenceCallback (
     mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;\r
     mTcgNvs->PhysicalPresence.Response = Response;\r
     return EFI_SUCCESS;\r
-  } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) \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
-    mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (\r
-                                             mTcgNvs->PhysicalPresence.Request,\r
-                                             mTcgNvs->PhysicalPresence.RequestParameter\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.RequestParameter = RequestParameter;\r
   } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
-    mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PhysicalPresence.Request);\r
-  } \r
+    mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PPRequestUserConfirm);\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -186,7 +203,7 @@ MemoryClearCallback (
                              );\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
@@ -194,6 +211,10 @@ MemoryClearCallback (
       return EFI_SUCCESS;\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
@@ -204,306 +225,150 @@ MemoryClearCallback (
                            DataSize,\r
                            &MorControl\r
                            );\r
-  if (EFI_ERROR (Status)) { \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
+  @retval EFI_SUCCESS   Notification runs successfully.\r
 \r
 **/\r
 EFI_STATUS\r
-UpdatePPVersion (\r
-  EFI_ACPI_DESCRIPTION_HEADER    *Table,\r
-  CHAR8                          *PPVer\r
-  )\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
+  EFI_STATUS Status;\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
-  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
-  //\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
-\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
-  //\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
+  if (mReadyToLockHandle != NULL) {\r
+    Status = gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+    mReadyToLockHandle = NULL;\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
+  The driver's common initialization routine.\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
+    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
+  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, &SwHandle);\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
+  mPpSoftwareSmi = SwContext.SwSmiInputValue;\r
 \r
   SwContext.SwSmiInputValue = (UINTN) -1;\r
-  Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\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
+  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
+    if (McSwHandle != NULL && SwDispatch != NULL) {\r
+      SwDispatch->UnRegister (SwDispatch, McSwHandle);\r
+    }\r
+    if (PpSwHandle != NULL && SwDispatch != NULL) {\r
+      SwDispatch->UnRegister (SwDispatch, PpSwHandle);\r
+    }\r
+    if (mReadyToLockHandle != NULL) {\r
+      gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+    }\r
+  }\r
 \r
+  return Status;\r
+}\r