summaryrefslogtreecommitdiff
path: root/SecurityPkg/Tcg
diff options
context:
space:
mode:
authorgdong1 <gdong1@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-02 07:49:32 +0000
committergdong1 <gdong1@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-02 07:49:32 +0000
commit0c18794ea4289f03fefc7117b56740414cc0536c (patch)
tree4e51c5cc23c69a67cead8c58464da870daa4c029 /SecurityPkg/Tcg
parent986d1dfb0813d6a7623531e85c2e2a7e1f956cf8 (diff)
downloadedk2-platforms-0c18794ea4289f03fefc7117b56740414cc0536c.tar.xz
Add security package to repository.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12261 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'SecurityPkg/Tcg')
-rw-r--r--SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c82
-rw-r--r--SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.h27
-rw-r--r--SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf50
-rw-r--r--SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.c1115
-rw-r--r--SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.h38
-rw-r--r--SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceDxe.inf61
-rw-r--r--SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceStrings.unibin0 -> 8304 bytes
-rw-r--r--SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.c134
-rw-r--r--SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf55
-rw-r--r--SecurityPkg/Tcg/TcgConfigDxe/TcgConfig.vfr114
-rw-r--r--SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c147
-rw-r--r--SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf75
-rw-r--r--SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c555
-rw-r--r--SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.h195
-rw-r--r--SecurityPkg/Tcg/TcgConfigDxe/TcgConfigNvData.h48
-rw-r--r--SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.unibin0 -> 5016 bytes
-rw-r--r--SecurityPkg/Tcg/TcgDxe/TcgDxe.c1212
-rw-r--r--SecurityPkg/Tcg/TcgDxe/TcgDxe.inf70
-rw-r--r--SecurityPkg/Tcg/TcgDxe/TisDxe.c432
-rw-r--r--SecurityPkg/Tcg/TcgDxe/TpmComm.c163
-rw-r--r--SecurityPkg/Tcg/TcgDxe/TpmComm.h99
-rw-r--r--SecurityPkg/Tcg/TcgPei/TcgPei.c593
-rw-r--r--SecurityPkg/Tcg/TcgPei/TcgPei.inf67
-rw-r--r--SecurityPkg/Tcg/TcgPei/TisPei.c160
-rw-r--r--SecurityPkg/Tcg/TcgPei/TpmComm.c272
-rw-r--r--SecurityPkg/Tcg/TcgPei/TpmComm.h163
-rw-r--r--SecurityPkg/Tcg/TcgSmm/TcgSmm.c455
-rw-r--r--SecurityPkg/Tcg/TcgSmm/TcgSmm.inf56
-rw-r--r--SecurityPkg/Tcg/TcgSmm/Tpm.asl354
29 files changed, 6792 insertions, 0 deletions
diff --git a/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c
new file mode 100644
index 0000000000..ce53112dc5
--- /dev/null
+++ b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c
@@ -0,0 +1,82 @@
+/** @file
+ TCG MOR (Memory Overwrite Request) Control Driver.
+
+ This driver initilize MemoryOverwriteRequestControl variable. It
+ will clear MOR_CLEAR_MEMORY_BIT bit if it is set.
+
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TcgMor.h"
+
+/**
+ Entry Point for TCG MOR Control driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+MorDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 MorControl;
+ UINTN DataSize;
+
+ ///
+ /// The firmware is required to create the MemoryOverwriteRequestControl UEFI variable.
+ ///
+
+ DataSize = sizeof (MorControl);
+ Status = gRT->GetVariable (
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ &gEfiMemoryOverwriteControlDataGuid,
+ NULL,
+ &DataSize,
+ &MorControl
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Set default value to 0
+ //
+ MorControl = 0;
+ } else {
+ if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
+ //
+ // MorControl is expected, directly return to avoid unnecessary variable operation
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Clear MOR_CLEAR_MEMORY_BIT
+ //
+ DEBUG ((EFI_D_INFO, "TcgMor: Clear MorClearMemory bit\n"));
+ MorControl &= 0xFE;
+ }
+
+ Status = gRT->SetVariable (
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ &gEfiMemoryOverwriteControlDataGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ &MorControl
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+
diff --git a/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.h b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.h
new file mode 100644
index 0000000000..bfad2cf2f0
--- /dev/null
+++ b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.h
@@ -0,0 +1,27 @@
+/** @file
+ The header file for TcgMor.
+
+Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __TCG_MOR_H__
+#define __TCG_MOR_H__
+
+#include <PiDxe.h>
+
+#include <Guid/MemoryOverwriteControl.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+
+#endif
+
diff --git a/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf
new file mode 100644
index 0000000000..e62a90447c
--- /dev/null
+++ b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf
@@ -0,0 +1,50 @@
+## @file
+# Component description file for Memory Overwrite Control driver.
+#
+# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TcgMor
+ FILE_GUID = AD416CE3-A483-45b1-94C2-4B4E4D575562
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = MorDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ TcgMor.c
+ TcgMor.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ DebugLib
+
+[Guids]
+ gEfiMemoryOverwriteControlDataGuid # GUID ALWAYS_CONSUMED
+
+[Depex]
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiTcgProtocolGuid
+
diff --git a/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.c b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.c
new file mode 100644
index 0000000000..187c3ca888
--- /dev/null
+++ b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.c
@@ -0,0 +1,1115 @@
+/** @file
+ This driver checks whether there is pending TPM request. If yes,
+ it will display TPM request information and ask for user confirmation.
+ The TPM request will be cleared after it is processed.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PhysicalPresence.h"
+
+EFI_HII_HANDLE mPpStringPackHandle;
+
+/**
+ Get TPM physical presence permanent flags.
+
+ @param[out] LifetimeLock Returns physicalPresenceLifetimeLock permanent flag.
+ @param[out] CmdEnable Returns physicalPresenceCMDEnable permanent flag.
+
+ @retval EFI_SUCCESS Flags were returns successfully.
+ @retval other Failed to locate EFI TCG Protocol.
+
+**/
+EFI_STATUS
+GetTpmCapability (
+ OUT BOOLEAN *LifetimeLock,
+ OUT BOOLEAN *CmdEnable
+ )
+{
+ EFI_STATUS Status;
+ EFI_TCG_PROTOCOL *TcgProtocol;
+ TPM_RQU_COMMAND_HDR *TpmRqu;
+ TPM_RSP_COMMAND_HDR *TpmRsp;
+ UINT32 *SendBufPtr;
+ UINT8 SendBuffer[sizeof (*TpmRqu) + sizeof (UINT32) * 3];
+ TPM_PERMANENT_FLAGS *TpmPermanentFlags;
+ UINT8 RecvBuffer[40];
+
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Fill request header
+ //
+ TpmRsp = (TPM_RSP_COMMAND_HDR*)RecvBuffer;
+ TpmRqu = (TPM_RQU_COMMAND_HDR*)SendBuffer;
+
+ TpmRqu->tag = H2NS (TPM_TAG_RQU_COMMAND);
+ TpmRqu->paramSize = H2NL (sizeof (SendBuffer));
+ TpmRqu->ordinal = H2NL (TPM_ORD_GetCapability);
+
+ //
+ // Set request parameter
+ //
+ SendBufPtr = (UINT32*)(TpmRqu + 1);
+ WriteUnaligned32 (SendBufPtr++, H2NL (TPM_CAP_FLAG));
+ WriteUnaligned32 (SendBufPtr++, H2NL (sizeof (TPM_CAP_FLAG_PERMANENT)));
+ WriteUnaligned32 (SendBufPtr, H2NL (TPM_CAP_FLAG_PERMANENT));
+
+ Status = TcgProtocol->PassThroughToTpm (
+ TcgProtocol,
+ sizeof (SendBuffer),
+ (UINT8*)TpmRqu,
+ sizeof (RecvBuffer),
+ (UINT8*)&RecvBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (TpmRsp->tag == H2NS (TPM_TAG_RSP_COMMAND));
+ ASSERT (TpmRsp->returnCode == 0);
+
+ TpmPermanentFlags = (TPM_PERMANENT_FLAGS *)&RecvBuffer[sizeof (TPM_RSP_COMMAND_HDR) + sizeof (UINT32)];
+
+ if (LifetimeLock != NULL) {
+ *LifetimeLock = TpmPermanentFlags->physicalPresenceLifetimeLock;
+ }
+
+ if (CmdEnable != NULL) {
+ *CmdEnable = TpmPermanentFlags->physicalPresenceCMDEnable;
+ }
+
+ return Status;
+}
+
+/**
+ Issue TSC_PhysicalPresence command to TPM.
+
+ @param[in] PhysicalPresence The state to set the TPM's Physical Presence flags.
+
+ @retval EFI_SUCCESS TPM executed the command successfully.
+ @retval EFI_SECURITY_VIOLATION TPM returned error when executing the command.
+ @retval other Failed to locate EFI TCG Protocol.
+
+**/
+EFI_STATUS
+TpmPhysicalPresence (
+ IN TPM_PHYSICAL_PRESENCE PhysicalPresence
+ )
+{
+ EFI_STATUS Status;
+ EFI_TCG_PROTOCOL *TcgProtocol;
+ TPM_RQU_COMMAND_HDR *TpmRqu;
+ TPM_PHYSICAL_PRESENCE *TpmPp;
+ TPM_RSP_COMMAND_HDR TpmRsp;
+ UINT8 Buffer[sizeof (*TpmRqu) + sizeof (*TpmPp)];
+
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TpmRqu = (TPM_RQU_COMMAND_HDR*)Buffer;
+ TpmPp = (TPM_PHYSICAL_PRESENCE*)(TpmRqu + 1);
+
+ TpmRqu->tag = H2NS (TPM_TAG_RQU_COMMAND);
+ TpmRqu->paramSize = H2NL (sizeof (Buffer));
+ TpmRqu->ordinal = H2NL (TSC_ORD_PhysicalPresence);
+ WriteUnaligned16 (TpmPp, (TPM_PHYSICAL_PRESENCE) H2NS (PhysicalPresence));
+
+ Status = TcgProtocol->PassThroughToTpm (
+ TcgProtocol,
+ sizeof (Buffer),
+ (UINT8*)TpmRqu,
+ sizeof (TpmRsp),
+ (UINT8*)&TpmRsp
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (TpmRsp.tag == H2NS (TPM_TAG_RSP_COMMAND));
+ if (TpmRsp.returnCode != 0) {
+ //
+ // If it fails, some requirements may be needed for this command.
+ //
+ return EFI_SECURITY_VIOLATION;
+ }
+ return Status;
+}
+
+/**
+ Issue a TPM command for which no additional output data will be returned.
+
+ @param[in] TcgProtocol EFI TCG Protocol instance.
+ @param[in] Ordinal TPM command code.
+ @param[in] AdditionalParameterSize Additional parameter size.
+ @param[in] AdditionalParameters Pointer to the Additional paramaters.
+
+ @retval TPM_PP_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.
+
+**/
+TPM_RESULT
+TpmCommandNoReturnData (
+ IN EFI_TCG_PROTOCOL *TcgProtocol,
+ IN TPM_COMMAND_CODE Ordinal,
+ IN UINTN AdditionalParameterSize,
+ IN VOID *AdditionalParameters
+ )
+{
+ EFI_STATUS Status;
+ TPM_RQU_COMMAND_HDR *TpmRqu;
+ TPM_RSP_COMMAND_HDR TpmRsp;
+ UINT32 Size;
+
+ TpmRqu = (TPM_RQU_COMMAND_HDR*)AllocatePool (
+ sizeof (*TpmRqu) + AdditionalParameterSize
+ );
+ if (TpmRqu == NULL) {
+ return TPM_PP_BIOS_FAILURE;
+ }
+
+ TpmRqu->tag = H2NS (TPM_TAG_RQU_COMMAND);
+ Size = (UINT32)(sizeof (*TpmRqu) + AdditionalParameterSize);
+ TpmRqu->paramSize = H2NL (Size);
+ TpmRqu->ordinal = H2NL (Ordinal);
+ gBS->CopyMem (TpmRqu + 1, AdditionalParameters, AdditionalParameterSize);
+
+ Status = TcgProtocol->PassThroughToTpm (
+ TcgProtocol,
+ Size,
+ (UINT8*)TpmRqu,
+ (UINT32)sizeof (TpmRsp),
+ (UINT8*)&TpmRsp
+ );
+ FreePool (TpmRqu);
+ if (EFI_ERROR (Status) || (TpmRsp.tag != H2NS (TPM_TAG_RSP_COMMAND))) {
+ return TPM_PP_BIOS_FAILURE;
+ }
+ return H2NL (TpmRsp.returnCode);
+}
+
+/**
+ Execute physical presence operation requested by the OS.
+
+ @param[in] TcgProtocol EFI TCG Protocol instance.
+ @param[in] CommandCode Physical presence operation value.
+ @param[in, out] PpiFlags The physical presence interface flags.
+
+ @retval TPM_PP_BIOS_FAILURE Unknown physical presence operation.
+ @retval TPM_PP_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.
+
+**/
+TPM_RESULT
+ExecutePhysicalPresence (
+ IN EFI_TCG_PROTOCOL *TcgProtocol,
+ IN UINT8 CommandCode,
+ IN OUT UINT8 *PpiFlags
+ )
+{
+ BOOLEAN BoolVal;
+ TPM_RESULT TpmResponse;
+ UINT32 InData[5];
+
+ switch (CommandCode) {
+ case ENABLE:
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_PhysicalEnable,
+ 0,
+ NULL
+ );
+
+ case DISABLE:
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_PhysicalDisable,
+ 0,
+ NULL
+ );
+
+ case ACTIVATE:
+ BoolVal = FALSE;
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_PhysicalSetDeactivated,
+ sizeof (BoolVal),
+ &BoolVal
+ );
+
+ case DEACTIVATE:
+ BoolVal = TRUE;
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_PhysicalSetDeactivated,
+ sizeof (BoolVal),
+ &BoolVal
+ );
+
+ case CLEAR:
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_ForceClear,
+ 0,
+ NULL
+ );
+
+ case ENABLE_ACTIVATE:
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE, PpiFlags);
+ if (TpmResponse == 0) {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ACTIVATE, PpiFlags);
+ }
+ return TpmResponse;
+
+ case DEACTIVATE_DISABLE:
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, DEACTIVATE, PpiFlags);
+ if (TpmResponse == 0) {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, DISABLE, PpiFlags);
+ }
+ return TpmResponse;
+
+ case SET_OWNER_INSTALL_TRUE:
+ BoolVal = TRUE;
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_SetOwnerInstall,
+ sizeof (BoolVal),
+ &BoolVal
+ );
+
+ case SET_OWNER_INSTALL_FALSE:
+ BoolVal = FALSE;
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_SetOwnerInstall,
+ sizeof (BoolVal),
+ &BoolVal
+ );
+
+ case ENABLE_ACTIVATE_OWNER_TRUE:
+ //
+ // ENABLE_ACTIVATE + SET_OWNER_INSTALL_TRUE
+ // SET_OWNER_INSTALL_TRUE will be executed atfer reboot
+ //
+ if ((*PpiFlags & FLAG_RESET_TRACK) == 0) {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);
+ *PpiFlags |= FLAG_RESET_TRACK;
+ } else {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, SET_OWNER_INSTALL_TRUE, PpiFlags);
+ *PpiFlags &= ~FLAG_RESET_TRACK;
+ }
+ return TpmResponse;
+
+ case DEACTIVATE_DISABLE_OWNER_FALSE:
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, SET_OWNER_INSTALL_FALSE, PpiFlags);
+ if (TpmResponse == 0) {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, DEACTIVATE_DISABLE, PpiFlags);
+ }
+ return TpmResponse;
+
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
+ InData[0] = H2NL (TPM_SET_STCLEAR_DATA); // CapabilityArea
+ InData[1] = H2NL (sizeof(UINT32)); // SubCapSize
+ InData[2] = H2NL (TPM_SD_DEFERREDPHYSICALPRESENCE); // SubCap
+ InData[3] = H2NL (sizeof(UINT32)); // SetValueSize
+ InData[4] = H2NL (1); // UnownedFieldUpgrade; bit0
+ return TpmCommandNoReturnData (
+ TcgProtocol,
+ TPM_ORD_SetCapability,
+ sizeof (UINT32) * 5,
+ InData
+ );
+
+ case SET_OPERATOR_AUTH:
+ //
+ // TPM_SetOperatorAuth
+ // This command requires UI to prompt user for Auth data
+ // Here it is NOT implemented
+ //
+ return TPM_PP_BIOS_FAILURE;
+
+ case CLEAR_ENABLE_ACTIVATE:
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, CLEAR, PpiFlags);
+ if (TpmResponse == 0) {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);
+ }
+ return TpmResponse;
+
+ case SET_NO_PPI_PROVISION_FALSE:
+ *PpiFlags &= ~FLAG_NO_PPI_PROVISION;
+ return 0;
+
+ case SET_NO_PPI_PROVISION_TRUE:
+ *PpiFlags |= FLAG_NO_PPI_PROVISION;
+ return 0;
+
+ case SET_NO_PPI_CLEAR_FALSE:
+ *PpiFlags &= ~FLAG_NO_PPI_CLEAR;
+ return 0;
+
+ case SET_NO_PPI_CLEAR_TRUE:
+ *PpiFlags |= FLAG_NO_PPI_CLEAR;
+ return 0;
+
+ case SET_NO_PPI_MAINTENANCE_FALSE:
+ *PpiFlags &= ~FLAG_NO_PPI_MAINTENANCE;
+ return 0;
+
+ case SET_NO_PPI_MAINTENANCE_TRUE:
+ *PpiFlags |= FLAG_NO_PPI_MAINTENANCE;
+ return 0;
+
+ case ENABLE_ACTIVATE_CLEAR:
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);
+ if (TpmResponse == 0) {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, CLEAR, PpiFlags);
+ }
+ return TpmResponse;
+
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
+ //
+ // ENABLE_ACTIVATE + CLEAR_ENABLE_ACTIVATE
+ // CLEAR_ENABLE_ACTIVATE will be executed atfer reboot.
+ //
+ if ((*PpiFlags & FLAG_RESET_TRACK) == 0) {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);
+ *PpiFlags |= FLAG_RESET_TRACK;
+ } else {
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, CLEAR_ENABLE_ACTIVATE, PpiFlags);
+ *PpiFlags &= ~FLAG_RESET_TRACK;
+ }
+ return TpmResponse;
+
+ default:
+ ;
+ }
+ return TPM_PP_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
+ReadUserKey (
+ IN BOOLEAN CautionKey
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ UINT16 InputKey;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ gBS->RestoreTPL (TPL_APPLICATION);
+
+ 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);
+
+ gBS->RaiseTPL (OldTpl);
+
+ if (InputKey != SCAN_ESC) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Display the confirm text and get user confirmation.
+
+ @param[in] TpmPpCommand The requested TPM physical presence command.
+
+ @retval TRUE The user has confirmed the changes.
+ @retval FALSE The user doesn't confirm the changes.
+**/
+BOOLEAN
+UserConfirm (
+ IN UINT8 TpmPpCommand
+ )
+{
+ CHAR16 *ConfirmText;
+ CHAR16 *TmpStr1;
+ CHAR16 *TmpStr2;
+ UINTN BufSize;
+ BOOLEAN CautionKey;
+ UINT16 Index;
+ CHAR16 DstStr[81];
+
+ TmpStr2 = NULL;
+ CautionKey = FALSE;
+ BufSize = CONFIRM_BUFFER_SIZE;
+ ConfirmText = AllocateZeroPool (BufSize);
+ ASSERT (ConfirmText != NULL);
+
+ mPpStringPackHandle = HiiAddPackages (
+ &gEfiPhysicalPresenceGuid,
+ NULL,
+ PhysicalPresenceDxeStrings,
+ NULL
+ );
+ ASSERT (mPpStringPackHandle != NULL);
+
+ switch (TpmPpCommand) {
+ case ENABLE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case DISABLE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DISABLE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case ACTIVATE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACTIVATE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case DEACTIVATE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DEACTIVATE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case CLEAR:
+ CautionKey = TRUE;
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CLEAR), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case ENABLE_ACTIVATE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE_ACTIVATE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case DEACTIVATE_DISABLE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DEACTIVATE_DISABLE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_OFF), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case SET_OWNER_INSTALL_TRUE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ALLOW_TAKE_OWNERSHIP), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case SET_OWNER_INSTALL_FALSE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DISALLOW_TAKE_OWNERSHIP), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case ENABLE_ACTIVATE_OWNER_TRUE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_TURN_ON), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case DEACTIVATE_DISABLE_OWNER_FALSE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_TURN_OFF), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_OFF), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
+ CautionKey = TRUE;
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_UNOWNED_FIELD_UPGRADE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_UPGRADE_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_MAINTAIN), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case SET_OPERATOR_AUTH:
+ //
+ // TPM_SetOperatorAuth
+ // This command requires UI to prompt user for Auth data
+ // Here it is NOT implemented
+ //
+ break;
+
+ case CLEAR_ENABLE_ACTIVATE:
+ CautionKey = TRUE;
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CLEAR_TURN_ON), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR_CONT), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case SET_NO_PPI_PROVISION_TRUE:
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_PROVISION), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_PPI_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_INFO), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case SET_NO_PPI_CLEAR_TRUE:
+ CautionKey = TRUE;
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CLEAR), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_PPI_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_CLEAR), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_INFO), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case SET_NO_PPI_MAINTENANCE_TRUE:
+ CautionKey = TRUE;
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_MAINTAIN), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_PPI_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_MAINTAIN), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_INFO), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case ENABLE_ACTIVATE_CLEAR:
+ CautionKey = TRUE;
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
+ CautionKey = TRUE;
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE), NULL);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR_CONT), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);
+ FreePool (TmpStr1);
+ break;
+
+ default:
+ ;
+ }
+
+ if (TmpStr2 == NULL) {
+ FreePool (ConfirmText);
+ return FALSE;
+ }
+
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_REJECT_KEY), NULL);
+ BufSize -= StrSize (ConfirmText);
+ UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);
+
+ DstStr[80] = L'\0';
+ for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {
+ StrnCpy(DstStr, ConfirmText + Index, 80);
+ Print (DstStr);
+ }
+
+ FreePool (TmpStr1);
+ FreePool (TmpStr2);
+ FreePool (ConfirmText);
+
+ if (ReadUserKey (CautionKey)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check and execute the requested physical presence command.
+
+ @param[in, out] TcgPpData Point to the physical presence NV variable.
+
+**/
+VOID
+ExecutePendingTpmRequest (
+ IN OUT EFI_PHYSICAL_PRESENCE *TcgPpData
+ )
+{
+ EFI_STATUS Status;
+ EFI_TCG_PROTOCOL *TcgProtocol;
+ UINTN DataSize;
+ UINT8 Flags;
+ BOOLEAN RequestConfirmed;
+
+ Flags = TcgPpData->Flags;
+ RequestConfirmed = FALSE;
+ switch (TcgPpData->PPRequest) {
+ case NO_ACTION:
+ return;
+ case ENABLE:
+ case DISABLE:
+ case ACTIVATE:
+ case DEACTIVATE:
+ case ENABLE_ACTIVATE:
+ case DEACTIVATE_DISABLE:
+ case SET_OWNER_INSTALL_TRUE:
+ case SET_OWNER_INSTALL_FALSE:
+ case ENABLE_ACTIVATE_OWNER_TRUE:
+ case DEACTIVATE_DISABLE_OWNER_FALSE:
+ case SET_OPERATOR_AUTH:
+ if ((Flags & FLAG_NO_PPI_PROVISION) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case CLEAR:
+ case ENABLE_ACTIVATE_CLEAR:
+ if ((Flags & FLAG_NO_PPI_CLEAR) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
+ if ((Flags & FLAG_NO_PPI_MAINTENANCE) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case CLEAR_ENABLE_ACTIVATE:
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
+ if ((Flags & FLAG_NO_PPI_CLEAR) != 0 && (Flags & FLAG_NO_PPI_PROVISION) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case SET_NO_PPI_PROVISION_FALSE:
+ case SET_NO_PPI_CLEAR_FALSE:
+ case SET_NO_PPI_MAINTENANCE_FALSE:
+ RequestConfirmed = TRUE;
+ break;
+ }
+
+ if ((Flags & FLAG_RESET_TRACK) != 0) {
+ //
+ // It had been confirmed in last boot, it doesn't need confirm again.
+ //
+ RequestConfirmed = TRUE;
+ }
+
+ if (!RequestConfirmed) {
+ //
+ // Print confirm text and wait for approval.
+ //
+ RequestConfirmed = UserConfirm (TcgPpData->PPRequest);
+ }
+
+ //
+ // Execute requested physical presence command.
+ //
+ TcgPpData->PPResponse = TPM_PP_USER_ABORT;
+ if (RequestConfirmed) {
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID**) &TcgProtocol);
+ ASSERT_EFI_ERROR (Status);
+ TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &TcgPpData->Flags);
+ }
+
+ //
+ // Clear request
+ //
+ if ((TcgPpData->Flags & FLAG_RESET_TRACK) == 0) {
+ TcgPpData->LastPPRequest = TcgPpData->PPRequest;
+ TcgPpData->PPRequest = 0;
+ }
+
+ //
+ // Save changes
+ //
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = gRT->SetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ TcgPpData
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ if (TcgPpData->PPResponse == TPM_PP_USER_ABORT) {
+ return;
+ }
+
+ //
+ // Reset system to make new TPM settings in effect
+ //
+ switch (TcgPpData->LastPPRequest) {
+ case ACTIVATE:
+ case DEACTIVATE:
+ case CLEAR:
+ case ENABLE_ACTIVATE:
+ case DEACTIVATE_DISABLE:
+ case ENABLE_ACTIVATE_OWNER_TRUE:
+ case DEACTIVATE_DISABLE_OWNER_FALSE:
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
+ case CLEAR_ENABLE_ACTIVATE:
+ case ENABLE_ACTIVATE_CLEAR:
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
+ break;
+ default:
+ if (TcgPpData->PPRequest != 0) {
+ break;
+ }
+ return;
+ }
+
+ Print (L"Rebooting system to make TPM settings in effect\n");
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+ ASSERT (FALSE);
+}
+
+/**
+ Check and execute the physical presence command requested and
+ Lock physical presence.
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN LifetimeLock;
+ BOOLEAN CmdEnable;
+ UINTN DataSize;
+ EFI_PHYSICAL_PRESENCE TcgPpData;
+
+ //
+ // Check pending request, if not exist, just return.
+ //
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = gRT->GetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &TcgPpData
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", TcgPpData.Flags, TcgPpData.PPRequest));
+
+ Status = GetTpmCapability (&LifetimeLock, &CmdEnable);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ if (!CmdEnable) {
+ if (LifetimeLock) {
+ //
+ // physicalPresenceCMDEnable is locked, can't execute physical presence command.
+ //
+ return ;
+ }
+ Status = TpmPhysicalPresence (TPM_PHYSICAL_PRESENCE_CMD_ENABLE);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ }
+
+ //
+ // Set operator physical presence flags
+ //
+ TpmPhysicalPresence (TPM_PHYSICAL_PRESENCE_PRESENT);
+
+ //
+ // Execute pending TPM request.
+ //
+ ExecutePendingTpmRequest (&TcgPpData);
+ DEBUG ((EFI_D_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse));
+
+ //
+ // Lock physical presence.
+ //
+ TpmPhysicalPresence (TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK);
+}
+
+/**
+ The driver's entry point.
+
+ @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 other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+ UINTN DataSize;
+ EFI_PHYSICAL_PRESENCE TcgPpData;
+
+ //
+ // Initialize physical presence variable exists.
+ //
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = gRT->GetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &TcgPpData
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));
+ TcgPpData.Flags |= FLAG_NO_PPI_PROVISION;
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = gRT->SetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ &TcgPpData
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // TPL Level of physical presence should be larger
+ // than one of TcgDxe driver (TPL_CALLBACK)
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ OnReadyToBoot,
+ NULL,
+ &Event
+ );
+ return Status;
+}
+
diff --git a/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.h b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.h
new file mode 100644
index 0000000000..63d6f21cae
--- /dev/null
+++ b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresence.h
@@ -0,0 +1,38 @@
+/** @file
+ The header file for TPM physical presence driver.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PHYSICAL_PRESENCE_H__
+#define __PHYSICAL_PRESENCE_H__
+
+#include <PiDxe.h>
+
+#include <Protocol/TcgService.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 <Guid/EventGroup.h>
+#include <Guid/PhysicalPresenceData.h>
+
+#define TPM_PP_USER_ABORT ((TPM_RESULT)(-0x10))
+#define TPM_PP_BIOS_FAILURE ((TPM_RESULT)(-0x0f))
+
+#define CONFIRM_BUFFER_SIZE 4096
+
+#endif
diff --git a/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceDxe.inf b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceDxe.inf
new file mode 100644
index 0000000000..9b4aded16f
--- /dev/null
+++ b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceDxe.inf
@@ -0,0 +1,61 @@
+## @file
+# Component file for PhysicalPresenceDxe driver.
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PhysicalPresenceDxe
+ FILE_GUID = D85A4A0C-2E73-4491-92E1-DCEFC3882A68
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = DriverEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[Sources]
+ PhysicalPresence.c
+ PhysicalPresence.h
+ PhysicalPresenceStrings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ HiiLib
+
+[Protocols]
+ gEfiTcgProtocolGuid
+
+[Guids]
+ gEfiPhysicalPresenceGuid
+
+[Depex]
+ gEfiTcgProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiResetArchProtocolGuid
+
diff --git a/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceStrings.uni b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceStrings.uni
new file mode 100644
index 0000000000..2034af7a95
--- /dev/null
+++ b/SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceStrings.uni
Binary files differ
diff --git a/SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.c b/SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.c
new file mode 100644
index 0000000000..e694db8cf1
--- /dev/null
+++ b/SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.c
@@ -0,0 +1,134 @@
+/** @file
+ This driver produces PEI_LOCK_PHYSICAL_PRESENCE_PPI to indicate
+ whether TPM need be locked or not. It can be replaced by a platform
+ specific driver.
+
+Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Ppi/LockPhysicalPresence.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Guid/PhysicalPresenceData.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+
+/**
+ This interface returns whether TPM physical presence needs be locked or not.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+
+ @retval TRUE The TPM physical presence should be locked.
+ @retval FALSE The TPM physical presence cannot be locked.
+
+**/
+BOOLEAN
+EFIAPI
+LockTpmPhysicalPresence (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+//
+// Gobal defintions for lock physical presence PPI and its descriptor.
+//
+PEI_LOCK_PHYSICAL_PRESENCE_PPI mLockPhysicalPresencePpi = {
+ LockTpmPhysicalPresence
+};
+
+EFI_PEI_PPI_DESCRIPTOR mLockPhysicalPresencePpiList = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiLockPhysicalPresencePpiGuid,
+ &mLockPhysicalPresencePpi
+};
+
+/**
+ This interface returns whether TPM physical presence needs be locked or not.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+
+ @retval TRUE The TPM physical presence should be locked.
+ @retval FALSE The TPM physical presence cannot be locked.
+
+**/
+BOOLEAN
+EFIAPI
+LockTpmPhysicalPresence (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
+ UINTN DataSize;
+ EFI_PHYSICAL_PRESENCE TcgPpData;
+
+ //
+ // The CRTM has sensed the physical presence assertion of the user. For example,
+ // the user has pressed the startup button or inserted a USB dongle. The details
+ // of the implementation are vendor-specific. Here we read a PCD value to indicate
+ // whether operator physical presence.
+ //
+ if (!PcdGetBool (PcdTpmPhysicalPresence)) {
+ return TRUE;
+ }
+
+ //
+ // Check the pending TPM requests. Lock TPM physical presence if there is no TPM
+ // request.
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **)&Variable
+ );
+ if (!EFI_ERROR (Status)) {
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = Variable->GetVariable (
+ Variable,
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &TcgPpData
+ );
+ if (!EFI_ERROR (Status)) {
+ if (TcgPpData.PPRequest != 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ //
+ // Lock TPM physical presence by default.
+ //
+ return TRUE;
+}
+
+/**
+ Entry point of this module.
+
+ It installs lock physical presence PPI.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Describes the list of possible PEI Services.
+
+ @return Status of install lock physical presence PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimEntry (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ return PeiServicesInstallPpi (&mLockPhysicalPresencePpiList);
+}
diff --git a/SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf b/SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf
new file mode 100644
index 0000000000..da4e032299
--- /dev/null
+++ b/SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf
@@ -0,0 +1,55 @@
+## @file
+# Component description file for physical presence PEI module.
+#
+# Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PhysicalPresencePei
+ FILE_GUID = 4FE772E8-FE3E-4086-B638-8C493C490488
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PeimEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[Sources]
+ PhysicalPresencePei.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PeiServicesLib
+
+[Ppis]
+ gPeiLockPhysicalPresencePpiGuid
+ gEfiPeiReadOnlyVariable2PpiGuid
+
+[Guids]
+ gEfiPhysicalPresenceGuid
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPhysicalPresence
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid AND
+ gEfiPeiReadOnlyVariable2PpiGuid AND
+ gPeiTpmInitializedPpiGuid
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfig.vfr b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfig.vfr
new file mode 100644
index 0000000000..360e5569f2
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfig.vfr
@@ -0,0 +1,114 @@
+/** @file
+ VFR file used by the TCG configuration component.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TcgConfigNvData.h"
+
+formset
+ guid = TCG_CONFIG_PRIVATE_GUID,
+ title = STRING_TOKEN(STR_TPM_TITLE),
+ help = STRING_TOKEN(STR_TPM_HELP),
+ classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
+
+ varstore TCG_CONFIGURATION,
+ varid = TCG_CONFIGURATION_VARSTORE_ID,
+ name = TCG_CONFIGURATION,
+ guid = TCG_CONFIG_PRIVATE_GUID;
+
+ form formid = TCG_CONFIGURATION_FORM_ID,
+ title = STRING_TOKEN(STR_TPM_TITLE);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ suppressif TRUE;
+ checkbox varid = TCG_CONFIGURATION.TpmEnable,
+ prompt = STRING_TOKEN(STR_NULL),
+ help = STRING_TOKEN(STR_NULL),
+ endcheckbox;
+ endif;
+
+ suppressif TRUE;
+ checkbox varid = TCG_CONFIGURATION.TpmActivate,
+ prompt = STRING_TOKEN(STR_NULL),
+ help = STRING_TOKEN(STR_NULL),
+ endcheckbox;
+ endif;
+
+ suppressif TRUE;
+ checkbox varid = TCG_CONFIGURATION.OriginalHideTpm,
+ prompt = STRING_TOKEN(STR_NULL),
+ help = STRING_TOKEN(STR_NULL),
+ endcheckbox;
+ endif;
+
+ text
+ help = STRING_TOKEN(STR_TPM_STATE_HELP),
+ text = STRING_TOKEN(STR_TPM_STATE_PROMPT),
+ text = STRING_TOKEN(STR_TPM_STATE_CONTENT);
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ label LABEL_TCG_CONFIGURATION_HIDETPM;
+
+ checkbox varid = TCG_CONFIGURATION.HideTpm,
+ questionid = KEY_HIDE_TPM,
+ prompt = STRING_TOKEN(STR_HIDE_TPM_PROMPT),
+ help = STRING_TOKEN(STR_HIDE_TPM_HELP),
+ flags = RESET_REQUIRED,
+ endcheckbox;
+
+ label LABEL_END;
+
+ grayoutif ideqval TCG_CONFIGURATION.OriginalHideTpm == 1;
+ oneof varid = TCG_CONFIGURATION.TpmOperation,
+ questionid = KEY_TPM_ACTION,
+ prompt = STRING_TOKEN(STR_TPM_OPERATION),
+ help = STRING_TOKEN(STR_TPM_OPERATION_HELP),
+ flags = INTERACTIVE,
+ //
+ // Disable (TPM_ORD_PhysicalDisable) command is not available when disabled.
+ // Activate/deactivate (TPM_ORD_physicalSetDeactivated) command is not available when disabled.
+ //
+ suppressif ideqval TCG_CONFIGURATION.TpmEnable == 0;
+ option text = STRING_TOKEN(STR_DISABLE), value = DISABLE, flags = 0;
+ option text = STRING_TOKEN(STR_TPM_ACTIVATE), value = ACTIVATE, flags = 0;
+ option text = STRING_TOKEN(STR_TPM_DEACTIVATE), value = DEACTIVATE, flags = 0;
+ option text = STRING_TOKEN(STR_TPM_DEACTIVATE_DISABLE), value = DEACTIVATE_DISABLE, flags = 0;
+ endif
+ //
+ // Clear (TPM_ORD_ForceClear) command is not available when disabled or deactivated.
+ //
+ suppressif ideqval TCG_CONFIGURATION.TpmEnable == 0 OR
+ ideqval TCG_CONFIGURATION.TpmActivate == 0;
+ option text = STRING_TOKEN(STR_TPM_CLEAR), value = CLEAR, flags = 0;
+ option text = STRING_TOKEN(STR_TPM_CLEAR_ENABLE_ACTIVATE), value = CLEAR_ENABLE_ACTIVATE, flags = 0;
+ endif
+
+ option text = STRING_TOKEN(STR_ENABLE), value = ENABLE, flags = 0;
+ option text = STRING_TOKEN(STR_TPM_ENABLE_ACTIVATE), value = ENABLE_ACTIVATE, flags = 0;
+ option text = STRING_TOKEN(STR_TPM_ENABLE_ACTIVATE_CLEAR), value = ENABLE_ACTIVATE_CLEAR, flags = 0;
+ option text = STRING_TOKEN(STR_TPM_ENABLE_ACTIVATE_CLEAR_E_A), value = ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE, flags = 0;
+ endoneof;
+
+ subtitle text = STRING_TOKEN(STR_NULL);
+
+ checkbox varid = TCG_CONFIGURATION.MorState,
+ questionid = KEY_TPM_MOR_ENABLE,
+ prompt = STRING_TOKEN(STR_MOR_PROMPT),
+ help = STRING_TOKEN(STR_MOR_HELP),
+ endcheckbox;
+ endif;
+
+ endform;
+
+endformset;
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c
new file mode 100644
index 0000000000..4b2008f577
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c
@@ -0,0 +1,147 @@
+/** @file
+ The module entry point for Tcg configuration module.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TcgConfigImpl.h"
+
+EFI_GUID gTcgConfigPrivateGuid = TCG_CONFIG_PRIVATE_GUID;
+
+/**
+ The entry point for Tcg configuration driver.
+
+ @param[in] ImageHandle The image handle of the driver.
+ @param[in] SystemTable The system table.
+
+ @retval EFI_ALREADY_STARTED The driver already exists in system.
+ @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of resources.
+ @retval EFI_SUCCES All the related protocols are installed on the driver.
+ @retval Others Fail to install protocols as indicated.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgConfigDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ TCG_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_TCG_PROTOCOL *TcgProtocol;
+
+ Status = TisPcRequestUseTpm ((TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "TPM not detected!\n"));
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol);
+ if (EFI_ERROR (Status)) {
+ TcgProtocol = NULL;
+ }
+
+ Status = gBS->OpenProtocol (
+ ImageHandle,
+ &gTcgConfigPrivateGuid,
+ NULL,
+ ImageHandle,
+ ImageHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Create a private data structure.
+ //
+ PrivateData = AllocateCopyPool (sizeof (TCG_CONFIG_PRIVATE_DATA), &mTcgConfigPrivateDateTemplate);
+ if (PrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PrivateData->TcgProtocol = TcgProtocol;
+ PrivateData->HideTpm = PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm);
+
+ //
+ // Install TCG configuration form
+ //
+ Status = InstallTcgConfigForm (PrivateData);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Install private GUID.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gTcgConfigPrivateGuid,
+ PrivateData,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+ if (PrivateData != NULL) {
+ UninstallTcgConfigForm (PrivateData);
+ }
+
+ return Status;
+}
+
+/**
+ Unload the Tcg configuration form.
+
+ @param[in] ImageHandle The driver's image handle.
+
+ @retval EFI_SUCCESS The Tcg configuration form is unloaded.
+ @retval Others Failed to unload the form.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgConfigDriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ TCG_CONFIG_PRIVATE_DATA *PrivateData;
+
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gTcgConfigPrivateGuid,
+ (VOID **) &PrivateData
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (PrivateData->Signature == TCG_CONFIG_PRIVATE_DATA_SIGNATURE);
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gTcgConfigPrivateGuid,
+ PrivateData,
+ NULL
+ );
+
+ UninstallTcgConfigForm (PrivateData);
+
+ return EFI_SUCCESS;
+}
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf
new file mode 100644
index 0000000000..d9d3102668
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf
@@ -0,0 +1,75 @@
+## @file
+# Component name for Tcg configuration module.
+#
+# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TcgConfigDxe
+ FILE_GUID = 1FA4DAFE-FA5D-4d75-BEA6-5863862C520A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = TcgConfigDriverEntryPoint
+ UNLOAD_IMAGE = TcgConfigDriverUnload
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ TcgConfigDriver.c
+ TcgConfigImpl.c
+ TcgConfigImpl.h
+ TcgConfig.vfr
+ TcgConfigStrings.uni
+ TcgConfigNvData.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+ UefiHiiServicesLib
+ DebugLib
+ HiiLib
+ PcdLib
+ PrintLib
+ TpmCommLib
+
+[Guids]
+ gEfiPhysicalPresenceGuid
+ gEfiIfrTianoGuid
+
+[Protocols]
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiTcgProtocolGuid ## CONSUMES
+
+[FixedPcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdMorEnable
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpm
+
+[Depex]
+ gEfiHiiConfigRoutingProtocolGuid AND
+ gEfiHiiDatabaseProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid \ No newline at end of file
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c
new file mode 100644
index 0000000000..535f5e852a
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c
@@ -0,0 +1,555 @@
+/** @file
+ HII Config Access protocol implementation of TCG configuration module.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TcgConfigImpl.h"
+
+EFI_GUID mTcgFormSetGuid = TCG_CONFIG_PRIVATE_GUID;
+CHAR16 mTcgStorageName[] = L"TCG_CONFIGURATION";
+
+TCG_CONFIG_PRIVATE_DATA mTcgConfigPrivateDateTemplate = {
+ TCG_CONFIG_PRIVATE_DATA_SIGNATURE,
+ {
+ TcgExtractConfig,
+ TcgRouteConfig,
+ TcgCallback
+ }
+};
+
+HII_VENDOR_DEVICE_PATH mTcgHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ TCG_CONFIG_PRIVATE_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH),
+ (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+/**
+ Get current state of TPM device.
+
+ @param[in] TcgProtocol Point to EFI_TCG_PROTOCOL instance.
+ @param[out] TpmEnable Flag to indicate TPM is enabled or not.
+ @param[out] TpmActivate Flag to indicate TPM is activated or not.
+
+ @retval EFI_SUCCESS State is successfully returned.
+ @retval EFI_DEVICE_ERROR Failed to get TPM response.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+GetTpmState (
+ IN EFI_TCG_PROTOCOL *TcgProtocol,
+ OUT BOOLEAN *TpmEnable, OPTIONAL
+ OUT BOOLEAN *TpmActivate OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ TPM_RSP_COMMAND_HDR *TpmRsp;
+ UINT32 TpmSendSize;
+ TPM_PERMANENT_FLAGS *TpmPermanentFlags;
+ UINT8 CmdBuf[64];
+
+ ASSERT (TcgProtocol != NULL);
+
+ //
+ // Get TPM Permanent flags (TpmEnable, TpmActivate)
+ //
+ if ((TpmEnable != NULL) || (TpmActivate != NULL)) {
+ TpmSendSize = sizeof (TPM_RQU_COMMAND_HDR) + sizeof (UINT32) * 3;
+ *(UINT16*)&CmdBuf[0] = H2NS (TPM_TAG_RQU_COMMAND);
+ *(UINT32*)&CmdBuf[2] = H2NL (TpmSendSize);
+ *(UINT32*)&CmdBuf[6] = H2NL (TPM_ORD_GetCapability);
+
+ *(UINT32*)&CmdBuf[10] = H2NL (TPM_CAP_FLAG);
+ *(UINT32*)&CmdBuf[14] = H2NL (sizeof (TPM_CAP_FLAG_PERMANENT));
+ *(UINT32*)&CmdBuf[18] = H2NL (TPM_CAP_FLAG_PERMANENT);
+
+ Status = TcgProtocol->PassThroughToTpm (
+ TcgProtocol,
+ TpmSendSize,
+ CmdBuf,
+ sizeof (CmdBuf),
+ CmdBuf
+ );
+ TpmRsp = (TPM_RSP_COMMAND_HDR *) &CmdBuf[0];
+ if (EFI_ERROR (Status) || (TpmRsp->tag != H2NS (TPM_TAG_RSP_COMMAND)) || (TpmRsp->returnCode != 0)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ TpmPermanentFlags = (TPM_PERMANENT_FLAGS *) &CmdBuf[sizeof (TPM_RSP_COMMAND_HDR) + sizeof (UINT32)];
+
+ if (TpmEnable != NULL) {
+ *TpmEnable = (BOOLEAN) !TpmPermanentFlags->disable;
+ }
+
+ if (TpmActivate != NULL) {
+ *TpmActivate = (BOOLEAN) !TpmPermanentFlags->deactivated;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param[in] Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param[out] Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param[out] Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ TCG_CONFIGURATION Configuration;
+ TCG_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_STRING ConfigRequestHdr;
+ EFI_STRING ConfigRequest;
+ BOOLEAN AllocatedRequest;
+ UINTN Size;
+ BOOLEAN TpmEnable;
+ BOOLEAN TpmActivate;
+ CHAR16 State[32];
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Progress = Request;
+ if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mTcgFormSetGuid, mTcgStorageName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ AllocatedRequest = FALSE;
+ Size = 0;
+
+ PrivateData = TCG_CONFIG_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ ZeroMem (&Configuration, sizeof (TCG_CONFIGURATION));
+
+ Configuration.MorState = PcdGetBool (PcdMorEnable);
+ Configuration.TpmOperation = ENABLE;
+ Configuration.HideTpm = PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm);
+ //
+ // Read the original value of HideTpm from PrivateData which won't be changed by Setup in this boot.
+ //
+ Configuration.OriginalHideTpm = PrivateData->HideTpm;
+
+ //
+ // Display current TPM state.
+ //
+ if (PrivateData->TcgProtocol != NULL) {
+ Status = GetTpmState (PrivateData->TcgProtocol, &TpmEnable, &TpmActivate);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UnicodeSPrint (
+ State,
+ sizeof (State),
+ L"%s, and %s",
+ TpmEnable ? L"Enabled" : L"Disabled",
+ TpmActivate ? L"Activated" : L"Deactivated"
+ );
+ Configuration.TpmEnable = TpmEnable;
+ Configuration.TpmActivate = TpmActivate;
+
+ HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM_STATE_CONTENT), State, NULL);
+ }
+
+ BufferSize = sizeof (Configuration);
+ ConfigRequest = Request;
+ if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+ //
+ // Request has no request element, construct full request string.
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (&mTcgFormSetGuid, mTcgStorageName, PrivateData->DriverHandle);
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64) BufferSize);
+ FreePool (ConfigRequestHdr);
+ }
+
+ Status = gHiiConfigRouting->BlockToConfig (
+ gHiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *) &Configuration,
+ BufferSize,
+ Results,
+ Progress
+ );
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ }
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param[out] Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ TCG_CONFIGURATION TcgConfiguration;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Progress = Configuration;
+ if (!HiiIsConfigHdrMatch (Configuration, &mTcgFormSetGuid, mTcgStorageName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (TCG_CONFIGURATION);
+ Status = gHiiConfigRouting->ConfigToBlock (
+ gHiiConfigRouting,
+ Configuration,
+ (UINT8 *) &TcgConfiguration,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PcdSetBool (PcdMorEnable, TcgConfiguration.MorState);
+ PcdSetBool (PcdHideTpm, TcgConfiguration.HideTpm);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save TPM request to variable space.
+
+ @param[in] PpRequest Physical Presence request command.
+
+ @retval EFI_SUCCESS The operation is finished successfully.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+SavePpRequest (
+ IN UINT8 PpRequest
+ )
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ EFI_PHYSICAL_PRESENCE PpData;
+
+ //
+ // Save TPM command to variable.
+ //
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = gRT->GetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &PpData
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PpData.PPRequest = PpRequest;
+ Status = gRT->SetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ &PpData
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Reset system.
+ //
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param[in] Action Specifies the type of action taken by the browser.
+ @param[in] QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param[in] Type The type of value for the question.
+ @param[in] Value A pointer to the data being sent to the original
+ exporting driver.
+ @param[out] ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
+ variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be saved.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Action != EFI_BROWSER_ACTION_CHANGING) || (QuestionId != KEY_TPM_ACTION)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SavePpRequest (Value->u8);
+ ASSERT (FALSE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function publish the TCG configuration Form for TPM device.
+
+ @param[in, out] PrivateData Points to TCG configuration private data.
+
+ @retval EFI_SUCCESS HII Form is installed for this network device.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+InstallTcgConfigForm (
+ IN OUT TCG_CONFIG_PRIVATE_DATA *PrivateData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+
+ DriverHandle = NULL;
+ ConfigAccess = &PrivateData->ConfigAccess;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mTcgHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ ConfigAccess,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PrivateData->DriverHandle = DriverHandle;
+
+ //
+ // Publish the HII package list
+ //
+ HiiHandle = HiiAddPackages (
+ &mTcgFormSetGuid,
+ DriverHandle,
+ TcgConfigDxeStrings,
+ TcgConfigBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mTcgHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ ConfigAccess,
+ NULL
+ );
+
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PrivateData->HiiHandle = HiiHandle;
+
+ //
+ // Remove the Hide TPM question from the IFR
+ //
+ if (!PcdGetBool (PcdHideTpmSupport)) {
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_TCG_CONFIGURATION_HIDETPM;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ HiiUpdateForm (HiiHandle, NULL, TCG_CONFIGURATION_FORM_ID, StartOpCodeHandle, EndOpCodeHandle);
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function removes TCG configuration Form.
+
+ @param[in, out] PrivateData Points to TCG configuration private data.
+
+**/
+VOID
+UninstallTcgConfigForm (
+ IN OUT TCG_CONFIG_PRIVATE_DATA *PrivateData
+ )
+{
+ //
+ // Uninstall HII package list
+ //
+ if (PrivateData->HiiHandle != NULL) {
+ HiiRemovePackages (PrivateData->HiiHandle);
+ PrivateData->HiiHandle = NULL;
+ }
+
+ //
+ // Uninstall HII Config Access Protocol
+ //
+ if (PrivateData->DriverHandle != NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ PrivateData->DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mTcgHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &PrivateData->ConfigAccess,
+ NULL
+ );
+ PrivateData->DriverHandle = NULL;
+ }
+
+ FreePool (PrivateData);
+}
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.h b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.h
new file mode 100644
index 0000000000..cbfca74392
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.h
@@ -0,0 +1,195 @@
+/** @file
+ The header file of HII Config Access protocol implementation of TCG
+ configuration module.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __TCG_CONFIG_IMPL_H__
+#define __TCG_CONFIG_IMPL_H__
+
+#include <Uefi.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/TcgService.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HiiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TpmCommLib.h>
+
+#include <Guid/MdeModuleHii.h>
+
+#include "TcgConfigNvData.h"
+
+//
+// Tool generated IFR binary data and String package data
+//
+extern UINT8 TcgConfigBin[];
+extern UINT8 TcgConfigDxeStrings[];
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+
+ EFI_TCG_PROTOCOL *TcgProtocol;
+
+ BOOLEAN HideTpm;
+} TCG_CONFIG_PRIVATE_DATA;
+
+extern TCG_CONFIG_PRIVATE_DATA mTcgConfigPrivateDateTemplate;
+
+#define TCG_CONFIG_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('T', 'C', 'G', 'D')
+#define TCG_CONFIG_PRIVATE_DATA_FROM_THIS(a) CR (a, TCG_CONFIG_PRIVATE_DATA, ConfigAccess, TCG_CONFIG_PRIVATE_DATA_SIGNATURE)
+
+
+/**
+ This function publish the TCG configuration Form for TPM device.
+
+ @param[in, out] PrivateData Points to TCG configuration private data.
+
+ @retval EFI_SUCCESS HII Form is installed for this network device.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+InstallTcgConfigForm (
+ IN OUT TCG_CONFIG_PRIVATE_DATA *PrivateData
+ );
+
+/**
+ This function removes TCG configuration Form.
+
+ @param[in, out] PrivateData Points to TCG configuration private data.
+
+**/
+VOID
+UninstallTcgConfigForm (
+ IN OUT TCG_CONFIG_PRIVATE_DATA *PrivateData
+ );
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param[in] Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param[out] Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param[out] Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ );
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param[out] Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ );
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param[in] Action Specifies the type of action taken by the browser.
+ @param[in] QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param[in] Type The type of value for the question.
+ @param[in] Value A pointer to the data being sent to the original
+ exporting driver.
+ @param[out] ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
+ variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be saved.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ );
+
+#endif
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigNvData.h b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigNvData.h
new file mode 100644
index 0000000000..982764c65c
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigNvData.h
@@ -0,0 +1,48 @@
+/** @file
+ Header file for NV data structure definition.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __TCG_CONFIG_NV_DATA_H__
+#define __TCG_CONFIG_NV_DATA_H__
+
+#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/PhysicalPresenceData.h>
+
+#define TCG_CONFIG_PRIVATE_GUID \
+ { \
+ 0xb0f901e4, 0xc424, 0x45de, {0x90, 0x81, 0x95, 0xe2, 0xb, 0xde, 0x6f, 0xb5 } \
+ }
+
+#define TCG_CONFIGURATION_VARSTORE_ID 0x0001
+#define TCG_CONFIGURATION_FORM_ID 0x0001
+
+#define KEY_HIDE_TPM 0x2000
+#define KEY_TPM_ACTION 0x3000
+#define KEY_TPM_MOR_ENABLE 0x4000
+
+#define LABEL_TCG_CONFIGURATION_HIDETPM 0x0001
+#define LABEL_END 0xffff
+
+//
+// Nv Data structure referenced by IFR
+//
+typedef struct {
+ BOOLEAN HideTpm;
+ BOOLEAN OriginalHideTpm;
+ BOOLEAN MorState;
+ UINT8 TpmOperation;
+ BOOLEAN TpmEnable;
+ BOOLEAN TpmActivate;
+} TCG_CONFIGURATION;
+
+#endif
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.uni b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.uni
new file mode 100644
index 0000000000..df39f62093
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.uni
Binary files differ
diff --git a/SecurityPkg/Tcg/TcgDxe/TcgDxe.c b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c
new file mode 100644
index 0000000000..4cb5d3084b
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c
@@ -0,0 +1,1212 @@
+/** @file
+ This module implements TCG EFI Protocol.
+
+Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/SmBios.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/SmBios.h>
+#include <Guid/HobList.h>
+#include <Guid/TcgEventHob.h>
+#include <Guid/EventGroup.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/TcgService.h>
+#include <Protocol/AcpiTable.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/HobLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TpmCommLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+
+#include "TpmComm.h"
+
+#define EFI_TCG_LOG_AREA_SIZE 0x10000
+
+#pragma pack (1)
+
+typedef struct _EFI_TCG_CLIENT_ACPI_TABLE {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT16 PlatformClass;
+ UINT32 Laml;
+ EFI_PHYSICAL_ADDRESS Lasa;
+} EFI_TCG_CLIENT_ACPI_TABLE;
+
+typedef struct _EFI_TCG_SERVER_ACPI_TABLE {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT16 PlatformClass;
+ UINT16 Reserved0;
+ UINT64 Laml;
+ EFI_PHYSICAL_ADDRESS Lasa;
+ UINT16 SpecRev;
+ UINT8 DeviceFlags;
+ UINT8 InterruptFlags;
+ UINT8 Gpe;
+ UINT8 Reserved1[3];
+ UINT32 GlobalSysInt;
+ EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE BaseAddress;
+ UINT32 Reserved2;
+ EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE ConfigAddress;
+ UINT8 PciSegNum;
+ UINT8 PciBusNum;
+ UINT8 PciDevNum;
+ UINT8 PciFuncNum;
+} EFI_TCG_SERVER_ACPI_TABLE;
+
+#pragma pack ()
+
+#define TCG_DXE_DATA_FROM_THIS(this) \
+ BASE_CR (this, TCG_DXE_DATA, TcgProtocol)
+
+typedef struct _TCG_DXE_DATA {
+ EFI_TCG_PROTOCOL TcgProtocol;
+ TCG_EFI_BOOT_SERVICE_CAPABILITY BsCap;
+ EFI_TCG_CLIENT_ACPI_TABLE *TcgClientAcpiTable;
+ EFI_TCG_SERVER_ACPI_TABLE *TcgServerAcpiTable;
+ UINTN EventLogSize;
+ UINT8 *LastEvent;
+ TIS_TPM_HANDLE TpmHandle;
+} TCG_DXE_DATA;
+
+
+
+EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate = {
+ {
+ EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
+ sizeof (mTcgClientAcpiTemplate),
+ 0x02 //Revision
+ //
+ // Compiler initializes the remaining bytes to 0
+ // These fields should be filled in in production
+ //
+ },
+ 0, // 0 for PC Client Platform Class
+ 0, // Log Area Max Length
+ (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1) // Log Area Start Address
+};
+
+//
+// The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
+// the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,
+// this _UID can be changed and should match with the _UID setting of the TPM
+// ACPI device object
+//
+EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate = {
+ {
+ EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
+ sizeof (mTcgServerAcpiTemplate),
+ 0x02 //Revision
+ //
+ // Compiler initializes the remaining bytes to 0
+ // These fields should be filled in in production
+ //
+ },
+ 1, // 1 for Server Platform Class
+ 0, // Reserved
+ 0, // Log Area Max Length
+ (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address
+ 0x0100, // TCG Specification revision 1.0
+ 2, // Device Flags
+ 0, // Interrupt Flags
+ 0, // GPE
+ {0}, // Reserved 3 bytes
+ 0, // Global System Interrupt
+ {
+ EFI_ACPI_3_0_SYSTEM_MEMORY,
+ 0,
+ 0,
+ EFI_ACPI_3_0_BYTE,
+ TPM_BASE_ADDRESS // Base Address
+ },
+ 0, // Reserved
+ {0}, // Configuration Address
+ 0xFF, // ACPI _UID value of the device, can be changed for different platforms
+ 0, // ACPI _UID value of the device, can be changed for different platforms
+ 0, // ACPI _UID value of the device, can be changed for different platforms
+ 0 // ACPI _UID value of the device, can be changed for different platforms
+};
+
+UINTN mBootAttempts = 0;
+CHAR16 mBootVarName[] = L"BootOrder";
+
+/**
+ This service provides EFI protocol capability information, state information
+ about the TPM, and Event Log state information.
+
+ @param[in] This Indicates the calling context
+ @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY
+ structure and fills in the fields with the EFI protocol
+ capability information and the current TPM state information.
+ @param[out] TCGFeatureFlags This is a pointer to the feature flags. No feature
+ flags are currently defined so this parameter
+ MUST be set to 0. However, in the future,
+ feature flags may be defined that, for example,
+ enable hash algorithm agility.
+ @param[out] EventLogLocation This is a pointer to the address of the event log in memory.
+ @param[out] EventLogLastEntry If the Event Log contains more than one entry,
+ this is a pointer to the address of the start of
+ the last entry in the event log in memory.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeStatusCheck (
+ IN EFI_TCG_PROTOCOL *This,
+ OUT TCG_EFI_BOOT_SERVICE_CAPABILITY *ProtocolCapability,
+ OUT UINT32 *TCGFeatureFlags,
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ if (ProtocolCapability != NULL) {
+ *ProtocolCapability = TcgData->BsCap;
+ }
+
+ if (TCGFeatureFlags != NULL) {
+ *TCGFeatureFlags = 0;
+ }
+
+ if (EventLogLocation != NULL) {
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+ *EventLogLocation = TcgData->TcgClientAcpiTable->Lasa;
+ } else {
+ *EventLogLocation = TcgData->TcgServerAcpiTable->Lasa;
+ }
+ }
+
+ if (EventLogLastEntry != NULL) {
+ if (TcgData->BsCap.TPMDeactivatedFlag) {
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;
+ } else {
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)TcgData->LastEvent;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This service abstracts the capability to do a hash operation on a data buffer.
+
+ @param[in] This Indicates the calling context
+ @param[in] HashData Pointer to the data buffer to be hashed
+ @param[in] HashDataLen Length of the data buffer to be hashed
+ @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
+ @param[in, out] HashedDataLen Resultant length of the hashed data
+ @param[in, out] HashedDataResult Resultant buffer of the hashed data
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER HashDataLen is NULL.
+ @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.
+ @retval EFI_UNSUPPORTED AlgorithmId not supported.
+ @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeHashAll (
+ IN EFI_TCG_PROTOCOL *This,
+ IN UINT8 *HashData,
+ IN UINT64 HashDataLen,
+ IN TCG_ALGORITHM_ID AlgorithmId,
+ IN OUT UINT64 *HashedDataLen,
+ IN OUT UINT8 **HashedDataResult
+ )
+{
+ if (HashedDataLen == NULL || HashedDataResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (AlgorithmId) {
+ case TPM_ALG_SHA:
+ if (*HashedDataLen == 0) {
+ *HashedDataLen = sizeof (TPM_DIGEST);
+ *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);
+ if (*HashedDataResult == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (*HashedDataLen < sizeof (TPM_DIGEST)) {
+ *HashedDataLen = sizeof (TPM_DIGEST);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *HashedDataLen = sizeof (TPM_DIGEST);
+
+ return TpmCommHashAll (
+ HashData,
+ (UINTN) HashDataLen,
+ (TPM_DIGEST*)*HashedDataResult
+ );
+ default:
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Add a new entry to the Event Log.
+
+ @param[in] TcgData TCG_DXE_DATA structure.
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS The new event log entry was added.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeLogEventI (
+ IN TCG_DXE_DATA *TcgData,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+ TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgClientAcpiTable->Lasa;
+ return TpmCommLogEvent (
+ &TcgData->LastEvent,
+ &TcgData->EventLogSize,
+ (UINTN)TcgData->TcgClientAcpiTable->Laml,
+ NewEventHdr,
+ NewEventData
+ );
+ } else {
+ TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgServerAcpiTable->Lasa;
+ return TpmCommLogEvent (
+ &TcgData->LastEvent,
+ &TcgData->EventLogSize,
+ (UINTN)TcgData->TcgServerAcpiTable->Laml,
+ NewEventHdr,
+ NewEventData
+ );
+ }
+}
+
+/**
+ This service abstracts the capability to add an entry to the Event Log.
+
+ @param[in] This Indicates the calling context
+ @param[in] TCGLogData Pointer to the start of the data buffer containing
+ the TCG_PCR_EVENT data structure. All fields in
+ this structure are properly filled by the caller.
+ @param[in, out] EventNumber The event number of the event just logged
+ @param[in] Flags Indicate additional flags. Only one flag has been
+ defined at this time, which is 0x01 and means the
+ extend operation should not be performed. All
+ other bits are reserved.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeLogEvent (
+ IN EFI_TCG_PROTOCOL *This,
+ IN TCG_PCR_EVENT *TCGLogData,
+ IN OUT UINT32 *EventNumber,
+ IN UINT32 Flags
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ if (TcgData->BsCap.TPMDeactivatedFlag) {
+ return EFI_DEVICE_ERROR;
+ }
+ return TcgDxeLogEventI (
+ TcgData,
+ (TCG_PCR_EVENT_HDR*)TCGLogData,
+ TCGLogData->Event
+ );
+}
+
+/**
+ This service is a proxy for commands to the TPM.
+
+ @param[in] This Indicates the calling context
+ @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block
+ @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block
+ @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block
+ @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid ordinal.
+ @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.
+ @retval EFI_TIMEOUT The TIS timed-out.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxePassThroughToTpm (
+ IN EFI_TCG_PROTOCOL *This,
+ IN UINT32 TpmInputParameterBlockSize,
+ IN UINT8 *TpmInputParameterBlock,
+ IN UINT32 TpmOutputParameterBlockSize,
+ IN UINT8 *TpmOutputParameterBlock
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ return TisPcExecute (
+ TcgData->TpmHandle,
+ "%r%/%r",
+ TpmInputParameterBlock,
+ (UINTN) TpmInputParameterBlockSize,
+ TpmOutputParameterBlock,
+ (UINTN) TpmOutputParameterBlockSize
+ );
+}
+
+/**
+ Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
+ and add an entry to the Event Log.
+
+ @param[in] TcgData TCG_DXE_DATA structure.
+ @param[in] HashData Physical address of the start of the data buffer
+ to be hashed, extended, and logged.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
+ @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeHashLogExtendEventI (
+ IN TCG_DXE_DATA *TcgData,
+ IN UINT8 *HashData,
+ IN UINT64 HashDataLen,
+ IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+ EFI_STATUS Status;
+
+ if (HashDataLen > 0) {
+ Status = TpmCommHashAll (
+ HashData,
+ (UINTN) HashDataLen,
+ &NewEventHdr->Digest
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = TpmCommExtend (
+ TcgData->TpmHandle,
+ &NewEventHdr->Digest,
+ NewEventHdr->PCRIndex,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = TcgDxeLogEventI (TcgData, NewEventHdr, NewEventData);
+ }
+
+ return Status;
+}
+
+/**
+ This service abstracts the capability to do a hash operation on a data buffer,
+ extend a specific TPM PCR with the hash result, and add an entry to the Event Log
+
+ @param[in] This Indicates the calling context
+ @param[in] HashData Physical address of the start of the data buffer
+ to be hashed, extended, and logged.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
+ @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
+ @param[in, out] TCGLogData The physical address of the start of the data
+ buffer containing the TCG_PCR_EVENT data structure.
+ @param[in, out] EventNumber The event number of the event just logged.
+ @param[out] EventLogLastEntry Physical address of the first byte of the entry
+ just placed in the Event Log. If the Event Log was
+ empty when this function was called then this physical
+ address will be the same as the physical address of
+ the start of the Event Log.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.
+ @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgDxeHashLogExtendEvent (
+ IN EFI_TCG_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS HashData,
+ IN UINT64 HashDataLen,
+ IN TPM_ALGORITHM_ID AlgorithmId,
+ IN OUT TCG_PCR_EVENT *TCGLogData,
+ IN OUT UINT32 *EventNumber,
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry
+ )
+{
+ TCG_DXE_DATA *TcgData;
+
+ TcgData = TCG_DXE_DATA_FROM_THIS (This);
+
+ if (TcgData->BsCap.TPMDeactivatedFlag) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (AlgorithmId != TPM_ALG_SHA) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return TcgDxeHashLogExtendEventI (
+ TcgData,
+ (UINT8 *) (UINTN) HashData,
+ HashDataLen,
+ (TCG_PCR_EVENT_HDR*)TCGLogData,
+ TCGLogData->Event
+ );
+}
+
+TCG_DXE_DATA mTcgDxeData = {
+ {
+ TcgDxeStatusCheck,
+ TcgDxeHashAll,
+ TcgDxeLogEvent,
+ TcgDxePassThroughToTpm,
+ TcgDxeHashLogExtendEvent
+ },
+ {
+ sizeof (mTcgDxeData.BsCap),
+ { 1, 2, 0, 0 },
+ { 1, 2, 0, 0 },
+ 1,
+ TRUE,
+ FALSE
+ },
+ &mTcgClientAcpiTemplate,
+ &mTcgServerAcpiTemplate,
+ 0,
+ NULL,
+ NULL
+};
+
+/**
+ Initialize the Event Log and log events passed from the PEI phase.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+
+**/
+EFI_STATUS
+EFIAPI
+SetupEventLog (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ TCG_PCR_EVENT *TcgEvent;
+ EFI_PEI_HOB_POINTERS GuidHob;
+ EFI_PHYSICAL_ADDRESS Lasa;
+
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+ Lasa = mTcgClientAcpiTemplate.Lasa;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE),
+ &Lasa
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mTcgClientAcpiTemplate.Lasa = Lasa;
+ //
+ // To initialize them as 0xFF is recommended
+ // because the OS can know the last entry for that.
+ //
+ SetMem ((VOID *)(UINTN)mTcgClientAcpiTemplate.Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF);
+ mTcgClientAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;
+
+ } else {
+ Lasa = mTcgServerAcpiTemplate.Lasa;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE),
+ &Lasa
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mTcgServerAcpiTemplate.Lasa = Lasa;
+ //
+ // To initialize them as 0xFF is recommended
+ // because the OS can know the last entry for that.
+ //
+ SetMem ((VOID *)(UINTN)mTcgServerAcpiTemplate.Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF);
+ mTcgServerAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;
+ }
+
+ GuidHob.Raw = GetHobList ();
+ while (!EFI_ERROR (Status) &&
+ (GuidHob.Raw = GetNextGuidHob (&gTcgEventEntryHobGuid, GuidHob.Raw)) != NULL) {
+ TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid);
+ GuidHob.Raw = GET_NEXT_HOB (GuidHob);
+ Status = TcgDxeLogEventI (
+ &mTcgDxeData,
+ (TCG_PCR_EVENT_HDR*)TcgEvent,
+ TcgEvent->Event
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Measure and log an action string, and extend the measurement result into PCR[5].
+
+ @param[in] String A specific string that indicates an Action event.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+TcgMeasureAction (
+ IN CHAR8 *String
+ )
+{
+ TCG_PCR_EVENT_HDR TcgEvent;
+
+ TcgEvent.PCRIndex = 5;
+ TcgEvent.EventType = EV_EFI_ACTION;
+ TcgEvent.EventSize = (UINT32)AsciiStrLen (String);
+ return TcgDxeHashLogExtendEventI (
+ &mTcgDxeData,
+ (UINT8*)String,
+ TcgEvent.EventSize,
+ &TcgEvent,
+ (UINT8 *) String
+ );
+}
+
+/**
+ Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+MeasureHandoffTables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTable;
+ TCG_PCR_EVENT_HDR TcgEvent;
+ EFI_HANDOFF_TABLE_POINTERS HandoffTables;
+
+ Status = EfiGetSystemConfigurationTable (
+ &gEfiSmbiosTableGuid,
+ (VOID **) &SmbiosTable
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ASSERT (SmbiosTable != NULL);
+
+ TcgEvent.PCRIndex = 1;
+ TcgEvent.EventType = EV_EFI_HANDOFF_TABLES;
+ TcgEvent.EventSize = sizeof (HandoffTables);
+
+ HandoffTables.NumberOfTables = 1;
+ HandoffTables.TableEntry[0].VendorGuid = gEfiSmbiosTableGuid;
+ HandoffTables.TableEntry[0].VendorTable = SmbiosTable;
+
+ DEBUG ((DEBUG_INFO, "The Smbios Table starts at: 0x%x\n", SmbiosTable->TableAddress));
+ DEBUG ((DEBUG_INFO, "The Smbios Table size: 0x%x\n", SmbiosTable->TableLength));
+
+ Status = TcgDxeHashLogExtendEventI (
+ &mTcgDxeData,
+ (UINT8*)(UINTN)SmbiosTable->TableAddress,
+ SmbiosTable->TableLength,
+ &TcgEvent,
+ (UINT8*)&HandoffTables
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Measure and log Separator event, and extend the measurement result into a specific PCR.
+
+ @param[in] PCRIndex PCR index.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+MeasureSeparatorEvent (
+ IN TPM_PCRINDEX PCRIndex
+ )
+{
+ TCG_PCR_EVENT_HDR TcgEvent;
+ UINT32 EventData;
+
+ EventData = 0;
+ TcgEvent.PCRIndex = PCRIndex;
+ TcgEvent.EventType = EV_SEPARATOR;
+ TcgEvent.EventSize = (UINT32)sizeof (EventData);
+ return TcgDxeHashLogExtendEventI (
+ &mTcgDxeData,
+ (UINT8 *)&EventData,
+ sizeof (EventData),
+ &TcgEvent,
+ (UINT8 *)&EventData
+ );
+}
+
+/**
+ Read an EFI Variable.
+
+ This function allocates a buffer to return the contents of the variable. The caller is
+ responsible for freeing the buffer.
+
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[out] VarSize The size of the variable data.
+
+ @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.
+
+**/
+VOID *
+EFIAPI
+ReadVariable (
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VarSize
+ )
+{
+ EFI_STATUS Status;
+ VOID *VarData;
+
+ *VarSize = 0;
+ Status = gRT->GetVariable (
+ VarName,
+ VendorGuid,
+ NULL,
+ VarSize,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return NULL;
+ }
+
+ VarData = AllocatePool (*VarSize);
+ if (VarData != NULL) {
+ Status = gRT->GetVariable (
+ VarName,
+ VendorGuid,
+ NULL,
+ VarSize,
+ VarData
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (VarData);
+ VarData = NULL;
+ *VarSize = 0;
+ }
+ }
+ return VarData;
+}
+
+/**
+ Measure and log an EFI variable, and extend the measurement result into a specific PCR.
+
+ @param[in] PCRIndex PCR Index.
+ @param[in] EventType Event type.
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[in] VarData The content of the variable data.
+ @param[in] VarSize The size of the variable data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+MeasureVariable (
+ IN TPM_PCRINDEX PCRIndex,
+ IN TCG_EVENTTYPE EventType,
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VendorGuid,
+ IN VOID *VarData,
+ IN UINTN VarSize
+ )
+{
+ EFI_STATUS Status;
+ TCG_PCR_EVENT_HDR TcgEvent;
+ UINTN VarNameLength;
+ EFI_VARIABLE_DATA *VarLog;
+
+ VarNameLength = StrLen (VarName);
+ TcgEvent.PCRIndex = PCRIndex;
+ TcgEvent.EventType = EventType;
+ TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
+ - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
+
+ VarLog = (EFI_VARIABLE_DATA*)AllocatePool (TcgEvent.EventSize);
+ if (VarLog == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ VarLog->VariableName = *VendorGuid;
+ VarLog->UnicodeNameLength = VarNameLength;
+ VarLog->VariableDataLength = VarSize;
+ CopyMem (
+ VarLog->UnicodeName,
+ VarName,
+ VarNameLength * sizeof (*VarName)
+ );
+ CopyMem (
+ (CHAR16 *)VarLog->UnicodeName + VarNameLength,
+ VarData,
+ VarSize
+ );
+
+ Status = TcgDxeHashLogExtendEventI (
+ &mTcgDxeData,
+ (UINT8*)VarData,
+ VarSize,
+ &TcgEvent,
+ (UINT8*)VarLog
+ );
+ FreePool (VarLog);
+ return Status;
+}
+
+/**
+ Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
+
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[out] VarSize The size of the variable data.
+ @param[out] VarData Pointer to the content of the variable.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+ReadAndMeasureBootVariable (
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VarSize,
+ OUT VOID **VarData
+ )
+{
+ EFI_STATUS Status;
+
+ *VarData = ReadVariable (VarName, VendorGuid, VarSize);
+ if (*VarData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = MeasureVariable (
+ 5,
+ EV_EFI_VARIABLE_BOOT,
+ VarName,
+ VendorGuid,
+ *VarData,
+ *VarSize
+ );
+ return Status;
+}
+
+/**
+ Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
+
+ The EFI boot variables are BootOrder and Boot#### variables.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+MeasureAllBootVariables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT16 *BootOrder;
+ UINTN BootCount;
+ UINTN Index;
+ VOID *BootVarData;
+ UINTN Size;
+
+ Status = ReadAndMeasureBootVariable (
+ mBootVarName,
+ &gEfiGlobalVariableGuid,
+ &BootCount,
+ (VOID **) &BootOrder
+ );
+ if (Status == EFI_NOT_FOUND) {
+ return EFI_SUCCESS;
+ }
+ ASSERT (BootOrder != NULL);
+
+ if (EFI_ERROR (Status)) {
+ FreePool (BootOrder);
+ return Status;
+ }
+
+ BootCount /= sizeof (*BootOrder);
+ for (Index = 0; Index < BootCount; Index++) {
+ UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);
+ Status = ReadAndMeasureBootVariable (
+ mBootVarName,
+ &gEfiGlobalVariableGuid,
+ &Size,
+ &BootVarData
+ );
+ if (!EFI_ERROR (Status)) {
+ FreePool (BootVarData);
+ }
+ }
+
+ FreePool (BootOrder);
+ return EFI_SUCCESS;
+}
+
+/**
+ Ready to Boot Event notification handler.
+
+ Sequence of OS boot events is measured in this event notification handler.
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ TPM_PCRINDEX PcrIndex;
+
+ if (mBootAttempts == 0) {
+
+ //
+ // Measure handoff tables.
+ //
+ Status = MeasureHandoffTables ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));
+ }
+
+ //
+ // Measure BootOrder & Boot#### variables.
+ //
+ Status = MeasureAllBootVariables ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));
+ }
+
+ //
+ // 1. This is the first boot attempt.
+ //
+ Status = TcgMeasureAction (
+ EFI_CALLING_EFI_APPLICATION
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // 2. Draw a line between pre-boot env and entering post-boot env.
+ //
+ for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
+ Status = MeasureSeparatorEvent (PcrIndex);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // 3. Measure GPT. It would be done in SAP driver.
+ //
+
+ //
+ // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
+ //
+
+ //
+ // 5. Read & Measure variable. BootOrder already measured.
+ //
+ } else {
+ //
+ // 6. Not first attempt, meaning a return from last attempt
+ //
+ Status = TcgMeasureAction (
+ EFI_RETURNING_FROM_EFI_APPLICATOIN
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ DEBUG ((EFI_D_INFO, "TPM TcgDxe Measure Data when ReadyToBoot\n"));
+ //
+ // Increase boot attempt counter.
+ //
+ mBootAttempts++;
+}
+
+/**
+ Install TCG ACPI Table when ACPI Table Protocol is available.
+
+ A system¡¯s firmware uses an ACPI table to identify the system's TCG capabilities
+ to the Post-Boot environment. The information in this ACPI table is not guaranteed
+ to be valid until the Host Platform transitions from pre-boot state to post-boot state.
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+**/
+VOID
+EFIAPI
+InstallAcpiTable (
+ IN EFI_EVENT Event,
+ IN VOID* Context
+ )
+{
+ UINTN TableKey;
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ UINT8 Checksum;
+
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
+
+ //
+ // The ACPI table must be checksumed before calling the InstallAcpiTable()
+ // service of the ACPI table protocol to install it.
+ //
+ Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));
+ mTcgClientAcpiTemplate.Header.Checksum = Checksum;
+
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ &mTcgClientAcpiTemplate,
+ sizeof (mTcgClientAcpiTemplate),
+ &TableKey
+ );
+ } else {
+
+ //
+ // The ACPI table must be checksumed before calling the InstallAcpiTable()
+ // service of the ACPI table protocol to install it.
+ //
+ Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));
+ mTcgServerAcpiTemplate.Header.Checksum = Checksum;
+
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ &mTcgServerAcpiTemplate,
+ sizeof (mTcgServerAcpiTemplate),
+ &TableKey
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Exit Boot Services Event notification handler.
+
+ Measure invocation and success of ExitBootServices.
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+
+**/
+VOID
+EFIAPI
+OnExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Measure invocation of ExitBootServices,
+ //
+ Status = TcgMeasureAction (
+ EFI_EXIT_BOOT_SERVICES_INVOCATION
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Measure success of ExitBootServices
+ //
+ Status = TcgMeasureAction (
+ EFI_EXIT_BOOT_SERVICES_SUCCEEDED
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Get TPM Deactivated state.
+
+ @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+GetTpmStatus (
+ OUT BOOLEAN *TPMDeactivatedFlag
+ )
+{
+ EFI_STATUS Status;
+ TPM_STCLEAR_FLAGS VFlags;
+
+ Status = TpmCommGetFlags (
+ mTcgDxeData.TpmHandle,
+ TPM_CAP_FLAG_VOLATILE,
+ &VFlags,
+ sizeof (VFlags)
+ );
+ if (!EFI_ERROR (Status)) {
+ *TPMDeactivatedFlag = VFlags.deactivated;
+ }
+
+ return Status;
+}
+
+/**
+ The driver's entry point.
+
+ It publishes EFI TCG Protocol.
+
+ @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 other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+ VOID *Registration;
+
+ mTcgDxeData.TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;
+ Status = TisPcRequestUseTpm (mTcgDxeData.TpmHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "TPM not detected!\n"));
+ return Status;
+ }
+
+ Status = GetTpmStatus (&mTcgDxeData.BsCap.TPMDeactivatedFlag);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "Line %d in file " __FILE__ ":\n "
+ "DriverEntry: TPM not working properly\n",
+ __LINE__
+ ));
+ return Status;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEfiTcgProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mTcgDxeData.TcgProtocol
+ );
+ //
+ // Install ACPI Table
+ //
+ EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);
+
+ if (!EFI_ERROR (Status) && !mTcgDxeData.BsCap.TPMDeactivatedFlag) {
+ //
+ // Setup the log area and copy event log from hob list to it
+ //
+ Status = SetupEventLog ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Measure handoff tables, Boot#### variables etc.
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ OnReadyToBoot,
+ NULL,
+ &Event
+ );
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ OnExitBootServices,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &Event
+ );
+ }
+
+ return Status;
+}
diff --git a/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf b/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
new file mode 100644
index 0000000000..95f37737c4
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
@@ -0,0 +1,70 @@
+## @file
+# Component file for module TcgDxe.
+# This module will produce TCG protocol and measure boot environment.
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TcgDxe
+ FILE_GUID = A5683620-7998-4bb2-A377-1C1E31E1E215
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DriverEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[Sources]
+ TcgDxe.c
+ TisDxe.c
+ TpmComm.c
+ TpmComm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiBootServicesTableLib
+ HobLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ TpmCommLib
+ PrintLib
+ UefiLib
+
+[Guids]
+ gEfiSmbiosTableGuid # ALWAYS_CONSUMED
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED
+ gTcgEventEntryHobGuid
+ gEfiEventReadyToBootGuid
+ gEfiEventExitBootServicesGuid
+
+[Protocols]
+ gEfiTcgProtocolGuid ## PRODUCES
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass
+
+[Depex]
+ TRUE
+
diff --git a/SecurityPkg/Tcg/TcgDxe/TisDxe.c b/SecurityPkg/Tcg/TcgDxe/TisDxe.c
new file mode 100644
index 0000000000..635ff77e13
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgDxe/TisDxe.c
@@ -0,0 +1,432 @@
+/** @file
+ TIS (TPM Interface Specification) functions used by TPM Dxe driver.
+
+Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Tpm12.h>
+#include <Library/TimerLib.h>
+#include <Library/TpmCommLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+
+STATIC UINT8 TpmCommandBuf[TPMCMDBUFLENGTH];
+
+/**
+ Send command to TPM for execution.
+
+ @param[in] TisReg TPM register space base address.
+ @param[in] TpmBuffer Buffer for TPM command data.
+ @param[in] DataLength TPM command data length.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+
+**/
+EFI_STATUS
+TisPcSend (
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ IN UINT8 *TpmBuffer,
+ IN UINT32 DataLength
+ )
+{
+ UINT16 BurstCount;
+ UINT32 Index;
+ EFI_STATUS Status;
+
+ Status = TisPcPrepareCommand (TisReg);
+ if (EFI_ERROR (Status)){
+ DEBUG ((DEBUG_ERROR, "The Tpm not ready!\n"));
+ return Status;
+ }
+ Index = 0;
+ while (Index < DataLength) {
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status)) {
+ return EFI_TIMEOUT;
+ }
+ for (; BurstCount > 0 && Index < DataLength; BurstCount--) {
+ MmioWrite8 ((UINTN) &TisReg->DataFifo, *(TpmBuffer + Index));
+ Index++;
+ }
+ }
+ //
+ // Ensure the Tpm status STS_EXPECT change from 1 to 0
+ //
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Status,
+ (UINT8) TIS_PC_VALID,
+ TIS_PC_STS_EXPECT,
+ TIS_TIMEOUT_C
+ );
+ return Status;
+}
+
+/**
+ Receive response data of last command from TPM.
+
+ @param[in] TisReg TPM register space base address.
+ @param[out] TpmBuffer Buffer for response data.
+ @param[out] RespSize Response data length.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+ @retval EFI_DEVICE_ERROR Unexpected device status.
+ @retval EFI_BUFFER_TOO_SMALL Response data is too long.
+
+**/
+EFI_STATUS
+TisPcReceive (
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ OUT UINT8 *TpmBuffer,
+ OUT UINT32 *RespSize
+ )
+{
+ EFI_STATUS Status;
+ UINT16 BurstCount;
+ UINT32 Index;
+ UINT32 ResponseSize;
+ UINT32 Data32;
+
+ //
+ // Wait for the command completion
+ //
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Status,
+ (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),
+ 0,
+ TIS_TIMEOUT_B
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read the response data header and check it
+ //
+ Index = 0;
+ BurstCount = 0;
+ while (Index < sizeof (TPM_RSP_COMMAND_HDR)) {
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status)) {
+ return EFI_TIMEOUT;
+ }
+ for (; BurstCount > 0 ; BurstCount--) {
+ *(TpmBuffer + Index) = MmioRead8 ((UINTN) &TisReg->DataFifo);
+ Index++;
+ if (Index == sizeof (TPM_RSP_COMMAND_HDR))
+ break;
+ }
+ }
+ //
+ // Check the reponse data header (tag,parasize and returncode )
+ //
+ CopyMem (&Data32, (TpmBuffer + 2), sizeof (UINT32));
+ ResponseSize = SwapBytes32 (Data32);
+ *RespSize = ResponseSize;
+ if (ResponseSize == sizeof (TPM_RSP_COMMAND_HDR)) {
+ return EFI_SUCCESS;
+ }
+ if (ResponseSize < sizeof (TPM_RSP_COMMAND_HDR)) {
+ return EFI_DEVICE_ERROR;
+ }
+ if (ResponseSize > TPMCMDBUFLENGTH) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Continue reading the remaining data
+ //
+ while (Index < ResponseSize) {
+ for (; BurstCount > 0 ; BurstCount--) {
+ *(TpmBuffer + Index) = MmioRead8 ((UINTN) &TisReg->DataFifo);
+ Index++;
+ if (Index == ResponseSize) {
+ return EFI_SUCCESS;
+ }
+ }
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status) && (Index < ResponseSize)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Format TPM command data according to the format control character.
+
+ @param[in] FmtChar Format control character.
+ @param[in, out] ap List of arguments.
+ @param[in] TpmBuffer Buffer for TPM command data.
+ @param[out] DataLength TPM command data length.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid format control character.
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.
+
+**/
+EFI_STATUS
+TisPcSendV (
+ IN UINT8 FmtChar,
+ IN OUT VA_LIST *ap,
+ UINT8 *TpmBuffer,
+ UINT32 *DataLength
+ )
+{
+ UINT8 DataByte;
+ UINT16 DataWord;
+ UINT32 DataDword;
+ TPM_RQU_COMMAND_HDR TpmCmdHdr;
+ TPM_RQU_COMMAND_HDR *TpmCmdPtr;
+ UINTN Size;
+ UINT8 *Raw;
+
+ switch (FmtChar) {
+
+ case 'b':
+ DataByte = VA_ARG (*ap, UINT8);
+ Raw = &DataByte;
+ Size = sizeof (DataByte);
+ break;
+
+ case 'w':
+ DataWord = VA_ARG (*ap, UINT16);
+ DataWord = SwapBytes16 (DataWord);
+ Raw = (UINT8*)&DataWord;
+ Size = sizeof (DataWord);
+ break;
+
+ case 'd':
+ DataDword = VA_ARG (*ap, UINT32);
+ DataDword = SwapBytes32 (DataDword);
+ Raw = (UINT8*)&DataDword;
+ Size = sizeof (DataDword);
+ break;
+
+ case 'h':
+ TpmCmdPtr = VA_ARG (*ap, TPM_RQU_COMMAND_HDR*);
+ TpmCmdHdr.tag = SwapBytes16 (TpmCmdPtr->tag);
+ TpmCmdHdr.paramSize = SwapBytes32 (TpmCmdPtr->paramSize);
+ TpmCmdHdr.ordinal = SwapBytes32 (TpmCmdPtr->ordinal);
+ Raw = (UINT8*) &TpmCmdHdr;
+ Size = sizeof (TpmCmdHdr);
+ break;
+
+ case 'r':
+ Raw = VA_ARG (*ap, UINT8*);
+ Size = VA_ARG (*ap, UINTN);
+ break;
+
+ case '\0':
+ return EFI_INVALID_PARAMETER;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if(*DataLength + (UINT32) Size > TPMCMDBUFLENGTH) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ CopyMem (TpmBuffer + *DataLength, Raw, Size);
+ *DataLength += (UINT32) Size;
+ return EFI_SUCCESS;
+}
+
+/**
+ Format reponse data according to the format control character.
+
+ @param[in] FmtChar Format control character.
+ @param[in, out] ap List of arguments.
+ @param[out] TpmBuffer Buffer for reponse data.
+ @param[in, out] DataIndex Data offset in reponse data buffer.
+ @param[in] RespSize Response data length.
+ @param[out] DataFinished Reach the end of Response data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid format control character.
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.
+
+**/
+EFI_STATUS
+TisPcReceiveV (
+ IN UINT8 FmtChar,
+ IN OUT VA_LIST *ap,
+ OUT UINT8 *TpmBuffer,
+ IN OUT UINT32 *DataIndex,
+ IN UINT32 RespSize,
+ OUT BOOLEAN *DataFinished
+ )
+{
+ UINT8 *Raw;
+ TPM_RSP_COMMAND_HDR *TpmRspPtr;
+ UINTN Size;
+
+ Raw = VA_ARG (*ap, UINT8*);
+ switch (FmtChar) {
+
+ case 'b':
+ Size = sizeof (UINT8);
+ break;
+
+ case 'w':
+ Size = sizeof (UINT16);
+ break;
+
+ case 'd':
+ Size = sizeof (UINT32);
+ break;
+
+ case 'h':
+ Size = sizeof (*TpmRspPtr);
+ break;
+
+ case 'r':
+ Size = VA_ARG (*ap, UINTN);
+ if(*DataIndex + (UINT32) Size <= RespSize) {
+ break;
+ }
+ *DataFinished = TRUE;
+ if (*DataIndex >= RespSize) {
+ return EFI_SUCCESS;
+ }
+ CopyMem (Raw, TpmBuffer + *DataIndex, RespSize - *DataIndex);
+ *DataIndex += RespSize - *DataIndex;
+ return EFI_SUCCESS;
+
+ case '\0':
+ return EFI_INVALID_PARAMETER;
+
+ default:
+ return EFI_WARN_UNKNOWN_GLYPH;
+ }
+
+ if(*DataIndex + (UINT32) Size > RespSize) {
+ *DataFinished = TRUE;
+ return EFI_SUCCESS;
+ }
+
+ if( *DataIndex + (UINT32) Size > TPMCMDBUFLENGTH )
+ return EFI_BUFFER_TOO_SMALL;
+
+ CopyMem (Raw, TpmBuffer + *DataIndex, Size);
+ *DataIndex += (UINT32) Size;
+
+ switch (FmtChar) {
+
+ case 'w':
+ *(UINT16*)Raw = SwapBytes16 (*(UINT16*) Raw);
+ break;
+
+ case 'd':
+ *(UINT32*)Raw = SwapBytes32 (*(UINT32*) Raw);
+ break;
+
+ case 'h':
+ TpmRspPtr = (TPM_RSP_COMMAND_HDR*) Raw;
+ TpmRspPtr->tag = SwapBytes16 (TpmRspPtr->tag);
+ TpmRspPtr->paramSize = SwapBytes32 (TpmRspPtr->paramSize);
+ TpmRspPtr->returnCode = SwapBytes32 (TpmRspPtr->returnCode);
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Send formatted command to TPM for execution and return formatted data from response.
+
+ @param[in] TisReg TPM Handle.
+ @param[in] Fmt Format control string.
+ @param[in] ... The variable argument list.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+
+**/
+EFI_STATUS
+EFIAPI
+TisPcExecute (
+ IN TIS_TPM_HANDLE TisReg,
+ IN CONST CHAR8 *Fmt,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Ap;
+ UINT32 BufSize;
+ UINT32 ResponseSize;
+ BOOLEAN DataFinished;
+
+ VA_START (Ap, Fmt);
+
+ //
+ // Put the formatted command to the TpmCommandBuf
+ //
+ BufSize = 0;
+ while (*Fmt != '\0') {
+ if (*Fmt == '%') Fmt++;
+ if (*Fmt == '/') break;
+ Status = TisPcSendV (*Fmt, &Ap, TpmCommandBuf, &BufSize);
+ if (EFI_ERROR( Status )) {
+ return Status;
+ }
+ Fmt++;
+ }
+ //
+ // Send the command to TPM
+ //
+ Status = TisPcSend (TisReg, TpmCommandBuf, BufSize);
+ if (EFI_ERROR (Status)) {
+ //
+ // Ensure the TPM state change from "Reception" to "Idle/Ready"
+ //
+ MmioWrite8 ((UINTN) &(((TIS_PC_REGISTERS_PTR) TisReg)->Status), TIS_PC_STS_READY);
+ return Status;
+ }
+
+ MmioWrite8 ((UINTN) &(((TIS_PC_REGISTERS_PTR) TisReg)->Status), TIS_PC_STS_GO);
+ Fmt++;
+ //
+ // Receive the response data from TPM
+ //
+ ZeroMem (TpmCommandBuf, TPMCMDBUFLENGTH);
+ Status = TisPcReceive (TisReg, TpmCommandBuf, &ResponseSize);
+ //
+ // Ensure the TPM state change from "Execution" or "Completion" to "Idle/Ready"
+ //
+ MmioWrite8 ((UINTN) &(((TIS_PC_REGISTERS_PTR) TisReg)->Status), TIS_PC_STS_READY);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the formatted data from the TpmCommandBuf.
+ //
+ BufSize =0;
+ DataFinished = FALSE;
+ while (*Fmt != '\0') {
+ if (*Fmt == '%') {
+ Fmt++;
+ }
+ Status = TisPcReceiveV (*Fmt, &Ap, TpmCommandBuf, &BufSize, ResponseSize, &DataFinished);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (DataFinished) {
+ return EFI_SUCCESS;
+ }
+ Fmt++;
+ }
+
+ VA_END (Ap);
+ return Status;
+}
+
diff --git a/SecurityPkg/Tcg/TcgDxe/TpmComm.c b/SecurityPkg/Tcg/TcgDxe/TpmComm.c
new file mode 100644
index 0000000000..c47794b4f6
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgDxe/TpmComm.c
@@ -0,0 +1,163 @@
+/** @file
+ Utility functions used by TPM Dxe driver.
+
+Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/TpmCommLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include "TpmComm.h"
+
+/**
+ Extend a TPM PCR.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] DigestToExtend The 160 bit value representing the event to be recorded.
+ @param[in] PcrIndex The PCR to be updated.
+ @param[out] NewPcrValue New PCR value after extend.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommExtend (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_DIGEST *DigestToExtend,
+ IN TPM_PCRINDEX PcrIndex,
+ OUT TPM_DIGEST *NewPcrValue
+ )
+{
+ EFI_STATUS Status;
+ TPM_DIGEST NewValue;
+ TPM_RQU_COMMAND_HDR CmdHdr;
+ TPM_RSP_COMMAND_HDR RspHdr;
+
+ if (NewPcrValue == NULL) {
+ NewPcrValue = &NewValue;
+ }
+
+ CmdHdr.tag = TPM_TAG_RQU_COMMAND;
+ CmdHdr.paramSize =
+ sizeof (CmdHdr) + sizeof (PcrIndex) + sizeof (*DigestToExtend);
+ CmdHdr.ordinal = TPM_ORD_Extend;
+ Status = TisPcExecute (
+ TpmHandle,
+ "%h%d%r%/%h%r",
+ &CmdHdr,
+ PcrIndex,
+ DigestToExtend,
+ (UINTN)sizeof (*DigestToExtend),
+ &RspHdr,
+ NewPcrValue,
+ (UINTN)sizeof (*NewPcrValue)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RspHdr.returnCode != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get TPM capability flags.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] FlagSubcap Flag subcap.
+ @param[out] FlagBuffer Pointer to the buffer for returned flag structure.
+ @param[in] FlagSize Size of the buffer.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommGetFlags (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN UINT32 FlagSubcap,
+ OUT VOID *FlagBuffer,
+ IN UINTN FlagSize
+ )
+{
+ EFI_STATUS Status;
+ TPM_RQU_COMMAND_HDR CmdHdr;
+ TPM_RSP_COMMAND_HDR RspHdr;
+ UINT32 Size;
+
+ CmdHdr.tag = TPM_TAG_RQU_COMMAND;
+ CmdHdr.paramSize = sizeof (CmdHdr) + sizeof (UINT32) * 3;
+ CmdHdr.ordinal = TPM_ORD_GetCapability;
+
+ Status = TisPcExecute (
+ TpmHandle,
+ "%h%d%d%d%/%h%d%r",
+ &CmdHdr,
+ TPM_CAP_FLAG,
+ sizeof (FlagSubcap),
+ FlagSubcap,
+ &RspHdr,
+ &Size,
+ FlagBuffer,
+ FlagSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RspHdr.returnCode != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Add a new entry to the Event Log.
+
+ @param[in, out] EventLogPtr Pointer to the Event Log data.
+ @param[in, out] LogSize Size of the Event Log.
+ @param[in] MaxSize Maximum size of the Event Log.
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS The new event log entry was added.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+
+**/
+EFI_STATUS
+TpmCommLogEvent (
+ IN OUT UINT8 **EventLogPtr,
+ IN OUT UINTN *LogSize,
+ IN UINTN MaxSize,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+ UINT32 NewLogSize;
+
+ NewLogSize = sizeof (*NewEventHdr) + NewEventHdr->EventSize;
+ if (NewLogSize + *LogSize > MaxSize) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *EventLogPtr += *LogSize;
+ *LogSize += NewLogSize;
+ CopyMem (*EventLogPtr, NewEventHdr, sizeof (*NewEventHdr));
+ CopyMem (
+ *EventLogPtr + sizeof (*NewEventHdr),
+ NewEventData,
+ NewEventHdr->EventSize
+ );
+ return EFI_SUCCESS;
+}
diff --git a/SecurityPkg/Tcg/TcgDxe/TpmComm.h b/SecurityPkg/Tcg/TcgDxe/TpmComm.h
new file mode 100644
index 0000000000..763ad76d62
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgDxe/TpmComm.h
@@ -0,0 +1,99 @@
+/** @file
+ Definitions and function prototypes used by TPM DXE driver.
+
+Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _TPM_COMM_H_
+#define _TPM_COMM_H_
+
+/**
+ Add a new entry to the Event Log.
+
+ @param[in, out] EventLogPtr Pointer to the Event Log data.
+ @param[in, out] LogSize Size of the Event Log.
+ @param[in] MaxSize Maximum size of the Event Log.
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS The new event log entry was added.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+
+**/
+EFI_STATUS
+TpmCommLogEvent (
+ IN OUT UINT8 **EventLogPtr,
+ IN OUT UINTN *LogSize,
+ IN UINTN MaxSize,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ );
+
+/**
+ Extend a TPM PCR.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] DigestToExtend The 160 bit value representing the event to be recorded.
+ @param[in] PcrIndex The PCR to be updated.
+ @param[out] NewPcrValue New PCR value after extend.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommExtend (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_DIGEST *DigestToExtend,
+ IN TPM_PCRINDEX PcrIndex,
+ OUT TPM_DIGEST *NewPcrValue
+ );
+
+/**
+ Get TPM capability flags.
+
+ @param[in] TpmHandle TPM handle.
+ @param[in] FlagSubcap Flag subcap.
+ @param[out] FlagBuffer Pointer to the buffer for returned flag structure.
+ @param[in] FlagSize Size of the buffer.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+TpmCommGetFlags (
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN UINT32 FlagSubcap,
+ OUT VOID *Buffer,
+ IN UINTN Size
+ );
+
+/**
+ Send formatted command to TPM for execution and return formatted data from response.
+
+ @param[in] TisReg TPM Handle.
+ @param[in] Fmt Format control string.
+ @param[in] ... The variable argument list.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.
+
+**/
+EFI_STATUS
+EFIAPI
+TisPcExecute (
+ IN TIS_TPM_HANDLE TisReg,
+ IN CONST CHAR8 *Fmt,
+ ...
+ );
+
+#endif // _TPM_COMM_H_
diff --git a/SecurityPkg/Tcg/TcgPei/TcgPei.c b/SecurityPkg/Tcg/TcgPei/TcgPei.c
new file mode 100644
index 0000000000..63caddec8c
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgPei/TcgPei.c
@@ -0,0 +1,593 @@
+/** @file
+ Initialize TPM device and measure FVs before handing off control to DXE.
+
+Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Ppi/LockPhysicalPresence.h>
+#include <Ppi/TpmInitialized.h>
+#include <Ppi/FirmwareVolume.h>
+#include <Guid/TcgEventHob.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/TpmCommLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+
+#include "TpmComm.h"
+
+BOOLEAN mImageInMemory = FALSE;
+
+EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiTpmInitializedPpiGuid,
+ NULL
+};
+
+/**
+ Lock physical presence if needed.
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PhysicalPresencePpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ Measure and record the Firmware Volum Information once FvInfoPPI install.
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
+ @return Others Fail to measure FV.
+
+**/
+EFI_STATUS
+EFIAPI
+FirmwareVolmeInfoPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
+ &gPeiLockPhysicalPresencePpiGuid,
+ PhysicalPresencePpiNotifyCallback
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiFirmwareVolumeInfoPpiGuid,
+ FirmwareVolmeInfoPpiNotifyCallback
+ }
+};
+
+CHAR8 mSCrtmVersion[] = "{D20BC7C6-A1A5-415c-AE85-38290AB6BE04}";
+
+EFI_PLATFORM_FIRMWARE_BLOB mMeasuredFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];
+UINT32 mMeasuredFvIndex = 0;
+
+/**
+ Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
+ and build a GUIDed HOB recording the event which will be passed to the DXE phase and
+ added into the Event Log.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] HashData Physical address of the start of the data buffer
+ to be hashed, extended, and logged.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
+ @param[in] TpmHandle TPM handle.
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+HashLogExtendEvent (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT8 *HashData,
+ IN UINTN HashDataLen,
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+ EFI_STATUS Status;
+ VOID *HobData;
+
+ HobData = NULL;
+ if (HashDataLen != 0) {
+ Status = TpmCommHashAll (
+ HashData,
+ HashDataLen,
+ &NewEventHdr->Digest
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = TpmCommExtend (
+ PeiServices,
+ TpmHandle,
+ &NewEventHdr->Digest,
+ NewEventHdr->PCRIndex,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ HobData = BuildGuidHob (
+ &gTcgEventEntryHobGuid,
+ sizeof (*NewEventHdr) + NewEventHdr->EventSize
+ );
+ if (HobData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
+ HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
+ CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
+ return EFI_SUCCESS;
+}
+
+/**
+ Measure CRTM version.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+MeasureCRTMVersion (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle
+ )
+{
+ TCG_PCR_EVENT_HDR TcgEventHdr;
+
+ //
+ // Here, only a static GUID is measured instead of real CRTM version.
+ // OEMs should get real CRTM version string and measure it.
+ //
+
+ TcgEventHdr.PCRIndex = 0;
+ TcgEventHdr.EventType = EV_S_CRTM_VERSION;
+ TcgEventHdr.EventSize = sizeof (mSCrtmVersion);
+ return HashLogExtendEvent (
+ PeiServices,
+ (UINT8*)&mSCrtmVersion,
+ TcgEventHdr.EventSize,
+ TpmHandle,
+ &TcgEventHdr,
+ (UINT8*)&mSCrtmVersion
+ );
+}
+
+/**
+ Measure FV image.
+ Add it into the measured FV list after the FV is measured successfully.
+
+ @param[in] FvBase Base address of FV image.
+ @param[in] FvLength Length of FV image.
+
+ @retval EFI_SUCCESS Fv image is measured successfully
+ or it has been already measured.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+MeasureFvImage (
+ IN EFI_PHYSICAL_ADDRESS FvBase,
+ IN UINT64 FvLength
+ )
+{
+ UINT32 Index;
+ EFI_STATUS Status;
+ EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
+ TCG_PCR_EVENT_HDR TcgEventHdr;
+ TIS_TPM_HANDLE TpmHandle;
+
+ TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS;
+
+ //
+ // Check whether FV is in the measured FV list.
+ //
+ for (Index = 0; Index < mMeasuredFvIndex; Index ++) {
+ if (mMeasuredFvInfo[Index].BlobBase == FvBase) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Measure and record the FV to the TPM
+ //
+ FvBlob.BlobBase = FvBase;
+ FvBlob.BlobLength = FvLength;
+
+ DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase));
+ DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength));
+
+ TcgEventHdr.PCRIndex = 0;
+ TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
+ TcgEventHdr.EventSize = sizeof (FvBlob);
+
+ Status = HashLogExtendEvent (
+ (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
+ (UINT8*) (UINTN) FvBlob.BlobBase,
+ (UINTN) FvBlob.BlobLength,
+ TpmHandle,
+ &TcgEventHdr,
+ (UINT8*) &FvBlob
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Add new FV into the measured FV list.
+ //
+ ASSERT (mMeasuredFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported));
+ if (mMeasuredFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {
+ mMeasuredFvInfo[mMeasuredFvIndex].BlobBase = FvBase;
+ mMeasuredFvInfo[mMeasuredFvIndex++].BlobLength = FvLength;
+ }
+
+ return Status;
+}
+
+/**
+ Measure main BIOS.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+MeasureMainBios (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FvInstances;
+ EFI_PEI_FV_HANDLE VolumeHandle;
+ EFI_FV_INFO VolumeInfo;
+ EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
+
+ FvInstances = 0;
+ while (TRUE) {
+ //
+ // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
+ // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
+ // platform for special CRTM TPM measuring.
+ //
+ Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Measure and record the firmware volume that is dispatched by PeiCore
+ //
+ Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Locate the corresponding FV_PPI according to founded FV's format guid
+ //
+ Status = PeiServicesLocatePpi (
+ &VolumeInfo.FvFormat,
+ 0,
+ NULL,
+ (VOID**)&FvPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
+ }
+
+ FvInstances++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Measure and record the Firmware Volum Information once FvInfoPPI install.
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
+ @return Others Fail to measure FV.
+
+**/
+EFI_STATUS
+EFIAPI
+FirmwareVolmeInfoPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
+ EFI_STATUS Status;
+ EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
+
+ Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
+
+ //
+ // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
+ //
+ Status = PeiServicesLocatePpi (
+ &Fv->FvFormat,
+ 0,
+ NULL,
+ (VOID**)&FvPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // This is an FV from an FFS file, and the parent FV must have already been measured,
+ // No need to measure twice, so just returns
+ //
+ if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
+ return EFI_SUCCESS;
+ }
+
+ return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
+}
+
+/**
+ Lock physical presence if needed.
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_ABORTED physicalPresenceCMDEnable is locked.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+PhysicalPresencePpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi;
+ BOOLEAN LifetimeLock;
+ BOOLEAN CmdEnable;
+ TIS_TPM_HANDLE TpmHandle;
+
+ TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS;
+ LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi;
+
+ if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Lock TPM physical presence.
+ //
+
+ Status = TpmCommGetCapability (PeiServices, TpmHandle, NULL, &LifetimeLock, &CmdEnable);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (!CmdEnable) {
+ if (LifetimeLock) {
+ //
+ // physicalPresenceCMDEnable is locked, can't change.
+ //
+ return EFI_ABORTED;
+ }
+
+ //
+ // Enable physical presence command
+ // It is necessary in order to lock physical presence
+ //
+ Status = TpmCommPhysicalPresence (
+ PeiServices,
+ TpmHandle,
+ TPM_PHYSICAL_PRESENCE_CMD_ENABLE
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Lock physical presence
+ //
+ Status = TpmCommPhysicalPresence (
+ PeiServices,
+ TpmHandle,
+ TPM_PHYSICAL_PRESENCE_LOCK
+ );
+ return Status;
+}
+
+/**
+ Check if TPM chip is activeated or not.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+
+ @retval TRUE TPM is activated.
+ @retval FALSE TPM is deactivated.
+
+**/
+BOOLEAN
+EFIAPI
+IsTpmUsable (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Deactivated;
+
+ Status = TpmCommGetCapability (PeiServices, TpmHandle, &Deactivated, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return (BOOLEAN)(!Deactivated);
+}
+
+/**
+ Do measurement after memory is ready.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimEntryMP (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ TIS_TPM_HANDLE TpmHandle;
+
+ TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;
+ Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (IsTpmUsable (PeiServices, TpmHandle)) {
+ Status = MeasureCRTMVersion (PeiServices, TpmHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = MeasureMainBios (PeiServices, TpmHandle);
+ }
+
+ //
+ // Post callbacks:
+ // 1). for the FvInfoPpi services to measure and record
+ // the additional Fvs to TPM
+ // 2). for the OperatorPresencePpi service to determine whether to
+ // lock the TPM
+ //
+ Status = PeiServicesNotifyPpi (&mNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Entry point of this module.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Describes the list of possible PEI Services.
+
+ @return Status.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimEntryMA (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ TIS_TPM_HANDLE TpmHandle;
+
+ if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = (**PeiServices).RegisterForShadow(FileHandle);
+ if (Status == EFI_ALREADY_STARTED) {
+ mImageInMemory = TRUE;
+ } else if (Status == EFI_NOT_FOUND) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (!mImageInMemory) {
+ //
+ // Initialize TPM device
+ //
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;
+ Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));
+ return Status;
+ }
+
+ Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode);
+ if (EFI_ERROR (Status) ) {
+ return Status;
+ }
+ Status = TpmCommContinueSelfTest ((EFI_PEI_SERVICES**)PeiServices, TpmHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (mImageInMemory) {
+ Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return Status;
+}
diff --git a/SecurityPkg/Tcg/TcgPei/TcgPei.inf b/SecurityPkg/Tcg/TcgPei/TcgPei.inf
new file mode 100644
index 0000000000..60a3bfa5f1
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgPei/TcgPei.inf
@@ -0,0 +1,67 @@
+## @file
+# This module will initialize TPM device and measure FVs in PEI phase.
+#
+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TcgPei
+ FILE_GUID = 2BE1E4A6-6505-43b3-9FFC-A3C8330E0432
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PeimEntryMA
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ TcgPei.c
+ TisPei.c
+ TpmComm.c
+ TpmComm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ HobLib
+ PeimEntryPoint
+ PeiServicesLib
+ BaseMemoryLib
+ DebugLib
+ TpmCommLib
+ TimerLib
+ IoLib
+ PeiServicesTablePointerLib
+
+[Guids]
+ gTcgEventEntryHobGuid
+
+[Ppis]
+ gPeiLockPhysicalPresencePpiGuid
+ gEfiPeiFirmwareVolumeInfoPpiGuid
+ gPeiTpmInitializedPpiGuid
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpm
+
+[FixedPcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported ## CONSUMES
+
+[Depex]
+ gEfiPeiMasterBootModePpiGuid AND
+ gEfiPeiReadOnlyVariable2PpiGuid
diff --git a/SecurityPkg/Tcg/TcgPei/TisPei.c b/SecurityPkg/Tcg/TcgPei/TisPei.c
new file mode 100644
index 0000000000..97d9628bda
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgPei/TisPei.c
@@ -0,0 +1,160 @@
+/** @file
+ TIS (TPM Interface Specification) functions used by TPM PEI driver.
+
+Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/TpmCommLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+
+/**
+ Send a command to TPM for execution and return response data.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TisReg TPM register space base address.
+ @param[in] BufferIn Buffer for command data.
+ @param[in] SizeIn Size of command data.
+ @param[in, out] BufferOut Buffer for response data.
+ @param[in, out] SizeOut Size of response data.
+
+ @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
+TisTpmCommand (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ IN UINT8 *BufferIn,
+ IN UINT32 SizeIn,
+ IN OUT UINT8 *BufferOut,
+ IN OUT UINT32 *SizeOut
+ )
+{
+ EFI_STATUS Status;
+ UINT16 BurstCount;
+ UINT32 Index;
+ UINT32 TpmOutSize;
+ UINT16 Data16;
+ UINT32 Data32;
+
+ Status = TisPcPrepareCommand (TisReg);
+ if (EFI_ERROR (Status)){
+ DEBUG ((DEBUG_ERROR, "Tpm is not ready for command!\n"));
+ return Status;
+ }
+ //
+ // Send the command data to Tpm
+ //
+ Index = 0;
+ while (Index < SizeIn) {
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ for (; BurstCount > 0 && Index < SizeIn; BurstCount--) {
+ MmioWrite8((UINTN)&TisReg->DataFifo, *(BufferIn + Index));
+ Index++;
+ }
+ }
+ //
+ // Check the Tpm status STS_EXPECT change from 1 to 0
+ //
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Status,
+ (UINT8) TIS_PC_VALID,
+ TIS_PC_STS_EXPECT,
+ TIS_TIMEOUT_C
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "The send buffer too small!\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Exit;
+ }
+ //
+ // Executed the TPM command and waiting for the response data ready
+ //
+ MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_GO);
+ Status = TisPcWaitRegisterBits (
+ &TisReg->Status,
+ (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),
+ 0,
+ TIS_TIMEOUT_B
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Wait for Tpm response data time out!!\n"));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ //
+ // Get response data header
+ //
+ Index = 0;
+ BurstCount = 0;
+ while (Index < sizeof (TPM_RSP_COMMAND_HDR)) {
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ for (; BurstCount > 0; BurstCount--) {
+ *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);
+ Index++;
+ if (Index == sizeof (TPM_RSP_COMMAND_HDR)) break;
+ }
+ }
+ //
+ // Check the reponse data header (tag,parasize and returncode )
+ //
+ CopyMem (&Data16, BufferOut, sizeof (UINT16));
+ if (SwapBytes16 (Data16) != TPM_TAG_RSP_COMMAND ) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));
+ TpmOutSize = SwapBytes32 (Data32);
+ if (*SizeOut < TpmOutSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Exit;
+ }
+ *SizeOut = TpmOutSize;
+ //
+ // Continue reading the remaining data
+ //
+ while ( Index < TpmOutSize ) {
+ for (; BurstCount > 0; BurstCount--) {
+ *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);
+ Index++;
+ if (Index == TpmOutSize) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+ Status = TisPcReadBurstCount (TisReg, &BurstCount);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+ }
+Exit:
+ MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);
+ return Status;
+}
+
diff --git a/SecurityPkg/Tcg/TcgPei/TpmComm.c b/SecurityPkg/Tcg/TcgPei/TpmComm.c
new file mode 100644
index 0000000000..fb5011ee9d
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgPei/TpmComm.c
@@ -0,0 +1,272 @@
+/** @file
+ Utility functions used by TPM PEI driver.
+
+Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TpmComm.h"
+
+/**
+ Send a command to TPM for execution and return response data.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TisReg TPM register space base address.
+ @param[in] BufferIn Buffer for command data.
+ @param[in] SizeIn Size of command data.
+ @param[in, out] BufferOut Buffer for response data.
+ @param[in, out] SizeOut size of response data.
+
+ @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
+TisTpmCommand (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_PC_REGISTERS_PTR TisReg,
+ IN UINT8 *BufferIn,
+ IN UINT32 SizeIn,
+ IN OUT UINT8 *BufferOut,
+ IN OUT UINT32 *SizeOut
+ );
+
+/**
+ Send TPM_Startup command to TPM.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[in] BootMode Boot mode.
+
+ @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
+TpmCommStartup (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ EFI_STATUS Status;
+ TPM_STARTUP_TYPE TpmSt;
+ UINT32 TpmRecvSize;
+ UINT32 TpmSendSize;
+ TPM_CMD_START_UP SendBuffer;
+ UINT8 RecvBuffer[20];
+
+ TpmSt = TPM_ST_CLEAR;
+ if (BootMode == BOOT_ON_S3_RESUME) {
+ TpmSt = TPM_ST_STATE;
+ }
+ //
+ // send Tpm command TPM_ORD_Startup
+ //
+ TpmRecvSize = 20;
+ TpmSendSize = sizeof (TPM_CMD_START_UP);
+ SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND);
+ SendBuffer.Hdr.paramSize = SwapBytes32 (TpmSendSize);
+ SendBuffer.Hdr.ordinal = SwapBytes32 (TPM_ORD_Startup);
+ SendBuffer.TpmSt = SwapBytes16 (TpmSt);
+ Status = TisTpmCommand (PeiServices, TpmHandle, (UINT8 *)&SendBuffer, TpmSendSize, RecvBuffer, &TpmRecvSize);
+ return Status;
+}
+
+/**
+ Send TPM_ContinueSelfTest command to TPM.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+
+ @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
+TpmCommContinueSelfTest (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TpmRecvSize;
+ UINT32 TpmSendSize;
+ TPM_CMD_SELF_TEST SendBuffer;
+ UINT8 RecvBuffer[20];
+
+ //
+ // send Tpm command TPM_ORD_ContinueSelfTest
+ //
+ TpmRecvSize = 20;
+ TpmSendSize = sizeof (TPM_CMD_SELF_TEST);
+ SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND);
+ SendBuffer.Hdr.paramSize = SwapBytes32 (TpmSendSize);
+ SendBuffer.Hdr.ordinal = SwapBytes32 (TPM_ORD_ContinueSelfTest);
+ Status = TisTpmCommand (PeiServices, TpmHandle, (UINT8 *)&SendBuffer, TpmSendSize, RecvBuffer, &TpmRecvSize);
+ return Status;
+}
+
+/**
+ Get TPM capability flags.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[out] Deactivated Returns deactivated flag.
+ @param[out] LifetimeLock Returns physicalPresenceLifetimeLock permanent flag.
+ @param[out] CmdEnable Returns physicalPresenceCMDEnable permanent flag.
+
+ @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
+TpmCommGetCapability (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ OUT BOOLEAN *Deactivated, OPTIONAL
+ OUT BOOLEAN *LifetimeLock, OPTIONAL
+ OUT BOOLEAN *CmdEnable OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TpmRecvSize;
+ UINT32 TpmSendSize;
+ TPM_CMD_GET_CAPABILITY SendBuffer;
+ UINT8 RecvBuffer[40];
+ TPM_PERMANENT_FLAGS *TpmPermanentFlags;
+
+ //
+ // send Tpm command TPM_ORD_GetCapability
+ //
+ TpmRecvSize = 40;
+ TpmSendSize = sizeof (TPM_CMD_GET_CAPABILITY);
+ SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND);
+ SendBuffer.Hdr.paramSize = SwapBytes32 (TpmSendSize);
+ SendBuffer.Hdr.ordinal = SwapBytes32 (TPM_ORD_GetCapability);
+ SendBuffer.Capability = SwapBytes32 (TPM_CAP_FLAG);
+ SendBuffer.CapabilityFlagSize = SwapBytes32 (sizeof (TPM_CAP_FLAG_PERMANENT));
+ SendBuffer.CapabilityFlag = SwapBytes32 (TPM_CAP_FLAG_PERMANENT);
+ Status = TisTpmCommand (PeiServices, TpmHandle, (UINT8 *)&SendBuffer, TpmSendSize, RecvBuffer, &TpmRecvSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TpmPermanentFlags = (TPM_PERMANENT_FLAGS *)&RecvBuffer[sizeof (TPM_RSP_COMMAND_HDR) + sizeof (UINT32)];
+ if (Deactivated != NULL) {
+ *Deactivated = TpmPermanentFlags->deactivated;
+ }
+
+ if (LifetimeLock != NULL) {
+ *LifetimeLock = TpmPermanentFlags->physicalPresenceLifetimeLock;
+ }
+
+ if (CmdEnable != NULL) {
+ *CmdEnable = TpmPermanentFlags->physicalPresenceCMDEnable;
+ }
+ return Status;
+}
+
+/**
+ Extend a TPM PCR.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[in] DigestToExtend The 160 bit value representing the event to be recorded.
+ @param[in] PcrIndex The PCR to be updated.
+ @param[out] NewPcrValue New PCR value after extend.
+
+ @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
+TpmCommExtend (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_DIGEST *DigestToExtend,
+ IN TPM_PCRINDEX PcrIndex,
+ OUT TPM_DIGEST *NewPcrValue
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TpmSendSize;
+ UINT32 TpmRecvSize;
+ TPM_CMD_EXTEND SendBuffer;
+ UINT8 RecvBuffer[10 + sizeof(TPM_DIGEST)];
+
+ //
+ // send Tpm command TPM_ORD_Extend
+ //
+ TpmRecvSize = sizeof (TPM_RSP_COMMAND_HDR) + sizeof (TPM_DIGEST);
+ TpmSendSize = sizeof (TPM_CMD_EXTEND);
+ SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND);
+ SendBuffer.Hdr.paramSize = SwapBytes32 (TpmSendSize);
+ SendBuffer.Hdr.ordinal = SwapBytes32 (TPM_ORD_Extend);
+ SendBuffer.PcrIndex = SwapBytes32 (PcrIndex);
+ CopyMem (&SendBuffer.TpmDigest, (UINT8 *)DigestToExtend, sizeof (TPM_DIGEST));
+ Status = TisTpmCommand (PeiServices, TpmHandle, (UINT8 *)&SendBuffer, TpmSendSize, RecvBuffer, &TpmRecvSize);
+ ASSERT_EFI_ERROR (Status);
+
+ if(NewPcrValue != NULL) {
+ CopyMem ((UINT8*)NewPcrValue, &RecvBuffer[10], sizeof (TPM_DIGEST));
+ }
+
+ return Status;
+}
+
+
+/**
+ Send TSC_PhysicalPresence command to TPM.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[in] PhysicalPresence The state to set the TPMs Physical Presence flags.
+
+ @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
+TpmCommPhysicalPresence (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_PHYSICAL_PRESENCE PhysicalPresence
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TpmSendSize;
+ UINT32 TpmRecvSize;
+ TPM_CMD_PHYSICAL_PRESENCE SendBuffer;
+ UINT8 RecvBuffer[10];
+
+ //
+ // send Tpm command TSC_ORD_PhysicalPresence
+ //
+ TpmRecvSize = 10;
+ TpmSendSize = sizeof (TPM_CMD_PHYSICAL_PRESENCE);
+ SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND);
+ SendBuffer.Hdr.paramSize = SwapBytes32 (TpmSendSize);
+ SendBuffer.Hdr.ordinal = SwapBytes32 (TSC_ORD_PhysicalPresence);
+ SendBuffer.PhysicalPresence = SwapBytes16 (PhysicalPresence);
+ Status = TisTpmCommand (PeiServices, TpmHandle, (UINT8 *)&SendBuffer, TpmSendSize, RecvBuffer, &TpmRecvSize);
+ return Status;
+}
diff --git a/SecurityPkg/Tcg/TcgPei/TpmComm.h b/SecurityPkg/Tcg/TcgPei/TpmComm.h
new file mode 100644
index 0000000000..52d7f2e20d
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgPei/TpmComm.h
@@ -0,0 +1,163 @@
+/** @file
+ The header file for TPM PEI driver.
+
+Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _TPM_COMM_H_
+#define _TPM_COMM_H_
+
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/TpmCommLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM_RQU_COMMAND_HDR Hdr;
+ TPM_STARTUP_TYPE TpmSt;
+} TPM_CMD_START_UP;
+
+typedef struct {
+ TPM_RQU_COMMAND_HDR Hdr;
+} TPM_CMD_SELF_TEST;
+
+typedef struct {
+ TPM_RQU_COMMAND_HDR Hdr;
+ UINT32 Capability;
+ UINT32 CapabilityFlagSize;
+ UINT32 CapabilityFlag;
+} TPM_CMD_GET_CAPABILITY;
+
+typedef struct {
+ TPM_RQU_COMMAND_HDR Hdr;
+ TPM_PCRINDEX PcrIndex;
+ TPM_DIGEST TpmDigest;
+} TPM_CMD_EXTEND;
+
+typedef struct {
+ TPM_RQU_COMMAND_HDR Hdr;
+ TPM_PHYSICAL_PRESENCE PhysicalPresence;
+} TPM_CMD_PHYSICAL_PRESENCE;
+
+#pragma pack()
+
+/**
+ Send TPM_Startup command to TPM.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[in] BootMode Boot mode.
+
+ @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
+TpmCommStartup (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN EFI_BOOT_MODE BootMode
+ );
+
+/**
+ Send TPM_ContinueSelfTest command to TPM.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+
+ @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
+TpmCommContinueSelfTest (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle
+ );
+
+/**
+ Get TPM capability flags.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[out] Deactivated Returns deactivated flag.
+ @param[out] LifetimeLock Returns physicalPresenceLifetimeLock permanent flag.
+ @param[out] CmdEnable Returns physicalPresenceCMDEnable permanent flag.
+
+ @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
+TpmCommGetCapability (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ OUT BOOLEAN *Deactivated, OPTIONAL
+ OUT BOOLEAN *LifetimeLock, OPTIONAL
+ OUT BOOLEAN *CmdEnable OPTIONAL
+ );
+
+/**
+ Extend a TPM PCR.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[in] DigestToExtend The 160 bit value representing the event to be recorded.
+ @param[in] PcrIndex The PCR to be updated.
+ @param[out] NewPcrValue New PCR value after extend.
+
+ @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
+TpmCommExtend (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_DIGEST *DigestToExtend,
+ IN TPM_PCRINDEX PcrIndex,
+ OUT TPM_DIGEST *NewPcrValue
+ );
+
+
+/**
+ Send TSC_PhysicalPresence command to TPM.
+
+ @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] TpmHandle TPM handle.
+ @param[in] PhysicalPresence The state to set the TPMs Physical Presence flags.
+
+ @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
+TpmCommPhysicalPresence (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN TIS_TPM_HANDLE TpmHandle,
+ IN TPM_PHYSICAL_PRESENCE PhysicalPresence
+ );
+
+#endif // _TPM_COMM_H_
diff --git a/SecurityPkg/Tcg/TcgSmm/TcgSmm.c b/SecurityPkg/Tcg/TcgSmm/TcgSmm.c
new file mode 100644
index 0000000000..9116944081
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgSmm/TcgSmm.c
@@ -0,0 +1,455 @@
+/** @file
+ It updates TPM items in ACPI table and registers SMI callback
+ functions for physical presence and ClearMemory.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <Guid/PhysicalPresenceData.h>
+#include <Guid/MemoryOverwriteControl.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SmmVariable.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>
+
+//
+// AML parsing definitions
+//
+#define AML_OPREGION_OP 0x80
+#define AML_BYTE_PREFIX 0x0A
+#define AML_DWORD_PREFIX 0x0C
+
+#pragma pack(1)
+typedef struct {
+ UINT8 SoftwareSmi;
+ UINT32 Parameter;
+ UINT32 Response;
+ UINT32 Request;
+ UINT32 LastRequest;
+ UINT32 ReturnCode;
+} PHYSICAL_PRESENCE_NVS;
+
+typedef struct {
+ UINT8 SoftwareSmi;
+ UINT32 Parameter;
+ UINT32 Request;
+} MEMORY_CLEAR_NVS;
+
+typedef struct {
+ PHYSICAL_PRESENCE_NVS PhysicalPresence;
+ MEMORY_CLEAR_NVS MemoryClear;
+} 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()
+
+EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
+TCG_NVS *mTcgNvs;
+
+/**
+ Software SMI callback for TPM physical presence which is called from ACPI method.
+
+ @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
+ )
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ EFI_PHYSICAL_PRESENCE PpData;
+ UINT8 Flags;
+ BOOLEAN RequestConfirmed;
+
+ //
+ // Get the Physical Presence variable
+ //
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = mSmmVariable->SmmGetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &PpData
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((EFI_D_INFO, "[TPM] PP callback, Parameter = %x\n", mTcgNvs->PhysicalPresence.Parameter));
+ if (mTcgNvs->PhysicalPresence.Parameter == 5) {
+ //
+ // Return TPM Operation Response to OS Environment
+ //
+ mTcgNvs->PhysicalPresence.LastRequest = PpData.LastPPRequest;
+ mTcgNvs->PhysicalPresence.Response = PpData.PPResponse;
+
+ } else if ((mTcgNvs->PhysicalPresence.Parameter == 2) || (mTcgNvs->PhysicalPresence.Parameter == 7)) {
+ //
+ // Submit TPM Operation Request to Pre-OS Environment
+ //
+
+ if (mTcgNvs->PhysicalPresence.Request == SET_OPERATOR_AUTH) {
+ //
+ // This command requires UI to prompt user for Auth data, NOT implemented.
+ //
+ mTcgNvs->PhysicalPresence.ReturnCode = 1;
+ return EFI_SUCCESS;
+ }
+
+ if (PpData.PPRequest != mTcgNvs->PhysicalPresence.Request) {
+ PpData.PPRequest = (UINT8) mTcgNvs->PhysicalPresence.Request;
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
+ Status = mSmmVariable->SmmSetVariable (
+ PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiPhysicalPresenceGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ &PpData
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // General failure.
+ //
+ mTcgNvs->PhysicalPresence.ReturnCode = 2;
+ return EFI_SUCCESS;
+ }
+ mTcgNvs->PhysicalPresence.ReturnCode = 0;
+ } else if (mTcgNvs->PhysicalPresence.Parameter == 8) {
+ //
+ // Get User Confirmation Status for Operation
+ //
+ Flags = PpData.Flags;
+ RequestConfirmed = FALSE;
+
+ switch (mTcgNvs->PhysicalPresence.Request) {
+ case ENABLE:
+ case DISABLE:
+ case ACTIVATE:
+ case DEACTIVATE:
+ case ENABLE_ACTIVATE:
+ case DEACTIVATE_DISABLE:
+ case SET_OWNER_INSTALL_TRUE:
+ case SET_OWNER_INSTALL_FALSE:
+ case ENABLE_ACTIVATE_OWNER_TRUE:
+ case DEACTIVATE_DISABLE_OWNER_FALSE:
+ if ((Flags & FLAG_NO_PPI_PROVISION) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case CLEAR:
+ case ENABLE_ACTIVATE_CLEAR:
+ if ((Flags & FLAG_NO_PPI_CLEAR) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
+ if ((Flags & FLAG_NO_PPI_MAINTENANCE) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
+ case CLEAR_ENABLE_ACTIVATE:
+ if ((Flags & FLAG_NO_PPI_CLEAR) != 0 && (Flags & FLAG_NO_PPI_PROVISION) != 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case SET_NO_PPI_PROVISION_FALSE:
+ case SET_NO_PPI_CLEAR_FALSE:
+ case SET_NO_PPI_MAINTENANCE_FALSE:
+ case NO_ACTION:
+ RequestConfirmed = TRUE;
+ break;
+
+ case SET_OPERATOR_AUTH:
+ //
+ // This command requires UI to prompt user for Auth data
+ // Here it is NOT implemented
+ //
+ mTcgNvs->PhysicalPresence.ReturnCode = 0;
+ return EFI_SUCCESS;
+ }
+
+ if (RequestConfirmed) {
+ //
+ // Allowed and physically present user not required
+ //
+ mTcgNvs->PhysicalPresence.ReturnCode = 4;
+ } else {
+ //
+ // Allowed and physically present user required
+ //
+ mTcgNvs->PhysicalPresence.ReturnCode = 3;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Software SMI callback for MemoryClear which is called from ACPI method.
+
+ @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;
+
+ if (mTcgNvs->MemoryClear.Parameter == 1) {
+ //
+ // Called from ACPI _DSM method, save the MOR data to variable.
+ //
+ MorControl = (UINT8) mTcgNvs->MemoryClear.Request;
+ } else if (mTcgNvs->MemoryClear.Parameter == 2) {
+ //
+ // Called from ACPI _PTS method, setup ClearMemory flags if needed.
+ //
+ DataSize = sizeof (UINT8);
+ Status = mSmmVariable->SmmGetVariable (
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ &gEfiMemoryOverwriteControlDataGuid,
+ NULL,
+ &DataSize,
+ &MorControl
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status == EFI_NOT_FOUND);
+ 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
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Find the operation region in TCG ACPI table by given Name and Size,
+ and initialize it if the region is found.
+
+ @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_OPREGION_OP) &&
+ (OpRegion->NameString == Name) &&
+ (OpRegion->RegionLen == Size) &&
+ (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;
+ break;
+ }
+ }
+
+ return (VOID *) (UINTN) MemoryAddress;
+}
+
+/**
+ 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;
+
+ Status = GetSectionFromFv (
+ &gEfiCallerIdGuid,
+ EFI_SECTION_RAW,
+ 0,
+ (VOID **) &Table,
+ &TableSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'c', 'g', 'T', 'a', 'b', 'l', 'e'));
+ mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), sizeof (TCG_NVS));
+ ASSERT (mTcgNvs != NULL);
+
+ //
+ // Publish the TPM ACPI table
+ //
+ 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;
+}
+
+/**
+ 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;
+
+ 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;
+
+ SwContext.SwSmiInputValue = (UINTN) -1;
+ Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
+
+ //
+ // Locate SmmVariableProtocol.
+ //
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/Tcg/TcgSmm/TcgSmm.inf b/SecurityPkg/Tcg/TcgSmm/TcgSmm.inf
new file mode 100644
index 0000000000..c8e7092e73
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgSmm/TcgSmm.inf
@@ -0,0 +1,56 @@
+## @file
+# This driver implements TPM definition block in ACPI table and
+# registers SMI callback functions for physical presence and
+# MemoryClear to handle the requests from ACPI method.
+#
+# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TcgSmm
+ FILE_GUID = 42293093-76B9-4482-8C02-3BEFDEA9B35D
+ MODULE_TYPE = DXE_SMM_DRIVER
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeTcgSmm
+
+[Sources]
+ TcgSmm.c
+ Tpm.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ SmmServicesTableLib
+ UefiBootServicesTableLib
+ DebugLib
+ DxeServicesLib
+
+[Guids]
+ gEfiPhysicalPresenceGuid
+ gEfiMemoryOverwriteControlDataGuid
+
+[Protocols]
+ gEfiSmmSwDispatch2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmmVariableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+ gEfiAcpiTableProtocolGuid AND
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiSmmVariableProtocolGuid AND
+ gEfiTcgProtocolGuid \ No newline at end of file
diff --git a/SecurityPkg/Tcg/TcgSmm/Tpm.asl b/SecurityPkg/Tcg/TcgSmm/Tpm.asl
new file mode 100644
index 0000000000..000fc661a9
--- /dev/null
+++ b/SecurityPkg/Tcg/TcgSmm/Tpm.asl
@@ -0,0 +1,354 @@
+/** @file
+ The TPM definition block in ACPI table for physical presence
+ and MemoryClear.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+DefinitionBlock (
+ "Tpm.aml",
+ "SSDT",
+ 1,
+ "Intel_",
+ "TcgTable",
+ 0x1000
+ )
+{
+ Scope (\_SB)
+ {
+ Device (TPM)
+ {
+ //
+ // Define _HID, "PNP0C31" is defined in
+ // "Secure Startup-FVE and TPM Admin BIOS and Platform Requirements"
+ //
+ Name (_HID, EISAID ("PNP0C31"))
+
+ //
+ // Readable name of this device, don't know if this way is correct yet
+ //
+ Name (_STR, Unicode ("TPM 1.2 Device"))
+
+ //
+ // Return the resource consumed by TPM device
+ //
+ Name (_CRS, ResourceTemplate () {
+ Memory32Fixed (ReadOnly, 0xfed40000, 0x5000)
+ })
+
+ //
+ // Operational region for Smi port access
+ //
+ OperationRegion (SMIP, SystemIO, 0xB2, 1)
+ Field (SMIP, ByteAcc, NoLock, Preserve)
+ {
+ IOB2, 8
+ }
+
+ //
+ // Operational region for TPM access
+ //
+ OperationRegion (TPMR, SystemMemory, 0xfed40000, 0x5000)
+ Field (TPMR, AnyAcc, NoLock, Preserve)
+ {
+ ACC0, 8,
+ }
+
+ //
+ // Operational region for TPM support, TPM Physical Presence and TPM Memory Clear
+ // Region Offset to be fixed at runtime
+ //
+ OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0x1E)
+ 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
+ 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
+ }
+
+ 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)))
+ {
+ //
+ // Triggle the SMI through ACPI _PTS method.
+ //
+ Store (0x02, MCIP)
+
+ //
+ // Triggle the SMI interrupt
+ //
+ Store (MCIN, IOB2)
+ }
+ }
+ Return (0)
+ }
+
+ Method (_STA, 0)
+ {
+ if (LEqual (ACC0, 0xff))
+ {
+ Return (0)
+ }
+ Return (0x0f)
+ }
+
+ //
+ // TCG Hardware Information
+ //
+ Method (HINF, 3, Serialized, 0, {BuffObj, PkgObj}, {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 () {ToBCD (1), ToBCD (20)}})
+ 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}, {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 ("1.2")
+ }
+ Case (2)
+ {
+ //
+ // b) Submit TPM Operation Request to Pre-OS Environment
+ //
+
+ Store (DerefOf (Index (Arg2, 0x00)), PPRQ)
+ Store (0x02, PPIP)
+
+ //
+ // Triggle the SMI interrupt
+ //
+ Store (PPIN, IOB2)
+ 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)
+
+ //
+ // Triggle the SMI interrupt
+ //
+ Store (PPIN, IOB2)
+
+ 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)
+
+ //
+ // Triggle the SMI interrupt
+ //
+ Store (PPIN, IOB2)
+ Return (FRET)
+ }
+ Case (8)
+ {
+ //
+ // e) Get User Confirmation Status for Operation
+ //
+ Store (8, PPIP)
+ Store (DerefOf (Index (Arg2, 0x00)), PPRQ)
+
+ //
+ // Triggle the SMI interrupt
+ //
+ Store (PPIN, IOB2)
+
+ Return (FRET)
+ }
+
+ Default {BreakPoint}
+ }
+ Return (1)
+ }
+
+ Method (TMCI, 3, Serialized, 0, IntObj, {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)
+
+ //
+ // Triggle the SMI through ACPI _DSM method.
+ //
+ Store (0x01, MCIP)
+
+ //
+ // Triggle the SMI interrupt
+ //
+ Store (MCIN, IOB2)
+ 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))
+ }
+
+ Return (Buffer () {0})
+ }
+ }
+ }
+}