[edk2-devel] [PATCH V3 20/32] AMD/VanGoghBoard: Check in FTPM module

Zhai, MingXin (Duke) via groups.io posted 32 patches 7 months, 2 weeks ago
Only 28 patches received!
[edk2-devel] [PATCH V3 20/32] AMD/VanGoghBoard: Check in FTPM module
Posted by Zhai, MingXin (Duke) via groups.io 7 months, 2 weeks ago
From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  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.

Signed-off-by: Ken Yao <ken.yao@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c   |  113 ++
 .../DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf |   48 +
 .../PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c   |  141 ++
 .../PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf |   47 +
 .../AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c |  108 ++
 .../Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf       |   43 +
 .../Tpm2InstanceLibAmdFTpm.inf                |   53 +
 .../Tpm2InstanceLibAmdFTpmDxe.c               |  109 ++
 .../Tpm2InstanceLibAmdFTpmPei.c               |  153 ++
 .../DxeTcg2PhysicalPresenceLib.c              | 1269 +++++++++++++++++
 .../DxeTcg2PhysicalPresenceLib.inf            |   68 +
 .../DxeTcg2PhysicalPresenceLib.uni            |   22 +
 .../PhysicalPresenceStrings.uni               |   57 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c         |  854 +++++++++++
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h         |  123 ++
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf       |   92 ++
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni       |   19 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni  |   15 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl           |  397 ++++++
 .../Tcg/Tcg2Config/Tcg2ConfigNvData.h         |  124 ++
 .../Tcg/Tcg2Config/Tcg2ConfigPei.inf          |   77 +
 .../Tcg/Tcg2Config/Tcg2ConfigPei.uni          |   14 +
 .../Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni     |   15 +
 .../Tcg/Tcg2Config/Tcg2ConfigPeim.c           |  148 ++
 .../SecurityPkg/Tcg/Tcg2Config/TpmDetection.c |   99 ++
 25 files changed, 4208 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
