--- /dev/null
+/** @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