[edk2-devel] [PATCH v2 4/6] SecurityPkg: Tcg2Smm: Separate Tcg2Smm into 2 modules

Yao, Jiewen jiewen.yao at intel.com
Wed Feb 24 01:20:54 UTC 2021


Reviewed-by: Jiewen Yao <Jiewen.yao at intel.com>

> -----Original Message-----
> From: Kun Qin <kun.q at outlook.com>
> Sent: Wednesday, February 10, 2021 9:25 AM
> To: devel at edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>;
> Zhang, Qi1 <qi1.zhang at intel.com>; Kumar, Rahul1 <rahul1.kumar at intel.com>
> Subject: [PATCH v2 4/6] SecurityPkg: Tcg2Smm: Separate Tcg2Smm into 2
> modules
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3169
> 
> This change separated the original Tcg2Smm module into 2 drivers: the
> SMM driver that registers callback for physical presence and memory
> clear; the Tcg2Acpi driver that patches and publishes ACPI table for
> runtime use.
> 
> Tcg2Smm introduced an SMI root handler to allow Tcg2Acpi to communicate
> the NVS region used by Tpm.asl and exchange the registered SwSmiValue.
> 
> Lastly, Tcg2Smm driver will publish gTcg2MmSwSmiRegisteredGuid at the end
> of entrypoint to ensure Tcg2Acpi to load after Tcg2Smm is ready to
> communicate.
> 
> Cc: Jiewen Yao <jiewen.yao at intel.com>
> Cc: Jian J Wang <jian.j.wang at intel.com>
> Cc: Qi Zhang <qi1.zhang at intel.com>
> Cc: Rahul Kumar <rahul1.kumar at intel.com>
> 
> Signed-off-by: Kun Qin <kun.q at outlook.com>
> ---
> 
> Notes:
>     v2:
>     - Newly added in v2.
> 
>     v2:
>     - Newly added.
> 
>  SecurityPkg/Tcg/{Tcg2Smm/Tcg2Smm.c => Tcg2Acpi/Tcg2Acpi.c}     | 350 ++++-
> ---
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c                              | 850 ++++----------------
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c                    |  82 ++
>  SecurityPkg/Include/Guid/TpmNvsMm.h                            |  68 ++
>  SecurityPkg/SecurityPkg.dec                                    |   7 +
>  SecurityPkg/SecurityPkg.dsc                                    |   1 +
>  SecurityPkg/Tcg/{Tcg2Smm/Tcg2Smm.inf => Tcg2Acpi/Tcg2Acpi.inf} |  32 +-
>  SecurityPkg/Tcg/{Tcg2Smm => Tcg2Acpi}/Tpm.asl                  |   0
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h                              | 119 +--
>  SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf                            |  25 +-
>  10 files changed, 542 insertions(+), 992 deletions(-)
> 
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> b/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.c
> similarity index 72%
> copy from SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> copy to SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.c
> index 08105c3692ba..7080df81efe7 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> +++ b/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.c
> @@ -1,20 +1,74 @@
>  /** @file
> -  It updates TPM2 items in ACPI table and registers SMI2 callback
> -  functions for Tcg2 physical presence, ClearMemory, and sample
> -  for dTPM StartMethod.
> +  This driver implements TPM 2.0 definition block in ACPI table and
> +  populates registered SMI callback functions for Tcg2 physical presence
> +  and MemoryClear to handle the requests for ACPI method.
> 
>    Caution: This module requires additional review when modified.
>    This driver will have external input - variable and ACPINvs data in SMM mode.
>    This external input must be validated carefully to avoid security issue.
> 
> -  PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted
> input and do some check.
> -
>  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) Microsoft Corporation.
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
> -#include "Tcg2Smm.h"
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Tpm2Acpi.h>
> +
> +#include <Guid/TpmInstance.h>
> +#include <Guid/TpmNvsMm.h>
> +#include <Guid/PiSmmCommunicationRegionTable.h>
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Protocol/Tcg2Protocol.h>
> +#include <Protocol/MmCommunication.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DxeServicesLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/TpmMeasurementLib.h>
> +#include <Library/Tpm2DeviceLib.h>
> +#include <Library/Tpm2CommandLib.h>
> +#include <Library/UefiLib.h>
> +
> +//
> +// Physical Presence Interface Version supported by Platform
> +//
> +#define PHYSICAL_PRESENCE_VERSION_TAG                              "$PV"
> +#define PHYSICAL_PRESENCE_VERSION_SIZE                             4
> +
> +//
> +// PNP _HID for TPM2 device
> +//
> +#define TPM_HID_TAG                                                "NNNN0000"
> +#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)
> 
>  #pragma pack(1)
> 
> @@ -49,142 +103,8 @@ EFI_TPM2_ACPI_TABLE_V4  mTpm2AcpiTemplate = {
>    EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
>  };
> 
> -EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable;
>  TCG_NVS                    *mTcgNvs;
> 
> -/**
> -  Software SMI callback for TPM physical presence which is called from ACPI
> method.
> -
> -  Caution: This function may receive untrusted input.
> -  Variable and ACPINvs are external input, so this function will validate
> -  its data structure to be valid value.
> -
> -  @param[in]      DispatchHandle  The unique handle assigned to this handler by
> SmiHandlerRegister().
> -  @param[in]      Context         Points to an optional handler context which was
> specified when the
> -                                  handler was registered.
> -  @param[in, out] CommBuffer      A pointer to a collection of data in memory
> that will
> -                                  be conveyed from a non-SMM environment into an SMM
> environment.
> -  @param[in, out] CommBufferSize  The size of the CommBuffer.
> -
> -  @retval EFI_SUCCESS             The interrupt was handled successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -PhysicalPresenceCallback (
> -  IN EFI_HANDLE                  DispatchHandle,
> -  IN CONST VOID                  *Context,
> -  IN OUT VOID                    *CommBuffer,
> -  IN OUT UINTN                   *CommBufferSize
> -  )
> -{
> -  UINT32                MostRecentRequest;
> -  UINT32                Response;
> -  UINT32                OperationRequest;
> -  UINT32                RequestParameter;
> -
> -
> -  if (mTcgNvs->PhysicalPresence.Parameter ==
> TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {
> -    mTcgNvs->PhysicalPresence.ReturnCode =
> Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
> -                                             &MostRecentRequest,
> -                                             &Response
> -                                             );
> -    mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;
> -    mTcgNvs->PhysicalPresence.Response = Response;
> -    return EFI_SUCCESS;
> -  } else if ((mTcgNvs->PhysicalPresence.Parameter ==
> TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS)
> -          || (mTcgNvs->PhysicalPresence.Parameter ==
> TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {
> -
> -    OperationRequest = mTcgNvs->PhysicalPresence.Request;
> -    RequestParameter = mTcgNvs->PhysicalPresence.RequestParameter;
> -    mTcgNvs->PhysicalPresence.ReturnCode =
> Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
> -                                             &OperationRequest,
> -                                             &RequestParameter
> -                                             );
> -    mTcgNvs->PhysicalPresence.Request = OperationRequest;
> -    mTcgNvs->PhysicalPresence.RequestParameter = RequestParameter;
> -  } else if (mTcgNvs->PhysicalPresence.Parameter ==
> TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {
> -    mTcgNvs->PhysicalPresence.ReturnCode =
> Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs-
> >PPRequestUserConfirm);
> -  }
> -
> -  return EFI_SUCCESS;
> -}
> -
> -
> -/**
> -  Software SMI callback for MemoryClear which is called from ACPI method.
> -
> -  Caution: This function may receive untrusted input.
> -  Variable and ACPINvs are external input, so this function will validate
> -  its data structure to be valid value.
> -
> -  @param[in]      DispatchHandle  The unique handle assigned to this handler by
> SmiHandlerRegister().
> -  @param[in]      Context         Points to an optional handler context which was
> specified when the
> -                                  handler was registered.
> -  @param[in, out] CommBuffer      A pointer to a collection of data in memory
> that will
> -                                  be conveyed from a non-SMM environment into an SMM
> environment.
> -  @param[in, out] CommBufferSize  The size of the CommBuffer.
> -
> -  @retval EFI_SUCCESS             The interrupt was handled successfully.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -MemoryClearCallback (
> -  IN EFI_HANDLE                  DispatchHandle,
> -  IN CONST VOID                  *Context,
> -  IN OUT VOID                    *CommBuffer,
> -  IN OUT UINTN                   *CommBufferSize
> -  )
> -{
> -  EFI_STATUS                     Status;
> -  UINTN                          DataSize;
> -  UINT8                          MorControl;
> -
> -  mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;
> -  if (mTcgNvs->MemoryClear.Parameter ==
> ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {
> -    MorControl = (UINT8) mTcgNvs->MemoryClear.Request;
> -  } else if (mTcgNvs->MemoryClear.Parameter ==
> ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {
> -    DataSize = sizeof (UINT8);
> -    Status = mSmmVariable->SmmGetVariable (
> -                             MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
> -                             &gEfiMemoryOverwriteControlDataGuid,
> -                             NULL,
> -                             &DataSize,
> -                             &MorControl
> -                             );
> -    if (EFI_ERROR (Status)) {
> -      mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
> -      DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n",
> Status));
> -      return EFI_SUCCESS;
> -    }
> -
> -    if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
> -      return EFI_SUCCESS;
> -    }
> -    MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;
> -  } else {
> -    mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
> -    DEBUG ((EFI_D_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n",
> mTcgNvs->MemoryClear.Parameter));
> -    return EFI_SUCCESS;
> -  }
> -
> -  DataSize = sizeof (UINT8);
> -  Status = mSmmVariable->SmmSetVariable (
> -                           MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
> -                           &gEfiMemoryOverwriteControlDataGuid,
> -                           EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
> -                           DataSize,
> -                           &MorControl
> -                           );
> -  if (EFI_ERROR (Status)) {
> -    mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
> -    DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n",
> Status));
> -  }
> -
> -  return EFI_SUCCESS;
> -}
> -
>  /**
>    Find the operation region in TCG ACPI table by given Name and Size,
>    and initialize it if the region is found.
> @@ -232,6 +152,103 @@ AssignOpRegion (
>    return (VOID *) (UINTN) MemoryAddress;
>  }
> 
> +/**
> +  Locate the MM communication buffer and protocol, then use it to exchange
> information with
> +  Tcg2StandaloneMmm on NVS address and SMI value.
> +
> +  @param[in, out] TcgNvs         The NVS subject to send to MM environment.
> +
> +  @return                        The status for locating MM common buffer,
> communicate to MM, etc.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ExchangeCommonBuffer (
> +  IN OUT  TCG_NVS                 *TcgNvs
> +)
> +{
> +  EFI_STATUS                                Status;
> +  EFI_MM_COMMUNICATION_PROTOCOL             *MmCommunication;
> +  EDKII_PI_SMM_COMMUNICATION_REGION_TABLE
> *PiSmmCommunicationRegionTable;
> +  EFI_MEMORY_DESCRIPTOR                     *MmCommMemRegion;
> +  EFI_MM_COMMUNICATE_HEADER                 *CommHeader;
> +  TPM_NVS_MM_COMM_BUFFER                    *CommBuffer;
> +  UINTN                                     CommBufferSize;
> +  UINTN                                     Index;
> +
> +  // Step 0: Sanity check for input argument
> +  if (TcgNvs == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a - Input argument is NULL!\n",
> __FUNCTION__));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Step 1: Grab the common buffer header
> +  Status = EfiGetSystemConfigurationTable
> (&gEdkiiPiSmmCommunicationRegionTableGuid, (VOID**)
> &PiSmmCommunicationRegionTable);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a - Failed to locate SMM communciation
> common buffer - %r!\n", __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  // Step 2: Grab one that is large enough to hold
> TPM_NVS_MM_COMM_BUFFER, the IPL one should be sufficient
> +  CommBufferSize = 0;
> +  MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR*)
> (PiSmmCommunicationRegionTable + 1);
> +  for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries;
> Index++) {
> +    if (MmCommMemRegion->Type == EfiConventionalMemory) {
> +      CommBufferSize = EFI_PAGES_TO_SIZE ((UINTN)MmCommMemRegion-
> >NumberOfPages);
> +      if (CommBufferSize >= (sizeof (TPM_NVS_MM_COMM_BUFFER) +
> OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data))) {
> +        break;
> +      }
> +    }
> +    MmCommMemRegion =
> (EFI_MEMORY_DESCRIPTOR*)((UINT8*)MmCommMemRegion +
> PiSmmCommunicationRegionTable->DescriptorSize);
> +  }
> +
> +  if (Index >= PiSmmCommunicationRegionTable->NumberOfEntries) {
> +    // Could not find one that meets our goal...
> +    DEBUG ((DEBUG_ERROR, "%a - Could not find a common buffer that is big
> enough for NVS!\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  // Step 3: Start to populate contents
> +  // Step 3.1: MM Communication common header
> +  CommHeader = (EFI_MM_COMMUNICATE_HEADER *) (UINTN)
> MmCommMemRegion->PhysicalStart;
> +  CommBufferSize = sizeof (TPM_NVS_MM_COMM_BUFFER) + OFFSET_OF
> (EFI_MM_COMMUNICATE_HEADER, Data);
> +  ZeroMem (CommHeader, CommBufferSize);
> +  CopyGuid (&CommHeader->HeaderGuid, &gTpmNvsMmGuid);
> +  CommHeader->MessageLength = sizeof (TPM_NVS_MM_COMM_BUFFER);
> +
> +  // Step 3.2: TPM_NVS_MM_COMM_BUFFER content per our needs
> +  CommBuffer = (TPM_NVS_MM_COMM_BUFFER *) (CommHeader->Data);
> +  CommBuffer->Function = TpmNvsMmExchangeInfo;
> +  CommBuffer->TargetAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TcgNvs;
> +
> +  // Step 4: Locate the protocol and signal Mmi.
> +  Status = gBS->LocateProtocol (&gEfiMmCommunicationProtocolGuid, NULL,
> (VOID**) &MmCommunication);
> +  if (!EFI_ERROR (Status)) {
> +    Status = MmCommunication->Communicate (MmCommunication,
> CommHeader, &CommBufferSize);
> +    DEBUG ((DEBUG_INFO, "%a - Communicate() = %r\n", __FUNCTION__,
> Status));
> +  }
> +  else {
> +    DEBUG ((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol
> - %r\n", __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  // Step 5: If everything goes well, populate the channel number
> +  if (!EFI_ERROR (CommBuffer->ReturnStatus)) {
> +    // Need to demote to UINT8 according to SMI value definition
> +    TcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) CommBuffer-
> >RegisteredPpSwiValue;
> +    TcgNvs->MemoryClear.SoftwareSmi = (UINT8) CommBuffer-
> >RegisteredMcSwiValue;
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a Communication returned software SMI value. PP: 0x%x; MC: 0x%x.\n",
> +      __FUNCTION__,
> +      TcgNvs->PhysicalPresence.SoftwareSmi,
> +      TcgNvs->MemoryClear.SoftwareSmi
> +      ));
> +  }
> +
> +  return (EFI_STATUS) CommBuffer->ReturnStatus;
> +}
> +
>  /**
>    Patch version string of Physical Presence interface supported by platform. The
> initial string tag in TPM
>  ACPI table is "$PV".
> @@ -259,7 +276,7 @@ UpdatePPVersion (
>         DataPtr += 1) {
>      if (AsciiStrCmp((CHAR8 *)DataPtr,  PHYSICAL_PRESENCE_VERSION_TAG) == 0)
> {
>        Status = AsciiStrCpyS((CHAR8 *)DataPtr,
> PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
> -      DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update
> status 0x%x\n", Status));
> +      DEBUG((DEBUG_INFO, "TPM2 Physical Presence Interface Version update
> status 0x%x\n", Status));
>        return Status;
>      }
>    }
> @@ -548,7 +565,7 @@ UpdateHID (
>    //
>    Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);
>    if (!EFI_ERROR(Status)) {
> -    DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n",
> ManufacturerID));
> +    DEBUG((DEBUG_INFO, "TPM_PT_MANUFACTURER 0x%08x\n",
> ManufacturerID));
>      //
>      // ManufacturerID defined in TCG Vendor ID Registry
>      // may tailed with 0x00 or 0x20
> @@ -568,15 +585,15 @@ UpdateHID (
>        PnpHID = FALSE;
>      }
>    } else {
> -    DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n",
> Status));
> +    DEBUG ((DEBUG_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n",
> Status));
>      ASSERT(FALSE);
>      return Status;
>    }
> 
>    Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1,
> &FirmwareVersion2);
>    if (!EFI_ERROR(Status)) {
> -    DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n",
> FirmwareVersion1));
> -    DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n",
> FirmwareVersion2));
> +    DEBUG((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n",
> FirmwareVersion1));
> +    DEBUG((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n",
> FirmwareVersion2));
>      //
>      //   #### is Firmware Version 1
>      //
> @@ -587,7 +604,7 @@ UpdateHID (
>      }
> 
>    } else {
> -    DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n",
> Status));
> +    DEBUG ((DEBUG_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X
> failed %x!\n", Status));
>      ASSERT(FALSE);
>      return Status;
>    }
> @@ -615,7 +632,7 @@ UpdateHID (
>      }
>    }
> 
> -  DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
> +  DEBUG((DEBUG_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
>    return EFI_NOT_FOUND;
>  }
> 
> @@ -716,6 +733,8 @@ PublishAcpiTable (
>    mTcgNvs->TpmIrqNum            = PcdGet32(PcdTpm2CurrentIrqNum);
>    mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;
> 
> +  Status = ExchangeCommonBuffer (mTcgNvs);
> +
>    //
>    // Publish the TPM ACPI table. Table is re-checksummed.
>    //
> @@ -806,7 +825,7 @@ PublishTpm2 (
>    case Tpm2PtpInterfaceTis:
>      break;
>    default:
> -    DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n",
> InterfaceType));
> +    DEBUG((DEBUG_ERROR, "TPM2 InterfaceType get error! %d\n",
> InterfaceType));
>      break;
>    }
> 
> @@ -849,58 +868,27 @@ PublishTpm2 (
>  **/
>  EFI_STATUS
>  EFIAPI
> -InitializeTcgSmm (
> +InitializeTcgAcpi (
>    IN EFI_HANDLE                  ImageHandle,
>    IN EFI_SYSTEM_TABLE            *SystemTable
>    )
>  {
>    EFI_STATUS                     Status;
> -  EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;
> -  EFI_SMM_SW_REGISTER_CONTEXT    SwContext;
> -  EFI_HANDLE                     SwHandle;
> 
>    if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid),
> &gEfiTpmDeviceInstanceTpm20DtpmGuid)){
> -    DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));
> +    DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));
>      return EFI_UNSUPPORTED;
>    }
> 
>    Status = PublishAcpiTable ();
>    ASSERT_EFI_ERROR (Status);
> 
> -  //
> -  // Get the Sw dispatch protocol and register SMI callback functions.
> -  //
> -  Status = gMmst->MmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid,
> NULL, (VOID**)&SwDispatch);
> -  ASSERT_EFI_ERROR (Status);
> -  SwContext.SwSmiInputValue = (UINTN) -1;
> -  Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback,
> &SwContext, &SwHandle);
> -  ASSERT_EFI_ERROR (Status);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> -  }
> -  mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8)
> SwContext.SwSmiInputValue;
> -
> -  SwContext.SwSmiInputValue = (UINTN) -1;
> -  Status = SwDispatch->Register (SwDispatch, MemoryClearCallback,
> &SwContext, &SwHandle);
> -  ASSERT_EFI_ERROR (Status);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> -  }
> -  mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
> -
> -  //
> -  // Locate SmmVariableProtocol.
> -  //
> -  Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL,
> (VOID**)&mSmmVariable);
> -  ASSERT_EFI_ERROR (Status);
> -
>    //
>    // Set TPM2 ACPI table
>    //
>    Status = PublishTpm2 ();
>    ASSERT_EFI_ERROR (Status);
> 
> -
>    return EFI_SUCCESS;
>  }
> 
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> index 08105c3692ba..977ea3b1dfd2 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
> @@ -10,47 +10,95 @@
>    PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted
> input and do some check.
> 
>  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) Microsoft Corporation.
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #include "Tcg2Smm.h"
> 
> -#pragma pack(1)
> -
> -typedef struct {
> -  EFI_ACPI_DESCRIPTION_HEADER Header;
> -  // Flags field is replaced in version 4 and above
> -  //    BIT0~15:  PlatformClass      This field is only valid for version 4 and above
> -  //    BIT16~31: Reserved
> -  UINT32                      Flags;
> -  UINT64                      AddressOfControlArea;
> -  UINT32                      StartMethod;
> -  UINT8                       PlatformSpecificParameters[12];  // size up to 12
> -  UINT32                      Laml;                          // Optional
> -  UINT64                      Lasa;                          // Optional
> -} EFI_TPM2_ACPI_TABLE_V4;
> -
> -#pragma pack()
> -
> -EFI_TPM2_ACPI_TABLE_V4  mTpm2AcpiTemplate = {
> -  {
> -    EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
> -    sizeof (mTpm2AcpiTemplate),
> -    EFI_TPM2_ACPI_TABLE_REVISION,
> -    //
> -    // Compiler initializes the remaining bytes to 0
> -    // These fields should be filled in in production
> -    //
> -  },
> -  0, // BIT0~15:  PlatformClass
> -     // BIT16~31: Reserved
> -  0, // Control Area
> -  EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
> -};
> -
> -EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable;
> -TCG_NVS                    *mTcgNvs;
> +EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable = NULL;
> +TCG_NVS                    *mTcgNvs = NULL;
> +UINTN                       mPpSoftwareSmi;
> +UINTN                       mMcSoftwareSmi;
> +EFI_HANDLE                  mReadyToLockHandle;
> +
> +/**
> +  Communication service SMI Handler entry.
> +
> +  This handler takes requests to exchange Mmi channel and Nvs address
> between MM and DXE.
> +
> +  Caution: This function may receive untrusted input.
> +  Communicate buffer and buffer size are external input, so this function will do
> basic validation.
> +
> +  @param[in]      DispatchHandle    The unique handle assigned to this handler
> by SmiHandlerRegister().
> +  @param[in]      RegisterContext   Points to an optional handler context which
> was specified when the
> +                                    handler was registered.
> +  @param[in, out] CommBuffer        A pointer to a collection of data in memory
> that will
> +                                    be conveyed from a non-SMM environment into an SMM
> environment.
> +  @param[in, out] CommBufferSize    The size of the CommBuffer.
> +
> +  @retval EFI_SUCCESS               The interrupt was handled and quiesced. No
> other handlers
> +                                    should still be called.
> +  @retval EFI_UNSUPPORTED           An unknown test function was requested.
> +  @retval EFI_ACCESS_DENIED         Part of the communication buffer lies in an
> invalid region.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TpmNvsCommunciate (
> +  IN     EFI_HANDLE                   DispatchHandle,
> +  IN     CONST VOID                   *RegisterContext,
> +  IN OUT VOID                         *CommBuffer,
> +  IN OUT UINTN                        *CommBufferSize
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINTN                     TempCommBufferSize;
> +  TPM_NVS_MM_COMM_BUFFER    *CommParams;
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a()\n", __FUNCTION__));
> +
> +  //
> +  // If input is invalid, stop processing this SMI
> +  //
> +  if (CommBuffer == NULL || CommBufferSize == NULL) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  TempCommBufferSize = *CommBufferSize;
> +
> +  if(TempCommBufferSize != sizeof (TPM_NVS_MM_COMM_BUFFER)) {
> +    DEBUG ((DEBUG_ERROR, "[%a] MM Communication buffer size is invalid for
> this handler!\n", __FUNCTION__));
> +    return EFI_ACCESS_DENIED;
> +  }
> +  if (!IsBufferOutsideMmValid ((UINTN) CommBuffer, TempCommBufferSize)) {
> +    DEBUG ((DEBUG_ERROR, "[%a] - MM Communication buffer in invalid
> location!\n", __FUNCTION__));
> +    return EFI_ACCESS_DENIED;
> +  }
> +
> +  //
> +  // Farm out the job to individual functions based on what was requested.
> +  //
> +  CommParams = (TPM_NVS_MM_COMM_BUFFER*) CommBuffer;
> +  Status = EFI_SUCCESS;
> +  switch (CommParams->Function) {
> +    case TpmNvsMmExchangeInfo:
> +      DEBUG ((DEBUG_VERBOSE, "[%a] - Function requested:
> MM_EXCHANGE_NVS_INFO\n", __FUNCTION__));
> +      CommParams->RegisteredPpSwiValue = mPpSoftwareSmi;
> +      CommParams->RegisteredMcSwiValue = mMcSoftwareSmi;
> +      mTcgNvs = (TCG_NVS*) (UINTN) CommParams->TargetAddress;
> +      break;
> +
> +    default:
> +      DEBUG ((DEBUG_INFO, "[%a] - Unknown function %d!\n", __FUNCTION__,
> CommParams->Function));
> +      Status = EFI_UNSUPPORTED;
> +      break;
> +  }
> +
> +  CommParams->ReturnStatus = (UINT64) Status;
> +  return EFI_SUCCESS;
> +}
> 
>  /**
>    Software SMI callback for TPM physical presence which is called from ACPI
> method.
> @@ -186,721 +234,137 @@ MemoryClearCallback (
>  }
> 
>  /**
> -  Find the operation region in TCG ACPI table by given Name and Size,
> -  and initialize it if the region is found.
> +  Notification for SMM ReadyToLock protocol.
> 
> -  @param[in, out] Table          The TPM item in ACPI table.
> -  @param[in]      Name           The name string to find in TPM table.
> -  @param[in]      Size           The size of the region to find.
> +  @param[in] Protocol   Points to the protocol's unique identifier.
> +  @param[in] Interface  Points to the interface instance.
> +  @param[in] Handle     The handle on which the interface was installed.
> 
> -  @return                        The allocated address for the found region.
> -
> -**/
> -VOID *
> -AssignOpRegion (
> -  EFI_ACPI_DESCRIPTION_HEADER    *Table,
> -  UINT32                         Name,
> -  UINT16                         Size
> -  )
> -{
> -  EFI_STATUS                     Status;
> -  AML_OP_REGION_32_8             *OpRegion;
> -  EFI_PHYSICAL_ADDRESS           MemoryAddress;
> -
> -  MemoryAddress = SIZE_4GB - 1;
> -
> -  //
> -  // Patch some pointers for the ASL code before loading the SSDT.
> -  //
> -  for (OpRegion  = (AML_OP_REGION_32_8 *) (Table + 1);
> -       OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);
> -       OpRegion  = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {
> -    if ((OpRegion->OpRegionOp  == AML_EXT_REGION_OP) &&
> -        (OpRegion->NameString  == Name) &&
> -        (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
> -        (OpRegion->BytePrefix  == AML_BYTE_PREFIX)) {
> -
> -      Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS,
> EFI_SIZE_TO_PAGES (Size), &MemoryAddress);
> -      ASSERT_EFI_ERROR (Status);
> -      ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
> -      OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;
> -      OpRegion->RegionLen    = (UINT8) Size;
> -      break;
> -    }
> -  }
> -
> -  return (VOID *) (UINTN) MemoryAddress;
> -}
> -
> -/**
> -  Patch version string of Physical Presence interface supported by platform. The
> initial string tag in TPM
> -ACPI table is "$PV".
> -
> -  @param[in, out] Table          The TPM item in ACPI table.
> -  @param[in]      PPVer          Version string of Physical Presence interface
> supported by platform.
> -
> -  @return                        The allocated address for the found region.
> -
> -**/
> -EFI_STATUS
> -UpdatePPVersion (
> -  EFI_ACPI_DESCRIPTION_HEADER    *Table,
> -  CHAR8                          *PPVer
> -  )
> -{
> -  EFI_STATUS  Status;
> -  UINT8       *DataPtr;
> -
> -  //
> -  // Patch some pointers for the ASL code before loading the SSDT.
> -  //
> -  for (DataPtr  = (UINT8 *)(Table + 1);
> -       DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length -
> PHYSICAL_PRESENCE_VERSION_SIZE);
> -       DataPtr += 1) {
> -    if (AsciiStrCmp((CHAR8 *)DataPtr,  PHYSICAL_PRESENCE_VERSION_TAG) == 0)
> {
> -      Status = AsciiStrCpyS((CHAR8 *)DataPtr,
> PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
> -      DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update
> status 0x%x\n", Status));
> -      return Status;
> -    }
> -  }
> -
> -  return EFI_NOT_FOUND;
> -}
> -
> -/**
> -  Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch
> is determined by input
> -  interrupt buffer size. BufferSize, PkgLength and interrupt descriptor 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.
> -  @param[out]     IsShortFormPkgLength   If _PRS returns Short length
> Package(ACPI spec 20.2.4).
> -
> -  @return                          patch status.
> -
> -**/
> -EFI_STATUS
> -UpdatePossibleResource (
> -  IN OUT  EFI_ACPI_DESCRIPTION_HEADER    *Table,
> -  IN      UINT32                         *IrqBuffer,
> -  IN      UINT32                         IrqBuffserSize,
> -  OUT     BOOLEAN                        *IsShortFormPkgLength
> -  )
> -{
> -  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 descriptor 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 := Integer
> -  //           Integer := 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 Descriptor (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 Descriptor + 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
> -      //
> -      *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 Descriptor (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 Descriptor + 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 long formed ResourceTemplate
> -        //
> -        *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 descriptor 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 descriptor and Patch END Tag, set Checksum field to
> 0
> -  //
> -  DataPtr       += 5 + IrqBuffserSize;
> -  *DataPtr       = ACPI_END_TAG_DESCRIPTOR;
> -  *(DataPtr + 1) = 0;
> -
> -  //
> -  // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
> -  //
> -  DataPtr += 2;
> -  if (DataPtr < DataEndPtr) {
> -    SetMem(DataPtr, (UINTN)DataEndPtr - (UINTN)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.
> -
> -  @return                               HID Update status.
> -
> -**/
> -EFI_STATUS
> -UpdateHID (
> -  EFI_ACPI_DESCRIPTION_HEADER    *Table
> -  )
> -{
> -  EFI_STATUS  Status;
> -  UINT8       *DataPtr;
> -  CHAR8       Hid[TPM_HID_ACPI_SIZE];
> -  UINT32      ManufacturerID;
> -  UINT32      FirmwareVersion1;
> -  UINT32      FirmwareVersion2;
> -  BOOLEAN     PnpHID;
> -
> -  PnpHID = TRUE;
> -
> -  //
> -  // Initialize HID with Default PNP string
> -  //
> -  ZeroMem(Hid, TPM_HID_ACPI_SIZE);
> -
> -  //
> -  // Get Manufacturer ID
> -  //
> -  Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);
> -  if (!EFI_ERROR(Status)) {
> -    DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n",
> ManufacturerID));
> -    //
> -    // ManufacturerID defined in TCG Vendor ID Registry
> -    // may tailed with 0x00 or 0x20
> -    //
> -    if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {
> -      //
> -      //  HID containing PNP ID "NNN####"
> -      //   NNN is uppercase letter for Vendor ID specified by manufacturer
> -      //
> -      CopyMem(Hid, &ManufacturerID, 3);
> -    } else {
> -      //
> -      //  HID containing ACP ID "NNNN####"
> -      //   NNNN is uppercase letter for Vendor ID specified by manufacturer
> -      //
> -      CopyMem(Hid, &ManufacturerID, 4);
> -      PnpHID = FALSE;
> -    }
> -  } else {
> -    DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n",
> Status));
> -    ASSERT(FALSE);
> -    return Status;
> -  }
> -
> -  Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1,
> &FirmwareVersion2);
> -  if (!EFI_ERROR(Status)) {
> -    DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n",
> FirmwareVersion1));
> -    DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n",
> FirmwareVersion2));
> -    //
> -    //   #### is Firmware Version 1
> -    //
> -    if (PnpHID) {
> -      AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d",
> ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
> -    } else {
> -      AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d",
> ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
> -    }
> -
> -  } else {
> -    DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n",
> Status));
> -    ASSERT(FALSE);
> -    return Status;
> -  }
> -
> -  //
> -  // Patch HID in ASL code before loading the SSDT.
> -  //
> -  for (DataPtr  = (UINT8 *)(Table + 1);
> -       DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length -
> TPM_HID_PNP_SIZE);
> -       DataPtr += 1) {
> -    if (AsciiStrCmp((CHAR8 *)DataPtr,  TPM_HID_TAG) == 0) {
> -      if (PnpHID) {
> -        CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);
> -        //
> -        // if HID is PNP ID, patch the last byte in HID TAG to Noop
> -        //
> -        *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;
> -      } else {
> -
> -        CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);
> -      }
> -      DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));
> -
> -      return Status;
> -    }
> -  }
> -
> -  DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
> -  return EFI_NOT_FOUND;
> -}
> -
> -/**
> -  Initialize and publish TPM items in ACPI table.
> -
> -  @retval   EFI_SUCCESS     The TCG ACPI table is published successfully.
> -  @retval   Others          The TCG ACPI table is not published.
> -
> -**/
> -EFI_STATUS
> -PublishAcpiTable (
> -  VOID
> -  )
> -{
> -  EFI_STATUS                     Status;
> -  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
> -  UINTN                          TableKey;
> -  EFI_ACPI_DESCRIPTION_HEADER    *Table;
> -  UINTN                          TableSize;
> -  UINT32                         *PossibleIrqNumBuf;
> -  UINT32                         PossibleIrqNumBufSize;
> -  BOOLEAN                        IsShortFormPkgLength;
> -
> -  IsShortFormPkgLength = FALSE;
> -
> -  Status = GetSectionFromFv (
> -             &gEfiCallerIdGuid,
> -             EFI_SECTION_RAW,
> -             0,
> -             (VOID **) &Table,
> -             &TableSize
> -             );
> -  ASSERT_EFI_ERROR (Status);
> -
> -  //
> -  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
> -  // The measurement has to be done before any update.
> -  // Otherwise, the PCR record would be different after TPM FW update
> -  // or the PCD configuration change.
> -  //
> -  TpmMeasureAndLogData(
> -    0,
> -    EV_POST_CODE,
> -    EV_POSTCODE_INFO_ACPI_DATA,
> -    ACPI_DATA_LEN,
> -    Table,
> -    TableSize
> -    );
> -
> -  //
> -  // Update Table version before measuring it to PCR
> -  //
> -  Status = UpdatePPVersion(Table, (CHAR8
> *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));
> -  ASSERT_EFI_ERROR (Status);
> -
> -  DEBUG ((
> -    DEBUG_INFO,
> -    "Current physical presence interface version - %a\n",
> -    (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)
> -    ));
> -
> -  //
> -  // Update TPM2 HID after measuring it to PCR
> -  //
> -  Status = UpdateHID(Table);
> -  if (EFI_ERROR(Status)) {
> -    return Status;
> -  }
> -
> -  if (PcdGet32(PcdTpm2CurrentIrqNum) != 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, &IsShortFormPkgLength);
> -      DEBUG ((
> -        DEBUG_INFO,
> -        "UpdatePossibleResource status - %x. TPM2 service may not ready in
> OS.\n",
> -        Status
> -        ));
> -    } else {
> -      DEBUG ((
> -        DEBUG_INFO,
> -        "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not
> ready in OS.\n",
> -        PossibleIrqNumBufSize
> -      ));
> -    }
> -  }
> -
> -  ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
> -  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(PcdTpm2CurrentIrqNum);
> -  mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;
> -
> -  //
> -  // Publish the TPM ACPI table. Table is re-checksummed.
> -  //
> -  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)
> &AcpiTable);
> -  ASSERT_EFI_ERROR (Status);
> -
> -  TableKey = 0;
> -  Status = AcpiTable->InstallAcpiTable (
> -                        AcpiTable,
> -                        Table,
> -                        TableSize,
> -                        &TableKey
> -                        );
> -  ASSERT_EFI_ERROR (Status);
> -
> -  return Status;
> -}
> -
> -/**
> -  Publish TPM2 ACPI table
> -
> -  @retval   EFI_SUCCESS     The TPM2 ACPI table is published successfully.
> -  @retval   Others          The TPM2 ACPI table is not published.
> +  @retval EFI_SUCCESS   Notification runs successfully.
> 
>  **/
>  EFI_STATUS
> -PublishTpm2 (
> -  VOID
> -  )
> +EFIAPI
> +TcgMmReadyToLock (
> +  IN CONST EFI_GUID  *Protocol,
> +  IN VOID            *Interface,
> +  IN EFI_HANDLE      Handle
> +)
>  {
> -  EFI_STATUS                     Status;
> -  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
> -  UINTN                          TableKey;
> -  UINT64                         OemTableId;
> -  EFI_TPM2_ACPI_CONTROL_AREA     *ControlArea;
> -  TPM2_PTP_INTERFACE_TYPE        InterfaceType;
> -
> -  //
> -  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
> -  // The measurement has to be done before any update.
> -  // Otherwise, the PCR record would be different after event log update
> -  // or the PCD configuration change.
> -  //
> -  TpmMeasureAndLogData(
> -    0,
> -    EV_POST_CODE,
> -    EV_POSTCODE_INFO_ACPI_DATA,
> -    ACPI_DATA_LEN,
> -    &mTpm2AcpiTemplate,
> -    mTpm2AcpiTemplate.Header.Length
> -    );
> -
> -  mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);
> -  DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n",
> mTpm2AcpiTemplate.Header.Revision));
> -
> -  //
> -  // PlatformClass is only valid for version 4 and above
> -  //    BIT0~15:  PlatformClass
> -  //    BIT16~31: Reserved
> -  //
> -  if (mTpm2AcpiTemplate.Header.Revision >=
> EFI_TPM2_ACPI_TABLE_REVISION_4) {
> -    mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) |
> PcdGet8(PcdTpmPlatformClass);
> -    DEBUG((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n",
> (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));
> -  }
> -
> -  mTpm2AcpiTemplate.Laml = PcdGet32(PcdTpm2AcpiTableLaml);
> -  mTpm2AcpiTemplate.Lasa = PcdGet64(PcdTpm2AcpiTableLasa);
> -  if ((mTpm2AcpiTemplate.Header.Revision <
> EFI_TPM2_ACPI_TABLE_REVISION_4) ||
> -      (mTpm2AcpiTemplate.Laml == 0) || (mTpm2AcpiTemplate.Lasa == 0)) {
> -    //
> -    // If version is smaller than 4 or Laml/Lasa is not valid, rollback to original
> Length.
> -    //
> -    mTpm2AcpiTemplate.Header.Length = sizeof(EFI_TPM2_ACPI_TABLE);
> -  }
> +  EFI_STATUS Status;
> 
> -  InterfaceType = PcdGet8(PcdActiveTpmInterfaceType);
> -  switch (InterfaceType) {
> -  case Tpm2PtpInterfaceCrb:
> -    mTpm2AcpiTemplate.StartMethod =
> EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INT
> ERFACE;
> -    mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64
> (PcdTpmBaseAddress) + 0x40;
> -    ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA
> *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;
> -    ControlArea->CommandSize  = 0xF80;
> -    ControlArea->ResponseSize = 0xF80;
> -    ControlArea->Command      = PcdGet64 (PcdTpmBaseAddress) + 0x80;
> -    ControlArea->Response     = PcdGet64 (PcdTpmBaseAddress) + 0x80;
> -    break;
> -  case Tpm2PtpInterfaceFifo:
> -  case Tpm2PtpInterfaceTis:
> -    break;
> -  default:
> -    DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n",
> InterfaceType));
> -    break;
> +  if (mReadyToLockHandle != NULL) {
> +    Status = gMmst->MmiHandlerUnRegister (mReadyToLockHandle);
> +    mReadyToLockHandle = NULL;
>    }
> -
> -  CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr
> (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
> -  OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
> -  CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof
> (UINT64));
> -  mTpm2AcpiTemplate.Header.OemRevision      = PcdGet32
> (PcdAcpiDefaultOemRevision);
> -  mTpm2AcpiTemplate.Header.CreatorId        = PcdGet32
> (PcdAcpiDefaultCreatorId);
> -  mTpm2AcpiTemplate.Header.CreatorRevision  = PcdGet32
> (PcdAcpiDefaultCreatorRevision);
> -
> -  //
> -  // Construct ACPI table
> -  //
> -  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)
> &AcpiTable);
> -  ASSERT_EFI_ERROR (Status);
> -
> -  Status = AcpiTable->InstallAcpiTable (
> -                        AcpiTable,
> -                        &mTpm2AcpiTemplate,
> -                        mTpm2AcpiTemplate.Header.Length,
> -                        &TableKey
> -                        );
> -  ASSERT_EFI_ERROR (Status);
> -
>    return Status;
>  }
> 
>  /**
> -  The driver's entry point.
> +  The driver's common initialization routine.
> 
>    It install callbacks for TPM physical presence and MemoryClear, and locate
>    SMM variable to be used in the callback function.
> 
> -  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
> -  @param[in] SystemTable  A pointer to the EFI System Table.
> -
>    @retval EFI_SUCCESS     The entry point is executed successfully.
>    @retval Others          Some error occurs when executing this entry point.
> 
>  **/
>  EFI_STATUS
> -EFIAPI
> -InitializeTcgSmm (
> -  IN EFI_HANDLE                  ImageHandle,
> -  IN EFI_SYSTEM_TABLE            *SystemTable
> +InitializeTcgCommon (
> +  VOID
>    )
>  {
>    EFI_STATUS                     Status;
>    EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;
>    EFI_SMM_SW_REGISTER_CONTEXT    SwContext;
> -  EFI_HANDLE                     SwHandle;
> +  EFI_HANDLE                     PpSwHandle;
> +  EFI_HANDLE                     McSwHandle;
> +  EFI_HANDLE                     NotifyHandle;
> 
>    if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid),
> &gEfiTpmDeviceInstanceTpm20DtpmGuid)){
>      DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));
>      return EFI_UNSUPPORTED;
>    }
> 
> -  Status = PublishAcpiTable ();
> +  // Register a root handler to communicate the NVS region and SMI channel
> between MM and DXE
> +  mReadyToLockHandle = NULL;
> +  Status = gMmst->MmiHandlerRegister (TpmNvsCommunciate,
> &gTpmNvsMmGuid, &mReadyToLockHandle);
>    ASSERT_EFI_ERROR (Status);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "[%a] Failed to register NVS communicate as root
> MM handler - %r!\n", __FUNCTION__, Status));
> +    goto Cleanup;
> +  }
> 
>    //
>    // Get the Sw dispatch protocol and register SMI callback functions.
>    //
>    Status = gMmst->MmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid,
> NULL, (VOID**)&SwDispatch);
>    ASSERT_EFI_ERROR (Status);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "[%a] Failed to locate Sw dispatch protocol -
>  %r!\n", __FUNCTION__, Status));
> +    goto Cleanup;
> +  }
> +
> +  PpSwHandle = NULL;
>    SwContext.SwSmiInputValue = (UINTN) -1;
> -  Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback,
> &SwContext, &SwHandle);
> +  Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback,
> &SwContext, &PpSwHandle);
>    ASSERT_EFI_ERROR (Status);
>    if (EFI_ERROR (Status)) {
> -    return Status;
> +    DEBUG ((DEBUG_ERROR, "[%a] Failed to register PP callback as SW MM
> handler - %r!\n", __FUNCTION__, Status));
> +    goto Cleanup;
>    }
> -  mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8)
> SwContext.SwSmiInputValue;
> +  mPpSoftwareSmi = SwContext.SwSmiInputValue;
> 
> +  McSwHandle = NULL;
>    SwContext.SwSmiInputValue = (UINTN) -1;
> -  Status = SwDispatch->Register (SwDispatch, MemoryClearCallback,
> &SwContext, &SwHandle);
> +  Status = SwDispatch->Register (SwDispatch, MemoryClearCallback,
> &SwContext, &McSwHandle);
>    ASSERT_EFI_ERROR (Status);
>    if (EFI_ERROR (Status)) {
> -    return Status;
> +    DEBUG ((DEBUG_ERROR, "[%a] Failed to register MC callback as SW MM
> handler - %r!\n", __FUNCTION__, Status));
> +    goto Cleanup;
>    }
> -  mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
> +  mMcSoftwareSmi = SwContext.SwSmiInputValue;
> 
>    //
>    // Locate SmmVariableProtocol.
>    //
>    Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL,
> (VOID**)&mSmmVariable);
>    ASSERT_EFI_ERROR (Status);
> +  if (EFI_ERROR (Status)) {
> +    // Should not happen
> +    DEBUG ((DEBUG_ERROR, "[%a] Failed to locate SMM variable protocol -
>  %r!\n", __FUNCTION__, Status));
> +    goto Cleanup;
> +  }
> 
> -  //
> -  // Set TPM2 ACPI table
> -  //
> -  Status = PublishTpm2 ();
> +  // Turn off the light before leaving the room... at least, take a remote...
> +  NotifyHandle = NULL;
> +  Status = gMmst->MmRegisterProtocolNotify
> (&gEfiMmReadyToLockProtocolGuid, TcgMmReadyToLock, &NotifyHandle);
>    ASSERT_EFI_ERROR (Status);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "[%a] Failed to register ready to lock notification -
>  %r!\n", __FUNCTION__, Status));
> +    goto Cleanup;
> +  }
> 
> +  Tcg2NotifyMmReady ();
> 
> -  return EFI_SUCCESS;
> +Cleanup:
> +  if (EFI_ERROR (Status)) {
> +    // Something is whacked, clean up the mess...
> +    if (NotifyHandle != NULL) {
> +      gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid,
> NULL, &NotifyHandle);
> +    }
> +    if (McSwHandle != NULL && SwDispatch != NULL) {
> +      SwDispatch->UnRegister (SwDispatch, McSwHandle);
> +    }
> +    if (PpSwHandle != NULL && SwDispatch != NULL) {
> +      SwDispatch->UnRegister (SwDispatch, PpSwHandle);
> +    }
> +    if (mReadyToLockHandle != NULL) {
> +      gMmst->MmiHandlerUnRegister (mReadyToLockHandle);
> +    }
> +  }
> +
> +  return Status;
>  }
> 
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c
> new file mode 100644
> index 000000000000..5930090b4e46
> --- /dev/null
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c
> @@ -0,0 +1,82 @@
> +/** @file
> +  TCG2 SMM driver that updates TPM2 items in ACPI table and registers
> +  SMI2 callback functions for Tcg2 physical presence, ClearMemory, and
> +  sample for dTPM StartMethod.
> +
> +  Caution: This module requires additional review when modified.
> +  This driver will have external input - variable and ACPINvs data in SMM mode.
> +  This external input must be validated carefully to avoid security issue.
> +
> +  PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted
> input and do some check.
> +
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) Microsoft Corporation.
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Tcg2Smm.h"
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/SmmMemLib.h>
> +
> +/**
> +  Notify the system that the SMM variable driver is ready.
> +**/
> +VOID
> +Tcg2NotifyMmReady (
> +  VOID
> +  )
> +{
> +  EFI_STATUS            Status;
> +  EFI_HANDLE            Handle;
> +
> +  Handle = NULL;
> +  Status = gBS->InstallProtocolInterface (
> +                  &Handle,
> +                  &gTcg2MmSwSmiRegisteredGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +}
> +
> +/**
> +  This function is an abstraction layer for implementation specific Mm buffer
> validation routine.
> +
> +  @param Buffer  The buffer start address to be checked.
> +  @param Length  The buffer length to be checked.
> +
> +  @retval TRUE  This buffer is valid per processor architecture and not overlap
> with SMRAM.
> +  @retval FALSE This buffer is not valid per processor architecture or overlap
> with SMRAM.
> +**/
> +BOOLEAN
> +IsBufferOutsideMmValid (
> +  IN EFI_PHYSICAL_ADDRESS  Buffer,
> +  IN UINT64                Length
> +  )
> +{
> +  return SmmIsBufferOutsideSmmValid (Buffer, Length);
> +}
> +
> +/**
> +  The driver's entry point.
> +
> +  It install callbacks for TPM physical presence and MemoryClear, and locate
> +  SMM variable to be used in the callback function.
> +
> +  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
> +  @param[in] SystemTable  A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS     The entry point is executed successfully.
> +  @retval Others          Some error occurs when executing this entry point.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeTcgSmm (
> +  IN EFI_HANDLE                  ImageHandle,
> +  IN EFI_SYSTEM_TABLE            *SystemTable
> +  )
> +{
> +  return InitializeTcgCommon ();
> +}
> diff --git a/SecurityPkg/Include/Guid/TpmNvsMm.h
> b/SecurityPkg/Include/Guid/TpmNvsMm.h
> new file mode 100644
> index 000000000000..a6e8e1f30f95
> --- /dev/null
> +++ b/SecurityPkg/Include/Guid/TpmNvsMm.h
> @@ -0,0 +1,68 @@
> +/** @file
> +  TPM NVS MM guid, used for exchanging information, including SWI value and
> NVS region
> +  information, for patching TPM ACPI table.
> +
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) Microsoft Corporation.
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef __TCG2_NVS_MM_H__
> +#define __TCG2_NVS_MM_H__
> +
> +#define MM_TPM_NVS_HOB_GUID \
> +  { 0xc96c76eb, 0xbc78, 0x429c, { 0x9f, 0x4b, 0xda, 0x51, 0x78, 0xc2, 0x84,
> 0x57 }}
> +
> +extern EFI_GUID gTpmNvsMmGuid;
> +
> +#pragma pack(1)
> +typedef struct {
> +  UINT8                  SoftwareSmi;
> +  UINT32                 Parameter;
> +  UINT32                 Response;
> +  UINT32                 Request;
> +  UINT32                 RequestParameter;
> +  UINT32                 LastRequest;
> +  UINT32                 ReturnCode;
> +} PHYSICAL_PRESENCE_NVS;
> +
> +typedef struct {
> +  UINT8                  SoftwareSmi;
> +  UINT32                 Parameter;
> +  UINT32                 Request;
> +  UINT32                 ReturnCode;
> +} MEMORY_CLEAR_NVS;
> +
> +typedef struct {
> +  PHYSICAL_PRESENCE_NVS  PhysicalPresence;
> +  MEMORY_CLEAR_NVS       MemoryClear;
> +  UINT32                 PPRequestUserConfirm;
> +  UINT32                 TpmIrqNum;
> +  BOOLEAN                IsShortFormPkgLength;
> +} TCG_NVS;
> +
> +typedef struct {
> +  UINT8                  OpRegionOp;
> +  UINT32                 NameString;
> +  UINT8                  RegionSpace;
> +  UINT8                  DWordPrefix;
> +  UINT32                 RegionOffset;
> +  UINT8                  BytePrefix;
> +  UINT8                  RegionLen;
> +} AML_OP_REGION_32_8;
> +
> +typedef struct {
> +  UINT64                Function;
> +  UINT64                ReturnStatus;
> +  EFI_PHYSICAL_ADDRESS  TargetAddress;
> +  UINT64                RegisteredPpSwiValue;
> +  UINT64                RegisteredMcSwiValue;
> +} TPM_NVS_MM_COMM_BUFFER;
> +#pragma pack()
> +
> +typedef enum {
> +  TpmNvsMmExchangeInfo,
> +} TPM_NVS_MM_FUNCTION;
> +
> +#endif  // __TCG_SMM_H__
> diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
> index 1b7d62e802b3..0970cae5c75e 100644
> --- a/SecurityPkg/SecurityPkg.dec
> +++ b/SecurityPkg/SecurityPkg.dec
> @@ -183,6 +183,13 @@ [Guids]
>    ## Include/OpalPasswordExtraInfoVariable.h
>    gOpalExtraInfoVariableGuid =  {0x44a2ad5d, 0x612c, 0x47b3, {0xb0, 0x6e,
> 0xc8, 0xf5, 0x0b, 0xfb, 0xf0, 0x7d}}
> 
> +  ## GUID used to exchange registered SWI value and NVS region between
> Tcg2Acpi and Tcg2Smm.
> +  ## Include/Guid/TpmNvsMm.h
> +  gTpmNvsMmGuid                      = { 0xc96c76eb, 0xbc78, 0x429c, { 0x9f, 0x4b,
> 0xda, 0x51, 0x78, 0xc2, 0x84, 0x57 }}
> +
> +  ## GUID used to enforce loading order between Tcg2Acpi and Tcg2Smm
> +  gTcg2MmSwSmiRegisteredGuid         = { 0x9d4548b9, 0xa48d, 0x4db4, { 0x9a,
> 0x68, 0x32, 0xc5, 0x13, 0x9e, 0x20, 0x18 } }
> +
> 
>  [Ppis]
>    ## The PPI GUID for that TPM physical presence should be locked.
> diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
> index 618420a56c33..928bff72baa3 100644
> --- a/SecurityPkg/SecurityPkg.dsc
> +++ b/SecurityPkg/SecurityPkg.dsc
> @@ -317,6 +317,7 @@ [Components.IA32, Components.X64]
>    SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf
>    SecurityPkg/Tcg/TcgSmm/TcgSmm.inf
>    SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> +  SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf
> 
> SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib
> .inf
> 
> SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalP
> resenceLib.inf
> 
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> b/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf
> similarity index 76%
> copy from SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> copy to SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf
> index 872ed27cbe71..d8e06881c01d 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> +++ b/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf
> @@ -13,8 +13,8 @@
>  #     "Errata for PC Client Specific Platform Firmware Profile Specification
> Version 1.0 Revision 1.03"
>  #
>  #  This driver implements TPM 2.0 definition block in ACPI table and
> -#  registers SMI callback functions for Tcg2 physical presence and
> -#  MemoryClear to handle the requests from ACPI method.
> +#  populates registered SMI callback functions for Tcg2 physical presence
> +#  and MemoryClear to handle the requests for ACPI method.
>  #
>  #  Caution: This module requires additional review when modified.
>  #  This driver will have external input - variable and ACPINvs data in SMM mode.
> @@ -28,17 +28,15 @@
> 
>  [Defines]
>    INF_VERSION                    = 0x00010005
> -  BASE_NAME                      = Tcg2Smm
> -  MODULE_UNI_FILE                = Tcg2Smm.uni
> -  FILE_GUID                      = 44A20657-10B8-4049-A148-ACD8812AF257
> -  MODULE_TYPE                    = DXE_SMM_DRIVER
> +  BASE_NAME                      = Tcg2Acpi
> +  FILE_GUID                      = 0D4BBF18-C2CC-4C23-BD63-BFDAD4C710D0
> +  MODULE_TYPE                    = DXE_DRIVER
>    PI_SPECIFICATION_VERSION       = 0x0001000A
>    VERSION_STRING                 = 1.0
> -  ENTRY_POINT                    = InitializeTcgSmm
> +  ENTRY_POINT                    = InitializeTcgAcpi
> 
>  [Sources]
> -  Tcg2Smm.h
> -  Tcg2Smm.c
> +  Tcg2Acpi.c
>    Tpm.asl
> 
>  [Packages]
> @@ -50,7 +48,6 @@ [LibraryClasses]
>    BaseLib
>    BaseMemoryLib
>    UefiDriverEntryPoint
> -  MmServicesTableLib
>    UefiBootServicesTableLib
>    DebugLib
>    DxeServicesLib
> @@ -60,16 +57,13 @@ [LibraryClasses]
>    PcdLib
> 
>  [Guids]
> -  ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"
> -  ## SOMETIMES_CONSUMES ## Variable:L"MemoryOverwriteRequestControl"
> -  gEfiMemoryOverwriteControlDataGuid
> -
>    gEfiTpmDeviceInstanceTpm20DtpmGuid                            ## PRODUCES           ##
> GUID       # TPM device identifier
> +  gTpmNvsMmGuid                                                 ## CONSUMES
> +  gEdkiiPiSmmCommunicationRegionTableGuid                       ## CONSUMES
> 
>  [Protocols]
> -  gEfiSmmSwDispatch2ProtocolGuid                                ## CONSUMES
> -  gEfiSmmVariableProtocolGuid                                   ## CONSUMES
>    gEfiAcpiTableProtocolGuid                                     ## CONSUMES
> +  gEfiMmCommunicationProtocolGuid                               ## CONSUMES
> 
>  [FixedPcd]
>    gEfiSecurityPkgTokenSpaceGuid.PcdSmiCommandIoPort             ## CONSUMES
> @@ -93,9 +87,5 @@ [Pcd]
> 
>  [Depex]
>    gEfiAcpiTableProtocolGuid AND
> -  gEfiSmmSwDispatch2ProtocolGuid AND
> -  gEfiSmmVariableProtocolGuid AND
> +  gTcg2MmSwSmiRegisteredGuid AND
>    gEfiTcg2ProtocolGuid
> -
> -[UserExtensions.TianoCore."ExtraFiles"]
> -  Tcg2SmmExtra.uni
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> b/SecurityPkg/Tcg/Tcg2Acpi/Tpm.asl
> similarity index 100%
> rename from SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
> rename to SecurityPkg/Tcg/Tcg2Acpi/Tpm.asl
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> index d7328c8f2ac9..d7f78aa43275 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
> @@ -2,6 +2,7 @@
>    The header file for Tcg2 SMM driver.
> 
>  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) Microsoft Corporation.
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -9,13 +10,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #ifndef __TCG2_SMM_H__
>  #define __TCG2_SMM_H__
> 
> -#include <PiDxe.h>
> -#include <IndustryStandard/Acpi.h>
> -#include <IndustryStandard/Tpm2Acpi.h>
> +#include <PiMm.h>
> 
>  #include <Guid/MemoryOverwriteControl.h>
>  #include <Guid/TpmInstance.h>
> +#include <Guid/TpmNvsMm.h>
> 
> +#include <Protocol/MmReadyToLock.h>
>  #include <Protocol/SmmSwDispatch2.h>
>  #include <Protocol/AcpiTable.h>
>  #include <Protocol/SmmVariable.h>
> @@ -25,56 +26,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <Library/BaseMemoryLib.h>
>  #include <Library/DebugLib.h>
>  #include <Library/MmServicesTableLib.h>
> -#include <Library/UefiDriverEntryPoint.h>
> -#include <Library/UefiBootServicesTableLib.h>
> -#include <Library/DxeServicesLib.h>
> -#include <Library/TpmMeasurementLib.h>
>  #include <Library/Tpm2CommandLib.h>
>  #include <Library/Tcg2PhysicalPresenceLib.h>
>  #include <Library/IoLib.h>
> -#include <Library/PrintLib.h>
>  #include <Library/PcdLib.h>
>  #include <Library/Tpm2DeviceLib.h>
> 
>  #include <IndustryStandard/TpmPtp.h>
> 
> -#pragma pack(1)
> -typedef struct {
> -  UINT8                  SoftwareSmi;
> -  UINT32                 Parameter;
> -  UINT32                 Response;
> -  UINT32                 Request;
> -  UINT32                 RequestParameter;
> -  UINT32                 LastRequest;
> -  UINT32                 ReturnCode;
> -} PHYSICAL_PRESENCE_NVS;
> -
> -typedef struct {
> -  UINT8                  SoftwareSmi;
> -  UINT32                 Parameter;
> -  UINT32                 Request;
> -  UINT32                 ReturnCode;
> -} MEMORY_CLEAR_NVS;
> -
> -typedef struct {
> -  PHYSICAL_PRESENCE_NVS  PhysicalPresence;
> -  MEMORY_CLEAR_NVS       MemoryClear;
> -  UINT32                 PPRequestUserConfirm;
> -  UINT32                 TpmIrqNum;
> -  BOOLEAN                IsShortFormPkgLength;
> -} TCG_NVS;
> -
> -typedef struct {
> -  UINT8                  OpRegionOp;
> -  UINT32                 NameString;
> -  UINT8                  RegionSpace;
> -  UINT8                  DWordPrefix;
> -  UINT32                 RegionOffset;
> -  UINT8                  BytePrefix;
> -  UINT8                  RegionLen;
> -} AML_OP_REGION_32_8;
> -#pragma pack()
> -
>  //
>  // The definition for TCG MOR
>  //
> @@ -87,36 +46,42 @@ typedef struct {
>  #define MOR_REQUEST_SUCCESS                                        0
>  #define MOR_REQUEST_GENERAL_FAILURE                                1
> 
> -//
> -// Physical Presence Interface Version supported by Platform
> -//
> -#define PHYSICAL_PRESENCE_VERSION_TAG                              "$PV"
> -#define PHYSICAL_PRESENCE_VERSION_SIZE                             4
> -
> -//
> -// PNP _HID for TPM2 device
> -//
> -#define TPM_HID_TAG                                                "NNNN0000"
> -#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)
> +/**
> +  Notify the system that the SMM variable driver is ready.
> +**/
> +VOID
> +Tcg2NotifyMmReady (
> +  VOID
> +  );
> +
> +/**
> +  This function is an abstraction layer for implementation specific Mm buffer
> validation routine.
> +
> +  @param Buffer  The buffer start address to be checked.
> +  @param Length  The buffer length to be checked.
> +
> +  @retval TRUE  This buffer is valid per processor architecture and not overlap
> with SMRAM.
> +  @retval FALSE This buffer is not valid per processor architecture or overlap
> with SMRAM.
> +**/
> +BOOLEAN
> +IsBufferOutsideMmValid (
> +  IN EFI_PHYSICAL_ADDRESS  Buffer,
> +  IN UINT64                Length
> +  );
> +
> +/**
> +  The driver's common initialization routine.
> +
> +  It install callbacks for TPM physical presence and MemoryClear, and locate
> +  SMM variable to be used in the callback function.
> +
> +  @retval EFI_SUCCESS     The entry point is executed successfully.
> +  @retval Others          Some error occurs when executing this entry point.
> +
> +**/
> +EFI_STATUS
> +InitializeTcgCommon (
> +  VOID
> +  );
> +
>  #endif  // __TCG_SMM_H__
> diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> index 872ed27cbe71..096338d0ef47 100644
> --- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
> @@ -39,7 +39,7 @@ [Defines]
>  [Sources]
>    Tcg2Smm.h
>    Tcg2Smm.c
> -  Tpm.asl
> +  Tcg2TraditionalMm.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> @@ -58,6 +58,7 @@ [LibraryClasses]
>    Tpm2CommandLib
>    Tcg2PhysicalPresenceLib
>    PcdLib
> +  SmmMemLib
> 
>  [Guids]
>    ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"
> @@ -65,34 +66,18 @@ [Guids]
>    gEfiMemoryOverwriteControlDataGuid
> 
>    gEfiTpmDeviceInstanceTpm20DtpmGuid                            ## PRODUCES           ##
> GUID       # TPM device identifier
> +  gTcg2MmSwSmiRegisteredGuid                                    ## PRODUCES
> +  gTpmNvsMmGuid                                                 ## CONSUMES
> 
>  [Protocols]
>    gEfiSmmSwDispatch2ProtocolGuid                                ## CONSUMES
>    gEfiSmmVariableProtocolGuid                                   ## CONSUMES
> -  gEfiAcpiTableProtocolGuid                                     ## CONSUMES
> -
> -[FixedPcd]
> -  gEfiSecurityPkgTokenSpaceGuid.PcdSmiCommandIoPort             ## CONSUMES
> +  gEfiMmReadyToLockProtocolGuid                                 ## CONSUMES
> 
>  [Pcd]
>    gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid              ## CONSUMES
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId            ##
> SOMETIMES_CONSUMES
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId       ##
> SOMETIMES_CONSUMES
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision      ##
> SOMETIMES_CONSUMES
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId        ##
> SOMETIMES_CONSUMES
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision  ##
> SOMETIMES_CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress               ## CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer  ##
> CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev                 ##
> CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass                 ##
> SOMETIMES_CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2CurrentIrqNum            ## CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf        ##
> CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType       ##
> CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml            ## CONSUMES
> -  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa            ## CONSUMES
> 
>  [Depex]
> -  gEfiAcpiTableProtocolGuid AND
>    gEfiSmmSwDispatch2ProtocolGuid AND
>    gEfiSmmVariableProtocolGuid AND
>    gEfiTcg2ProtocolGuid
> --
> 2.30.0.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#72124): https://edk2.groups.io/g/devel/message/72124
Mute This Topic: https://groups.io/mt/80522087/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list