new file mode 100644
index 0000000000..fe359cdc28
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
@@ -0,0 +1,113 @@
+/** @file
+  This library is TPM2 device router. Platform can register multi TPM2 instance to it
+  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+  At most one TPM2 instance can be finally registered, and other will return unsupported.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Protocol/AmdPspFtpmProtocol.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+PSP_FTPM_PROTOCOL  *PspFtpmProtocol;
+extern EFI_GUID    gAmdPspFtpmProtocolGuid;
+
+/**
+  The constructor function for this library.
+
+  @param  None
+
+  @retval EFI_SUCCESS   This library is ready for use.
+
+**/
+EFI_STATUS
+EFIAPI
+Tpm2DeviceLibConstructor (
+  VOID
+  )
+{
+  return gBS->LocateProtocol (&gAmdPspFtpmProtocolGuid, NULL, (VOID **)&PspFtpmProtocol);
+}
+
+/**
+  This service enables the sending of commands to the TPM2.
+
+  @param[in]  InputParameterBlockSize  Size of the TPM2 input parameter block.
+  @param[in]  InputParameterBlock      Pointer to the TPM2 input parameter block.
+  @param[in]  OutputParameterBlockSize Size of the TPM2 output parameter block.
+  @param[in]  OutputParameterBlock     Pointer to the TPM2 output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if ((NULL == InputParameterBlock) || (NULL == OutputParameterBlock) || (0 == InputParameterBlockSize)) {
+    DEBUG ((DEBUG_ERROR, "Buffer == NULL or InputParameterBlockSize == 0\n"));
+    Status = EFI_INVALID_PARAMETER;
+    return Status;
+  }
+
+  Status = PspFtpmProtocol->Execute (
+                              PspFtpmProtocol,
+                              (VOID *)InputParameterBlock,
+                              InputParameterBlockSize,
+                              (VOID *)OutputParameterBlock,
+                              OutputParameterBlockSize
+                              );
+
+  return Status;
+}
+
+/**
+  This service requests use TPM2.
+
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.
+  @retval EFI_NOT_FOUND    TPM2 not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RequestUseTpm (
+  VOID
+  )
+{
+  FTPM_INFO  FtpmStatus;
+
+  return PspFtpmProtocol->GetInfo (PspFtpmProtocol, &FtpmStatus);
+}
+
+/**
+  This service register TPM2 device.
+
+  @Param Tpm2Device  TPM2 device
+
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RegisterTpm2DeviceLib (
+  IN TPM2_DEVICE_INTERFACE  *Tpm2Device
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
new file mode 100644
index 0000000000..6708abdfce
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
@@ -0,0 +1,48 @@
+## @file
+#  Provides TPM 2.0 TIS functions
+#
+#  This library is TPM 2.0 device router. Platform can register multi TPM 2.0 instance to
+#  it via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+#  At most one TPM 2.0 instance can be finally registered, and other will return unsupported.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2DeviceLibFtpm
+  FILE_GUID                      = E98C81D3-B90D-4D28-AB48-A207C89D44C0
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tpm2DeviceLib | DXE_DRIVER DXE_RUNTIME_DRIVER
+  CONSTRUCTOR                    = Tpm2DeviceLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources.common]
+  Tpm2DeviceLibFtpm.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+
+[Protocols]
+  gAmdPspFtpmProtocolGuid
+
+[Depex]
+  gAmdPspFtpmProtocolGuid
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
new file mode 100644
index 0000000000..9e8cb5588d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
@@ -0,0 +1,141 @@
+/** @file
+  This library is TPM2 device router. Platform can register multi TPM2 instance to it
+  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+  At most one TPM2 instance can be finally registered, and other will return unsupported.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Pi/PiPeiCis.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Ppi/AmdPspFtpmPpi.h>
+
+/**
+  The constructor function for this library.
+
+  @param  None
+
+  @retval EFI_SUCCESS   This library is ready for use.
+
+**/
+
+extern EFI_GUID  gAmdPspFtpmPpiGuid;
+
+EFI_STATUS
+EFIAPI
+Tpm2DeviceLibConstructor (
+  VOID
+  )
+{
+  PSP_FTPM_PPI  *PspFtpmPpi;
+
+  return (*GetPeiServicesTablePointer ())->LocatePpi (
+                                             GetPeiServicesTablePointer (),
+                                             &gAmdPspFtpmPpiGuid,
+                                             0,
+                                             NULL,
+                                             (VOID **)&PspFtpmPpi
+                                             );
+}
+
+/**
+  This service enables the sending of commands to the TPM2.
+
+  @param[in]  InputParameterBlockSize  Size of the TPM2 input parameter block.
+  @param[in]  InputParameterBlock      Pointer to the TPM2 input parameter block.
+  @param[in]  OutputParameterBlockSize Size of the TPM2 output parameter block.
+  @param[in]  OutputParameterBlock     Pointer to the TPM2 output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if ((NULL == InputParameterBlock) || (NULL == OutputParameterBlock) || (0 == InputParameterBlockSize)) {
+    DEBUG ((DEBUG_ERROR, "Buffer == NULL or InputParameterBlockSize == 0\n"));
+    Status = EFI_INVALID_PARAMETER;
+    return Status;
+  }
+
+  PSP_FTPM_PPI  *PspFtpmPpi;
+
+  Status = (*GetPeiServicesTablePointer ())->LocatePpi (
+                                               GetPeiServicesTablePointer (),
+                                               &gAmdPspFtpmPpiGuid,
+                                               0,
+                                               NULL,
+                                               (VOID **)&PspFtpmPpi
+                                               );
+  if (!EFI_ERROR (Status)) {
+    Status = PspFtpmPpi->Execute (
+                           PspFtpmPpi,
+                           (VOID *)InputParameterBlock,
+                           InputParameterBlockSize,
+                           (VOID *)OutputParameterBlock,
+                           OutputParameterBlockSize
+                           );
+  }
+
+  return Status;
+}
+
+/**
+  This service requests use TPM2.
+
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.
+  @retval EFI_NOT_FOUND    TPM2 not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RequestUseTpm (
+  VOID
+  )
+{
+  UINTN         FtpmStatus;
+  PSP_FTPM_PPI  *PspFtpmPpi;
+  EFI_STATUS    Status = (*GetPeiServicesTablePointer ())->LocatePpi (
+                                                             GetPeiServicesTablePointer (),
+                                                             &gAmdPspFtpmPpiGuid,
+                                                             0,
+                                                             NULL,
+                                                             (VOID **)&PspFtpmPpi
+                                                             );
+
+  return Status || PspFtpmPpi->CheckStatus (PspFtpmPpi, &FtpmStatus);
+}
+
+/**
+  This service register TPM2 device.
+
+  @Param Tpm2Device  TPM2 device
+
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RegisterTpm2DeviceLib (
+  IN TPM2_DEVICE_INTERFACE  *Tpm2Device
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
new file mode 100644
index 0000000000..a38ada3efd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
@@ -0,0 +1,47 @@
+## @file
+#  Provides TPM 2.0 TIS functions
+#
+#  This library is TPM 2.0 device router. Platform can register multi TPM 2.0 instance to
+#  it via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+#  At most one TPM 2.0 instance can be finally registered, and other will return unsupported.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2DeviceLibFtpm
+  FILE_GUID                      = 2E230843-274F-4C14-A4B5-46B6167E7A5C
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tpm2DeviceLib | PEIM
+  CONSTRUCTOR                    = Tpm2DeviceLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources.common]
+  Tpm2DeviceLibFtpm.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+
+[Ppis]
+  gAmdPspFtpmPpiGuid
+
+[Depex]
+  gAmdPspFtpmPpiGuid
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c
new file mode 100644
index 0000000000..713c87a1ca
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c
@@ -0,0 +1,108 @@
+/** @file
+  This library is TPM2 TCG2 protocol lib.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/AmdPspFtpmLib.h>
+
+/**
+  The constructor function for this library.
+
+  @param  None
+
+  @retval EFI_SUCCESS   This library is ready for use.
+
+**/
+EFI_STATUS
+EFIAPI
+Tpm2DeviceLibConstructor (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This service enables the sending of commands to the TPM2.
+
+  @param[in]  InputParameterBlockSize  Size of the TPM2 input parameter block.
+  @param[in]  InputParameterBlock      Pointer to the TPM2 input parameter block.
+  @param[in]  OutputParameterBlockSize Size of the TPM2 output parameter block.
+  @param[in]  OutputParameterBlock     Pointer to the TPM2 output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if ((NULL == InputParameterBlock) || (NULL == OutputParameterBlock) || (0 == InputParameterBlockSize)) {
+    DEBUG ((DEBUG_ERROR, "Buffer == NULL or InputParameterBlockSize == 0\n"));
+    Status = EFI_INVALID_PARAMETER;
+    return Status;
+  }
+
+  Status = FtpmExecuteCommand (
+             (VOID *)InputParameterBlock,
+             InputParameterBlockSize,
+             (VOID *)OutputParameterBlock,
+             OutputParameterBlockSize
+             );
+
+  return Status;
+}
+
+/**
+  This service requests use TPM2.
+
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.
+  @retval EFI_NOT_FOUND    TPM2 not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RequestUseTpm (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       FtpmStatus;
+
+  Status = FtpmGetInfo (&FtpmStatus);
+  return Status;
+}
+
+/**
+  This service register TPM2 device.
+
+  @Param Tpm2Device  TPM2 device
+
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RegisterTpm2DeviceLib (
+  IN TPM2_DEVICE_INTERFACE  *Tpm2Device
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf
new file mode 100644
index 0000000000..7e42703347
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf
@@ -0,0 +1,43 @@
+## @file
+#  Provides function interfaces to communicate with TPM 2.0 device
+#
+#  This library helps to use TPM 2.0 device in library function API
+#  based on TPM2 protocol.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2DeviceLibFtpm
+  FILE_GUID                      = 1E0C813B-46F5-4578-AA2D-E0AFFD89F2F9
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tpm2DeviceLib
+  CONSTRUCTOR                    = Tpm2DeviceLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources.common]
+  Tpm2DeviceLibFtpm.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  AmdPspFtpmLib
+
+[Depex]
+  TRUE
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf
new file mode 100644
index 0000000000..2b957fd942
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf
@@ -0,0 +1,53 @@
+## @file
+#  AMD Ftpm 2.0 Instance Library Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2InstanceLibAmdFtpm
+  FILE_GUID                      = F1FA6737-93AC-4B72-8906-3EAE247CFF8D
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NULL
+  CONSTRUCTOR                    = Tpm2InstanceLibAmdFTpmConstructor
+
+[Sources.IA32]
+  Tpm2InstanceLibAmdFTpmPei.c
+
+[Sources.X64]
+  Tpm2InstanceLibAmdFTpmDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses.X64]
+  UefiBootServicesTableLib
+
+[LibraryClasses.IA32]
+  PeiServicesLib
+
+[Protocols.X64]
+  gAmdPspFtpmProtocolGuid
+
+[Ppis.IA32]
+  gAmdPspFtpmPpiGuid
+  gAmdPspFtpmFactoryResetPpiGuid
+
+[Guids]
+  gEfiTpmDeviceInstanceNoneGuid
+
+[Pcd]
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdPspSystemTpmConfig
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid
+
+[Depex.IA32]
+  TRUE
+
+[Depex.X64]
+  TRUE
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c
new file mode 100644
index 0000000000..af9bf81c18
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c
@@ -0,0 +1,109 @@
+/** @file
+  Implements Tpm2InstanceLibAmdFTpmDxe.C
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/AmdPspFtpmProtocol.h>
+#include <Library/AmdPspFtpmLib.h>
+
+// gEfiTpmDeviceInstanceTpm20AmdFtpmGuid
+#define TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM  \
+  {0x286bf25a, 0xc2c3, 0x408c, {0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17}}
+
+PSP_FTPM_PROTOCOL  *mfTpmProtocol = NULL;
+
+/**
+  This service enables the sending of commands to the FTPM.
+
+  @param[in]      InputParameterBlockSize  Size of the FTPM input parameter block.
+  @param[in]      InputParameterBlock      Pointer to the FTPM input parameter block.
+  @param[in,out]  OutputParameterBlockSize Size of the FTPM output parameter block.
+  @param[in]      OutputParameterBlock     Pointer to the FTPM output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+FTpmSubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  return mfTpmProtocol->Execute (mfTpmProtocol, InputParameterBlock, InputParameterBlockSize, OutputParameterBlock, OutputParameterBlockSize);
+}
+
+/**
+  This service requests use FTPM.
+
+  @retval EFI_SUCCESS      Get the control of FTPM chip.
+  @retval EFI_NOT_FOUND    FTPM not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+FTpmRequestUseTpm (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       fTpmStatus;
+
+  if ((PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_PSP_FTPM) ||
+      (PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_HSP_FTPM))
+  {
+    Status = mfTpmProtocol->CheckStatus (mfTpmProtocol, &fTpmStatus);
+    DEBUG ((DEBUG_INFO, "fTPM Status = %r\n", Status));
+    return Status;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+TPM2_DEVICE_INTERFACE  mFTpmInternalTpm2Device = {
+  TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM,
+  FTpmSubmitCommand,
+  FTpmRequestUseTpm,
+};
+
+/**
+  The function register FTPM instance.
+
+  @retval EFI_SUCCESS   FTPM instance is registered, or system dose not surpport registr FTPM instance
+**/
+EFI_STATUS
+EFIAPI
+Tpm2InstanceLibAmdFTpmConstructor (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->LocateProtocol (
+                  &gAmdPspFtpmProtocolGuid,
+                  NULL,
+                  (VOID **)&mfTpmProtocol
+                  );
+  if (Status == EFI_SUCCESS) {
+    Status = Tpm2RegisterTpm2DeviceLib (&mFTpmInternalTpm2Device);
+    if (Status == EFI_UNSUPPORTED) {
+      //
+      // Unsupported means platform policy does not need this instance enabled.
+      //
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c
new file mode 100644
index 0000000000..35671644e2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c
@@ -0,0 +1,153 @@
+/** @file
+  Implements Tpm2InstanceLibAmdFTpmPei.C
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/PcdLib.h>
+#include <Ppi/AmdPspFtpmPpi.h>
+#include <Library/AmdPspFtpmLib.h>
+#include <Guid/TpmInstance.h>
+
+// gEfiTpmDeviceInstanceTpm20AmdFtpmGuid
+#define TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM  \
+  {0x286bf25a, 0xc2c3, 0x408c, {0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17}}
+
+/**
+ * @brief gAmdFtpmFactoryResetPpiGuid callback, disable TPM
+ *
+ * @param PeiServices
+ * @param NotifyDesc
+ * @param InvokePpi
+ * @return EFI_STATUS
+ */
+EFI_STATUS
+EFIAPI
+AmdFtpmFactoryResetCallback (
+  IN  EFI_PEI_SERVICES           **PeiServices,
+  IN  EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN  VOID                       *InvokePpi
+  )
+{
+  UINTN       Size;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "AmdFtpmFactoryResetCallback\n"));
+  // gEfiTpmDeviceInstanceNoneGuid GUID value used for PcdTpmInstanceGuid to indicate TPM is disabled.
+  Size   = sizeof (gEfiTpmDeviceInstanceNoneGuid);
+  Status = PcdSetPtrS (PcdTpmInstanceGuid, &Size, &gEfiTpmDeviceInstanceNoneGuid);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mAmdFtpmFactoryResetPpiCallback = {
+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gAmdPspFtpmFactoryResetPpiGuid,
+  AmdFtpmFactoryResetCallback
+};
+
+/**
+  This service enables the sending of commands to the FTPM.
+
+  @param[in]      InputParameterBlockSize  Size of the FTPM input parameter block.
+  @param[in]      InputParameterBlock      Pointer to the FTPM input parameter block.
+  @param[in,out]  OutputParameterBlockSize Size of the FTPM output parameter block.
+  @param[in]      OutputParameterBlock     Pointer to the FTPM output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+FTpmSubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  PSP_FTPM_PPI  *AmdFtpmPpi;
+  EFI_STATUS    Status;
+
+  Status = PeiServicesLocatePpi (&gAmdPspFtpmPpiGuid, 0, NULL, (VOID **)&AmdFtpmPpi);
+  if (Status == EFI_SUCCESS) {
+    return AmdFtpmPpi->Execute (AmdFtpmPpi, InputParameterBlock, InputParameterBlockSize, OutputParameterBlock, OutputParameterBlockSize);
+  }
+
+  return Status;
+}
+
+/**
+  This service requests use FTPM.
+
+  @retval EFI_SUCCESS      Get the control of FTPM chip.
+  @retval EFI_NOT_FOUND    FTPM not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+FTpmRequestUseTpm (
+  VOID
+  )
+{
+  if ((PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_PSP_FTPM) ||
+      (PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_HSP_FTPM))
+  {
+    // @todo Test fTPM functionality
+    DEBUG ((DEBUG_INFO, "fTPM is used\n"));
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+TPM2_DEVICE_INTERFACE  mFTpmInternalTpm2Device = {
+  TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM,
+  FTpmSubmitCommand,
+  FTpmRequestUseTpm,
+};
+
+/**
+  The function register FTPM instance.
+
+  @retval EFI_SUCCESS   FTPM instance is registered, or system dose not surpport registr FTPM instance
+**/
+EFI_STATUS
+EFIAPI
+Tpm2InstanceLibAmdFTpmConstructor (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+  PSP_FTPM_PPI  *AmdFtpmPpi;
+
+  if ((PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_PSP_FTPM) ||
+      (PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_HSP_FTPM))
+  {
+    //
+    // AMD HSP f-TPM for EDK2 Core Base, Get the HSP PSP TcgEvetLog before BIOS
+    //
+    Status = PeiServicesLocatePpi (&gAmdPspFtpmPpiGuid, 0, NULL, (VOID **)&AmdFtpmPpi);
+    if (Status == EFI_SUCCESS) {
+      Status = Tpm2RegisterTpm2DeviceLib (&mFTpmInternalTpm2Device);
+      if (Status == EFI_UNSUPPORTED) {
+        //
+        // Unsupported means platform policy does not need this instance enabled.
+        //
+        return EFI_SUCCESS;
+      }
+    }
+
+    PeiServicesNotifyPpi (&mAmdFtpmFactoryResetPpiCallback);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
new file mode 100644
index 0000000000..28b945fbba
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
@@ -0,0 +1,1269 @@
+/** @file
+  Execute pending TPM2 requests from OS or BIOS.
+
+  Caution: This module requires additional review when modified.
+  This driver will have external input - variable.
+  This external input must be validated carefully to avoid security issue.
+
+  Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/Tcg2Protocol.h>
+#include <Protocol/VariableLock.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HobLib.h>
+#include <Guid/EventGroup.h>
+#include <Guid/Tcg2PhysicalPresenceData.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+#include <Library/Tcg2PpVendorLib.h>
+
+#define CONFIRM_BUFFER_SIZE  4096
+
+EFI_HII_HANDLE  mTcg2PpStringPackHandle;
+
+/**
+  Get string by string id from HII Interface.
+
+  @param[in] Id          String ID.
+
+  @retval    CHAR16 *    String from ID.
+  @retval    NULL        If error occurs.
+
+**/
+CHAR16 *
+Tcg2PhysicalPresenceGetStringById (
+  IN  EFI_STRING_ID  Id
+  )
+{
+  return HiiGetString (mTcg2PpStringPackHandle, Id, NULL);
+}
+
+/**
+  Send ClearControl and Clear command to TPM.
+
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
+
+  @retval EFI_SUCCESS           Operation completed successfully.
+  @retval EFI_TIMEOUT           The register can't run into the expected status in time.
+  @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.
+  @retval EFI_DEVICE_ERROR      Unexpected device behavior.
+
+**/
+EFI_STATUS
+EFIAPI
+Tpm2CommandClear (
+  IN TPM2B_AUTH  *PlatformAuth  OPTIONAL
+  )
+{
+  EFI_STATUS         Status;
+  TPMS_AUTH_COMMAND  *AuthSession;
+  TPMS_AUTH_COMMAND  LocalAuthSession;
+
+  if (PlatformAuth == NULL) {
+    AuthSession = NULL;
+  } else {
+    AuthSession = &LocalAuthSession;
+    ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));
+    LocalAuthSession.sessionHandle = TPM_RS_PW;
+    LocalAuthSession.hmac.size     = PlatformAuth->size;
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
+  }
+
+  DEBUG ((DEBUG_INFO, "Tpm2ClearControl ... \n"));
+  Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);
+  DEBUG ((DEBUG_INFO, "Tpm2ClearControl - %r\n", Status));
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  DEBUG ((DEBUG_INFO, "Tpm2Clear ... \n"));
+  Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);
+  DEBUG ((DEBUG_INFO, "Tpm2Clear - %r\n", Status));
+
+Done:
+  ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));
+  return Status;
+}
+
+/**
+  Change EPS.
+
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
+
+  @retval EFI_SUCCESS Operation completed successfully.
+**/
+EFI_STATUS
+Tpm2CommandChangeEps (
+  IN TPM2B_AUTH  *PlatformAuth  OPTIONAL
+  )
+{
+  EFI_STATUS         Status;
+  TPMS_AUTH_COMMAND  *AuthSession;
+  TPMS_AUTH_COMMAND  LocalAuthSession;
+
+  if (PlatformAuth == NULL) {
+    AuthSession = NULL;
+  } else {
+    AuthSession = &LocalAuthSession;
+    ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));
+    LocalAuthSession.sessionHandle = TPM_RS_PW;
+    LocalAuthSession.hmac.size     = PlatformAuth->size;
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
+  }
+
+  Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession);
+  DEBUG ((DEBUG_INFO, "Tpm2ChangeEPS - %r\n", Status));
+
+  ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));
+  return Status;
+}
+
+/**
+  Execute physical presence operation requested by the OS.
+
+  @param[in]      PlatformAuth        platform auth value. NULL means no platform auth change.
+  @param[in]      CommandCode         Physical presence operation value.
+  @param[in]      CommandParameter    Physical presence operation parameter.
+  @param[in, out] PpiFlags            The physical presence interface flags.
+
+  @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Unknown physical presence operation.
+  @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Error occurred during sending command to TPM or
+                                                   receiving response from TPM.
+  @retval Others                                   Return code from the TPM device after command execution.
+**/
+UINT32
+Tcg2ExecutePhysicalPresence (
+  IN      TPM2B_AUTH *PlatformAuth, OPTIONAL
+  IN      UINT32                           CommandCode,
+  IN      UINT32                           CommandParameter,
+  IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_TCG2_EVENT_ALGORITHM_BITMAP  TpmHashAlgorithmBitmap;
+  UINT32                           ActivePcrBanks;
+
+  switch (CommandCode) {
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+      Status = Tpm2CommandClear (PlatformAuth);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
+      PpiFlags->PPFlags |= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+      Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // PP spec requirements:
+      //    Firmware should check that all requested (set) hashing algorithms are supported with respective PCR banks.
+      //    Firmware has to ensure that at least one PCR banks is active.
+      // If not, an error is returned and no action is taken.
+      //
+      if ((CommandParameter == 0) || ((CommandParameter & (~TpmHashAlgorithmBitmap)) != 0)) {
+        DEBUG ((DEBUG_ERROR, "PCR banks %x to allocate are not supported by TPM. Skip operation\n", CommandParameter));
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      }
+
+      Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, CommandParameter);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+      Status = Tpm2CommandChangeEps (PlatformAuth);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
+      Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
+      ASSERT_EFI_ERROR (Status);
+      Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, TpmHashAlgorithmBitmap);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+      PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
+      PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
+      PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    default:
+      if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      }
+  }
+}
+
+/**
+  Read the specified key for user confirmation.
+
+  @param[in]  CautionKey  If true,  F12 is used as confirm key;
+                          If false, F10 is used as confirm key.
+
+  @retval     TRUE        User confirmed the changes by input.
+  @retval     FALSE       User discarded the changes.
+**/
+BOOLEAN
+Tcg2ReadUserKey (
+  IN     BOOLEAN  CautionKey
+  )
+{
+  EFI_STATUS     Status;
+  EFI_INPUT_KEY  Key;
+  UINT16         InputKey;
+
+  InputKey = 0;
+  do {
+    Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
+    if (!EFI_ERROR (Status)) {
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+      if (Key.ScanCode == SCAN_ESC) {
+        InputKey = Key.ScanCode;
+      }
+
+      if ((Key.ScanCode == SCAN_F10) && !CautionKey) {
+        InputKey = Key.ScanCode;
+      }
+
+      if ((Key.ScanCode == SCAN_F12) && CautionKey) {
+        InputKey = Key.ScanCode;
+      }
+    }
+  } while (InputKey == 0);
+
+  if (InputKey != SCAN_ESC) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Fill Buffer With BootHashAlg.
+
+  @param[in] Buffer               Buffer to be filled.
+  @param[in] BufferSize           Size of buffer.
+  @param[in] BootHashAlg          BootHashAlg.
+
+**/
+VOID
+Tcg2FillBufferWithBootHashAlg (
+  IN UINT16  *Buffer,
+  IN UINTN   BufferSize,
+  IN UINT32  BootHashAlg
+  )
+{
+  Buffer[0] = 0;
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+}
+
+/**
+  Display the confirm text and get user confirmation.
+
+  @param[in] TpmPpCommand             The requested TPM physical presence command.
+  @param[in] TpmPpCommandParameter    The requested TPM physical presence command parameter.
+
+  @retval    TRUE          The user has confirmed the changes.
+  @retval    FALSE         The user doesn't confirm the changes.
+**/
+BOOLEAN
+Tcg2UserConfirm (
+  IN      UINT32  TpmPpCommand,
+  IN      UINT32  TpmPpCommandParameter
+  )
+{
+  CHAR16                            *ConfirmText;
+  CHAR16                            *TmpStr1;
+  CHAR16                            *TmpStr2;
+  UINTN                             BufSize;
+  BOOLEAN                           CautionKey;
+  BOOLEAN                           NoPpiInfo;
+  UINT16                            Index;
+  CHAR16                            DstStr[81];
+  CHAR16                            TempBuffer[1024];
+  CHAR16                            TempBuffer2[1024];
+  EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
+  EFI_TCG2_BOOT_SERVICE_CAPABILITY  ProtocolCapability;
+  UINT32                            CurrentPCRBanks;
+  EFI_STATUS                        Status;
+
+  TmpStr2     = NULL;
+  CautionKey  = FALSE;
+  NoPpiInfo   = FALSE;
+  BufSize     = CONFIRM_BUFFER_SIZE;
+  ConfirmText = AllocateZeroPool (BufSize);
+  ASSERT (ConfirmText != NULL);
+
+  mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, DxeTcg2PhysicalPresenceLibStrings, NULL);
+  ASSERT (mTcg2PpStringPackHandle != NULL);
+
+  switch (TpmPpCommand) {
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+      CautionKey = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
+      CautionKey = TRUE;
+      NoPpiInfo  = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+      Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);
+      ASSERT_EFI_ERROR (Status);
+
+      ProtocolCapability.Size = sizeof (ProtocolCapability);
+      Status                  = Tcg2Protocol->GetCapability (
+                                                Tcg2Protocol,
+                                                &ProtocolCapability
+                                                );
+      ASSERT_EFI_ERROR (Status);
+
+      Status = Tcg2Protocol->GetActivePcrBanks (
+                               Tcg2Protocol,
+                               &CurrentPCRBanks
+                               );
+      ASSERT_EFI_ERROR (Status);
+
+      CautionKey = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof (TempBuffer), TpmPpCommandParameter);
+      Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof (TempBuffer2), CurrentPCRBanks);
+
+      TmpStr1 = AllocateZeroPool (BufSize);
+      ASSERT (TmpStr1 != NULL);
+      UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer);
+
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+      CautionKey = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ENABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_DISABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+      NoPpiInfo = TRUE;
+      TmpStr2   = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_ENABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      NoPpiInfo = TRUE;
+      TmpStr2   = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_DISABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    default:
+      ;
+  }
+
+  if (TmpStr2 == NULL) {
+    FreePool (ConfirmText);
+    return FALSE;
+  }
+
+  if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) {
+    if (CautionKey) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
+    } else {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
+    }
+
+    StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+    FreePool (TmpStr1);
+
+    if (NoPpiInfo) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+    }
+
+    TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));
+  } else {
+    if (CautionKey) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY));
+    } else {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY));
+    }
+
+    StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+    FreePool (TmpStr1);
+
+    if (NoPpiInfo) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+    }
+
+    TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY));
+  }
+
+  BufSize -= StrSize (ConfirmText);
+  UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);
+
+  DstStr[80] = L'\0';
+  for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {
+    StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1);
+    Print (DstStr);
+  }
+
+  FreePool (TmpStr1);
+  FreePool (TmpStr2);
+  FreePool (ConfirmText);
+  HiiRemovePackages (mTcg2PpStringPackHandle);
+
+  if (Tcg2ReadUserKey (CautionKey)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Check if there is a valid physical presence command request. Also updates parameter value
+  to whether the requested physical presence command already confirmed by user
+
+   @param[in]  TcgPpData                 EFI Tcg2 Physical Presence request data.
+   @param[in]  Flags                     The physical presence interface flags.
+   @param[out] RequestConfirmed          If the physical presence operation command required user confirm from UI.
+                                           True, it indicates the command doesn't require user confirm, or already confirmed
+                                                 in last boot cycle by user.
+                                           False, it indicates the command need user confirm from UI.
+
+   @retval  TRUE        Physical Presence operation command is valid.
+   @retval  FALSE       Physical Presence operation command is invalid.
+
+**/
+BOOLEAN
+Tcg2HaveValidTpmRequest  (
+  IN      EFI_TCG2_PHYSICAL_PRESENCE        *TcgPpData,
+  IN      EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags,
+  OUT     BOOLEAN                           *RequestConfirmed
+  )
+{
+  EFI_TCG2_PROTOCOL  *Tcg2Protocol;
+  EFI_STATUS         Status;
+  BOOLEAN            IsRequestValid;
+
+  *RequestConfirmed = FALSE;
+
+  if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
+    //
+    // Need TCG2 protocol.
+    //
+    Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);
+    if (EFI_ERROR (Status)) {
+      return FALSE;
+    }
+  }
+
+  switch (TcgPpData->PPRequest) {
+    case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
+      *RequestConfirmed = TRUE;
+      return TRUE;
+
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
+      *RequestConfirmed = TRUE;
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
+      *RequestConfirmed = TRUE;
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+      if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
+      *RequestConfirmed = TRUE;
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      break;
+
+    default:
+      if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+        IsRequestValid = Tcg2PpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);
+        if (!IsRequestValid) {
+          return FALSE;
+        } else {
+          break;
+        }
+      } else {
+        //
+        // Wrong Physical Presence command
+        //
+        return FALSE;
+      }
+  }
+
+  if ((Flags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) != 0) {
+    //
+    // It had been confirmed in last boot, it doesn't need confirm again.
+    //
+    *RequestConfirmed = TRUE;
+  }
+
+  //
+  // Physical Presence command is correct
+  //
+  return TRUE;
+}
+
+/**
+  Check and execute the requested physical presence command.
+
+  Caution: This function may receive untrusted input.
+  TcgPpData variable is external input, so this function will validate
+  its data structure to be valid value.
+
+  @param[in]      PlatformAuth      platform auth value. NULL means no platform auth change.
+  @param[in, out] TcgPpData         Pointer to the physical presence NV variable.
+  @param[in, out] Flags             Pointer to the physical presence interface flags.
+**/
+VOID
+Tcg2ExecutePendingTpmRequest (
+  IN      TPM2B_AUTH *PlatformAuth, OPTIONAL
+  IN OUT  EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,
+  IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *Flags
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             DataSize;
+  BOOLEAN                           RequestConfirmed;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  NewFlags;
+  BOOLEAN                           ResetRequired;
+  UINT32                            NewPPFlags;
+
+  if (TcgPpData->PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
+    //
+    // No operation request
+    //
+    return;
+  }
+
+  if (!Tcg2HaveValidTpmRequest (TcgPpData, *Flags, &RequestConfirmed)) {
+    //
+    // Invalid operation request.
+    //
+    if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
+      TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_SUCCESS;
+    } else {
+      TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+    }
+
+    TcgPpData->LastPPRequest      = TcgPpData->PPRequest;
+    TcgPpData->PPRequest          = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+    TcgPpData->PPRequestParameter = 0;
+
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+    Status   = gRT->SetVariable (
+                      TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                      &gEfiTcg2PhysicalPresenceGuid,
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                      DataSize,
+                      TcgPpData
+                      );
+    return;
+  }
+
+  ResetRequired = FALSE;
+  if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+    NewFlags              = *Flags;
+    NewPPFlags            = NewFlags.PPFlags;
+    TcgPpData->PPResponse = Tcg2PpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);
+    NewFlags.PPFlags      = NewPPFlags;
+  } else {
+    if (!RequestConfirmed) {
+      //
+      // Print confirm text and wait for approval.
+      //
+      DEBUG ((DEBUG_INFO, "Print confirm text and wait for approval.\n"));
+      RequestConfirmed = TRUE;
+      // RequestConfirmed = Tcg2UserConfirm (TcgPpData->PPRequest, TcgPpData->PPRequestParameter);
+    }
+
+    //
+    // Execute requested physical presence command
+    //
+    TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;
+    NewFlags              = *Flags;
+    if (RequestConfirmed) {
+      TcgPpData->PPResponse = Tcg2ExecutePhysicalPresence (
+                                PlatformAuth,
+                                TcgPpData->PPRequest,
+                                TcgPpData->PPRequestParameter,
+                                &NewFlags
+                                );
+    }
+  }
+
+  //
+  // Save the flags if it is updated.
+  //
+  if (CompareMem (Flags, &NewFlags, sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS)) != 0) {
+    *Flags = NewFlags;
+    Status = gRT->SetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                    sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
+                    &NewFlags
+                    );
+  }
+
+  //
+  // Clear request
+  //
+  if ((NewFlags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) == 0) {
+    TcgPpData->LastPPRequest      = TcgPpData->PPRequest;
+    TcgPpData->PPRequest          = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+    TcgPpData->PPRequestParameter = 0;
+  }
+
+  //
+  // Save changes
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->SetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                    DataSize,
+                    TcgPpData
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Fail to set variable %S, %r\n", TCG2_PHYSICAL_PRESENCE_VARIABLE, Status));
+    return;
+  }
+
+  if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {
+    DEBUG ((DEBUG_INFO, "User abort the TPM action \n"));
+    return;
+  }
+
+  //
+  // Reset system to make new TPM settings in effect
+  //
+  switch (TcgPpData->LastPPRequest) {
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      return;
+
+    default:
+      if (TcgPpData->LastPPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+        if (ResetRequired) {
+          break;
+        } else {
+          return;
+        }
+      }
+
+      if (TcgPpData->PPRequest != TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
+        break;
+      }
+
+      return;
+  }
+
+  // Print (L"Rebooting system to make TPM2 settings in effect\n");
+  DEBUG ((DEBUG_INFO, "Rebooting system to make TPM2 settings in effect\n"));
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+  ASSERT (FALSE);
+}
+
+/**
+  Check and execute the pending TPM request.
+
+  The TPM request may come from OS or BIOS. This API will display request information and wait
+  for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
+  the TPM request is confirmed, and one or more reset may be required to make TPM request to
+  take effect.
+
+  This API should be invoked after console in and console out are all ready as they are required
+  to display request information and get user input to confirm the request.
+
+  @param[in]  PlatformAuth                   platform auth value. NULL means no platform auth change.
+**/
+VOID
+EFIAPI
+Tcg2PhysicalPresenceLibProcessRequest (
+  IN      TPM2B_AUTH  *PlatformAuth  OPTIONAL
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             DataSize;
+  EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
+  EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
+
+  //
+  // This flags variable controls whether physical presence is required for TPM command.
+  // It should be protected from malicious software. We set it as read-only variable here.
+  //
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
+  if (!EFI_ERROR (Status)) {
+    Status = VariableLockProtocol->RequestToLock (
+                                     VariableLockProtocol,
+                                     TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                                     &gEfiTcg2PhysicalPresenceGuid
+                                     );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  // On AMD FCH, always do S4 for shutdown.
+  // Todo: Chang to PCD method for this
+  //
+  // Check S4 resume
+  //
+  //  if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
+  //    DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n"));
+  //    return ;
+  //  }
+
+  //
+  // Initialize physical presence flags.
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpiFlags
+                    );
+  if (EFI_ERROR (Status)) {
+    PpiFlags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags);
+    Status           = gRT->SetVariable (
+                              TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                              &gEfiTcg2PhysicalPresenceGuid,
+                              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                              sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
+                              &PpiFlags
+                              );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));
+      return;
+    }
+
+    DEBUG ((DEBUG_INFO, "[TPM2] Initial physical presence flags value is 0x%x\n", PpiFlags.PPFlags));
+  }
+
+  //
+  // Initialize physical presence variable.
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &TcgPpData
+                    );
+  if (EFI_ERROR (Status)) {
+    ZeroMem ((VOID *)&TcgPpData, sizeof (TcgPpData));
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+    Status   = gRT->SetVariable (
+                      TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                      &gEfiTcg2PhysicalPresenceGuid,
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                      DataSize,
+                      &TcgPpData
+                      );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));
+      return;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));
+
+  //
+  // Execute pending TPM request.
+  //
+  Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, &PpiFlags);
+  DEBUG ((DEBUG_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));
+}
+
+/**
+  Check if the pending TPM request needs user input to confirm.
+
+  The TPM request may come from OS. This API will check if TPM request exists and need user
+  input to confirmation.
+
+  @retval    TRUE        TPM needs input to confirm user physical presence.
+  @retval    FALSE       TPM doesn't need input to confirm user physical presence.
+
+**/
+BOOLEAN
+EFIAPI
+Tcg2PhysicalPresenceLibNeedUserConfirm (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
+  UINTN                             DataSize;
+  BOOLEAN                           RequestConfirmed;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
+
+  // In AMD FCH, always do S4 for Shutdown.
+  // Todo: Chang to PCD method for this
+  //
+  // Check S4 resume
+  //
+  //  if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
+  //    DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n"));
+  //    return FALSE;
+  //  }
+
+  //
+  // Check Tpm requests
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &TcgPpData
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[TPM2] GetVariable %S, %r\n", TCG2_PHYSICAL_PRESENCE_VARIABLE, Status));
+    return FALSE;
+  }
+
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpiFlags
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[TPM2] GetVariable %S, %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
+    return FALSE;
+  }
+
+  if (TcgPpData.PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
+    //
+    // No operation request
+    //
+    return FALSE;
+  }
+
+  if (!Tcg2HaveValidTpmRequest (&TcgPpData, PpiFlags, &RequestConfirmed)) {
+    //
+    // Invalid operation request.
+    //
+    return FALSE;
+  }
+
+  if (!RequestConfirmed) {
+    //
+    // Need UI to confirm
+    //
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  The handler for TPM physical presence function:
+  Return TPM Operation Response to OS Environment.
+
+  @param[out]     MostRecentRequest Most recent operation request.
+  @param[out]     Response          Response to the most recent operation request.
+
+  @return Return Code for Return TPM Operation Response to OS Environment.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
+  OUT UINT32  *MostRecentRequest,
+  OUT UINT32  *Response
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       DataSize;
+  EFI_TCG2_PHYSICAL_PRESENCE  PpData;
+
+  DEBUG ((DEBUG_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
+
+  //
+  // Get the Physical Presence variable
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpData
+                    );
+  if (EFI_ERROR (Status)) {
+    *MostRecentRequest = 0;
+    *Response          = 0;
+    DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
+    return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
+  }
+
+  *MostRecentRequest = PpData.LastPPRequest;
+  *Response          = PpData.PPResponse;
+
+  return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
+}
+
+/**
+  The handler for TPM physical presence function:
+  Submit TPM Operation Request to Pre-OS Environment and
+  Submit TPM Operation Request to Pre-OS Environment 2.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]      OperationRequest TPM physical presence operation request.
+  @param[in]      RequestParameter TPM physical presence operation request parameter.
+
+  @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
+          Submit TPM Operation Request to Pre-OS Environment 2.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
+  IN UINT32  OperationRequest,
+  IN UINT32  RequestParameter
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             DataSize;
+  EFI_TCG2_PHYSICAL_PRESENCE        PpData;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
+
+  DEBUG ((DEBUG_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));
+
+  //
+  // Get the Physical Presence variable
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpData
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
+    return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
+  }
+
+  if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
+      (OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN))
+  {
+    return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
+  }
+
+  if ((PpData.PPRequest != OperationRequest) ||
+      (PpData.PPRequestParameter != RequestParameter))
+  {
+    PpData.PPRequest          = (UINT8)OperationRequest;
+    PpData.PPRequestParameter = RequestParameter;
+    DataSize                  = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+    Status                    = gRT->SetVariable (
+                                       TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                                       &gEfiTcg2PhysicalPresenceGuid,
+                                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                                       DataSize,
+                                       &PpData
+                                       );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
+      return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
+    }
+  }
+
+  if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+    Status   = gRT->GetVariable (
+                      TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                      &gEfiTcg2PhysicalPresenceGuid,
+                      NULL,
+                      &DataSize,
+                      &Flags
+                      );
+    if (EFI_ERROR (Status)) {
+      Flags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags);
+    }
+
+    return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter);
+  }
+
+  return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
+}
+
+/**
+  Return TPM2 ManagementFlags set by PP interface.
+
+  @retval    ManagementFlags    TPM2 Management Flags.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibGetManagementFlags (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
+  UINTN                             DataSize;
+
+  DEBUG ((DEBUG_INFO, "[TPM2] GetManagementFlags\n"));
+
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpiFlags
+                    );
+  if (EFI_ERROR (Status)) {
+    PpiFlags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags);
+  }
+
+  return PpiFlags.PPFlags;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
new file mode 100644
index 0000000000..2ce1133596
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
@@ -0,0 +1,68 @@
+## @file
+#  Executes TPM 2.0 requests from OS or BIOS
+#
+#  This library will check and execute TPM 2.0 request from OS or BIOS. The request may
+#  ask for user confirmation before execution.
+#
+#  Caution: This module requires additional review when modified.
+#  This driver will have external input - variable.
+#  This external input must be validated carefully to avoid security issue.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeTcg2PhysicalPresenceLib
+  MODULE_UNI_FILE                = DxeTcg2PhysicalPresenceLib.uni
+  FILE_GUID                      = 7E507A86-DE8B-4AD3-BC4C-0498389098D3
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tcg2PhysicalPresenceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  DxeTcg2PhysicalPresenceLib.c
+  PhysicalPresenceStrings.uni
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+  MemoryAllocationLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiRuntimeServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  PrintLib
+  HiiLib
+  HobLib
+  Tpm2CommandLib
+  Tcg2PpVendorLib
+
+[Protocols]
+  gEfiTcg2ProtocolGuid                 ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid       ## SOMETIMES_CONSUMES
+
+[Pcd]
+  gEfiSecurityPkgTokenSpaceGuid.PcdTcg2PhysicalPresenceFlags       ## SOMETIMES_CONSUMES
+
+[Guids]
+  ## SOMETIMES_CONSUMES ## HII
+  ## SOMETIMES_PRODUCES ## Variable:L"Tcg2PhysicalPresence"
+  ## SOMETIMES_CONSUMES ## Variable:L"Tcg2PhysicalPresence"
+  ## SOMETIMES_PRODUCES ## Variable:L"Tcg2PhysicalPresenceFlags"
+  ## SOMETIMES_CONSUMES ## Variable:L"Tcg2PhysicalPresenceFlags"
+  gEfiTcg2PhysicalPresenceGuid
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni
new file mode 100644
index 0000000000..d7e4af732b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Executes TPM 2.0 requests from OS or BIOS
+//
+// This library will check and execute TPM 2.0 request from OS or BIOS. The request may
+// ask for user confirmation before execution.
+//
+// Caution: This module requires additional review when modified.
+// This driver will have external input - variable.
+// This external input must be validated carefully to avoid security issue.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "Executes TPM 2.0 requests from OS or BIOS"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This library will check and execute TPM 2.0 request from OS or BIOS. The request may ask for user confirmation before execution.\n"
+                                                        "Caution: This module requires additional review when modified. This driver will have external input - variable. This external input must be validated carefully to avoid security issue."
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni
new file mode 100644
index 0000000000..70fa651455
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni
@@ -0,0 +1,57 @@
+// /** @file
+// String definitions for TPM 2.0 physical presence confirm text.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#langdef en-US "English"
+
+#string TPM_HEAD_STR                  #language en-US    "A configuration change was requested to %s this computer's TPM (Trusted Platform Module)\n\n"
+#string TPM_PPI_HEAD_STR              #language en-US    "A configuration change was requested to allow the Operating System to %s the computer's TPM (Trusted Platform Module) without asking for user confirmation in the future.\n\n"
+
+#string TPM_ACCEPT_KEY                #language en-US    "Press F10 "
+#string TPM_CAUTION_KEY               #language en-US    "Press F12 "
+#string TPM_REJECT_KEY                #language en-US    "to %s the TPM \nPress ESC to reject this change request and continue\n"
+
+#string TPM_ENABLE                    #language en-US    "enable"
+#string TPM_DISABLE                   #language en-US    "disable"
+#string TPM_CLEAR                     #language en-US    "clear"
+#string TPM_SET_PCR_BANKS                       #language en-US    "change the boot measurements to use PCR bank(s) of"
+#string TPM_CHANGE_EPS                          #language en-US    "clear and change identity of"
+#string TPM_DISABLE_ENDORSEMENT_ENABLE_STORAGE  #language en-US    "disable access to some secrets stored in"
+
+#string TPM_NO_PPI_MAINTAIN           #language en-US    "maintain"
+#string TPM_NO_PPI_TURN_ON            #language en-US    "turn on"
+#string TPM_NO_PPI_TURN_OFF           #language en-US    "turn off"
+#string TPM_NO_PPI_INFO               #language en-US    "to approve future Operating System requests "
+
+#string TPM_WARNING_DISABLE           #language en-US    "WARNING: Doing so might prevent security applications that rely on the TPM from functioning as expected.\n\n"
+#string TPM_WARNING_CLEAR             #language en-US    "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted by these keys. "
+#string TPM_NOTE_CLEAR                #language en-US    "NOTE: This action does not clear the TPM, but by approving this configuration change, future actions to clear the TPM will not require user confirmation.\n\n"
+#string TPM_WARNING_SET_PCR_BANKS_1                     #language en-US    "WARNING: Changing the PCR bank(s) of the boot measurements may prevent the Operating System from properly processing the measurements. Please check if your Operating System supports the new PCR bank(s).\n\n"
+#string TPM_WARNING_SET_PCR_BANKS_2                     #language en-US    "WARNING: Secrets in the TPM that are bound to the boot state of your machine may become unusable.\n\n"
+#string TPM_WARNING_CHANGE_EPS_1                        #language en-US    "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted with these keys.\n\n"
+#string TPM_WARNING_CHANGE_EPS_2                        #language en-US    "WARNING: Changing the identity of the TPM may require additional steps to establish trust into the new identity.\n\n"
+#string TPM_WARNING_PP_CHANGE_PCRS_FALSE                #language en-US    "WARNING: Allowing future changes to format of the boot measurement log may affect the Operating System.\n\n"
+#string TPM_WARNING_PP_CHANGE_EPS_FALSE_1               #language en-US    "WARNING: Allowing future changes to the TPM's firmware may affect the operation of the TPM and may erase information stored on the TPM.\n\n"
+#string TPM_WARNING_PP_CHANGE_EPS_FALSE_2               #language en-US    "You may lose all created keys and access to data encrypted by these keys.\n\n"
+#string TPM_WARNING_DISABLE_ENDORSEMENT_ENABLE_STORAGE  #language en-US    "WARNING: Doing so might prevent security applications that rely on the TPM from functioning as expected.\n\n"
+
+#string TCG_STORAGE_HEAD_STR                  #language en-US    "A configuration change was requested to %s on subsequent boots\n\n"
+#string TCG_STORAGE_PPI_HEAD_STR              #language en-US    "A configuration change was requested to allow the Operating System to %s without asking for user confirmation in the future.\n\n"
+
+#string TCG_STORAGE_ACCEPT_KEY                #language en-US    "Press F10 "
+#string TCG_STORAGE_CAUTION_KEY               #language en-US    "Press F12 "
+#string TCG_STORAGE_REJECT_KEY                #language en-US    "to %s\nPress ESC to reject this change request and continue\n"
+
+#string TCG_STORAGE_NO_PPI_INFO               #language en-US    "to approve future Operating System requests "
+
+#string TCG_STORAGE_ENABLE_BLOCK_SID          #language en-US    "issue a Block SID authentication command"
+#string TCG_STORAGE_DISABLE_BLOCK_SID         #language en-US    "disable issuing a Block SID authentication command"
+
+#string TCG_STORAGE_PP_ENABLE_BLOCK_SID       #language en-US    "enable blocking SID authentication"
+#string TCG_STORAGE_PP_DISABLE_BLOCK_SID      #language en-US    "disable blocking SID authentication"
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c
new file mode 100644
index 0000000000..62317165cb
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c
@@ -0,0 +1,854 @@
+/** @file
+  It updates fTPM2 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) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Tcg2Smm.h"
+
+TPM2_CONTROL_AREA  *mFtpmControlArea = NULL;
+
+EFI_TPM2_ACPI_TABLE  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;
+
+/**
+  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;
+      return EFI_SUCCESS;
+    }
+
+    if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
+      return EFI_SUCCESS;
+    }
+
+    MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;
+  }
+
+  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;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Find the operation region in TCG ACPI table by given Name and Size,
+  and initialize it if the region is found.
+
+  @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.
+
+  @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;
+}
+
+/**
+  Find the fTPM Control Area operation region in TCG ACPI table by given Name and Size,
+  and initialize it if the region is found.
+
+  @param[in, out] Table            The TPM item in ACPI table.
+  @param[in]      Name             The name string to find in TPM table.
+  @param[in]      ControlAreaAddr  The Control Area address to set.
+  @param[in]      ControlAreaSize  The Control Area size to size.
+
+  @return                          The allocated address for the found region.
+
+**/
+EFI_STATUS
+PatchTpmControlAreaOpRegion (
+  EFI_ACPI_DESCRIPTION_HEADER  *Table,
+  UINT32                       Name,
+  UINT32                       ControlAreaAddr,
+  UINT8                        ControlAreaSize
+  )
+{
+  EFI_STATUS          Status    = EFI_NOT_FOUND;
+  AML_OP_REGION_32_8  *OpRegion = NULL;
+
+  //
+  // 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))
+    {
+      OpRegion->RegionOffset = ControlAreaAddr;
+      OpRegion->RegionLen    = ControlAreaSize;
+      Status                 = EFI_SUCCESS;
+      break;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Patch the Memory32Fixed definitions in TCG ACPI table, and initialize their value for pre-defined signatures.
+
+  @param[in, out] Table          The TPM item in ACPI table.
+  @param[in]      CommandAddr    The Command Address to set for certain signature in Memory32Fixed.
+  @param[in]      ResponseAddr   The Response Address to set for certain signature in Memory32Fixed.
+
+  @return                        The allocated address for the found region.
+
+**/
+EFI_STATUS
+AssignMemory32Fixed (
+  EFI_ACPI_DESCRIPTION_HEADER  *Table,
+  UINT32                       CommandAddr,
+  UINT32                       ResponseAddr
+  )
+{
+  EFI_STATUS  Status              = EFI_NOT_FOUND;
+  UINT8       *TmpPtr             = NULL;
+  BOOLEAN     CommandAddrPatched  = FALSE;
+  BOOLEAN     ResponseAddrPatched = FALSE;
+
+  //
+  // Patch some pointers for the ASL code before loading the SSDT.
+  //
+  for (TmpPtr = (UINT8 *)Table; TmpPtr <= (UINT8 *)Table + Table->Length; ) {
+    if (*(UINT32 *)TmpPtr  == 0xA5A5A5A5) {
+      *(UINT32 *)TmpPtr  = CommandAddr;
+      CommandAddrPatched = TRUE;
+      TmpPtr             = TmpPtr + 4;
+    } else if (*(UINT32 *)TmpPtr  == 0xAAAAAAAA) {
+      *(UINT32 *)TmpPtr   = ResponseAddr;
+      ResponseAddrPatched = TRUE;
+      TmpPtr              = TmpPtr + 4;
+    } else if (CommandAddrPatched && ResponseAddrPatched) {
+      Status = EFI_SUCCESS;
+      break;
+    }
+
+    ++TmpPtr;
+  }
+
+  return Status;
+}
+
+/**
+  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 ((DEBUG_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 descirptor in ByteList need to be patched
+
+  @param[in, out] Table            The TPM item in ACPI table.
+  @param[in]      IrqBuffer        Input new IRQ buffer.
+  @param[in]      IrqBuffserSize   Input new IRQ buffer size.
+  @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 descirptor in ByteList
+  //
+  // =============  Buffer ====================
+  //           DefBuffer := BufferOp PkgLength BufferSize ByteList
+  //            BufferOp := 0x11
+  //
+  // ==============PkgLength==================
+  //          PkgLength := PkgLeadByte |
+  //                              <PkgLeadByte ByteData> |
+  //                              <PkgLeadByte ByteData ByteData> |
+  //                              <PkgLeadByte ByteData ByteData ByteData>
+  //
+  //       PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
+  //                               <bit 5-4: Only used if PkgLength <= 63 >
+  //                               <bit 3-0: Least significant package length nybble>
+  //
+  // ==============BufferSize==================
+  //        BufferSize := Integar
+  //           Integar := ByteConst|WordConst|DwordConst....
+  //
+  //           ByteConst := BytePrefix ByteData
+  //
+  // ==============ByteList===================
+  //          ByteList := ByteData ByteList
+  //
+  // =========================================
+
+  //
+  // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
+  //
+  for (DataPtr  = (UINT8 *)(Table + 1);
+       DataPtr < (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+       DataPtr += 1)
+  {
+    if (CompareMem (DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {
+      //
+      // Jump over object name & BufferOp
+      //
+      DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+      if ((*DataPtr & (BIT7|BIT6)) == 0) {
+        OrignalPkgLength = (UINT32)*DataPtr;
+        DataEndPtr       = DataPtr + OrignalPkgLength;
+
+        //
+        // Jump over PkgLength = PkgLeadByte only
+        //
+        NewPkgLength++;
+
+        //
+        // Jump over BufferSize
+        //
+        if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
+          NewPkgLength += 2;
+        } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
+          NewPkgLength += 3;
+        } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
+          NewPkgLength += 5;
+        } else {
+          ASSERT (FALSE);
+          return EFI_UNSUPPORTED;
+        }
+      } else {
+        ASSERT (FALSE);
+        return EFI_UNSUPPORTED;
+      }
+
+      //
+      // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
+      //
+      NewPkgLength += 19 + IrqBuffserSize;
+      if (NewPkgLength > 63) {
+        break;
+      }
+
+      if (NewPkgLength > OrignalPkgLength) {
+        ASSERT (FALSE);
+        return EFI_INVALID_PARAMETER;
+      }
+
+      //
+      // 1.1 Patch PkgLength
+      //
+      *DataPtr = (UINT8)NewPkgLength;
+
+      //
+      // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
+      //      It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
+      //
+      *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
+
+      //
+      // Notify _PRS to report short formed ResourceTemplate
+      //
+      *IsShortFormPkgLength = TRUE;
+
+      break;
+    }
+  }
+
+  //
+  // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
+  //
+  if (NewPkgLength > 63) {
+    NewPkgLength     = 0;
+    OrignalPkgLength = 0;
+    for (DataPtr  = (UINT8 *)(Table + 1);
+         DataPtr < (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+         DataPtr += 1)
+    {
+      if (CompareMem (DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {
+        //
+        // Jump over object name & BufferOp
+        //
+        DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+        if ((*DataPtr & (BIT7|BIT6)) != 0) {
+          OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);
+          DataEndPtr       = DataPtr + OrignalPkgLength;
+          //
+          // Jump over PkgLength = PkgLeadByte + ByteData length
+          //
+          NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
+
+          //
+          // Jump over BufferSize
+          //
+          if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
+            NewPkgLength += 2;
+          } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
+            NewPkgLength += 3;
+          } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
+            NewPkgLength += 5;
+          } else {
+            ASSERT (FALSE);
+            return EFI_UNSUPPORTED;
+          }
+        } else {
+          ASSERT (FALSE);
+          return EFI_UNSUPPORTED;
+        }
+
+        //
+        // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2  Bytes)
+        //
+        NewPkgLength += 19 + IrqBuffserSize;
+
+        if (NewPkgLength > OrignalPkgLength) {
+          ASSERT (FALSE);
+          return EFI_INVALID_PARAMETER;
+        }
+
+        //
+        // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
+        //
+        *DataPtr       = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
+        *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
+
+        //
+        // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
+        //     It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
+        //
+        *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);
+
+        //
+        // Notify _PRS to report 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 descirptor patch interrupt descriptor
+  //
+  *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);
+  //
+  //   3.2 Patch Interrupt Table Length
+  //
+  *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof (UINT32));
+  //
+  //   3.3 Copy patched InterruptNumBuffer
+  //
+  CopyMem (DataPtr + 5, IrqBuffer, IrqBuffserSize);
+
+  //
+  // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field to 0
+  //
+  DataPtr       += 5 + IrqBuffserSize;
+  *DataPtr       = ACPI_END_TAG_DESCRIPTOR;
+  *(DataPtr + 1) = 0;
+
+  //
+  // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
+  //
+  DataPtr += 2;
+  if (DataPtr < DataEndPtr) {
+    SetMem (DataPtr, (UINTN)DataEndPtr - (UINTN)DataPtr, AML_NOOP_OP);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  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);
+
+  //
+  // 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)
+    ));
+
+  //
+
+  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
+        ));
+    }
+  }
+
+  //
+  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
+  //
+  TpmMeasureAndLogData (
+    0,
+    EV_POST_CODE,
+    EV_POSTCODE_INFO_ACPI_DATA,
+    ACPI_DATA_LEN,
+    Table,
+    TableSize
+    );
+
+  ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
+  CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId));
+
+  DEBUG ((DEBUG_INFO, "FtpmControlArea: 0x%lX\n", (UINTN)(VOID *)mFtpmControlArea));
+  DEBUG ((DEBUG_INFO, "CommandSize: 0x%lX, ResponseSize: 0x%lX \n", mFtpmControlArea->CommandSize, mFtpmControlArea->ResponseSize));
+
+  Status = AssignMemory32Fixed (Table, (UINT32)mFtpmControlArea->CommandAddress, (UINT32)mFtpmControlArea->ResponseAddress);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PatchTpmControlAreaOpRegion (Table, SIGNATURE_32 ('T', 'P', 'M', 'C'), (UINT32)(UINTN)(VOID *)mFtpmControlArea + 0x10, sizeof (EFI_TPM2_ACPI_CONTROL_AREA));
+  ASSERT_EFI_ERROR (Status);
+
+  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-checksumed.
+  //
+  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.
+
+**/
+EFI_STATUS
+PublishTpm2 (
+  VOID
+  )
+{
+  EFI_STATUS               Status;
+  EFI_ACPI_TABLE_PROTOCOL  *AcpiTable;
+  UINTN                    TableKey;
+  UINT64                   OemTableId;
+
+  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)));
+  }
+
+  //
+  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
+  //
+  TpmMeasureAndLogData (
+    0,
+    EV_POST_CODE,
+    EV_POSTCODE_INFO_ACPI_DATA,
+    ACPI_DATA_LEN,
+    &mTpm2AcpiTemplate,
+    sizeof (mTpm2AcpiTemplate)
+    );
+
+  mTpm2AcpiTemplate.StartMethod          = EFI_TPM2_ACPI_TABLE_START_METHOD_ACPI;
+  mTpm2AcpiTemplate.AddressOfControlArea = ((UINT64)(UINTN)(VOID *)mFtpmControlArea + 0x10);
+
+  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,
+                        sizeof (mTpm2AcpiTemplate),
+                        &TableKey
+                        );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  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
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;
+  EFI_SMM_SW_REGISTER_CONTEXT    SwContext;
+  EFI_HANDLE                     SwHandle;
+
+  DEBUG ((DEBUG_INFO, "InitializeTcgSmm Entry \n"));
+  if (!CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)) {
+    DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  // if (!GetFtpmControlArea(&mFtpmControlArea)) {
+  //   DEBUG ((DEBUG_ERROR, "Get fTPM Control Area failed!\n"));
+  //   return EFI_UNSUPPORTED;
+  // }
+  mFtpmControlArea = (VOID *)(UINTN)PcdGet64 (PcdTpmBaseAddress);
+  DEBUG ((DEBUG_INFO, "Get PcdTpmBaseAddress:%x\n", mFtpmControlArea));
+  Status = PublishAcpiTable ();
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Get the Sw dispatch protocol and register SMI callback functions.
+  //
+  Status = gSmst->SmmLocateProtocol (&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;
+  DEBUG ((DEBUG_INFO, "PhysicalPresence SoftwareSmi: 0x%X\n", (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;
+  DEBUG ((DEBUG_INFO, "MemoryClear SoftwareSmi: 0x%X\n", (UINT8)SwContext.SwSmiInputValue));
+
+  //
+  // Locate SmmVariableProtocol.
+  //
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Set TPM2 ACPI table
+  //
+  Status = PublishTpm2 ();
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h
new file mode 100644
index 0000000000..0e9b367c80
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h
@@ -0,0 +1,123 @@
+/** @file
+  The header file for Tcg2 SMM driver.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+  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 <Guid/MemoryOverwriteControl.h>
+#include <Guid/TpmInstance.h>
+
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SmmVariable.h>
+#include <Protocol/Tcg2Protocol.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.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/AmdPspCommonLib.h>
+#include <Library/AmdPspFtpmLib.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
+//
+#define ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE  1
+#define ACPI_FUNCTION_PTS_CLEAR_MOR_BIT           2
+
+//
+// The return code for Memory Clear Interface Functions
+//
+#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)
+#endif // TCG_SMM_H_
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf
new file mode 100644
index 0000000000..52419f55ea
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf
@@ -0,0 +1,92 @@
+## @file
+#  Provides ACPI methods for fTPM 2.0 support
+#
+#  Spec Compliance Info:
+#     "TCG ACPI Specification Level 00 Revision 00.37"
+#     "Physical Presence Interface Specification Version 1.30 Revision 00.52"
+#     "Platform Reset Attack Mitigation Specification Version 1.00"
+#    TPM2.0 ACPI device object
+#     "TCG PC Client Platform Firmware Profile Specification for TPM Family 2.0 Level 00 Revision 00.21"
+#
+#  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.
+#
+#  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.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tcg2Smm
+  MODULE_UNI_FILE                = Tcg2Smm.uni
+  FILE_GUID                      = 44A20657-10B8-4049-A148-ACD8812AF257
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeTcgSmm
+
+[Sources]
+  Tcg2Smm.h
+  Tcg2Smm.c
+  Tpm.asl
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  UefiDriverEntryPoint
+  SmmServicesTableLib
+  UefiBootServicesTableLib
+  DebugLib
+  DxeServicesLib
+  TpmMeasurementLib
+  Tcg2PhysicalPresenceLib
+  PcdLib
+  # AmdPspCommonLib
+
+[Guids]
+  ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"
+  ## SOMETIMES_CONSUMES ## Variable:L"MemoryOverwriteRequestControl"
+  gEfiMemoryOverwriteControlDataGuid
+  gEfiTpmDeviceInstanceTpm20DtpmGuid                            ## CONSUMES           ## GUID       # TPM device identifier
+
+[Protocols]
+  gEfiSmmSwDispatch2ProtocolGuid                                ## CONSUMES
+  gEfiSmmVariableProtocolGuid                                   ## CONSUMES
+  gEfiAcpiTableProtocolGuid                                     ## 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.PcdTcgPhysicalPresenceInterfaceVer  ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev                 ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass                 ## SOMETIMES_CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2CurrentIrqNum            ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf        ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress
+
+[Depex]
+  gEfiAcpiTableProtocolGuid AND
+  gEfiSmmSwDispatch2ProtocolGuid AND
+  gEfiSmmVariableProtocolGuid AND
+  gEfiTcg2ProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  Tcg2SmmExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
new file mode 100644
index 0000000000..d2cf9159c6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
@@ -0,0 +1,19 @@
+// /** @file
+// Provides ACPI metholds for fTPM 2.0 support
+//
+// 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.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "Provides ACPI metholds for TPM 2.0 support"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "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.\n"
+                                                        "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 issues."
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni
new file mode 100644
index 0000000000..b85ec10eba
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Tcg2Smm Localized Strings and Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"TCG2 (Trusted Computing Group) SMM"
+
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
new file mode 100644
index 0000000000..a11ce43f85
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
@@ -0,0 +1,397 @@
+/** @file
+  The TPM2 definition block in ACPI table for TCG2 physical presence
+  and MemoryClear.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+(c)Copyright 2016 HP Development Company, L.P.<BR>
+Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock (
+  "Tpm.aml",
+  "SSDT",
+  2,
+  "AMD   ",
+  "Tpm2Tabl",
+  0x1000
+  )
+{
+  Scope (\_SB)
+  {
+    Device (TPM)
+    {
+      //
+      // TCG2
+      //
+
+      //
+      //  TAG for patching TPM2.0 _HID
+      //
+      Name (_HID, "MSFT0101")
+
+      Name (_CID, "MSFT0101")
+
+      //
+      // Readable name of this device, don't know if this way is correct yet
+      //
+      Name (_STR, Unicode ("TPM 2.0 Device"))
+
+      //
+      // Return the resource consumed by TPM device
+      //
+      Name (_CRS, ResourceTemplate () {
+        Memory32Fixed (ReadWrite, 0xA5A5A5A5, 0x4000)  // Command Address
+        Memory32Fixed (ReadWrite, 0xAAAAAAAA, 0x4000)  // Response Address
+      })
+
+      //
+      // Operational region for Smi port access, FixedPcdGet16 (PcdAmdFchCfgSmiCmdPortAddr)
+      //
+      OperationRegion (SMIP, SystemIO, 0xB0, 1)
+      Field (SMIP, ByteAcc, NoLock, Preserve)
+      {
+          IOB0, 8
+      }
+
+      //
+      // Operational region for fTPM control area.
+      // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code.
+      //
+      OperationRegion (TPMC, SystemMemory, 0xFFFF0000, 0xF0)
+      Field (TPMC, DWordAcc, NoLock, Preserve)
+      {
+        REQS,   32,
+        STAS,   32,
+        CANC,   32,
+        STAR,   32,
+                AccessAs (QWordAcc, 0),
+        INTC,   64,
+                AccessAs (DWordAcc, 0),
+        CMDS,   32,
+                AccessAs (QWordAcc, 0),
+        CMDA,   64,
+                AccessAs (DWordAcc, 0),
+        RSPS,   32,
+                AccessAs (QWordAcc, 0),
+        RSPA,   64
+      }
+
+      //
+      // Operational region for TPM support, TPM Physical Presence and TPM Memory Clear
+      // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code.
+      //
+      OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0xF0)
+      Field (TNVS, AnyAcc, NoLock, Preserve)
+      {
+        PPIN,   8,  //   Software SMI for Physical Presence Interface
+        PPIP,   32, //   Used for save physical presence paramter
+        PPRP,   32, //   Physical Presence request operation response
+        PPRQ,   32, //   Physical Presence request operation
+        PPRM,   32, //   Physical Presence request operation parameter
+        LPPR,   32, //   Last Physical Presence request operation
+        FRET,   32, //   Physical Presence function return code
+        MCIN,   8,  //   Software SMI for Memory Clear Interface
+        MCIP,   32, //   Used for save the Mor paramter
+        MORD,   32, //   Memory Overwrite Request Data
+        MRET,   32, //   Memory Overwrite function return code
+        UCRQ,   32  //   Phyical Presence request operation to Get User Confirmation Status
+      }
+
+      Method (PTS, 1, Serialized)
+      {
+        //
+        // Detect Sx state for MOR, only S4, S5 need to handle
+        //
+        If (LAnd (LLess (Arg0, 6), LGreater (Arg0, 3)))
+        {
+          //
+          // Bit4 -- DisableAutoDetect. 0 -- Firmware MAY autodetect.
+          //
+          If (LNot (And (MORD, 0x10)))
+          {
+            //
+            // Trigger the SMI through ACPI _PTS method.
+            //
+            Store (0x02, MCIP)
+
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (MCIN, IOB0)
+          }
+        }
+        Return (0)
+      }
+
+      Method (_STA, 0)
+      {
+        Return (0x0f)
+      }
+
+      //
+      // TCG Hardware Information
+      //
+      Method (HINF, 3, Serialized, 0, {BuffObj, PkgObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger(Arg1))
+        {
+          Case (0)
+          {
+            //
+            // Standard query
+            //
+            Return (Buffer () {0x03})
+          }
+          Case (1)
+          {
+            //
+            // Return failure if no TPM present
+            //
+            Name(TPMV, Package () {0x01, Package () {0x2, 0x0}})
+            if (LEqual (_STA (), 0x00))
+            {
+              Return (Package () {0x00})
+            }
+
+            //
+            // Return TPM version
+            //
+            Return (TPMV)
+          }
+          Default {BreakPoint}
+        }
+        Return (Buffer () {0})
+      }
+
+      Name(TPM2, Package (0x02){
+        Zero,
+        Zero
+      })
+
+      Name(TPM3, Package (0x03){
+        Zero,
+        Zero,
+        Zero
+      })
+
+      //
+      // TCG Physical Presence Interface
+      //
+      Method (TPPI, 3, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger(Arg1))
+        {
+          Case (0)
+          {
+            //
+            // Standard query, supports function 1-8
+            //
+            Return (Buffer () {0xFF, 0x01})
+          }
+          Case (1)
+          {
+            //
+            // a) Get Physical Presence Interface Version
+            //
+            Return ("$PV")
+          }
+          Case (2)
+          {
+            //
+            // b) Submit TPM Operation Request to Pre-OS Environment
+            //
+            Store (DerefOf (Index (Arg2, 0x00)), PPRQ)
+            Store (0, PPRM)
+            Store (0x02, PPIP)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Return (FRET)
+
+
+          }
+          Case (3)
+          {
+            //
+            // c) Get Pending TPM Operation Requested By the OS
+            //
+            Store (PPRQ, Index (TPM2, 0x01))
+            Return (TPM2)
+          }
+          Case (4)
+          {
+            //
+            // d) Get Platform-Specific Action to Transition to Pre-OS Environment
+            //
+            Return (2)
+          }
+          Case (5)
+          {
+            //
+            // e) Return TPM Operation Response to OS Environment
+            //
+            Store (0x05, PPIP)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Store (LPPR, Index (TPM3, 0x01))
+            Store (PPRP, Index (TPM3, 0x02))
+
+            Return (TPM3)
+          }
+          Case (6)
+          {
+
+            //
+            // f) Submit preferred user language (Not implemented)
+            //
+
+            Return (3)
+
+          }
+          Case (7)
+          {
+            //
+            // g) Submit TPM Operation Request to Pre-OS Environment 2
+            //
+            Store (7, PPIP)
+            Store (DerefOf (Index (Arg2, 0x00)), PPRQ)
+            Store (0, PPRM)
+            If (LEqual (PPRQ, 23)) {
+              Store (DerefOf (Index (Arg2, 0x01)), PPRM)
+            }
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Return (FRET)
+          }
+          Case (8)
+          {
+            //
+            // e) Get User Confirmation Status for Operation
+            //
+            Store (8, PPIP)
+            Store (DerefOf (Index (Arg2, 0x00)), UCRQ)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Return (FRET)
+          }
+
+          Default {BreakPoint}
+        }
+        Return (1)
+      }
+
+      Method (TMCI, 3, Serialized, 0, IntObj, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger (Arg1))
+        {
+          Case (0)
+          {
+            //
+            // Standard query, supports function 1-1
+            //
+            Return (Buffer () {0x03})
+          }
+          Case (1)
+          {
+            //
+            // Save the Operation Value of the Request to MORD (reserved memory)
+            //
+            Store (DerefOf (Index (Arg2, 0x00)), MORD)
+            //
+            // Trigger the SMI through ACPI _DSM method.
+            //
+            Store (0x01, MCIP)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (MCIN, IOB0)
+            Return (MRET)
+          }
+          Default {BreakPoint}
+        }
+        Return (1)
+      }
+
+      // ACPI Start Method to permit the OS to request the firmware to execute or cancel a TPM 2.0 command.
+      Method (TPMS, 3, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj, UnknownObj})
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger(Arg1)) {
+
+        Case (0) {
+          //
+          // Standard query, supports function 1
+          //
+          Return (Buffer () {0x03})
+        }
+
+        Case (1) {
+          //
+          // Start
+          //
+          Return (0)
+        }
+
+        Default {BreakPoint}
+        }
+        Return (1)
+      }
+
+      Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj})
+      {
+        //
+        // TCG Hardware Information
+        //
+        If(LEqual(Arg0, ToUUID ("cf8e16a5-c1e8-4e25-b712-4f54a96702c8")))
+        {
+          Return (HINF (Arg1, Arg2, Arg3))
+        }
+        //
+        // TCG Physical Presence Interface
+        //
+        If(LEqual(Arg0, ToUUID ("3dddfaa6-361b-4eb4-a424-8d10089d1653")))
+        {
+          Return (TPPI (Arg1, Arg2, Arg3))
+        }
+        //
+        // TCG Memory Clear Interface
+        //
+        If(LEqual(Arg0, ToUUID ("376054ed-cc13-4675-901c-4756d7f2d45d")))
+        {
+          Return (TMCI (Arg1, Arg2, Arg3))
+        }
+        //
+        // ACPI Start Method
+        //
+        If(LEqual (Arg0, ToUUID ("6bbf6cab-5463-4714-b7cd-f0203c0368d4")))
+        {
+          Return (TPMS (Arg1, Arg2, Arg3))
+        }
+
+        Return (Buffer () {0})
+      }
+    }
+  }
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
new file mode 100644
index 0000000000..8833c40f74
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
@@ -0,0 +1,124 @@
+/** @file
+  Header file for NV data structure definition.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TCG2_CONFIG_NV_DATA_H_
+#define TCG2_CONFIG_NV_DATA_H_
+
+#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/Tcg2ConfigHii.h>
+#include <IndustryStandard/TcgPhysicalPresence.h>
+
+//
+// BUGBUG: In order to pass VfrCompiler, we have to redefine below MACRO, which already in <Protocol/Tcg2Protocol.h>.
+//
+#ifndef TCG2_H_
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2  0x00000001
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2    0x00000002
+#endif
+#define EFI_TCG2_EVENT_LOG_FORMAT_ALL  (EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
+
+#define TCG2_CONFIGURATION_VARSTORE_ID       0x0001
+#define TCG2_CONFIGURATION_INFO_VARSTORE_ID  0x0002
+#define TCG2_VERSION_VARSTORE_ID             0x0003
+#define TCG2_CONFIGURATION_FORM_ID           0x0001
+
+#define KEY_TPM_DEVICE                0x2000
+#define KEY_TPM2_OPERATION            0x2001
+#define KEY_TPM2_OPERATION_PARAMETER  0x2002
+#define KEY_TPM2_PCR_BANKS_REQUEST_0  0x2003
+#define KEY_TPM2_PCR_BANKS_REQUEST_1  0x2004
+#define KEY_TPM2_PCR_BANKS_REQUEST_2  0x2005
+#define KEY_TPM2_PCR_BANKS_REQUEST_3  0x2006
+#define KEY_TPM2_PCR_BANKS_REQUEST_4  0x2007
+#define KEY_TPM_DEVICE_INTERFACE      0x2008
+#define KEY_TCG2_PPI_VERSION          0x2009
+#define KEY_TPM2_ACPI_REVISION        0x200A
+
+#define TPM_DEVICE_NULL      0
+#define TPM_DEVICE_1_2       1
+#define TPM_DEVICE_2_0_DTPM  2
+#define TPM_DEVICE_MIN       TPM_DEVICE_1_2
+#define TPM_DEVICE_MAX       TPM_DEVICE_2_0_DTPM
+#define TPM_DEVICE_DEFAULT   TPM_DEVICE_2_0_DTPM
+
+#define TPM2_ACPI_REVISION_3  3
+#define TPM2_ACPI_REVISION_4  4
+
+#define TPM_DEVICE_INTERFACE_TIS       0
+#define TPM_DEVICE_INTERFACE_PTP_FIFO  1
+#define TPM_DEVICE_INTERFACE_PTP_CRB   2
+#define TPM_DEVICE_INTERFACE_MAX       TPM_DEVICE_INTERFACE_PTP_FIFO
+#define TPM_DEVICE_INTERFACE_DEFAULT   TPM_DEVICE_INTERFACE_PTP_CRB
+
+#define TCG2_PROTOCOL_VERSION_DEFAULT      0x0001
+#define EFI_TCG2_EVENT_LOG_FORMAT_DEFAULT  EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
+
+#define TCG2_PPI_VERSION_1_2  0x322E31                    // "1.2"
+#define TCG2_PPI_VERSION_1_3  0x332E31                    // "1.3"
+
+//
+// Nv Data structure referenced by IFR, TPM device user desired
+//
+typedef struct {
+  UINT8    TpmDevice;
+} TCG2_CONFIGURATION;
+
+typedef struct {
+  UINT64    PpiVersion;
+  UINT8     Tpm2AcpiTableRev;
+} TCG2_VERSION;
+
+typedef struct {
+  BOOLEAN    Sha1Supported;
+  BOOLEAN    Sha256Supported;
+  BOOLEAN    Sha384Supported;
+  BOOLEAN    Sha512Supported;
+  BOOLEAN    Sm3Supported;
+  UINT8      TpmDeviceInterfaceAttempt;
+  BOOLEAN    TpmDeviceInterfacePtpFifoSupported;
+  BOOLEAN    TpmDeviceInterfacePtpCrbSupported;
+} TCG2_CONFIGURATION_INFO;
+
+//
+// Variable saved for S3, TPM detected, only valid in S3 path.
+// This variable is ReadOnly.
+//
+typedef struct {
+  UINT8    TpmDeviceDetected;
+} TCG2_DEVICE_DETECTION;
+
+#define TCG2_STORAGE_NAME           L"TCG2_CONFIGURATION"
+#define TCG2_STORAGE_INFO_NAME      L"TCG2_CONFIGURATION_INFO"
+#define TCG2_DEVICE_DETECTION_NAME  L"TCG2_DEVICE_DETECTION"
+#define TCG2_VERSION_NAME           L"TCG2_VERSION"
+
+#define TPM_INSTANCE_ID_LIST  { \
+  {TPM_DEVICE_INTERFACE_NONE,           TPM_DEVICE_NULL},      \
+  {TPM_DEVICE_INTERFACE_TPM12,          TPM_DEVICE_1_2},       \
+  {TPM_DEVICE_INTERFACE_TPM20_DTPM,     TPM_DEVICE_2_0_DTPM},  \
+}
+
+//
+// BUGBUG: In order to pass VfrCompiler, we have to redefine GUID here.
+//
+#ifndef __BASE_H__
+typedef struct {
+  UINT32    Data1;
+  UINT16    Data2;
+  UINT16    Data3;
+  UINT8     Data4[8];
+} GUID;
+#endif
+
+typedef struct {
+  GUID     TpmInstanceGuid;
+  UINT8    TpmDevice;
+} TPM_INSTANCE_ID;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
new file mode 100644
index 0000000000..e1530fb874
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
@@ -0,0 +1,77 @@
+## @file
+#  Set TPM device type
+#
+#  This module initializes TPM device type based on variable and detection.
+#  NOTE: This module is only for reference only, each platform should have its own setup page.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tcg2ConfigPei
+  MODULE_UNI_FILE                = Tcg2ConfigPei.uni
+  FILE_GUID                      = EADD5061-93EF-4CCC-8450-F78A7F0820F0
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = Tcg2ConfigPeimEntryPoint
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+# [BootMode]
+#   S3_RESUME                 ## SOMETIMES_CONSUMES
+#
+
+[Sources]
+  Tcg2ConfigPeim.c
+  Tcg2ConfigNvData.h
+  TpmDetection.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  PeiServicesLib
+  PeimEntryPoint
+  DebugLib
+  PcdLib
+  Tpm2CommandLib
+  Tpm2DeviceLib
+  IoLib
+  PciExpressLib
+
+[Guids]
+  ## SOMETIMES_CONSUMES ## Variable:L"TCG2_CONFIGURATION"
+  ## SOMETIMES_CONSUMES ## Variable:L"TCG2_DEVICE_DETECTION"
+  gTcg2ConfigFormSetGuid
+  gEfiTpmDeviceSelectedGuid           ## PRODUCES             ## GUID    # Used as a PPI GUID
+  gEfiTpmDeviceInstanceNoneGuid       ## SOMETIMES_CONSUMES   ## GUID    # TPM device identifier
+
+[Ppis]
+  gEfiPeiReadOnlyVariable2PpiGuid     ## CONSUMES
+  gPeiTpmInitializationDonePpiGuid    ## SOMETIMES_PRODUCES
+
+[Pcd]
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid                 ## PRODUCES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy         ## PRODUCES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmAutoDetection                ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress                  ## SOMETIMES_CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdSpiDtpmEnabled
+
+[Depex]
+  gEfiPeiMemoryDiscoveredPpiGuid AND
+  gEfiPeiMasterBootModePpiGuid AND
+  gEfiPeiReadOnlyVariable2PpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  Tcg2ConfigPeiExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni
new file mode 100644
index 0000000000..4d1e7ae6ac
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni
@@ -0,0 +1,14 @@
+// /** @file
+// Set TPM device type
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#string STR_MODULE_ABSTRACT             #language en-US "Set TPM device type"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module initializes TPM device type based on variable and detection.\n"
+                                                        "NOTE: This module is only for reference only, each platform should have its own setup page."
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni
new file mode 100644
index 0000000000..0e79ee614a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Tcg2ConfigDxe Localized Strings and Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"TCG2 (Trusted Computing Group) Configuration DXE"
+
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
new file mode 100644
index 0000000000..9d90581388
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
@@ -0,0 +1,148 @@
+/** @file
+  The module entry point for Tcg2 configuration module.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Guid/TpmInstance.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/TpmInitialized.h>
+#include <Protocol/Tcg2Protocol.h>
+#include "Tcg2ConfigNvData.h"
+
+TPM_INSTANCE_ID  mTpmInstanceId[] = TPM_INSTANCE_ID_LIST;
+
+CONST EFI_PEI_PPI_DESCRIPTOR  gTpmSelectedPpi = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiTpmDeviceSelectedGuid,
+  NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mTpmInitializationDonePpiList = {
+  EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gPeiTpmInitializationDonePpiGuid,
+  NULL
+};
+
+/**
+  This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.
+
+  @param  SetupTpmDevice  TpmDevice configuration in setup driver
+
+  @return TpmDevice configuration
+**/
+UINT8
+DetectTpmDevice (
+  IN UINT8  SetupTpmDevice
+  );
+
+/**
+  The entry point for Tcg2 configuration driver.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCES             Convert variable to PCD successfully.
+  @retval Others                 Fail to convert variable to PCD.
+**/
+EFI_STATUS
+EFIAPI
+Tcg2ConfigPeimEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  UINTN                            Size;
+  EFI_STATUS                       Status;
+  EFI_STATUS                       Status2;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *VariablePpi;
+  TCG2_CONFIGURATION               Tcg2Configuration;
+  UINTN                            Index;
+  UINT8                            TpmDevice;
+
+  Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&VariablePpi);
+  ASSERT_EFI_ERROR (Status);
+
+  Size   = sizeof (Tcg2Configuration);
+  Status = VariablePpi->GetVariable (
+                          VariablePpi,
+                          TCG2_STORAGE_NAME,
+                          &gTcg2ConfigFormSetGuid,
+                          NULL,
+                          &Size,
+                          &Tcg2Configuration
+                          );
+  if (EFI_ERROR (Status)) {
+    //
+    // Variable not ready, set default value
+    //
+    Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT;
+  }
+
+  //
+  // Validation
+  //
+  if ((Tcg2Configuration.TpmDevice > TPM_DEVICE_MAX) || (Tcg2Configuration.TpmDevice < TPM_DEVICE_MIN)) {
+    Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT;
+  }
+
+  //
+  // Although we have SetupVariable info, we still need detect TPM device manually.
+  //
+  DEBUG ((DEBUG_INFO, "Tcg2Configuration.TpmDevice from Setup: %x\n", Tcg2Configuration.TpmDevice));
+
+  if (PcdGetBool (PcdTpmAutoDetection)) {
+    TpmDevice = DetectTpmDevice (Tcg2Configuration.TpmDevice);
+    DEBUG ((DEBUG_INFO, "TpmDevice final: %x\n", TpmDevice));
+    if (TpmDevice != TPM_DEVICE_NULL) {
+      Tcg2Configuration.TpmDevice = TpmDevice;
+    }
+  } else {
+    TpmDevice = Tcg2Configuration.TpmDevice;
+  }
+
+  //
+  // Convert variable to PCD.
+  // This is work-around because there is no gurantee DynamicHiiPcd can return correct value in DXE phase.
+  // Using DynamicPcd instead.
+  //
+  // NOTE: Tcg2Configuration variable contains the desired TpmDevice type,
+  // while PcdTpmInstanceGuid PCD contains the real detected TpmDevice type
+  //
+  for (Index = 0; Index < sizeof (mTpmInstanceId)/sizeof (mTpmInstanceId[0]); Index++) {
+    if (TpmDevice == mTpmInstanceId[Index].TpmDevice) {
+      Size   = sizeof (mTpmInstanceId[Index].TpmInstanceGuid);
+      Status = PcdSetPtrS (PcdTpmInstanceGuid, &Size, &mTpmInstanceId[Index].TpmInstanceGuid);
+      ASSERT_EFI_ERROR (Status);
+      DEBUG ((DEBUG_INFO, "TpmDevice PCD: %g\n", &mTpmInstanceId[Index].TpmInstanceGuid));
+      break;
+    }
+  }
+
+  //
+  // Selection done
+  //
+  Status = PeiServicesInstallPpi (&gTpmSelectedPpi);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Even if no TPM is selected or detected, we still need intall TpmInitializationDonePpi.
+  // Because TcgPei or Tcg2Pei will not run, but we still need a way to notify other driver.
+  // Other driver can know TPM initialization state by TpmInitializedPpi.
+  //
+  if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid)) {
+    Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
+    ASSERT_EFI_ERROR (Status2);
+  }
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c
new file mode 100644
index 0000000000..4a31738b13
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c
@@ -0,0 +1,99 @@
+/** @file
+  fTPM2.0/dTPM2.0 auto detection.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <IndustryStandard/Tpm20.h>
+#include "Tcg2ConfigNvData.h"
+
+EFI_STATUS
+InitDtpmInterface (
+  IN  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.
+
+  @param  SetupTpmDevice  TpmDevice configuration in setup driver
+
+  @return TpmDevice configuration
+**/
+UINT8
+DetectTpmDevice (
+  IN UINT8  SetupTpmDevice
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_BOOT_MODE                    BootMode;
+  TCG2_DEVICE_DETECTION            Tcg2DeviceDetection;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *VariablePpi;
+  UINTN                            Size;
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // In S3, we rely on normal boot Detection, because we save to ReadOnly Variable in normal boot.
+  //
+  if (BootMode == BOOT_ON_S3_RESUME) {
+    DEBUG ((DEBUG_INFO, "DetectTpmDevice: S3 mode\n"));
+
+    Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&VariablePpi);
+    ASSERT_EFI_ERROR (Status);
+
+    Size = sizeof (TCG2_DEVICE_DETECTION);
+    ZeroMem (&Tcg2DeviceDetection, sizeof (Tcg2DeviceDetection));
+    Status = VariablePpi->GetVariable (
+                            VariablePpi,
+                            TCG2_DEVICE_DETECTION_NAME,
+                            &gTcg2ConfigFormSetGuid,
+                            NULL,
+                            &Size,
+                            &Tcg2DeviceDetection
+                            );
+    if (!EFI_ERROR (Status) &&
+        (Tcg2DeviceDetection.TpmDeviceDetected >= TPM_DEVICE_MIN) &&
+        (Tcg2DeviceDetection.TpmDeviceDetected <= TPM_DEVICE_MAX))
+    {
+      DEBUG ((DEBUG_INFO, "TpmDevice from DeviceDetection: %x\n", Tcg2DeviceDetection.TpmDeviceDetected));
+      Status = Tpm2Startup (TPM_SU_STATE);
+      return Tcg2DeviceDetection.TpmDeviceDetected;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "DetectTpmDevice:\n"));
+
+  Status = Tpm2RequestUseTpm ();
+  if (EFI_ERROR (Status)) {
+    //
+    // TPM 2.0 not available
+    //
+    return TPM_DEVICE_NULL;
+  }
+
+  Status = Tpm2Startup (TPM_SU_CLEAR);
+  DEBUG ((DEBUG_INFO, "Tpm2Startup: %r\n", Status));
+  if (EFI_ERROR (Status)) {
+    return TPM_DEVICE_NULL;
+  }
+
+  return TPM_DEVICE_2_0_DTPM;
+}
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114596): https://edk2.groups.io/g/devel/message/114596
Mute This Topic: https://groups.io/mt/103975473/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-