]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
Add TPM2 support defined in trusted computing group.
[mirror_edk2.git] / SecurityPkg / Library / DxeTcg2PhysicalPresenceLib / DxeTcg2PhysicalPresenceLib.c
diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
new file mode 100644 (file)
index 0000000..46fc616
--- /dev/null
@@ -0,0 +1,1245 @@
+/** @file\r
+  Execute pending TPM2 requests from OS or BIOS.\r
+\r
+  Caution: This module requires additional review when modified.\r
+  This driver will have external input - variable.\r
+  This external input must be validated carefully to avoid security issue.\r
+\r
+  Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation.\r
+\r
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Tcg2Protocol.h>\r
+#include <Protocol/VariableLock.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/Tcg2PhysicalPresenceData.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tcg2PhysicalPresenceLib.h>\r
+#include <Library/Tcg2PpVendorLib.h>\r
+\r
+#define CONFIRM_BUFFER_SIZE         4096\r
+\r
+EFI_HII_HANDLE mTcg2PpStringPackHandle;\r
+\r
+/**\r
+  Get string by string id from HII Interface.\r
+\r
+  @param[in] Id          String ID.\r
+\r
+  @retval    CHAR16 *    String from ID.\r
+  @retval    NULL        If error occurs.\r
+\r
+**/\r
+CHAR16 *\r
+Tcg2PhysicalPresenceGetStringById (\r
+  IN  EFI_STRING_ID   Id\r
+  )\r
+{\r
+  return HiiGetString (mTcg2PpStringPackHandle, Id, NULL);\r
+}\r
+\r
+/**\r
+  Send ClearControl and Clear command to TPM.\r
+\r
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_TIMEOUT           The register can't run into the expected status in time.\r
+  @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.\r
+  @retval EFI_DEVICE_ERROR      Unexpected device behavior.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2CommandClear (\r
+  IN TPM2B_AUTH                *PlatformAuth  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPMS_AUTH_COMMAND         *AuthSession;\r
+  TPMS_AUTH_COMMAND         LocalAuthSession;\r
+\r
+  if (PlatformAuth == NULL) {\r
+    AuthSession = NULL;\r
+  } else {\r
+    AuthSession = &LocalAuthSession;\r
+    ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));\r
+    LocalAuthSession.sessionHandle = TPM_RS_PW;\r
+    LocalAuthSession.hmac.size = PlatformAuth->size;\r
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "Tpm2ClearControl ... \n"));\r
+  Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);\r
+  DEBUG ((EFI_D_INFO, "Tpm2ClearControl - %r\n", Status));\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+  DEBUG ((EFI_D_INFO, "Tpm2Clear ... \n"));\r
+  Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);\r
+  DEBUG ((EFI_D_INFO, "Tpm2Clear - %r\n", Status));\r
+\r
+Done:\r
+  ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Alloc PCR data.\r
+\r
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.\r
+  @param[in]  SupportedPCRBanks Supported PCR banks\r
+  @param[in]  PCRBanks          PCR banks\r
+  \r
+  @retval EFI_SUCCESS Operation completed successfully.\r
+**/\r
+EFI_STATUS\r
+Tpm2CommandAllocPcr (\r
+  IN TPM2B_AUTH                *PlatformAuth,  OPTIONAL\r
+  IN UINT32                    SupportedPCRBanks,\r
+  IN UINT32                    PCRBanks\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPMS_AUTH_COMMAND         *AuthSession;\r
+  TPMS_AUTH_COMMAND         LocalAuthSession;\r
+  TPML_PCR_SELECTION        PcrAllocation;\r
+  TPMI_YES_NO               AllocationSuccess;\r
+  UINT32                    MaxPCR;\r
+  UINT32                    SizeNeeded;\r
+  UINT32                    SizeAvailable;\r
+\r
+  if (PlatformAuth == NULL) {\r
+    AuthSession = NULL;\r
+  } else {\r
+    AuthSession = &LocalAuthSession;\r
+    ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));\r
+    LocalAuthSession.sessionHandle = TPM_RS_PW;\r
+    LocalAuthSession.hmac.size = PlatformAuth->size;\r
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
+  }\r
+\r
+  //\r
+  // Fill input\r
+  //\r
+  ZeroMem (&PcrAllocation, sizeof(PcrAllocation));\r
+  if ((EFI_TCG2_BOOT_HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1;\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;\r
+    if ((EFI_TCG2_BOOT_HASH_ALG_SHA1 & PCRBanks) != 0) {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;\r
+    } else {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;\r
+    }\r
+    PcrAllocation.count++;\r
+  }\r
+  if ((EFI_TCG2_BOOT_HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256;\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;\r
+    if ((EFI_TCG2_BOOT_HASH_ALG_SHA256 & PCRBanks) != 0) {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;\r
+    } else {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;\r
+    }\r
+    PcrAllocation.count++;\r
+  }\r
+  if ((EFI_TCG2_BOOT_HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384;\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;\r
+    if ((EFI_TCG2_BOOT_HASH_ALG_SHA384 & PCRBanks) != 0) {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;\r
+    } else {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;\r
+    }\r
+    PcrAllocation.count++;\r
+  }\r
+  if ((EFI_TCG2_BOOT_HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512;\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;\r
+    if ((EFI_TCG2_BOOT_HASH_ALG_SHA512 & PCRBanks) != 0) {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;\r
+    } else {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;\r
+    }\r
+    PcrAllocation.count++;\r
+  }\r
+  if ((EFI_TCG2_BOOT_HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256;\r
+    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;\r
+    if ((EFI_TCG2_BOOT_HASH_ALG_SM3_256 & PCRBanks) != 0) {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;\r
+    } else {\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;\r
+      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;\r
+    }\r
+    PcrAllocation.count++;\r
+  }\r
+  Status = Tpm2PcrAllocate (\r
+             TPM_RH_PLATFORM,\r
+             AuthSession,\r
+             &PcrAllocation,\r
+             &AllocationSuccess,\r
+             &MaxPCR,\r
+             &SizeNeeded,\r
+             &SizeAvailable\r
+             );\r
+  DEBUG ((EFI_D_INFO, "Tpm2PcrAllocate - %r\n", Status));\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));\r
+  DEBUG ((EFI_D_INFO, "MaxPCR            - %08x\n", MaxPCR));\r
+  DEBUG ((EFI_D_INFO, "SizeNeeded        - %08x\n", SizeNeeded));\r
+  DEBUG ((EFI_D_INFO, "SizeAvailable     - %08x\n", SizeAvailable));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Change EPS.\r
+\r
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.\r
+  \r
+  @retval EFI_SUCCESS Operation completed successfully.\r
+**/\r
+EFI_STATUS\r
+Tpm2CommandChangeEps (\r
+  IN TPM2B_AUTH                *PlatformAuth  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPMS_AUTH_COMMAND         *AuthSession;\r
+  TPMS_AUTH_COMMAND         LocalAuthSession;\r
+\r
+  if (PlatformAuth == NULL) {\r
+    AuthSession = NULL;\r
+  } else {\r
+    AuthSession = &LocalAuthSession;\r
+    ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));\r
+    LocalAuthSession.sessionHandle = TPM_RS_PW;\r
+    LocalAuthSession.hmac.size = PlatformAuth->size;\r
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
+  }\r
+\r
+  Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession);\r
+  DEBUG ((EFI_D_INFO, "Tpm2ChangeEPS - %r\n", Status));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Execute physical presence operation requested by the OS.\r
+\r
+  @param[in]      PlatformAuth        platform auth value. NULL means no platform auth change.\r
+  @param[in]      CommandCode         Physical presence operation value.\r
+  @param[in]      CommandParameter    Physical presence operation parameter.\r
+  @param[in, out] PpiFlags            The physical presence interface flags.\r
+  \r
+  @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Unknown physical presence operation.\r
+  @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Error occurred during sending command to TPM or \r
+                                                   receiving response from TPM.\r
+  @retval Others                                   Return code from the TPM device after command execution.\r
+**/\r
+UINT32\r
+Tcg2ExecutePhysicalPresence (\r
+  IN      TPM2B_AUTH                       *PlatformAuth,  OPTIONAL\r
+  IN      UINT32                           CommandCode,\r
+  IN      UINT32                           CommandParameter,\r
+  IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_TCG2_PROTOCOL                 *Tcg2Protocol;\r
+  EFI_TCG2_BOOT_SERVICE_CAPABILITY  ProtocolCapability;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ProtocolCapability.Size = sizeof(ProtocolCapability);\r
+  Status = Tcg2Protocol->GetCapability (\r
+                           Tcg2Protocol,\r
+                           &ProtocolCapability\r
+                           );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  switch (CommandCode) {\r
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
+      Status = Tpm2CommandClear (PlatformAuth);\r
+      if (EFI_ERROR (Status)) {\r
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
+      } else {\r
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+      }\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:\r
+      PpiFlags->PPFlags |= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;\r
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:\r
+      PpiFlags->PPFlags &= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;\r
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
+      Status = Tpm2CommandAllocPcr (PlatformAuth, ProtocolCapability.HashAlgorithmBitmap, CommandParameter);\r
+      if (EFI_ERROR (Status)) {\r
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
+      } else {\r
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+      }\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
+      Status = Tpm2CommandChangeEps (PlatformAuth);\r
+      if (EFI_ERROR (Status)) {\r
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
+      } else {\r
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+      }\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:\r
+      Status = Tpm2CommandAllocPcr (PlatformAuth, ProtocolCapability.HashAlgorithmBitmap, ProtocolCapability.HashAlgorithmBitmap);\r
+      if (EFI_ERROR (Status)) {\r
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
+      } else {\r
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+      }\r
+\r
+    default:\r
+      if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+      } else {\r
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
+      }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Read the specified key for user confirmation.\r
+\r
+  @param[in]  CautionKey  If true,  F12 is used as confirm key;\r
+                          If false, F10 is used as confirm key.\r
+\r
+  @retval     TRUE        User confirmed the changes by input.\r
+  @retval     FALSE       User discarded the changes.\r
+**/\r
+BOOLEAN\r
+Tcg2ReadUserKey (\r
+  IN     BOOLEAN                    CautionKey\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_INPUT_KEY                     Key;\r
+  UINT16                            InputKey;\r
+      \r
+  InputKey = 0; \r
+  do {\r
+    Status = gBS->CheckEvent (gST->ConIn->WaitForKey);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+      if (Key.ScanCode == SCAN_ESC) {\r
+        InputKey = Key.ScanCode;\r
+      }\r
+      if ((Key.ScanCode == SCAN_F10) && !CautionKey) {\r
+        InputKey = Key.ScanCode;\r
+      }\r
+      if ((Key.ScanCode == SCAN_F12) && CautionKey) {\r
+        InputKey = Key.ScanCode;\r
+      }\r
+    }      \r
+  } while (InputKey == 0);\r
+\r
+  if (InputKey != SCAN_ESC) {\r
+    return TRUE;\r
+  }\r
+  \r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Fill Buffer With BootHashAlg.\r
+\r
+  @param[in] Buffer               Buffer to be filled.\r
+  @param[in] BufferSize           Size of buffer.\r
+  @param[in] BootHashAlg          BootHashAlg.\r
+\r
+**/\r
+VOID\r
+Tcg2FillBufferWithBootHashAlg (\r
+  IN UINT16  *Buffer,\r
+  IN UINTN   BufferSize,\r
+  IN UINT32  BootHashAlg\r
+  )\r
+{\r
+  Buffer[0] = 0;\r
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {\r
+    if (Buffer[0] != 0) {\r
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+    }\r
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+  }\r
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {\r
+    if (Buffer[0] != 0) {\r
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+    }\r
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+  }\r
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {\r
+    if (Buffer[0] != 0) {\r
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+    }\r
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+  }\r
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {\r
+    if (Buffer[0] != 0) {\r
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+    }\r
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+  }\r
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {\r
+    if (Buffer[0] != 0) {\r
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+    }\r
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
+  }\r
+}\r
+\r
+/**\r
+  Display the confirm text and get user confirmation.\r
+\r
+  @param[in] TpmPpCommand             The requested TPM physical presence command.\r
+  @param[in] TpmPpCommandParameter    The requested TPM physical presence command parameter.\r
+\r
+  @retval    TRUE          The user has confirmed the changes.\r
+  @retval    FALSE         The user doesn't confirm the changes.\r
+**/\r
+BOOLEAN\r
+Tcg2UserConfirm (\r
+  IN      UINT32                    TpmPpCommand,\r
+  IN      UINT32                    TpmPpCommandParameter\r
+  )\r
+{\r
+  CHAR16                            *ConfirmText;\r
+  CHAR16                            *TmpStr1;\r
+  CHAR16                            *TmpStr2; \r
+  UINTN                             BufSize;\r
+  BOOLEAN                           CautionKey;\r
+  BOOLEAN                           NoPpiInfo;\r
+  UINT16                            Index;\r
+  CHAR16                            DstStr[81];\r
+  CHAR16                            TempBuffer[1024];\r
+  CHAR16                            TempBuffer2[1024];\r
+  EFI_TCG2_PROTOCOL                 *Tcg2Protocol;\r
+  EFI_TCG2_BOOT_SERVICE_CAPABILITY  ProtocolCapability;\r
+  UINT32                            CurrentPCRBanks;\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ProtocolCapability.Size = sizeof(ProtocolCapability);\r
+  Status = Tcg2Protocol->GetCapability (\r
+                           Tcg2Protocol,\r
+                           &ProtocolCapability\r
+                           );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = Tcg2Protocol->GetActivePcrBanks (\r
+                           Tcg2Protocol,\r
+                           &CurrentPCRBanks\r
+                           );\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  TmpStr2     = NULL;\r
+  CautionKey  = FALSE;\r
+  NoPpiInfo   = FALSE;\r
+  BufSize     = CONFIRM_BUFFER_SIZE;\r
+  ConfirmText = AllocateZeroPool (BufSize);\r
+  ASSERT (ConfirmText != NULL);\r
+\r
+  switch (TpmPpCommand) {\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
+      CautionKey = TRUE;\r
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);      \r
+\r
+      break;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:\r
+      CautionKey = TRUE;\r
+      NoPpiInfo  = TRUE;\r
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));\r
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1); \r
+\r
+      break;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
+      CautionKey = TRUE;\r
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS));\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);      \r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);      \r
+\r
+      Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), TpmPpCommandParameter);\r
+      Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof(TempBuffer2), CurrentPCRBanks);\r
+\r
+      TmpStr1 = AllocateZeroPool (BufSize);\r
+      ASSERT (TmpStr1 != NULL);\r
+      UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer);\r
+\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);      \r
+\r
+      break;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
+      CautionKey = TRUE;\r
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS));\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);      \r
+      \r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);      \r
+\r
+      break;\r
+      \r
+\r
+    default:\r
+      ;\r
+  }\r
+\r
+  if (TmpStr2 == NULL) {\r
+    FreePool (ConfirmText);\r
+    return FALSE;\r
+  }\r
+\r
+  if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) {\r
+    if (CautionKey) {\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
+    } else {\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));\r
+    }\r
+    StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+    FreePool (TmpStr1);\r
+\r
+    if (NoPpiInfo) {\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);\r
+    }\r
+\r
+    TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));\r
+  } else {\r
+    if (CautionKey) {\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY));\r
+    } else {\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY));\r
+    }\r
+    StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+    FreePool (TmpStr1);\r
+\r
+    if (NoPpiInfo) {\r
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO));\r
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);\r
+    }\r
+\r
+    TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY));\r
+  }\r
+  BufSize -= StrSize (ConfirmText);\r
+  UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);\r
+\r
+  DstStr[80] = L'\0';\r
+  for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {\r
+    StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1);    \r
+    Print (DstStr);    \r
+  }\r
+  \r
+  FreePool (TmpStr1);\r
+  FreePool (TmpStr2);\r
+  FreePool (ConfirmText);\r
+\r
+  if (Tcg2ReadUserKey (CautionKey)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;  \r
+}\r
+\r
+/**\r
+  Check if there is a valid physical presence command request. Also updates parameter value \r
+  to whether the requested physical presence command already confirmed by user\r
\r
+   @param[in]  TcgPpData                 EFI Tcg2 Physical Presence request data. \r
+   @param[in]  Flags                     The physical presence interface flags.\r
+   @param[out] RequestConfirmed            If the physical presence operation command required user confirm from UI.\r
+                                             True, it indicates the command doesn't require user confirm, or already confirmed \r
+                                                   in last boot cycle by user.\r
+                                             False, it indicates the command need user confirm from UI.\r
+\r
+   @retval  TRUE        Physical Presence operation command is valid.\r
+   @retval  FALSE       Physical Presence operation command is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+Tcg2HaveValidTpmRequest  (\r
+  IN      EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,\r
+  IN      EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags,\r
+  OUT     BOOLEAN                          *RequestConfirmed\r
+  )\r
+{\r
+  BOOLEAN  IsRequestValid;\r
+\r
+  *RequestConfirmed = FALSE;\r
+\r
+  switch (TcgPpData->PPRequest) {\r
+    case TCG2_PHYSICAL_PRESENCE_NO_ACTION:\r
+      *RequestConfirmed = TRUE;\r
+      return TRUE;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {\r
+        *RequestConfirmed = TRUE;\r
+      }\r
+      break;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:\r
+      *RequestConfirmed = TRUE;\r
+      break;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:\r
+      break;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {\r
+        *RequestConfirmed = TRUE;\r
+      }\r
+      break;\r
+\r
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {\r
+        *RequestConfirmed = TRUE;\r
+      }\r
+      break;\r
+      \r
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:\r
+      *RequestConfirmed = TRUE;\r
+      break;\r
+\r
+    default:\r
+      if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {\r
+        IsRequestValid = Tcg2PpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);\r
+        if (!IsRequestValid) {\r
+          return FALSE;\r
+        } else {\r
+          break;\r
+        }\r
+      } else {\r
+        //\r
+        // Wrong Physical Presence command\r
+        //\r
+        return FALSE;\r
+      }\r
+  }\r
+\r
+  if ((Flags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) != 0) {\r
+    //\r
+    // It had been confirmed in last boot, it doesn't need confirm again.\r
+    //\r
+    *RequestConfirmed = TRUE;\r
+  }\r
+\r
+  //\r
+  // Physical Presence command is correct\r
+  //\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Check and execute the requested physical presence command.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  TcgPpData variable is external input, so this function will validate\r
+  its data structure to be valid value.\r
+\r
+  @param[in] PlatformAuth         platform auth value. NULL means no platform auth change.\r
+  @param[in] TcgPpData            Point to the physical presence NV variable.\r
+  @param[in] Flags                The physical presence interface flags.\r
+**/\r
+VOID\r
+Tcg2ExecutePendingTpmRequest (\r
+  IN      TPM2B_AUTH                       *PlatformAuth,  OPTIONAL\r
+  IN      EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,\r
+  IN      EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             DataSize;\r
+  BOOLEAN                           RequestConfirmed;\r
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  NewFlags;\r
+  BOOLEAN                           ResetRequired;\r
+  UINT32                            NewPPFlags;\r
+\r
+  if (TcgPpData->PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {\r
+    //\r
+    // No operation request\r
+    //\r
+    return;\r
+  }\r
+\r
+  if (!Tcg2HaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {\r
+    //\r
+    // Invalid operation request.\r
+    //\r
+    if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
+      TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
+    } else {\r
+      TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
+    }\r
+    TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
+    TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;\r
+    TcgPpData->PPRequestParameter = 0;\r
+\r
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+    Status = gRT->SetVariable (\r
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                    &gEfiTcg2PhysicalPresenceGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    DataSize,\r
+                    TcgPpData\r
+                    );\r
+    return;\r
+  }\r
+\r
+  ResetRequired = FALSE;\r
+  if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {\r
+    NewFlags = Flags;\r
+    NewPPFlags = NewFlags.PPFlags;\r
+    TcgPpData->PPResponse = Tcg2PpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);\r
+    NewFlags.PPFlags = NewPPFlags;\r
+  } else {\r
+    if (!RequestConfirmed) {\r
+      //\r
+      // Print confirm text and wait for approval. \r
+      //\r
+      RequestConfirmed = Tcg2UserConfirm (TcgPpData->PPRequest, TcgPpData->PPRequestParameter);\r
+    }\r
+\r
+    //\r
+    // Execute requested physical presence command\r
+    //\r
+    TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;\r
+    NewFlags = Flags;\r
+    if (RequestConfirmed) {\r
+      TcgPpData->PPResponse = Tcg2ExecutePhysicalPresence (\r
+                                PlatformAuth,\r
+                                TcgPpData->PPRequest, \r
+                                TcgPpData->PPRequestParameter, \r
+                                &NewFlags\r
+                                );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Save the flags if it is updated.\r
+  //\r
+  if (CompareMem (&Flags, &NewFlags, sizeof(EFI_TCG2_PHYSICAL_PRESENCE_FLAGS)) != 0) {\r
+    Status   = gRT->SetVariable (\r
+                      TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                      &gEfiTcg2PhysicalPresenceGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),\r
+                      &NewFlags\r
+                      ); \r
+  }\r
+\r
+  //\r
+  // Clear request\r
+  //\r
+  if ((NewFlags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) == 0) {\r
+    TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
+    TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;    \r
+    TcgPpData->PPRequestParameter = 0;\r
+  }\r
+\r
+  //\r
+  // Save changes\r
+  //\r
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+  Status = gRT->SetVariable (\r
+                  TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTcg2PhysicalPresenceGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  DataSize,\r
+                  TcgPpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Reset system to make new TPM settings in effect\r
+  //\r
+  switch (TcgPpData->LastPPRequest) {\r
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:\r
+      break;\r
+\r
+    default:\r
+      if (TcgPpData->LastPPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {\r
+        if (ResetRequired) {\r
+          break;\r
+        } else {\r
+          return ;\r
+        }\r
+      }\r
+      if (TcgPpData->PPRequest != TCG2_PHYSICAL_PRESENCE_NO_ACTION) {\r
+        break;\r
+      }\r
+      return;\r
+  }\r
+\r
+  Print (L"Rebooting system to make TPM2 settings in effect\n");\r
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+  ASSERT (FALSE);  \r
+}\r
+\r
+/**\r
+  Check and execute the pending TPM request.\r
+\r
+  The TPM request may come from OS or BIOS. This API will display request information and wait \r
+  for user confirmation if TPM request exists. The TPM request will be sent to TPM device after\r
+  the TPM request is confirmed, and one or more reset may be required to make TPM request to \r
+  take effect.\r
+  \r
+  This API should be invoked after console in and console out are all ready as they are required\r
+  to display request information and get user input to confirm the request.  \r
+\r
+  @param[in]  PlatformAuth                   platform auth value. NULL means no platform auth change.\r
+**/\r
+VOID\r
+EFIAPI\r
+Tcg2PhysicalPresenceLibProcessRequest (\r
+  IN      TPM2B_AUTH                     *PlatformAuth  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             DataSize;\r
+  EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;\r
+  EFI_TCG2_PROTOCOL                 *Tcg2Protocol;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;\r
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+  \r
+  //\r
+  // Check S4 resume\r
+  //\r
+  if (GetBootModeHob () == BOOT_ON_S4_RESUME) {\r
+    DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));\r
+    return ;\r
+  }\r
+\r
+  mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, DxeTcg2PhysicalPresenceLibStrings, NULL);\r
+  ASSERT (mTcg2PpStringPackHandle != NULL);\r
+\r
+  //\r
+  // Initialize physical presence flags.\r
+  //\r
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);\r
+  Status = gRT->GetVariable (\r
+                  TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                  &gEfiTcg2PhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpiFlags\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    PpiFlags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT;\r
+    Status   = gRT->SetVariable (\r
+                      TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                      &gEfiTcg2PhysicalPresenceGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),\r
+                      &PpiFlags\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));\r
+      return ;\r
+    }\r
+  }\r
+  DEBUG ((EFI_D_INFO, "[TPM2] PpiFlags = %x\n", PpiFlags.PPFlags));\r
+\r
+  //\r
+  // This flags variable controls whether physical presence is required for TPM command. \r
+  // It should be protected from malicious software. We set it as read-only variable here.\r
+  //\r
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = VariableLockProtocol->RequestToLock (\r
+                                     VariableLockProtocol,\r
+                                     TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                                     &gEfiTcg2PhysicalPresenceGuid\r
+                                     );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Initialize physical presence variable.\r
+  //\r
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+  Status = gRT->GetVariable (\r
+                  TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTcg2PhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &TcgPpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));\r
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+    Status   = gRT->SetVariable (\r
+                      TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                      &gEfiTcg2PhysicalPresenceGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      DataSize,\r
+                      &TcgPpData\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));\r
+      return ;\r
+    }\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));\r
+\r
+  //\r
+  // Execute pending TPM request.\r
+  //  \r
+  Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, PpiFlags);\r
+  DEBUG ((EFI_D_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));\r
+\r
+}\r
+\r
+/**\r
+  Check if the pending TPM request needs user input to confirm.\r
+\r
+  The TPM request may come from OS. This API will check if TPM request exists and need user\r
+  input to confirmation.\r
+  \r
+  @retval    TRUE        TPM needs input to confirm user physical presence.\r
+  @retval    FALSE       TPM doesn't need input to confirm user physical presence.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+Tcg2PhysicalPresenceLibNeedUserConfirm(\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;\r
+  UINTN                             DataSize;\r
+  BOOLEAN                           RequestConfirmed;\r
+  EFI_TCG2_PROTOCOL                 *Tcg2Protocol;\r
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check S4 resume\r
+  //\r
+  if (GetBootModeHob () == BOOT_ON_S4_RESUME) {\r
+    DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check Tpm requests\r
+  //\r
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+  Status = gRT->GetVariable (\r
+                  TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTcg2PhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &TcgPpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);\r
+  Status = gRT->GetVariable (\r
+                  TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                  &gEfiTcg2PhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpiFlags\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  \r
+  if (TcgPpData.PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {\r
+    //\r
+    // No operation request\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  if (!Tcg2HaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {\r
+    //\r
+    // Invalid operation request.\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  if (!RequestConfirmed) {\r
+    //\r
+    // Need UI to confirm\r
+    //\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  The handler for TPM physical presence function:\r
+  Return TPM Operation Response to OS Environment.\r
+\r
+  @param[out]     MostRecentRequest Most recent operation request.\r
+  @param[out]     Response          Response to the most recent operation request.\r
+\r
+  @return Return Code for Return TPM Operation Response to OS Environment.\r
+**/\r
+UINT32\r
+EFIAPI\r
+Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (\r
+  OUT UINT32                *MostRecentRequest,\r
+  OUT UINT32                *Response\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             DataSize;\r
+  EFI_TCG2_PHYSICAL_PRESENCE        PpData;\r
+  \r
+  DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));\r
+\r
+  //\r
+  // Get the Physical Presence variable\r
+  //\r
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+  Status = gRT->GetVariable (\r
+                  TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTcg2PhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    *MostRecentRequest = 0;\r
+    *Response          = 0;\r
+    DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));\r
+    return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;\r
+  }\r
+  \r
+  *MostRecentRequest = PpData.LastPPRequest;\r
+  *Response          = PpData.PPResponse;\r
+\r
+  return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;\r
+}\r
+\r
+/**\r
+  The handler for TPM physical presence function:\r
+  Submit TPM Operation Request to Pre-OS Environment and\r
+  Submit TPM Operation Request to Pre-OS Environment 2.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  \r
+  @param[in]      OperationRequest TPM physical presence operation request.\r
+  @param[in]      RequestParameter TPM physical presence operation request parameter.\r
+\r
+  @return Return Code for Submit TPM Operation Request to Pre-OS Environment and\r
+          Submit TPM Operation Request to Pre-OS Environment 2.\r
+**/\r
+UINT32\r
+EFIAPI\r
+Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (\r
+  IN UINT32                 OperationRequest,\r
+  IN UINT32                 RequestParameter\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             DataSize;\r
+  EFI_TCG2_PHYSICAL_PRESENCE        PpData;\r
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;\r
+  \r
+  DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));\r
+  \r
+  //\r
+  // Get the Physical Presence variable\r
+  //\r
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+  Status = gRT->GetVariable (\r
+                  TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTcg2PhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));\r
+    return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;\r
+  }\r
+\r
+  if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&\r
+      (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) ) {\r
+    //\r
+    // This command requires UI to prompt user for Auth data.\r
+    //\r
+    return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;\r
+  }\r
+\r
+  if (PpData.PPRequest != OperationRequest) {\r
+    PpData.PPRequest = (UINT8)OperationRequest;\r
+    PpData.PPRequestParameter = RequestParameter;\r
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);\r
+    Status = gRT->SetVariable (\r
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,\r
+                    &gEfiTcg2PhysicalPresenceGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    DataSize,\r
+                    &PpData\r
+                    );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) { \r
+    DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));\r
+    return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;\r
+  }\r
+\r
+  if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {\r
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);\r
+    Status = gRT->GetVariable (\r
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                    &gEfiTcg2PhysicalPresenceGuid,\r
+                    NULL,\r
+                    &DataSize,\r
+                    &Flags\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT;\r
+    }\r
+    return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter);\r
+  }\r
+\r
+  return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;\r
+}\r