]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add TPM2 implementation.
authorjyao1 <jyao1>
Wed, 18 Sep 2013 05:31:18 +0000 (05:31 +0000)
committerjyao1 <jyao1@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 18 Sep 2013 05:31:18 +0000 (05:31 +0000)
signed off by: jiewen.yao@intel.com
reviewed by: guo.dong@intel.com

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14687 6f19259b-4bc3-4df7-8a09-765794883524

98 files changed:
SecurityPkg/Include/Guid/TpmInstance.h [new file with mode: 0644]
SecurityPkg/Include/Guid/TrEEConfigHii.h [new file with mode: 0644]
SecurityPkg/Include/Guid/TrEEPhysicalPresenceData.h [new file with mode: 0644]
SecurityPkg/Include/Library/HashLib.h [new file with mode: 0644]
SecurityPkg/Include/Library/Tpm12CommandLib.h [new file with mode: 0644]
SecurityPkg/Include/Library/Tpm12DeviceLib.h [new file with mode: 0644]
SecurityPkg/Include/Library/Tpm2CommandLib.h [new file with mode: 0644]
SecurityPkg/Include/Library/Tpm2DeviceLib.h [new file with mode: 0644]
SecurityPkg/Include/Library/TrEEPhysicalPresenceLib.h [new file with mode: 0644]
SecurityPkg/Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h [new file with mode: 0644]
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
SecurityPkg/Library/DxeImageVerificationLib/Measurement.c [new file with mode: 0644]
SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c [new file with mode: 0644]
SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf [new file with mode: 0644]
SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c
SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.c [new file with mode: 0644]
SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf [new file with mode: 0644]
SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/PhysicalPresenceStrings.uni [new file with mode: 0644]
SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.c [new file with mode: 0644]
SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf [new file with mode: 0644]
SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.c [new file with mode: 0644]
SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf [new file with mode: 0644]
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.c [new file with mode: 0644]
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.h [new file with mode: 0644]
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c [new file with mode: 0644]
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf [new file with mode: 0644]
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c [new file with mode: 0644]
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf [new file with mode: 0644]
SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c [new file with mode: 0644]
SecurityPkg/Library/HashLibTpm2/HashLibTpm2.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm12CommandLib/Tpm12Ownership.c [new file with mode: 0644]
SecurityPkg/Library/Tpm12CommandLib/Tpm12Startup.c [new file with mode: 0644]
SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c [new file with mode: 0644]
SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c [new file with mode: 0644]
SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2CommandLib/Tpm2Test.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Tis.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.inf [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.c [new file with mode: 0644]
SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf [new file with mode: 0644]
SecurityPkg/SecurityPkg.dec
SecurityPkg/SecurityPkg.dsc
SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf
SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c
SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf
SecurityPkg/Tcg/TcgDxe/TcgDxe.c
SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
SecurityPkg/Tcg/TcgPei/TcgPei.c
SecurityPkg/Tcg/TcgPei/TcgPei.inf
SecurityPkg/Tcg/TcgSmm/TcgSmm.c
SecurityPkg/Tcg/TcgSmm/TcgSmm.h
SecurityPkg/Tcg/TcgSmm/TcgSmm.inf
SecurityPkg/Tcg/TrEEConfig/TpmDetection.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfig.vfr [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigDriver.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigDxe.inf [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigImpl.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigImpl.h [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigNvData.h [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigPeim.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEEConfig/TrEEConfigStrings.uni [new file with mode: 0644]
SecurityPkg/Tcg/TrEEDxe/MeasureBootPeCoff.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEEDxe/TrEEDxe.inf [new file with mode: 0644]
SecurityPkg/Tcg/TrEEPei/TrEEPei.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEEPei/TrEEPei.inf [new file with mode: 0644]
SecurityPkg/Tcg/TrEESmm/Tpm.asl [new file with mode: 0644]
SecurityPkg/Tcg/TrEESmm/TrEESmm.c [new file with mode: 0644]
SecurityPkg/Tcg/TrEESmm/TrEESmm.h [new file with mode: 0644]
SecurityPkg/Tcg/TrEESmm/TrEESmm.inf [new file with mode: 0644]
SecurityPkg/VariableAuthenticated/RuntimeDxe/Measurement.c [new file with mode: 0644]
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf

diff --git a/SecurityPkg/Include/Guid/TpmInstance.h b/SecurityPkg/Include/Guid/TpmInstance.h
new file mode 100644 (file)
index 0000000..27c727b
--- /dev/null
@@ -0,0 +1,38 @@
+/** @file\r
+  TPM instance guid, used for PcdTpmInstanceGuid.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __TPM_INSTANCE_GUID_H__\r
+#define __TPM_INSTANCE_GUID_H__\r
+\r
+#define TPM_DEVICE_INTERFACE_NONE  \\r
+  { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }\r
+\r
+#define TPM_DEVICE_INTERFACE_TPM12  \\r
+  { 0x8b01e5b6, 0x4f19, 0x46e8, { 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc } }\r
+\r
+#define TPM_DEVICE_INTERFACE_TPM20_DTPM  \\r
+  { 0x286bf25a, 0xc2c3, 0x408c, { 0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17 } }\r
+\r
+extern EFI_GUID  gEfiTpmDeviceInstanceNoneGuid;\r
+extern EFI_GUID  gEfiTpmDeviceInstanceTpm12Guid;\r
+extern EFI_GUID  gEfiTpmDeviceInstanceTpm20DtpmGuid;\r
+\r
+\r
+#define TPM_DEVICE_SELECTED_GUID  \\r
+  { 0x7f4158d3, 0x74d, 0x456d, { 0x8c, 0xb2, 0x1, 0xf9, 0xc8, 0xf7, 0x9d, 0xaa } }\r
+\r
+extern EFI_GUID  gEfiTpmDeviceSelectedGuid;\r
+\r
+#endif\r
+\r
diff --git a/SecurityPkg/Include/Guid/TrEEConfigHii.h b/SecurityPkg/Include/Guid/TrEEConfigHii.h
new file mode 100644 (file)
index 0000000..b5d1de7
--- /dev/null
@@ -0,0 +1,25 @@
+/** @file\r
+  GUIDs used as HII FormSet and HII Package list GUID in TrEEConfig driver. \r
+  \r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution.  \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php.                                            \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __TREE_CONFIG_HII_GUID_H__\r
+#define __TREE_CONFIG_HII_GUID_H__\r
+\r
+#define TREE_CONFIG_FORM_SET_GUID \\r
+  { \\r
+    0xc54b425f, 0xaa79, 0x48b4, { 0x98, 0x1f, 0x99, 0x8b, 0x3c, 0x4b, 0x64, 0x1c } \\r
+  }\r
+\r
+extern EFI_GUID gTrEEConfigFormSetGuid;\r
+\r
+#endif\r
diff --git a/SecurityPkg/Include/Guid/TrEEPhysicalPresenceData.h b/SecurityPkg/Include/Guid/TrEEPhysicalPresenceData.h
new file mode 100644 (file)
index 0000000..65750cd
--- /dev/null
@@ -0,0 +1,62 @@
+/** @file\r
+  Define the variable data structures used for TrEE physical presence.\r
+  The TPM2 request from firmware or OS is saved to variable. And it is\r
+  cleared after it is processed in the next boot cycle. The TPM2 response \r
+  is saved to variable.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __TREE_PHYSICAL_PRESENCE_DATA_GUID_H__\r
+#define __TREE_PHYSICAL_PRESENCE_DATA_GUID_H__\r
+\r
+#define EFI_TREE_PHYSICAL_PRESENCE_DATA_GUID \\r
+  { \\r
+    0xf24643c2, 0xc622, 0x494e, { 0x8a, 0xd, 0x46, 0x32, 0x57, 0x9c, 0x2d, 0x5b }\\r
+  }\r
+\r
+#define TREE_PHYSICAL_PRESENCE_VARIABLE  L"TrEEPhysicalPresence"\r
+\r
+typedef struct {\r
+  UINT8   PPRequest;      ///< Physical Presence request command.\r
+  UINT8   LastPPRequest;\r
+  UINT32  PPResponse;\r
+} EFI_TREE_PHYSICAL_PRESENCE;\r
+\r
+//\r
+// The definition bit of the flags\r
+//\r
+#define TREE_FLAG_NO_PPI_CLEAR                        BIT1\r
+#define TREE_FLAG_RESET_TRACK                         BIT3\r
+\r
+//\r
+// This variable is used to save TPM Management Flags and corresponding operations.\r
+// It should be protected from malicious software (e.g. Set it as read-only variable). \r
+//\r
+#define TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE  L"TrEEPhysicalPresenceFlags"\r
+\r
+//\r
+// The definition of physical presence operation actions\r
+//\r
+#define TREE_PHYSICAL_PRESENCE_NO_ACTION                               0\r
+#define TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR                     5\r
+#define TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2                   14\r
+#define TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE                  17\r
+#define TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE                   18\r
+#define TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3                   21\r
+#define TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4                   22\r
+\r
+#define TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX                           22\r
+\r
+extern EFI_GUID  gEfiTrEEPhysicalPresenceGuid;\r
+\r
+#endif\r
+\r
diff --git a/SecurityPkg/Include/Library/HashLib.h b/SecurityPkg/Include/Library/HashLib.h
new file mode 100644 (file)
index 0000000..b857569
--- /dev/null
@@ -0,0 +1,169 @@
+/** @file\r
+  Ihis library abstract TPM2 hash calculation.\r
+  The platform can choose multiply hash, while caller just need invoke these API.\r
+  Then all hash value will be returned and/or extended.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _HASH_LIB_H_\r
+#define _HASH_LIB_H_\r
+\r
+#include <Uefi.h>\r
+#include <Protocol/Hash.h>\r
+\r
+typedef UINTN  HASH_HANDLE;\r
+\r
+/**\r
+  Start hash sequence.\r
+\r
+  @param HashHandle Hash handle.\r
+\r
+  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.\r
+  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashStart (\r
+  OUT HASH_HANDLE    *HashHandle\r
+  );\r
+\r
+/**\r
+  Update hash sequence data.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence updated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashUpdate (\r
+  IN HASH_HANDLE    HashHandle,\r
+  IN VOID           *DataToHash,\r
+  IN UINTN          DataToHashLen\r
+  );\r
+\r
+/**\r
+  Hash sequence complete and extend to PCR.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashCompleteAndExtend (\r
+  IN HASH_HANDLE         HashHandle,\r
+  IN TPMI_DH_PCR         PcrIndex,\r
+  IN VOID                *DataToHash,\r
+  IN UINTN               DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES *DigestList\r
+  );\r
+\r
+/**\r
+  Hash data and extend to PCR.\r
+\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash data and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashAndExtend (\r
+  IN TPMI_DH_PCR                    PcrIndex,\r
+  IN VOID                           *DataToHash,\r
+  IN UINTN                          DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES            *DigestList\r
+  );\r
+\r
+/**\r
+  Start hash sequence.\r
+\r
+  @param HashHandle Hash handle.\r
+\r
+  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.\r
+  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *HASH_INIT) (\r
+  OUT HASH_HANDLE    *HashHandle\r
+  );\r
+\r
+/**\r
+  Update hash sequence data.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence updated.\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *HASH_UPDATE) (\r
+  IN HASH_HANDLE    HashHandle,\r
+  IN VOID           *DataToHash,\r
+  IN UINTN          DataToHashLen\r
+  );\r
+\r
+/**\r
+  Complete hash sequence complete.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *HASH_FINAL) (\r
+  IN HASH_HANDLE         HashHandle,\r
+  OUT TPML_DIGEST_VALUES *DigestList\r
+  );\r
+\r
+#define HASH_ALGORITHM_SHA1_GUID    EFI_HASH_ALGORITHM_SHA1_GUID\r
+#define HASH_ALGORITHM_SHA256_GUID  EFI_HASH_ALGORITHM_SHA256_GUID\r
+#define HASH_ALGORITHM_SHA384_GUID  EFI_HASH_ALGORITHM_SHA384_GUID\r
+#define HASH_ALGORITHM_SHA512_GUID  EFI_HASH_ALGORITHM_SHA512_GUID\r
+\r
+typedef struct {\r
+  EFI_GUID                           HashGuid;\r
+  HASH_INIT                          HashInit;\r
+  HASH_UPDATE                        HashUpdate;\r
+  HASH_FINAL                         HashFinal;\r
+} HASH_INTERFACE;\r
+\r
+/**\r
+  This service register Hash.\r
+\r
+  @param HashInterface  Hash interface\r
+\r
+  @retval EFI_SUCCESS          This hash interface is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this interface.\r
+  @retval EFI_ALREADY_STARTED  System already register this interface.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterHashInterfaceLib (\r
+  IN HASH_INTERFACE   *HashInterface\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Include/Library/Tpm12CommandLib.h b/SecurityPkg/Include/Library/Tpm12CommandLib.h
new file mode 100644 (file)
index 0000000..8b62823
--- /dev/null
@@ -0,0 +1,46 @@
+/** @file\r
+  This library is used by other modules to send TPM12 command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _TPM12_COMMAND_LIB_H_\r
+#define _TPM12_COMMAND_LIB_H_\r
+\r
+#include <IndustryStandard/Tpm12.h>\r
+\r
+/**\r
+  Send Startup command to TPM1.2.\r
+\r
+  @param TpmSt           Startup Type.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12Startup (\r
+  IN TPM_STARTUP_TYPE          TpmSt\r
+  );\r
+\r
+/**\r
+  Send ForceClear command to TPM1.2.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12ForceClear (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Include/Library/Tpm12DeviceLib.h b/SecurityPkg/Include/Library/Tpm12DeviceLib.h
new file mode 100644 (file)
index 0000000..ab1f522
--- /dev/null
@@ -0,0 +1,54 @@
+/** @file\r
+  This library abstract how to access TPM12 hardware device.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _TPM12_DEVICE_LIB_H_\r
+#define _TPM12_DEVICE_LIB_H_\r
+\r
+#include <IndustryStandard/Tpm12.h>\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM12.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM12 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM12 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM12 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM12 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  );\r
+\r
+/**\r
+  This service requests use TPM12.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM12 chip.\r
+  @retval EFI_NOT_FOUND    TPM12 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12RequestUseTpm (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Include/Library/Tpm2CommandLib.h b/SecurityPkg/Include/Library/Tpm2CommandLib.h
new file mode 100644 (file)
index 0000000..5ec3ead
--- /dev/null
@@ -0,0 +1,824 @@
+/** @file\r
+  This library is used by other modules to send TPM2 command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _TPM2_COMMAND_LIB_H_\r
+#define _TPM2_COMMAND_LIB_H_\r
+\r
+#include <IndustryStandard/Tpm20.h>\r
+\r
+/**\r
+  This command starts a hash or an Event sequence.\r
+  If hashAlg is an implemented hash, then a hash sequence is started.\r
+  If hashAlg is TPM_ALG_NULL, then an Event sequence is started.\r
+\r
+  @param[in]  HashAlg           The hash algorithm to use for the hash sequence\r
+                                An Event sequence starts if this is TPM_ALG_NULL.\r
+  @param[out] SequenceHandle    A handle to reference the sequence\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HashSequenceStart (\r
+  IN TPMI_ALG_HASH   HashAlg,\r
+  OUT TPMI_DH_OBJECT *SequenceHandle\r
+  );\r
+\r
+/**\r
+  This command is used to add data to a hash or HMAC sequence.\r
+  The amount of data in buffer may be any size up to the limits of the TPM.\r
+  NOTE: In all TPM, a buffer size of 1,024 octets is allowed.\r
+\r
+  @param[in] SequenceHandle    Handle for the sequence object\r
+  @param[in] Buffer            Data to be added to hash\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SequenceUpdate (\r
+  IN TPMI_DH_OBJECT   SequenceHandle,\r
+  IN TPM2B_MAX_BUFFER *Buffer\r
+  );\r
+\r
+/**\r
+  This command adds the last part of data, if any, to an Event sequence and returns the result in a digest list.\r
+  If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in\r
+  the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each\r
+  bank extended with the associated digest value.\r
+\r
+  @param[in]  PcrHandle         PCR to be extended with the Event data\r
+  @param[in]  SequenceHandle    Authorization for the sequence\r
+  @param[in]  Buffer            Data to be added to the Event\r
+  @param[out] Results           List of digests computed for the PCR\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2EventSequenceComplete (\r
+  IN TPMI_DH_PCR         PcrHandle,\r
+  IN TPMI_DH_OBJECT      SequenceHandle,\r
+  IN TPM2B_MAX_BUFFER    *Buffer,\r
+  OUT TPML_DIGEST_VALUES *Results\r
+  );\r
+\r
+/**\r
+  This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.\r
+\r
+  @param[in]  SequenceHandle    Authorization for the sequence\r
+  @param[in]  Buffer            Data to be added to the hash/HMAC\r
+  @param[out] Result            The returned HMAC or digest in a sized buffer\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SequenceComplete (\r
+  IN TPMI_DH_OBJECT      SequenceHandle,\r
+  IN TPM2B_MAX_BUFFER    *Buffer,\r
+  OUT TPM2B_DIGEST       *Result\r
+  );\r
+\r
+/**\r
+  Send Startup command to TPM2.\r
+\r
+  @param[in] StartupType           TPM_SU_CLEAR or TPM_SU_STATE\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2Startup (\r
+  IN      TPM_SU             StartupType\r
+  );\r
+\r
+/**\r
+  Send Shutdown command to TPM2.\r
+\r
+  @param[in] ShutdownType           TPM_SU_CLEAR or TPM_SU_STATE.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2Shutdown (\r
+  IN      TPM_SU             ShutdownType\r
+  );\r
+\r
+/**\r
+  This command causes the TPM to perform a test of its capabilities.\r
+  If the fullTest is YES, the TPM will test all functions.\r
+  If fullTest = NO, the TPM will only test those functions that have not previously been tested.\r
+\r
+  @param[in] FullTest    YES if full test to be performed\r
+                         NO if only test of untested functions required\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SelfTest (\r
+  IN TPMI_YES_NO          FullTest\r
+  );\r
+\r
+/**\r
+  This command removes all TPM context associated with a specific Owner.\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2Clear (\r
+  IN TPMI_RH_CLEAR             AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  );\r
+\r
+/**\r
+  Disables and enables the execution of TPM2_Clear().\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] Disable           YES if the disableOwnerClear flag is to be SET,\r
+                               NO if the flag is to be CLEAR.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ClearControl (\r
+  IN TPMI_RH_CLEAR             AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN TPMI_YES_NO               Disable\r
+  );\r
+\r
+/**\r
+  This command allows the authorization secret for a hierarchy or lockout to be changed using the current\r
+  authorization value as the command authorization.\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] NewAuth           New authorization secret\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HierarchyChangeAuth (\r
+  IN TPMI_RH_HIERARCHY_AUTH    AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN TPM2B_AUTH                *NewAuth\r
+  );\r
+\r
+/**\r
+  This replaces the current EPS with a value from the RNG and sets the Endorsement hierarchy controls to\r
+  their default initialization values.\r
+\r
+  @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ChangeEPS (\r
+  IN TPMI_RH_PLATFORM          AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession\r
+  );\r
+\r
+/**\r
+  This replaces the current PPS with a value from the RNG and sets platformPolicy to the default\r
+  initialization value (the Empty Buffer).\r
+\r
+  @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ChangePPS (\r
+  IN TPMI_RH_PLATFORM          AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession\r
+  );\r
+\r
+/**\r
+  This command enables and disables use of a hierarchy.\r
+\r
+  @param[in] AuthHandle        TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] Hierarchy         Hierarchy of the enable being modified\r
+  @param[in] State             YES if the enable should be SET,\r
+                               NO if the enable should be CLEAR\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HierarchyControl (\r
+  IN TPMI_RH_HIERARCHY         AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN TPMI_RH_HIERARCHY         Hierarchy,\r
+  IN TPMI_YES_NO               State\r
+  );\r
+\r
+/**\r
+  This command cancels the effect of a TPM lockout due to a number of successive authorization failures.\r
+  If this command is properly authorized, the lockout counter is set to zero.\r
+\r
+  @param[in]  LockHandle            LockHandle\r
+  @param[in]  AuthSession           Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2DictionaryAttackLockReset (\r
+  IN  TPMI_RH_LOCKOUT           LockHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession\r
+  );\r
+\r
+/**\r
+  This command cancels the effect of a TPM lockout due to a number of successive authorization failures.\r
+  If this command is properly authorized, the lockout counter is set to zero.\r
+\r
+  @param[in]  LockHandle            LockHandle\r
+  @param[in]  AuthSession           Auth Session context\r
+  @param[in]  NewMaxTries           Count of authorization failures before the lockout is imposed\r
+  @param[in]  NewRecoveryTime       Time in seconds before the authorization failure count is automatically decremented\r
+  @param[in]  LockoutRecovery       Time in seconds after a lockoutAuth failure before use of lockoutAuth is allowed\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2DictionaryAttackParameters (\r
+  IN  TPMI_RH_LOCKOUT           LockHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN  UINT32                    NewMaxTries,\r
+  IN  UINT32                    NewRecoveryTime,\r
+  IN  UINT32                    LockoutRecovery\r
+  );\r
+\r
+/**\r
+  This command is used to read the public area and Name of an NV Index.\r
+\r
+  @param[in]  NvIndex            The NV Index.\r
+  @param[out] NvPublic           The public area of the index.\r
+  @param[out] NvName             The Name of the nvIndex.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvReadPublic (\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  OUT     TPM2B_NV_PUBLIC           *NvPublic,\r
+  OUT     TPM2B_NAME                *NvName\r
+  );\r
+\r
+/**\r
+  This command defines the attributes of an NV Index and causes the TPM to\r
+  reserve space to hold the data associated with the index.\r
+  If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.\r
+  @param[in]  AuthSession        Auth Session context\r
+  @param[in]  Auth               The authorization data.\r
+  @param[in]  NvPublic           The public area of the index.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_ALREADY_STARTED    The command was returned successfully, but NvIndex is already defined.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvDefineSpace (\r
+  IN      TPMI_RH_PROVISION         AuthHandle,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN      TPM2B_AUTH                *Auth,\r
+  IN      TPM2B_NV_PUBLIC           *NvPublic\r
+  );\r
+\r
+/**\r
+  This command removes an index from the TPM.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.\r
+  @param[in]  NvIndex            The NV Index.\r
+  @param[in]  AuthSession        Auth Session context\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvUndefineSpace (\r
+  IN      TPMI_RH_PROVISION         AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  );\r
+\r
+/**\r
+  This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace().\r
+\r
+  @param[in]     AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]     NvIndex            The index to be read.\r
+  @param[in]     AuthSession        Auth Session context\r
+  @param[in]     Size               Number of bytes to read.\r
+  @param[in]     Offset             Byte offset into the area.\r
+  @param[in,out] OutData            The data read.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvRead (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN      UINT16                    Size,\r
+  IN      UINT16                    Offset,\r
+  IN OUT  TPM2B_MAX_BUFFER          *OutData\r
+  );\r
+\r
+/**\r
+  This command writes a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace().\r
+\r
+  @param[in]  AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]  NvIndex            The NV Index of the area to write.\r
+  @param[in]  AuthSession        Auth Session context\r
+  @param[in]  InData             The data to write.\r
+  @param[in]  Offset             The offset into the NV Area.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvWrite (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN      TPM2B_MAX_BUFFER          *InData,\r
+  IN      UINT16                    Offset\r
+  );\r
+\r
+/**\r
+  This command may be used to prevent further reads of the Index until the next TPM2_Startup (TPM_SU_CLEAR).\r
+\r
+  @param[in]  AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]  NvIndex            The NV Index of the area to lock.\r
+  @param[in]  AuthSession        Auth Session context\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvReadLock (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  );\r
+\r
+/**\r
+  This command may be used to inhibit further writes of the Index.\r
+\r
+  @param[in]  AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]  NvIndex            The NV Index of the area to lock.\r
+  @param[in]  AuthSession        Auth Session context\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvWriteLock (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  );\r
+\r
+/**\r
+  The command will SET TPMA_NV_WRITELOCKED for all indexes that have their TPMA_NV_GLOBALLOCK attribute SET.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.\r
+  @param[in]  AuthSession        Auth Session context\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvGlobalWriteLock (\r
+  IN      TPMI_RH_PROVISION         AuthHandle,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  );\r
+\r
+/**\r
+  This command is used to cause an update to the indicated PCR.\r
+  The digests parameter contains one or more tagged digest value identified by an algorithm ID.\r
+  For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).\r
+\r
+  @param[in] PcrHandle   Handle of the PCR\r
+  @param[in] Digests     List of tagged digest values to be extended\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrExtend (\r
+  IN      TPMI_DH_PCR               PcrHandle,\r
+  IN      TPML_DIGEST_VALUES        *Digests\r
+  );\r
+\r
+/**\r
+  This command is used to cause an update to the indicated PCR.\r
+  The data in eventData is hashed using the hash algorithm associated with each bank in which the\r
+  indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle\r
+  references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in\r
+  TPM2_PCR_Extend().\r
+  A TPM shall support an Event.size of zero through 1,024 inclusive.\r
+\r
+  @param[in]  PcrHandle   Handle of the PCR\r
+  @param[in]  EventData   Event data in sized buffer\r
+  @param[out] Digests     List of digest\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrEvent (\r
+  IN      TPMI_DH_PCR               PcrHandle,\r
+  IN      TPM2B_EVENT               *EventData,\r
+     OUT  TPML_DIGEST_VALUES        *Digests\r
+  );\r
+\r
+/**\r
+  This command returns the values of all PCR specified in pcrSelect.\r
+\r
+  @param[in]  PcrSelectionIn     The selection of PCR to read.\r
+  @param[out] PcrUpdateCounter   The current value of the PCR update counter.\r
+  @param[out] PcrSelectionOut    The PCR in the returned list.\r
+  @param[out] PcrValues          The contents of the PCR indicated in pcrSelect.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrRead (\r
+  IN      TPML_PCR_SELECTION        *PcrSelectionIn,\r
+     OUT  UINT32                    *PcrUpdateCounter,\r
+     OUT  TPML_PCR_SELECTION        *PcrSelectionOut,\r
+     OUT  TPML_DIGEST               *PcrValues\r
+  );\r
+\r
+/**\r
+  This command is used to set the desired PCR allocation of PCR and algorithms.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_PLATFORM+{PP}\r
+  @param[in]  AuthSession        Auth Session context\r
+  @param[in]  PcrAllocation      The requested allocation\r
+  @param[out] AllocationSuccess  YES if the allocation succeeded\r
+  @param[out] MaxPCR             maximum number of PCR that may be in a bank\r
+  @param[out] SizeNeeded         number of octets required to satisfy the request\r
+  @param[out] SizeAvailable      Number of octets available. Computed before the allocation\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrAllocate (\r
+  IN  TPMI_RH_PLATFORM          AuthHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN  TPML_PCR_SELECTION        *PcrAllocation,\r
+  OUT TPMI_YES_NO               *AllocationSuccess,\r
+  OUT UINT32                    *MaxPCR,\r
+  OUT UINT32                    *SizeNeeded,\r
+  OUT UINT32                    *SizeAvailable\r
+  );\r
+\r
+/**\r
+  This command returns various information regarding the TPM and its current state.\r
+\r
+  The capability parameter determines the category of data returned. The property parameter \r
+  selects the first value of the selected category to be returned. If there is no property \r
+  that corresponds to the value of property, the next higher value is returned, if it exists.\r
+  The moreData parameter will have a value of YES if there are more values of the requested \r
+  type that were not returned.\r
+  If no next capability exists, the TPM will return a zero-length list and moreData will have \r
+  a value of NO.\r
+\r
+  NOTE: \r
+  To simplify this function, leave returned CapabilityData for caller to unpack since there are \r
+  many capability categories and only few categories will be used in firmware. It means the caller\r
+  need swap the byte order for the feilds in CapabilityData.\r
+\r
+  @param[in]  Capability         Group selection; determines the format of the response.\r
+  @param[in]  Property           Further definition of information. \r
+  @param[in]  PropertyCount      Number of properties of the indicated type to return.\r
+  @param[out] MoreData           Flag to indicate if there are more values of this type.\r
+  @param[out] CapabilityData     The capability data.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapability (\r
+  IN      TPM_CAP                   Capability,\r
+  IN      UINT32                    Property,\r
+  IN      UINT32                    PropertyCount,\r
+  OUT     TPMI_YES_NO               *MoreData,\r
+  OUT     TPMS_CAPABILITY_DATA      *CapabilityData\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM Family.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the Family.\r
+\r
+  @param[out] Family             The Family of TPM. (a 4-octet character string)\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityFamily (\r
+  OUT     CHAR8                     *Family\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM manufacture ID.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the TPM manufacture ID.\r
+\r
+  @param[out] ManufactureId      The manufacture ID of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityManufactureID (\r
+  OUT     UINT32                    *ManufactureId\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM FirmwareVersion.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the TPM FirmwareVersion.\r
+\r
+  @param[out] FirmwareVersion1   The FirmwareVersion1.\r
+  @param[out] FirmwareVersion2   The FirmwareVersion2.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityFirmwareVersion (\r
+  OUT     UINT32                    *FirmwareVersion1,\r
+  OUT     UINT32                    *FirmwareVersion2\r
+  );\r
+\r
+/**\r
+  This command returns the information of the maximum value for commandSize and responseSize in a command.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the max command size and response size\r
+\r
+  @param[out] MaxCommandSize     The maximum value for commandSize in a command.\r
+  @param[out] MaxResponseSize    The maximum value for responseSize in a command.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityMaxCommandResponseSize (\r
+  OUT UINT32                    *MaxCommandSize,\r
+  OUT UINT32                    *MaxResponseSize\r
+  );\r
+\r
+/**\r
+  This command returns Returns a list of TPMS_ALG_PROPERTIES. Each entry is an\r
+  algorithm ID and a set of properties of the algorithm. \r
+\r
+  This function parse the value got from TPM2_GetCapability and return the list.\r
+\r
+  @param[out] AlgList      List of algorithm.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilitySupportedAlg (\r
+  OUT TPML_ALG_PROPERTY      *AlgList\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM LockoutCounter.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the LockoutCounter.\r
+\r
+  @param[out] LockoutCounter     The LockoutCounter of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityLockoutCounter (\r
+  OUT     UINT32                    *LockoutCounter\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM LockoutInterval.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the LockoutInterval.\r
+\r
+  @param[out] LockoutInterval    The LockoutInterval of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityLockoutInterval (\r
+  OUT     UINT32                    *LockoutInterval\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM InputBufferSize.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the InputBufferSize.\r
+\r
+  @param[out] InputBufferSize    The InputBufferSize of TPM.\r
+                                 the maximum size of a parameter (typically, a TPM2B_MAX_BUFFER)\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityInputBufferSize (\r
+  OUT     UINT32                    *InputBufferSize\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM PCRs.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the PcrSelection.\r
+\r
+  @param[out] Pcrs    The Pcr Selection\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityPcrs (\r
+  OUT TPML_PCR_SELECTION      *Pcrs\r
+  );\r
+\r
+/**\r
+  This command returns the information of TPM AlgorithmSet.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the AlgorithmSet.\r
+\r
+  @param[out] AlgorithmSet    The AlgorithmSet of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityAlgorithmSet (\r
+  OUT     UINT32      *AlgorithmSet\r
+  );\r
+\r
+/**\r
+  This command is used to check to see if specific combinations of algorithm parameters are supported.\r
+\r
+  @param[in]  Parameters              Algorithm parameters to be validated\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2TestParms (\r
+  IN  TPMT_PUBLIC_PARMS           *Parameters\r
+  );\r
+\r
+/**\r
+  This command allows the platform to change the set of algorithms that are used by the TPM.\r
+  The algorithmSet setting is a vendor-dependent value.\r
+\r
+  @param[in]  AuthHandle              TPM_RH_PLATFORM\r
+  @param[in]  AuthSession             Auth Session context\r
+  @param[in]  AlgorithmSet            A TPM vendor-dependent value indicating the\r
+                                      algorithm set selection\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SetAlgorithmSet (\r
+  IN  TPMI_RH_PLATFORM          AuthHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN  UINT32                    AlgorithmSet\r
+  );\r
+\r
+//\r
+// Help function\r
+//\r
+\r
+/**\r
+  Copy AuthSessionIn to TPM2 command buffer.\r
+\r
+  @param [in]  AuthSessionIn   Input AuthSession data\r
+  @param [out] AuthSessionOut  Output AuthSession data in TPM2 command buffer\r
+\r
+  @return AuthSession size\r
+**/\r
+UINT32\r
+EFIAPI\r
+CopyAuthSessionCommand (\r
+  IN      TPMS_AUTH_COMMAND         *AuthSessionIn, OPTIONAL\r
+  OUT     UINT8                     *AuthSessionOut\r
+  );\r
+\r
+/**\r
+  Copy AuthSessionIn from TPM2 response buffer.\r
+\r
+  @param [in]  AuthSessionIn   Input AuthSession data in TPM2 response buffer\r
+  @param [out] AuthSessionOut  Output AuthSession data\r
+\r
+  @return AuthSession size\r
+**/\r
+UINT32\r
+EFIAPI\r
+CopyAuthSessionResponse (\r
+  IN      UINT8                      *AuthSessionIn,\r
+  OUT     TPMS_AUTH_RESPONSE         *AuthSessionOut OPTIONAL\r
+  );\r
+\r
+/**\r
+  Return size of digest.\r
+\r
+  @param[in] HashAlgo  Hash algorithm\r
+\r
+  @return size of digest\r
+**/\r
+UINT16\r
+EFIAPI\r
+GetHashSizeFromAlgo (\r
+  IN TPMI_ALG_HASH    HashAlgo\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Include/Library/Tpm2DeviceLib.h b/SecurityPkg/Include/Library/Tpm2DeviceLib.h
new file mode 100644 (file)
index 0000000..67f158e
--- /dev/null
@@ -0,0 +1,109 @@
+/** @file\r
+  This library abstract how to access TPM2 hardware device.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _TPM2_DEVICE_LIB_H_\r
+#define _TPM2_DEVICE_LIB_H_\r
+\r
+#include <Uefi.h>\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  );\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RequestUseTpm (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *TPM2_SUBMIT_COMMAND) (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  );\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *TPM2_REQUEST_USE_TPM) (\r
+  VOID\r
+  );\r
+\r
+typedef struct {\r
+  EFI_GUID                           ProviderGuid;\r
+  TPM2_SUBMIT_COMMAND                Tpm2SubmitCommand;\r
+  TPM2_REQUEST_USE_TPM               Tpm2RequestUseTpm;\r
+} TPM2_DEVICE_INTERFACE;\r
+\r
+/**\r
+  This service register TPM2 device.\r
+\r
+  @param Tpm2Device  TPM2 device\r
+\r
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.\r
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RegisterTpm2DeviceLib (\r
+  IN TPM2_DEVICE_INTERFACE   *Tpm2Device\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Include/Library/TrEEPhysicalPresenceLib.h b/SecurityPkg/Include/Library/TrEEPhysicalPresenceLib.h
new file mode 100644 (file)
index 0000000..781fd16
--- /dev/null
@@ -0,0 +1,57 @@
+/** @file\r
+  Ihis library is intended to be used by BDS modules.\r
+  This library will executing TPM2 request.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _TREE_PHYSICAL_PRESENCE_LIB_H_\r
+#define _TREE_PHYSICAL_PRESENCE_LIB_H_\r
+\r
+#include <IndustryStandard/Tpm20.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+/**\r
+  Check and execute the pending TPM request.\r
+\r
+  The TPM request may come from OS or BIOS. This API will display request information and wait \r
+  for user confirmation if TPM request exists. The TPM request will be sent to TPM device after\r
+  the TPM request is confirmed, and one or more reset may be required to make TPM request to \r
+  take effect.\r
+  \r
+  This API should be invoked after console in and console out are all ready as they are required\r
+  to display request information and get user input to confirm the request.  \r
+\r
+  @param  PlatformAuth                   platform auth value. NULL means no platform auth change.\r
+**/\r
+VOID\r
+EFIAPI\r
+TrEEPhysicalPresenceLibProcessRequest (\r
+  IN      TPM2B_AUTH                     *PlatformAuth  OPTIONAL\r
+  );\r
+\r
+/**\r
+  Check if the pending TPM request needs user input to confirm.\r
+\r
+  The TPM request may come from OS. This API will check if TPM request exists and need user\r
+  input to confirmation.\r
+  \r
+  @retval    TRUE        TPM needs input to confirm user physical presence.\r
+  @retval    FALSE       TPM doesn't need input to confirm user physical presence.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TrEEPhysicalPresenceLibNeedUserConfirm(\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h
new file mode 100644 (file)
index 0000000..88d09b0
--- /dev/null
@@ -0,0 +1,37 @@
+/** @file\r
+  Ihis PPI means a FV does not need to be extended to PCR by TCG modules.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_H__\r
+#define __EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_H__\r
+\r
+#define EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI_GUID \\r
+ { 0x6e056ff9, 0xc695, 0x4364, { 0x9e, 0x2c, 0x61, 0x26, 0xf5, 0xce, 0xea, 0xae } }\r
+\r
+typedef struct {\r
+  EFI_PHYSICAL_ADDRESS              FvBase;\r
+  UINT64                            FvLength;\r
+} EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_FV;\r
+\r
+//\r
+// This PPI means a FV does not need to be extended to PCR by TCG modules.\r
+//\r
+typedef struct {\r
+  UINT32                                                Count;\r
+  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_FV  Fv[1];\r
+} EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI;\r
+\r
+extern EFI_GUID gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid;\r
+\r
+#endif\r
+\r
index 2458ee2ae1c586f6f919c6ccc1dac89e7be308a8..8860daeafac4781a5d0ccfcb6bf873d23df333af 100644 (file)
@@ -71,6 +71,25 @@ HASH_TABLE mHash[] = {
   { L"SHA512", 64, &mHashOidValue[32], 9, NULL,                NULL,       NULL,          NULL       }\r
 };\r
 \r
+/**\r
+  SecureBoot Hook for processing image verification.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+  @param[in] DataSize                     Size of Data found. If size is less than the\r
+                                          data, this value contains the required size.\r
+  @param[in] Data                         Data pointer.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid,\r
+  IN UINTN                                  DataSize,\r
+  IN VOID                                   *Data\r
+  );\r
+\r
 /**\r
   Reads contents of a PE/COFF image in memory buffer.\r
 \r
@@ -846,6 +865,7 @@ IsSignatureFoundInDatabase (
           // Find the signature in database.\r
           //\r
           IsFound = TRUE;\r
+          SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
           break;\r
         }\r
 \r
@@ -948,6 +968,7 @@ IsPkcsSignedDataVerifiedBySignatureList (
                            mImageDigestSize\r
                            );\r
           if (VerifyStatus) {\r
+            SecureBootHook (VariableName, VendorGuid, CertList->SignatureSize, Cert);\r
             goto Done;\r
           }\r
           Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
index 0c6ab968f0c11f41a5fe9c4f1e0c9ee7642203cb..0e6a5d1ce6a41e03afabdd18f1ab8c32e5843ee6 100644 (file)
@@ -35,6 +35,7 @@
 [Sources]\r
   DxeImageVerificationLib.c\r
   DxeImageVerificationLib.h\r
+  Measurement.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
@@ -54,6 +55,7 @@
   BaseCryptLib\r
   SecurityManagementLib\r
   PeCoffLib\r
+  TpmMeasurementLib\r
 \r
 [Protocols]\r
   gEfiFirmwareVolume2ProtocolGuid\r
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c b/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c
new file mode 100644 (file)
index 0000000..2213423
--- /dev/null
@@ -0,0 +1,322 @@
+/** @file\r
+  Measure TrEE required variable.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Guid/ImageAuthentication.h>\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+\r
+typedef struct {\r
+  CHAR16                                 *VariableName;\r
+  EFI_GUID                               *VendorGuid;\r
+} VARIABLE_TYPE;\r
+\r
+typedef struct {\r
+  CHAR16                                 *VariableName;\r
+  EFI_GUID                               *VendorGuid;\r
+  VOID                                   *Data;\r
+  UINTN                                  Size;\r
+} VARIABLE_RECORD;\r
+\r
+#define  MEASURED_AUTHORITY_COUNT_MAX  0x100\r
+\r
+UINTN            mMeasuredAuthorityCount    = 0;\r
+UINTN            mMeasuredAuthorityCountMax = 0;\r
+VARIABLE_RECORD  *mMeasuredAuthorityList    = NULL;\r
+\r
+VARIABLE_TYPE  mVariableType[] = {\r
+  {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},\r
+};\r
+\r
+/**\r
+  This function will check if VarName should be recorded and return the address of VarName if it is needed.\r
+\r
+  @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.\r
+\r
+  @return the address of VarName.\r
+**/\r
+CHAR16 *\r
+AssignVarName (\r
+  IN      CHAR16                    *VarName\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
+    if (StrCmp (VarName, mVariableType[Index].VariableName) == 0) {\r
+      return mVariableType[Index].VariableName;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  This function will check if VendorGuid should be recorded and return the address of VendorGuid if it is needed.\r
+\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+\r
+  @return the address of VendorGuid.\r
+**/\r
+EFI_GUID *\r
+AssignVendorGuid (\r
+  IN      EFI_GUID                  *VendorGuid\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
+    if (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)) {\r
+      return mVariableType[Index].VendorGuid;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  This function will add variable information to MeasuredAuthorityList.\r
+\r
+  @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+  @param[in]  VarData           The content of the variable data.  \r
+  @param[in]  VarSize           The size of the variable data.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+**/\r
+EFI_STATUS\r
+AddDataMeasured (\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  IN      VOID                      *Data,\r
+  IN      UINTN                     Size\r
+  )\r
+{\r
+  VARIABLE_RECORD  *NewMeasuredAuthorityList;\r
+\r
+  ASSERT (mMeasuredAuthorityCount <= mMeasuredAuthorityCountMax);\r
+  if (mMeasuredAuthorityCount == mMeasuredAuthorityCountMax) {\r
+    //\r
+    // Need enlarge\r
+    //\r
+    NewMeasuredAuthorityList = AllocateZeroPool (sizeof(VARIABLE_RECORD) * (mMeasuredAuthorityCountMax + MEASURED_AUTHORITY_COUNT_MAX));\r
+    if (NewMeasuredAuthorityList == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    if (mMeasuredAuthorityList != NULL) {\r
+      CopyMem (NewMeasuredAuthorityList, mMeasuredAuthorityList, sizeof(VARIABLE_RECORD) * mMeasuredAuthorityCount);\r
+      FreePool (mMeasuredAuthorityList);\r
+    }\r
+    mMeasuredAuthorityList     = NewMeasuredAuthorityList;\r
+    mMeasuredAuthorityCountMax += MEASURED_AUTHORITY_COUNT_MAX;\r
+  }\r
+\r
+  //\r
+  // Add new entry\r
+  //\r
+  mMeasuredAuthorityList[mMeasuredAuthorityCount].VariableName = AssignVarName (VarName);\r
+  mMeasuredAuthorityList[mMeasuredAuthorityCount].VendorGuid   = AssignVendorGuid (VendorGuid);\r
+  mMeasuredAuthorityList[mMeasuredAuthorityCount].Size         = Size;\r
+  mMeasuredAuthorityList[mMeasuredAuthorityCount].Data         = AllocatePool (Size);\r
+  if (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  CopyMem (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data, Data, Size);\r
+  mMeasuredAuthorityCount++;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function will return if this variable is already measured.\r
+\r
+  @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+  @param[in]  VarData           The content of the variable data.  \r
+  @param[in]  VarSize           The size of the variable data.  \r
+\r
+  @retval TRUE  The data is already measured.\r
+  @retval FALSE The data is not measured yet.\r
+**/\r
+BOOLEAN\r
+IsDataMeasured (\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  IN      VOID                      *Data,\r
+  IN      UINTN                     Size\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < mMeasuredAuthorityCount; Index++) {\r
+    if ((StrCmp (VarName, mMeasuredAuthorityList[Index].VariableName) == 0) &&\r
+        (CompareGuid (VendorGuid, mMeasuredAuthorityList[Index].VendorGuid)) &&\r
+        (CompareMem (Data, mMeasuredAuthorityList[Index].Data, Size) == 0) &&\r
+        (Size == mMeasuredAuthorityList[Index].Size)) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This function will return if this variable is SecureAuthority Variable.\r
+\r
+  @param[in]  VariableName      A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+\r
+  @retval TRUE  This is SecureAuthority Variable\r
+  @retval FALSE This is not SecureAuthority Variable\r
+**/\r
+BOOLEAN\r
+IsSecureAuthorityVariable (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  )\r
+{\r
+  UINTN   Index;\r
+\r
+  for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
+    if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) && \r
+        (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {\r
+      return TRUE;\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+  @param[in]  VarData           The content of the variable data.  \r
+  @param[in]  VarSize           The size of the variable data.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MeasureVariable (\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  IN      VOID                      *VarData,\r
+  IN      UINTN                     VarSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             VarNameLength;\r
+  EFI_VARIABLE_DATA_TREE            *VarLog;\r
+  UINT32                            VarLogSize;\r
+\r
+  //\r
+  // The EFI_VARIABLE_DATA_TREE.VariableData value shall be the EFI_SIGNATURE_DATA value\r
+  // from the EFI_SIGNATURE_LIST that contained the authority that was used to validate the image\r
+  //\r
+  VarNameLength      = StrLen (VarName);\r
+  VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
+                        - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
+\r
+  VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize);\r
+  if (VarLog == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName));\r
+  VarLog->UnicodeNameLength  = VarNameLength;\r
+  VarLog->VariableDataLength = VarSize;\r
+  CopyMem (\r
+     VarLog->UnicodeName,\r
+     VarName,\r
+     VarNameLength * sizeof (*VarName)\r
+     );\r
+  CopyMem (\r
+     (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
+     VarData,\r
+     VarSize\r
+     );\r
+\r
+  DEBUG ((EFI_D_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));\r
+  DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
+\r
+  Status = TpmMeasureAndLogData (\r
+             7,\r
+             EV_EFI_VARIABLE_AUTHORITY,\r
+             VarLog,\r
+             VarLogSize,\r
+             VarLog,\r
+             VarLogSize\r
+             );\r
+  FreePool (VarLog);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  SecureBoot Hook for processing image verification.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+  @param[in] DataSize                     Size of Data found. If size is less than the\r
+                                          data, this value contains the required size.\r
+  @param[in] Data                         Data pointer.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid,\r
+  IN UINTN                                  DataSize,\r
+  IN VOID                                   *Data\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+\r
+  if (!IsSecureAuthorityVariable (VariableName, VendorGuid)) {\r
+    return ;\r
+  }\r
+\r
+  if (IsDataMeasured (VariableName, VendorGuid, Data, DataSize)) {\r
+    DEBUG ((EFI_D_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n"));\r
+    return ;\r
+  }\r
+\r
+  Status = MeasureVariable (\r
+             VariableName,\r
+             VendorGuid,\r
+             Data,\r
+             DataSize\r
+             );\r
+  DEBUG ((EFI_D_ERROR, "MeasureBootPolicyVariable - %r\n", Status));\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    AddDataMeasured (VariableName, VendorGuid, Data, DataSize);\r
+  }\r
+\r
+  return ;\r
+}\r
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
new file mode 100644 (file)
index 0000000..3c81b5a
--- /dev/null
@@ -0,0 +1,700 @@
+/** @file\r
+  The library instance provides security service of TPM2 measure boot.\r
+\r
+  Caution: This file requires additional review when modified.\r
+  This library will have external input - PE/COFF image and GPT partition.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
+\r
+  DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
+\r
+  TrEEMeasurePeImage() function will accept untrusted PE/COFF image and validate its\r
+  data structure within this image buffer before use.\r
+\r
+  TrEEMeasureGptTable() function will receive untrusted GPT partition table, and parse\r
+  partition data carefully.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/TrEEProtocol.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/DiskIo.h>\r
+#include <Protocol/DevicePathToText.h>\r
+#include <Protocol/FirmwareVolumeBlock.h>\r
+\r
+#include <Guid/MeasuredFvHob.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/SecurityManagementLib.h>\r
+#include <Library/HobLib.h>\r
+\r
+//\r
+// Flag to check GPT partition. It only need be measured once.\r
+//\r
+BOOLEAN                           mTrEEMeasureGptTableFlag = FALSE;\r
+EFI_GUID                          mTrEEZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+UINTN                             mTrEEMeasureGptCount = 0;\r
+VOID                              *mTrEEFileBuffer;\r
+UINTN                             mTrEEImageSize;\r
+//\r
+// Measured FV handle cache\r
+//\r
+EFI_HANDLE                        mTrEECacheMeasuredHandle  = NULL;\r
+MEASURED_HOB_DATA                 *mTrEEMeasuredHobData     = NULL;\r
+\r
+/**\r
+  Reads contents of a PE/COFF image in memory buffer.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
+\r
+  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.\r
+  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.\r
+  @param  ReadSize        On input, the size in bytes of the requested read operation.  \r
+                          On output, the number of bytes actually read.\r
+  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.\r
+  \r
+  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeTpm2MeasureBootLibImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+{\r
+  UINTN               EndPosition;\r
+\r
+  if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  EndPosition = FileOffset + *ReadSize;\r
+  if (EndPosition > mTrEEImageSize) {\r
+    *ReadSize = (UINT32)(mTrEEImageSize - FileOffset);\r
+  }\r
+\r
+  if (FileOffset >= mTrEEImageSize) {\r
+    *ReadSize = 0;\r
+  }\r
+\r
+  CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Measure GPT table data into TPM log.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  The GPT partition table is external input, so this function should parse partition data carefully.\r
+\r
+  @param TreeProtocol            Pointer to the located TREE protocol instance.\r
+  @param GptHandle               Handle that GPT partition was installed.\r
+\r
+  @retval EFI_SUCCESS            Successfully measure GPT table.\r
+  @retval EFI_UNSUPPORTED        Not support GPT table on the given handle.\r
+  @retval EFI_DEVICE_ERROR       Can't get GPT table because device error.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure GPT table.\r
+  @retval other error value\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEMeasureGptTable (\r
+  IN  EFI_TREE_PROTOCOL  *TreeProtocol,\r
+  IN  EFI_HANDLE         GptHandle\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_BLOCK_IO_PROTOCOL             *BlockIo;\r
+  EFI_DISK_IO_PROTOCOL              *DiskIo;\r
+  EFI_PARTITION_TABLE_HEADER        *PrimaryHeader;\r
+  EFI_PARTITION_ENTRY               *PartitionEntry;\r
+  UINT8                             *EntryPtr;\r
+  UINTN                             NumberOfPartition;\r
+  UINT32                            Index;\r
+  TrEE_EVENT                        *TreeEvent;\r
+  EFI_GPT_DATA                      *GptData;\r
+  UINT32                            EventSize;\r
+\r
+  if (mTrEEMeasureGptCount > 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Read the EFI Partition Table Header\r
+  //  \r
+  PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *) AllocatePool (BlockIo->Media->BlockSize);\r
+  if (PrimaryHeader == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }  \r
+  Status = DiskIo->ReadDisk (\r
+                     DiskIo,\r
+                     BlockIo->Media->MediaId,\r
+                     1 * BlockIo->Media->BlockSize,\r
+                     BlockIo->Media->BlockSize,\r
+                     (UINT8 *)PrimaryHeader\r
+                     );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n"));\r
+    FreePool (PrimaryHeader);\r
+    return EFI_DEVICE_ERROR;\r
+  }  \r
+  //\r
+  // Read the partition entry.\r
+  //\r
+  EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);\r
+  if (EntryPtr == NULL) {\r
+    FreePool (PrimaryHeader);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  Status = DiskIo->ReadDisk (\r
+                     DiskIo,\r
+                     BlockIo->Media->MediaId,\r
+                     MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
+                     PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,\r
+                     EntryPtr\r
+                     );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (PrimaryHeader);\r
+    FreePool (EntryPtr);\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  \r
+  //\r
+  // Count the valid partition\r
+  //\r
+  PartitionEntry    = (EFI_PARTITION_ENTRY *)EntryPtr;\r
+  NumberOfPartition = 0;\r
+  for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
+    if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mTrEEZeroGuid)) {\r
+      NumberOfPartition++;  \r
+    }\r
+    PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
+  }\r
+\r
+  //\r
+  // Prepare Data for Measurement\r
+  // \r
+  EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) \r
+                        + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
+  TreeEvent = (TrEE_EVENT *) AllocateZeroPool (EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event));\r
+  if (TreeEvent == NULL) {\r
+    FreePool (PrimaryHeader);\r
+    FreePool (EntryPtr);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TreeEvent->Size = EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event);\r
+  TreeEvent->Header.HeaderSize    = sizeof(TrEE_EVENT_HEADER);\r
+  TreeEvent->Header.HeaderVersion = TREE_EVENT_HEADER_VERSION;\r
+  TreeEvent->Header.PCRIndex      = 5;\r
+  TreeEvent->Header.EventType     = EV_EFI_GPT_EVENT;\r
+  GptData = (EFI_GPT_DATA *) TreeEvent->Event;  \r
+\r
+  //\r
+  // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition\r
+  //  \r
+  CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));\r
+  GptData->NumberOfPartitions = NumberOfPartition;\r
+  //\r
+  // Copy the valid partition entry\r
+  //\r
+  PartitionEntry    = (EFI_PARTITION_ENTRY*)EntryPtr;\r
+  NumberOfPartition = 0;\r
+  for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
+    if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mTrEEZeroGuid)) {\r
+      CopyMem (\r
+        (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,\r
+        (UINT8 *)PartitionEntry,\r
+        PrimaryHeader->SizeOfPartitionEntry\r
+        );\r
+      NumberOfPartition++;\r
+    }\r
+    PartitionEntry =(EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
+  }\r
+\r
+  //\r
+  // Measure the GPT data\r
+  //\r
+  Status = TreeProtocol->HashLogExtendEvent (\r
+             TreeProtocol,\r
+             0,\r
+             (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData,\r
+             (UINT64) EventSize,\r
+             TreeEvent\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    mTrEEMeasureGptCount++;\r
+  }\r
+\r
+  FreePool (PrimaryHeader);\r
+  FreePool (EntryPtr);\r
+  FreePool (TreeEvent);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Measure PE image into TPM log based on the authenticode image hashing in\r
+  PE/COFF Specification 8.0 Appendix A.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
+\r
+  @param[in] TreeProtocol   Pointer to the located TREE protocol instance.\r
+  @param[in] ImageAddress   Start address of image buffer.\r
+  @param[in] ImageSize      Image size\r
+  @param[in] LinkTimeBase   Address that the image is loaded into memory.\r
+  @param[in] ImageType      Image subsystem type.\r
+  @param[in] FilePath       File path is corresponding to the input image.\r
+\r
+  @retval EFI_SUCCESS            Successfully measure image.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.\r
+  @retval EFI_UNSUPPORTED        ImageType is unsupported or PE image is mal-format.  \r
+  @retval other error value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEMeasurePeImage (\r
+  IN  EFI_TREE_PROTOCOL         *TreeProtocol,\r
+  IN  EFI_PHYSICAL_ADDRESS      ImageAddress,\r
+  IN  UINTN                     ImageSize,\r
+  IN  UINTN                     LinkTimeBase,\r
+  IN  UINT16                    ImageType,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TrEE_EVENT                        *TreeEvent;\r
+  EFI_IMAGE_LOAD_EVENT              *ImageLoad;\r
+  UINT32                            FilePathSize;\r
+  UINT32                            EventSize;\r
+\r
+  Status        = EFI_UNSUPPORTED;\r
+  ImageLoad     = NULL;\r
+  FilePathSize  = (UINT32) GetDevicePathSize (FilePath);\r
+\r
+  //\r
+  // Determine destination PCR by BootPolicy\r
+  //\r
+  EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;\r
+  TreeEvent = AllocateZeroPool (EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event));\r
+  if (TreeEvent == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TreeEvent->Size = EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event);\r
+  TreeEvent->Header.HeaderSize    = sizeof(TrEE_EVENT_HEADER);\r
+  TreeEvent->Header.HeaderVersion = TREE_EVENT_HEADER_VERSION;\r
+  ImageLoad           = (EFI_IMAGE_LOAD_EVENT *) TreeEvent->Event;\r
+\r
+  switch (ImageType) {\r
+    case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
+      TreeEvent->Header.EventType = EV_EFI_BOOT_SERVICES_APPLICATION;\r
+      TreeEvent->Header.PCRIndex  = 4;\r
+      break;\r
+    case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
+      TreeEvent->Header.EventType = EV_EFI_BOOT_SERVICES_DRIVER;\r
+      TreeEvent->Header.PCRIndex  = 2;\r
+      break;\r
+    case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
+      TreeEvent->Header.EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;\r
+      TreeEvent->Header.PCRIndex  = 2;\r
+      break;\r
+    default:\r
+      DEBUG ((\r
+        EFI_D_ERROR,\r
+        "TrEEMeasurePeImage: Unknown subsystem type %d",\r
+        ImageType\r
+        ));\r
+      goto Finish;\r
+  }\r
+\r
+  ImageLoad->ImageLocationInMemory = ImageAddress;\r
+  ImageLoad->ImageLengthInMemory   = ImageSize;\r
+  ImageLoad->ImageLinkTimeAddress  = LinkTimeBase;\r
+  ImageLoad->LengthOfDevicePath    = FilePathSize;\r
+  CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);\r
+\r
+  //\r
+  // Log the PE data\r
+  //\r
+  Status = TreeProtocol->HashLogExtendEvent (\r
+             TreeProtocol,\r
+             PE_COFF_IMAGE,\r
+             ImageAddress,\r
+             ImageSize,\r
+             TreeEvent\r
+             );\r
+  if (Status == EFI_VOLUME_FULL) {\r
+    //\r
+    // Volume full here means the image is hashed and its result is extended to PCR.\r
+    // But the event log cann't be saved since log area is full.\r
+    // Just return EFI_SUCCESS in order not to block the image load.\r
+    //\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+Finish:\r
+  FreePool (TreeEvent);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The security handler is used to abstract platform-specific policy \r
+  from the DXE core response to an attempt to use a file that returns a \r
+  given status for the authentication check from the section extraction protocol.  \r
+\r
+  The possible responses in a given SAP implementation may include locking \r
+  flash upon failure to authenticate, attestation logging for all signed drivers, \r
+  and other exception operations.  The File parameter allows for possible logging \r
+  within the SAP of the driver.\r
+\r
+  If File is NULL, then EFI_INVALID_PARAMETER is returned.\r
+\r
+  If the file specified by File with an authentication status specified by \r
+  AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.\r
+\r
+  If the file specified by File with an authentication status specified by \r
+  AuthenticationStatus is not safe for the DXE Core to use under any circumstances, \r
+  then EFI_ACCESS_DENIED is returned.\r
+\r
+  If the file specified by File with an authentication status specified by \r
+  AuthenticationStatus is not safe for the DXE Core to use right now, but it \r
+  might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is \r
+  returned.\r
+\r
+  @param[in]      AuthenticationStatus  This is the authentication status returned\r
+                                        from the securitymeasurement services for the\r
+                                        input file.\r
+  @param[in]      File       This is a pointer to the device path of the file that is\r
+                             being dispatched. This will optionally be used for logging.\r
+  @param[in]      FileBuffer File buffer matches the input file device path.\r
+  @param[in]      FileSize   Size of File buffer matches the input file device path.\r
+  @param[in]      BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
+\r
+  @retval EFI_SUCCESS             The file specified by DevicePath and non-NULL\r
+                                  FileBuffer did authenticate, and the platform policy dictates\r
+                                  that the DXE Foundation may use the file.\r
+  @retval other error value\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeTpm2MeasureBootHandler (\r
+  IN  UINT32                           AuthenticationStatus,\r
+  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
+  IN  VOID                             *FileBuffer,\r
+  IN  UINTN                            FileSize,\r
+  IN  BOOLEAN                          BootPolicy\r
+  )\r
+{\r
+  EFI_TREE_PROTOCOL                   *TreeProtocol;\r
+  EFI_STATUS                          Status;\r
+  TREE_BOOT_SERVICE_CAPABILITY        ProtocolCapability;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL            *OrigDevicePathNode;\r
+  EFI_HANDLE                          Handle;\r
+  EFI_HANDLE                          TempHandle;\r
+  BOOLEAN                             ApplicationRequired;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbProtocol;\r
+  EFI_PHYSICAL_ADDRESS                FvAddress;\r
+  UINT32                              Index;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // TrEE protocol is not installed. So, TPM2 is not present.\r
+    // Don't do any measurement, and directly return EFI_SUCCESS.\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler - TrEE - %r\n", Status));\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability);\r
+  Status = TreeProtocol->GetCapability (\r
+                           TreeProtocol, \r
+                           &ProtocolCapability\r
+                           );\r
+  if (EFI_ERROR (Status) || !ProtocolCapability.TrEEPresentFlag) {\r
+    //\r
+    // TPM device doesn't work or activate.\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler (%r) - TrEEPresentFlag - %x\n", Status, ProtocolCapability.TrEEPresentFlag));\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Copy File Device Path\r
+  //\r
+  OrigDevicePathNode = DuplicateDevicePath (File);\r
+  \r
+  //\r
+  // 1. Check whether this device path support BlockIo protocol.\r
+  // Is so, this device path may be a GPT device path.\r
+  //\r
+  DevicePathNode = OrigDevicePathNode;\r
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);\r
+  if (!EFI_ERROR (Status) && !mTrEEMeasureGptTableFlag) {\r
+    //\r
+    // Find the gpt partion on the given devicepath\r
+    //\r
+    DevicePathNode = OrigDevicePathNode;\r
+    ASSERT (DevicePathNode != NULL);\r
+    while (!IsDevicePathEnd (DevicePathNode)) {\r
+      //\r
+      // Find the Gpt partition\r
+      //\r
+      if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH &&\r
+            DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP) {\r
+        //\r
+        // Check whether it is a gpt partition or not\r
+        //                           \r
+        if (((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER && \r
+            ((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID) {\r
+\r
+          //\r
+          // Change the partition device path to its parent device path (disk) and get the handle.\r
+          //\r
+          DevicePathNode->Type    = END_DEVICE_PATH_TYPE;\r
+          DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
+          DevicePathNode          = OrigDevicePathNode;\r
+          Status = gBS->LocateDevicePath (\r
+                         &gEfiDiskIoProtocolGuid,\r
+                         &DevicePathNode,\r
+                         &Handle\r
+                         );\r
+          if (!EFI_ERROR (Status)) {\r
+            //\r
+            // Measure GPT disk.\r
+            //\r
+            Status = TrEEMeasureGptTable (TreeProtocol, Handle);\r
+            DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler - TrEEMeasureGptTable - %r\n", Status));\r
+            if (!EFI_ERROR (Status)) {\r
+              //\r
+              // GPT disk check done.\r
+              //\r
+              mTrEEMeasureGptTableFlag = TRUE;\r
+            }\r
+          }\r
+          FreePool (OrigDevicePathNode);\r
+          OrigDevicePathNode = DuplicateDevicePath (File);\r
+          ASSERT (OrigDevicePathNode != NULL);\r
+          break;\r
+        }\r
+      }\r
+      DevicePathNode    = NextDevicePathNode (DevicePathNode);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // 2. Measure PE image.\r
+  //\r
+  ApplicationRequired = FALSE;\r
+\r
+  //\r
+  // Check whether this device path support FVB protocol.\r
+  //\r
+  DevicePathNode = OrigDevicePathNode;\r
+  Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Don't check FV image, and directly return EFI_SUCCESS.\r
+    // It can be extended to the specific FV authentication according to the different requirement.\r
+    //\r
+    if (IsDevicePathEnd (DevicePathNode)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    //\r
+    // The PE image from unmeasured Firmware volume need be measured\r
+    // The PE image from measured Firmware volume will be mearsured according to policy below.\r
+    //   If it is driver, do not measure\r
+    //   If it is application, still measure.\r
+    //\r
+    ApplicationRequired = TRUE;\r
+\r
+    if (mTrEECacheMeasuredHandle != Handle && mTrEEMeasuredHobData != NULL) {\r
+      //\r
+      // Search for Root FV of this PE image\r
+      //\r
+      TempHandle = Handle;\r
+      do {\r
+        Status = gBS->HandleProtocol(\r
+                        TempHandle, \r
+                        &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                        (VOID**)&FvbProtocol\r
+                        );\r
+        TempHandle = FvbProtocol->ParentHandle;\r
+      } while (!EFI_ERROR(Status) && FvbProtocol->ParentHandle != NULL);\r
+\r
+      //\r
+      // Search in measured FV Hob\r
+      //\r
+      Status = FvbProtocol->GetPhysicalAddress(FvbProtocol, &FvAddress);\r
+      if (EFI_ERROR(Status)){\r
+        return Status;\r
+      }\r
+\r
+      ApplicationRequired = FALSE;\r
+\r
+      for (Index = 0; Index < mTrEEMeasuredHobData->Num; Index++) {\r
+        if(mTrEEMeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) {\r
+          //\r
+          // Cache measured FV for next measurement\r
+          //\r
+          mTrEECacheMeasuredHandle = Handle;\r
+          ApplicationRequired  = TRUE;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // File is not found.\r
+  //\r
+  if (FileBuffer == NULL) {\r
+    Status = EFI_SECURITY_VIOLATION;\r
+    goto Finish;\r
+  }\r
+\r
+  mTrEEImageSize  = FileSize;\r
+  mTrEEFileBuffer = FileBuffer;\r
+\r
+  //\r
+  // Measure PE Image\r
+  //\r
+  DevicePathNode = OrigDevicePathNode;\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+  ImageContext.Handle    = (VOID *) FileBuffer;\r
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeTpm2MeasureBootLibImageRead;\r
+\r
+  //\r
+  // Get information about the image being loaded\r
+  //\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // The information can't be got from the invalid PeImage\r
+    //\r
+    goto Finish;\r
+  }\r
+  \r
+  //\r
+  // Measure only application if Application flag is set\r
+  // Measure drivers and applications if Application flag is not set\r
+  //\r
+  if ((!ApplicationRequired) || \r
+        (ApplicationRequired && ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) {  \r
+    //\r
+    // Print the image path to be measured.\r
+    //    \r
+    DEBUG_CODE_BEGIN ();\r
+      CHAR16                            *ToText;\r
+      ToText = ConvertDevicePathToText (\r
+                 DevicePathNode,\r
+                 FALSE,\r
+                 TRUE\r
+                 );\r
+      if (ToText != NULL) {\r
+        DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));\r
+        FreePool (ToText);\r
+      }\r
+    DEBUG_CODE_END ();\r
+\r
+    //\r
+    // Measure PE image into TPM log.\r
+    //\r
+    Status = TrEEMeasurePeImage (\r
+               TreeProtocol,\r
+               (EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer, \r
+               FileSize, \r
+               (UINTN) ImageContext.ImageAddress, \r
+               ImageContext.ImageType, \r
+               DevicePathNode\r
+               );\r
+    DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler - TrEEMeasurePeImage - %r\n", Status));\r
+  }\r
+\r
+  //\r
+  // Done, free the allocated resource.\r
+  //\r
+Finish:\r
+  if (OrigDevicePathNode != NULL) {\r
+    FreePool (OrigDevicePathNode);\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler - %r\n", Status));\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Register the security handler to provide TPM measure boot service.\r
+\r
+  @param  ImageHandle  ImageHandle of the loaded driver.\r
+  @param  SystemTable  Pointer to the EFI System Table.\r
+\r
+  @retval  EFI_SUCCESS            Register successfully.\r
+  @retval  EFI_OUT_OF_RESOURCES   No enough memory to register this handler.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeTpm2MeasureBootLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE  *GuidHob;\r
+\r
+  GuidHob = NULL;\r
+\r
+  GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid);\r
+\r
+  if (GuidHob != NULL) {\r
+    mTrEEMeasuredHobData = GET_GUID_HOB_DATA (GuidHob);\r
+  }\r
+\r
+  return RegisterSecurity2Handler (\r
+          DxeTpm2MeasureBootHandler,\r
+          EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
+          );\r
+}\r
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
new file mode 100644 (file)
index 0000000..4dfd62b
--- /dev/null
@@ -0,0 +1,63 @@
+## @file\r
+#  The library instance provides security service of TPM2 measure boot.\r
+#\r
+#  Caution: This module requires additional review when modified.\r
+#  This library will have external input - PE/COFF image and GPT partition.\r
+#  This external input must be validated carefully to avoid security issue like\r
+#  buffer overflow, integer overflow.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DxeTpm2MeasureBootLib\r
+  FILE_GUID                      = 778CE4F4-36BD-4ae7-B8F0-10B420B0D174\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = NULL|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER \r
+  CONSTRUCTOR                    = DxeTpm2MeasureBootLibConstructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  DxeTpm2MeasureBootLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseMemoryLib\r
+  DebugLib\r
+  MemoryAllocationLib\r
+  DevicePathLib\r
+  UefiBootServicesTableLib\r
+  BaseCryptLib\r
+  PeCoffLib\r
+  BaseLib\r
+  SecurityManagementLib\r
+  HobLib\r
+\r
+[Guids]\r
+  gMeasuredFvHobGuid\r
+\r
+[Protocols]\r
+  gEfiTrEEProtocolGuid                   ## CONSUMES\r
+  gEfiFirmwareVolumeBlockProtocolGuid   ## CONSUMES\r
+  gEfiBlockIoProtocolGuid               ## CONSUMES\r
+  gEfiDiskIoProtocolGuid                ## CONSUMES\r
+\r
index b4732bc6fb50ca82e0f58e4899d2bf34fe362adf..ffeac59ba4d5f5d7d420bd386bc1cc6a6602070c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   This library is used by other modules to measure data to TPM.\r
 \r
-Copyright (c) 2012, Intel Corporation. All rights reserved. <BR>\r
+Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved. <BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -15,6 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <PiDxe.h>\r
 \r
 #include <Protocol/TcgService.h>\r
+#include <Protocol/TrEEProtocol.h>\r
 \r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
@@ -93,6 +94,67 @@ Tpm12MeasureAndLogData (
   return Status;\r
 }\r
 \r
+/**\r
+  Tpm20 measure and log data, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in]  PcrIndex         PCR Index.\r
+  @param[in]  EventType        Event type.\r
+  @param[in]  EventLog         Measurement event log.\r
+  @param[in]  LogLen           Event log length in bytes.\r
+  @param[in]  HashData         The start of the data buffer to be hashed, extended.\r
+  @param[in]  HashDataLen      The length, in bytes, of the buffer referenced by HashData\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_UNSUPPORTED       TPM device not available.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+Tpm20MeasureAndLogData (\r
+  IN UINT32             PcrIndex,\r
+  IN UINT32             EventType,\r
+  IN VOID               *EventLog,\r
+  IN UINT32             LogLen,\r
+  IN VOID               *HashData,\r
+  IN UINT64             HashDataLen\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_TREE_PROTOCOL         *TreeProtocol;\r
+  TrEE_EVENT                *TreeEvent;\r
+\r
+  //\r
+  // TrEEPresentFlag is checked in HashLogExtendEvent\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  TreeEvent = (TrEE_EVENT *) AllocateZeroPool (LogLen + sizeof (TrEE_EVENT));\r
+  if(TreeEvent == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TreeEvent->Size = (UINT32)LogLen + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event);\r
+  TreeEvent->Header.HeaderSize    = sizeof(TrEE_EVENT_HEADER);\r
+  TreeEvent->Header.HeaderVersion = TREE_EVENT_HEADER_VERSION;\r
+  TreeEvent->Header.PCRIndex      = PcrIndex;\r
+  TreeEvent->Header.EventType     = EventType;\r
+  CopyMem (&TreeEvent->Event[0], EventLog, LogLen);\r
+\r
+  Status = TreeProtocol->HashLogExtendEvent (\r
+                           TreeProtocol,\r
+                           0,\r
+                           (EFI_PHYSICAL_ADDRESS)(UINTN)HashData,\r
+                           HashDataLen,\r
+                           TreeEvent\r
+                           );\r
+  FreePool (TreeEvent);\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Tpm measure and log data, and extend the measurement result into a specific PCR.\r
 \r
@@ -132,6 +194,19 @@ TpmMeasureAndLogData (
                HashData,\r
                HashDataLen\r
                );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Try to measure using Tpm20 protocol\r
+    //\r
+    Status = Tpm20MeasureAndLogData(\r
+               PcrIndex,\r
+               EventType,\r
+               EventLog,\r
+               LogLen,\r
+               HashData,\r
+               HashDataLen\r
+               );\r
+  }\r
 \r
   return Status;\r
 }\r
index a09900f5562ddc66fe099e33aedaf28c4f6e47fa..75cc7730700b96f83aeb160089278264faba9c23 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
-#  This library is used by other modules to measure data to TPM 1.2.\r
+#  This library is used by other modules to measure data to TPM 1.2 or TPM 2.0.\r
 #\r
-# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
@@ -40,4 +40,5 @@
   UefiBootServicesTableLib\r
 \r
 [Protocols]\r
-  gEfiTcgProtocolGuid
\ No newline at end of file
+  gEfiTcgProtocolGuid\r
+  gEfiTrEEProtocolGuid\r
diff --git a/SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.c b/SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.c
new file mode 100644 (file)
index 0000000..28b809b
--- /dev/null
@@ -0,0 +1,716 @@
+/** @file\r
+  Execute pending TPM2 requests from OS or BIOS.\r
+\r
+  Caution: This module requires additional review when modified.\r
+  This driver will have external input - variable.\r
+  This external input must be validated carefully to avoid security issue.\r
+\r
+  TrEEExecutePendingTpmRequest() will receive untrusted input and do validation.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/TrEEProtocol.h>\r
+#include <Protocol/VariableLock.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/TrEEPhysicalPresenceData.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+\r
+#define TPM_PP_SUCCESS              0\r
+#define TPM_PP_USER_ABORT           ((TPM_RESULT)(-0x10))\r
+#define TPM_PP_BIOS_FAILURE         ((TPM_RESULT)(-0x0f))\r
+\r
+#define CONFIRM_BUFFER_SIZE         4096\r
+\r
+EFI_HII_HANDLE mTrEEPpStringPackHandle;\r
+\r
+/**\r
+  Get string by string id from HII Interface.\r
+\r
+  @param[in] Id          String ID.\r
+\r
+  @retval    CHAR16 *    String from ID.\r
+  @retval    NULL        If error occurs.\r
+\r
+**/\r
+CHAR16 *\r
+TrEEPhysicalPresenceGetStringById (\r
+  IN  EFI_STRING_ID   Id\r
+  )\r
+{\r
+  return HiiGetString (mTrEEPpStringPackHandle, Id, NULL);\r
+}\r
+\r
+/**\r
+  Send ClearControl and Clear command to TPM.\r
+\r
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_TIMEOUT           The register can't run into the expected status in time.\r
+  @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.\r
+  @retval EFI_DEVICE_ERROR      Unexpected device behavior.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TpmCommandClear (\r
+  IN TPM2B_AUTH                *PlatformAuth  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPMS_AUTH_COMMAND         *AuthSession;\r
+  TPMS_AUTH_COMMAND         LocalAuthSession;\r
+\r
+  if (PlatformAuth == NULL) {\r
+    AuthSession = NULL;\r
+  } else {\r
+    AuthSession = &LocalAuthSession;\r
+    ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));\r
+    LocalAuthSession.sessionHandle = TPM_RS_PW;\r
+    LocalAuthSession.hmac.size = PlatformAuth->size;\r
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "Tpm2ClearControl ... \n"));\r
+  Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);\r
+  DEBUG ((EFI_D_ERROR, "Tpm2ClearControl - %r\n", Status));\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+  DEBUG ((EFI_D_ERROR, "Tpm2Clear ... \n"));\r
+  Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);\r
+  DEBUG ((EFI_D_ERROR, "Tpm2Clear - %r\n", Status));\r
+\r
+Done:\r
+  ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Execute physical presence operation requested by the OS.\r
+\r
+  @param[in]      PlatformAuth        platform auth value. NULL means no platform auth change.\r
+  @param[in]      CommandCode         Physical presence operation value.\r
+  @param[in, out] PpiFlags            The physical presence interface flags.\r
+  \r
+  @retval TPM_PP_BIOS_FAILURE         Unknown physical presence operation.\r
+  @retval TPM_PP_BIOS_FAILURE         Error occurred during sending command to TPM or \r
+                                      receiving response from TPM.\r
+  @retval Others                      Return code from the TPM device after command execution.\r
+**/\r
+TPM_RESULT\r
+TrEEExecutePhysicalPresence (\r
+  IN      TPM2B_AUTH                *PlatformAuth,  OPTIONAL\r
+  IN      UINT8                     CommandCode,\r
+  IN OUT  UINT8                     *PpiFlags\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  switch (CommandCode) {\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
+      Status = TpmCommandClear (PlatformAuth);\r
+      if (EFI_ERROR (Status)) {\r
+        return TPM_PP_BIOS_FAILURE;\r
+      } else {\r
+        return TPM_PP_SUCCESS;\r
+      }\r
+\r
+    case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
+      *PpiFlags &= ~TREE_FLAG_NO_PPI_CLEAR;\r
+      return TPM_PP_SUCCESS;\r
+\r
+    case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
+      *PpiFlags |= TREE_FLAG_NO_PPI_CLEAR;\r
+      return TPM_PP_SUCCESS;\r
+\r
+    default:\r
+      if (CommandCode <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
+        return TPM_PP_SUCCESS;\r
+      } else {\r
+        return TPM_PP_BIOS_FAILURE;\r
+      }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Read the specified key for user confirmation.\r
+\r
+  @param[in]  CautionKey  If true,  F12 is used as confirm key;\r
+                          If false, F10 is used as confirm key.\r
+\r
+  @retval     TRUE        User confirmed the changes by input.\r
+  @retval     FALSE       User discarded the changes.\r
+**/\r
+BOOLEAN\r
+TrEEReadUserKey (\r
+  IN     BOOLEAN                    CautionKey\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_INPUT_KEY                     Key;\r
+  UINT16                            InputKey;\r
+      \r
+  InputKey = 0; \r
+  do {\r
+    Status = gBS->CheckEvent (gST->ConIn->WaitForKey);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+      if (Key.ScanCode == SCAN_ESC) {\r
+        InputKey = Key.ScanCode;\r
+      }\r
+      if ((Key.ScanCode == SCAN_F10) && !CautionKey) {\r
+        InputKey = Key.ScanCode;\r
+      }\r
+      if ((Key.ScanCode == SCAN_F12) && CautionKey) {\r
+        InputKey = Key.ScanCode;\r
+      }\r
+    }      \r
+  } while (InputKey == 0);\r
+\r
+  if (InputKey != SCAN_ESC) {\r
+    return TRUE;\r
+  }\r
+  \r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  The constructor function register UNI strings into imageHandle.\r
+  \r
+  It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. \r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+  \r
+  @retval EFI_SUCCESS   The constructor successfully added string package.\r
+  @retval Other value   The constructor can't add string package.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEPhysicalPresenceLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  mTrEEPpStringPackHandle = HiiAddPackages (&gEfiTrEEPhysicalPresenceGuid, ImageHandle, DxeTrEEPhysicalPresenceLibStrings, NULL);\r
+  ASSERT (mTrEEPpStringPackHandle != NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Display the confirm text and get user confirmation.\r
+\r
+  @param[in] TpmPpCommand  The requested TPM physical presence command.\r
+\r
+  @retval    TRUE          The user has confirmed the changes.\r
+  @retval    FALSE         The user doesn't confirm the changes.\r
+**/\r
+BOOLEAN\r
+TrEEUserConfirm (\r
+  IN      UINT8                     TpmPpCommand\r
+  )\r
+{\r
+  CHAR16                            *ConfirmText;\r
+  CHAR16                            *TmpStr1;\r
+  CHAR16                            *TmpStr2; \r
+  UINTN                             BufSize;\r
+  BOOLEAN                           CautionKey;\r
+  UINT16                            Index;\r
+  CHAR16                            DstStr[81];\r
+    \r
+  TmpStr2     = NULL;\r
+  CautionKey  = FALSE;\r
+  BufSize     = CONFIRM_BUFFER_SIZE;\r
+  ConfirmText = AllocateZeroPool (BufSize);\r
+  ASSERT (ConfirmText != NULL);\r
+\r
+  switch (TpmPpCommand) {\r
+\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
+      CautionKey = TRUE;\r
+      TmpStr2 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
+      StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);      \r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
+      StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);\r
+      break;\r
+\r
+    case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
+      CautionKey = TRUE;\r
+      TmpStr2 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));\r
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));\r
+      StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
+      StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1); \r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
+      StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);\r
+\r
+      TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));\r
+      StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+      FreePool (TmpStr1);\r
+      break;\r
+\r
+    default:\r
+      ;\r
+  }\r
+\r
+  if (TmpStr2 == NULL) {\r
+    FreePool (ConfirmText);\r
+    return FALSE;\r
+  }\r
+\r
+  TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));\r
+  BufSize -= StrSize (ConfirmText);\r
+  UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);\r
+\r
+  DstStr[80] = L'\0';\r
+  for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {\r
+    StrnCpy(DstStr, ConfirmText + Index, 80);    \r
+    Print (DstStr);    \r
+  }\r
+  \r
+  FreePool (TmpStr1);\r
+  FreePool (TmpStr2);\r
+  FreePool (ConfirmText);\r
+\r
+  if (TrEEReadUserKey (CautionKey)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;  \r
+}\r
+\r
+/**\r
+  Check if there is a valid physical presence command request. Also updates parameter value \r
+  to whether the requested physical presence command already confirmed by user\r
\r
+   @param[in]  TcgPpData                 EFI TrEE Physical Presence request data. \r
+   @param[in]  Flags                     The physical presence interface flags.\r
+   @param[out] RequestConfirmed            If the physical presence operation command required user confirm from UI.\r
+                                             True, it indicates the command doesn't require user confirm, or already confirmed \r
+                                                   in last boot cycle by user.\r
+                                             False, it indicates the command need user confirm from UI.\r
+\r
+   @retval  TRUE        Physical Presence operation command is valid.\r
+   @retval  FALSE       Physical Presence operation command is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+TrEEHaveValidTpmRequest  (\r
+  IN      EFI_TREE_PHYSICAL_PRESENCE     *TcgPpData,\r
+  IN      UINT8                          Flags,\r
+  OUT     BOOLEAN                        *RequestConfirmed\r
+  )\r
+{\r
+  *RequestConfirmed = FALSE;\r
+\r
+  switch (TcgPpData->PPRequest) {\r
+    case TREE_PHYSICAL_PRESENCE_NO_ACTION:\r
+      *RequestConfirmed = TRUE;\r
+      return TRUE;\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
+      if ((Flags & TREE_FLAG_NO_PPI_CLEAR) != 0) {\r
+        *RequestConfirmed = TRUE;\r
+      }\r
+      break;\r
+\r
+    case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
+      *RequestConfirmed = TRUE;\r
+      break;\r
+\r
+    case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // Wrong Physical Presence command\r
+      //\r
+      return FALSE;\r
+  }\r
+\r
+  if ((Flags & TREE_FLAG_RESET_TRACK) != 0) {\r
+    //\r
+    // It had been confirmed in last boot, it doesn't need confirm again.\r
+    //\r
+    *RequestConfirmed = TRUE;\r
+  }\r
+\r
+  //\r
+  // Physical Presence command is correct\r
+  //\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Check and execute the requested physical presence command.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  TcgPpData variable is external input, so this function will validate\r
+  its data structure to be valid value.\r
+\r
+  @param[in] PlatformAuth         platform auth value. NULL means no platform auth change.\r
+  @param[in] TcgPpData            Point to the physical presence NV variable.\r
+  @param[in] Flags                The physical presence interface flags.\r
+**/\r
+VOID\r
+TrEEExecutePendingTpmRequest (\r
+  IN      TPM2B_AUTH                     *PlatformAuth,  OPTIONAL\r
+  IN      EFI_TREE_PHYSICAL_PRESENCE     *TcgPpData,\r
+  IN      UINT8                          Flags\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             DataSize;\r
+  BOOLEAN                           RequestConfirmed;\r
+  UINT8                             NewFlags;\r
+\r
+  if (TcgPpData->PPRequest == TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
+    //\r
+    // No operation request\r
+    //\r
+    return;\r
+  }\r
+\r
+  if (!TrEEHaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {\r
+    //\r
+    // Invalid operation request.\r
+    //\r
+    if (TcgPpData->PPRequest <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
+      TcgPpData->PPResponse = TPM_PP_SUCCESS;\r
+    } else {\r
+      TcgPpData->PPResponse = TPM_PP_BIOS_FAILURE;\r
+    }\r
+    TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
+    TcgPpData->PPRequest = TREE_PHYSICAL_PRESENCE_NO_ACTION;\r
+    DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+    Status = gRT->SetVariable (\r
+                    TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                    &gEfiTrEEPhysicalPresenceGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    DataSize,\r
+                    TcgPpData\r
+                    );\r
+    return;\r
+  }\r
+\r
+  if (!RequestConfirmed) {\r
+    //\r
+    // Print confirm text and wait for approval. \r
+    //\r
+    RequestConfirmed = TrEEUserConfirm (TcgPpData->PPRequest\r
+                                        );\r
+  }\r
+\r
+  //\r
+  // Execute requested physical presence command\r
+  //\r
+  TcgPpData->PPResponse = TPM_PP_USER_ABORT;\r
+  NewFlags = Flags;\r
+  if (RequestConfirmed) {\r
+    TcgPpData->PPResponse = TrEEExecutePhysicalPresence (PlatformAuth, TcgPpData->PPRequest, \r
+                                                         &NewFlags);\r
+  }\r
+\r
+  //\r
+  // Save the flags if it is updated.\r
+  //\r
+  if (Flags != NewFlags) {\r
+    Status   = gRT->SetVariable (\r
+                      TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                      &gEfiTrEEPhysicalPresenceGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      sizeof (UINT8),\r
+                      &NewFlags\r
+                      ); \r
+  }\r
+\r
+  //\r
+  // Clear request\r
+  //\r
+  if ((NewFlags & TREE_FLAG_RESET_TRACK) == 0) {\r
+    TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
+    TcgPpData->PPRequest = TREE_PHYSICAL_PRESENCE_NO_ACTION;    \r
+  }\r
+\r
+  //\r
+  // Save changes\r
+  //\r
+  DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+  Status = gRT->SetVariable (\r
+                  TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTrEEPhysicalPresenceGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  DataSize,\r
+                  TcgPpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  if (TcgPpData->PPResponse == TPM_PP_USER_ABORT) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Reset system to make new TPM settings in effect\r
+  //\r
+  switch (TcgPpData->LastPPRequest) {\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
+    case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
+      break;\r
+    default:\r
+      if (TcgPpData->PPRequest != TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
+        break;\r
+      }\r
+      return;\r
+  }\r
+\r
+  Print (L"Rebooting system to make TPM2 settings in effect\n");\r
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+  ASSERT (FALSE);  \r
+}\r
+\r
+/**\r
+  Check and execute the pending TPM request.\r
+\r
+  The TPM request may come from OS or BIOS. This API will display request information and wait \r
+  for user confirmation if TPM request exists. The TPM request will be sent to TPM device after\r
+  the TPM request is confirmed, and one or more reset may be required to make TPM request to \r
+  take effect.\r
+  \r
+  This API should be invoked after console in and console out are all ready as they are required\r
+  to display request information and get user input to confirm the request.  \r
+\r
+  @param[in]  PlatformAuth                   platform auth value. NULL means no platform auth change.\r
+**/\r
+VOID\r
+EFIAPI\r
+TrEEPhysicalPresenceLibProcessRequest (\r
+  IN      TPM2B_AUTH                     *PlatformAuth  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             DataSize;\r
+  EFI_TREE_PHYSICAL_PRESENCE        TcgPpData;\r
+  EFI_TREE_PROTOCOL                 *TreeProtocol;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;\r
+  UINT8                             PpiFlags;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // Initialize physical presence flags.\r
+  //\r
+  DataSize = sizeof (UINT8);\r
+  Status = gRT->GetVariable (\r
+                  TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                  &gEfiTrEEPhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpiFlags\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      PpiFlags = 0;\r
+      Status   = gRT->SetVariable (\r
+                        TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                        &gEfiTrEEPhysicalPresenceGuid,\r
+                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                        sizeof (UINT8),\r
+                        &PpiFlags\r
+                        );\r
+    }\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+  DEBUG ((EFI_D_ERROR, "[TPM2] PpiFlags = %x, Status = %r\n", PpiFlags, Status));\r
+\r
+  //\r
+  // This flags variable controls whether physical presence is required for TPM command. \r
+  // It should be protected from malicious software. We set it as read-only variable here.\r
+  //\r
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = VariableLockProtocol->RequestToLock (\r
+                                     VariableLockProtocol,\r
+                                     TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                                     &gEfiTrEEPhysicalPresenceGuid\r
+                                     );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Initialize physical presence variable.\r
+  //\r
+  DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+  Status = gRT->GetVariable (\r
+                  TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTrEEPhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &TcgPpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));\r
+      DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+      Status   = gRT->SetVariable (\r
+                        TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                        &gEfiTrEEPhysicalPresenceGuid,\r
+                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                        DataSize,\r
+                        &TcgPpData\r
+                        );\r
+    }\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));\r
+\r
+  //\r
+  // Execute pending TPM request.\r
+  //  \r
+  TrEEExecutePendingTpmRequest (PlatformAuth, &TcgPpData, PpiFlags);\r
+  DEBUG ((EFI_D_ERROR, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags));\r
+\r
+}\r
+\r
+/**\r
+  Check if the pending TPM request needs user input to confirm.\r
+\r
+  The TPM request may come from OS. This API will check if TPM request exists and need user\r
+  input to confirmation.\r
+  \r
+  @retval    TRUE        TPM needs input to confirm user physical presence.\r
+  @retval    FALSE       TPM doesn't need input to confirm user physical presence.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TrEEPhysicalPresenceLibNeedUserConfirm(\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_TREE_PHYSICAL_PRESENCE        TcgPpData;\r
+  UINTN                             DataSize;\r
+  BOOLEAN                           RequestConfirmed;\r
+  EFI_TREE_PROTOCOL                 *TreeProtocol;\r
+  UINT8                             PpiFlags;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check Tpm requests\r
+  //\r
+  DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+  Status = gRT->GetVariable (\r
+                  TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTrEEPhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &TcgPpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  DataSize = sizeof (UINT8);\r
+  Status = gRT->GetVariable (\r
+                  TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                  &gEfiTrEEPhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpiFlags\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  \r
+  if (TcgPpData.PPRequest == TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
+    //\r
+    // No operation request\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  if (!TrEEHaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {\r
+    //\r
+    // Invalid operation request.\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  if (!RequestConfirmed) {\r
+    //\r
+    // Need UI to confirm\r
+    //\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
diff --git a/SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf b/SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf
new file mode 100644 (file)
index 0000000..3ef9a82
--- /dev/null
@@ -0,0 +1,59 @@
+## @file\r
+# TrEE physical presence library instance. This library will execute TPM2 request.\r
+#\r
+#  Caution: This module requires additional review when modified.\r
+#  This driver will have external input - variable.\r
+#  This external input must be validated carefully to avoid security issue.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DxeTrEEPhysicalPresenceLib   \r
+  FILE_GUID                      = 601ECB06-7874-489e-A280-805780F6C861\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TrEEPhysicalPresenceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_APPLICATION UEFI_DRIVER \r
+  CONSTRUCTOR                    = TrEEPhysicalPresenceLibConstructor\r
+  \r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  DxeTrEEPhysicalPresenceLib.c\r
+  PhysicalPresenceStrings.uni\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  UefiRuntimeServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PrintLib\r
+  HiiLib\r
+  Tpm2CommandLib\r
+\r
+[Protocols]\r
+  gEfiTrEEProtocolGuid\r
+  gEdkiiVariableLockProtocolGuid\r
+\r
+[Guids]\r
+  gEfiTrEEPhysicalPresenceGuid\r
diff --git a/SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/PhysicalPresenceStrings.uni b/SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/PhysicalPresenceStrings.uni
new file mode 100644 (file)
index 0000000..26c10ac
Binary files /dev/null and b/SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/PhysicalPresenceStrings.uni differ
diff --git a/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.c b/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.c
new file mode 100644 (file)
index 0000000..a42c60d
--- /dev/null
@@ -0,0 +1,155 @@
+/** @file\r
+  Ihis library is BaseCrypto SHA1 hash instance.\r
+  It can be registered to BaseCrypto router, to serve as hash engine.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HashLib.h>\r
+\r
+/**\r
+  The function set SHA1 to digest list.\r
+\r
+  @param DigestList digest list\r
+  @param Sha1Digest SHA1 digest\r
+**/\r
+VOID\r
+Tpm2SetSha1ToDigestList (\r
+  IN TPML_DIGEST_VALUES *DigestList,\r
+  IN UINT8              *Sha1Digest\r
+  )\r
+{\r
+  DigestList->count = 1;\r
+  DigestList->digests[0].hashAlg = TPM_ALG_SHA1;\r
+  CopyMem (\r
+    DigestList->digests[0].digest.sha1,\r
+    Sha1Digest,\r
+    SHA1_DIGEST_SIZE\r
+    );\r
+}\r
+\r
+/**\r
+  Start hash sequence.\r
+\r
+  @param HashHandle Hash handle.\r
+\r
+  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.\r
+  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Sha1HashInit (\r
+  OUT HASH_HANDLE    *HashHandle\r
+  )\r
+{\r
+  VOID     *Sha1Ctx;\r
+  UINTN    CtxSize;\r
+\r
+  CtxSize = Sha1GetContextSize ();\r
+  Sha1Ctx = AllocatePool (CtxSize);\r
+  ASSERT (Sha1Ctx != NULL);\r
+\r
+  Sha1Init (Sha1Ctx);\r
+\r
+  *HashHandle = (HASH_HANDLE)Sha1Ctx;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update hash sequence data.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence updated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Sha1HashUpdate (\r
+  IN HASH_HANDLE    HashHandle,\r
+  IN VOID           *DataToHash,\r
+  IN UINTN          DataToHashLen\r
+  )\r
+{\r
+  VOID     *Sha1Ctx;\r
+\r
+  Sha1Ctx = (VOID *)HashHandle;\r
+  Sha1Update (Sha1Ctx, DataToHash, DataToHashLen);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Complete hash sequence complete.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Sha1HashFinal (\r
+  IN HASH_HANDLE         HashHandle,\r
+  OUT TPML_DIGEST_VALUES *DigestList\r
+  )\r
+{\r
+  UINT8         Digest[SHA1_DIGEST_SIZE];\r
+  VOID          *Sha1Ctx;\r
+\r
+  Sha1Ctx = (VOID *)HashHandle;\r
+  Sha1Final (Sha1Ctx, Digest);\r
+\r
+  FreePool (Sha1Ctx);\r
+  \r
+  Tpm2SetSha1ToDigestList (DigestList, Digest);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+HASH_INTERFACE  mSha1InternalHashInstance = {\r
+  HASH_ALGORITHM_SHA1_GUID,\r
+  Sha1HashInit,\r
+  Sha1HashUpdate,\r
+  Sha1HashFinal,\r
+};\r
+\r
+/**\r
+  The function register SHA1 instance.\r
+  \r
+  @retval EFI_SUCCESS   SHA1 instance is registered, or system dose not surpport registr SHA1 instance\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashInstanceLibSha1Constructor (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = RegisterHashInterfaceLib (&mSha1InternalHashInstance);\r
+  if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) {\r
+    //\r
+    // Unsupported means platform policy does not need this instance enabled.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  return Status;\r
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf b/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
new file mode 100644 (file)
index 0000000..d5fe6fe
--- /dev/null
@@ -0,0 +1,44 @@
+## @file\r
+#  Ihis library is BaseCrypto SHA1 hash instance.\r
+#  It can be registered to BaseCrypto router, to serve as hash engine.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = HashInstanceLibSha1\r
+  FILE_GUID                      = 9A7A6AB4-9DA6-4aa4-90CB-6D4B79EDA7B9\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = NULL\r
+  CONSTRUCTOR                    = HashInstanceLibSha1Constructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  HashInstanceLibSha1.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2CommandLib\r
+  MemoryAllocationLib\r
+  BaseCryptLib\r
diff --git a/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.c b/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.c
new file mode 100644 (file)
index 0000000..abc97b4
--- /dev/null
@@ -0,0 +1,155 @@
+/** @file\r
+  Ihis library is BaseCrypto SHA256 hash instance.\r
+  It can be registered to BaseCrypto router, to serve as hash engine.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HashLib.h>\r
+\r
+/**\r
+  The function set SHA256 to digest list.\r
+\r
+  @param DigestList   digest list\r
+  @param Sha256Digest SHA256 digest\r
+**/\r
+VOID\r
+Tpm2SetSha256ToDigestList (\r
+  IN TPML_DIGEST_VALUES *DigestList,\r
+  IN UINT8              *Sha256Digest\r
+  )\r
+{\r
+  DigestList->count = 1;\r
+  DigestList->digests[0].hashAlg = TPM_ALG_SHA256;\r
+  CopyMem (\r
+    DigestList->digests[0].digest.sha256,\r
+    Sha256Digest,\r
+    SHA256_DIGEST_SIZE\r
+    );\r
+}\r
+\r
+/**\r
+  Start hash sequence.\r
+\r
+  @param HashHandle Hash handle.\r
+\r
+  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.\r
+  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Sha256HashInit (\r
+  OUT HASH_HANDLE    *HashHandle\r
+  )\r
+{\r
+  VOID     *Sha256Ctx;\r
+  UINTN    CtxSize;\r
+\r
+  CtxSize = Sha256GetContextSize ();\r
+  Sha256Ctx = AllocatePool (CtxSize);\r
+  ASSERT (Sha256Ctx != NULL);\r
+\r
+  Sha256Init (Sha256Ctx);\r
+\r
+  *HashHandle = (HASH_HANDLE)Sha256Ctx;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update hash sequence data.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence updated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Sha256HashUpdate (\r
+  IN HASH_HANDLE    HashHandle,\r
+  IN VOID           *DataToHash,\r
+  IN UINTN          DataToHashLen\r
+  )\r
+{\r
+  VOID     *Sha256Ctx;\r
+\r
+  Sha256Ctx = (VOID *)HashHandle;\r
+  Sha256Update (Sha256Ctx, DataToHash, DataToHashLen);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Complete hash sequence complete.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Sha256HashFinal (\r
+  IN HASH_HANDLE         HashHandle,\r
+  OUT TPML_DIGEST_VALUES *DigestList\r
+  )\r
+{\r
+  UINT8         Digest[SHA256_DIGEST_SIZE];\r
+  VOID          *Sha256Ctx;\r
+\r
+  Sha256Ctx = (VOID *)HashHandle;\r
+  Sha256Final (Sha256Ctx, Digest);\r
+\r
+  FreePool (Sha256Ctx);\r
+  \r
+  Tpm2SetSha256ToDigestList (DigestList, Digest);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+HASH_INTERFACE  mSha256InternalHashInstance = {\r
+  HASH_ALGORITHM_SHA256_GUID,\r
+  Sha256HashInit,\r
+  Sha256HashUpdate,\r
+  Sha256HashFinal,\r
+};\r
+\r
+/**\r
+  The function register SHA256 instance.\r
+  \r
+  @retval EFI_SUCCESS   SHA256 instance is registered, or system dose not surpport registr SHA256 instance\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashInstanceLibSha256Constructor (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = RegisterHashInterfaceLib (&mSha256InternalHashInstance);\r
+  if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) {\r
+    //\r
+    // Unsupported means platform policy does not need this instance enabled.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  return Status;\r
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf b/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
new file mode 100644 (file)
index 0000000..a1fb891
--- /dev/null
@@ -0,0 +1,44 @@
+## @file\r
+#  Ihis library is BaseCrypto SHA256 hash instance.\r
+#  It can be registered to BaseCrypto router, to serve as hash engine.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = HashInstanceLibSha256\r
+  FILE_GUID                      = 5810798A-ED30-4080-8DD7-B9667A748C02\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = NULL\r
+  CONSTRUCTOR                    = HashInstanceLibSha256Constructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  HashInstanceLibSha256.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2CommandLib\r
+  MemoryAllocationLib\r
+  BaseCryptLib\r
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.c
new file mode 100644 (file)
index 0000000..833cce2
--- /dev/null
@@ -0,0 +1,77 @@
+/** @file\r
+  Ihis is BaseCrypto router support function.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+typedef struct {\r
+  EFI_GUID  Guid;\r
+  UINT32    Mask;\r
+} TPM2_HASH_MASK;\r
+\r
+TPM2_HASH_MASK mTpm2HashMask[] = {\r
+  {HASH_ALGORITHM_SHA1_GUID,         TREE_BOOT_HASH_ALG_SHA1},\r
+  {HASH_ALGORITHM_SHA256_GUID,       TREE_BOOT_HASH_ALG_SHA256},\r
+  {HASH_ALGORITHM_SHA384_GUID,       TREE_BOOT_HASH_ALG_SHA384},\r
+  {HASH_ALGORITHM_SHA512_GUID,       TREE_BOOT_HASH_ALG_SHA512},\r
+};\r
+\r
+/**\r
+  The function get hash mask info from algorithm.\r
+\r
+  @param HashGuid Hash Guid\r
+\r
+  @return HashMask\r
+**/\r
+UINT32\r
+EFIAPI\r
+Tpm2GetHashMaskFromAlgo (\r
+  IN EFI_GUID  *HashGuid\r
+  )\r
+{\r
+  UINTN  Index;\r
+  for (Index = 0; Index < sizeof(mTpm2HashMask)/sizeof(mTpm2HashMask[0]); Index++) {\r
+    if (CompareGuid (HashGuid, &mTpm2HashMask[Index].Guid)) {\r
+      return mTpm2HashMask[Index].Mask;\r
+    }\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+  The function set digest to digest list.\r
+\r
+  @param DigestList digest list\r
+  @param Digest     digest data\r
+**/\r
+VOID\r
+EFIAPI\r
+Tpm2SetHashToDigestList (\r
+  IN OUT TPML_DIGEST_VALUES *DigestList,\r
+  IN TPML_DIGEST_VALUES     *Digest\r
+  )\r
+{\r
+  CopyMem (\r
+    &DigestList->digests[DigestList->count],\r
+    &Digest->digests[0],\r
+    sizeof(Digest->digests[0])\r
+    );\r
+  DigestList->count ++;\r
+}\r
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.h b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.h
new file mode 100644 (file)
index 0000000..f0ea3ca
--- /dev/null
@@ -0,0 +1,44 @@
+/** @file\r
+  Ihis is BaseCrypto router support function definition.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _HASH_LIB_BASE_CRYPTO_ROUTER_COMMON_H_\r
+#define _HASH_LIB_BASE_CRYPTO_ROUTER_COMMON_H_\r
+\r
+/**\r
+  The function get hash mask info from algorithm.\r
+\r
+  @param HashGuid Hash Guid\r
+\r
+  @return HashMask\r
+**/\r
+UINT32\r
+EFIAPI\r
+Tpm2GetHashMaskFromAlgo (\r
+  IN EFI_GUID  *HashGuid\r
+  );\r
+\r
+/**\r
+  The function set digest to digest list.\r
+\r
+  @param DigestList digest list\r
+  @param Digest     digest data\r
+**/\r
+VOID\r
+EFIAPI\r
+Tpm2SetHashToDigestList (\r
+  IN OUT TPML_DIGEST_VALUES *DigestList,\r
+  IN TPML_DIGEST_VALUES     *Digest\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
new file mode 100644 (file)
index 0000000..8e93335
--- /dev/null
@@ -0,0 +1,221 @@
+/** @file\r
+  Ihis library is BaseCrypto router. It will redirect hash request to each individual\r
+  hash handler registerd, such as SHA1, SHA256.\r
+  Platform can use PcdTpm2HashMask to mask some hash engines.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/HashLib.h>\r
+\r
+#include "HashLibBaseCryptoRouterCommon.h"\r
+\r
+HASH_INTERFACE   mHashInterface[HASH_COUNT] = {0};\r
+UINTN            mHashInterfaceCount = 0;\r
+\r
+/**\r
+  Start hash sequence.\r
+\r
+  @param HashHandle Hash handle.\r
+\r
+  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.\r
+  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashStart (\r
+  OUT HASH_HANDLE    *HashHandle\r
+  )\r
+{\r
+  HASH_HANDLE  *HashCtx;\r
+  UINTN        Index;\r
+\r
+  if (mHashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashCtx = AllocatePool (sizeof(*HashCtx) * mHashInterfaceCount);\r
+  ASSERT (HashCtx != NULL);\r
+\r
+  for (Index = 0; Index < mHashInterfaceCount; Index++) {\r
+    mHashInterface[Index].HashInit (&HashCtx[Index]);\r
+  }\r
+\r
+  *HashHandle = (HASH_HANDLE)HashCtx;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update hash sequence data.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence updated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashUpdate (\r
+  IN HASH_HANDLE    HashHandle,\r
+  IN VOID           *DataToHash,\r
+  IN UINTN          DataToHashLen\r
+  )\r
+{\r
+  HASH_HANDLE  *HashCtx;\r
+  UINTN        Index;\r
+\r
+  if (mHashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashCtx = (HASH_HANDLE *)HashHandle;\r
+\r
+  for (Index = 0; Index < mHashInterfaceCount; Index++) {\r
+    mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Hash sequence complete and extend to PCR.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashCompleteAndExtend (\r
+  IN HASH_HANDLE         HashHandle,\r
+  IN TPMI_DH_PCR         PcrIndex,\r
+  IN VOID                *DataToHash,\r
+  IN UINTN               DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES *DigestList\r
+  )\r
+{\r
+  TPML_DIGEST_VALUES Digest;\r
+  HASH_HANDLE        *HashCtx;\r
+  UINTN              Index;\r
+  EFI_STATUS         Status;\r
+\r
+  if (mHashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashCtx = (HASH_HANDLE *)HashHandle;\r
+  ZeroMem (DigestList, sizeof(*DigestList));\r
+\r
+  for (Index = 0; Index < mHashInterfaceCount; Index++) {\r
+    mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);\r
+    mHashInterface[Index].HashFinal (HashCtx[Index], &Digest);\r
+    Tpm2SetHashToDigestList (DigestList, &Digest);\r
+  }\r
+\r
+  FreePool (HashCtx);\r
+\r
+  Status = Tpm2PcrExtend (\r
+             PcrIndex,\r
+             DigestList\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Hash data and extend to PCR.\r
+\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash data and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashAndExtend (\r
+  IN TPMI_DH_PCR                    PcrIndex,\r
+  IN VOID                           *DataToHash,\r
+  IN UINTN                          DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES            *DigestList\r
+  )\r
+{\r
+  HASH_HANDLE    HashHandle;\r
+  EFI_STATUS     Status;\r
+\r
+  if (mHashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashStart (&HashHandle);\r
+  HashUpdate (HashHandle, DataToHash, DataToHashLen);\r
+  Status = HashCompleteAndExtend (HashHandle, PcrIndex, NULL, 0, DigestList);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This service register Hash.\r
+\r
+  @param HashInterface  Hash interface\r
+\r
+  @retval EFI_SUCCESS          This hash interface is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this interface.\r
+  @retval EFI_ALREADY_STARTED  System already register this interface.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterHashInterfaceLib (\r
+  IN HASH_INTERFACE   *HashInterface\r
+  )\r
+{\r
+  UINTN              Index;\r
+  UINT32             HashMask;\r
+\r
+  //\r
+  // Check allow\r
+  //\r
+  HashMask = Tpm2GetHashMaskFromAlgo (&HashInterface->HashGuid);\r
+  if ((HashMask & PcdGet32 (PcdTpm2HashMask)) == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (mHashInterfaceCount >= sizeof(mHashInterface)/sizeof(mHashInterface[0])) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Check duplication\r
+  //\r
+  for (Index = 0; Index < mHashInterfaceCount; Index++) {\r
+    if (CompareGuid (&mHashInterface[Index].HashGuid, &HashInterface->HashGuid)) {\r
+      return EFI_ALREADY_STARTED;\r
+    }\r
+  }\r
+\r
+  CopyMem (&mHashInterface[mHashInterfaceCount], HashInterface, sizeof(*HashInterface));\r
+  mHashInterfaceCount ++;\r
+  \r
+  return EFI_SUCCESS;\r
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf
new file mode 100644 (file)
index 0000000..f2cf915
--- /dev/null
@@ -0,0 +1,49 @@
+## @file\r
+#  Ihis library is BaseCrypto router. It will redirect hash request to each individual\r
+#  hash handler registerd, such as SHA1, SHA256.\r
+#  Platform can use PcdTpm2HashMask to mask some hash engines.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = HashLibBaseCryptoRouterDxe\r
+  FILE_GUID                      = 158DC712-F15A-44dc-93BB-1675045BE066\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = HashLibBaseCrypto|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  HashLibBaseCryptoRouterCommon.h\r
+  HashLibBaseCryptoRouterCommon.c\r
+  HashLibBaseCryptoRouterDxe.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2CommandLib\r
+  MemoryAllocationLib\r
+  PcdLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask\r
+\r
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
new file mode 100644 (file)
index 0000000..1e7eb2d
--- /dev/null
@@ -0,0 +1,288 @@
+/** @file\r
+  Ihis library is BaseCrypto router. It will redirect hash request to each individual\r
+  hash handler registerd, such as SHA1, SHA256.\r
+  Platform can use PcdTpm2HashMask to mask some hash engines.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/HashLib.h>\r
+\r
+#include "HashLibBaseCryptoRouterCommon.h"\r
+\r
+#define HASH_LIB_PEI_ROUTER_GUID \\r
+  { 0x84681c08, 0x6873, 0x46f3, { 0x8b, 0xb7, 0xab, 0x66, 0x18, 0x95, 0xa1, 0xb3 } }\r
+\r
+EFI_GUID mHashLibPeiRouterGuid = HASH_LIB_PEI_ROUTER_GUID;\r
+\r
+typedef struct {\r
+  UINTN            HashInterfaceCount;\r
+  HASH_INTERFACE   HashInterface[HASH_COUNT];\r
+} HASH_INTERFACE_HOB;\r
+\r
+/**\r
+  This function get hash interface.\r
+\r
+  @retval hash interface.\r
+**/\r
+HASH_INTERFACE_HOB *\r
+InternalGetHashInterface (\r
+  VOID\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE *Hob;\r
+\r
+  Hob = GetFirstGuidHob (&mHashLibPeiRouterGuid);\r
+  if (Hob == NULL) {\r
+    return NULL;\r
+  }\r
+  return (HASH_INTERFACE_HOB *)(Hob + 1);\r
+}\r
+\r
+/**\r
+  Start hash sequence.\r
+\r
+  @param HashHandle Hash handle.\r
+\r
+  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.\r
+  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashStart (\r
+  OUT HASH_HANDLE    *HashHandle\r
+  )\r
+{\r
+  HASH_INTERFACE_HOB *HashInterfaceHob;\r
+  HASH_HANDLE        *HashCtx;\r
+  UINTN              Index;\r
+\r
+  HashInterfaceHob = InternalGetHashInterface ();\r
+  if (HashInterfaceHob == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (HashInterfaceHob->HashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashCtx = AllocatePool (sizeof(*HashCtx) * HashInterfaceHob->HashInterfaceCount);\r
+  ASSERT (HashCtx != NULL);\r
+\r
+  for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {\r
+    HashInterfaceHob->HashInterface[Index].HashInit (&HashCtx[Index]);\r
+  }\r
+\r
+  *HashHandle = (HASH_HANDLE)HashCtx;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update hash sequence data.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence updated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashUpdate (\r
+  IN HASH_HANDLE    HashHandle,\r
+  IN VOID           *DataToHash,\r
+  IN UINTN          DataToHashLen\r
+  )\r
+{\r
+  HASH_INTERFACE_HOB *HashInterfaceHob;\r
+  HASH_HANDLE        *HashCtx;\r
+  UINTN              Index;\r
+\r
+  HashInterfaceHob = InternalGetHashInterface ();\r
+  if (HashInterfaceHob == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (HashInterfaceHob->HashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashCtx = (HASH_HANDLE *)HashHandle;\r
+\r
+  for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {\r
+    HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Hash sequence complete and extend to PCR.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashCompleteAndExtend (\r
+  IN HASH_HANDLE         HashHandle,\r
+  IN TPMI_DH_PCR         PcrIndex,\r
+  IN VOID                *DataToHash,\r
+  IN UINTN               DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES *DigestList\r
+  )\r
+{\r
+  TPML_DIGEST_VALUES Digest;\r
+  HASH_INTERFACE_HOB *HashInterfaceHob;\r
+  HASH_HANDLE        *HashCtx;\r
+  UINTN              Index;\r
+  EFI_STATUS         Status;\r
+\r
+  HashInterfaceHob = InternalGetHashInterface ();\r
+  if (HashInterfaceHob == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (HashInterfaceHob->HashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashCtx = (HASH_HANDLE *)HashHandle;\r
+  ZeroMem (DigestList, sizeof(*DigestList));\r
+\r
+  for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {\r
+    HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);\r
+    HashInterfaceHob->HashInterface[Index].HashFinal (HashCtx[Index], &Digest);\r
+    Tpm2SetHashToDigestList (DigestList, &Digest);\r
+  }\r
+\r
+  FreePool (HashCtx);\r
+\r
+  Status = Tpm2PcrExtend (\r
+             PcrIndex,\r
+             DigestList\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Hash data and extend to PCR.\r
+\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash data and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashAndExtend (\r
+  IN TPMI_DH_PCR                    PcrIndex,\r
+  IN VOID                           *DataToHash,\r
+  IN UINTN                          DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES            *DigestList\r
+  )\r
+{\r
+  HASH_INTERFACE_HOB *HashInterfaceHob;\r
+  HASH_HANDLE        HashHandle;\r
+  EFI_STATUS         Status;\r
+\r
+  HashInterfaceHob = InternalGetHashInterface ();\r
+  if (HashInterfaceHob == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (HashInterfaceHob->HashInterfaceCount == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashStart (&HashHandle);\r
+  HashUpdate (HashHandle, DataToHash, DataToHashLen);\r
+  Status = HashCompleteAndExtend (HashHandle, PcrIndex, NULL, 0, DigestList);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This service register Hash.\r
+\r
+  @param HashInterface  Hash interface\r
+\r
+  @retval EFI_SUCCESS          This hash interface is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this interface.\r
+  @retval EFI_ALREADY_STARTED  System already register this interface.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterHashInterfaceLib (\r
+  IN HASH_INTERFACE   *HashInterface\r
+  )\r
+{\r
+  UINTN              Index;\r
+  HASH_INTERFACE_HOB *HashInterfaceHob;\r
+  HASH_INTERFACE_HOB LocalHashInterfaceHob;\r
+  UINT32             HashMask;\r
+\r
+  //\r
+  // Check allow\r
+  //\r
+  HashMask = Tpm2GetHashMaskFromAlgo (&HashInterface->HashGuid);\r
+  if ((HashMask & PcdGet32 (PcdTpm2HashMask)) == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HashInterfaceHob = InternalGetHashInterface ();\r
+  if (HashInterfaceHob == NULL) {\r
+    ZeroMem (&LocalHashInterfaceHob, sizeof(LocalHashInterfaceHob));\r
+    HashInterfaceHob = BuildGuidDataHob (&mHashLibPeiRouterGuid, &LocalHashInterfaceHob, sizeof(LocalHashInterfaceHob));\r
+    if (HashInterfaceHob == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+\r
+  if (HashInterfaceHob->HashInterfaceCount >= HASH_COUNT) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Check duplication\r
+  //\r
+  for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {\r
+    if (CompareGuid (&HashInterfaceHob->HashInterface[Index].HashGuid, &HashInterface->HashGuid)) {\r
+      //\r
+      // In PEI phase, there will be shadow driver dispatched again.\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "RegisterHashInterfaceLib - Override\n"));\r
+      CopyMem (&HashInterfaceHob->HashInterface[Index], HashInterface, sizeof(*HashInterface));\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  CopyMem (&HashInterfaceHob->HashInterface[HashInterfaceHob->HashInterfaceCount], HashInterface, sizeof(*HashInterface));\r
+  HashInterfaceHob->HashInterfaceCount ++;\r
+  \r
+  return EFI_SUCCESS;\r
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf
new file mode 100644 (file)
index 0000000..5e3d74e
--- /dev/null
@@ -0,0 +1,50 @@
+## @file\r
+#  Ihis library is BaseCrypto router. It will redirect hash request to each individual\r
+#  hash handler registerd, such as SHA1, SHA256.\r
+#  Platform can use PcdTpm2HashMask to mask some hash engines.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = HashLibBaseCryptoRouterPei\r
+  FILE_GUID                      = DDCBCFBA-8EEB-488a-96D6-097831A6E50B\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = HashLibBaseCrypto|PEIM\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  HashLibBaseCryptoRouterCommon.h\r
+  HashLibBaseCryptoRouterCommon.c\r
+  HashLibBaseCryptoRouterPei.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2CommandLib\r
+  MemoryAllocationLib\r
+  PcdLib\r
+  HobLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask\r
+\r
diff --git a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c
new file mode 100644 (file)
index 0000000..b2e01af
--- /dev/null
@@ -0,0 +1,342 @@
+/** @file\r
+  Ihis library uses TPM2 device to calculation hash.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+typedef struct {\r
+  TPM_ALG_ID AlgoId;\r
+  UINT32     Mask;\r
+} TPM2_HASH_MASK;\r
+\r
+TPM2_HASH_MASK mTpm2HashMask[] = {\r
+  {TPM_ALG_SHA1,         TREE_BOOT_HASH_ALG_SHA1},\r
+  {TPM_ALG_SHA256,       TREE_BOOT_HASH_ALG_SHA256},\r
+  {TPM_ALG_SHA384,       TREE_BOOT_HASH_ALG_SHA384},\r
+  {TPM_ALG_SHA512,       TREE_BOOT_HASH_ALG_SHA512},\r
+};\r
+\r
+/**\r
+  The function get algorith from hash mask info.\r
+\r
+  @return Hash algorithm\r
+**/\r
+TPM_ALG_ID\r
+Tpm2GetAlgoFromHashMask (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 HashMask;\r
+  UINTN  Index;\r
+\r
+  HashMask = PcdGet32 (PcdTpm2HashMask);\r
+  for (Index = 0; Index < sizeof(mTpm2HashMask)/sizeof(mTpm2HashMask[0]); Index++) {\r
+    if (mTpm2HashMask[Index].Mask == HashMask) {\r
+      return mTpm2HashMask[Index].AlgoId;\r
+    }\r
+  }\r
+\r
+  return TPM_ALG_NULL;\r
+}\r
+\r
+/**\r
+  Start hash sequence.\r
+\r
+  @param HashHandle Hash handle.\r
+\r
+  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.\r
+  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashStart (\r
+  OUT HASH_HANDLE    *HashHandle\r
+  )\r
+{\r
+  TPMI_DH_OBJECT        SequenceHandle;\r
+  EFI_STATUS            Status;\r
+  TPM_ALG_ID            AlgoId;\r
+\r
+  AlgoId = Tpm2GetAlgoFromHashMask ();\r
+\r
+  Status = Tpm2HashSequenceStart (AlgoId, &SequenceHandle);\r
+  if (!EFI_ERROR (Status)) {\r
+    *HashHandle = (HASH_HANDLE)SequenceHandle;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Update hash sequence data.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence updated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashUpdate (\r
+  IN HASH_HANDLE    HashHandle,\r
+  IN VOID           *DataToHash,\r
+  IN UINTN          DataToHashLen\r
+  )\r
+{\r
+  UINT8            *Buffer;\r
+  UINT64           HashLen;\r
+  TPM2B_MAX_BUFFER HashBuffer;\r
+  EFI_STATUS       Status;\r
+\r
+  Buffer = (UINT8 *)(UINTN)DataToHash;\r
+  for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
+\r
+    HashBuffer.size = sizeof(HashBuffer.buffer);\r
+    CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
+    Buffer += sizeof(HashBuffer.buffer);\r
+\r
+    Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Last one\r
+  //\r
+  HashBuffer.size = (UINT16)HashLen;\r
+  CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
+  Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Hash sequence complete and extend to PCR.\r
+\r
+  @param HashHandle    Hash handle.\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashCompleteAndExtend (\r
+  IN HASH_HANDLE         HashHandle,\r
+  IN TPMI_DH_PCR         PcrIndex,\r
+  IN VOID                *DataToHash,\r
+  IN UINTN               DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES *DigestList\r
+  )\r
+{\r
+  UINT8            *Buffer;\r
+  UINT64           HashLen;\r
+  TPM2B_MAX_BUFFER HashBuffer;\r
+  EFI_STATUS       Status;\r
+  TPM_ALG_ID       AlgoId;\r
+  TPM2B_DIGEST     Result;\r
+\r
+  AlgoId = Tpm2GetAlgoFromHashMask ();\r
+\r
+  Buffer = (UINT8 *)(UINTN)DataToHash;\r
+  for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
+\r
+    HashBuffer.size = sizeof(HashBuffer.buffer);\r
+    CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
+    Buffer += sizeof(HashBuffer.buffer);\r
+\r
+    Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Last one\r
+  //\r
+  HashBuffer.size = (UINT16)HashLen;\r
+  CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
+\r
+  ZeroMem(DigestList, sizeof(*DigestList));\r
+  DigestList->count = HASH_COUNT;\r
+\r
+  if (AlgoId == TPM_ALG_NULL) {\r
+    Status = Tpm2EventSequenceComplete (\r
+               PcrIndex,\r
+               (TPMI_DH_OBJECT)HashHandle,\r
+               &HashBuffer,\r
+               DigestList\r
+               );\r
+  } else {\r
+    Status = Tpm2SequenceComplete (\r
+               (TPMI_DH_OBJECT)HashHandle,\r
+               &HashBuffer,\r
+               &Result\r
+               );\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+    DigestList->count = 1;\r
+    DigestList->digests[0].hashAlg = AlgoId;\r
+    CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);\r
+    Status = Tpm2PcrExtend (\r
+               PcrIndex,\r
+               DigestList\r
+               );\r
+  }\r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Hash data and extend to PCR.\r
+\r
+  @param PcrIndex      PCR to be extended.\r
+  @param DataToHash    Data to be hashed.\r
+  @param DataToHashLen Data size.\r
+  @param DigestList    Digest list.\r
+\r
+  @retval EFI_SUCCESS     Hash data and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashAndExtend (\r
+  IN TPMI_DH_PCR                    PcrIndex,\r
+  IN VOID                           *DataToHash,\r
+  IN UINTN                          DataToHashLen,\r
+  OUT TPML_DIGEST_VALUES            *DigestList\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  UINT8              *Buffer;\r
+  UINT64             HashLen;\r
+  TPMI_DH_OBJECT     SequenceHandle;\r
+  TPM2B_MAX_BUFFER   HashBuffer;\r
+  TPM_ALG_ID         AlgoId;\r
+  TPM2B_EVENT        EventData;\r
+  TPM2B_DIGEST       Result;\r
+\r
+  DEBUG((EFI_D_INFO, "\n HashAndExtend Entry \n"));\r
+\r
+  SequenceHandle = 0xFFFFFFFF; // Know bad value\r
+\r
+  AlgoId = Tpm2GetAlgoFromHashMask ();\r
+\r
+  if ((AlgoId == TPM_ALG_NULL) && (DataToHashLen <= sizeof(EventData.buffer))) {\r
+    EventData.size = (UINT16)DataToHashLen;\r
+    CopyMem (EventData.buffer, DataToHash, DataToHashLen);\r
+    Status = Tpm2PcrEvent (PcrIndex, &EventData, DigestList);\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = Tpm2HashSequenceStart(AlgoId, &SequenceHandle);\r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  DEBUG((EFI_D_INFO, "\n Tpm2HashSequenceStart Success \n"));\r
+\r
+  Buffer = (UINT8 *)(UINTN)DataToHash;\r
+  for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
+\r
+    HashBuffer.size = sizeof(HashBuffer.buffer);\r
+    CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
+    Buffer += sizeof(HashBuffer.buffer);\r
+\r
+    Status = Tpm2SequenceUpdate(SequenceHandle, &HashBuffer);\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+  DEBUG((EFI_D_INFO, "\n Tpm2SequenceUpdate Success \n"));\r
+\r
+  HashBuffer.size = (UINT16)HashLen;\r
+  CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
+\r
+  ZeroMem(DigestList, sizeof(*DigestList));\r
+  DigestList->count = HASH_COUNT;\r
+\r
+  if (AlgoId == TPM_ALG_NULL) {\r
+    Status = Tpm2EventSequenceComplete (\r
+               PcrIndex,\r
+               SequenceHandle,\r
+               &HashBuffer,\r
+               DigestList\r
+               );\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    DEBUG((EFI_D_INFO, "\n Tpm2EventSequenceComplete Success \n"));\r
+  } else {\r
+    Status = Tpm2SequenceComplete (\r
+               SequenceHandle,\r
+               &HashBuffer,\r
+               &Result\r
+               );\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    DEBUG((EFI_D_INFO, "\n Tpm2SequenceComplete Success \n"));\r
+\r
+    DigestList->count = 1;\r
+    DigestList->digests[0].hashAlg = AlgoId;\r
+    CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);\r
+    Status = Tpm2PcrExtend (\r
+               PcrIndex,\r
+               DigestList\r
+               );\r
+    if (EFI_ERROR(Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    DEBUG((EFI_D_INFO, "\n Tpm2PcrExtend Success \n"));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This service register Hash.\r
+\r
+  @param HashInterface  Hash interface\r
+\r
+  @retval EFI_SUCCESS          This hash interface is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this interface.\r
+  @retval EFI_ALREADY_STARTED  System already register this interface.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterHashInterfaceLib (\r
+  IN HASH_INTERFACE   *HashInterface\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.inf b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.inf
new file mode 100644 (file)
index 0000000..ebd81a2
--- /dev/null
@@ -0,0 +1,45 @@
+## @file\r
+#  Ihis library uses TPM2 device to calculation hash.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = HashLibTpm2\r
+  FILE_GUID                      = 1317F0D5-7842-475c-B1CA-6EDC20DCBE7D\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = HashLibTpm2\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  HashLibTpm2.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2CommandLib\r
+  MemoryAllocationLib\r
+  PcdLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask\r
diff --git a/SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf b/SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf
new file mode 100644 (file)
index 0000000..622eb2b
--- /dev/null
@@ -0,0 +1,43 @@
+## @file\r
+#  This library is used by other modules to send TPM12 command.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm12CommandLib\r
+  FILE_GUID                      = C595047C-70B3-4731-99CC-A014E956D7A7\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm12CommandLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm12Startup.c\r
+  Tpm12Ownership.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  IoLib\r
+  TimerLib\r
+  DebugLib\r
+  Tpm12DeviceLib\r
+\r
diff --git a/SecurityPkg/Library/Tpm12CommandLib/Tpm12Ownership.c b/SecurityPkg/Library/Tpm12CommandLib/Tpm12Ownership.c
new file mode 100644 (file)
index 0000000..63cc174
--- /dev/null
@@ -0,0 +1,72 @@
+/** @file\r
+  Implement TPM1.2 Startup related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <IndustryStandard/Tpm12.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/Tpm12DeviceLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM_RQU_COMMAND_HDR   Hdr;\r
+} TPM_CMD_FORCE_CLEAR;\r
+\r
+typedef struct {\r
+  TPM_RSP_COMMAND_HDR   Hdr;\r
+} TPM_RSP_FORCE_CLEAR;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  Send ForceClear command to TPM1.2.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12ForceClear (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINT32                            TpmRecvSize;\r
+  UINT32                            TpmSendSize;\r
+  TPM_CMD_FORCE_CLEAR               SendBuffer;\r
+  TPM_RSP_FORCE_CLEAR               RecvBuffer;\r
+  UINT32                            ReturnCode;\r
+\r
+  //\r
+  // send Tpm command TPM_ORD_ForceClear\r
+  //\r
+  TpmRecvSize               = sizeof (TPM_RSP_FORCE_CLEAR);\r
+  TpmSendSize               = sizeof (TPM_CMD_FORCE_CLEAR);\r
+  SendBuffer.Hdr.tag        = SwapBytes16 (TPM_TAG_RQU_COMMAND);\r
+  SendBuffer.Hdr.paramSize  = SwapBytes32 (TpmSendSize);\r
+  SendBuffer.Hdr.ordinal    = SwapBytes32 (TPM_ORD_ForceClear);\r
+\r
+  Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode);\r
+  switch (ReturnCode) {\r
+  case TPM_SUCCESS:\r
+    return EFI_SUCCESS;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/Tpm12CommandLib/Tpm12Startup.c b/SecurityPkg/Library/Tpm12CommandLib/Tpm12Startup.c
new file mode 100644 (file)
index 0000000..684c9b5
--- /dev/null
@@ -0,0 +1,78 @@
+/** @file\r
+  Implement TPM1.2 Startup related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <IndustryStandard/Tpm12.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/Tpm12DeviceLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM_RQU_COMMAND_HDR   Hdr;\r
+  TPM_STARTUP_TYPE      TpmSt;\r
+} TPM_CMD_START_UP;\r
+\r
+typedef struct {\r
+  TPM_RSP_COMMAND_HDR   Hdr;\r
+} TPM_RSP_START_UP;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  Send Startup command to TPM1.2.\r
+\r
+  @param TpmSt           Startup Type.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12Startup (\r
+  IN TPM_STARTUP_TYPE          TpmSt\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINT32                            TpmRecvSize;\r
+  UINT32                            TpmSendSize;\r
+  TPM_CMD_START_UP                  SendBuffer;\r
+  TPM_RSP_START_UP                  RecvBuffer;\r
+  UINT32                            ReturnCode;\r
+\r
+  //\r
+  // send Tpm command TPM_ORD_Startup\r
+  //\r
+  TpmRecvSize               = sizeof (TPM_RSP_START_UP);\r
+  TpmSendSize               = sizeof (TPM_CMD_START_UP);\r
+  SendBuffer.Hdr.tag        = SwapBytes16 (TPM_TAG_RQU_COMMAND);\r
+  SendBuffer.Hdr.paramSize  = SwapBytes32 (TpmSendSize);\r
+  SendBuffer.Hdr.ordinal    = SwapBytes32 (TPM_ORD_Startup);\r
+  SendBuffer.TpmSt          = SwapBytes16 (TpmSt);\r
+\r
+  Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode);\r
+  switch (ReturnCode) {\r
+  case TPM_SUCCESS:\r
+  case TPM_INVALID_POSTINIT:\r
+    // In warm reset, TPM may response TPM_INVALID_POSTINIT\r
+    return EFI_SUCCESS;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf b/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf
new file mode 100644 (file)
index 0000000..0eb91ee
--- /dev/null
@@ -0,0 +1,44 @@
+## @file\r
+#  Ihis library is TPM2 DTPM device lib.\r
+#  Choosing this library means platform uses and only uses DTPM device as TPM2 engine.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm12DeviceLibDTpm\r
+  FILE_GUID                      = BC2B7672-A48B-4d58-B39E-AEE3707B5A23\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm12DeviceLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm12Tis.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  IoLib\r
+  TimerLib\r
+  DebugLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress
\ No newline at end of file
diff --git a/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c b/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c
new file mode 100644 (file)
index 0000000..2ad5345
--- /dev/null
@@ -0,0 +1,572 @@
+/** @file\r
+  TIS (TPM Interface Specification) functions used by TPM1.2.\r
+  \r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <IndustryStandard/Tpm12.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/Tpm12CommandLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+//\r
+// Set structure alignment to 1-byte\r
+//\r
+#pragma pack (1)\r
+\r
+//\r
+// Register set map as specified in TIS specification Chapter 10\r
+//\r
+typedef struct {\r
+  ///\r
+  /// Used to gain ownership for this particular port.\r
+  ///\r
+  UINT8                             Access;             // 0\r
+  UINT8                             Reserved1[7];       // 1\r
+  ///\r
+  /// Controls interrupts.\r
+  ///\r
+  UINT32                            IntEnable;          // 8\r
+  ///\r
+  /// SIRQ vector to be used by the TPM.\r
+  ///\r
+  UINT8                             IntVector;          // 0ch\r
+  UINT8                             Reserved2[3];       // 0dh\r
+  ///\r
+  /// What caused interrupt.\r
+  ///\r
+  UINT32                            IntSts;             // 10h\r
+  ///\r
+  /// Shows which interrupts are supported by that particular TPM.\r
+  ///\r
+  UINT32                            IntfCapability;     // 14h\r
+  ///\r
+  /// Status Register. Provides status of the TPM.\r
+  ///\r
+  UINT8                             Status;             // 18h\r
+  ///\r
+  /// Number of consecutive writes that can be done to the TPM.\r
+  ///\r
+  UINT16                            BurstCount;         // 19h\r
+  UINT8                             Reserved3[9];\r
+  ///\r
+  /// Read or write FIFO, depending on transaction.\r
+  ///\r
+  UINT32                            DataFifo;           // 24h\r
+  UINT8                             Reserved4[0xed8];   // 28h\r
+  ///\r
+  /// Vendor ID\r
+  ///\r
+  UINT16                            Vid;                // 0f00h\r
+  ///\r
+  /// Device ID\r
+  ///\r
+  UINT16                            Did;                // 0f02h\r
+  ///\r
+  /// Revision ID\r
+  ///\r
+  UINT8                             Rid;                // 0f04h\r
+  ///\r
+  /// TCG defined configuration registers.\r
+  ///\r
+  UINT8                             TcgDefined[0x7b];   // 0f05h\r
+  ///\r
+  /// Alias to I/O legacy space.\r
+  ///\r
+  UINT32                            LegacyAddress1;     // 0f80h\r
+  ///\r
+  /// Additional 8 bits for I/O legacy space extension.\r
+  ///\r
+  UINT32                            LegacyAddress1Ex;   // 0f84h\r
+  ///\r
+  /// Alias to second I/O legacy space.\r
+  ///\r
+  UINT32                            LegacyAddress2;     // 0f88h\r
+  ///\r
+  /// Additional 8 bits for second I/O legacy space extension.\r
+  ///\r
+  UINT32                            LegacyAddress2Ex;   // 0f8ch\r
+  ///\r
+  /// Vendor-defined configuration registers.\r
+  ///\r
+  UINT8                             VendorDefined[0x70];// 0f90h\r
+} TIS_PC_REGISTERS;\r
+\r
+//\r
+// Restore original structure alignment\r
+//\r
+#pragma pack ()\r
+\r
+//\r
+// Define pointer types used to access TIS registers on PC\r
+//\r
+typedef TIS_PC_REGISTERS  *TIS_PC_REGISTERS_PTR;\r
+\r
+//\r
+// Define bits of ACCESS and STATUS registers\r
+//\r
+\r
+///\r
+/// This bit is a 1 to indicate that the other bits in this register are valid.\r
+///\r
+#define TIS_PC_VALID                BIT7\r
+///\r
+/// Indicate that this locality is active.\r
+///\r
+#define TIS_PC_ACC_ACTIVE           BIT5\r
+///\r
+/// Set to 1 to indicate that this locality had the TPM taken away while\r
+/// this locality had the TIS_PC_ACC_ACTIVE bit set.\r
+///\r
+#define TIS_PC_ACC_SEIZED           BIT4\r
+///\r
+/// Set to 1 to indicate that TPM MUST reset the\r
+/// TIS_PC_ACC_ACTIVE bit and remove ownership for localities less than the\r
+/// locality that is writing this bit.\r
+///\r
+#define TIS_PC_ACC_SEIZE            BIT3\r
+///\r
+/// When this bit is 1, another locality is requesting usage of the TPM.\r
+///\r
+#define TIS_PC_ACC_PENDIND          BIT2\r
+///\r
+/// Set to 1 to indicate that this locality is requesting to use TPM.\r
+///\r
+#define TIS_PC_ACC_RQUUSE           BIT1\r
+///\r
+/// A value of 1 indicates that a T/OS has not been established on the platform\r
+///\r
+#define TIS_PC_ACC_ESTABLISH        BIT0\r
+\r
+///\r
+/// When this bit is 1, TPM is in the Ready state, \r
+/// indicating it is ready to receive a new command.\r
+///\r
+#define TIS_PC_STS_READY            BIT6\r
+///\r
+/// Write a 1 to this bit to cause the TPM to execute that command.\r
+///\r
+#define TIS_PC_STS_GO               BIT5\r
+///\r
+/// This bit indicates that the TPM has data available as a response.\r
+///\r
+#define TIS_PC_STS_DATA             BIT4\r
+///\r
+/// The TPM sets this bit to a value of 1 when it expects another byte of data for a command.\r
+///\r
+#define TIS_PC_STS_EXPECT           BIT3\r
+///\r
+/// Writes a 1 to this bit to force the TPM to re-send the response.\r
+///\r
+#define TIS_PC_STS_RETRY            BIT1\r
+\r
+//\r
+// Default TimeOut value\r
+//\r
+#define TIS_TIMEOUT_A               (750  * 1000)  // 750ms\r
+#define TIS_TIMEOUT_B               (2000 * 1000)  // 2s\r
+#define TIS_TIMEOUT_C               (750  * 1000)  // 750ms\r
+#define TIS_TIMEOUT_D               (750  * 1000)  // 750ms\r
+\r
+//\r
+// Max TPM command/reponse length\r
+//\r
+#define TPMCMDBUFLENGTH             1024\r
+\r
+/**\r
+  Check whether TPM chip exist.\r
+\r
+  @param[in] TisReg  Pointer to TIS register.\r
+\r
+  @retval    TRUE    TPM chip exists.\r
+  @retval    FALSE   TPM chip is not found.\r
+**/\r
+BOOLEAN\r
+Tpm12TisPcPresenceCheck (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg\r
+  )\r
+{\r
+  UINT8                             RegRead;\r
+  \r
+  RegRead = MmioRead8 ((UINTN)&TisReg->Access);\r
+  return (BOOLEAN)(RegRead != (UINT8)-1);\r
+}\r
+\r
+/**\r
+  Check whether the value of a TPM chip register satisfies the input BIT setting.\r
+\r
+  @param[in]  Register     Address port of register to be checked.\r
+  @param[in]  BitSet       Check these data bits are set.\r
+  @param[in]  BitClear     Check these data bits are clear.\r
+  @param[in]  TimeOut      The max wait time (unit MicroSecond) when checking register.\r
+\r
+  @retval     EFI_SUCCESS  The register satisfies the check bit.\r
+  @retval     EFI_TIMEOUT  The register can't run into the expected status in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12TisPcWaitRegisterBits (\r
+  IN      UINT8                     *Register,\r
+  IN      UINT8                     BitSet,\r
+  IN      UINT8                     BitClear,\r
+  IN      UINT32                    TimeOut\r
+  )\r
+{\r
+  UINT8                             RegRead;\r
+  UINT32                            WaitTime;\r
+\r
+  for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){\r
+    RegRead = MmioRead8 ((UINTN)Register);\r
+    if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0)\r
+      return EFI_SUCCESS;\r
+    MicroSecondDelay (30);\r
+  }\r
+  return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+  Get BurstCount by reading the burstCount field of a TIS regiger \r
+  in the time of default TIS_TIMEOUT_D.\r
+\r
+  @param[in]  TisReg                Pointer to TIS register.\r
+  @param[out] BurstCount            Pointer to a buffer to store the got BurstConut.\r
+\r
+  @retval     EFI_SUCCESS           Get BurstCount.\r
+  @retval     EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.\r
+  @retval     EFI_TIMEOUT           BurstCount can't be got in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12TisPcReadBurstCount (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg,\r
+     OUT  UINT16                    *BurstCount\r
+  )\r
+{\r
+  UINT32                            WaitTime;\r
+  UINT8                             DataByte0;\r
+  UINT8                             DataByte1;\r
+\r
+  if (BurstCount == NULL || TisReg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  WaitTime = 0;\r
+  do {\r
+    //\r
+    // TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,\r
+    // so it needs to use MmioRead8 to read two times\r
+    //\r
+    DataByte0   = MmioRead8 ((UINTN)&TisReg->BurstCount);\r
+    DataByte1   = MmioRead8 ((UINTN)&TisReg->BurstCount + 1);\r
+    *BurstCount = (UINT16)((DataByte1 << 8) + DataByte0);\r
+    if (*BurstCount != 0) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    MicroSecondDelay (30);\r
+    WaitTime += 30;\r
+  } while (WaitTime < TIS_TIMEOUT_D);\r
+\r
+  return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+  Set TPM chip to ready state by sending ready command TIS_PC_STS_READY \r
+  to Status Register in time.\r
+\r
+  @param[in] TisReg                Pointer to TIS register.\r
+\r
+  @retval    EFI_SUCCESS           TPM chip enters into ready state.\r
+  @retval    EFI_INVALID_PARAMETER TisReg is NULL.\r
+  @retval    EFI_TIMEOUT           TPM chip can't be set to ready state in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12TisPcPrepareCommand (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+\r
+  if (TisReg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
+  Status = Tpm12TisPcWaitRegisterBits (\r
+             &TisReg->Status,\r
+             TIS_PC_STS_READY,\r
+             0,\r
+             TIS_TIMEOUT_B\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE \r
+  to ACCESS Register in the time of default TIS_TIMEOUT_A.\r
+\r
+  @param[in] TisReg                Pointer to TIS register.\r
+\r
+  @retval    EFI_SUCCESS           Get the control of TPM chip.\r
+  @retval    EFI_INVALID_PARAMETER TisReg is NULL.\r
+  @retval    EFI_NOT_FOUND         TPM chip doesn't exit.\r
+  @retval    EFI_TIMEOUT           Can't get the TPM control in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12TisPcRequestUseTpm (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  \r
+  if (TisReg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  if (!Tpm12TisPcPresenceCheck (TisReg)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  MmioWrite8((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);\r
+  Status = Tpm12TisPcWaitRegisterBits (\r
+             &TisReg->Access,\r
+             (UINT8)(TIS_PC_ACC_ACTIVE |TIS_PC_VALID),\r
+             0,\r
+             TIS_TIMEOUT_A\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send a command to TPM for execution and return response data.\r
+\r
+  @param[in]      TisReg        TPM register space base address.  \r
+  @param[in]      BufferIn      Buffer for command data.  \r
+  @param[in]      SizeIn        Size of command data.  \r
+  @param[in, out] BufferOut     Buffer for response data.  \r
+  @param[in, out] SizeOut       Size of response data.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_TIMEOUT           The register can't run into the expected status in time.\r
+  @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.\r
+  @retval EFI_DEVICE_ERROR      Unexpected device behavior.\r
+  @retval EFI_UNSUPPORTED       Unsupported TPM version\r
+\r
+**/\r
+EFI_STATUS\r
+Tpm12TisTpmCommand (\r
+  IN     TIS_PC_REGISTERS_PTR       TisReg,\r
+  IN     UINT8                      *BufferIn,\r
+  IN     UINT32                     SizeIn,\r
+  IN OUT UINT8                      *BufferOut,\r
+  IN OUT UINT32                     *SizeOut\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINT16                            BurstCount;\r
+  UINT32                            Index;\r
+  UINT32                            TpmOutSize;\r
+  UINT16                            Data16;\r
+  UINT32                            Data32;\r
+\r
+  DEBUG_CODE (\r
+    UINTN  DebugSize;\r
+\r
+    DEBUG ((EFI_D_INFO, "Tpm12TisTpmCommand Send - "));\r
+    if (SizeIn > 0x100) {\r
+      DebugSize = 0x40;\r
+    } else {\r
+      DebugSize = SizeIn;\r
+    }\r
+    for (Index = 0; Index < DebugSize; Index++) {\r
+      DEBUG ((EFI_D_INFO, "%02x ", BufferIn[Index]));\r
+    }\r
+    if (DebugSize != SizeIn) {\r
+      DEBUG ((EFI_D_INFO, "...... "));\r
+      for (Index = SizeIn - 0x20; Index < SizeIn; Index++) {\r
+        DEBUG ((EFI_D_INFO, "%02x ", BufferIn[Index]));\r
+      }\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  );\r
+  TpmOutSize = 0;\r
+\r
+  Status = Tpm12TisPcPrepareCommand (TisReg);\r
+  if (EFI_ERROR (Status)){\r
+    DEBUG ((DEBUG_ERROR, "Tpm12 is not ready for command!\n"));\r
+    return Status;\r
+  }\r
+  //\r
+  // Send the command data to Tpm\r
+  //\r
+  Index = 0;\r
+  while (Index < SizeIn) {\r
+    Status = Tpm12TisPcReadBurstCount (TisReg, &BurstCount);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+    for (; BurstCount > 0 && Index < SizeIn; BurstCount--) {\r
+      MmioWrite8((UINTN)&TisReg->DataFifo, *(BufferIn + Index));\r
+      Index++;\r
+    }\r
+  }\r
+  //\r
+  // Check the Tpm status STS_EXPECT change from 1 to 0\r
+  //\r
+  Status = Tpm12TisPcWaitRegisterBits (\r
+             &TisReg->Status,\r
+             (UINT8) TIS_PC_VALID,\r
+             TIS_PC_STS_EXPECT,\r
+             TIS_TIMEOUT_C\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Tpm12 The send buffer too small!\n"));\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Exit;\r
+  }\r
+  //\r
+  // Executed the TPM command and waiting for the response data ready\r
+  //\r
+  MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_GO);\r
+  Status = Tpm12TisPcWaitRegisterBits (\r
+             &TisReg->Status,\r
+             (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),\r
+             0,\r
+             TIS_TIMEOUT_B\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Wait for Tpm12 response data time out!!\n"));\r
+    Status = EFI_TIMEOUT;\r
+    goto Exit;\r
+  }\r
+  //\r
+  // Get response data header\r
+  //\r
+  Index = 0;\r
+  BurstCount = 0;\r
+  while (Index < sizeof (TPM_RSP_COMMAND_HDR)) {\r
+    Status = Tpm12TisPcReadBurstCount (TisReg, &BurstCount);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+    for (; BurstCount > 0; BurstCount--) {\r
+      *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
+      Index++;\r
+      if (Index == sizeof (TPM_RSP_COMMAND_HDR)) break;\r
+    }\r
+  }\r
+  DEBUG_CODE (\r
+    DEBUG ((EFI_D_INFO, "Tpm12TisTpmCommand ReceiveHeader - "));\r
+    for (Index = 0; Index < sizeof (TPM_RSP_COMMAND_HDR); Index++) {\r
+      DEBUG ((EFI_D_INFO, "%02x ", BufferOut[Index]));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  );\r
+  //\r
+  // Check the reponse data header (tag,parasize and returncode )\r
+  //\r
+  CopyMem (&Data16, BufferOut, sizeof (UINT16));\r
+  if (SwapBytes16 (Data16) != TPM_TAG_RSP_COMMAND) {\r
+    DEBUG ((EFI_D_ERROR, "TPM12: TPM_ST_RSP error - %x\n", TPM_TAG_RSP_COMMAND));\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Exit;\r
+  }\r
+\r
+  CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));\r
+  TpmOutSize  = SwapBytes32 (Data32);\r
+  if (*SizeOut < TpmOutSize) {\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Exit;\r
+  }\r
+  *SizeOut = TpmOutSize;\r
+  //\r
+  // Continue reading the remaining data\r
+  //\r
+  while ( Index < TpmOutSize ) {\r
+    for (; BurstCount > 0; BurstCount--) {\r
+      *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
+      Index++;\r
+      if (Index == TpmOutSize) {\r
+        Status = EFI_SUCCESS;\r
+        goto Exit;\r
+      }\r
+    }\r
+    Status = Tpm12TisPcReadBurstCount (TisReg, &BurstCount);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+  }\r
+Exit:\r
+  DEBUG_CODE (\r
+    DEBUG ((EFI_D_INFO, "Tpm12TisTpmCommand Receive - "));\r
+    for (Index = 0; Index < TpmOutSize; Index++) {\r
+      DEBUG ((EFI_D_INFO, "%02x ", BufferOut[Index]));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  );\r
+  MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM12.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM12 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM12 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM12 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM12 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  return Tpm12TisTpmCommand (\r
+           (TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress),\r
+           InputParameterBlock,\r
+           InputParameterBlockSize,\r
+           OutputParameterBlock,\r
+           OutputParameterBlockSize\r
+           );\r
+}\r
+\r
+/**\r
+  This service requests use TPM12.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM12 chip.\r
+  @retval EFI_NOT_FOUND    TPM12 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  return Tpm12TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+}\r
diff --git a/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c b/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c
new file mode 100644 (file)
index 0000000..6b793bf
--- /dev/null
@@ -0,0 +1,108 @@
+/** @file\r
+  Ihis library is TPM12 TCG protocol lib.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/Tpm12DeviceLib.h>\r
+#include <Protocol/TcgService.h>\r
+#include <IndustryStandard/Tpm12.h>\r
+\r
+EFI_TCG_PROTOCOL  *mTcgProtocol = NULL; \r
+\r
+/**\r
+  This service enables the sending of commands to the TPM12.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM12 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM12 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM12 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM12 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPM_RSP_COMMAND_HDR       *Header;\r
+\r
+  if (mTcgProtocol == NULL) {\r
+    Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &mTcgProtocol);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // TCG protocol is not installed. So, TPM12 is not present.\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Tpm12SubmitCommand - TCG - %r\n", Status));\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  //\r
+  // Assume when TCG Protocol is ready, RequestUseTpm already done.\r
+  //\r
+  Status = mTcgProtocol->PassThroughToTpm (\r
+                           mTcgProtocol,\r
+                           InputParameterBlockSize,\r
+                           InputParameterBlock,\r
+                           *OutputParameterBlockSize,\r
+                           OutputParameterBlock\r
+                           );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Header = (TPM_RSP_COMMAND_HDR *)OutputParameterBlock;\r
+  *OutputParameterBlockSize = SwapBytes32 (Header->paramSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This service requests use TPM12.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM12 chip.\r
+  @retval EFI_NOT_FOUND    TPM12 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+\r
+  if (mTcgProtocol == NULL) {\r
+    Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &mTcgProtocol);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // TCG protocol is not installed. So, TPM12 is not present.\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Tpm12RequestUseTpm - TCG - %r\n", Status));\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  //\r
+  // Assume when TCG Protocol is ready, RequestUseTpm already done.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf b/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf
new file mode 100644 (file)
index 0000000..7ab5217
--- /dev/null
@@ -0,0 +1,42 @@
+## @file\r
+#  Ihis library is TPM12 TCG protocol lib.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm12DeviceLibTcg\r
+  FILE_GUID                      = 4D8B77D9-E923-48f8-B070-4053D78B7E56\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm12DeviceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_APPLICATION UEFI_DRIVER \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm12DeviceLibTcg.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  UefiBootServicesTableLib\r
+\r
+[Protocols]\r
+  gEfiTcgProtocolGuid                           ## CONSUMES\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c
new file mode 100644 (file)
index 0000000..0fe2c36
--- /dev/null
@@ -0,0 +1,741 @@
+/** @file\r
+  Implement TPM2 Capability related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPM_CAP                   Capability;\r
+  UINT32                    Property;\r
+  UINT32                    PropertyCount;\r
+} TPM2_GET_CAPABILITY_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER      Header;\r
+  TPMI_YES_NO               MoreData;\r
+  TPMS_CAPABILITY_DATA      CapabilityData;\r
+} TPM2_GET_CAPABILITY_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMT_PUBLIC_PARMS         Parameters;\r
+} TPM2_TEST_PARMS_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+} TPM2_TEST_PARMS_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command returns various information regarding the TPM and its current state.\r
+\r
+  The capability parameter determines the category of data returned. The property parameter \r
+  selects the first value of the selected category to be returned. If there is no property \r
+  that corresponds to the value of property, the next higher value is returned, if it exists.\r
+  The moreData parameter will have a value of YES if there are more values of the requested \r
+  type that were not returned.\r
+  If no next capability exists, the TPM will return a zero-length list and moreData will have \r
+  a value of NO.\r
+\r
+  NOTE: \r
+  To simplify this function, leave returned CapabilityData for caller to unpack since there are \r
+  many capability categories and only few categories will be used in firmware. It means the caller\r
+  need swap the byte order for the feilds in CapabilityData.\r
+\r
+  @param[in]  Capability         Group selection; determines the format of the response.\r
+  @param[in]  Property           Further definition of information. \r
+  @param[in]  PropertyCount      Number of properties of the indicated type to return.\r
+  @param[out] MoreData           Flag to indicate if there are more values of this type.\r
+  @param[out] CapabilityData     The capability data.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapability (\r
+  IN      TPM_CAP                   Capability,\r
+  IN      UINT32                    Property,\r
+  IN      UINT32                    PropertyCount,\r
+  OUT     TPMI_YES_NO               *MoreData,\r
+  OUT     TPMS_CAPABILITY_DATA      *CapabilityData\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_GET_CAPABILITY_COMMAND       SendBuffer;\r
+  TPM2_GET_CAPABILITY_RESPONSE      RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_GetCapability);\r
+\r
+  SendBuffer.Capability = SwapBytes32 (Capability);\r
+  SendBuffer.Property = SwapBytes32 (Property);\r
+  SendBuffer.PropertyCount = SwapBytes32 (PropertyCount);\r
\r
+  SendBufferSize = (UINT32) sizeof (SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+    \r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT8)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Return the response\r
+  //\r
+  *MoreData = RecvBuffer.MoreData;\r
+  //\r
+  // Does not unpack all possiable property here, the caller should unpack it and note the byte order.\r
+  //\r
+  CopyMem (CapabilityData, &RecvBuffer.CapabilityData, RecvBufferSize - sizeof (TPM2_RESPONSE_HEADER) - sizeof (UINT8));\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM Family.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the Family.\r
+\r
+  @param[out] Family             The Family of TPM. (a 4-octet character string)\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityFamily (\r
+  OUT     CHAR8                     *Family\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status; \r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_FAMILY_INDICATOR, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  CopyMem (Family, &TpmCap.data.tpmProperties.tpmProperty->value, 4);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM manufacture ID.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the TPM manufacture ID.\r
+\r
+  @param[out] ManufactureId      The manufacture ID of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityManufactureID (\r
+  OUT     UINT32                    *ManufactureId\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status; \r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_MANUFACTURER, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  *ManufactureId = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM FirmwareVersion.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the TPM FirmwareVersion.\r
+\r
+  @param[out] FirmwareVersion1   The FirmwareVersion1.\r
+  @param[out] FirmwareVersion2   The FirmwareVersion2.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityFirmwareVersion (\r
+  OUT     UINT32                    *FirmwareVersion1,\r
+  OUT     UINT32                    *FirmwareVersion2\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status; \r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_FIRMWARE_VERSION_1, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  *FirmwareVersion1 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_FIRMWARE_VERSION_2, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  *FirmwareVersion2 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of the maximum value for commandSize and responseSize in a command.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the max command size and response size\r
+\r
+  @param[out] MaxCommandSize     The maximum value for commandSize in a command.\r
+  @param[out] MaxResponseSize    The maximum value for responseSize in a command.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityMaxCommandResponseSize (\r
+  OUT UINT32                    *MaxCommandSize,\r
+  OUT UINT32                    *MaxResponseSize\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status;\r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_MAX_COMMAND_SIZE, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *MaxCommandSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_MAX_RESPONSE_SIZE, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *MaxResponseSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+  return EFI_SUCCESS; \r
+}\r
+\r
+/**\r
+  This command returns Returns a list of TPMS_ALG_PROPERTIES. Each entry is an\r
+  algorithm ID and a set of properties of the algorithm. \r
+\r
+  This function parse the value got from TPM2_GetCapability and return the list.\r
+\r
+  @param[out] AlgList      List of algorithm.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilitySupportedAlg (\r
+  OUT TPML_ALG_PROPERTY      *AlgList\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  UINTN                   Index;\r
+  EFI_STATUS              Status;\r
\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_ALGS, \r
+             1, \r
+             MAX_CAP_ALGS, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  CopyMem (AlgList, &TpmCap.data.algorithms, sizeof (TPML_ALG_PROPERTY));\r
+\r
+  AlgList->count = SwapBytes32 (AlgList->count);\r
+  for (Index = 0; Index < AlgList->count; Index++) {\r
+    AlgList->algProperties[Index].alg = SwapBytes16 (AlgList->algProperties[Index].alg);\r
+    WriteUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties)));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM LockoutCounter.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the LockoutCounter.\r
+\r
+  @param[out] LockoutCounter     The LockoutCounter of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityLockoutCounter (\r
+  OUT     UINT32                    *LockoutCounter\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status; \r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_LOCKOUT_COUNTER, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  *LockoutCounter = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM LockoutInterval.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the LockoutInterval.\r
+\r
+  @param[out] LockoutInterval    The LockoutInterval of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityLockoutInterval (\r
+  OUT     UINT32                    *LockoutInterval\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status; \r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_LOCKOUT_INTERVAL, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  *LockoutInterval = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM InputBufferSize.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the InputBufferSize.\r
+\r
+  @param[out] InputBufferSize    The InputBufferSize of TPM.\r
+                                 the maximum size of a parameter (typically, a TPM2B_MAX_BUFFER)\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityInputBufferSize (\r
+  OUT     UINT32                    *InputBufferSize\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status; \r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_INPUT_BUFFER, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  *InputBufferSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM PCRs.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the PcrSelection.\r
+\r
+  @param[out] Pcrs    The Pcr Selection\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityPcrs (\r
+  OUT TPML_PCR_SELECTION      *Pcrs\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status;\r
+  UINTN                   Index;\r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_PCRS, \r
+             0, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Pcrs->count = SwapBytes32 (TpmCap.data.assignedPCR.count);\r
+  for (Index = 0; Index < Pcrs->count; Index++) {\r
+    Pcrs->pcrSelections[Index].hash = SwapBytes16 (TpmCap.data.assignedPCR.pcrSelections[Index].hash);\r
+    Pcrs->pcrSelections[Index].sizeofSelect = TpmCap.data.assignedPCR.pcrSelections[Index].sizeofSelect;\r
+    CopyMem (Pcrs->pcrSelections[Index].pcrSelect, TpmCap.data.assignedPCR.pcrSelections[Index].pcrSelect, Pcrs->pcrSelections[Index].sizeofSelect);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the information of TPM AlgorithmSet.\r
+\r
+  This function parse the value got from TPM2_GetCapability and return the AlgorithmSet.\r
+\r
+  @param[out] AlgorithmSet    The AlgorithmSet of TPM.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2GetCapabilityAlgorithmSet (\r
+  OUT     UINT32      *AlgorithmSet\r
+  )\r
+{\r
+  TPMS_CAPABILITY_DATA    TpmCap;\r
+  TPMI_YES_NO             MoreData;\r
+  EFI_STATUS              Status; \r
+\r
+  Status = Tpm2GetCapability (\r
+             TPM_CAP_TPM_PROPERTIES, \r
+             TPM_PT_ALGORITHM_SET, \r
+             1, \r
+             &MoreData, \r
+             &TpmCap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  *AlgorithmSet = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command is used to check to see if specific combinations of algorithm parameters are supported.\r
+\r
+  @param[in]  Parameters              Algorithm parameters to be validated\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2TestParms (\r
+  IN  TPMT_PUBLIC_PARMS           *Parameters\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_TEST_PARMS_COMMAND           SendBuffer;\r
+  TPM2_TEST_PARMS_RESPONSE          RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT8                             *Buffer;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_TestParms);\r
+\r
+  Buffer = (UINT8 *)&SendBuffer.Parameters;\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->type));\r
+  Buffer += sizeof(UINT16);\r
+  switch (Parameters->type) {\r
+  case TPM_ALG_KEYEDHASH:\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.scheme));\r
+    Buffer += sizeof(UINT16);\r
+    switch (Parameters->parameters.keyedHashDetail.scheme.scheme) {\r
+    case TPM_ALG_HMAC:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.hmac.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_XOR:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.kdf));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  case TPM_ALG_SYMCIPHER:\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.algorithm));\r
+    Buffer += sizeof(UINT16);\r
+    switch (Parameters->parameters.symDetail.algorithm) {\r
+    case TPM_ALG_AES:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.aes));\r
+      Buffer += sizeof(UINT16);\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.aes));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_SM4:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.SM4));\r
+      Buffer += sizeof(UINT16);\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.SM4));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_XOR:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.xor));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_NULL:\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    break;\r
+  case TPM_ALG_RSA:\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.algorithm));\r
+    Buffer += sizeof(UINT16);\r
+    switch (Parameters->parameters.rsaDetail.symmetric.algorithm) {\r
+    case TPM_ALG_AES:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.aes));\r
+      Buffer += sizeof(UINT16);\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.aes));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_SM4:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.SM4));\r
+      Buffer += sizeof(UINT16);\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.SM4));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_NULL:\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.scheme));\r
+    Buffer += sizeof(UINT16);\r
+    switch (Parameters->parameters.rsaDetail.scheme.scheme) {\r
+    case TPM_ALG_RSASSA:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsassa.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_RSAPSS:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsapss.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_RSAES:\r
+      break;\r
+    case TPM_ALG_OAEP:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.oaep.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_NULL:\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.keyBits));\r
+    Buffer += sizeof(UINT16);\r
+    WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Parameters->parameters.rsaDetail.exponent));\r
+    Buffer += sizeof(UINT32);\r
+    break;\r
+  case TPM_ALG_ECC:\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.algorithm));\r
+    Buffer += sizeof(UINT16);\r
+    switch (Parameters->parameters.eccDetail.symmetric.algorithm) {\r
+    case TPM_ALG_AES:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.aes));\r
+      Buffer += sizeof(UINT16);\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.aes));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_SM4:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.SM4));\r
+      Buffer += sizeof(UINT16);\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.SM4));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_NULL:\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.scheme));\r
+    Buffer += sizeof(UINT16);\r
+    switch (Parameters->parameters.eccDetail.scheme.scheme) {\r
+    case TPM_ALG_ECDSA:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdsa.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_ECDAA:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdaa.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_ECSCHNORR:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecSchnorr.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_ECDH:\r
+      break;\r
+    case TPM_ALG_NULL:\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.curveID));\r
+    Buffer += sizeof(UINT16);\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.scheme));\r
+    Buffer += sizeof(UINT16);\r
+    switch (Parameters->parameters.eccDetail.kdf.scheme) {\r
+    case TPM_ALG_MGF1:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.mgf1.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_KDF1_SP800_108:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_KDF1_SP800_56a:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_KDF2:\r
+      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf2.hashAlg));\r
+      Buffer += sizeof(UINT16);\r
+      break;\r
+    case TPM_ALG_NULL:\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    break;\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf b/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
new file mode 100644 (file)
index 0000000..804f063
--- /dev/null
@@ -0,0 +1,48 @@
+## @file\r
+#  This library is used by other modules to send TPM2 command.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm2CommandLib\r
+  FILE_GUID                      = 2F572F32-8BE5-4868-BD1D-7438AD97DC27\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm2CommandLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm2Capability.c\r
+  Tpm2Sequences.c\r
+  Tpm2Integrity.c\r
+  Tpm2Hierarchy.c\r
+  Tpm2NVStorage.c\r
+  Tpm2Startup.c\r
+  Tpm2Test.c\r
+  Tpm2DictionaryAttack.c\r
+  Tpm2Miscellaneous.c\r
+  Tpm2Help.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2DeviceLib\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c
new file mode 100644 (file)
index 0000000..2f6488f
--- /dev/null
@@ -0,0 +1,203 @@
+/** @file\r
+  Implement TPM2 DictionaryAttack related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_LOCKOUT           LockHandle;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_DICTIONARY_ATTACK_LOCK_RESET_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_DICTIONARY_ATTACK_LOCK_RESET_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_LOCKOUT           LockHandle;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  UINT32                    NewMaxTries;\r
+  UINT32                    NewRecoveryTime;\r
+  UINT32                    LockoutRecovery;\r
+} TPM2_DICTIONARY_ATTACK_PARAMETERS_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_DICTIONARY_ATTACK_PARAMETERS_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command cancels the effect of a TPM lockout due to a number of successive authorization failures.\r
+  If this command is properly authorized, the lockout counter is set to zero.\r
+\r
+  @param[in]  LockHandle            TPM_RH_LOCKOUT\r
+  @param[in]  AuthSession           Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2DictionaryAttackLockReset (\r
+  IN  TPMI_RH_LOCKOUT           LockHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  TPM2_DICTIONARY_ATTACK_LOCK_RESET_COMMAND  SendBuffer;\r
+  TPM2_DICTIONARY_ATTACK_LOCK_RESET_RESPONSE RecvBuffer;\r
+  UINT32                                     SendBufferSize;\r
+  UINT32                                     RecvBufferSize;\r
+  UINT8                                      *Buffer;\r
+  UINT32                                     SessionInfoSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_DictionaryAttackLockReset);\r
+\r
+  SendBuffer.LockHandle = SwapBytes32 (LockHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackLockReset - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackLockReset - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command cancels the effect of a TPM lockout due to a number of successive authorization failures.\r
+  If this command is properly authorized, the lockout counter is set to zero.\r
+\r
+  @param[in]  LockHandle            TPM_RH_LOCKOUT\r
+  @param[in]  AuthSession           Auth Session context\r
+  @param[in]  NewMaxTries           Count of authorization failures before the lockout is imposed\r
+  @param[in]  NewRecoveryTime       Time in seconds before the authorization failure count is automatically decremented\r
+  @param[in]  LockoutRecovery       Time in seconds after a lockoutAuth failure before use of lockoutAuth is allowed\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2DictionaryAttackParameters (\r
+  IN  TPMI_RH_LOCKOUT           LockHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN  UINT32                    NewMaxTries,\r
+  IN  UINT32                    NewRecoveryTime,\r
+  IN  UINT32                    LockoutRecovery\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  TPM2_DICTIONARY_ATTACK_PARAMETERS_COMMAND  SendBuffer;\r
+  TPM2_DICTIONARY_ATTACK_PARAMETERS_RESPONSE RecvBuffer;\r
+  UINT32                                     SendBufferSize;\r
+  UINT32                                     RecvBufferSize;\r
+  UINT8                                      *Buffer;\r
+  UINT32                                     SessionInfoSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_DictionaryAttackParameters);\r
+\r
+  SendBuffer.LockHandle = SwapBytes32 (LockHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  //\r
+  // Real data\r
+  //\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(NewMaxTries));\r
+  Buffer += sizeof(UINT32);\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(NewRecoveryTime));\r
+  Buffer += sizeof(UINT32);\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(LockoutRecovery));\r
+  Buffer += sizeof(UINT32);\r
+\r
+  SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackParameters - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackParameters - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c
new file mode 100644 (file)
index 0000000..4f5fcb5
--- /dev/null
@@ -0,0 +1,166 @@
+/** @file\r
+  Implement TPM2 help.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+typedef struct {\r
+  TPMI_ALG_HASH              HashAlgo;\r
+  UINT16                     HashSize;\r
+} INTERNAL_HASH_INFO;\r
+\r
+STATIC INTERNAL_HASH_INFO mHashInfo[] = {\r
+  {TPM_ALG_SHA1,          SHA1_DIGEST_SIZE},\r
+  {TPM_ALG_SHA256,        SHA256_DIGEST_SIZE},\r
+  {TPM_ALG_SM3_256,       SM3_256_DIGEST_SIZE},\r
+  {TPM_ALG_SHA384,        SHA384_DIGEST_SIZE},\r
+  {TPM_ALG_SHA512,        SHA512_DIGEST_SIZE},\r
+};\r
+\r
+/**\r
+  Return size of digest.\r
+\r
+  @param[in] HashAlgo  Hash algorithm\r
+\r
+  @return size of digest\r
+**/\r
+UINT16\r
+EFIAPI\r
+GetHashSizeFromAlgo (\r
+  IN TPMI_ALG_HASH    HashAlgo\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {\r
+    if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
+      return mHashInfo[Index].HashSize;\r
+    }\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Copy AuthSessionIn to TPM2 command buffer.\r
+\r
+  @param [in]  AuthSessionIn   Input AuthSession data\r
+  @param [out] AuthSessionOut  Output AuthSession data in TPM2 command buffer\r
+\r
+  @return AuthSession size\r
+**/\r
+UINT32\r
+EFIAPI\r
+CopyAuthSessionCommand (\r
+  IN      TPMS_AUTH_COMMAND         *AuthSessionIn, OPTIONAL\r
+  OUT     UINT8                     *AuthSessionOut\r
+  )\r
+{\r
+  UINT8  *Buffer;\r
+\r
+  Buffer = (UINT8 *)AuthSessionOut;\r
+  \r
+  //\r
+  // Add in Auth session\r
+  //\r
+  if (AuthSessionIn != NULL) {\r
+    //  sessionHandle\r
+    WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AuthSessionIn->sessionHandle));\r
+    Buffer += sizeof(UINT32);\r
+\r
+    // nonce\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->nonce.size));\r
+    Buffer += sizeof(UINT16);\r
+\r
+    CopyMem (Buffer, AuthSessionIn->nonce.buffer, AuthSessionIn->nonce.size);\r
+    Buffer += AuthSessionIn->nonce.size;\r
+\r
+    // sessionAttributes\r
+    *(UINT8 *)Buffer = *(UINT8 *)&AuthSessionIn->sessionAttributes;\r
+    Buffer += sizeof(UINT8);\r
+\r
+    // hmac\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->hmac.size));\r
+    Buffer += sizeof(UINT16);\r
+\r
+    CopyMem (Buffer, AuthSessionIn->hmac.buffer, AuthSessionIn->hmac.size);\r
+    Buffer += AuthSessionIn->hmac.size;\r
+  } else {\r
+    //  sessionHandle\r
+    WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(TPM_RS_PW));\r
+    Buffer += sizeof(UINT32);\r
+\r
+    // nonce = nullNonce\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));\r
+    Buffer += sizeof(UINT16);\r
+\r
+    // sessionAttributes = 0\r
+    *(UINT8 *)Buffer = 0x00;\r
+    Buffer += sizeof(UINT8);\r
+\r
+    // hmac = nullAuth\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));\r
+    Buffer += sizeof(UINT16);\r
+  }\r
+\r
+  return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionOut);\r
+}\r
+\r
+/**\r
+  Copy AuthSessionIn from TPM2 response buffer.\r
+\r
+  @param [in]  AuthSessionIn   Input AuthSession data in TPM2 response buffer\r
+  @param [out] AuthSessionOut  Output AuthSession data\r
+\r
+  @return AuthSession size\r
+**/\r
+UINT32\r
+EFIAPI\r
+CopyAuthSessionResponse (\r
+  IN      UINT8                      *AuthSessionIn,\r
+  OUT     TPMS_AUTH_RESPONSE         *AuthSessionOut OPTIONAL\r
+  )\r
+{\r
+  UINT8                      *Buffer;\r
+  TPMS_AUTH_RESPONSE         LocalAuthSessionOut;\r
+\r
+  if (AuthSessionOut == NULL) {\r
+    AuthSessionOut = &LocalAuthSessionOut;\r
+  }\r
+\r
+  Buffer = (UINT8 *)AuthSessionIn;\r
+\r
+  // nonce\r
+  AuthSessionOut->nonce.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  CopyMem (AuthSessionOut->nonce.buffer, Buffer, AuthSessionOut->nonce.size);\r
+  Buffer += AuthSessionOut->nonce.size;\r
+\r
+  // sessionAttributes\r
+  *(UINT8 *)&AuthSessionOut->sessionAttributes = *(UINT8 *)Buffer;\r
+  Buffer += sizeof(UINT8);\r
+\r
+  // hmac\r
+  AuthSessionOut->hmac.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  CopyMem (AuthSessionOut->hmac.buffer, Buffer, AuthSessionOut->hmac.size);\r
+  Buffer += AuthSessionOut->hmac.size;\r
+\r
+  return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionIn);\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
new file mode 100644 (file)
index 0000000..c6935d9
--- /dev/null
@@ -0,0 +1,635 @@
+/** @file\r
+  Implement TPM2 Hierarchy related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_CLEAR             AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_CLEAR_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CLEAR_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_CLEAR             AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPMI_YES_NO               Disable;\r
+} TPM2_CLEAR_CONTROL_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CLEAR_CONTROL_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_HIERARCHY_AUTH    AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPM2B_AUTH                NewAuth;\r
+} TPM2_HIERARCHY_CHANGE_AUTH_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PLATFORM          AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_CHANGE_EPS_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CHANGE_EPS_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PLATFORM          AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_CHANGE_PPS_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CHANGE_PPS_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_HIERARCHY         AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPMI_RH_HIERARCHY         Hierarchy;\r
+  TPMI_YES_NO               State;\r
+} TPM2_HIERARCHY_CONTROL_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_HIERARCHY_CONTROL_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command removes all TPM context associated with a specific Owner.\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2Clear (\r
+  IN TPMI_RH_CLEAR             AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_CLEAR_COMMAND                Cmd;\r
+  TPM2_CLEAR_RESPONSE               Res;\r
+  UINT32                            ResultBufSize;\r
+  UINT32                            CmdSize;\r
+  UINT32                            RespSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_Clear);\r
+  Cmd.AuthHandle         = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize   = SwapBytes32(CmdSize);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Clear: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Clear: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  // None\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Disables and enables the execution of TPM2_Clear().\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] Disable           YES if the disableOwnerClear flag is to be SET,\r
+                               NO if the flag is to be CLEAR.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ClearControl (\r
+  IN TPMI_RH_CLEAR             AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN TPMI_YES_NO               Disable\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_CLEAR_CONTROL_COMMAND        Cmd;\r
+  TPM2_CLEAR_CONTROL_RESPONSE       Res;\r
+  UINT32                            ResultBufSize;\r
+  UINT32                            CmdSize;\r
+  UINT32                            RespSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_ClearControl);\r
+  Cmd.AuthHandle         = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // disable\r
+  *(UINT8 *)Buffer = Disable;\r
+  Buffer += sizeof(UINT8);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize   = SwapBytes32(CmdSize);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ClearControl: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ClearControl: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "ClearControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  // None\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command allows the authorization secret for a hierarchy or lockout to be changed using the current\r
+  authorization value as the command authorization.\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] NewAuth           New authorization secret\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HierarchyChangeAuth (\r
+  IN TPMI_RH_HIERARCHY_AUTH    AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN TPM2B_AUTH                *NewAuth\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  TPM2_HIERARCHY_CHANGE_AUTH_COMMAND   Cmd;\r
+  TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE  Res;\r
+  UINT32                               CmdSize;\r
+  UINT32                               RespSize;\r
+  UINT8                                *Buffer;\r
+  UINT32                               SessionInfoSize;\r
+  UINT8                                *ResultBuf;\r
+  UINT32                               ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_HierarchyChangeAuth);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // New Authorization size\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NewAuth->size));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  // New Authorizeation\r
+  CopyMem(Buffer, NewAuth->buffer, NewAuth->size);\r
+  Buffer += NewAuth->size;\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"HierarchyChangeAuth: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This replaces the current EPS with a value from the RNG and sets the Endorsement hierarchy controls to\r
+  their default initialization values.\r
+\r
+  @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ChangeEPS (\r
+  IN TPMI_RH_PLATFORM          AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPM2_CHANGE_EPS_COMMAND   Cmd;\r
+  TPM2_CHANGE_EPS_RESPONSE  Res;\r
+  UINT32                    CmdSize;\r
+  UINT32                    RespSize;\r
+  UINT8                     *Buffer;\r
+  UINT32                    SessionInfoSize;\r
+  UINT8                     *ResultBuf;\r
+  UINT32                    ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_ChangeEPS);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangeEPS: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangeEPS: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"ChangeEPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This replaces the current PPS with a value from the RNG and sets platformPolicy to the default\r
+  initialization value (the Empty Buffer).\r
+\r
+  @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ChangePPS (\r
+  IN TPMI_RH_PLATFORM          AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPM2_CHANGE_PPS_COMMAND   Cmd;\r
+  TPM2_CHANGE_PPS_RESPONSE  Res;\r
+  UINT32                    CmdSize;\r
+  UINT32                    RespSize;\r
+  UINT8                     *Buffer;\r
+  UINT32                    SessionInfoSize;\r
+  UINT8                     *ResultBuf;\r
+  UINT32                    ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_ChangePPS);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangePPS: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangePPS: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"ChangePPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command enables and disables use of a hierarchy.\r
+\r
+  @param[in] AuthHandle        TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] Hierarchy         Hierarchy of the enable being modified\r
+  @param[in] State             YES if the enable should be SET,\r
+                               NO if the enable should be CLEAR\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HierarchyControl (\r
+  IN TPMI_RH_HIERARCHY         AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN TPMI_RH_HIERARCHY         Hierarchy,\r
+  IN TPMI_YES_NO               State\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  TPM2_HIERARCHY_CONTROL_COMMAND   Cmd;\r
+  TPM2_HIERARCHY_CONTROL_RESPONSE  Res;\r
+  UINT32                           CmdSize;\r
+  UINT32                           RespSize;\r
+  UINT8                            *Buffer;\r
+  UINT32                           SessionInfoSize;\r
+  UINT8                            *ResultBuf;\r
+  UINT32                           ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_HierarchyControl);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Hierarchy));\r
+  Buffer += sizeof(UINT32);\r
+\r
+  *(UINT8 *)Buffer = State;\r
+  Buffer += sizeof(UINT8);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyControl: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyControl: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"HierarchyControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
new file mode 100644 (file)
index 0000000..88dcc0a
--- /dev/null
@@ -0,0 +1,525 @@
+/** @file\r
+  Implement TPM2 Integrity related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_DH_PCR               PcrHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSessionPcr;\r
+  TPML_DIGEST_VALUES        DigestValues;\r
+} TPM2_PCR_EXTEND_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSessionPcr;\r
+} TPM2_PCR_EXTEND_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_DH_PCR               PcrHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSessionPcr;\r
+  TPM2B_EVENT               EventData;\r
+} TPM2_PCR_EVENT_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPML_DIGEST_VALUES         Digests;\r
+  TPMS_AUTH_RESPONSE         AuthSessionPcr;\r
+} TPM2_PCR_EVENT_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPML_PCR_SELECTION        PcrSelectionIn;\r
+} TPM2_PCR_READ_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER      Header;\r
+  UINT32                    PcrUpdateCounter;\r
+  TPML_PCR_SELECTION        PcrSelectionOut;\r
+  TPML_DIGEST               PcrValues;\r
+} TPM2_PCR_READ_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PLATFORM          AuthHandle;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPML_PCR_SELECTION        PcrAllocation;\r
+} TPM2_PCR_ALLOCATE_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMI_YES_NO                AllocationSuccess;\r
+  UINT32                     MaxPCR;\r
+  UINT32                     SizeNeeded;\r
+  UINT32                     SizeAvailable;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_PCR_ALLOCATE_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command is used to cause an update to the indicated PCR.\r
+  The digests parameter contains one or more tagged digest value identified by an algorithm ID.\r
+  For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).\r
+\r
+  @param[in] PcrHandle   Handle of the PCR\r
+  @param[in] Digests     List of tagged digest values to be extended\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrExtend (\r
+  IN      TPMI_DH_PCR               PcrHandle,\r
+  IN      TPML_DIGEST_VALUES        *Digests\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_PCR_EXTEND_COMMAND           Cmd;\r
+  TPM2_PCR_EXTEND_RESPONSE          Res;\r
+  UINT32                            CmdSize;\r
+  UINT32                            RespSize;\r
+  UINT32                            ResultBufSize;\r
+  UINT8                             *Buffer;\r
+  UINTN                             Index;\r
+  UINT32                            SessionInfoSize;\r
+  UINT16                            DigestSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Extend);\r
+  Cmd.PcrHandle          = SwapBytes32(PcrHandle);\r
+\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSessionPcr;\r
+  \r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+  \r
+  //Digest Count\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Digests->count));\r
+  Buffer += sizeof(UINT32);\r
+  \r
+  //Digest\r
+  for (Index = 0; Index < Digests->count; Index++) {\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Digests->digests[Index].hashAlg));\r
+    Buffer += sizeof(UINT16);\r
+    DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);\r
+    if (DigestSize == 0) {\r
+      DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    CopyMem(\r
+      Buffer,\r
+      &Digests->digests[Index].digest,\r
+      DigestSize\r
+      );\r
+    Buffer += DigestSize;\r
+  }\r
+\r
+  CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  // None\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command is used to cause an update to the indicated PCR.\r
+  The data in eventData is hashed using the hash algorithm associated with each bank in which the\r
+  indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle\r
+  references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in\r
+  TPM2_PCR_Extend().\r
+  A TPM shall support an Event.size of zero through 1,024 inclusive.\r
+\r
+  @param[in]  PcrHandle   Handle of the PCR\r
+  @param[in]  EventData   Event data in sized buffer\r
+  @param[out] Digests     List of digest\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrEvent (\r
+  IN      TPMI_DH_PCR               PcrHandle,\r
+  IN      TPM2B_EVENT               *EventData,\r
+     OUT  TPML_DIGEST_VALUES        *Digests\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_PCR_EVENT_COMMAND            Cmd;\r
+  TPM2_PCR_EVENT_RESPONSE           Res;\r
+  UINT32                            CmdSize;\r
+  UINT32                            RespSize;\r
+  UINT32                            ResultBufSize;\r
+  UINT8                             *Buffer;\r
+  UINTN                             Index;\r
+  UINT32                            SessionInfoSize;\r
+  UINT16                            DigestSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Event);\r
+  Cmd.PcrHandle          = SwapBytes32(PcrHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSessionPcr;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // Event\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(EventData->size));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  CopyMem (Buffer, EventData->buffer, EventData->size);\r
+  Buffer += EventData->size;\r
+  \r
+  CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+  Buffer = (UINT8 *)&Res.Digests;\r
+\r
+  Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer));\r
+  Buffer += sizeof(UINT32);\r
+  for (Index = 0; Index < Digests->count; Index++) {\r
+    Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));\r
+    Buffer += sizeof(UINT16);\r
+    DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);\r
+    if (DigestSize == 0) {\r
+      DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    CopyMem(\r
+      &Digests->digests[Index].digest,\r
+      Buffer,\r
+      DigestSize\r
+      );\r
+    Buffer += DigestSize;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command returns the values of all PCR specified in pcrSelect.\r
+\r
+  @param[in]  PcrSelectionIn     The selection of PCR to read.\r
+  @param[out] PcrUpdateCounter   The current value of the PCR update counter.\r
+  @param[out] PcrSelectionOut    The PCR in the returned list.\r
+  @param[out] PcrValues          The contents of the PCR indicated in pcrSelect.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrRead (\r
+  IN      TPML_PCR_SELECTION        *PcrSelectionIn,\r
+     OUT  UINT32                    *PcrUpdateCounter,\r
+     OUT  TPML_PCR_SELECTION        *PcrSelectionOut,\r
+     OUT  TPML_DIGEST               *PcrValues\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_PCR_READ_COMMAND             SendBuffer;\r
+  TPM2_PCR_READ_RESPONSE            RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINTN                             Index;\r
+  TPML_DIGEST                       *PcrValuesOut;\r
+  TPM2B_DIGEST                      *Digests;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PCR_Read);\r
\r
+  SendBuffer.PcrSelectionIn.count = SwapBytes32(PcrSelectionIn->count);\r
+  for (Index = 0; Index < PcrSelectionIn->count; Index++) {\r
+    SendBuffer.PcrSelectionIn.pcrSelections[Index].hash = SwapBytes16(PcrSelectionIn->pcrSelections[Index].hash);\r
+    SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect;\r
+    CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect);\r
+  }\r
+\r
+  SendBufferSize = sizeof(SendBuffer.Header) + sizeof(SendBuffer.PcrSelectionIn.count) + sizeof(SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count;\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Return the response\r
+  //\r
+\r
+  //\r
+  // PcrUpdateCounter\r
+  //\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  *PcrUpdateCounter = SwapBytes32(RecvBuffer.PcrUpdateCounter);\r
+\r
+  //\r
+  // PcrSelectionOut\r
+  //\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  PcrSelectionOut->count = SwapBytes32(RecvBuffer.PcrSelectionOut.count);\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  for (Index = 0; Index < PcrSelectionOut->count; Index++) {\r
+    PcrSelectionOut->pcrSelections[Index].hash = SwapBytes16(RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash);\r
+    PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect;\r
+    CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect);\r
+  }\r
+\r
+  //\r
+  // PcrValues\r
+  //\r
+  PcrValuesOut = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count);\r
+  PcrValues->count = SwapBytes32(PcrValuesOut->count);\r
+  Digests = PcrValuesOut->digests;\r
+  for (Index = 0; Index < PcrValues->count; Index++) {\r
+    PcrValues->digests[Index].size = SwapBytes16(Digests->size);\r
+    CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size);\r
+    Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof(Digests->size) + PcrValues->digests[Index].size);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command is used to set the desired PCR allocation of PCR and algorithms.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_PLATFORM+{PP}\r
+  @param[in]  AuthSession        Auth Session context\r
+  @param[in]  PcrAllocation      The requested allocation\r
+  @param[out] AllocationSuccess  YES if the allocation succeeded\r
+  @param[out] MaxPCR             maximum number of PCR that may be in a bank\r
+  @param[out] SizeNeeded         number of octets required to satisfy the request\r
+  @param[out] SizeAvailable      Number of octets available. Computed before the allocation\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2PcrAllocate (\r
+  IN  TPMI_RH_PLATFORM          AuthHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN  TPML_PCR_SELECTION        *PcrAllocation,\r
+  OUT TPMI_YES_NO               *AllocationSuccess,\r
+  OUT UINT32                    *MaxPCR,\r
+  OUT UINT32                    *SizeNeeded,\r
+  OUT UINT32                    *SizeAvailable\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  TPM2_PCR_ALLOCATE_COMMAND   Cmd;\r
+  TPM2_PCR_ALLOCATE_RESPONSE  Res;\r
+  UINT32                      CmdSize;\r
+  UINT32                      RespSize;\r
+  UINT8                       *Buffer;\r
+  UINT32                      SessionInfoSize;\r
+  UINT8                       *ResultBuf;\r
+  UINT32                      ResultBufSize;\r
+  UINTN                       Index;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_PCR_Allocate);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // Count\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(PcrAllocation->count));\r
+  Buffer += sizeof(UINT32);\r
+  for (Index = 0; Index < PcrAllocation->count; Index++) {\r
+    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PcrAllocation->pcrSelections[Index].hash));\r
+    Buffer += sizeof(UINT16);\r
+    *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect;\r
+    Buffer += sizeof(UINT8);\r
+    CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect);\r
+    Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect;\r
+  }\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Return the response\r
+  //\r
+  *AllocationSuccess = Res.AllocationSuccess;\r
+  *MaxPCR = SwapBytes32(Res.MaxPCR);\r
+  *SizeNeeded = SwapBytes32(Res.SizeNeeded);\r
+  *SizeAvailable = SwapBytes32(Res.SizeAvailable);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c
new file mode 100644 (file)
index 0000000..914ad7f
--- /dev/null
@@ -0,0 +1,114 @@
+/** @file\r
+  Implement TPM2 Miscellanenous related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_HIERARCHY_AUTH    AuthHandle;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  UINT32                    AlgorithmSet;\r
+} TPM2_SET_ALGORITHM_SET_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_SET_ALGORITHM_SET_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command allows the platform to change the set of algorithms that are used by the TPM.\r
+  The algorithmSet setting is a vendor-dependent value.\r
+\r
+  @param[in]  AuthHandle              TPM_RH_PLATFORM\r
+  @param[in]  AuthSession             Auth Session context\r
+  @param[in]  AlgorithmSet            A TPM vendor-dependent value indicating the\r
+                                      algorithm set selection\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SetAlgorithmSet (\r
+  IN  TPMI_RH_PLATFORM          AuthHandle,\r
+  IN  TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN  UINT32                    AlgorithmSet\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  TPM2_SET_ALGORITHM_SET_COMMAND             SendBuffer;\r
+  TPM2_SET_ALGORITHM_SET_RESPONSE            RecvBuffer;\r
+  UINT32                                     SendBufferSize;\r
+  UINT32                                     RecvBufferSize;\r
+  UINT8                                      *Buffer;\r
+  UINT32                                     SessionInfoSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_SetAlgorithmSet);\r
+\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  //\r
+  // Real data\r
+  //\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AlgorithmSet));\r
+  Buffer += sizeof(UINT32);\r
+\r
+  SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
new file mode 100644 (file)
index 0000000..c4714d3
--- /dev/null
@@ -0,0 +1,938 @@
+/** @file\r
+  Implement TPM2 NVStorage related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+#define RC_NV_ReadPublic_nvIndex            (TPM_RC_H + TPM_RC_1)\r
+\r
+#define RC_NV_DefineSpace_authHandle        (TPM_RC_H + TPM_RC_1)\r
+#define RC_NV_DefineSpace_auth              (TPM_RC_P + TPM_RC_1)\r
+#define RC_NV_DefineSpace_publicInfo        (TPM_RC_P + TPM_RC_2)\r
+\r
+#define RC_NV_UndefineSpace_authHandle      (TPM_RC_H + TPM_RC_1)\r
+#define RC_NV_UndefineSpace_nvIndex         (TPM_RC_H + TPM_RC_2)\r
+\r
+#define RC_NV_Read_authHandle               (TPM_RC_H + TPM_RC_1)\r
+#define RC_NV_Read_nvIndex                  (TPM_RC_H + TPM_RC_2)\r
+#define RC_NV_Read_size                     (TPM_RC_P + TPM_RC_1)\r
+#define RC_NV_Read_offset                   (TPM_RC_P + TPM_RC_2)\r
+\r
+#define RC_NV_Write_authHandle              (TPM_RC_H + TPM_RC_1)\r
+#define RC_NV_Write_nvIndex                 (TPM_RC_H + TPM_RC_2)\r
+#define RC_NV_Write_data                    (TPM_RC_P + TPM_RC_1)\r
+#define RC_NV_Write_offset                  (TPM_RC_P + TPM_RC_2)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_NV_INDEX          NvIndex;\r
+} TPM2_NV_READPUBLIC_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER      Header;\r
+  TPM2B_NV_PUBLIC           NvPublic;\r
+  TPM2B_NAME                NvName;\r
+} TPM2_NV_READPUBLIC_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PROVISION         AuthHandle;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPM2B_AUTH                Auth;\r
+  TPM2B_NV_PUBLIC           NvPublic;\r
+} TPM2_NV_DEFINESPACE_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_NV_DEFINESPACE_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PROVISION         AuthHandle;\r
+  TPMI_RH_NV_INDEX          NvIndex;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_NV_UNDEFINESPACE_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_NV_UNDEFINESPACE_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_NV_AUTH           AuthHandle;\r
+  TPMI_RH_NV_INDEX          NvIndex;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  UINT16                    Size;\r
+  UINT16                    Offset;\r
+} TPM2_NV_READ_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPM2B_MAX_BUFFER           Data;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_NV_READ_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_NV_AUTH           AuthHandle;\r
+  TPMI_RH_NV_INDEX          NvIndex;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPM2B_MAX_BUFFER          Data;\r
+  UINT16                    Offset;\r
+} TPM2_NV_WRITE_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_NV_WRITE_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_NV_AUTH           AuthHandle;\r
+  TPMI_RH_NV_INDEX          NvIndex;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_NV_READLOCK_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_NV_READLOCK_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_NV_AUTH           AuthHandle;\r
+  TPMI_RH_NV_INDEX          NvIndex;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_NV_WRITELOCK_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_NV_WRITELOCK_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PROVISION         AuthHandle;\r
+  UINT32                    AuthSessionSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_NV_GLOBALWRITELOCK_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     AuthSessionSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_NV_GLOBALWRITELOCK_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command is used to read the public area and Name of an NV Index.\r
+\r
+  @param[in]  NvIndex            The NV Index.\r
+  @param[out] NvPublic           The public area of the index.\r
+  @param[out] NvName             The Name of the nvIndex.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvReadPublic (\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  OUT     TPM2B_NV_PUBLIC           *NvPublic,\r
+  OUT     TPM2B_NAME                *NvName\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_READPUBLIC_COMMAND        SendBuffer;\r
+  TPM2_NV_READPUBLIC_RESPONSE       RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT16                            NvPublicSize;\r
+  UINT16                            NvNameSize;\r
+  UINT8                             *Buffer;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadPublic);\r
+\r
+  SendBuffer.NvIndex = SwapBytes32 (NvIndex);\r
\r
+  SendBufferSize = (UINT32) sizeof (SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    // return data\r
+    break;\r
+  case TPM_RC_HANDLE + RC_NV_ReadPublic_nvIndex: // TPM_RC_NV_DEFINED:\r
+    return EFI_NOT_FOUND;\r
+  case TPM_RC_VALUE + RC_NV_ReadPublic_nvIndex:\r
+    return EFI_INVALID_PARAMETER;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Basic check\r
+  //\r
+  NvPublicSize = SwapBytes16 (RecvBuffer.NvPublic.size);\r
+  NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize)));\r
+\r
+  if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x, NvNameSize %x\n", RecvBufferSize, NvNameSize));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Return the response\r
+  //\r
+  CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize);\r
+  NvPublic->size = NvPublicSize;\r
+  NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex);\r
+  NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg);\r
+  WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes)));\r
+  NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size);\r
+  Buffer = (UINT8 *)&NvPublic->nvPublic.authPolicy;\r
+  Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size;\r
+  NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));\r
+\r
+  CopyMem (NvName, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize, NvNameSize);\r
+  NvName->size = NvNameSize;\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command defines the attributes of an NV Index and causes the TPM to\r
+  reserve space to hold the data associated with the index.\r
+  If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.\r
+  @param[in]  AuthSession        Auth Session context\r
+  @param[in]  Auth               The authorization data.\r
+  @param[in]  NvPublic           The public area of the index.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_ALREADY_STARTED    The command was returned successfully, but NvIndex is already defined.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvDefineSpace (\r
+  IN      TPMI_RH_PROVISION         AuthHandle,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN      TPM2B_AUTH                *Auth,\r
+  IN      TPM2B_NV_PUBLIC           *NvPublic\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_DEFINESPACE_COMMAND       SendBuffer;\r
+  TPM2_NV_DEFINESPACE_RESPONSE      RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT16                            NvPublicSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace);\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  //\r
+  // IndexAuth\r
+  //\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size));\r
+  Buffer += sizeof(UINT16);\r
+  CopyMem(Buffer, Auth->buffer, Auth->size);\r
+  Buffer += Auth->size;\r
+\r
+  //\r
+  // NvPublic\r
+  //\r
+  NvPublicSize = NvPublic->size;\r
+\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize));\r
+  Buffer += sizeof(UINT16);\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex));\r
+  Buffer += sizeof(UINT32);\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg));\r
+  Buffer += sizeof(UINT16);\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes)));\r
+  Buffer += sizeof(UINT32);\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size));\r
+  Buffer += sizeof(UINT16);\r
+  CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size);\r
+  Buffer += NvPublic->nvPublic.authPolicy.size;\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    // return data\r
+    break;\r
+  case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo:\r
+  case TPM_RC_SIZE + RC_NV_DefineSpace_auth:\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  case TPM_RC_ATTRIBUTES:\r
+  case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo:\r
+    return EFI_UNSUPPORTED;\r
+  case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_NV_DEFINED:\r
+    return EFI_ALREADY_STARTED;\r
+  case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo:\r
+  case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_NV_SPACE:\r
+    return EFI_OUT_OF_RESOURCES;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command removes an index from the TPM.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.\r
+  @param[in]  NvIndex            The NV Index.\r
+  @param[in]  AuthSession        Auth Session context\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvUndefineSpace (\r
+  IN      TPMI_RH_PROVISION         AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_UNDEFINESPACE_COMMAND     SendBuffer;\r
+  TPM2_NV_UNDEFINESPACE_RESPONSE    RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_UndefineSpace);\r
+\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+  SendBuffer.NvIndex = SwapBytes32 (NvIndex);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    // return data\r
+    break;\r
+  case TPM_RC_ATTRIBUTES:\r
+  case TPM_RC_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex:\r
+    return EFI_UNSUPPORTED;\r
+  case TPM_RC_NV_AUTHORIZATION:\r
+    return EFI_SECURITY_VIOLATION;\r
+  case TPM_RC_HANDLE + RC_NV_UndefineSpace_nvIndex: // TPM_RC_NV_DEFINED:\r
+    return EFI_NOT_FOUND;\r
+  case TPM_RC_HANDLE + RC_NV_UndefineSpace_authHandle: // TPM_RC_NV_DEFINED:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_VALUE + RC_NV_UndefineSpace_authHandle:\r
+  case TPM_RC_VALUE + RC_NV_UndefineSpace_nvIndex:\r
+    return EFI_INVALID_PARAMETER;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace().\r
+\r
+  @param[in]     AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]     NvIndex            The index to be read.\r
+  @param[in]     AuthSession        Auth Session context\r
+  @param[in]     Size               Number of bytes to read.\r
+  @param[in]     Offset             Byte offset into the area.\r
+  @param[in,out] OutData            The data read.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvRead (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN      UINT16                    Size,\r
+  IN      UINT16                    Offset,\r
+  IN OUT  TPM2B_MAX_BUFFER          *OutData\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_READ_COMMAND              SendBuffer;\r
+  TPM2_NV_READ_RESPONSE             RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Read);\r
+\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+  SendBuffer.NvIndex = SwapBytes32 (NvIndex);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Size));\r
+  Buffer += sizeof(UINT16);\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvRead - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvRead - responseCode - %x\n", ResponseCode));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    // return data\r
+    break;\r
+  case TPM_RC_NV_AUTHORIZATION:\r
+    return EFI_SECURITY_VIOLATION;\r
+  case TPM_RC_NV_LOCKED:\r
+    return EFI_ACCESS_DENIED;\r
+  case TPM_RC_NV_RANGE:\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  case TPM_RC_NV_UNINITIALIZED:\r
+    return EFI_NOT_READY;\r
+  case TPM_RC_HANDLE + RC_NV_Read_nvIndex: // TPM_RC_NV_DEFINED:\r
+    return EFI_NOT_FOUND;\r
+  case TPM_RC_HANDLE + RC_NV_Read_authHandle: // TPM_RC_NV_DEFINED:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_VALUE + RC_NV_Read_nvIndex:\r
+  case TPM_RC_VALUE + RC_NV_Read_authHandle:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_BAD_AUTH + RC_NV_Read_authHandle + TPM_RC_S:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_AUTH_UNAVAILABLE:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_AUTH_FAIL + RC_NV_Read_authHandle + TPM_RC_S:\r
+    return EFI_INVALID_PARAMETER;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  case TPM_RC_ATTRIBUTES + RC_NV_Read_authHandle + TPM_RC_S:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Return the response\r
+  //\r
+  OutData->size = SwapBytes16 (RecvBuffer.Data.size);\r
+  CopyMem (OutData->buffer, &RecvBuffer.Data.buffer, OutData->size);\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command writes a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace().\r
+\r
+  @param[in]  AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]  NvIndex            The NV Index of the area to write.\r
+  @param[in]  AuthSession        Auth Session context\r
+  @param[in]  InData             The data to write.\r
+  @param[in]  Offset             The offset into the NV Area.\r
+  \r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvWrite (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN      TPM2B_MAX_BUFFER          *InData,\r
+  IN      UINT16                    Offset\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_WRITE_COMMAND             SendBuffer;\r
+  TPM2_NV_WRITE_RESPONSE            RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Write);\r
+\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+  SendBuffer.NvIndex = SwapBytes32 (NvIndex);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (InData->size));\r
+  Buffer += sizeof(UINT16);\r
+  CopyMem (Buffer, InData->buffer, InData->size);\r
+  Buffer += InData->size;\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  SendBufferSize = (UINT32) (Buffer - (UINT8 *)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - responseCode - %x\n", ResponseCode));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    return EFI_SUCCESS;\r
+  case TPM_RC_ATTRIBUTES:\r
+    return EFI_UNSUPPORTED;\r
+  case TPM_RC_NV_AUTHORIZATION:\r
+    return EFI_SECURITY_VIOLATION;\r
+  case TPM_RC_NV_LOCKED:\r
+    return EFI_ACCESS_DENIED;\r
+  case TPM_RC_NV_RANGE:\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  case TPM_RC_HANDLE + RC_NV_Write_nvIndex: // TPM_RC_NV_DEFINED:\r
+    return EFI_NOT_FOUND;\r
+  case TPM_RC_HANDLE + RC_NV_Write_authHandle: // TPM_RC_NV_DEFINED:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_VALUE + RC_NV_Write_nvIndex:\r
+  case TPM_RC_VALUE + RC_NV_Write_authHandle:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_BAD_AUTH + RC_NV_Write_authHandle + TPM_RC_S:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_AUTH_UNAVAILABLE:\r
+    return EFI_INVALID_PARAMETER;\r
+  case TPM_RC_AUTH_FAIL + RC_NV_Write_authHandle + TPM_RC_S:\r
+    return EFI_INVALID_PARAMETER;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  case TPM_RC_ATTRIBUTES + RC_NV_Write_authHandle + TPM_RC_S:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+}\r
+\r
+/**\r
+  This command may be used to prevent further reads of the Index until the next TPM2_Startup (TPM_SU_CLEAR).\r
+\r
+  @param[in]  AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]  NvIndex            The NV Index of the area to lock.\r
+  @param[in]  AuthSession        Auth Session context\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvReadLock (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_READLOCK_COMMAND          SendBuffer;\r
+  TPM2_NV_READLOCK_RESPONSE         RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadLock);\r
+\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+  SendBuffer.NvIndex = SwapBytes32 (NvIndex);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    // return data\r
+    break;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command may be used to inhibit further writes of the Index.\r
+\r
+  @param[in]  AuthHandle         the handle indicating the source of the authorization value.\r
+  @param[in]  NvIndex            The NV Index of the area to lock.\r
+  @param[in]  AuthSession        Auth Session context\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvWriteLock (\r
+  IN      TPMI_RH_NV_AUTH           AuthHandle,\r
+  IN      TPMI_RH_NV_INDEX          NvIndex,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_WRITELOCK_COMMAND         SendBuffer;\r
+  TPM2_NV_WRITELOCK_RESPONSE        RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_WriteLock);\r
+\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+  SendBuffer.NvIndex = SwapBytes32 (NvIndex);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    // return data\r
+    break;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  The command will SET TPMA_NV_WRITELOCKED for all indexes that have their TPMA_NV_GLOBALLOCK attribute SET.\r
+\r
+  @param[in]  AuthHandle         TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.\r
+  @param[in]  AuthSession        Auth Session context\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_NOT_FOUND          The command was returned successfully, but NvIndex is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2NvGlobalWriteLock (\r
+  IN      TPMI_RH_PROVISION         AuthHandle,\r
+  IN      TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_NV_GLOBALWRITELOCK_COMMAND   SendBuffer;\r
+  TPM2_NV_GLOBALWRITELOCK_RESPONSE  RecvBuffer;\r
+  UINT32                            SendBufferSize;\r
+  UINT32                            RecvBufferSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+  TPM_RC                            ResponseCode;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_GlobalWriteLock);\r
+\r
+  SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&SendBuffer.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);\r
+\r
+  SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);\r
+  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
+\r
+  //\r
+  // send Tpm command\r
+  //\r
+  RecvBufferSize = sizeof (RecvBuffer);\r
+  Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);\r
+  if (ResponseCode != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
+  }\r
+  switch (ResponseCode) {\r
+  case TPM_RC_SUCCESS:\r
+    // return data\r
+    break;\r
+  default:\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c
new file mode 100644 (file)
index 0000000..305b6f2
--- /dev/null
@@ -0,0 +1,508 @@
+/** @file\r
+  Implement TPM2 Sequences related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER  Header;\r
+  TPM2B_AUTH           Auth;\r
+  TPMI_ALG_HASH        HashAlg;\r
+} TPM2_HASH_SEQUENCE_START_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER  Header;\r
+  TPMI_DH_OBJECT        SequenceHandle;\r
+} TPM2_HASH_SEQUENCE_START_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_DH_OBJECT            SequenceHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSessionSeq;\r
+  TPM2B_MAX_BUFFER          Buffer;\r
+} TPM2_SEQUENCE_UPDATE_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSessionSeq;\r
+} TPM2_SEQUENCE_UPDATE_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_DH_PCR               PcrHandle;\r
+  TPMI_DH_OBJECT            SequenceHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSessionPcr;\r
+  TPMS_AUTH_COMMAND         AuthSessionSeq;\r
+  TPM2B_MAX_BUFFER          Buffer;\r
+} TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPML_DIGEST_VALUES         Results;\r
+  TPMS_AUTH_RESPONSE         AuthSessionPcr;\r
+  TPMS_AUTH_RESPONSE         AuthSessionSeq;\r
+} TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_DH_OBJECT            SequenceHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSessionSeq;\r
+  TPM2B_MAX_BUFFER          Buffer;\r
+  TPMI_RH_HIERARCHY         Hierarchy;\r
+} TPM2_SEQUENCE_COMPLETE_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPM2B_DIGEST               Digest;\r
+  TPMS_AUTH_RESPONSE         AuthSessionSeq;\r
+} TPM2_SEQUENCE_COMPLETE_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command starts a hash or an Event sequence.\r
+  If hashAlg is an implemented hash, then a hash sequence is started.\r
+  If hashAlg is TPM_ALG_NULL, then an Event sequence is started.\r
+\r
+  @param[in]  HashAlg           The hash algorithm to use for the hash sequence\r
+                                An Event sequence starts if this is TPM_ALG_NULL.\r
+  @param[out] SequenceHandle    A handle to reference the sequence\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HashSequenceStart (\r
+  IN TPMI_ALG_HASH   HashAlg,\r
+  OUT TPMI_DH_OBJECT *SequenceHandle\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_HASH_SEQUENCE_START_COMMAND  Cmd;\r
+  TPM2_HASH_SEQUENCE_START_RESPONSE Res;\r
+  UINT32                            CmdSize;\r
+  UINT32                            RespSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            ResultBufSize;\r
+\r
+  ZeroMem(&Cmd, sizeof(Cmd));\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_HashSequenceStart);\r
+\r
+  Buffer = (UINT8 *)&Cmd.Auth;\r
+\r
+  // auth = nullAuth\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  // hashAlg\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  // sequenceHandle\r
+  *SequenceHandle = SwapBytes32(Res.SequenceHandle);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command is used to add data to a hash or HMAC sequence.\r
+  The amount of data in buffer may be any size up to the limits of the TPM.\r
+  NOTE: In all TPM, a buffer size of 1,024 octets is allowed.\r
+\r
+  @param[in] SequenceHandle    Handle for the sequence object\r
+  @param[in] Buffer            Data to be added to hash\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SequenceUpdate (\r
+  IN TPMI_DH_OBJECT   SequenceHandle,\r
+  IN TPM2B_MAX_BUFFER *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  TPM2_SEQUENCE_UPDATE_COMMAND  Cmd;\r
+  TPM2_SEQUENCE_UPDATE_RESPONSE Res;\r
+  UINT32                        CmdSize;\r
+  UINT32                        RespSize;\r
+  UINT8                         *BufferPtr;\r
+  UINT32                        SessionInfoSize;\r
+  UINT32                        ResultBufSize;\r
+\r
+  ZeroMem(&Cmd, sizeof(Cmd));\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceUpdate);\r
+  Cmd.SequenceHandle = SwapBytes32(SequenceHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);\r
+  BufferPtr += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // buffer.size\r
+  WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));\r
+  BufferPtr += sizeof(UINT16);\r
+\r
+  CopyMem(BufferPtr, &Buffer->buffer, Buffer->size);\r
+  BufferPtr += Buffer->size;\r
+\r
+  CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd,&ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  // None\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command adds the last part of data, if any, to an Event sequence and returns the result in a digest list.\r
+  If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in\r
+  the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each\r
+  bank extended with the associated digest value.\r
+\r
+  @param[in]  PcrHandle         PCR to be extended with the Event data\r
+  @param[in]  SequenceHandle    Authorization for the sequence\r
+  @param[in]  Buffer            Data to be added to the Event\r
+  @param[out] Results           List of digests computed for the PCR\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2EventSequenceComplete (\r
+  IN TPMI_DH_PCR         PcrHandle,\r
+  IN TPMI_DH_OBJECT      SequenceHandle,\r
+  IN TPM2B_MAX_BUFFER    *Buffer,\r
+  OUT TPML_DIGEST_VALUES *Results\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND  Cmd;\r
+  TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE Res;\r
+  UINT32                                CmdSize;\r
+  UINT32                                RespSize;\r
+  UINT8                                 *BufferPtr;\r
+  UINT32                                SessionInfoSize;\r
+  UINT32                                SessionInfoSize2;\r
+  UINT32                                Index;\r
+  UINT32                                ResultBufSize;\r
+  UINT16                                DigestSize;\r
+\r
+  ZeroMem(&Cmd, sizeof(Cmd));\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_EventSequenceComplete);\r
+  Cmd.PcrHandle = SwapBytes32(PcrHandle);\r
+  Cmd.SequenceHandle = SwapBytes32(SequenceHandle);\r
+\r
+  //\r
+  // Add in pcrHandle Auth session\r
+  //\r
+  BufferPtr = (UINT8 *)&Cmd.AuthSessionPcr;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);\r
+  BufferPtr += SessionInfoSize;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize2 = CopyAuthSessionCommand (NULL, BufferPtr);\r
+  BufferPtr += SessionInfoSize2;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize + SessionInfoSize2);\r
+\r
+  // buffer.size\r
+  WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));\r
+  BufferPtr += sizeof(UINT16);\r
+\r
+  CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);\r
+  BufferPtr += Buffer->size;\r
+\r
+  CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  BufferPtr = (UINT8 *)&Res.Results;\r
+\r
+  // count\r
+  Results->count = SwapBytes32(ReadUnaligned32 ((UINT32 *)BufferPtr));\r
+  BufferPtr += sizeof(UINT32);\r
+\r
+  for (Index = 0; Index < Results->count; Index++) {\r
+    Results->digests[Index].hashAlg = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));\r
+    BufferPtr += sizeof(UINT16);\r
+\r
+    DigestSize = GetHashSizeFromAlgo (Results->digests[Index].hashAlg);\r
+    if (DigestSize == 0) {\r
+      DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results->digests[Index].hashAlg));\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    CopyMem(\r
+      &Results->digests[Index].digest,\r
+      BufferPtr,\r
+      DigestSize\r
+      );\r
+    BufferPtr += DigestSize;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.\r
+\r
+  @param[in]  SequenceHandle    Authorization for the sequence\r
+  @param[in]  Buffer            Data to be added to the hash/HMAC\r
+  @param[out] Result            The returned HMAC or digest in a sized buffer\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SequenceComplete (\r
+  IN TPMI_DH_OBJECT      SequenceHandle,\r
+  IN TPM2B_MAX_BUFFER    *Buffer,\r
+  OUT TPM2B_DIGEST       *Result\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  TPM2_SEQUENCE_COMPLETE_COMMAND        Cmd;\r
+  TPM2_SEQUENCE_COMPLETE_RESPONSE       Res;\r
+  UINT32                                CmdSize;\r
+  UINT32                                RespSize;\r
+  UINT8                                 *BufferPtr;\r
+  UINT32                                SessionInfoSize;\r
+  UINT32                                ResultBufSize;\r
+\r
+  ZeroMem(&Cmd, sizeof(Cmd));\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceComplete);\r
+  Cmd.SequenceHandle = SwapBytes32(SequenceHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);\r
+  BufferPtr += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // buffer.size\r
+  WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));\r
+  BufferPtr += sizeof(UINT16);\r
+\r
+  CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);\r
+  BufferPtr += Buffer->size;\r
+\r
+  // Hierarchy\r
+  WriteUnaligned32 ((UINT32 *)BufferPtr, SwapBytes32 (TPM_RH_NULL));\r
+  BufferPtr += sizeof (UINT32);\r
+\r
+  CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "SequenceComplete: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  BufferPtr = (UINT8 *)&Res.Digest;\r
+\r
+  // digestSize\r
+  Result->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));\r
+  BufferPtr += sizeof(UINT16);\r
+\r
+  CopyMem(\r
+    Result->buffer,\r
+    BufferPtr,\r
+    Result->size\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c
new file mode 100644 (file)
index 0000000..e8af403
--- /dev/null
@@ -0,0 +1,102 @@
+/** @file\r
+  Implement TPM2 Startup related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER  Header;\r
+  TPM_SU               StartupType;\r
+} TPM2_STARTUP_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER Header;\r
+} TPM2_STARTUP_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER  Header;\r
+  TPM_SU               ShutdownType;\r
+} TPM2_SHUTDOWN_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER Header;\r
+} TPM2_SHUTDOWN_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  Send Startup command to TPM2.\r
+\r
+  @param[in] StartupType           TPM_SU_CLEAR or TPM_SU_STATE\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2Startup (\r
+  IN      TPM_SU             StartupType\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_STARTUP_COMMAND              Cmd;\r
+  TPM2_STARTUP_RESPONSE             Res;\r
+  UINT32                            ResultBufSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  Cmd.Header.paramSize   = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_Startup);\r
+  Cmd.StartupType        = SwapBytes16(StartupType);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send Shutdown command to TPM2.\r
+\r
+  @param[in] ShutdownType           TPM_SU_CLEAR or TPM_SU_STATE.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2Shutdown (\r
+  IN      TPM_SU             ShutdownType\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_SHUTDOWN_COMMAND             Cmd;\r
+  TPM2_SHUTDOWN_RESPONSE            Res;\r
+  UINT32                            ResultBufSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  Cmd.Header.paramSize   = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_Shutdown);\r
+  Cmd.ShutdownType       = SwapBytes16(ShutdownType);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Test.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Test.c
new file mode 100644 (file)
index 0000000..453351b
--- /dev/null
@@ -0,0 +1,66 @@
+/** @file\r
+  Implement TPM2 Test related command.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER  Header;\r
+  TPMI_YES_NO          FullTest;\r
+} TPM2_SELF_TEST_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER Header;\r
+} TPM2_SELF_TEST_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command causes the TPM to perform a test of its capabilities.\r
+  If the fullTest is YES, the TPM will test all functions.\r
+  If fullTest = NO, the TPM will only test those functions that have not previously been tested.\r
+\r
+  @param[in] FullTest    YES if full test to be performed\r
+                         NO if only test of untested functions required\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SelfTest (\r
+  IN TPMI_YES_NO          FullTest\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_SELF_TEST_COMMAND            Cmd;\r
+  TPM2_SELF_TEST_RESPONSE           Res;\r
+  UINT32                            ResultBufSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_NO_SESSIONS);\r
+  Cmd.Header.paramSize   = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_SelfTest);\r
+  Cmd.FullTest           = FullTest;\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c
new file mode 100644 (file)
index 0000000..7d10dbb
--- /dev/null
@@ -0,0 +1,116 @@
+/** @file\r
+  Ihis library is TPM2 DTPM device lib.\r
+  Choosing this library means platform uses and only uses DTPM device as TPM2 engine.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DTpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  );\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DTpm2RequestUseTpm (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  return DTpm2SubmitCommand (\r
+           InputParameterBlockSize,\r
+           InputParameterBlock,\r
+           OutputParameterBlockSize,\r
+           OutputParameterBlock\r
+           );\r
+}\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  return DTpm2RequestUseTpm ();\r
+}\r
+\r
+/**\r
+  This service register TPM2 device.\r
+\r
+  @param Tpm2Device  TPM2 device\r
+\r
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.\r
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RegisterTpm2DeviceLib (\r
+  IN TPM2_DEVICE_INTERFACE   *Tpm2Device\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
new file mode 100644 (file)
index 0000000..78df432
--- /dev/null
@@ -0,0 +1,45 @@
+## @file\r
+#  Ihis library is TPM2 DTPM device lib.\r
+#  Choosing this library means platform uses and only uses DTPM device as TPM2 engine.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm2DeviceLibDTpm\r
+  FILE_GUID                      = E54A3327-A345-4068-8842-70AC0D519855\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm2DeviceLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm2Tis.c\r
+  Tpm2DeviceLibDTpm.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  IoLib\r
+  TimerLib\r
+  DebugLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c
new file mode 100644 (file)
index 0000000..6a6a042
--- /dev/null
@@ -0,0 +1,85 @@
+/** @file\r
+  Ihis library is TPM2 DTPM instance.\r
+  It can be registered to Tpm2 Device router, to be active TPM2 engine,\r
+  based on platform setting.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+\r
+#include <Guid/TpmInstance.h>\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DTpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  );\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DTpm2RequestUseTpm (\r
+  VOID\r
+  );\r
+\r
+TPM2_DEVICE_INTERFACE  mDTpm2InternalTpm2Device = {\r
+  TPM_DEVICE_INTERFACE_TPM20_DTPM,\r
+  DTpm2SubmitCommand,\r
+  DTpm2RequestUseTpm,\r
+};\r
+\r
+/**\r
+  The function register DTPM2.0 instance.\r
+  \r
+  @retval EFI_SUCCESS   DTPM2.0 instance is registered, or system dose not surpport registr DTPM2.0 instance\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2InstanceLibDTpmConstructor (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = Tpm2RegisterTpm2DeviceLib (&mDTpm2InternalTpm2Device);\r
+  if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) {\r
+    //\r
+    // Unsupported means platform policy does not need this instance enabled.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
new file mode 100644 (file)
index 0000000..a4d8068
--- /dev/null
@@ -0,0 +1,47 @@
+## @file\r
+#  Ihis library is TPM2 DTPM instance.\r
+#  It can be registered to Tpm2 Device router, to be active TPM2 engine,\r
+#  based on platform setting.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm2InstanceLibDTpm\r
+  FILE_GUID                      = 286BF25A-C2C3-408c-B3B4-25E6758B7317\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = NULL\r
+  CONSTRUCTOR                    = Tpm2InstanceLibDTpmConstructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm2Tis.c\r
+  Tpm2InstanceLibDTpm.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  IoLib\r
+  TimerLib\r
+  DebugLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Tis.c b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Tis.c
new file mode 100644 (file)
index 0000000..cf85d4c
--- /dev/null
@@ -0,0 +1,583 @@
+/** @file\r
+  TIS (TPM Interface Specification) functions used by dTPM2.0 library.\r
+  \r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/Tpm20.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+//\r
+// Set structure alignment to 1-byte\r
+//\r
+#pragma pack (1)\r
+\r
+//\r
+// Register set map as specified in TIS specification Chapter 10\r
+//\r
+typedef struct {\r
+  ///\r
+  /// Used to gain ownership for this particular port.\r
+  ///\r
+  UINT8                             Access;             // 0\r
+  UINT8                             Reserved1[7];       // 1\r
+  ///\r
+  /// Controls interrupts.\r
+  ///\r
+  UINT32                            IntEnable;          // 8\r
+  ///\r
+  /// SIRQ vector to be used by the TPM.\r
+  ///\r
+  UINT8                             IntVector;          // 0ch\r
+  UINT8                             Reserved2[3];       // 0dh\r
+  ///\r
+  /// What caused interrupt.\r
+  ///\r
+  UINT32                            IntSts;             // 10h\r
+  ///\r
+  /// Shows which interrupts are supported by that particular TPM.\r
+  ///\r
+  UINT32                            IntfCapability;     // 14h\r
+  ///\r
+  /// Status Register. Provides status of the TPM.\r
+  ///\r
+  UINT8                             Status;             // 18h\r
+  ///\r
+  /// Number of consecutive writes that can be done to the TPM.\r
+  ///\r
+  UINT16                            BurstCount;         // 19h\r
+  ///\r
+  /// TPM2 support CANCEL at BIT[24] of STATUS register (WO)\r
+  ///\r
+  UINT8                             StatusEx;           // 1Bh\r
+  UINT8                             Reserved3[8];\r
+  ///\r
+  /// Read or write FIFO, depending on transaction.\r
+  ///\r
+  UINT32                            DataFifo;           // 24h\r
+  UINT8                             Reserved4[0xed8];   // 28h\r
+  ///\r
+  /// Vendor ID\r
+  ///\r
+  UINT16                            Vid;                // 0f00h\r
+  ///\r
+  /// Device ID\r
+  ///\r
+  UINT16                            Did;                // 0f02h\r
+  ///\r
+  /// Revision ID\r
+  ///\r
+  UINT8                             Rid;                // 0f04h\r
+  ///\r
+  /// TCG defined configuration registers.\r
+  ///\r
+  UINT8                             TcgDefined[0x7b];   // 0f05h\r
+  ///\r
+  /// Alias to I/O legacy space.\r
+  ///\r
+  UINT32                            LegacyAddress1;     // 0f80h\r
+  ///\r
+  /// Additional 8 bits for I/O legacy space extension.\r
+  ///\r
+  UINT32                            LegacyAddress1Ex;   // 0f84h\r
+  ///\r
+  /// Alias to second I/O legacy space.\r
+  ///\r
+  UINT32                            LegacyAddress2;     // 0f88h\r
+  ///\r
+  /// Additional 8 bits for second I/O legacy space extension.\r
+  ///\r
+  UINT32                            LegacyAddress2Ex;   // 0f8ch\r
+  ///\r
+  /// Vendor-defined configuration registers.\r
+  ///\r
+  UINT8                             VendorDefined[0x70];// 0f90h\r
+} TIS_PC_REGISTERS;\r
+\r
+//\r
+// Restore original structure alignment\r
+//\r
+#pragma pack ()\r
+\r
+//\r
+// Define pointer types used to access TIS registers on PC\r
+//\r
+typedef TIS_PC_REGISTERS  *TIS_PC_REGISTERS_PTR;\r
+\r
+//\r
+// Define bits of ACCESS and STATUS registers\r
+//\r
+\r
+///\r
+/// This bit is a 1 to indicate that the other bits in this register are valid.\r
+///\r
+#define TIS_PC_VALID                BIT7\r
+///\r
+/// Indicate that this locality is active.\r
+///\r
+#define TIS_PC_ACC_ACTIVE           BIT5\r
+///\r
+/// Set to 1 to indicate that this locality had the TPM taken away while\r
+/// this locality had the TIS_PC_ACC_ACTIVE bit set.\r
+///\r
+#define TIS_PC_ACC_SEIZED           BIT4\r
+///\r
+/// Set to 1 to indicate that TPM MUST reset the\r
+/// TIS_PC_ACC_ACTIVE bit and remove ownership for localities less than the\r
+/// locality that is writing this bit.\r
+///\r
+#define TIS_PC_ACC_SEIZE            BIT3\r
+///\r
+/// When this bit is 1, another locality is requesting usage of the TPM.\r
+///\r
+#define TIS_PC_ACC_PENDIND          BIT2\r
+///\r
+/// Set to 1 to indicate that this locality is requesting to use TPM.\r
+///\r
+#define TIS_PC_ACC_RQUUSE           BIT1\r
+///\r
+/// A value of 1 indicates that a T/OS has not been established on the platform\r
+///\r
+#define TIS_PC_ACC_ESTABLISH        BIT0\r
+\r
+///\r
+/// When this bit is 1, TPM is in the Ready state, \r
+/// indicating it is ready to receive a new command.\r
+///\r
+#define TIS_PC_STS_READY            BIT6\r
+///\r
+/// Write a 1 to this bit to cause the TPM to execute that command.\r
+///\r
+#define TIS_PC_STS_GO               BIT5\r
+///\r
+/// This bit indicates that the TPM has data available as a response.\r
+///\r
+#define TIS_PC_STS_DATA             BIT4\r
+///\r
+/// The TPM sets this bit to a value of 1 when it expects another byte of data for a command.\r
+///\r
+#define TIS_PC_STS_EXPECT           BIT3\r
+///\r
+/// Writes a 1 to this bit to force the TPM to re-send the response.\r
+///\r
+#define TIS_PC_STS_RETRY            BIT1\r
+\r
+//\r
+// Default TimeOut value\r
+//\r
+#define TIS_TIMEOUT_A               (1000 * 1000)  // 1s\r
+#define TIS_TIMEOUT_B               (2000 * 1000)  // 2s\r
+#define TIS_TIMEOUT_C               (1000 * 1000)  // 1s\r
+#define TIS_TIMEOUT_D               (1000 * 1000)  // 1s\r
+\r
+#define TIS_TIMEOUT_MAX             (90000 * 1000)  // 90s\r
+\r
+//\r
+// Max TPM command/reponse length\r
+//\r
+#define TPMCMDBUFLENGTH             0x500\r
+\r
+/**\r
+  Check whether TPM chip exist.\r
+\r
+  @param[in] TisReg  Pointer to TIS register.\r
+\r
+  @retval    TRUE    TPM chip exists.\r
+  @retval    FALSE   TPM chip is not found.\r
+**/\r
+BOOLEAN\r
+TisPcPresenceCheck (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg\r
+  )\r
+{\r
+  UINT8                             RegRead;\r
+  \r
+  RegRead = MmioRead8 ((UINTN)&TisReg->Access);\r
+  return (BOOLEAN)(RegRead != (UINT8)-1);\r
+}\r
+\r
+/**\r
+  Check whether the value of a TPM chip register satisfies the input BIT setting.\r
+\r
+  @param[in]  Register     Address port of register to be checked.\r
+  @param[in]  BitSet       Check these data bits are set.\r
+  @param[in]  BitClear     Check these data bits are clear.\r
+  @param[in]  TimeOut      The max wait time (unit MicroSecond) when checking register.\r
+\r
+  @retval     EFI_SUCCESS  The register satisfies the check bit.\r
+  @retval     EFI_TIMEOUT  The register can't run into the expected status in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TisPcWaitRegisterBits (\r
+  IN      UINT8                     *Register,\r
+  IN      UINT8                     BitSet,\r
+  IN      UINT8                     BitClear,\r
+  IN      UINT32                    TimeOut\r
+  )\r
+{\r
+  UINT8                             RegRead;\r
+  UINT32                            WaitTime;\r
+\r
+  for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){\r
+    RegRead = MmioRead8 ((UINTN)Register);\r
+    if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0)\r
+      return EFI_SUCCESS;\r
+    MicroSecondDelay (30);\r
+  }\r
+  return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+  Get BurstCount by reading the burstCount field of a TIS regiger \r
+  in the time of default TIS_TIMEOUT_D.\r
+\r
+  @param[in]  TisReg                Pointer to TIS register.\r
+  @param[out] BurstCount            Pointer to a buffer to store the got BurstConut.\r
+\r
+  @retval     EFI_SUCCESS           Get BurstCount.\r
+  @retval     EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.\r
+  @retval     EFI_TIMEOUT           BurstCount can't be got in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TisPcReadBurstCount (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg,\r
+     OUT  UINT16                    *BurstCount\r
+  )\r
+{\r
+  UINT32                            WaitTime;\r
+  UINT8                             DataByte0;\r
+  UINT8                             DataByte1;\r
+\r
+  if (BurstCount == NULL || TisReg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  WaitTime = 0;\r
+  do {\r
+    //\r
+    // TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,\r
+    // so it needs to use MmioRead8 to read two times\r
+    //\r
+    DataByte0   = MmioRead8 ((UINTN)&TisReg->BurstCount);\r
+    DataByte1   = MmioRead8 ((UINTN)&TisReg->BurstCount + 1);\r
+    *BurstCount = (UINT16)((DataByte1 << 8) + DataByte0);\r
+    if (*BurstCount != 0) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    MicroSecondDelay (30);\r
+    WaitTime += 30;\r
+  } while (WaitTime < TIS_TIMEOUT_D);\r
+\r
+  return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+  Set TPM chip to ready state by sending ready command TIS_PC_STS_READY \r
+  to Status Register in time.\r
+\r
+  @param[in] TisReg                Pointer to TIS register.\r
+\r
+  @retval    EFI_SUCCESS           TPM chip enters into ready state.\r
+  @retval    EFI_INVALID_PARAMETER TisReg is NULL.\r
+  @retval    EFI_TIMEOUT           TPM chip can't be set to ready state in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TisPcPrepareCommand (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+\r
+  if (TisReg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
+  Status = TisPcWaitRegisterBits (\r
+             &TisReg->Status,\r
+             TIS_PC_STS_READY,\r
+             0,\r
+             TIS_TIMEOUT_B\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE \r
+  to ACCESS Register in the time of default TIS_TIMEOUT_A.\r
+\r
+  @param[in] TisReg                Pointer to TIS register.\r
+\r
+  @retval    EFI_SUCCESS           Get the control of TPM chip.\r
+  @retval    EFI_INVALID_PARAMETER TisReg is NULL.\r
+  @retval    EFI_NOT_FOUND         TPM chip doesn't exit.\r
+  @retval    EFI_TIMEOUT           Can't get the TPM control in time.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TisPcRequestUseTpm (\r
+  IN      TIS_PC_REGISTERS_PTR      TisReg\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  \r
+  if (TisReg == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  if (!TisPcPresenceCheck (TisReg)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  MmioWrite8((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);\r
+  Status = TisPcWaitRegisterBits (\r
+             &TisReg->Access,\r
+             (UINT8)(TIS_PC_ACC_ACTIVE |TIS_PC_VALID),\r
+             0,\r
+             TIS_TIMEOUT_A\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send a command to TPM for execution and return response data.\r
+\r
+  @param[in]      TisReg        TPM register space base address.  \r
+  @param[in]      BufferIn      Buffer for command data.  \r
+  @param[in]      SizeIn        Size of command data.  \r
+  @param[in, out] BufferOut     Buffer for response data.  \r
+  @param[in, out] SizeOut       Size of response data.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_TIMEOUT           The register can't run into the expected status in time.\r
+  @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.\r
+  @retval EFI_DEVICE_ERROR      Unexpected device behavior.\r
+  @retval EFI_UNSUPPORTED       Unsupported TPM version\r
+\r
+**/\r
+EFI_STATUS\r
+TisTpmCommand (\r
+  IN     TIS_PC_REGISTERS_PTR       TisReg,\r
+  IN     UINT8                      *BufferIn,\r
+  IN     UINT32                     SizeIn,\r
+  IN OUT UINT8                      *BufferOut,\r
+  IN OUT UINT32                     *SizeOut\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINT16                            BurstCount;\r
+  UINT32                            Index;\r
+  UINT32                            TpmOutSize;\r
+  UINT16                            Data16;\r
+  UINT32                            Data32;\r
+\r
+  DEBUG_CODE (\r
+    UINTN  DebugSize;\r
+\r
+    DEBUG ((EFI_D_INFO, "TisTpmCommand Send - "));\r
+    if (SizeIn > 0x100) {\r
+      DebugSize = 0x40;\r
+    } else {\r
+      DebugSize = SizeIn;\r
+    }\r
+    for (Index = 0; Index < DebugSize; Index++) {\r
+      DEBUG ((EFI_D_INFO, "%02x ", BufferIn[Index]));\r
+    }\r
+    if (DebugSize != SizeIn) {\r
+      DEBUG ((EFI_D_INFO, "...... "));\r
+      for (Index = SizeIn - 0x20; Index < SizeIn; Index++) {\r
+        DEBUG ((EFI_D_INFO, "%02x ", BufferIn[Index]));\r
+      }\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  );\r
+  TpmOutSize = 0;\r
+\r
+  Status = TisPcPrepareCommand (TisReg);\r
+  if (EFI_ERROR (Status)){\r
+    DEBUG ((DEBUG_ERROR, "Tpm is not ready for command!\n"));\r
+    return Status;\r
+  }\r
+  //\r
+  // Send the command data to Tpm\r
+  //\r
+  Index = 0;\r
+  while (Index < SizeIn) {\r
+    Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+    for (; BurstCount > 0 && Index < SizeIn; BurstCount--) {\r
+      MmioWrite8((UINTN)&TisReg->DataFifo, *(BufferIn + Index));\r
+      Index++;\r
+    }\r
+  }\r
+  //\r
+  // Check the Tpm status STS_EXPECT change from 1 to 0\r
+  //\r
+  Status = TisPcWaitRegisterBits (\r
+             &TisReg->Status,\r
+             (UINT8) TIS_PC_VALID,\r
+             TIS_PC_STS_EXPECT,\r
+             TIS_TIMEOUT_C\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "The send buffer too small!\n"));\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Exit;\r
+  }\r
+  //\r
+  // Executed the TPM command and waiting for the response data ready\r
+  //\r
+  MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_GO);\r
+\r
+  //\r
+  // NOTE: That may take many seconds to minutes for certain commands, such as key generation.\r
+  //\r
+  Status = TisPcWaitRegisterBits (\r
+             &TisReg->Status,\r
+             (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),\r
+             0,\r
+             TIS_TIMEOUT_MAX\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Wait for Tpm response data time out!!\n"));\r
+    Status = EFI_TIMEOUT;\r
+    goto Exit;\r
+  }\r
+  //\r
+  // Get response data header\r
+  //\r
+  Index = 0;\r
+  BurstCount = 0;\r
+  while (Index < sizeof (TPM2_RESPONSE_HEADER)) {\r
+    Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+    for (; BurstCount > 0; BurstCount--) {\r
+      *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
+      Index++;\r
+      if (Index == sizeof (TPM2_RESPONSE_HEADER)) break;\r
+    }\r
+  }\r
+  DEBUG_CODE (\r
+    DEBUG ((EFI_D_INFO, "TisTpmCommand ReceiveHeader - "));\r
+    for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) {\r
+      DEBUG ((EFI_D_INFO, "%02x ", BufferOut[Index]));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  );\r
+  //\r
+  // Check the reponse data header (tag,parasize and returncode )\r
+  //\r
+  CopyMem (&Data16, BufferOut, sizeof (UINT16));\r
+  // TPM2 should not use this RSP_COMMAND\r
+  if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) {\r
+    DEBUG ((EFI_D_ERROR, "TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Exit;\r
+  }\r
+\r
+  CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));\r
+  TpmOutSize  = SwapBytes32 (Data32);\r
+  if (*SizeOut < TpmOutSize) {\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Exit;\r
+  }\r
+  *SizeOut = TpmOutSize;\r
+  //\r
+  // Continue reading the remaining data\r
+  //\r
+  while ( Index < TpmOutSize ) {\r
+    for (; BurstCount > 0; BurstCount--) {\r
+      *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
+      Index++;\r
+      if (Index == TpmOutSize) {\r
+        Status = EFI_SUCCESS;\r
+        goto Exit;\r
+      }\r
+    }\r
+    Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+  }\r
+Exit:\r
+  DEBUG_CODE (\r
+    DEBUG ((EFI_D_INFO, "TisTpmCommand Receive - "));\r
+    for (Index = 0; Index < TpmOutSize; Index++) {\r
+      DEBUG ((EFI_D_INFO, "%02x ", BufferOut[Index]));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  );\r
+  MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DTpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  return TisTpmCommand (\r
+           (TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress),\r
+           InputParameterBlock,\r
+           InputParameterBlockSize,\r
+           OutputParameterBlock,\r
+           OutputParameterBlockSize\r
+           );\r
+}\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DTpm2RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  return TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.c b/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.c
new file mode 100644 (file)
index 0000000..5e1501e
--- /dev/null
@@ -0,0 +1,98 @@
+/** @file\r
+  Ihis library is TPM2 device router. Platform can register multi TPM2 instance to it\r
+  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.\r
+  At most one TPM2 instance can be finally registered, and other will return unsupported.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+\r
+TPM2_DEVICE_INTERFACE  mInternalTpm2DeviceInterface;\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  if (mInternalTpm2DeviceInterface.Tpm2SubmitCommand == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  return mInternalTpm2DeviceInterface.Tpm2SubmitCommand (\r
+                                        InputParameterBlockSize,\r
+                                        InputParameterBlock,\r
+                                        OutputParameterBlockSize,\r
+                                        OutputParameterBlock\r
+                                        );\r
+}\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  if (mInternalTpm2DeviceInterface.Tpm2RequestUseTpm == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  return mInternalTpm2DeviceInterface.Tpm2RequestUseTpm ();\r
+}\r
+\r
+/**\r
+  This service register TPM2 device.\r
+\r
+  @param Tpm2Device  TPM2 device\r
+\r
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.\r
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RegisterTpm2DeviceLib (\r
+  IN TPM2_DEVICE_INTERFACE   *Tpm2Device\r
+  )\r
+{\r
+  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &Tpm2Device->ProviderGuid)){\r
+    DEBUG ((EFI_D_ERROR, "WARNING: Tpm2RegisterTpm2DeviceLib - does not support %g registration\n", &Tpm2Device->ProviderGuid));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  CopyMem (&mInternalTpm2DeviceInterface, Tpm2Device, sizeof(mInternalTpm2DeviceInterface));\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf b/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf
new file mode 100644 (file)
index 0000000..2e69988
--- /dev/null
@@ -0,0 +1,44 @@
+## @file\r
+#  Ihis library is TPM2 device router. Platform can register multi TPM2 instance to it\r
+#  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.\r
+#  At most one TPM2 instance can be finally registered, and other will return unsupported.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm2DeviceLibRouterDxe\r
+  FILE_GUID                      = C3D69D87-5200-4aab-A6DB-2569BA1A92FC\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm2DeviceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm2DeviceLibRouterDxe.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.c b/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.c
new file mode 100644 (file)
index 0000000..f59b7bf
--- /dev/null
@@ -0,0 +1,143 @@
+/** @file\r
+  Ihis library is TPM2 device router. Platform can register multi TPM2 instance to it\r
+  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.\r
+  At most one TPM2 instance can be finally registered, and other will return unsupported.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+\r
+EFI_GUID mInternalTpm2DeviceInterfaceGuid = {\r
+  0x349cf818, 0xc0ba, 0x4c43, 0x92, 0x9a, 0xc8, 0xa1, 0xb1, 0xb3, 0xd2, 0x55\r
+};\r
+\r
+/**\r
+  This function get TPM2.0 interface.\r
+\r
+  @retval TPM2.0 interface.\r
+**/\r
+TPM2_DEVICE_INTERFACE *\r
+InternalGetTpm2DeviceInterface (\r
+  VOID\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE *Hob;\r
+\r
+  Hob = GetFirstGuidHob (&mInternalTpm2DeviceInterfaceGuid);\r
+  if (Hob == NULL) {\r
+    return NULL;\r
+  }\r
+  return (TPM2_DEVICE_INTERFACE *)(Hob + 1);\r
+}\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  TPM2_DEVICE_INTERFACE *Tpm2DeviceInterface;\r
+\r
+  Tpm2DeviceInterface = InternalGetTpm2DeviceInterface ();\r
+  if (Tpm2DeviceInterface == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return Tpm2DeviceInterface->Tpm2SubmitCommand (\r
+                                InputParameterBlockSize,\r
+                                InputParameterBlock,\r
+                                OutputParameterBlockSize,\r
+                                OutputParameterBlock\r
+                                );\r
+}\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  TPM2_DEVICE_INTERFACE *Tpm2DeviceInterface;\r
+\r
+  Tpm2DeviceInterface = InternalGetTpm2DeviceInterface ();\r
+  if (Tpm2DeviceInterface == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  return Tpm2DeviceInterface->Tpm2RequestUseTpm ();\r
+}\r
+\r
+/**\r
+  This service register TPM2 device.\r
+\r
+  @param Tpm2Device  TPM2 device\r
+\r
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.\r
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RegisterTpm2DeviceLib (\r
+  IN TPM2_DEVICE_INTERFACE   *Tpm2Device\r
+  )\r
+{\r
+  TPM2_DEVICE_INTERFACE *Tpm2DeviceInterface;\r
+\r
+  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &Tpm2Device->ProviderGuid)){\r
+    DEBUG ((EFI_D_ERROR, "WARNING: Tpm2RegisterTpm2DeviceLib - does not support %g registration\n", &Tpm2Device->ProviderGuid));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Tpm2DeviceInterface = InternalGetTpm2DeviceInterface ();\r
+  if (Tpm2DeviceInterface != NULL) {\r
+    //\r
+    // In PEI phase, there will be shadow driver dispatched again.\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "Tpm2RegisterTpm2DeviceLib - Override\n"));\r
+    CopyMem (Tpm2DeviceInterface, Tpm2Device, sizeof(*Tpm2Device));\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    Tpm2Device = BuildGuidDataHob (&mInternalTpm2DeviceInterfaceGuid, Tpm2Device, sizeof(*Tpm2Device));\r
+    if (Tpm2Device != NULL) {\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.inf b/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.inf
new file mode 100644 (file)
index 0000000..dbdfc3d
--- /dev/null
@@ -0,0 +1,46 @@
+## @file\r
+#  Ihis library is TPM2 device router. Platform can register multi TPM2 instance to it\r
+#  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.\r
+#  At most one TPM2 instance can be finally registered, and other will return unsupported.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm2DeviceLibRouterPei\r
+  FILE_GUID                      = 97CDCF04-4C8E-42fe-8015-11CC8A6E9D81\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm2DeviceLib|PEIM\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm2DeviceLibRouterPei.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  HobLib\r
+  PcdLib\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
+  
\ No newline at end of file
diff --git a/SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.c b/SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.c
new file mode 100644 (file)
index 0000000..53963b7
--- /dev/null
@@ -0,0 +1,125 @@
+/** @file\r
+  Ihis library is TPM2 TREE protocol lib.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+#include <IndustryStandard/Tpm20.h>\r
+\r
+EFI_TREE_PROTOCOL  *mTreeProtocol = NULL; \r
+\r
+/**\r
+  This service enables the sending of commands to the TPM2.\r
+\r
+  @param[in]      InputParameterBlockSize  Size of the TPM2 input parameter block.\r
+  @param[in]      InputParameterBlock      Pointer to the TPM2 input parameter block.\r
+  @param[in,out]  OutputParameterBlockSize Size of the TPM2 output parameter block.\r
+  @param[in]      OutputParameterBlock     Pointer to the TPM2 output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2SubmitCommand (\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN OUT UINT32        *OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPM2_RESPONSE_HEADER      *Header;\r
+\r
+  if (mTreeProtocol == NULL) {\r
+    Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &mTreeProtocol);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // TrEE protocol is not installed. So, TPM2 is not present.\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Tpm2SubmitCommand - TrEE - %r\n", Status));\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  //\r
+  // Assume when TrEE Protocol is ready, RequestUseTpm already done.\r
+  //\r
+  Status = mTreeProtocol->SubmitCommand (\r
+                            mTreeProtocol,\r
+                            InputParameterBlockSize,\r
+                            InputParameterBlock,\r
+                            *OutputParameterBlockSize,\r
+                            OutputParameterBlock\r
+                            );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Header = (TPM2_RESPONSE_HEADER *)OutputParameterBlock;\r
+  *OutputParameterBlockSize = SwapBytes32 (Header->paramSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This service requests use TPM2.\r
+\r
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.\r
+  @retval EFI_NOT_FOUND    TPM2 not found.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+\r
+  if (mTreeProtocol == NULL) {\r
+    Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &mTreeProtocol);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // TrEE protocol is not installed. So, TPM2 is not present.\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Tpm2RequestUseTpm - TrEE - %r\n", Status));\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  //\r
+  // Assume when TrEE Protocol is ready, RequestUseTpm already done.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This service register TPM2 device.\r
+\r
+  @param Tpm2Device  TPM2 device\r
+\r
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.\r
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.\r
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2RegisterTpm2DeviceLib (\r
+  IN TPM2_DEVICE_INTERFACE   *Tpm2Device\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf b/SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf
new file mode 100644 (file)
index 0000000..684b1f1
--- /dev/null
@@ -0,0 +1,42 @@
+## @file\r
+#  Ihis library is TPM2 TREE protocol lib.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm2DeviceLibTrEE\r
+  FILE_GUID                      = BBCB6F85-303C-4eb9-8182-AF98D4B3020C\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm2DeviceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  Tpm2DeviceLibTrEE.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  UefiBootServicesTableLib\r
+\r
+[Protocols]\r
+  gEfiTrEEProtocolGuid                           ## CONSUMES\r
index 444332c88cf1e8b057e177685bf46df13e6d32b4..a5209fc6dbebe5665a88e0b51025a28a77fd77d9 100644 (file)
   ##  @libraryclass  Definitions for common TPM commands as library API for TPM\r
   #                  module use.\r
   TpmCommLib|Include/Library/TpmCommLib.h\r
+  Tpm2CommandLib|Include/Library/Tpm2CommandLib.h\r
+  Tpm2DeviceLib|Include/Library/Tpm2DeviceLib.h\r
+  TrEEPhysicalPresenceLib|Include/Library/TrEEPhysicalPresenceLib.h\r
+  TpmMeasurementLib|Include/Library/TpmMeasurementLib.h\r
 \r
 [Guids]\r
   ## Security package token space guid\r
   ## Include/Guid/SecureBootConfigHii.h\r
   gSecureBootConfigFormSetGuid       = { 0x5daf50a5, 0xea81, 0x4de2, {0x8f, 0x9b, 0xca, 0xbd, 0xa9, 0xcf, 0x5c, 0x14}}\r
                                       \r
+  ## Include/Guid/TrEEPhysicalPresenceData.h\r
+  gEfiTrEEPhysicalPresenceGuid = { 0xf24643c2, 0xc622, 0x494e, { 0x8a, 0xd, 0x46, 0x32, 0x57, 0x9c, 0x2d, 0x5b }}\r
+\r
+  ## Include/Guid/TpmInstance.h\r
+  gEfiTpmDeviceInstanceNoneGuid      = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }\r
+  gEfiTpmDeviceInstanceTpm12Guid     = { 0x8b01e5b6, 0x4f19, 0x46e8, { 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc } }\r
+  gEfiTpmDeviceInstanceTpm20DtpmGuid = { 0x286bf25a, 0xc2c3, 0x408c, { 0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17 } }\r
+  gEfiTpmDeviceSelectedGuid          = { 0x7f4158d3, 0x74d, 0x456d, { 0x8c, 0xb2, 0x1, 0xf9, 0xc8, 0xf7, 0x9d, 0xaa } }\r
+\r
+  ## Include/Guid/TrEEConfigHii.h\r
+  gTrEEConfigFormSetGuid              = {0xc54b425f, 0xaa79, 0x48b4, { 0x98, 0x1f, 0x99, 0x8b, 0x3c, 0x4b, 0x64, 0x1c }}\r
+\r
 [Ppis]\r
   ## Include/Ppi/LockPhysicalPresence.h\r
   gPeiLockPhysicalPresencePpiGuid    = { 0xef9aefe5, 0x2bd3, 0x4031, { 0xaf, 0x7d, 0x5e, 0xfe, 0x5a, 0xbb, 0x9a, 0xd } }\r
@@ -81,6 +97,9 @@
   ## Include/Ppi/TpmInitialized.h\r
   gPeiTpmInitializedPpiGuid      = { 0xe9db0d58, 0xd48d, 0x47f6, { 0x9c, 0x6e, 0x6f, 0x40, 0xe8, 0x6c, 0x7b, 0x41 }}\r
 \r
+  ## Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h\r
+  gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid = { 0x6e056ff9, 0xc695, 0x4364, { 0x9e, 0x2c, 0x61, 0x26, 0xf5, 0xce, 0xea, 0xae } }\r
+\r
 [PcdsFixedAtBuild]\r
   ## Pcd for OptionRom.\r
   #  Image verification policy settings:\r
   ## This PCD is used to specify the default value for physicalPresenceHWEnable bit when setting physicalPresenceLifetimeLock bit.\r
   ## If PcdPhysicalPresenceHwEnable is set to TRUE, physicalPresenceHWEnable bit will be set, else this bit will be cleared.\r
   gEfiSecurityPkgTokenSpaceGuid.PcdPhysicalPresenceHwEnable|TRUE|BOOLEAN|0x00010005\r
+\r
+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]\r
+  ## This PCD indicates if debugger exists.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdFirmwareDebuggerInitialized|FALSE|BOOLEAN|0x00010009\r
+\r
+  ## This PCD indicates the TPM2 initializatin policy.\r
+  ## 0: No initialization needed - most likely used for chipset SRTM sloution, in which TPM is already initialized.\r
+  ## 1: Initialization needed.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2InitializationPolicy|1|UINT8|0x0001000A\r
+\r
+  ## This PCD indicates the TPM initializatin policy.\r
+  ## 0: No initialization needed - most likely used for chipset SRTM sloution, in which TPM is already initialized.\r
+  ## 1: Initialization needed.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy|1|UINT8|0x0001000B\r
+\r
+  ## This PCD indicates the TPM2 SelfTest policy.\r
+  ## 0: No SelfTest needed - most likely used for fTPM, because it might already be tested.\r
+  ## 1: SelfTest needed.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2SelfTestPolicy|1|UINT8|0x0001000C\r
+\r
+  ## This PCD indicates the TPM2 SCRTM policy.\r
+  ##   0: No SCRTM needed - In this case, it is already done.\r
+  ##   1: SCRTM done by BIOS.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2ScrtmPolicy|1|UINT8|0x0001000D\r
+\r
+  ## This PCD indicates the TPM SCRTM policy.\r
+  ##   0: No SCRTM needed - In this case, it is already done.\r
+  ##   1: SCRTM done by BIOS.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmScrtmPolicy|1|UINT8|0x0001000E\r
+\r
+  ## Guid name to identify TPM instance\r
+  ## TPM_DEVICE_INTERFACE_NONE means disable\r
+  ## TPM_DEVICE_INTERFACE_TPM12 means TPM1.2 DTPM\r
+  ## TPM_DEVICE_INTERFACE_DTPM2 means TPM2 DTPM\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid |{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }|VOID*|0x0001000F\r
+\r
+  ## This PCD indicates the TPM2 Hash mask.\r
+  ##   BIT0: SHA1\r
+  ##   BIT1: SHA256\r
+  ##   BIT2: SHA384\r
+  ##   BIT3: SHA512\r
+  ## If this bit is set, that means this algorithm is needed to extend to PCR.\r
+  ## If this bit is clear, that means this algorithm is NOT needed to extend to PCR.\r
+  ## 0xFFFFFFFF means extend all.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask|0xFFFFFFFF|UINT32|0x00010010\r
+\r
+  ## This PCD indicates if BIOS auto detect TPM1.2 or dTPM2.0.\r
+  ## 0: No auto detection.\r
+  ## 1: Auto detection.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmAutoDetection|TRUE|BOOLEAN|0x00010011\r
+\r
+  ## This PCD indicates TPM base address.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0xFED40000|UINT64|0x00010012\r
index 54b5b2464dbec2cfdba5735a9868833f073b8de8..ebe65b8d0d1f400a6d4815728f736bf8abbc0e04 100644 (file)
@@ -32,6 +32,7 @@
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
   UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
 \r
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
   UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
@@ -51,6 +52,9 @@
   PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf\r
   TcgPhysicalPresenceLib|SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.inf\r
   TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf\r
+  Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf\r
+  Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf\r
+  TrEEPhysicalPresenceLib|SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf\r
 \r
 [LibraryClasses.common.PEIM]\r
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf\r
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
   MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf\r
+  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf\r
+  Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf\r
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf\r
 \r
 [LibraryClasses.common.DXE_DRIVER]\r
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
+  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf\r
+  Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf\r
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
 \r
 [LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_SAL_DRIVER,]\r
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
   DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf\r
+  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf\r
+  Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf\r
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
 \r
 [LibraryClasses.common.DXE_RUNTIME_DRIVER]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
+  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf\r
+  Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf\r
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
 \r
 [LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
+  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf\r
+  Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf\r
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
 \r
 [LibraryClasses.IPF.DXE_SAL_DRIVER]\r
   ExtendedSalLib|MdePkg/Library/DxeRuntimeExtendedSalLib/DxeRuntimeExtendedSalLib.inf\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/BaseCryptLibRuntimeCryptProtocol.inf\r
+  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf\r
+  Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf\r
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
 \r
 [LibraryClasses.common.DXE_SMM_DRIVER]\r
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
   SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf\r
   MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf\r
+  Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf\r
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
     \r
+[PcdsDynamicDefault.common.DEFAULT]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0xb6, 0xe5, 0x01, 0x8b, 0x19, 0x4f, 0xe8, 0x46, 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc}\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2InitializationPolicy|1\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2SelfTestPolicy|1\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2ScrtmPolicy|1\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy|1\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmScrtmPolicy|1\r
+\r
 [Components]\r
   SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf\r
   SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf\r
   #\r
   SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf\r
   SecurityPkg/Library/TpmCommLib/TpmCommLib.inf\r
+  SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.inf\r
+  SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf\r
+  SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf\r
+  SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf\r
 \r
   SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf\r
   SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf\r
-  \r
+\r
+  #\r
+  # TPM2\r
+  #\r
+  SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf\r
+  SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf\r
+\r
+  SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf\r
+  SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf\r
+\r
+  SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf\r
+  SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
+  SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf\r
+  SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf\r
+  SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf\r
+  SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.inf\r
+\r
+  SecurityPkg/Library/HashLibTpm2/HashLibTpm2.inf\r
+\r
 [Components.IA32, Components.X64, Components.IPF]\r
   SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf\r
   SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf\r
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf\r
   }\r
 \r
+  #\r
+  # TPM2\r
+  #\r
+  SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf\r
+  SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf\r
+\r
+  SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf {\r
+    <LibraryClasses>\r
+      Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf\r
+      Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf\r
+  }\r
+  SecurityPkg/Tcg/TrEEPei/TrEEPei.inf {\r
+    <LibraryClasses>\r
+      Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.inf\r
+      NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf\r
+      NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf\r
+      NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf\r
+  }\r
+\r
+  SecurityPkg/Tcg/TrEEDxe/TrEEDxe.inf {\r
+    <LibraryClasses>\r
+      Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf\r
+      NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf\r
+      NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf\r
+      NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf\r
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf\r
+  }\r
+  SecurityPkg/Tcg/TrEEConfig/TrEEConfigDxe.inf {\r
+    <LibraryClasses>\r
+      Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf\r
+  }\r
+\r
 [Components.IA32, Components.X64]\r
   SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf\r
   SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf\r
   SecurityPkg/Tcg/TcgSmm/TcgSmm.inf\r
+  SecurityPkg/Tcg/TrEESmm/TrEESmm.inf\r
 \r
 [Components.IPF]\r
   SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/EsalVariableDxeSal.inf \r
index 6cf51b78dad6a3746cc3d5ef00085d57ed8cc947..1aa296b47c27699252b9c1f2a8767dfc6023cb42 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Component description file for Memory Overwrite Control driver.\r
 #\r
-# Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
@@ -47,5 +47,5 @@
 [Depex]\r
   gEfiVariableArchProtocolGuid AND\r
   gEfiVariableWriteArchProtocolGuid AND\r
-  gEfiTcgProtocolGuid\r
+  ( gEfiTcgProtocolGuid OR gEfiTrEEProtocolGuid )\r
 \r
index 2d3728cdb228a75f16a2e8cf5cba20b3781ad46f..a9a10c9e107f527d7a45f5c2436d1847e749bd44 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The module entry point for Tcg configuration module.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials \r
 are licensed and made available under the terms and conditions of the BSD License \r
 which accompanies this distribution.  The full text of the license may be found at \r
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "TcgConfigImpl.h"\r
+#include <Guid/TpmInstance.h>\r
 \r
 /**\r
   The entry point for Tcg configuration driver.\r
@@ -37,6 +38,11 @@ TcgConfigDriverEntryPoint (
   TCG_CONFIG_PRIVATE_DATA   *PrivateData;\r
   EFI_TCG_PROTOCOL          *TcgProtocol;\r
 \r
+  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
+    DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   Status = TisPcRequestUseTpm ((TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "TPM not detected!\n"));\r
index 5edd6ab4b8e4bff6eac671e0aff3dfbf291360b1..cdfc89c2ece4564e301f01acec4b339cab75cf77 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Component name for Tcg configuration module.\r
 #\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
@@ -56,6 +56,7 @@
   gEfiPhysicalPresenceGuid\r
   gEfiIfrTianoGuid\r
   gTcgConfigFormSetGuid\r
+  gEfiTpmDeviceInstanceTpm12Guid\r
 \r
 [Protocols]\r
   gEfiHiiConfigAccessProtocolGuid               ## PRODUCES\r
@@ -67,6 +68,7 @@
 \r
 [Pcd]\r
   gEfiSecurityPkgTokenSpaceGuid.PcdHideTpm\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
 \r
 [Depex]\r
   gEfiHiiConfigRoutingProtocolGuid  AND\r
index 4f3568ba840123b9acde334cb67499ec99f0fb3b..322d726037e949f373e613a58b2f8b1ea29e3192 100644 (file)
@@ -24,6 +24,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <IndustryStandard/Acpi.h>\r
 #include <IndustryStandard/PeImage.h>\r
 #include <IndustryStandard/SmBios.h>\r
+#include <IndustryStandard/TcpaAcpi.h>\r
 \r
 #include <Guid/GlobalVariable.h>\r
 #include <Guid/SmBios.h>\r
@@ -31,6 +32,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Guid/TcgEventHob.h>\r
 #include <Guid/EventGroup.h>\r
 #include <Guid/EventExitBootServiceFailed.h>\r
+#include <Guid/TpmInstance.h>\r
+\r
 #include <Protocol/DevicePath.h>\r
 #include <Protocol/TcgService.h>\r
 #include <Protocol/AcpiTable.h>\r
@@ -53,38 +56,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #define  EFI_TCG_LOG_AREA_SIZE        0x10000\r
 \r
-#pragma pack (1)\r
-\r
-typedef struct _EFI_TCG_CLIENT_ACPI_TABLE {\r
-  EFI_ACPI_DESCRIPTION_HEADER       Header;\r
-  UINT16                            PlatformClass;\r
-  UINT32                            Laml;\r
-  EFI_PHYSICAL_ADDRESS              Lasa;\r
-} EFI_TCG_CLIENT_ACPI_TABLE;\r
-\r
-typedef struct _EFI_TCG_SERVER_ACPI_TABLE {\r
-  EFI_ACPI_DESCRIPTION_HEADER             Header;\r
-  UINT16                                  PlatformClass;\r
-  UINT16                                  Reserved0;\r
-  UINT64                                  Laml;\r
-  EFI_PHYSICAL_ADDRESS                    Lasa;\r
-  UINT16                                  SpecRev;\r
-  UINT8                                   DeviceFlags;\r
-  UINT8                                   InterruptFlags;\r
-  UINT8                                   Gpe;\r
-  UINT8                                   Reserved1[3];\r
-  UINT32                                  GlobalSysInt;\r
-  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE  BaseAddress;\r
-  UINT32                                  Reserved2;\r
-  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE  ConfigAddress;\r
-  UINT8                                   PciSegNum;\r
-  UINT8                                   PciBusNum;\r
-  UINT8                                   PciDevNum;\r
-  UINT8                                   PciFuncNum;\r
-} EFI_TCG_SERVER_ACPI_TABLE;\r
-\r
-#pragma pack ()\r
-\r
 #define TCG_DXE_DATA_FROM_THIS(this)  \\r
   BASE_CR (this, TCG_DXE_DATA, TcgProtocol)\r
 \r
@@ -1344,6 +1315,11 @@ DriverEntry (
   EFI_EVENT                         Event;\r
   VOID                              *Registration;\r
 \r
+  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
+    DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   mTcgDxeData.TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;\r
   Status = TisPcRequestUseTpm (mTcgDxeData.TpmHandle);\r
   if (EFI_ERROR (Status)) {\r
index 6d5febf96257bc15380958e6c20b01acf81151cf..40984291f868b954634b8f5600ee19984a4e2058 100644 (file)
@@ -58,6 +58,7 @@
   gEfiEventReadyToBootGuid\r
   gEfiEventExitBootServicesGuid\r
   gEventExitBootServicesFailedGuid              # ALWAYS_CONSUMED\r
+  gEfiTpmDeviceInstanceTpm12Guid\r
 \r
 [Protocols]\r
   gEfiTcgProtocolGuid                           ## PRODUCES\r
@@ -67,6 +68,7 @@
 \r
 [Pcd]\r
   gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision\r
index 350e60e56123351165173831c402d8bd7d4d63ae..7ff869d0fc80ceb08961769175c08442e4fd8a8b 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Initialize TPM device and measure FVs before handing off control to DXE.\r
 \r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials \r
 are licensed and made available under the terms and conditions of the BSD License \r
 which accompanies this distribution.  The full text of the license may be found at \r
@@ -21,9 +21,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Ppi/TpmInitialized.h>\r
 #include <Ppi/FirmwareVolume.h>\r
 #include <Ppi/EndOfPeiPhase.h>\r
+#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>\r
 \r
 #include <Guid/TcgEventHob.h>\r
 #include <Guid/MeasuredFvHob.h>\r
+#include <Guid/TpmInstance.h>\r
 \r
 #include <Library/DebugLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
@@ -51,6 +53,8 @@ UINT32 mMeasuredBaseFvIndex = 0;
 EFI_PLATFORM_FIRMWARE_BLOB mMeasuredChildFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];\r
 UINT32 mMeasuredChildFvIndex = 0;\r
 \r
+EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;\r
+\r
 /**\r
   Lock physical presence if needed.\r
 \r
@@ -311,6 +315,19 @@ MeasureFvImage (
 \r
   TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS;\r
 \r
+  //\r
+  // Check if it is in Excluded FV list\r
+  //\r
+  if (mMeasurementExcludedFvPpi != NULL) {\r
+    for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {\r
+      if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {\r
+        DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase));\r
+        DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength));\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
   //\r
   // Check whether FV is in the measured FV list.\r
   //\r
@@ -627,6 +644,14 @@ PeimEntryMP (
   EFI_STATUS                        Status;\r
   TIS_TPM_HANDLE                    TpmHandle;\r
 \r
+  Status = PeiServicesLocatePpi (\r
+               &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, \r
+               0, \r
+               NULL,\r
+               (VOID**)&mMeasurementExcludedFvPpi\r
+               );\r
+  // Do not check status, because it is optional\r
+\r
   TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;\r
   Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);\r
   if (EFI_ERROR (Status)) {\r
@@ -634,8 +659,10 @@ PeimEntryMP (
   }\r
 \r
   if (IsTpmUsable (PeiServices, TpmHandle)) {\r
-    Status = MeasureCRTMVersion (PeiServices, TpmHandle);\r
-    ASSERT_EFI_ERROR (Status);\r
+    if (PcdGet8 (PcdTpmScrtmPolicy) == 1) {\r
+      Status = MeasureCRTMVersion (PeiServices, TpmHandle);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
 \r
     Status = MeasureMainBios (PeiServices, TpmHandle);\r
   }  \r
@@ -673,6 +700,11 @@ PeimEntryMA (
   EFI_BOOT_MODE                     BootMode;\r
   TIS_TPM_HANDLE                    TpmHandle;\r
 \r
+  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
+    DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -703,9 +735,11 @@ PeimEntryMA (
       return Status;\r
     }\r
 \r
-    Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode);\r
-    if (EFI_ERROR (Status) ) {\r
-      return Status;\r
+    if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {\r
+      Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode);\r
+      if (EFI_ERROR (Status) ) {\r
+        return Status;\r
+      }\r
     }\r
 \r
     //\r
index 48d4efce5ce19d0d9840440ee419afa71ad192a6..d02296247802092581ca86c02b45442921123975 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  This module will initialize TPM device and measure FVs in PEI phase.\r
 #\r
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
 [Guids]\r
   gTcgEventEntryHobGuid\r
   gMeasuredFvHobGuid\r
+  gEfiTpmDeviceInstanceTpm12Guid\r
 \r
 [Ppis]\r
   gPeiLockPhysicalPresencePpiGuid\r
   gEfiPeiFirmwareVolumeInfoPpiGuid\r
+  gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid\r
   gPeiTpmInitializedPpiGuid\r
   gEfiEndOfPeiSignalPpiGuid\r
 \r
@@ -65,6 +67,9 @@
   gEfiSecurityPkgTokenSpaceGuid.PcdPhysicalPresenceCmdEnable\r
   gEfiSecurityPkgTokenSpaceGuid.PcdPhysicalPresenceHwEnable\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString             ## CONSUMES\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmScrtmPolicy\r
 \r
 [FixedPcd]\r
   gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport\r
@@ -72,4 +77,5 @@
 \r
 [Depex]\r
   gEfiPeiMasterBootModePpiGuid AND\r
-  gEfiPeiReadOnlyVariable2PpiGuid\r
+  gEfiPeiReadOnlyVariable2PpiGuid AND\r
+  gEfiTpmDeviceSelectedGuid\r
index 06df822e998cc399063a1e288744f1b2a0fd26e9..045c1846fc8446b10004100000bd3e79547c99b8 100644 (file)
@@ -386,6 +386,11 @@ InitializeTcgSmm (
   EFI_SMM_SW_REGISTER_CONTEXT    SwContext;\r
   EFI_HANDLE                     SwHandle;\r
 \r
+  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
+    DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   Status = PublishAcpiTable ();\r
   ASSERT_EFI_ERROR (Status);\r
 \r
index 582b18214d9fe9c40d1e5a4e2a8db442a9eb01d3..eee8bc3d718bffc9e22d51b2f8f55b664e250fa9 100644 (file)
@@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Guid/PhysicalPresenceData.h>\r
 #include <Guid/MemoryOverwriteControl.h>\r
+#include <Guid/TpmInstance.h>\r
 \r
 #include <Protocol/SmmSwDispatch2.h>\r
 #include <Protocol/AcpiTable.h>\r
index 075f298f538163ccac7d602d231f888f3b6fc775..5a862b41b2ef743fa69d6736bf4b2077d4f40c53 100644 (file)
@@ -50,6 +50,7 @@
 [Guids]\r
   gEfiPhysicalPresenceGuid\r
   gEfiMemoryOverwriteControlDataGuid\r
+  gEfiTpmDeviceInstanceTpm12Guid\r
 \r
 [Protocols]\r
   gEfiSmmSwDispatch2ProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
@@ -57,6 +58,7 @@
   gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
 \r
 [Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId\r
 \r
 [Depex]\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TpmDetection.c b/SecurityPkg/Tcg/TrEEConfig/TpmDetection.c
new file mode 100644 (file)
index 0000000..b8aab1f
--- /dev/null
@@ -0,0 +1,107 @@
+/** @file\r
+  TPM1.2/dTPM2.0 auto detection.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/Tpm12DeviceLib.h>\r
+#include <Library/Tpm12CommandLib.h>\r
+#include <IndustryStandard/Tpm12.h>\r
+\r
+#include "TrEEConfigNvData.h"\r
+\r
+/**\r
+  This routine return if dTPM (1.2 or 2.0) present.\r
+\r
+  @retval TRUE  dTPM present\r
+  @retval FALSE dTPM not present\r
+**/\r
+BOOLEAN\r
+IsDtpmPresent (\r
+  VOID\r
+  )\r
+{\r
+  UINT8                             RegRead;\r
+  \r
+  RegRead = MmioRead8 ((UINTN)PcdGet64 (PcdTpmBaseAddress));\r
+  if (RegRead == 0xFF) {\r
+    DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Dtpm not present\n"));\r
+    return FALSE;\r
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Dtpm present\n"));\r
+    return TRUE;\r
+  }\r
+}\r
+\r
+/**\r
+  This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.\r
+\r
+  @param  SetupTpmDevice  TpmDevice configuration in setup driver\r
+\r
+  @return TpmDevice configuration\r
+**/\r
+UINT8\r
+DetectTpmDevice (\r
+  IN UINT8 SetupTpmDevice\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_BOOT_MODE                     BootMode;\r
+\r
+  Status = PeiServicesGetBootMode (&BootMode);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // In S3, we rely on Setup option, because we save to Setup in normal boot.\r
+  //\r
+  if (BootMode == BOOT_ON_S3_RESUME) {\r
+    DEBUG ((EFI_D_ERROR, "DetectTpmDevice: S3 mode\n"));\r
+    return SetupTpmDevice;\r
+  }\r
+\r
+  if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {\r
+    DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Tpm is hide\n"));\r
+    return TPM_DEVICE_NULL;\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "DetectTpmDevice:\n"));\r
+  if ((!IsDtpmPresent ()) || (SetupTpmDevice == TPM_DEVICE_NULL)) {\r
+    // dTPM not available\r
+    return TPM_DEVICE_NULL;\r
+  }\r
+\r
+  // dTPM available and not disabled by setup\r
+  // We need check if it is TPM1.2 or TPM2.0\r
+  // So try TPM1.2 command at first\r
+\r
+  Status = Tpm12RequestUseTpm ();\r
+  if (EFI_ERROR (Status)) {\r
+    return TPM_DEVICE_2_0_DTPM;\r
+  }\r
+\r
+  Status = Tpm12Startup (TPM_ST_CLEAR);\r
+  if (EFI_ERROR (Status)) {\r
+    return TPM_DEVICE_2_0_DTPM;\r
+  }\r
+\r
+  // NO initialization needed again.\r
+  PcdSet8 (PcdTpmInitializationPolicy, 0);\r
+  return TPM_DEVICE_1_2;\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfig.vfr b/SecurityPkg/Tcg/TrEEConfig/TrEEConfig.vfr
new file mode 100644 (file)
index 0000000..74e2363
--- /dev/null
@@ -0,0 +1,67 @@
+/** @file\r
+  VFR file used by the TREE configuration component.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TrEEConfigNvData.h"\r
+\r
+formset\r
+  guid      = TREE_CONFIG_FORM_SET_GUID,\r
+  title     = STRING_TOKEN(STR_TREE_TITLE),\r
+  help      = STRING_TOKEN(STR_TREE_HELP),\r
+  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,\r
+\r
+  varstore TREE_CONFIGURATION,\r
+    varid = TREE_CONFIGURATION_VARSTORE_ID,\r
+    name  = TREE_CONFIGURATION,\r
+    guid  = TREE_CONFIG_FORM_SET_GUID;\r
+\r
+  form formid = TREE_CONFIGURATION_FORM_ID,\r
+    title = STRING_TOKEN(STR_TREE_TITLE);\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    text\r
+      help   = STRING_TOKEN(STR_TREE_DEVICE_STATE_HELP),\r
+      text   = STRING_TOKEN(STR_TREE_DEVICE_STATE_PROMPT),\r
+        text   = STRING_TOKEN(STR_TREE_DEVICE_STATE_CONTENT);\r
+\r
+    oneof varid  = TREE_CONFIGURATION.TpmDevice,\r
+          questionid = KEY_TPM_DEVICE,\r
+          prompt = STRING_TOKEN(STR_TREE_DEVICE_PROMPT),\r
+          help   = STRING_TOKEN(STR_TREE_DEVICE_HELP),\r
+          flags  = INTERACTIVE,\r
+            option text = STRING_TOKEN(STR_TREE_TPM_DISABLE),      value = TPM_DEVICE_NULL,         flags = RESET_REQUIRED;\r
+            option text = STRING_TOKEN(STR_TREE_TPM_1_2),          value = TPM_DEVICE_1_2,          flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\r
+            option text = STRING_TOKEN(STR_TREE_TPM_2_0_DTPM),     value = TPM_DEVICE_2_0_DTPM,     flags = RESET_REQUIRED;\r
+    endoneof;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    suppressif ideqvallist TREE_CONFIGURATION.TpmDevice == TPM_DEVICE_NULL TPM_DEVICE_1_2;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    subtitle text = STRING_TOKEN(STR_TREE_PP_OPERATION);\r
+\r
+    oneof varid  = TREE_CONFIGURATION.Tpm2Operation,\r
+          prompt = STRING_TOKEN(STR_TREE_OPERATION),\r
+          help   = STRING_TOKEN(STR_TREE_OPERATION_HELP),\r
+          flags  = INTERACTIVE,\r
+            option text = STRING_TOKEN(STR_TREE_NO_ACTION), value = TREE_PHYSICAL_PRESENCE_NO_ACTION, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\r
+            option text = STRING_TOKEN(STR_TREE_CLEAR), value = TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR, flags = RESET_REQUIRED;\r
+    endoneof;\r
+\r
+    endif;\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigDriver.c b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigDriver.c
new file mode 100644 (file)
index 0000000..f3c8e5f
--- /dev/null
@@ -0,0 +1,171 @@
+/** @file\r
+  The module entry point for TrEE configuration module.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TrEEConfigImpl.h"\r
+\r
+extern TPM_INSTANCE_ID  mTpmInstanceId[TPM_DEVICE_MAX + 1];\r
+\r
+/**\r
+  The entry point for TrEE configuration driver.\r
+\r
+  @param[in]  ImageHandle        The image handle of the driver.\r
+  @param[in]  SystemTable        The system table.\r
+\r
+  @retval EFI_ALREADY_STARTED    The driver already exists in system.\r
+  @retval EFI_OUT_OF_RESOURCES   Fail to execute entry point due to lack of resources.\r
+  @retval EFI_SUCCES             All the related protocols are installed on the driver.\r
+  @retval Others                 Fail to install protocols as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEConfigDriverEntryPoint (\r
+  IN EFI_HANDLE          ImageHandle,\r
+  IN EFI_SYSTEM_TABLE    *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  TREE_CONFIG_PRIVATE_DATA      *PrivateData;\r
+  TREE_CONFIGURATION            TrEEConfiguration;\r
+  UINTN                         Index;\r
+  UINTN                         DataSize;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ImageHandle,\r
+                  &gEfiCallerIdGuid,\r
+                  NULL,\r
+                  ImageHandle,\r
+                  ImageHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+  \r
+  //\r
+  // Create a private data structure.\r
+  //\r
+  PrivateData = AllocateCopyPool (sizeof (TREE_CONFIG_PRIVATE_DATA), &mTrEEConfigPrivateDateTemplate);\r
+  ASSERT (PrivateData != NULL);\r
+\r
+  //\r
+  // Install private GUID.\r
+  //    \r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ImageHandle,\r
+                  &gEfiCallerIdGuid,\r
+                  PrivateData,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DataSize = sizeof(TrEEConfiguration);\r
+  Status = gRT->GetVariable (\r
+                  TREE_STORAGE_NAME,\r
+                  &gTrEEConfigFormSetGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &TrEEConfiguration\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+  }\r
+  //\r
+  // We should always reinit PP request.\r
+  //\r
+  TrEEConfiguration.Tpm2Operation = TREE_PHYSICAL_PRESENCE_NO_ACTION;\r
+\r
+  //\r
+  // Sync data from PCD to variable, so that we do not need detect again in S3 phase.\r
+  //\r
+\r
+  //\r
+  // Get data from PCD to make sure data consistant - platform driver is suppose to construct this PCD accroding to Variable\r
+  //\r
+  for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) {\r
+    if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &mTpmInstanceId[Index].TpmInstanceGuid)) {\r
+      TrEEConfiguration.TpmDevice = mTpmInstanceId[Index].TpmDevice;\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Save to variable so platform driver can get it.\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  TREE_STORAGE_NAME,\r
+                  &gTrEEConfigFormSetGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof(TrEEConfiguration),\r
+                  &TrEEConfiguration\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  //\r
+  // Install TrEE configuration form\r
+  //\r
+  Status = InstallTrEEConfigForm (PrivateData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+  if (PrivateData != NULL) {\r
+    UninstallTrEEConfigForm (PrivateData);\r
+  }  \r
+  \r
+  return Status;\r
+}\r
+\r
+/**\r
+  Unload the TrEE configuration form.\r
+\r
+  @param[in]  ImageHandle         The driver's image handle.\r
+\r
+  @retval     EFI_SUCCESS         The TrEE configuration form is unloaded.\r
+  @retval     Others              Failed to unload the form.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEConfigDriverUnload (\r
+  IN EFI_HANDLE  ImageHandle\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  TREE_CONFIG_PRIVATE_DATA    *PrivateData;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  ImageHandle,\r
+                  &gEfiCallerIdGuid,\r
+                  (VOID **) &PrivateData\r
+                  );  \r
+  if (EFI_ERROR (Status)) {\r
+    return Status;  \r
+  }\r
+  \r
+  ASSERT (PrivateData->Signature == TREE_CONFIG_PRIVATE_DATA_SIGNATURE);\r
+\r
+  gBS->UninstallMultipleProtocolInterfaces (\r
+         &ImageHandle,\r
+         &gEfiCallerIdGuid,\r
+         PrivateData,\r
+         NULL\r
+         );\r
+  \r
+  UninstallTrEEConfigForm (PrivateData);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigDxe.inf b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigDxe.inf
new file mode 100644 (file)
index 0000000..0878fb6
--- /dev/null
@@ -0,0 +1,74 @@
+## @file\r
+#  Component name for TrEE configuration module.\r
+#  NOTE: This module is only for reference only, each platform should have its own setup page.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = TrEEConfigDxe\r
+  FILE_GUID                      = 3141FD4D-EA02-4a70-9BCE-97EE837319AC\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = TrEEConfigDriverEntryPoint\r
+  UNLOAD_IMAGE                   = TrEEConfigDriverUnload\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  TrEEConfigDriver.c\r
+  TrEEConfigImpl.c\r
+  TrEEConfigImpl.h\r
+  TrEEConfig.vfr\r
+  TrEEConfigStrings.uni\r
+  TrEEConfigNvData.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiDriverEntryPoint\r
+  UefiHiiServicesLib\r
+  DebugLib\r
+  HiiLib\r
+  PcdLib\r
+  PrintLib\r
+  Tpm2DeviceLib\r
+  Tpm12DeviceLib\r
+  Tpm2CommandLib\r
+\r
+[Guids]\r
+  gEfiTrEEPhysicalPresenceGuid\r
+  gTrEEConfigFormSetGuid\r
+\r
+[Protocols]\r
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES\r
+  gEfiHiiConfigRoutingProtocolGuid              ## CONSUMES\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
+\r
+[Depex]\r
+  gEfiTrEEProtocolGuid              AND\r
+  gEfiHiiConfigRoutingProtocolGuid  AND\r
+  gEfiHiiDatabaseProtocolGuid       AND\r
+  gEfiVariableArchProtocolGuid      AND\r
+  gEfiVariableWriteArchProtocolGuid
\ No newline at end of file
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigImpl.c b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigImpl.c
new file mode 100644 (file)
index 0000000..41bafa2
--- /dev/null
@@ -0,0 +1,454 @@
+/** @file\r
+  HII Config Access protocol implementation of TREE configuration module.\r
+  NOTE: This module is only for reference only, each platform should have its own setup page.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TrEEConfigImpl.h"\r
+#include <Library/PcdLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Guid/TpmInstance.h>\r
+\r
+TPM_INSTANCE_ID  mTpmInstanceId[TPM_DEVICE_MAX + 1] = TPM_INSTANCE_ID_LIST;\r
+\r
+TREE_CONFIG_PRIVATE_DATA         mTrEEConfigPrivateDateTemplate = {\r
+  TREE_CONFIG_PRIVATE_DATA_SIGNATURE,\r
+  {\r
+    TrEEExtractConfig,\r
+    TrEERouteConfig,\r
+    TrEECallback\r
+  }\r
+};\r
+\r
+HII_VENDOR_DEVICE_PATH          mTrEEHiiVendorDevicePath = {\r
+  {\r
+    {\r
+      HARDWARE_DEVICE_PATH,\r
+      HW_VENDOR_DP,\r
+      {\r
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
+      }\r
+    },\r
+    TREE_CONFIG_FORM_SET_GUID\r
+  },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    { \r
+      (UINT8) (END_DEVICE_PATH_LENGTH),\r
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
+    }\r
+  }\r
+};\r
+\r
+/**\r
+  This function allows a caller to extract the current configuration for one\r
+  or more named elements from the target driver.\r
+\r
+  @param[in]   This              Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]   Request           A null-terminated Unicode string in\r
+                                 <ConfigRequest> format.\r
+  @param[out]  Progress          On return, points to a character in the Request\r
+                                 string. Points to the string's null terminator if\r
+                                 request was successful. Points to the most recent\r
+                                 '&' before the first failing name/value pair (or\r
+                                 the beginning of the string if the failure is in\r
+                                 the first name/value pair) if the request was not\r
+                                 successful.\r
+  @param[out]  Results           A null-terminated Unicode string in\r
+                                 <ConfigAltResp> format which has all values filled\r
+                                 in for the names in the Request string. String to\r
+                                 be allocated by the called function.\r
+\r
+  @retval EFI_SUCCESS            The Results is filled with the requested values.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
+  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEExtractConfig (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL        *This,\r
+  IN CONST EFI_STRING                            Request,\r
+       OUT EFI_STRING                            *Progress,\r
+       OUT EFI_STRING                            *Results\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  UINTN                      BufferSize;\r
+  TREE_CONFIGURATION         Configuration;\r
+  TREE_CONFIG_PRIVATE_DATA   *PrivateData;\r
+  EFI_STRING                 ConfigRequestHdr;\r
+  EFI_STRING                 ConfigRequest;\r
+  BOOLEAN                    AllocatedRequest;\r
+  UINTN                      Size;\r
+  UINTN                      Index;\r
+\r
+  if (Progress == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Progress = Request;\r
+  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTrEEConfigFormSetGuid, TREE_STORAGE_NAME)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  ConfigRequestHdr = NULL;\r
+  ConfigRequest    = NULL;\r
+  AllocatedRequest = FALSE;\r
+  Size             = 0;\r
+\r
+  PrivateData = TREE_CONFIG_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+  //  \r
+  BufferSize = sizeof (Configuration);\r
+  Status = gRT->GetVariable (\r
+                  TREE_STORAGE_NAME,\r
+                  &gTrEEConfigFormSetGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  &Configuration\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get data from PCD to make sure data consistant - platform driver is suppose to construct this PCD accroding to Variable\r
+  //\r
+  for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) {\r
+    if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &mTpmInstanceId[Index].TpmInstanceGuid)) {\r
+      Configuration.TpmDevice = mTpmInstanceId[Index].TpmDevice;\r
+      break;\r
+    }\r
+  }\r
+\r
+  BufferSize = sizeof (Configuration);\r
+  ConfigRequest = Request;\r
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
+    //\r
+    // Request has no request element, construct full request string.\r
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
+    //\r
+    ConfigRequestHdr = HiiConstructConfigHdr (&gTrEEConfigFormSetGuid, TREE_STORAGE_NAME, PrivateData->DriverHandle);\r
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
+    ConfigRequest = AllocateZeroPool (Size);\r
+    ASSERT (ConfigRequest != NULL);\r
+    AllocatedRequest = TRUE;\r
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64) BufferSize);\r
+    FreePool (ConfigRequestHdr);\r
+  }\r
+\r
+  Status = gHiiConfigRouting->BlockToConfig (\r
+                                gHiiConfigRouting,\r
+                                ConfigRequest,\r
+                                (UINT8 *) &Configuration,\r
+                                BufferSize,\r
+                                Results,\r
+                                Progress\r
+                                );\r
+  //\r
+  // Free the allocated config request string.\r
+  //\r
+  if (AllocatedRequest) {\r
+    FreePool (ConfigRequest);\r
+  }\r
+  //\r
+  // Set Progress string to the original request string.\r
+  //\r
+  if (Request == NULL) {\r
+    *Progress = NULL;\r
+  } else if (StrStr (Request, L"OFFSET") == NULL) {\r
+    *Progress = Request + StrLen (Request);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Save TPM request to variable space.\r
+\r
+  @param[in] PpRequest             Physical Presence request command.\r
+\r
+  @retval    EFI_SUCCESS           The operation is finished successfully.\r
+  @retval    Others                Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+SaveTrEEPpRequest (\r
+  IN UINT8                         PpRequest\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            DataSize;\r
+  EFI_TREE_PHYSICAL_PRESENCE       PpData;\r
+\r
+  //\r
+  // Save TPM command to variable.\r
+  //\r
+  DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+  Status = gRT->GetVariable (\r
+                  TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTrEEPhysicalPresenceGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &PpData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }                \r
+                  \r
+  PpData.PPRequest = PpRequest;\r
+  Status = gRT->SetVariable (\r
+                  TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                  &gEfiTrEEPhysicalPresenceGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  DataSize,\r
+                  &PpData\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]  Configuration      A null-terminated Unicode string in <ConfigResp>\r
+                                 format.\r
+  @param[out] Progress           A pointer to a string filled in with the offset of\r
+                                 the most recent '&' before the first failing\r
+                                 name/value pair (or the beginning of the string if\r
+                                 the failure is in the first name/value pair) or\r
+                                 the terminating NULL if all was successful.\r
+\r
+  @retval EFI_SUCCESS            The Results is processed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEERouteConfig (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
+  IN CONST EFI_STRING                          Configuration,\r
+       OUT EFI_STRING                          *Progress\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            BufferSize;\r
+  TREE_CONFIGURATION               TrEEConfiguration;\r
+\r
+  if (Configuration == NULL || Progress == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Progress = Configuration;\r
+  if (!HiiIsConfigHdrMatch (Configuration, &gTrEEConfigFormSetGuid, TREE_STORAGE_NAME)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  BufferSize = sizeof (TrEEConfiguration);\r
+  Status = gRT->GetVariable (\r
+                  TREE_STORAGE_NAME,\r
+                  &gTrEEConfigFormSetGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  &TrEEConfiguration\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
+  //\r
+  BufferSize = sizeof (TREE_CONFIGURATION);\r
+  Status = gHiiConfigRouting->ConfigToBlock (\r
+                                gHiiConfigRouting,\r
+                                Configuration,\r
+                                (UINT8 *) &TrEEConfiguration,\r
+                                &BufferSize,\r
+                                Progress\r
+                                );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Save to variable so platform driver can get it.\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  TREE_STORAGE_NAME,\r
+                  &gTrEEConfigFormSetGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof(TrEEConfiguration),\r
+                  &TrEEConfiguration\r
+                  );\r
+\r
+  SaveTrEEPpRequest (TrEEConfiguration.Tpm2Operation\r
+                     );\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]  Action             Specifies the type of action taken by the browser.\r
+  @param[in]  QuestionId         A unique value which is sent to the original\r
+                                 exporting driver so that it can identify the type\r
+                                 of data to expect.\r
+  @param[in]  Type               The type of value for the question.\r
+  @param[in]  Value              A pointer to the data being sent to the original\r
+                                 exporting driver.\r
+  @param[out] ActionRequest      On return, points to the action requested by the\r
+                                 callback function.\r
+\r
+  @retval EFI_SUCCESS            The callback successfully handled the action.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
+                                 variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
+                                 callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEECallback (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
+  IN     EFI_BROWSER_ACTION                    Action,\r
+  IN     EFI_QUESTION_ID                       QuestionId,\r
+  IN     UINT8                                 Type,\r
+  IN     EFI_IFR_TYPE_VALUE                    *Value,\r
+     OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
+  )\r
+{\r
+  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) ||\r
+      (QuestionId != KEY_TPM_DEVICE)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function publish the TREE configuration Form for TPM device.\r
+\r
+  @param[in, out]  PrivateData   Points to TREE configuration private data.\r
+\r
+  @retval EFI_SUCCESS            HII Form is installed for this network device.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.\r
+  @retval Others                 Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+InstallTrEEConfigForm (\r
+  IN OUT TREE_CONFIG_PRIVATE_DATA  *PrivateData\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+\r
+  DriverHandle = NULL;\r
+  ConfigAccess = &PrivateData->ConfigAccess;\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &DriverHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &mTrEEHiiVendorDevicePath,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  ConfigAccess,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  PrivateData->DriverHandle = DriverHandle;\r
+\r
+  //\r
+  // Publish the HII package list\r
+  //\r
+  HiiHandle = HiiAddPackages (\r
+                &gTrEEConfigFormSetGuid,\r
+                DriverHandle,\r
+                TrEEConfigDxeStrings,\r
+                TrEEConfigBin,\r
+                NULL\r
+                );\r
+  if (HiiHandle == NULL) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           DriverHandle,\r
+           &gEfiDevicePathProtocolGuid,\r
+           &mTrEEHiiVendorDevicePath,\r
+           &gEfiHiiConfigAccessProtocolGuid,\r
+           ConfigAccess,\r
+           NULL\r
+           );  \r
+\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  PrivateData->HiiHandle = HiiHandle;\r
+\r
+  return EFI_SUCCESS;  \r
+}\r
+\r
+/**\r
+  This function removes TREE configuration Form.\r
+\r
+  @param[in, out]  PrivateData   Points to TREE configuration private data.\r
+\r
+**/\r
+VOID\r
+UninstallTrEEConfigForm (\r
+  IN OUT TREE_CONFIG_PRIVATE_DATA    *PrivateData\r
+  )\r
+{\r
+  //\r
+  // Uninstall HII package list\r
+  //\r
+  if (PrivateData->HiiHandle != NULL) {\r
+    HiiRemovePackages (PrivateData->HiiHandle);\r
+    PrivateData->HiiHandle = NULL;\r
+  }\r
+\r
+  //\r
+  // Uninstall HII Config Access Protocol\r
+  //\r
+  if (PrivateData->DriverHandle != NULL) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           PrivateData->DriverHandle,\r
+           &gEfiDevicePathProtocolGuid,\r
+           &mTrEEHiiVendorDevicePath,\r
+           &gEfiHiiConfigAccessProtocolGuid,\r
+           &PrivateData->ConfigAccess,\r
+           NULL\r
+           );\r
+    PrivateData->DriverHandle = NULL;\r
+  }\r
+  \r
+  FreePool (PrivateData);\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigImpl.h b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigImpl.h
new file mode 100644 (file)
index 0000000..0d62c83
--- /dev/null
@@ -0,0 +1,191 @@
+/** @file\r
+  The header file of HII Config Access protocol implementation of TREE\r
+  configuration module.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __TREE_CONFIG_IMPL_H__\r
+#define __TREE_CONFIG_IMPL_H__\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiHiiServicesLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PrintLib.h>\r
+\r
+#include <Guid/MdeModuleHii.h>\r
+\r
+#include "TrEEConfigNvData.h"\r
+\r
+//\r
+// Tool generated IFR binary data and String package data\r
+//\r
+extern UINT8                        TrEEConfigBin[];\r
+extern UINT8                        TrEEConfigDxeStrings[];\r
+\r
+///\r
+/// HII specific Vendor Device Path definition.\r
+///\r
+typedef struct {\r
+  VENDOR_DEVICE_PATH                VendorDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL          End;\r
+} HII_VENDOR_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  UINTN                             Signature;\r
+\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;\r
+  EFI_HII_HANDLE                    HiiHandle;\r
+  EFI_HANDLE                        DriverHandle;  \r
+\r
+} TREE_CONFIG_PRIVATE_DATA;\r
+\r
+extern TREE_CONFIG_PRIVATE_DATA      mTrEEConfigPrivateDateTemplate;\r
+\r
+#define TREE_CONFIG_PRIVATE_DATA_SIGNATURE     SIGNATURE_32 ('T', 'r', 'E', 'D')\r
+#define TREE_CONFIG_PRIVATE_DATA_FROM_THIS(a)  CR (a, TREE_CONFIG_PRIVATE_DATA, ConfigAccess, TREE_CONFIG_PRIVATE_DATA_SIGNATURE)\r
+\r
+\r
+/**\r
+  This function publish the TREE configuration Form for TPM device.\r
+\r
+  @param[in, out]  PrivateData   Points to TREE configuration private data.\r
+\r
+  @retval EFI_SUCCESS            HII Form is installed for this network device.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.\r
+  @retval Others                 Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+InstallTrEEConfigForm (\r
+  IN OUT TREE_CONFIG_PRIVATE_DATA  *PrivateData\r
+  );\r
+\r
+/**\r
+  This function removes TREE configuration Form.\r
+\r
+  @param[in, out]  PrivateData   Points to TREE configuration private data.\r
+\r
+**/\r
+VOID\r
+UninstallTrEEConfigForm (\r
+  IN OUT TREE_CONFIG_PRIVATE_DATA    *PrivateData\r
+  );\r
+\r
+/**\r
+  This function allows a caller to extract the current configuration for one\r
+  or more named elements from the target driver.\r
+\r
+  @param[in]   This              Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]   Request           A null-terminated Unicode string in\r
+                                 <ConfigRequest> format.\r
+  @param[out]  Progress          On return, points to a character in the Request\r
+                                 string. Points to the string's null terminator if\r
+                                 request was successful. Points to the most recent\r
+                                 '&' before the first failing name/value pair (or\r
+                                 the beginning of the string if the failure is in\r
+                                 the first name/value pair) if the request was not\r
+                                 successful.\r
+  @param[out]  Results           A null-terminated Unicode string in\r
+                                 <ConfigAltResp> format which has all values filled\r
+                                 in for the names in the Request string. String to\r
+                                 be allocated by the called function.\r
+\r
+  @retval EFI_SUCCESS            The Results is filled with the requested values.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
+  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEExtractConfig (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL        *This,\r
+  IN CONST EFI_STRING                            Request,\r
+       OUT EFI_STRING                            *Progress,\r
+       OUT EFI_STRING                            *Results\r
+  );\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]  Configuration      A null-terminated Unicode string in <ConfigResp>\r
+                                 format.\r
+  @param[out] Progress           A pointer to a string filled in with the offset of\r
+                                 the most recent '&' before the first failing\r
+                                 name/value pair (or the beginning of the string if\r
+                                 the failure is in the first name/value pair) or\r
+                                 the terminating NULL if all was successful.\r
+\r
+  @retval EFI_SUCCESS            The Results is processed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEERouteConfig (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
+  IN CONST EFI_STRING                          Configuration,\r
+       OUT EFI_STRING                          *Progress\r
+  );\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]  Action             Specifies the type of action taken by the browser.\r
+  @param[in]  QuestionId         A unique value which is sent to the original\r
+                                 exporting driver so that it can identify the type\r
+                                 of data to expect.\r
+  @param[in]  Type               The type of value for the question.\r
+  @param[in]  Value              A pointer to the data being sent to the original\r
+                                 exporting driver.\r
+  @param[out] ActionRequest      On return, points to the action requested by the\r
+                                 callback function.\r
+\r
+  @retval EFI_SUCCESS            The callback successfully handled the action.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
+                                 variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
+                                 callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEECallback (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
+  IN     EFI_BROWSER_ACTION                    Action,\r
+  IN     EFI_QUESTION_ID                       QuestionId,\r
+  IN     UINT8                                 Type,\r
+  IN     EFI_IFR_TYPE_VALUE                    *Value,\r
+     OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
+  );\r
+\r
+#endif\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigNvData.h b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigNvData.h
new file mode 100644 (file)
index 0000000..cb9f5a8
--- /dev/null
@@ -0,0 +1,66 @@
+/** @file\r
+  Header file for NV data structure definition.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __TREE_CONFIG_NV_DATA_H__\r
+#define __TREE_CONFIG_NV_DATA_H__\r
+\r
+#include <Guid/HiiPlatformSetupFormset.h>\r
+#include <Guid/TrEEPhysicalPresenceData.h>\r
+#include <Guid/TrEEConfigHii.h>\r
+\r
+#define TREE_CONFIGURATION_VARSTORE_ID  0x0001\r
+#define TREE_CONFIGURATION_FORM_ID      0x0001\r
+\r
+#define KEY_TPM_DEVICE                                 0x2000\r
+\r
+#define TPM_DEVICE_NULL           0\r
+#define TPM_DEVICE_1_2            1\r
+#define TPM_DEVICE_2_0_DTPM       2\r
+#define TPM_DEVICE_MAX            TPM_DEVICE_2_0_DTPM\r
+#define TPM_DEVICE_DEFAULT        TPM_DEVICE_1_2\r
+\r
+//\r
+// Nv Data structure referenced by IFR\r
+//\r
+typedef struct {\r
+  UINT8   TpmDevice;\r
+  UINT8   Tpm2Operation;\r
+} TREE_CONFIGURATION;\r
+\r
+#define TREE_STORAGE_NAME  L"TREE_CONFIGURATION"\r
+\r
+#define TPM_INSTANCE_ID_LIST  { \\r
+  {TPM_DEVICE_INTERFACE_NONE,           TPM_DEVICE_NULL},      \\r
+  {TPM_DEVICE_INTERFACE_TPM12,          TPM_DEVICE_1_2},       \\r
+  {TPM_DEVICE_INTERFACE_TPM20_DTPM,     TPM_DEVICE_2_0_DTPM},  \\r
+}\r
+\r
+//\r
+// BUGBUG: In order to pass VfrCompiler, we have to redefine GUID here.\r
+//\r
+#ifndef __BASE_H__\r
+typedef struct {\r
+  UINT32  Data1;\r
+  UINT16  Data2;\r
+  UINT16  Data3;\r
+  UINT8   Data4[8];\r
+} GUID;\r
+#endif\r
+\r
+typedef struct {\r
+  GUID       TpmInstanceGuid;\r
+  UINT8      TpmDevice;\r
+} TPM_INSTANCE_ID;\r
+\r
+#endif\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf
new file mode 100644 (file)
index 0000000..c6a489a
--- /dev/null
@@ -0,0 +1,70 @@
+## @file\r
+#  Component name for TrEE configuration module.\r
+#  NOTE: This module is only for reference only, each platform should have its own setup page.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = TrEEConfigPei\r
+  FILE_GUID                      = A5C1EF72-9379-4370-B4C7-0F5126CAC38E\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = TrEEConfigPeimEntryPoint\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  TrEEConfigPeim.c\r
+  TrEEConfigNvData.h\r
+  TpmDetection.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  PeiServicesLib\r
+  PeimEntryPoint\r
+  DebugLib\r
+  PcdLib\r
+  TimerLib\r
+  IoLib\r
+  Tpm12CommandLib\r
+  Tpm12DeviceLib\r
+\r
+[Guids]\r
+  gEfiTrEEPhysicalPresenceGuid\r
+  gTrEEConfigFormSetGuid\r
+  gEfiTpmDeviceSelectedGuid\r
+\r
+[Ppis]\r
+  gEfiPeiReadOnlyVariable2PpiGuid\r
+\r
+[FixedPcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdHideTpm\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmAutoDetection\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress\r
+\r
+[Depex]\r
+  gEfiPeiMasterBootModePpiGuid AND\r
+  gEfiPeiReadOnlyVariable2PpiGuid
\ No newline at end of file
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigPeim.c b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigPeim.c
new file mode 100644 (file)
index 0000000..77d640d
--- /dev/null
@@ -0,0 +1,133 @@
+/** @file\r
+  The module entry point for TrEE configuration module.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Guid/TpmInstance.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Ppi/ReadOnlyVariable2.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include "TrEEConfigNvData.h"\r
+\r
+TPM_INSTANCE_ID  mTpmInstanceId[] = TPM_INSTANCE_ID_LIST;\r
+\r
+CONST EFI_PEI_PPI_DESCRIPTOR gTpmSelectedPpi = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEfiTpmDeviceSelectedGuid,\r
+  NULL\r
+};\r
+\r
+/**\r
+  This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.\r
+\r
+  @param  SetupTpmDevice  TpmDevice configuration in setup driver\r
+\r
+  @return TpmDevice configuration\r
+**/\r
+UINT8\r
+DetectTpmDevice (\r
+  IN UINT8 SetupTpmDevice\r
+  );\r
+\r
+/**\r
+  The entry point for TrEE configuration driver.\r
+\r
+  @param  FileHandle  Handle of the file being invoked.\r
+  @param  PeiServices Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_SUCCES             Convert variable to PCD successfully.\r
+  @retval Others                 Fail to convert variable to PCD.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrEEConfigPeimEntryPoint (\r
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+  UINTN                           Size;\r
+  EFI_STATUS                      Status;\r
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;\r
+  TREE_CONFIGURATION              TrEEConfiguration;\r
+  UINTN                           Index;\r
+  UINT8                           TpmDevice;\r
+\r
+  Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Size = sizeof(TrEEConfiguration);\r
+  Status = VariablePpi->GetVariable (\r
+                          VariablePpi,\r
+                          TREE_STORAGE_NAME,\r
+                          &gTrEEConfigFormSetGuid,\r
+                          NULL,\r
+                          &Size,\r
+                          &TrEEConfiguration\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Variable not ready, set default value\r
+    //\r
+    TrEEConfiguration.TpmDevice           = TPM_DEVICE_DEFAULT;\r
+  }\r
+\r
+  //\r
+  // Validation\r
+  //\r
+  if (TrEEConfiguration.TpmDevice > TPM_DEVICE_MAX) {\r
+    TrEEConfiguration.TpmDevice   = TPM_DEVICE_DEFAULT;\r
+  }\r
+\r
+  //\r
+  // Although we have SetupVariable info, we still need detect TPM device manually.\r
+  //\r
+  DEBUG ((EFI_D_ERROR, "TrEEConfiguration.TpmDevice from Setup: %x\n", TrEEConfiguration.TpmDevice));\r
+\r
+  if (PcdGetBool (PcdTpmAutoDetection)) {\r
+    TpmDevice = DetectTpmDevice (TrEEConfiguration.TpmDevice);\r
+    DEBUG ((EFI_D_ERROR, "TrEEConfiguration.TpmDevice final: %x\n", TpmDevice));\r
+    TrEEConfiguration.TpmDevice = TpmDevice;\r
+  }\r
+\r
+  //\r
+  // Convert variable to PCD.\r
+  // This is work-around because there is no gurantee DynamicHiiPcd can return correct value in DXE phase.\r
+  // Using DynamicPcd instead.\r
+  //\r
+  for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) {\r
+    if (TrEEConfiguration.TpmDevice == mTpmInstanceId[Index].TpmDevice) {\r
+      Size = sizeof(mTpmInstanceId[Index].TpmInstanceGuid);\r
+      PcdSetPtr (PcdTpmInstanceGuid, &Size, &mTpmInstanceId[Index].TpmInstanceGuid);\r
+      DEBUG ((EFI_D_ERROR, "TrEEConfiguration.TpmDevice PCD: %g\n", &mTpmInstanceId[Index].TpmInstanceGuid));\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Selection done\r
+  //\r
+  Status = PeiServicesInstallPpi (&gTpmSelectedPpi);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEEConfig/TrEEConfigStrings.uni b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigStrings.uni
new file mode 100644 (file)
index 0000000..29c02e7
Binary files /dev/null and b/SecurityPkg/Tcg/TrEEConfig/TrEEConfigStrings.uni differ
diff --git a/SecurityPkg/Tcg/TrEEDxe/MeasureBootPeCoff.c b/SecurityPkg/Tcg/TrEEDxe/MeasureBootPeCoff.c
new file mode 100644 (file)
index 0000000..e80e029
--- /dev/null
@@ -0,0 +1,357 @@
+/** @file\r
+  This module implements measuring PeCoff image for TrEE Protocol.\r
+  \r
+  Caution: This file requires additional review when modified.\r
+  This driver will have external input - PE/COFF image.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/HashLib.h>\r
+\r
+/**\r
+  Measure PE image into TPM log based on the authenticode image hashing in\r
+  PE/COFF Specification 8.0 Appendix A.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
+\r
+  @param[in]  PCRIndex       TPM PCR index\r
+  @param[in]  ImageAddress   Start address of image buffer.\r
+  @param[in]  ImageSize      Image size\r
+  @param[out] DigestList     Digeest list of this image.\r
+\r
+  @retval EFI_SUCCESS            Successfully measure image.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.\r
+  @retval other error value\r
+**/\r
+EFI_STATUS\r
+MeasurePeImageAndExtend (\r
+  IN  UINT32                    PCRIndex,\r
+  IN  EFI_PHYSICAL_ADDRESS      ImageAddress,\r
+  IN  UINTN                     ImageSize,\r
+  OUT TPML_DIGEST_VALUES        *DigestList\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  UINT32                               PeCoffHeaderOffset;\r
+  EFI_IMAGE_SECTION_HEADER             *Section;\r
+  UINT8                                *HashBase;\r
+  UINTN                                HashSize;\r
+  UINTN                                SumOfBytesHashed;\r
+  EFI_IMAGE_SECTION_HEADER             *SectionHeader;\r
+  UINTN                                Index;\r
+  UINTN                                Pos;\r
+  UINT16                               Magic;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  UINT32                               NumberOfRvaAndSizes;\r
+  UINT32                               CertSize;\r
+  HASH_HANDLE                          HashHandle;\r
+\r
+  HashHandle = 0xFFFFFFFF; // Know bad value\r
+\r
+  Status        = EFI_UNSUPPORTED;\r
+  SectionHeader = NULL;\r
+\r
+  //\r
+  // Check PE/COFF image\r
+  //\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;\r
+  PeCoffHeaderOffset = 0;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    PeCoffHeaderOffset = DosHdr->e_lfanew;\r
+  }\r
+\r
+  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
+  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Finish;\r
+  }\r
+\r
+  //\r
+  // PE/COFF Image Measurement\r
+  //\r
+  //    NOTE: The following codes/steps are based upon the authenticode image hashing in\r
+  //      PE/COFF Specification 8.0 Appendix A.\r
+  //\r
+  //\r
+\r
+  // 1.  Load the image header into memory.\r
+\r
+  // 2.  Initialize a SHA hash context.\r
+\r
+  Status = HashStart (&HashHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Finish;\r
+  }\r
+\r
+  //\r
+  // Measuring PE/COFF Image Header;\r
+  // But CheckSum field and SECURITY data directory (certificate) are excluded\r
+  //\r
+  if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
+    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+    //\r
+    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+  } else {\r
+    //\r
+    // Get the magic value from the PE/COFF Optional Header\r
+    //\r
+    Magic = Hdr.Pe32->OptionalHeader.Magic;\r
+  }\r
+  \r
+  //\r
+  // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
+  // 4.  Hash the image header from its base to beginning of the image checksum.\r
+  //\r
+  HashBase = (UINT8 *) (UINTN) ImageAddress;\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset\r
+    //\r
+    NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+    HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+  } else {\r
+    //\r
+    // Use PE32+ offset\r
+    //\r
+    NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+    HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+  }\r
+\r
+  Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Finish;\r
+  }  \r
+\r
+  //\r
+  // 5.  Skip over the image checksum (it occupies a single ULONG).\r
+  //\r
+  if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+    //\r
+    // 6.  Since there is no Cert Directory in optional header, hash everything\r
+    //     from the end of the checksum to the end of image header.\r
+    //\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset.\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset.\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+    }\r
+\r
+    if (HashSize != 0) {\r
+      Status  = HashUpdate (HashHandle, HashBase, HashSize);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Finish;\r
+      }\r
+    }    \r
+  } else {\r
+    //\r
+    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
+    //\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset\r
+      //    \r
+      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+    }\r
+\r
+    if (HashSize != 0) {\r
+      Status  = HashUpdate (HashHandle, HashBase, HashSize);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Finish;\r
+      }\r
+    }\r
+\r
+    //\r
+    // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
+    // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
+    //\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+    }\r
+    \r
+    if (HashSize != 0) {\r
+      Status  = HashUpdate (HashHandle, HashBase, HashSize);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Finish;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header\r
+  //\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset\r
+    //\r
+    SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
+  } else {\r
+    //\r
+    // Use PE32+ offset\r
+    //\r
+    SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
+  }\r
+\r
+  //\r
+  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
+  //     structures in the image. The 'NumberOfSections' field of the image\r
+  //     header indicates how big the table should be. Do not include any\r
+  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);\r
+  if (SectionHeader == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Finish;\r
+  }\r
+\r
+  //\r
+  // 12.  Using the 'PointerToRawData' in the referenced section headers as\r
+  //      a key, arrange the elements in the table in ascending order. In other\r
+  //      words, sort the section headers according to the disk-file offset of\r
+  //      the section.\r
+  //\r
+  Section = (EFI_IMAGE_SECTION_HEADER *) (\r
+               (UINT8 *) (UINTN) ImageAddress +\r
+               PeCoffHeaderOffset +\r
+               sizeof(UINT32) +\r
+               sizeof(EFI_IMAGE_FILE_HEADER) +\r
+               Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
+               );\r
+  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
+    Pos = Index;\r
+    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
+      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof(EFI_IMAGE_SECTION_HEADER));\r
+      Pos--;\r
+    }\r
+    CopyMem (&SectionHeader[Pos], Section, sizeof(EFI_IMAGE_SECTION_HEADER));\r
+    Section += 1;\r
+  }\r
+\r
+  //\r
+  // 13.  Walk through the sorted table, bring the corresponding section\r
+  //      into memory, and hash the entire section (using the 'SizeOfRawData'\r
+  //      field in the section header to determine the amount of data to hash).\r
+  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
+  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.\r
+  //\r
+  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
+    Section  = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index];\r
+    if (Section->SizeOfRawData == 0) {\r
+      continue;\r
+    }\r
+    HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData;\r
+    HashSize = (UINTN) Section->SizeOfRawData;\r
+\r
+    Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Finish;\r
+    }\r
+\r
+    SumOfBytesHashed += HashSize;\r
+  }\r
+\r
+  //\r
+  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
+  //      data in the file that needs to be added to the hash. This data begins\r
+  //      at file offset SUM_OF_BYTES_HASHED and its length is:\r
+  //             FileSize  -  (CertDirectory->Size)\r
+  //\r
+  if (ImageSize > SumOfBytesHashed) {\r
+    HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed;\r
+\r
+    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      CertSize = 0;\r
+    } else {\r
+      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+        //\r
+        // Use PE32 offset.\r
+        //\r
+        CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+      } else {\r
+        //\r
+        // Use PE32+ offset.\r
+        //\r
+        CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+      }\r
+    }\r
+\r
+    if (ImageSize > CertSize + SumOfBytesHashed) {\r
+      HashSize = (UINTN) (ImageSize - CertSize - SumOfBytesHashed);\r
+\r
+      Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Finish;\r
+      }\r
+    } else if (ImageSize < CertSize + SumOfBytesHashed) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Finish;\r
+    }\r
+  }\r
+\r
+  //\r
+  // 17.  Finalize the SHA hash.\r
+  //\r
+  Status = HashCompleteAndExtend (HashHandle, PCRIndex, NULL, 0, DigestList);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Finish;\r
+  }\r
+\r
+Finish:\r
+  if (SectionHeader != NULL) {\r
+    FreePool (SectionHeader);\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c b/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c
new file mode 100644 (file)
index 0000000..9451b55
--- /dev/null
@@ -0,0 +1,1977 @@
+/** @file\r
+  This module implements TrEE Protocol.\r
+  \r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <IndustryStandard/SmBios.h>\r
+#include <IndustryStandard/TcpaAcpi.h>\r
+\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/SmBios.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/TcgEventHob.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/EventExitBootServiceFailed.h>\r
+#include <Guid/ImageAuthentication.h>\r
+#include <Guid/TpmInstance.h>\r
+\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/AcpiTable.h>\r
+#include <Protocol/MpService.h>\r
+#include <Protocol/VariableWrite.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Library/PerformanceLib.h>\r
+\r
+#define PERF_ID_TREE_DXE  0x3120\r
+\r
+typedef struct {\r
+  CHAR16                                 *VariableName;\r
+  EFI_GUID                               *VendorGuid;\r
+} VARIABLE_TYPE;\r
+\r
+#define  EFI_TCG_LOG_AREA_SIZE        0x10000\r
+\r
+#define  TREE_DEFAULT_MAX_COMMAND_SIZE        0x1000\r
+#define  TREE_DEFAULT_MAX_RESPONSE_SIZE       0x1000\r
+\r
+typedef struct {\r
+  EFI_GUID               *EventGuid;\r
+  TREE_EVENT_LOG_FORMAT  LogFormat;\r
+  UINT32                 BootHashAlg;\r
+  UINT16                 DigestAlgID;\r
+  TPMI_ALG_HASH          TpmHashAlgo;\r
+} TREE_EVENT_INFO_STRUCT;\r
+\r
+TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {\r
+  {&gTcgEventEntryHobGuid,             TREE_EVENT_LOG_FORMAT_TCG_1_2,      TREE_BOOT_HASH_ALG_SHA1,     0,                       TPM_ALG_SHA1},\r
+};\r
+\r
+#define TCG_EVENT_LOG_AREA_COUNT_MAX   5\r
+\r
+typedef struct {\r
+  TREE_EVENT_LOG_FORMAT             EventLogFormat;\r
+  EFI_PHYSICAL_ADDRESS              Lasa;\r
+  UINT64                            Laml;\r
+  UINTN                             EventLogSize;\r
+  UINT8                             *LastEvent;\r
+  BOOLEAN                           EventLogStarted;\r
+  BOOLEAN                           EventLogTruncated;\r
+} TCG_EVENT_LOG_AREA_STRUCT;\r
+\r
+typedef struct _TCG_DXE_DATA {\r
+  TREE_BOOT_SERVICE_CAPABILITY      BsCap;\r
+  EFI_TCG_CLIENT_ACPI_TABLE         *TcgClientAcpiTable;\r
+  EFI_TCG_SERVER_ACPI_TABLE         *TcgServerAcpiTable;\r
+  TCG_EVENT_LOG_AREA_STRUCT         EventLogAreaStruct[TCG_EVENT_LOG_AREA_COUNT_MAX];\r
+} TCG_DXE_DATA;\r
+\r
+EFI_TCG_CLIENT_ACPI_TABLE           mTcgClientAcpiTemplate = {\r
+  {\r
+    EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
+    sizeof (mTcgClientAcpiTemplate),\r
+    0x02                      //Revision\r
+    //\r
+    // Compiler initializes the remaining bytes to 0\r
+    // These fields should be filled in in production\r
+    //\r
+  },\r
+  0,                          // 0 for PC Client Platform Class\r
+  0,                          // Log Area Max Length\r
+  (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1)  // Log Area Start Address\r
+};\r
+\r
+//\r
+// The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,\r
+// the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,\r
+// this _UID can be changed and should match with the _UID setting of the TPM \r
+// ACPI device object  \r
+//\r
+EFI_TCG_SERVER_ACPI_TABLE           mTcgServerAcpiTemplate = {\r
+  {\r
+    EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
+    sizeof (mTcgServerAcpiTemplate),\r
+    0x02                      //Revision\r
+    //\r
+    // Compiler initializes the remaining bytes to 0\r
+    // These fields should be filled in in production\r
+    //\r
+  },\r
+  1,                          // 1 for Server Platform Class\r
+  0,                          // Reserved\r
+  0,                          // Log Area Max Length\r
+  (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address\r
+  0x0100,                     // TCG Specification revision 1.0\r
+  2,                          // Device Flags\r
+  0,                          // Interrupt Flags\r
+  0,                          // GPE\r
+  {0},                        // Reserved 3 bytes\r
+  0,                          // Global System Interrupt\r
+  {\r
+    EFI_ACPI_3_0_SYSTEM_MEMORY,\r
+    0,\r
+    0,\r
+    EFI_ACPI_3_0_BYTE,\r
+    0x0          // Base Address\r
+  },\r
+  0,                          // Reserved\r
+  {0},                        // Configuration Address\r
+  0xFF,                       // ACPI _UID value of the device, can be changed for different platforms\r
+  0,                          // ACPI _UID value of the device, can be changed for different platforms\r
+  0,                          // ACPI _UID value of the device, can be changed for different platforms\r
+  0                           // ACPI _UID value of the device, can be changed for different platforms\r
+};\r
+\r
+TCG_DXE_DATA                 mTcgDxeData = {\r
+  {\r
+    sizeof (TREE_BOOT_SERVICE_CAPABILITY_1_0),     // Size\r
+    { 1, 0 },                       // StructureVersion\r
+    { 1, 0 },                       // ProtocolVersion\r
+    TREE_BOOT_HASH_ALG_SHA1,        // HashAlgorithmBitmap\r
+    TREE_EVENT_LOG_FORMAT_TCG_1_2,  // SupportedEventLogs\r
+    TRUE,                           // TrEEPresentFlag\r
+    TREE_DEFAULT_MAX_COMMAND_SIZE,  // MaxCommandSize\r
+    TREE_DEFAULT_MAX_RESPONSE_SIZE, // MaxResponseSize\r
+    0                               // ManufacturerID\r
+  },\r
+  &mTcgClientAcpiTemplate,\r
+  &mTcgServerAcpiTemplate,\r
+};\r
+\r
+UINTN  mBootAttempts  = 0;\r
+CHAR16 mBootVarName[] = L"BootOrder";\r
+\r
+VARIABLE_TYPE  mVariableType[] = {\r
+  {EFI_SECURE_BOOT_MODE_NAME,    &gEfiGlobalVariableGuid},\r
+  {EFI_PLATFORM_KEY_NAME,        &gEfiGlobalVariableGuid},\r
+  {EFI_KEY_EXCHANGE_KEY_NAME,    &gEfiGlobalVariableGuid},\r
+  {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},\r
+  {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},\r
+};\r
+\r
+EFI_HANDLE mImageHandle;\r
+\r
+/**\r
+  Measure PE image into TPM log based on the authenticode image hashing in\r
+  PE/COFF Specification 8.0 Appendix A.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
+\r
+  @param[in]  PCRIndex       TPM PCR index\r
+  @param[in]  ImageAddress   Start address of image buffer.\r
+  @param[in]  ImageSize      Image size\r
+  @param[out] DigestList     Digeest list of this image.\r
+\r
+  @retval EFI_SUCCESS            Successfully measure image.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.\r
+  @retval other error value\r
+**/\r
+EFI_STATUS\r
+MeasurePeImageAndExtend (\r
+  IN  UINT32                    PCRIndex,\r
+  IN  EFI_PHYSICAL_ADDRESS      ImageAddress,\r
+  IN  UINTN                     ImageSize,\r
+  OUT TPML_DIGEST_VALUES        *DigestList\r
+  );\r
+\r
+/**\r
+\r
+  This function dump raw data.\r
+\r
+  @param  Data  raw data\r
+  @param  Size  raw data size\r
+\r
+**/\r
+VOID\r
+InternalDumpData (\r
+  IN UINT8  *Data,\r
+  IN UINTN  Size\r
+  )\r
+{\r
+  UINTN  Index;\r
+  for (Index = 0; Index < Size; Index++) {\r
+    DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index]));\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  This function dump raw data with colume format.\r
+\r
+  @param  Data  raw data\r
+  @param  Size  raw data size\r
+\r
+**/\r
+VOID\r
+InternalDumpHex (\r
+  IN UINT8  *Data,\r
+  IN UINTN  Size\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINTN   Count;\r
+  UINTN   Left;\r
+\r
+#define COLUME_SIZE  (16 * 2)\r
+\r
+  Count = Size / COLUME_SIZE;\r
+  Left  = Size % COLUME_SIZE;\r
+  for (Index = 0; Index < Count; Index++) {\r
+    DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));\r
+    InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  }\r
+\r
+  if (Left != 0) {\r
+    DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));\r
+    InternalDumpData (Data + Index * COLUME_SIZE, Left);\r
+    DEBUG ((EFI_D_INFO, "\n"));\r
+  }\r
+}\r
+\r
+/**\r
+  Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function\r
+  Caller is responsible to free LocationBuf.\r
+\r
+  @param[out] LocationBuf          Returns Processor Location Buffer.\r
+  @param[out] Num                  Returns processor number.\r
+\r
+  @retval EFI_SUCCESS              Operation completed successfully.\r
+  @retval EFI_UNSUPPORTED       MpService protocol not found.\r
+\r
+**/\r
+EFI_STATUS\r
+GetProcessorsCpuLocation (\r
+    OUT  EFI_CPU_PHYSICAL_LOCATION   **LocationBuf,\r
+    OUT  UINTN                       *Num\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_MP_SERVICES_PROTOCOL          *MpProtocol;\r
+  UINTN                             ProcessorNum;\r
+  UINTN                             EnabledProcessorNum;\r
+  EFI_PROCESSOR_INFORMATION         ProcessorInfo;\r
+  EFI_CPU_PHYSICAL_LOCATION         *ProcessorLocBuf;\r
+  UINTN                             Index;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // MP protocol is not installed\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = MpProtocol->GetNumberOfProcessors(\r
+                         MpProtocol,\r
+                         &ProcessorNum,\r
+                         &EnabledProcessorNum\r
+                         );\r
+  if (EFI_ERROR(Status)){\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->AllocatePool(\r
+                  EfiBootServicesData,\r
+                  sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
+                  (VOID **) &ProcessorLocBuf\r
+                  );\r
+  if (EFI_ERROR(Status)){\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get each processor Location info\r
+  //\r
+  for (Index = 0; Index < ProcessorNum; Index++) {\r
+    Status = MpProtocol->GetProcessorInfo(\r
+                           MpProtocol,\r
+                           Index,\r
+                           &ProcessorInfo\r
+                           );\r
+    if (EFI_ERROR(Status)){\r
+      FreePool(ProcessorLocBuf);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Get all Processor Location info & measure\r
+    //\r
+    CopyMem(\r
+      &ProcessorLocBuf[Index],\r
+      &ProcessorInfo.Location,\r
+      sizeof(EFI_CPU_PHYSICAL_LOCATION)\r
+      );\r
+  }\r
+\r
+  *LocationBuf = ProcessorLocBuf;\r
+  *Num = ProcessorNum;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The EFI_TREE_PROTOCOL GetCapability function call provides protocol\r
+  capability information and state information about the TrEE.\r
+\r
+  @param[in]      This               Indicates the calling context\r
+  @param[in, out] ProtocolCapability The caller allocates memory for a TREE_BOOT_SERVICE_CAPABILITY\r
+                                     structure and sets the size field to the size of the structure allocated.\r
+                                     The callee fills in the fields with the EFI protocol capability information\r
+                                     and the current TrEE state information up to the number of fields which\r
+                                     fit within the size of the structure passed in.\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+                                 The ProtocolCapability variable will not be populated. \r
+  @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect.\r
+                                 The ProtocolCapability variable will not be populated.\r
+  @retval EFI_BUFFER_TOO_SMALL   The ProtocolCapability variable is too small to hold the full response.\r
+                                 It will be partially populated (required Size field will be set). \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeGetCapability (\r
+  IN EFI_TREE_PROTOCOL                *This,\r
+  IN OUT TREE_BOOT_SERVICE_CAPABILITY *ProtocolCapability\r
+  )\r
+{\r
+  DEBUG ((EFI_D_ERROR, "TreeGetCapability ...\n"));\r
+\r
+  if ((This == NULL) || (ProtocolCapability == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (ProtocolCapability->Size < mTcgDxeData.BsCap.Size) {\r
+    ProtocolCapability->Size = mTcgDxeData.BsCap.Size;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, mTcgDxeData.BsCap.Size);\r
+  DEBUG ((EFI_D_ERROR, "TreeGetCapability - %r\n", EFI_SUCCESS));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function dump event log.\r
+\r
+  @param[in]  EventLogFormat     The type of the event log for which the information is requested.\r
+  @param[in]  EventLogLocation   A pointer to the memory address of the event log.\r
+  @param[in]  EventLogLastEntry  If the Event Log contains more than one entry, this is a pointer to the\r
+                                 address of the start of the last entry in the event log in memory.\r
+**/\r
+VOID\r
+DumpEventLog (\r
+  IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
+  IN EFI_PHYSICAL_ADDRESS  EventLogLocation,\r
+  IN EFI_PHYSICAL_ADDRESS  EventLogLastEntry\r
+  )\r
+{\r
+  TCG_PCR_EVENT_HDR         *EventHdr;\r
+  UINTN                     Index;\r
+\r
+  DEBUG ((EFI_D_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));\r
+  \r
+  switch (EventLogFormat) {\r
+  case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
+    EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;\r
+    while ((UINTN)EventHdr <= EventLogLastEntry) {\r
+      DEBUG ((EFI_D_INFO, "  Event:\n"));\r
+      DEBUG ((EFI_D_INFO, "    PCRIndex  - %d\n", EventHdr->PCRIndex));\r
+      DEBUG ((EFI_D_INFO, "    EventType - 0x%08x\n", EventHdr->EventType));\r
+      DEBUG ((EFI_D_INFO, "    Digest    - "));\r
+      for (Index = 0; Index < sizeof(TCG_DIGEST); Index++) {\r
+        DEBUG ((EFI_D_INFO, "%02x ", EventHdr->Digest.digest[Index]));\r
+      }\r
+      DEBUG ((EFI_D_INFO, "\n"));\r
+      DEBUG ((EFI_D_INFO, "    EventSize - 0x%08x\n", EventHdr->EventSize));\r
+      InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);\r
+      EventHdr = (TCG_PCR_EVENT_HDR *)((UINTN)EventHdr + sizeof(TCG_PCR_EVENT_HDR) + EventHdr->EventSize);\r
+    }\r
+    break;\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  The EFI_TREE_PROTOCOL Get Event Log function call allows a caller to\r
+  retrieve the address of a given event log and its last entry. \r
+\r
+  @param[in]  This               Indicates the calling context\r
+  @param[in]  EventLogFormat     The type of the event log for which the information is requested.\r
+  @param[out] EventLogLocation   A pointer to the memory address of the event log.\r
+  @param[out] EventLogLastEntry  If the Event Log contains more than one entry, this is a pointer to the\r
+                                 address of the start of the last entry in the event log in memory.\r
+  @param[out] EventLogTruncated  If the Event Log is missing at least one entry because an event would\r
+                                 have exceeded the area allocated for events, this value is set to TRUE.\r
+                                 Otherwise, the value will be FALSE and the Event Log will be complete.\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect\r
+                                 (e.g. asking for an event log whose format is not supported).\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeGetEventLog (\r
+  IN EFI_TREE_PROTOCOL     *This,\r
+  IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
+  OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,\r
+  OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry,\r
+  OUT BOOLEAN              *EventLogTruncated\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  DEBUG ((EFI_D_ERROR, "TreeGetEventLog ...\n"));\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+    if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+    if (EventLogLocation != NULL) {\r
+      *EventLogLocation = 0;\r
+    }\r
+    if (EventLogLastEntry != NULL) {\r
+      *EventLogLastEntry = 0;\r
+    }\r
+    if (EventLogTruncated != NULL) {\r
+      *EventLogTruncated = FALSE;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EventLogLocation != NULL) {\r
+    *EventLogLocation = mTcgDxeData.EventLogAreaStruct[Index].Lasa;\r
+    DEBUG ((EFI_D_ERROR, "TreeGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));\r
+  }\r
+\r
+  if (EventLogLastEntry != NULL) {\r
+    if (!mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted) {\r
+      *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
+    } else {\r
+      *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].LastEvent;\r
+    }\r
+    DEBUG ((EFI_D_ERROR, "TreeGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));\r
+  }\r
+\r
+  if (EventLogTruncated != NULL) {\r
+    *EventLogTruncated = mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated;\r
+    DEBUG ((EFI_D_ERROR, "TreeGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "TreeGetEventLog - %r\n", EFI_SUCCESS));\r
+\r
+  // Dump Event Log for debug purpose\r
+  if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {\r
+    DumpEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Add a new entry to the Event Log.\r
+\r
+  @param[in, out] EventLogPtr     Pointer to the Event Log data.  \r
+  @param[in, out] LogSize         Size of the Event Log.  \r
+  @param[in]      MaxSize         Maximum size of the Event Log.\r
+  @param[in]      NewEventHdr     Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.  \r
+  @param[in]      NewEventHdrSize New event header size.\r
+  @param[in]      NewEventData    Pointer to the new event data.  \r
+  @param[in]      NewEventSize    New event data size.\r
+  \r
+  @retval EFI_SUCCESS           The new event log entry was added.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgCommLogEvent (\r
+  IN OUT  UINT8                     **EventLogPtr,\r
+  IN OUT  UINTN                     *LogSize,\r
+  IN      UINTN                     MaxSize,\r
+  IN      VOID                      *NewEventHdr,\r
+  IN      UINT32                    NewEventHdrSize,\r
+  IN      UINT8                     *NewEventData,\r
+  IN      UINT32                    NewEventSize\r
+  )\r
+{\r
+  UINTN                            NewLogSize;\r
+\r
+  if (NewEventSize > MAX_ADDRESS -  NewEventHdrSize) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewLogSize = NewEventHdrSize + NewEventSize;\r
+\r
+  if (NewLogSize > MAX_ADDRESS -  *LogSize) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (NewLogSize + *LogSize > MaxSize) {\r
+    DEBUG ((EFI_D_INFO, "  MaxSize    - 0x%x\n", MaxSize));\r
+    DEBUG ((EFI_D_INFO, "  NewLogSize - 0x%x\n", NewLogSize));\r
+    DEBUG ((EFI_D_INFO, "  LogSize    - 0x%x\n", *LogSize));\r
+    DEBUG ((EFI_D_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  *EventLogPtr += *LogSize;\r
+  *LogSize += NewLogSize;\r
+  CopyMem (*EventLogPtr, NewEventHdr, NewEventHdrSize);\r
+  CopyMem (\r
+    *EventLogPtr + NewEventHdrSize,\r
+    NewEventData,\r
+    NewEventSize\r
+    );\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Add a new entry to the Event Log.\r
+\r
+  @param[in] EventLogFormat  The type of the event log for which the information is requested.\r
+  @param[in] NewEventHdr     Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.  \r
+  @param[in] NewEventHdrSize New event header size.\r
+  @param[in] NewEventData    Pointer to the new event data.  \r
+  @param[in] NewEventSize    New event data size.\r
+\r
+  @retval EFI_SUCCESS           The new event log entry was added.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgDxeLogEvent (\r
+  IN      TREE_EVENT_LOG_FORMAT     EventLogFormat,\r
+  IN      VOID                      *NewEventHdr,\r
+  IN      UINT32                    NewEventHdrSize,\r
+  IN      UINT8                     *NewEventData,\r
+  IN      UINT32                    NewEventSize\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+  UINTN        Index;\r
+\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+    if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated) {\r
+    return EFI_VOLUME_FULL;\r
+  }\r
+\r
+  mTcgDxeData.EventLogAreaStruct[Index].LastEvent = (UINT8*)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].Lasa;\r
+  Status = TcgCommLogEvent (\r
+             &mTcgDxeData.EventLogAreaStruct[Index].LastEvent,\r
+             &mTcgDxeData.EventLogAreaStruct[Index].EventLogSize,\r
+             (UINTN)mTcgDxeData.EventLogAreaStruct[Index].Laml,\r
+             NewEventHdr,\r
+             NewEventHdrSize,\r
+             NewEventData,\r
+             NewEventSize\r
+             );\r
+  \r
+  if (Status == EFI_DEVICE_ERROR) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else if (Status == EFI_OUT_OF_RESOURCES) {\r
+    mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated = TRUE;\r
+    return EFI_VOLUME_FULL;\r
+  } else if (Status == EFI_SUCCESS) {\r
+    mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted = TRUE;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function return hash algorithm from event log format.\r
+\r
+  @param[in]     EventLogFormat    Event log format.\r
+\r
+  @return hash algorithm.\r
+**/\r
+TPMI_ALG_HASH\r
+TrEEGetHashAlgoFromLogFormat (\r
+  IN      TREE_EVENT_LOG_FORMAT     EventLogFormat\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+    if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {\r
+      return mTreeEventInfo[Index].TpmHashAlgo;\r
+    }\r
+  }\r
+  return TPM_ALG_SHA1;\r
+}\r
+\r
+/**\r
+  This function return hash algorithm ID from event log format.\r
+\r
+  @param[in]     EventLogFormat    Event log format.\r
+\r
+  @return hash algorithm ID.\r
+**/\r
+UINT16\r
+TrEEGetAlgIDFromLogFormat (\r
+  IN      TREE_EVENT_LOG_FORMAT     EventLogFormat\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+    if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {\r
+      return mTreeEventInfo[Index].DigestAlgID;\r
+    }\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+  This function return boot hash algorithm from event log format.\r
+\r
+  @param[in]     EventLogFormat    Event log format.\r
+\r
+  @return boot hash algorithm.\r
+**/\r
+UINT32\r
+TrEEGetBootHashAlgFromLogFormat (\r
+  IN      TREE_EVENT_LOG_FORMAT     EventLogFormat\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+    if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {\r
+      return mTreeEventInfo[Index].BootHashAlg;\r
+    }\r
+  }\r
+  return TREE_BOOT_HASH_ALG_SHA1;\r
+}\r
+\r
+/**\r
+  This function get digest from digest list.\r
+\r
+  @param HashAlg    digest algorithm\r
+  @param DigestList digest list\r
+  @param Digest     digest\r
+\r
+  @retval EFI_SUCCESS   Sha1Digest is found and returned.\r
+  @retval EFI_NOT_FOUND Sha1Digest is not found.\r
+**/\r
+EFI_STATUS\r
+Tpm2GetDigestFromDigestList (\r
+  IN TPMI_ALG_HASH      HashAlg,\r
+  IN TPML_DIGEST_VALUES *DigestList,\r
+  IN VOID               *Digest\r
+  )\r
+{\r
+  UINTN  Index;\r
+  UINT16 DigestSize;\r
+\r
+  DigestSize = GetHashSizeFromAlgo (HashAlg);\r
+  for (Index = 0; Index < DigestList->count; Index++) {\r
+    if (DigestList->digests[Index].hashAlg == HashAlg) {\r
+      CopyMem (\r
+        Digest,\r
+        &DigestList->digests[Index].digest,\r
+        DigestSize\r
+        );\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Add a new entry to the Event Log.\r
+\r
+  @param[in]     DigestList    A list of digest.\r
+  @param[in,out] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.\r
+  @param[in]     NewEventData  Pointer to the new event data.\r
+\r
+  @retval EFI_SUCCESS           The new event log entry was added.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+**/\r
+EFI_STATUS\r
+TcgDxeLogHashEvent (\r
+  IN TPML_DIGEST_VALUES             *DigestList,\r
+  IN OUT  TCG_PCR_EVENT_HDR         *NewEventHdr,\r
+  IN      UINT8                     *NewEventData\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_TPL                           OldTpl;\r
+  UINTN                             Index;\r
+  EFI_STATUS                        RetStatus;\r
+\r
+  RetStatus = EFI_SUCCESS;\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+      DEBUG ((EFI_D_INFO, "  LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));\r
+      switch (mTreeEventInfo[Index].LogFormat) {\r
+      case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
+        Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
+        if (!EFI_ERROR (Status)) {\r
+          //\r
+          // Enter critical region\r
+          //\r
+          OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+          Status = TcgDxeLogEvent (\r
+                     mTreeEventInfo[Index].LogFormat,\r
+                     NewEventHdr,\r
+                     sizeof(TCG_PCR_EVENT_HDR),\r
+                     NewEventData,\r
+                     NewEventHdr->EventSize\r
+                     );\r
+          if (Status != EFI_SUCCESS) {\r
+            RetStatus = Status;\r
+          }\r
+          gBS->RestoreTPL (OldTpl);\r
+          //\r
+          // Exit critical region\r
+          //\r
+        }\r
+        break;\r
+      }\r
+  }\r
+\r
+  return RetStatus;\r
+}\r
+\r
+/**\r
+  Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
+  and add an entry to the Event Log.\r
+\r
+  @param[in]      Flags         Bitmap providing additional information.\r
+  @param[in]      HashData      Physical address of the start of the data buffer \r
+                                to be hashed, extended, and logged.\r
+  @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData\r
+  @param[in, out] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.  \r
+  @param[in]      NewEventData  Pointer to the new event data.  \r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+  @retval EFI_DEVICE_ERROR      The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgDxeHashLogExtendEvent (\r
+  IN      UINT64                    Flags,\r
+  IN      UINT8                     *HashData,\r
+  IN      UINT64                    HashDataLen,\r
+  IN OUT  TCG_PCR_EVENT_HDR         *NewEventHdr,\r
+  IN      UINT8                     *NewEventData\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPML_DIGEST_VALUES                DigestList;\r
+\r
+  Status = HashAndExtend (\r
+             NewEventHdr->PCRIndex,\r
+             HashData,\r
+             (UINTN)HashDataLen,\r
+             &DigestList\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
+      Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The EFI_TREE_PROTOCOL HashLogExtendEvent function call provides callers with\r
+  an opportunity to extend and optionally log events without requiring\r
+  knowledge of actual TPM commands. \r
+  The extend operation will occur even if this function cannot create an event\r
+  log entry (e.g. due to the event log being full). \r
+\r
+  @param[in]  This               Indicates the calling context\r
+  @param[in]  Flags              Bitmap providing additional information.\r
+  @param[in]  DataToHash         Physical address of the start of the data buffer to be hashed. \r
+  @param[in]  DataToHashLen      The length in bytes of the buffer referenced by DataToHash.\r
+  @param[in]  Event              Pointer to data buffer containing information about the event.\r
+\r
+  @retval EFI_SUCCESS            Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR       The command was unsuccessful.\r
+  @retval EFI_VOLUME_FULL        The extend operation occurred, but the event could not be written to one or more event logs.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect.\r
+  @retval EFI_UNSUPPORTED        The PE/COFF image type is not supported.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeHashLogExtendEvent (\r
+  IN EFI_TREE_PROTOCOL    *This,\r
+  IN UINT64               Flags,\r
+  IN EFI_PHYSICAL_ADDRESS DataToHash,\r
+  IN UINT64               DataToHashLen,\r
+  IN TrEE_EVENT           *Event\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  TCG_PCR_EVENT_HDR  NewEventHdr;\r
+  TPML_DIGEST_VALUES DigestList;\r
+\r
+  DEBUG ((EFI_D_ERROR, "TreeHashLogExtendEvent ...\n"));\r
+\r
+  if ((This == NULL) || (DataToHash == 0) || (Event == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (Event->Size < Event->Header.HeaderSize + sizeof(UINT32)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Event->Header.PCRIndex > MAX_PCR_INDEX) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  NewEventHdr.PCRIndex  = Event->Header.PCRIndex;\r
+  NewEventHdr.EventType = Event->Header.EventType;\r
+  NewEventHdr.EventSize = Event->Size - sizeof(UINT32) - Event->Header.HeaderSize;\r
+  if ((Flags & PE_COFF_IMAGE) != 0) {\r
+    Status = MeasurePeImageAndExtend (\r
+               NewEventHdr.PCRIndex,\r
+               DataToHash,\r
+               (UINTN)DataToHashLen,\r
+               &DigestList\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
+        Status = TcgDxeLogHashEvent (&DigestList, &NewEventHdr, Event->Event);\r
+      }\r
+    }\r
+  } else {\r
+    Status = TcgDxeHashLogExtendEvent (\r
+               Flags,\r
+               (UINT8 *) (UINTN) DataToHash,\r
+               DataToHashLen,\r
+               &NewEventHdr,\r
+               Event->Event\r
+               );\r
+  }\r
+  DEBUG ((EFI_D_ERROR, "TreeHashLogExtendEvent - %r\n", Status));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This service enables the sending of commands to the TrEE.\r
+\r
+  @param[in]  This                     Indicates the calling context\r
+  @param[in]  InputParameterBlockSize  Size of the TrEE input parameter block.\r
+  @param[in]  InputParameterBlock      Pointer to the TrEE input parameter block.\r
+  @param[in]  OutputParameterBlockSize Size of the TrEE output parameter block.\r
+  @param[in]  OutputParameterBlock     Pointer to the TrEE output parameter block.\r
+\r
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect.\r
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeSubmitCommand (\r
+  IN EFI_TREE_PROTOCOL *This,\r
+  IN UINT32            InputParameterBlockSize,\r
+  IN UINT8             *InputParameterBlock,\r
+  IN UINT32            OutputParameterBlockSize,\r
+  IN UINT8             *OutputParameterBlock\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  DEBUG ((EFI_D_ERROR, "TreeSubmitCommand ...\n"));\r
+\r
+  if ((This == NULL) ||\r
+      (InputParameterBlockSize == 0) || (InputParameterBlock == NULL) ||\r
+      (OutputParameterBlockSize == 0) || (OutputParameterBlock == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (InputParameterBlockSize >= mTcgDxeData.BsCap.MaxCommandSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (OutputParameterBlockSize >= mTcgDxeData.BsCap.MaxResponseSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = Tpm2SubmitCommand (\r
+             InputParameterBlockSize,\r
+             InputParameterBlock,\r
+             &OutputParameterBlockSize,\r
+             OutputParameterBlock\r
+             );\r
+  DEBUG ((EFI_D_ERROR, "TreeSubmitCommand - %r\n", Status));\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_TREE_PROTOCOL mTreeProtocol = {\r
+    TreeGetCapability,\r
+    TreeGetEventLog,\r
+    TreeHashLogExtendEvent,\r
+    TreeSubmitCommand\r
+};\r
+\r
+/**\r
+  Initialize the Event Log and log events passed from the PEI phase.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+SetupEventLog (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  VOID                    *TcgEvent;\r
+  EFI_PEI_HOB_POINTERS    GuidHob;\r
+  EFI_PHYSICAL_ADDRESS    Lasa;\r
+  UINTN                   Index;\r
+\r
+  DEBUG ((EFI_D_INFO, "SetupEventLog\n"));\r
+\r
+  //\r
+  // 1. Create Log Area\r
+  //\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+      mTcgDxeData.EventLogAreaStruct[Index].EventLogFormat = mTreeEventInfo[Index].LogFormat;\r
+      Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
+      Status = gBS->AllocatePages (\r
+                      AllocateMaxAddress,\r
+                      EfiACPIMemoryNVS,\r
+                      EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE),\r
+                      &Lasa\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      mTcgDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
+      mTcgDxeData.EventLogAreaStruct[Index].Laml = EFI_TCG_LOG_AREA_SIZE;\r
+      //\r
+      // To initialize them as 0xFF is recommended \r
+      // because the OS can know the last entry for that.\r
+      //\r
+      SetMem ((VOID *)(UINTN)Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF);\r
+  }\r
+\r
+  //\r
+  // 2. Create ACPI table for TCG1.2 only\r
+  //\r
+    if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
+      mTcgClientAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
+      mTcgClientAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;\r
+    } else {\r
+      mTcgServerAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
+      mTcgServerAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;\r
+    }\r
+\r
+  //\r
+  // 3. Sync data from PEI to DXE\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+      GuidHob.Raw = GetHobList ();\r
+      Status = EFI_SUCCESS;\r
+      while (!EFI_ERROR (Status) && \r
+             (GuidHob.Raw = GetNextGuidHob (mTreeEventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) {\r
+        TcgEvent    = GET_GUID_HOB_DATA (GuidHob.Guid);\r
+        GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
+        switch (mTreeEventInfo[Index].LogFormat) {\r
+        case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
+          Status = TcgDxeLogEvent (\r
+                     mTreeEventInfo[Index].LogFormat,\r
+                     TcgEvent,\r
+                     sizeof(TCG_PCR_EVENT_HDR),\r
+                     ((TCG_PCR_EVENT*)TcgEvent)->Event,\r
+                     ((TCG_PCR_EVENT_HDR*)TcgEvent)->EventSize\r
+                     );\r
+          break;\r
+        }\r
+      }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Measure and log an action string, and extend the measurement result into PCR[5].\r
+\r
+  @param[in] String           A specific string that indicates an Action event.  \r
+  \r
+  @retval EFI_SUCCESS         Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR    The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgMeasureAction (\r
+  IN      CHAR8                     *String\r
+  )\r
+{\r
+  TCG_PCR_EVENT_HDR                 TcgEvent;\r
+\r
+  TcgEvent.PCRIndex  = 5;\r
+  TcgEvent.EventType = EV_EFI_ACTION;\r
+  TcgEvent.EventSize = (UINT32)AsciiStrLen (String);\r
+  return TcgDxeHashLogExtendEvent (\r
+           0,\r
+           (UINT8*)String,\r
+           TcgEvent.EventSize,\r
+           &TcgEvent,\r
+           (UINT8 *) String\r
+           );\r
+}\r
+\r
+/**\r
+  Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
+\r
+  @retval EFI_SUCCESS         Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR    The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureHandoffTables (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  SMBIOS_TABLE_ENTRY_POINT          *SmbiosTable;\r
+  TCG_PCR_EVENT_HDR                 TcgEvent;\r
+  EFI_HANDOFF_TABLE_POINTERS        HandoffTables;\r
+  UINTN                             ProcessorNum;\r
+  EFI_CPU_PHYSICAL_LOCATION         *ProcessorLocBuf;\r
+\r
+  //\r
+  // Measure SMBIOS with EV_EFI_HANDOFF_TABLES to PCR[1]\r
+  //\r
+  Status = EfiGetSystemConfigurationTable (\r
+             &gEfiSmbiosTableGuid,\r
+             (VOID **) &SmbiosTable\r
+             );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    ASSERT (SmbiosTable != NULL);\r
+\r
+    TcgEvent.PCRIndex  = 1;\r
+    TcgEvent.EventType = EV_EFI_HANDOFF_TABLES;\r
+    TcgEvent.EventSize = sizeof (HandoffTables);\r
+\r
+    HandoffTables.NumberOfTables = 1;\r
+    HandoffTables.TableEntry[0].VendorGuid  = gEfiSmbiosTableGuid;\r
+    HandoffTables.TableEntry[0].VendorTable = SmbiosTable;\r
+\r
+    DEBUG ((DEBUG_INFO, "The Smbios Table starts at: 0x%x\n", SmbiosTable->TableAddress));\r
+    DEBUG ((DEBUG_INFO, "The Smbios Table size: 0x%x\n", SmbiosTable->TableLength));\r
+\r
+    Status = TcgDxeHashLogExtendEvent (\r
+               0,\r
+               (UINT8*)(UINTN)SmbiosTable->TableAddress,\r
+               SmbiosTable->TableLength,\r
+               &TcgEvent,\r
+               (UINT8*)&HandoffTables\r
+               );\r
+  }\r
+\r
+  if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
+    //\r
+    // Tcg Server spec. \r
+    // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
+    //\r
+    Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);\r
+\r
+    if (!EFI_ERROR(Status)){\r
+      TcgEvent.PCRIndex  = 1;\r
+      TcgEvent.EventType = EV_TABLE_OF_DEVICES;\r
+      TcgEvent.EventSize = sizeof (HandoffTables);\r
+\r
+      HandoffTables.NumberOfTables = 1;\r
+      HandoffTables.TableEntry[0].VendorGuid  = gEfiMpServiceProtocolGuid;\r
+      HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
+\r
+      Status = TcgDxeHashLogExtendEvent (\r
+                 0,\r
+                 (UINT8*)(UINTN)ProcessorLocBuf,\r
+                 sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
+                 &TcgEvent,\r
+                 (UINT8*)&HandoffTables\r
+                 );\r
+\r
+      FreePool(ProcessorLocBuf);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Measure and log Separator event, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in] PCRIndex         PCR index.  \r
+\r
+  @retval EFI_SUCCESS         Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR    The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureSeparatorEvent (\r
+  IN      TPM_PCRINDEX              PCRIndex\r
+  )\r
+{\r
+  TCG_PCR_EVENT_HDR                 TcgEvent;\r
+  UINT32                            EventData;\r
+\r
+  DEBUG ((EFI_D_ERROR, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex));\r
+\r
+  EventData = 0;\r
+  TcgEvent.PCRIndex  = PCRIndex;\r
+  TcgEvent.EventType = EV_SEPARATOR;\r
+  TcgEvent.EventSize = (UINT32)sizeof (EventData);\r
+  return TcgDxeHashLogExtendEvent (\r
+           0,\r
+           (UINT8 *)&EventData,\r
+           sizeof (EventData),\r
+           &TcgEvent,\r
+           (UINT8 *)&EventData\r
+           );\r
+}\r
+\r
+/**\r
+  Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in]  PCRIndex          PCR Index.  \r
+  @param[in]  EventType         Event type.  \r
+  @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+  @param[in]  VarData           The content of the variable data.  \r
+  @param[in]  VarSize           The size of the variable data.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureVariable (\r
+  IN      TPM_PCRINDEX              PCRIndex,\r
+  IN      TCG_EVENTTYPE             EventType,\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  IN      VOID                      *VarData,\r
+  IN      UINTN                     VarSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TCG_PCR_EVENT_HDR                 TcgEvent;\r
+  UINTN                             VarNameLength;\r
+  EFI_VARIABLE_DATA_TREE            *VarLog;\r
+\r
+  ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));\r
+\r
+  DEBUG ((EFI_D_ERROR, "TrEEDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType));\r
+  DEBUG ((EFI_D_ERROR, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
+\r
+  VarNameLength      = StrLen (VarName);\r
+  TcgEvent.PCRIndex  = PCRIndex;\r
+  TcgEvent.EventType = EventType;\r
+  TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
+                        - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
+\r
+  VarLog = (EFI_VARIABLE_DATA_TREE*)AllocatePool (TcgEvent.EventSize);\r
+  if (VarLog == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  VarLog->VariableName       = *VendorGuid;\r
+  VarLog->UnicodeNameLength  = VarNameLength;\r
+  VarLog->VariableDataLength = VarSize;\r
+  CopyMem (\r
+     VarLog->UnicodeName,\r
+     VarName,\r
+     VarNameLength * sizeof (*VarName)\r
+     );\r
+  if (VarSize != 0) {\r
+    CopyMem (\r
+       (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
+       VarData,\r
+       VarSize\r
+       );\r
+  }\r
+\r
+  if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
+    //\r
+    // Digest is the event data (EFI_VARIABLE_DATA_TREE)\r
+    //\r
+    Status = TcgDxeHashLogExtendEvent (\r
+               0,\r
+               (UINT8*)VarLog,\r
+               TcgEvent.EventSize,\r
+               &TcgEvent,\r
+               (UINT8*)VarLog\r
+               );\r
+  } else {\r
+    Status = TcgDxeHashLogExtendEvent (\r
+               0,\r
+               (UINT8*)VarData,\r
+               VarSize,\r
+               &TcgEvent,\r
+               (UINT8*)VarLog\r
+               );\r
+  }\r
+  FreePool (VarLog);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read then Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in]  PCRIndex          PCR Index.  \r
+  @param[in]  EventType         Event type.  \r
+  @param[in]   VarName          A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]   VendorGuid       A unique identifier for the vendor.\r
+  @param[out]  VarSize          The size of the variable data.  \r
+  @param[out]  VarData          Pointer to the content of the variable.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadAndMeasureVariable (\r
+  IN      TPM_PCRINDEX              PCRIndex,\r
+  IN      TCG_EVENTTYPE             EventType,\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  OUT     UINTN                     *VarSize,\r
+  OUT     VOID                      **VarData\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize);\r
+  if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // It is valid case, so we need handle it.\r
+      //\r
+      *VarData = NULL;\r
+      *VarSize = 0;\r
+    }\r
+  } else {\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    ASSERT (*VarData != NULL);\r
+  }\r
+\r
+  Status = MeasureVariable (\r
+             PCRIndex,\r
+             EventType,\r
+             VarName,\r
+             VendorGuid,\r
+             *VarData,\r
+             *VarSize\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].\r
+\r
+  @param[in]   VarName          A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]   VendorGuid       A unique identifier for the vendor.\r
+  @param[out]  VarSize          The size of the variable data.  \r
+  @param[out]  VarData          Pointer to the content of the variable.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadAndMeasureBootVariable (\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  OUT     UINTN                     *VarSize,\r
+  OUT     VOID                      **VarData\r
+  )\r
+{\r
+  return ReadAndMeasureVariable (\r
+           5,\r
+           EV_EFI_VARIABLE_BOOT,\r
+           VarName,\r
+           VendorGuid,\r
+           VarSize,\r
+           VarData\r
+           );\r
+}\r
+\r
+/**\r
+  Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7].\r
+\r
+  @param[in]   VarName          A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]   VendorGuid       A unique identifier for the vendor.\r
+  @param[out]  VarSize          The size of the variable data.  \r
+  @param[out]  VarData          Pointer to the content of the variable.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadAndMeasureSecureVariable (\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  OUT     UINTN                     *VarSize,\r
+  OUT     VOID                      **VarData\r
+  )\r
+{\r
+  return ReadAndMeasureVariable (\r
+           7,\r
+           EV_EFI_VARIABLE_DRIVER_CONFIG,\r
+           VarName,\r
+           VendorGuid,\r
+           VarSize,\r
+           VarData\r
+           );\r
+}\r
+\r
+/**\r
+  Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
+\r
+  The EFI boot variables are BootOrder and Boot#### variables.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureAllBootVariables (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINT16                            *BootOrder;\r
+  UINTN                             BootCount;\r
+  UINTN                             Index;\r
+  VOID                              *BootVarData;\r
+  UINTN                             Size;\r
+\r
+  Status = ReadAndMeasureBootVariable (\r
+             mBootVarName,\r
+             &gEfiGlobalVariableGuid,\r
+             &BootCount,\r
+             (VOID **) &BootOrder\r
+             );\r
+  if (Status == EFI_NOT_FOUND) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  ASSERT (BootOrder != NULL);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (BootOrder);\r
+    return Status;\r
+  }\r
+\r
+  BootCount /= sizeof (*BootOrder);\r
+  for (Index = 0; Index < BootCount; Index++) {\r
+    UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
+    Status = ReadAndMeasureBootVariable (\r
+               mBootVarName,\r
+               &gEfiGlobalVariableGuid,\r
+               &Size,\r
+               &BootVarData\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      FreePool (BootVarData);\r
+    }\r
+  }\r
+\r
+  FreePool (BootOrder);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR.\r
+\r
+  The EFI boot variables are BootOrder and Boot#### variables.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureAllSecureVariables (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  VOID                              *Data;\r
+  UINTN                             DataSize;\r
+  UINTN                             Index;\r
+\r
+  Status = EFI_NOT_FOUND;\r
+  for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
+    Status = ReadAndMeasureSecureVariable (\r
+               mVariableType[Index].VariableName,\r
+               mVariableType[Index].VendorGuid,\r
+               &DataSize,\r
+               &Data\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Data != NULL) {\r
+        FreePool (Data);\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureLaunchOfFirmwareDebugger (\r
+  VOID\r
+  )\r
+{\r
+  TCG_PCR_EVENT_HDR                 TcgEvent;\r
+\r
+  TcgEvent.PCRIndex  = 7;\r
+  TcgEvent.EventType = EV_EFI_ACTION;\r
+  TcgEvent.EventSize = sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
+  return TcgDxeHashLogExtendEvent (\r
+           0,\r
+           (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
+           sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
+           &TcgEvent,\r
+           (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING\r
+           );\r
+}\r
+\r
+/**\r
+  Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR.\r
+\r
+  Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed)\r
+   - The contents of the SecureBoot variable\r
+   - The contents of the PK variable\r
+   - The contents of the KEK variable\r
+   - The contents of the EFI_IMAGE_SECURITY_DATABASE variable\r
+   - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable\r
+   - Separator\r
+   - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path\r
+\r
+  NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE,\r
+  EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3].\r
+\r
+  @param[in]  Event     Event whose notification function is being invoked\r
+  @param[in]  Context   Pointer to the notification function's context\r
+**/\r
+VOID\r
+EFIAPI\r
+MeasureSecureBootPolicy (\r
+  IN EFI_EVENT                      Event,\r
+  IN VOID                           *Context\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  VOID        *Protocol;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  if (PcdGetBool (PcdFirmwareDebuggerInitialized)) {\r
+    Status = MeasureLaunchOfFirmwareDebugger ();\r
+    DEBUG ((EFI_D_ERROR, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
+  }\r
+\r
+  Status = MeasureAllSecureVariables ();\r
+  DEBUG ((EFI_D_ERROR, "MeasureAllSecureVariables - %r\n", Status));\r
+\r
+  //\r
+  // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure)\r
+  // and ImageVerification (Authority)\r
+  // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So\r
+  // the Authority measurement happen before ReadToBoot event.\r
+  //\r
+  Status = MeasureSeparatorEvent (7);\r
+  DEBUG ((EFI_D_ERROR, "MeasureSeparatorEvent - %r\n", Status));\r
+  return ;\r
+}\r
+\r
+/**\r
+  Ready to Boot Event notification handler.\r
+\r
+  Sequence of OS boot events is measured in this event notification handler.\r
+\r
+  @param[in]  Event     Event whose notification function is being invoked\r
+  @param[in]  Context   Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnReadyToBoot (\r
+  IN      EFI_EVENT                 Event,\r
+  IN      VOID                      *Context\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM_PCRINDEX                      PcrIndex;\r
+\r
+  PERF_START_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE);\r
+  if (mBootAttempts == 0) {\r
+\r
+    //\r
+    // Measure handoff tables.\r
+    //\r
+    Status = MeasureHandoffTables ();\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));\r
+    }\r
+\r
+    //\r
+    // Measure BootOrder & Boot#### variables.\r
+    //\r
+    Status = MeasureAllBootVariables ();\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));\r
+    }\r
+\r
+    //\r
+    // 1. This is the first boot attempt.\r
+    //\r
+    Status = TcgMeasureAction (\r
+               EFI_CALLING_EFI_APPLICATION\r
+               );\r
+\r
+    //\r
+    // 2. Draw a line between pre-boot env and entering post-boot env.\r
+    // PCR[7] is already done.\r
+    //\r
+    for (PcrIndex = 0; PcrIndex < 7; PcrIndex++) {\r
+      Status = MeasureSeparatorEvent (PcrIndex);\r
+    }\r
+\r
+    //\r
+    // 3. Measure GPT. It would be done in SAP driver.\r
+    //\r
+\r
+    //\r
+    // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
+    //\r
+\r
+    //\r
+    // 5. Read & Measure variable. BootOrder already measured.\r
+    //\r
+  } else {\r
+    //\r
+    // 6. Not first attempt, meaning a return from last attempt\r
+    //\r
+    Status = TcgMeasureAction (\r
+               EFI_RETURNING_FROM_EFI_APPLICATOIN\r
+               );\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "TPM2 TrEEDxe Measure Data when ReadyToBoot\n"));\r
+  //\r
+  // Increase boot attempt counter.\r
+  //\r
+  mBootAttempts++;\r
+  PERF_END_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE + 1);\r
+}\r
+\r
+/**\r
+  Install TCG ACPI Table when ACPI Table Protocol is available.\r
+\r
+  A system's firmware uses an ACPI table to identify the system's TCG capabilities \r
+  to the Post-Boot environment. The information in this ACPI table is not guaranteed \r
+  to be valid until the Host Platform transitions from pre-boot state to post-boot state.  \r
+\r
+  @param[in]  Event     Event whose notification function is being invoked\r
+  @param[in]  Context   Pointer to the notification function's context\r
+**/\r
+VOID\r
+EFIAPI\r
+InstallAcpiTable (\r
+  IN EFI_EVENT                      Event,\r
+  IN VOID                           *Context\r
+  )\r
+{\r
+  UINTN                             TableKey;\r
+  EFI_STATUS                        Status;\r
+  EFI_ACPI_TABLE_PROTOCOL           *AcpiTable;\r
+  UINT8                             Checksum;\r
+  UINT64                            OemTableId;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
+    CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));\r
+    OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+    CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+    mTcgClientAcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+    mTcgClientAcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+    mTcgClientAcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+    //\r
+    // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
+    // service of the ACPI table protocol to install it.\r
+    //\r
+    Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));\r
+    mTcgClientAcpiTemplate.Header.Checksum = Checksum;\r
+\r
+    Status = AcpiTable->InstallAcpiTable (\r
+                            AcpiTable,\r
+                            &mTcgClientAcpiTemplate,\r
+                            sizeof (mTcgClientAcpiTemplate),\r
+                            &TableKey\r
+                            );\r
+  } else {\r
+    CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));\r
+    OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+    CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+    mTcgServerAcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+    mTcgServerAcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+    mTcgServerAcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+    //\r
+    // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
+    // service of the ACPI table protocol to install it.\r
+    //\r
+    Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));\r
+    mTcgServerAcpiTemplate.Header.Checksum = Checksum;\r
+\r
+    mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress);\r
+    Status = AcpiTable->InstallAcpiTable (\r
+                            AcpiTable,\r
+                            &mTcgServerAcpiTemplate,\r
+                            sizeof (mTcgServerAcpiTemplate),\r
+                            &TableKey\r
+                            );\r
+  }\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Exit Boot Services Event notification handler.\r
+\r
+  Measure invocation and success of ExitBootServices.\r
+\r
+  @param[in]  Event     Event whose notification function is being invoked\r
+  @param[in]  Context   Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnExitBootServices (\r
+  IN      EFI_EVENT                 Event,\r
+  IN      VOID                      *Context\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  //\r
+  // Measure invocation of ExitBootServices,\r
+  //\r
+  Status = TcgMeasureAction (\r
+             EFI_EXIT_BOOT_SERVICES_INVOCATION\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Measure success of ExitBootServices\r
+  //\r
+  Status = TcgMeasureAction (\r
+             EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Exit Boot Services Failed Event notification handler.\r
+\r
+  Measure Failure of ExitBootServices.\r
+\r
+  @param[in]  Event     Event whose notification function is being invoked\r
+  @param[in]  Context   Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnExitBootServicesFailed (\r
+  IN      EFI_EVENT                 Event,\r
+  IN      VOID                      *Context\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  //\r
+  // Measure Failure of ExitBootServices,\r
+  //\r
+  Status = TcgMeasureAction (\r
+             EFI_EXIT_BOOT_SERVICES_FAILED\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+}\r
+\r
+/**\r
+  The function install TrEE protocol.\r
+  \r
+  @retval EFI_SUCCESS     TrEE protocol is installed.\r
+  @retval other           Some error occurs.\r
+**/\r
+EFI_STATUS\r
+InstallTrEE (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_HANDLE        Handle;\r
+\r
+  Handle = NULL;\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &Handle,\r
+                  &gEfiTrEEProtocolGuid,\r
+                  &mTreeProtocol,\r
+                  NULL\r
+                  );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The driver's entry point. It publishes EFI TrEE Protocol.\r
+\r
+  @param[in] ImageHandle  The firmware allocated handle for the EFI image.  \r
+  @param[in] SystemTable  A pointer to the EFI System Table.\r
+  \r
+  @retval EFI_SUCCESS     The entry point is executed successfully.\r
+  @retval other           Some error occurs when executing this entry point.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverEntry (\r
+  IN    EFI_HANDLE                  ImageHandle,\r
+  IN    EFI_SYSTEM_TABLE            *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_EVENT                         Event;\r
+  VOID                              *Registration;\r
+  UINT32                            MaxCommandSize;\r
+  UINT32                            MaxResponseSize;\r
+  TPML_PCR_SELECTION                Pcrs;\r
+  UINTN                             Index;\r
+  UINT32                            TpmHashAlgorithmBitmap;\r
+\r
+  mImageHandle = ImageHandle;\r
+\r
+  if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
+      CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
+    DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = Tpm2RequestUseTpm ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "TPM not detected!\n"));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Fill information\r
+  //\r
+  DEBUG ((EFI_D_ERROR, "TrEE.ProtocolVersion  - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor));\r
+  DEBUG ((EFI_D_ERROR, "TrEE.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor));\r
+\r
+  Status = Tpm2GetCapabilityManufactureID (&mTcgDxeData.BsCap.ManufacturerID);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID fail!\n"));\r
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID));\r
+  }\r
+\r
+  DEBUG_CODE (\r
+    UINT32                    FirmwareVersion1;\r
+    UINT32                    FirmwareVersion2;\r
+\r
+    Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n"));\r
+    } else {\r
+      DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2));\r
+    }\r
+  );\r
+\r
+  Status = Tpm2GetCapabilityMaxCommandResponseSize (&MaxCommandSize, &MaxResponseSize);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n"));\r
+  } else {\r
+    mTcgDxeData.BsCap.MaxCommandSize  = (UINT16)MaxCommandSize;\r
+    mTcgDxeData.BsCap.MaxResponseSize = (UINT16)MaxResponseSize;\r
+    DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize));\r
+  }\r
+\r
+  Status = Tpm2GetCapabilityPcrs (&Pcrs);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));\r
+    TpmHashAlgorithmBitmap = TREE_BOOT_HASH_ALG_SHA1;\r
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));\r
+    TpmHashAlgorithmBitmap = 0;\r
+    for (Index = 0; Index < Pcrs.count; Index++) {\r
+      DEBUG ((EFI_D_ERROR, "hash - %x\n", Pcrs.pcrSelections[Index].hash));\r
+      switch (Pcrs.pcrSelections[Index].hash) {\r
+      case TPM_ALG_SHA1:\r
+        TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA1;\r
+        break;\r
+      case TPM_ALG_SHA256:\r
+        TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA256;\r
+        break;\r
+      case TPM_ALG_SHA384:\r
+        TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA384;\r
+        break;\r
+      case TPM_ALG_SHA512:\r
+        TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA512;\r
+        break;\r
+      case TPM_ALG_SM3_256:\r
+        // TBD: Spec not define TREE_BOOT_HASH_ALG_SM3_256 yet\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  DEBUG ((EFI_D_ERROR, "TPM.HashAlgorithmBitmap - 0x%08x\n", TpmHashAlgorithmBitmap));\r
+\r
+  DEBUG ((EFI_D_ERROR, "TrEE.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs));\r
+  mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap;\r
+  DEBUG ((EFI_D_ERROR, "TrEE.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap));\r
+\r
+  if (mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+    //\r
+    // Setup the log area and copy event log from hob list to it\r
+    //\r
+    Status = SetupEventLog ();\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Measure handoff tables, Boot#### variables etc.\r
+    //\r
+    Status = EfiCreateEventReadyToBootEx (\r
+               TPL_CALLBACK,\r
+               OnReadyToBoot,\r
+               NULL,\r
+               &Event\r
+               );\r
+\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    OnExitBootServices,\r
+                    NULL,\r
+                    &gEfiEventExitBootServicesGuid,\r
+                    &Event\r
+                    );\r
+\r
+    //\r
+    // Measure Exit Boot Service failed \r
+    //\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    OnExitBootServicesFailed,\r
+                    NULL,\r
+                    &gEventExitBootServicesFailedGuid,\r
+                    &Event\r
+                    );\r
+\r
+    //\r
+    // Create event callback, because we need access variable on SecureBootPolicyVariable\r
+    // We should use VariableWriteArch instead of VariableArch, because Variable driver\r
+    // may update SecureBoot value based on last setting.\r
+    //\r
+    EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration);\r
+  }\r
+\r
+  //\r
+  // Install ACPI Table\r
+  //\r
+  EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
+\r
+  //\r
+  // Install TrEEProtocol\r
+  //\r
+  Status = InstallTrEE ();\r
+  DEBUG ((EFI_D_ERROR, "InstallTrEE - %r\n", Status));\r
+\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.inf b/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.inf
new file mode 100644 (file)
index 0000000..a1f1741
--- /dev/null
@@ -0,0 +1,91 @@
+## @file\r
+#  Component file for module TrEEDxe.\r
+#  This module will produce TrEE protocol and measure boot environment.\r
+#\r
+#  Caution: This module requires additional review when modified.\r
+#  This driver will have external input - PE/COFF image.\r
+#  This external input must be validated carefully to avoid security issue like\r
+#  buffer overflow, integer overflow.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = TrEEDxe\r
+  FILE_GUID                      = 2A7946E3-1AB2-49a9-ACCB-C6275139C1A5\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = DriverEntry\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+  TrEEDxe.c\r
+  MeasureBootPeCoff.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  UefiBootServicesTableLib\r
+  HobLib\r
+  UefiDriverEntryPoint\r
+  UefiRuntimeServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2CommandLib\r
+  PrintLib\r
+  UefiLib\r
+  Tpm2DeviceLib\r
+  HashLib\r
+  PerformanceLib\r
+\r
+[Guids]\r
+  gEfiSmbiosTableGuid                           # ALWAYS_CONSUMED\r
+  gEfiGlobalVariableGuid                        # ALWAYS_CONSUMED\r
+  gTcgEventEntryHobGuid\r
+  gEfiEventReadyToBootGuid\r
+  gEfiEventExitBootServicesGuid\r
+  gEventExitBootServicesFailedGuid              # ALWAYS_CONSUMED\r
+  gEfiImageSecurityDatabaseGuid\r
+  gEfiTpmDeviceInstanceNoneGuid\r
+  gEfiTpmDeviceInstanceTpm12Guid\r
+\r
+[Protocols]\r
+  gEfiTrEEProtocolGuid                          ## PRODUCES\r
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiMpServiceProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiVariableWriteArchProtocolGuid             # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdFirmwareDebuggerInitialized\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision\r
+\r
+[Depex]\r
+  TRUE\r
+\r
diff --git a/SecurityPkg/Tcg/TrEEPei/TrEEPei.c b/SecurityPkg/Tcg/TrEEPei/TrEEPei.c
new file mode 100644 (file)
index 0000000..5b5ff6c
--- /dev/null
@@ -0,0 +1,694 @@
+/** @file\r
+  Initialize TPM2 device and measure FVs before handing off control to DXE.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Ppi/FirmwareVolumeInfo.h>\r
+#include <Ppi/LockPhysicalPresence.h>\r
+#include <Ppi/TpmInitialized.h>\r
+#include <Ppi/FirmwareVolume.h>\r
+#include <Ppi/EndOfPeiPhase.h>\r
+#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>\r
+\r
+#include <Guid/TcgEventHob.h>\r
+#include <Guid/MeasuredFvHob.h>\r
+#include <Guid/TpmInstance.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+#include <Library/PerformanceLib.h>\r
+\r
+#define PERF_ID_TREE_PEI  0x3080\r
+\r
+typedef struct {\r
+  EFI_GUID               *EventGuid;\r
+  TREE_EVENT_LOG_FORMAT  LogFormat;\r
+  UINT32                 BootHashAlg;\r
+  UINT16                 DigestAlgID;\r
+  TPMI_ALG_HASH          TpmHashAlgo;\r
+} TREE_EVENT_INFO_STRUCT;\r
+\r
+TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {\r
+  {&gTcgEventEntryHobGuid,             TREE_EVENT_LOG_FORMAT_TCG_1_2,      TREE_BOOT_HASH_ALG_SHA1,     0,                       TPM_ALG_SHA1},\r
+};\r
+\r
+BOOLEAN                 mImageInMemory  = FALSE;\r
+EFI_PEI_FILE_HANDLE     mFileHandle;\r
+\r
+EFI_PEI_PPI_DESCRIPTOR  mTpmInitializedPpiList = {\r
+  EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+  &gPeiTpmInitializedPpiGuid,\r
+  NULL\r
+};\r
+\r
+EFI_PLATFORM_FIRMWARE_BLOB mMeasuredBaseFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];\r
+UINT32 mMeasuredBaseFvIndex = 0;\r
+\r
+EFI_PLATFORM_FIRMWARE_BLOB mMeasuredChildFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];\r
+UINT32 mMeasuredChildFvIndex = 0;\r
+\r
+/**\r
+  Measure and record the Firmware Volum Information once FvInfoPPI install.\r
+\r
+  @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param[in] NotifyDescriptor  Address of the notification descriptor data structure.\r
+  @param[in] Ppi               Address of the PPI that was installed.\r
+\r
+  @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.\r
+  @return Others               Fail to measure FV.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FirmwareVolmeInfoPpiNotifyCallback (\r
+  IN EFI_PEI_SERVICES              **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,\r
+  IN VOID                          *Ppi\r
+  );\r
+\r
+/**\r
+  Record all measured Firmware Volum Information into a Guid Hob\r
+\r
+  @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param[in] NotifyDescriptor  Address of the notification descriptor data structure.\r
+  @param[in] Ppi               Address of the PPI that was installed.\r
+\r
+  @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.\r
+  @return Others               Fail to measure FV.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EndofPeiSignalNotifyCallBack (\r
+  IN EFI_PEI_SERVICES              **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,\r
+  IN VOID                          *Ppi\r
+  );\r
+\r
+EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {\r
+  {\r
+    EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
+    &gEfiPeiFirmwareVolumeInfoPpiGuid,\r
+    FirmwareVolmeInfoPpiNotifyCallback \r
+  },\r
+  {\r
+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+    &gEfiEndOfPeiSignalPpiGuid,\r
+    EndofPeiSignalNotifyCallBack\r
+  }\r
+};\r
+\r
+EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;\r
+\r
+/**\r
+  This function return hash algorithm from event log format.\r
+\r
+  @param[in]     EventLogFormat    Event log format.\r
+\r
+  @return hash algorithm.\r
+**/\r
+TPMI_ALG_HASH\r
+TrEEGetHashAlgoFromLogFormat (\r
+  IN      TREE_EVENT_LOG_FORMAT     EventLogFormat\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+    if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {\r
+      return mTreeEventInfo[Index].TpmHashAlgo;\r
+    }\r
+  }\r
+  return TPM_ALG_SHA1;\r
+}\r
+\r
+/**\r
+  This function get digest from digest list.\r
+\r
+  @param HashAlg    digest algorithm\r
+  @param DigestList digest list\r
+  @param Digest     digest\r
+\r
+  @retval EFI_SUCCESS   Sha1Digest is found and returned.\r
+  @retval EFI_NOT_FOUND Sha1Digest is not found.\r
+**/\r
+EFI_STATUS\r
+Tpm2GetDigestFromDigestList (\r
+  IN TPMI_ALG_HASH      HashAlg,\r
+  IN TPML_DIGEST_VALUES *DigestList,\r
+  IN VOID               *Digest\r
+  )\r
+{\r
+  UINTN  Index;\r
+  UINT16 DigestSize;\r
+\r
+  DigestSize = GetHashSizeFromAlgo (HashAlg);\r
+  for (Index = 0; Index < DigestList->count; Index++) {\r
+    if (DigestList->digests[Index].hashAlg == HashAlg) {\r
+      CopyMem (\r
+        Digest,\r
+        &DigestList->digests[Index].digest,\r
+        DigestSize\r
+        );\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Record all measured Firmware Volum Information into a Guid Hob\r
+  Guid Hob payload layout is \r
+\r
+     UINT32 *************************** FIRMWARE_BLOB number\r
+     EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array\r
+\r
+  @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param[in] NotifyDescriptor  Address of the notification descriptor data structure.\r
+  @param[in] Ppi               Address of the PPI that was installed.\r
+\r
+  @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.\r
+  @return Others               Fail to measure FV.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EndofPeiSignalNotifyCallBack (\r
+  IN EFI_PEI_SERVICES              **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,\r
+  IN VOID                          *Ppi\r
+  )\r
+{  \r
+  MEASURED_HOB_DATA *MeasuredHobData;\r
+\r
+  MeasuredHobData = NULL;\r
+\r
+  //\r
+  // Create a Guid hob to save all measured Fv \r
+  //\r
+  MeasuredHobData = BuildGuidHob(\r
+                      &gMeasuredFvHobGuid,\r
+                      sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)\r
+                      );\r
+\r
+  if (MeasuredHobData != NULL){\r
+    //\r
+    // Save measured FV info enty number\r
+    //\r
+    MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;\r
+\r
+    //\r
+    // Save measured base Fv info\r
+    //\r
+    CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));\r
+\r
+    //\r
+    // Save measured child Fv info\r
+    //\r
+    CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Add a new entry to the Event Log.\r
+\r
+  @param[in]     DigestList    A list of digest.\r
+  @param[in,out] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.\r
+  @param[in]     NewEventData  Pointer to the new event data.\r
+\r
+  @retval EFI_SUCCESS           The new event log entry was added.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+**/\r
+EFI_STATUS\r
+LogHashEvent (\r
+  IN TPML_DIGEST_VALUES             *DigestList,\r
+  IN OUT  TCG_PCR_EVENT_HDR         *NewEventHdr,\r
+  IN      UINT8                     *NewEventData\r
+  )\r
+{\r
+  VOID                              *HobData;\r
+  EFI_STATUS                        Status;\r
+  UINTN                             Index;\r
+  EFI_STATUS                        RetStatus;\r
+\r
+  RetStatus = EFI_SUCCESS;\r
+  for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+      DEBUG ((EFI_D_INFO, "  LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));\r
+      switch (mTreeEventInfo[Index].LogFormat) {\r
+      case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
+        Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
+        if (!EFI_ERROR (Status)) {\r
+          HobData = BuildGuidHob (\r
+                     &gTcgEventEntryHobGuid,\r
+                     sizeof (*NewEventHdr) + NewEventHdr->EventSize\r
+                     );\r
+          if (HobData == NULL) {\r
+            RetStatus = EFI_OUT_OF_RESOURCES;\r
+            break;\r
+          }\r
+\r
+          CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));\r
+          HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));\r
+          CopyMem (HobData, NewEventData, NewEventHdr->EventSize);\r
+        }\r
+        break;\r
+      }\r
+  }\r
+\r
+  return RetStatus;\r
+}\r
+\r
+/**\r
+  Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
+  and build a GUIDed HOB recording the event which will be passed to the DXE phase and\r
+  added into the Event Log.\r
+\r
+  @param[in]      Flags         Bitmap providing additional information.\r
+  @param[in]      HashData      Physical address of the start of the data buffer \r
+                                to be hashed, extended, and logged.\r
+  @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData.\r
+  @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.  \r
+  @param[in]      NewEventData  Pointer to the new event data.  \r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+  @retval EFI_DEVICE_ERROR      The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+HashLogExtendEvent (\r
+  IN      UINT64                    Flags,\r
+  IN      UINT8                     *HashData,\r
+  IN      UINTN                     HashDataLen,\r
+  IN      TCG_PCR_EVENT_HDR         *NewEventHdr,\r
+  IN      UINT8                     *NewEventData\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPML_DIGEST_VALUES                DigestList;\r
+\r
+  Status = HashAndExtend (\r
+             NewEventHdr->PCRIndex,\r
+             HashData,\r
+             HashDataLen,\r
+             &DigestList\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
+      Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
+    }\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Measure CRTM version.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+  @retval EFI_DEVICE_ERROR      The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureCRTMVersion (\r
+  VOID\r
+  )\r
+{\r
+  TCG_PCR_EVENT_HDR                 TcgEventHdr;\r
+\r
+  //\r
+  // Use FirmwareVersion string to represent CRTM version.\r
+  // OEMs should get real CRTM version string and measure it.\r
+  //\r
+\r
+  TcgEventHdr.PCRIndex  = 0;\r
+  TcgEventHdr.EventType = EV_S_CRTM_VERSION;\r
+  TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));\r
+\r
+  return HashLogExtendEvent (\r
+           0,\r
+           (UINT8*)PcdGetPtr (PcdFirmwareVersionString),\r
+           TcgEventHdr.EventSize,\r
+           &TcgEventHdr,\r
+           (UINT8*)PcdGetPtr (PcdFirmwareVersionString)\r
+           );\r
+}\r
+\r
+/**\r
+  Measure FV image. \r
+  Add it into the measured FV list after the FV is measured successfully. \r
+\r
+  @param[in]  FvBase            Base address of FV image.\r
+  @param[in]  FvLength          Length of FV image.\r
+\r
+  @retval EFI_SUCCESS           Fv image is measured successfully \r
+                                or it has been already measured.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+  @retval EFI_DEVICE_ERROR      The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureFvImage (\r
+  IN EFI_PHYSICAL_ADDRESS           FvBase,\r
+  IN UINT64                         FvLength\r
+  )\r
+{\r
+  UINT32                            Index;\r
+  EFI_STATUS                        Status;\r
+  EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;\r
+  TCG_PCR_EVENT_HDR                 TcgEventHdr;\r
+\r
+  //\r
+  // Check if it is in Excluded FV list\r
+  //\r
+  if (mMeasurementExcludedFvPpi != NULL) {\r
+    for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {\r
+      if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {\r
+        DEBUG ((DEBUG_INFO, "The FV which is excluded by TrEEPei starts at: 0x%x\n", FvBase));\r
+        DEBUG ((DEBUG_INFO, "The FV which is excluded by TrEEPei has the size: 0x%x\n", FvLength));\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check whether FV is in the measured FV list.\r
+  //\r
+  for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {\r
+    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Measure and record the FV to the TPM\r
+  //\r
+  FvBlob.BlobBase   = FvBase;\r
+  FvBlob.BlobLength = FvLength;\r
+\r
+  DEBUG ((DEBUG_INFO, "The FV which is measured by TrEEPei starts at: 0x%x\n", FvBlob.BlobBase));\r
+  DEBUG ((DEBUG_INFO, "The FV which is measured by TrEEPei has the size: 0x%x\n", FvBlob.BlobLength));\r
+\r
+  TcgEventHdr.PCRIndex = 0;\r
+  TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;\r
+  TcgEventHdr.EventSize = sizeof (FvBlob);\r
+\r
+  Status = HashLogExtendEvent (\r
+             0,\r
+             (UINT8*) (UINTN) FvBlob.BlobBase,\r
+             (UINTN) FvBlob.BlobLength,\r
+             &TcgEventHdr,\r
+             (UINT8*) &FvBlob\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Add new FV into the measured FV list.\r
+  //\r
+  ASSERT (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported));\r
+  if (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
+    mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase   = FvBase;\r
+    mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;\r
+    mMeasuredBaseFvIndex++;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Measure main BIOS.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+  @retval EFI_DEVICE_ERROR      The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureMainBios (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINT32                            FvInstances;\r
+  EFI_PEI_FV_HANDLE                 VolumeHandle;\r
+  EFI_FV_INFO                       VolumeInfo;\r
+  EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;\r
+\r
+  PERF_START_EX (mFileHandle, "EventRec", "TrEEPei", 0, PERF_ID_TREE_PEI);\r
+  FvInstances    = 0;\r
+  while (TRUE) {\r
+    //\r
+    // Traverse all firmware volume instances of Static Core Root of Trust for Measurement\r
+    // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special\r
+    // platform for special CRTM TPM measuring.\r
+    //\r
+    Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  \r
+    //\r
+    // Measure and record the firmware volume that is dispatched by PeiCore\r
+    //\r
+    Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);\r
+    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // Locate the corresponding FV_PPI according to founded FV's format guid\r
+    //\r
+    Status = PeiServicesLocatePpi (\r
+               &VolumeInfo.FvFormat, \r
+               0, \r
+               NULL,\r
+               (VOID**)&FvPpi\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);\r
+    }\r
+\r
+    FvInstances++;\r
+  }\r
+  PERF_END_EX (mFileHandle, "EventRec", "TrEEPei", 0, PERF_ID_TREE_PEI + 1);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Measure and record the Firmware Volum Information once FvInfoPPI install.\r
+\r
+  @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param[in] NotifyDescriptor  Address of the notification descriptor data structure.\r
+  @param[in] Ppi               Address of the PPI that was installed.\r
+\r
+  @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.\r
+  @return Others               Fail to measure FV.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FirmwareVolmeInfoPpiNotifyCallback (\r
+  IN EFI_PEI_SERVICES               **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR      *NotifyDescriptor,\r
+  IN VOID                           *Ppi\r
+  )\r
+{\r
+  EFI_PEI_FIRMWARE_VOLUME_INFO_PPI  *Fv;\r
+  EFI_STATUS                        Status;\r
+  EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;\r
+\r
+  Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;\r
+\r
+  //\r
+  // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+             &Fv->FvFormat, \r
+             0, \r
+             NULL,\r
+             (VOID**)&FvPpi\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  //\r
+  // This is an FV from an FFS file, and the parent FV must have already been measured,\r
+  // No need to measure twice, so just record the FV and return\r
+  //\r
+  if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {\r
+    \r
+    ASSERT (mMeasuredChildFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported));\r
+    if (mMeasuredChildFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
+      mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase   = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;\r
+      mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;\r
+      mMeasuredChildFvIndex++;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);\r
+}\r
+\r
+/**\r
+  Do measurement after memory is ready.\r
+\r
+  @param[in]      PeiServices   Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+  @retval EFI_DEVICE_ERROR      The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+PeimEntryMP (\r
+  IN      EFI_PEI_SERVICES          **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = PeiServicesLocatePpi (\r
+               &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, \r
+               0, \r
+               NULL,\r
+               (VOID**)&mMeasurementExcludedFvPpi\r
+               );\r
+  // Do not check status, because it is optional\r
+\r
+  if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {\r
+    Status = MeasureCRTMVersion ();\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  Status = MeasureMainBios ();\r
+\r
+  //\r
+  // Post callbacks:\r
+  // for the FvInfoPpi services to measure and record\r
+  // the additional Fvs to TPM\r
+  //\r
+  Status = PeiServicesNotifyPpi (&mNotifyList[0]);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Entry point of this module.\r
+\r
+  @param[in] FileHandle   Handle of the file being invoked.\r
+  @param[in] PeiServices  Describes the list of possible PEI Services.\r
+\r
+  @return Status.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeimEntryMA (\r
+  IN       EFI_PEI_FILE_HANDLE      FileHandle,\r
+  IN CONST EFI_PEI_SERVICES         **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_BOOT_MODE                     BootMode;\r
+\r
+  if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
+      CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
+    DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Update for Performance optimization\r
+  //\r
+  Status = Tpm2RequestUseTpm ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));\r
+    return Status;\r
+  }\r
+\r
+  Status = PeiServicesGetBootMode (&BootMode);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // In S3 path, skip shadow logic. no measurement is required\r
+  //\r
+  if (BootMode != BOOT_ON_S3_RESUME) {\r
+    Status = (**PeiServices).RegisterForShadow(FileHandle);\r
+    if (Status == EFI_ALREADY_STARTED) {\r
+      mImageInMemory = TRUE;\r
+      mFileHandle = FileHandle;\r
+    } else if (Status == EFI_NOT_FOUND) {\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+  if (!mImageInMemory) {\r
+    //\r
+    // Initialize TPM device\r
+    //\r
+    if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {\r
+      if (BootMode == BOOT_ON_S3_RESUME) {\r
+        Status = Tpm2Startup (TPM_SU_STATE);\r
+        if (EFI_ERROR (Status) ) {\r
+          Status = Tpm2Startup (TPM_SU_CLEAR);\r
+        }\r
+      } else {\r
+        Status = Tpm2Startup (TPM_SU_CLEAR);\r
+      }\r
+      if (EFI_ERROR (Status) ) {\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // TpmSelfTest is optional on S3 path, skip it to save S3 time\r
+    //\r
+    if (BootMode != BOOT_ON_S3_RESUME) {\r
+      if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {\r
+        Status = Tpm2SelfTest (NO);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+      }\r
+    }\r
+\r
+    Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (mImageInMemory) {\r
+    Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEEPei/TrEEPei.inf b/SecurityPkg/Tcg/TrEEPei/TrEEPei.inf
new file mode 100644 (file)
index 0000000..3de112c
--- /dev/null
@@ -0,0 +1,75 @@
+## @file\r
+#  This module will initialize TPM2 device and measure FVs in PEI phase.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = TrEEPei\r
+  FILE_GUID                      = CA5A1928-6523-409d-A9FE-5DCC87387222\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = PeimEntryMA\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  TrEEPei.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  HobLib\r
+  PeimEntryPoint\r
+  PeiServicesLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  Tpm2CommandLib\r
+  PeiServicesTablePointerLib\r
+  Tpm2DeviceLib\r
+  HashLib\r
+  PerformanceLib\r
+\r
+[Guids]\r
+  gTcgEventEntryHobGuid\r
+  gMeasuredFvHobGuid\r
+  gEfiTpmDeviceInstanceNoneGuid\r
+  gEfiTpmDeviceInstanceTpm12Guid\r
+\r
+[Ppis]\r
+  gEfiPeiFirmwareVolumeInfoPpiGuid\r
+  gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid\r
+  gPeiTpmInitializedPpiGuid\r
+  gEfiEndOfPeiSignalPpiGuid\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdHideTpm\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString             ## CONSUMES\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2InitializationPolicy\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2SelfTestPolicy\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2ScrtmPolicy\r
+\r
+[FixedPcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported             ## CONSUMES\r
+\r
+[Depex]\r
+  gEfiPeiMasterBootModePpiGuid AND\r
+  gEfiPeiReadOnlyVariable2PpiGuid AND\r
+  gEfiTpmDeviceSelectedGuid\r
diff --git a/SecurityPkg/Tcg/TrEESmm/Tpm.asl b/SecurityPkg/Tcg/TrEESmm/Tpm.asl
new file mode 100644 (file)
index 0000000..507f999
--- /dev/null
@@ -0,0 +1,354 @@
+/** @file\r
+  The TPM2 definition block in ACPI table for TrEE physical presence  \r
+  and MemoryClear.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+DefinitionBlock (\r
+  "Tpm.aml",\r
+  "SSDT",\r
+  1,\r
+  "INTEL ",\r
+  "Tpm2Tabl",\r
+  0x1000\r
+  )\r
+{\r
+  Scope (\_SB)\r
+  {\r
+    Device (TPM)\r
+    {\r
+      //\r
+      // TREE\r
+      //\r
+      Name (_HID, "MSFT0101")\r
+      \r
+      //\r
+      // Readable name of this device, don't know if this way is correct yet\r
+      //\r
+      Name (_STR, Unicode ("TPM 2.0 Device"))\r
+\r
+      //\r
+      // Return the resource consumed by TPM device\r
+      //\r
+      Name (_CRS, ResourceTemplate () {\r
+        Memory32Fixed (ReadOnly, 0xfed40000, 0x5000)\r
+      })\r
+\r
+      //\r
+      // Operational region for Smi port access\r
+      //\r
+      OperationRegion (SMIP, SystemIO, 0xB2, 1)\r
+      Field (SMIP, ByteAcc, NoLock, Preserve)\r
+      { \r
+          IOB2, 8\r
+      }\r
+\r
+      //\r
+      // Operational region for TPM access\r
+      //\r
+      OperationRegion (TPMR, SystemMemory, 0xfed40000, 0x5000)\r
+      Field (TPMR, AnyAcc, NoLock, Preserve)\r
+      {\r
+        ACC0, 8,\r
+      }\r
+\r
+      //\r
+      // Operational region for TPM support, TPM Physical Presence and TPM Memory Clear\r
+      // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code.\r
+      //\r
+      OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0xF0)\r
+      Field (TNVS, AnyAcc, NoLock, Preserve)\r
+      {\r
+        PPIN,   8,  //   Software SMI for Physical Presence Interface\r
+        PPIP,   32, //   Used for save physical presence paramter\r
+        PPRP,   32, //   Physical Presence request operation response\r
+        PPRQ,   32, //   Physical Presence request operation\r
+        LPPR,   32, //   Last Physical Presence request operation\r
+        FRET,   32, //   Physical Presence function return code\r
+        MCIN,   8,  //   Software SMI for Memory Clear Interface\r
+        MCIP,   32, //   Used for save the Mor paramter\r
+        MORD,   32, //   Memory Overwrite Request Data\r
+        MRET,   32  //   Memory Overwrite function return code\r
+      }\r
+\r
+      Method (PTS, 1, Serialized)\r
+      {  \r
+        //\r
+        // Detect Sx state for MOR, only S4, S5 need to handle\r
+        //\r
+        If (LAnd (LLess (Arg0, 6), LGreater (Arg0, 3)))\r
+        {   \r
+          //\r
+          // Bit4 -- DisableAutoDetect. 0 -- Firmware MAY autodetect.\r
+          //\r
+          If (LNot (And (MORD, 0x10)))\r
+          {\r
+            //\r
+            // Triggle the SMI through ACPI _PTS method.\r
+            //\r
+            Store (0x02, MCIP)\r
+              \r
+            //\r
+            // Triggle the SMI interrupt\r
+            //\r
+            Store (MCIN, IOB2)\r
+          }\r
+        }\r
+        Return (0)\r
+      }   \r
+\r
+      Method (_STA, 0)\r
+      {\r
+        if (LEqual (ACC0, 0xff))\r
+        {\r
+            Return (0)\r
+        }\r
+        Return (0x0f)\r
+      }\r
+\r
+      //\r
+      // TCG Hardware Information\r
+      //\r
+      Method (HINF, 3, Serialized, 0, {BuffObj, PkgObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj\r
+      {\r
+        //\r
+        // Switch by function index\r
+        //\r
+        Switch (ToInteger(Arg1))\r
+        {\r
+          Case (0)\r
+          {\r
+            //\r
+            // Standard query\r
+            //\r
+            Return (Buffer () {0x03})\r
+          }\r
+          Case (1)\r
+          {\r
+            //\r
+            // Return failure if no TPM present\r
+            //\r
+            Name(TPMV, Package () {0x01, Package () {0x2, 0x0}})\r
+            if (LEqual (_STA (), 0x00))\r
+            {\r
+              Return (Package () {0x00})\r
+            }\r
+\r
+            //\r
+            // Return TPM version\r
+            //\r
+            Return (TPMV)\r
+          }\r
+          Default {BreakPoint}\r
+        }\r
+        Return (Buffer () {0})\r
+      }\r
+\r
+      Name(TPM2, Package (0x02){\r
+        Zero, \r
+        Zero\r
+      })\r
+\r
+      Name(TPM3, Package (0x03){\r
+        Zero, \r
+        Zero,\r
+        Zero\r
+      })\r
+\r
+      //\r
+      // TCG Physical Presence Interface\r
+      //\r
+      Method (TPPI, 3, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj\r
+      {        \r
+        //\r
+        // Switch by function index\r
+        //\r
+        Switch (ToInteger(Arg1))\r
+        {\r
+          Case (0)\r
+          {\r
+            //\r
+            // Standard query, supports function 1-8\r
+            //\r
+            Return (Buffer () {0xFF, 0x01})\r
+          }\r
+          Case (1)\r
+          {\r
+            //\r
+            // a) Get Physical Presence Interface Version\r
+            //\r
+            Return ("1.2")\r
+          }\r
+          Case (2)\r
+          {\r
+            //\r
+            // b) Submit TPM Operation Request to Pre-OS Environment\r
+            //\r
+                  \r
+            Store (DerefOf (Index (Arg2, 0x00)), PPRQ)\r
+            Store (0x02, PPIP)\r
+              \r
+            //\r
+            // Triggle the SMI interrupt\r
+            //\r
+            Store (PPIN, IOB2)\r
+            Return (FRET)\r
+\r
+\r
+          }\r
+          Case (3)\r
+          {\r
+            //\r
+            // c) Get Pending TPM Operation Requested By the OS\r
+            //\r
+                  \r
+            Store (PPRQ, Index (TPM2, 0x01))\r
+            Return (TPM2)\r
+          }\r
+          Case (4)\r
+          {\r
+            //\r
+            // d) Get Platform-Specific Action to Transition to Pre-OS Environment\r
+            //\r
+            Return (2)\r
+          }\r
+          Case (5)\r
+          {\r
+            //\r
+            // e) Return TPM Operation Response to OS Environment\r
+            //\r
+            Store (0x05, PPIP)\r
+                  \r
+            //\r
+            // Triggle the SMI interrupt\r
+            //\r
+            Store (PPIN, IOB2)\r
+                  \r
+            Store (LPPR, Index (TPM3, 0x01))\r
+            Store (PPRP, Index (TPM3, 0x02))\r
+\r
+            Return (TPM3)\r
+          }\r
+          Case (6)\r
+          {\r
+\r
+            //\r
+            // f) Submit preferred user language (Not implemented)\r
+            //\r
+\r
+            Return (3)\r
+\r
+          }\r
+          Case (7)\r
+          {\r
+            //\r
+            // g) Submit TPM Operation Request to Pre-OS Environment 2\r
+            //\r
+            Store (7, PPIP)\r
+            Store (DerefOf (Index (Arg2, 0x00)), PPRQ)\r
+                \r
+            //\r
+            // Triggle the SMI interrupt \r
+            //\r
+            Store (PPIN, IOB2)  \r
+            Return (FRET)\r
+          }\r
+          Case (8)\r
+          {\r
+            //\r
+            // e) Get User Confirmation Status for Operation\r
+            //\r
+            Store (8, PPIP)\r
+            Store (DerefOf (Index (Arg2, 0x00)), PPRQ)\r
+                  \r
+            //\r
+            // Triggle the SMI interrupt\r
+            //\r
+            Store (PPIN, IOB2)\r
+                  \r
+            Return (FRET)\r
+          }\r
+\r
+          Default {BreakPoint}\r
+        }\r
+        Return (1)\r
+      }\r
+\r
+      Method (TMCI, 3, Serialized, 0, IntObj, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj\r
+      {\r
+        //\r
+        // Switch by function index\r
+        //\r
+        Switch (ToInteger (Arg1))\r
+        {\r
+          Case (0)\r
+          {\r
+            //\r
+            // Standard query, supports function 1-1\r
+            //\r
+            Return (Buffer () {0x03})\r
+          }\r
+          Case (1)\r
+          {\r
+            //\r
+            // Save the Operation Value of the Request to MORD (reserved memory)\r
+            //\r
+            Store (DerefOf (Index (Arg2, 0x00)), MORD)\r
+                  \r
+            //\r
+            // Triggle the SMI through ACPI _DSM method.\r
+            //\r
+            Store (0x01, MCIP)\r
+                  \r
+            //\r
+            // Triggle the SMI interrupt\r
+            //\r
+            Store (MCIN, IOB2)\r
+            Return (MRET)\r
+          }\r
+          Default {BreakPoint}\r
+        }\r
+        Return (1)        \r
+      }\r
+\r
+      Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj})\r
+      {\r
+\r
+        //\r
+        // TCG Hardware Information\r
+        //\r
+        If(LEqual(Arg0, ToUUID ("cf8e16a5-c1e8-4e25-b712-4f54a96702c8")))\r
+        {\r
+          Return (HINF (Arg1, Arg2, Arg3))\r
+        }\r
+\r
+        //\r
+        // TCG Physical Presence Interface\r
+        //\r
+        If(LEqual(Arg0, ToUUID ("3dddfaa6-361b-4eb4-a424-8d10089d1653")))\r
+        {\r
+          Return (TPPI (Arg1, Arg2, Arg3))\r
+        }\r
+\r
+        //\r
+        // TCG Memory Clear Interface\r
+        //\r
+        If(LEqual(Arg0, ToUUID ("376054ed-cc13-4675-901c-4756d7f2d45d")))\r
+        {\r
+          Return (TMCI (Arg1, Arg2, Arg3))\r
+        }\r
+\r
+        Return (Buffer () {0})\r
+      }\r
+    }\r
+  }\r
+}\r
diff --git a/SecurityPkg/Tcg/TrEESmm/TrEESmm.c b/SecurityPkg/Tcg/TrEESmm/TrEESmm.c
new file mode 100644 (file)
index 0000000..4826b79
--- /dev/null
@@ -0,0 +1,480 @@
+/** @file\r
+  It updates TPM2 items in ACPI table and registers SMI2 callback\r
+  functions for TrEE physical presence, ClearMemory, and sample\r
+  for dTPM StartMethod.\r
+\r
+  Caution: This module requires additional review when modified.\r
+  This driver will have external input - variable and ACPINvs data in SMM mode.\r
+  This external input must be validated carefully to avoid security issue.\r
+\r
+  PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TrEESmm.h"\r
+\r
+EFI_TPM2_ACPI_TABLE  mTpm2AcpiTemplate = {\r
+  {\r
+    EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,\r
+    sizeof (mTpm2AcpiTemplate),\r
+    EFI_TPM2_ACPI_TABLE_REVISION,\r
+    //\r
+    // Compiler initializes the remaining bytes to 0\r
+    // These fields should be filled in in production\r
+    //\r
+  },\r
+  0, // Flags\r
+  0, // Control Area\r
+  EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod\r
+};\r
+\r
+EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable;\r
+TCG_NVS                    *mTcgNvs;\r
+\r
+/**\r
+  Software SMI callback for TPM physical presence which is called from ACPI method.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  Variable and ACPINvs are external input, so this function will validate\r
+  its data structure to be valid value.\r
+\r
+  @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
+  @param[in]      Context         Points to an optional handler context which was specified when the\r
+                                  handler was registered.\r
+  @param[in, out] CommBuffer      A pointer to a collection of data in memory that will\r
+                                  be conveyed from a non-SMM environment into an SMM environment.\r
+  @param[in, out] CommBufferSize  The size of the CommBuffer.\r
+\r
+  @retval EFI_SUCCESS             The interrupt was handled successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PhysicalPresenceCallback (\r
+  IN EFI_HANDLE                  DispatchHandle,\r
+  IN CONST VOID                  *Context,\r
+  IN OUT VOID                    *CommBuffer,\r
+  IN OUT UINTN                   *CommBufferSize\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  UINTN                          DataSize;\r
+  EFI_TREE_PHYSICAL_PRESENCE     PpData;\r
+  UINT8                          Flags;\r
+  BOOLEAN                        RequestConfirmed;\r
+\r
+  //\r
+  // Get the Physical Presence variable\r
+  //\r
+  DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+  Status = mSmmVariable->SmmGetVariable (\r
+                           TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                           &gEfiTrEEPhysicalPresenceGuid,\r
+                           NULL,\r
+                           &DataSize,\r
+                           &PpData\r
+                           );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "[TPM2] PP callback, Parameter = %x, Request = %x\n", mTcgNvs->PhysicalPresence.Parameter, mTcgNvs->PhysicalPresence.Request));\r
+\r
+  if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {\r
+    mTcgNvs->PhysicalPresence.LastRequest = PpData.LastPPRequest;\r
+    mTcgNvs->PhysicalPresence.Response    = PpData.PPResponse;\r
+  } else if ((mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) \r
+          || (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {\r
+    if (mTcgNvs->PhysicalPresence.Request > TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
+      //\r
+      // This command requires UI to prompt user for Auth data.\r
+      //\r
+      mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_NOT_IMPLEMENTED;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    if (PpData.PPRequest != mTcgNvs->PhysicalPresence.Request) {\r
+      PpData.PPRequest = (UINT8) mTcgNvs->PhysicalPresence.Request;\r
+      DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
+      Status = mSmmVariable->SmmSetVariable (\r
+                               TREE_PHYSICAL_PRESENCE_VARIABLE,\r
+                               &gEfiTrEEPhysicalPresenceGuid,\r
+                               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                               DataSize,\r
+                               &PpData\r
+                               );\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) { \r
+      mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_GENERAL_FAILURE;\r
+      return EFI_SUCCESS;\r
+    }\r
+    mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_SUCCESS;\r
+  } else if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
+    //\r
+    // Get the Physical Presence flags\r
+    //\r
+    DataSize = sizeof (UINT8);\r
+    Status = mSmmVariable->SmmGetVariable (\r
+                             TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
+                             &gEfiTrEEPhysicalPresenceGuid,\r
+                             NULL,\r
+                             &DataSize,\r
+                             &Flags\r
+                             );\r
+    if (EFI_ERROR (Status)) {\r
+      mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_GENERAL_FAILURE;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    RequestConfirmed = FALSE;\r
+\r
+    switch (mTcgNvs->PhysicalPresence.Request) {\r
+\r
+      case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
+      case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
+      case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
+      case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
+        if ((Flags & TREE_FLAG_NO_PPI_CLEAR) != 0) {\r
+          RequestConfirmed = TRUE;\r
+        }\r
+        break;\r
+\r
+      case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
+        RequestConfirmed = TRUE;\r
+        break;\r
+\r
+      case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
+        break;\r
+\r
+      default:\r
+        if (mTcgNvs->PhysicalPresence.Request <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
+          RequestConfirmed = TRUE;\r
+        } else {\r
+          mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_NOT_IMPLEMENTED; \r
+          return EFI_SUCCESS;\r
+        }\r
+        break;\r
+    }\r
+\r
+    if (RequestConfirmed) {\r
+      mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_ALLOWED_AND_PPUSER_NOT_REQUIRED;\r
+    } else {\r
+      mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_ALLOWED_AND_PPUSER_REQUIRED;\r
+    }    \r
+  } \r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Software SMI callback for MemoryClear which is called from ACPI method.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  Variable and ACPINvs are external input, so this function will validate\r
+  its data structure to be valid value.\r
+\r
+  @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
+  @param[in]      Context         Points to an optional handler context which was specified when the\r
+                                  handler was registered.\r
+  @param[in, out] CommBuffer      A pointer to a collection of data in memory that will\r
+                                  be conveyed from a non-SMM environment into an SMM environment.\r
+  @param[in, out] CommBufferSize  The size of the CommBuffer.\r
+\r
+  @retval EFI_SUCCESS             The interrupt was handled successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MemoryClearCallback (\r
+  IN EFI_HANDLE                  DispatchHandle,\r
+  IN CONST VOID                  *Context,\r
+  IN OUT VOID                    *CommBuffer,\r
+  IN OUT UINTN                   *CommBufferSize\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  UINTN                          DataSize;\r
+  UINT8                          MorControl;\r
+\r
+  mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;\r
+  if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {\r
+    MorControl = (UINT8) mTcgNvs->MemoryClear.Request;\r
+  } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {\r
+    DataSize = sizeof (UINT8);\r
+    Status = mSmmVariable->SmmGetVariable (\r
+                             MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+                             &gEfiMemoryOverwriteControlDataGuid,\r
+                             NULL,\r
+                             &DataSize,\r
+                             &MorControl\r
+                             );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;\r
+  }\r
+\r
+  DataSize = sizeof (UINT8);\r
+  Status = mSmmVariable->SmmSetVariable (\r
+                           MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+                           &gEfiMemoryOverwriteControlDataGuid,\r
+                           EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                           DataSize,\r
+                           &MorControl\r
+                           );\r
+  if (EFI_ERROR (Status)) { \r
+    mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Find the operation region in TCG ACPI table by given Name and Size,\r
+  and initialize it if the region is found.\r
+\r
+  @param[in, out] Table          The TPM item in ACPI table.\r
+  @param[in]      Name           The name string to find in TPM table.\r
+  @param[in]      Size           The size of the region to find.\r
+\r
+  @return                        The allocated address for the found region.\r
+\r
+**/\r
+VOID *\r
+AssignOpRegion (\r
+  EFI_ACPI_DESCRIPTION_HEADER    *Table,\r
+  UINT32                         Name,\r
+  UINT16                         Size\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  AML_OP_REGION_32_8             *OpRegion;\r
+  EFI_PHYSICAL_ADDRESS           MemoryAddress;\r
+\r
+  MemoryAddress = SIZE_4GB - 1;\r
+\r
+  //\r
+  // Patch some pointers for the ASL code before loading the SSDT.\r
+  //\r
+  for (OpRegion  = (AML_OP_REGION_32_8 *) (Table + 1);\r
+       OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);\r
+       OpRegion  = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {\r
+    if ((OpRegion->OpRegionOp  == AML_EXT_REGION_OP) && \r
+        (OpRegion->NameString  == Name) &&\r
+        (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&\r
+        (OpRegion->BytePrefix  == AML_BYTE_PREFIX)) {\r
+\r
+      Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);\r
+      ASSERT_EFI_ERROR (Status);\r
+      ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);\r
+      OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;\r
+      OpRegion->RegionLen    = (UINT8) Size;\r
+      break;\r
+    }\r
+  }\r
+\r
+  return (VOID *) (UINTN) MemoryAddress;\r
+}\r
+\r
+/**\r
+  Initialize and publish TPM items in ACPI table.\r
+\r
+  @retval   EFI_SUCCESS     The TCG ACPI table is published successfully.\r
+  @retval   Others          The TCG ACPI table is not published.\r
+\r
+**/\r
+EFI_STATUS\r
+PublishAcpiTable (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;\r
+  UINTN                          TableKey;\r
+  EFI_ACPI_DESCRIPTION_HEADER    *Table;\r
+  UINTN                          TableSize;\r
+\r
+  Status = GetSectionFromFv (\r
+             &gEfiCallerIdGuid,\r
+             EFI_SECTION_RAW,\r
+             0,\r
+             (VOID **) &Table,\r
+             &TableSize\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+\r
+  //\r
+  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
+  //\r
+  TpmMeasureAndLogData(\r
+    0,\r
+    EV_POST_CODE,\r
+    EV_POSTCODE_INFO_ACPI_DATA,\r
+    ACPI_DATA_LEN,\r
+    Table,\r
+    TableSize\r
+    );\r
+\r
+\r
+  ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));\r
+  CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );\r
+  mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
+  ASSERT (mTcgNvs != NULL);\r
+\r
+  //\r
+  // Publish the TPM ACPI table\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  TableKey = 0;\r
+  Status = AcpiTable->InstallAcpiTable (\r
+                        AcpiTable,\r
+                        Table,\r
+                        TableSize,\r
+                        &TableKey\r
+                        );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Publish TPM2 ACPI table\r
+\r
+  @retval   EFI_SUCCESS     The TPM2 ACPI table is published successfully.\r
+  @retval   Others          The TPM2 ACPI table is not published.\r
+\r
+**/\r
+EFI_STATUS\r
+PublishTpm2 (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;\r
+  UINTN                          TableKey;\r
+  UINT64                         OemTableId;\r
+\r
+  //\r
+  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
+  //\r
+  TpmMeasureAndLogData(\r
+    0,\r
+    EV_POST_CODE,\r
+    EV_POSTCODE_INFO_ACPI_DATA,\r
+    ACPI_DATA_LEN,\r
+    &mTpm2AcpiTemplate,\r
+    sizeof(mTpm2AcpiTemplate)\r
+    );\r
+\r
+  CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));\r
+  OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+  CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+  mTpm2AcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+  mTpm2AcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+  mTpm2AcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+\r
+  //\r
+  // Construct ACPI table\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = AcpiTable->InstallAcpiTable (\r
+                        AcpiTable,\r
+                        &mTpm2AcpiTemplate,\r
+                        sizeof(mTpm2AcpiTemplate),\r
+                        &TableKey\r
+                        );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The driver's entry point.\r
+\r
+  It install callbacks for TPM physical presence and MemoryClear, and locate \r
+  SMM variable to be used in the callback function.\r
+\r
+  @param[in] ImageHandle  The firmware allocated handle for the EFI image.  \r
+  @param[in] SystemTable  A pointer to the EFI System Table.\r
+  \r
+  @retval EFI_SUCCESS     The entry point is executed successfully.\r
+  @retval Others          Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeTcgSmm (\r
+  IN EFI_HANDLE                  ImageHandle,\r
+  IN EFI_SYSTEM_TABLE            *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;\r
+  EFI_SMM_SW_REGISTER_CONTEXT    SwContext;\r
+  EFI_HANDLE                     SwHandle;\r
+\r
+  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){\r
+    DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PublishAcpiTable ();\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get the Sw dispatch protocol and register SMI callback functions.\r
+  //\r
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);\r
+  ASSERT_EFI_ERROR (Status);\r
+  SwContext.SwSmiInputValue = (UINTN) -1;\r
+  Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
+\r
+  SwContext.SwSmiInputValue = (UINTN) -1;\r
+  Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
+  \r
+  //\r
+  // Locate SmmVariableProtocol.\r
+  //\r
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Set TPM2 ACPI table\r
+  //\r
+  Status = PublishTpm2 ();\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/SecurityPkg/Tcg/TrEESmm/TrEESmm.h b/SecurityPkg/Tcg/TrEESmm/TrEESmm.h
new file mode 100644 (file)
index 0000000..8f4117e
--- /dev/null
@@ -0,0 +1,117 @@
+/** @file\r
+  The header file for TrEE SMM driver.\r
+  \r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __TREE_SMM_H__\r
+#define __TREE_SMM_H__\r
+\r
+#include <PiDxe.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/Tpm2Acpi.h>\r
+\r
+#include <Guid/TrEEPhysicalPresenceData.h>\r
+#include <Guid/MemoryOverwriteControl.h>\r
+#include <Guid/TpmInstance.h>\r
+\r
+#include <Protocol/SmmSwDispatch2.h>\r
+#include <Protocol/AcpiTable.h>\r
+#include <Protocol/SmmVariable.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/SmmServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  UINT8                  SoftwareSmi;\r
+  UINT32                 Parameter;\r
+  UINT32                 Response;\r
+  UINT32                 Request;\r
+  UINT32                 LastRequest;\r
+  UINT32                 ReturnCode;\r
+} PHYSICAL_PRESENCE_NVS;\r
+\r
+typedef struct {\r
+  UINT8                  SoftwareSmi;\r
+  UINT32                 Parameter;\r
+  UINT32                 Request;\r
+  UINT32                 ReturnCode;\r
+} MEMORY_CLEAR_NVS;\r
+\r
+typedef struct {\r
+  PHYSICAL_PRESENCE_NVS  PhysicalPresence;\r
+  MEMORY_CLEAR_NVS       MemoryClear;\r
+} TCG_NVS;\r
+\r
+typedef struct {\r
+  UINT8                  OpRegionOp;\r
+  UINT32                 NameString;\r
+  UINT8                  RegionSpace;\r
+  UINT8                  DWordPrefix;\r
+  UINT32                 RegionOffset;\r
+  UINT8                  BytePrefix;\r
+  UINT8                  RegionLen;\r
+} AML_OP_REGION_32_8;\r
+#pragma pack()\r
+\r
+//\r
+// The definition for TCG physical presence ACPI function\r
+//\r
+#define ACPI_FUNCTION_GET_PHYSICAL_PRESENCE_INTERFACE_VERSION      1\r
+#define ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS                       2\r
+#define ACPI_FUNCTION_GET_PENDING_REQUEST_BY_OS                    3\r
+#define ACPI_FUNCTION_GET_PLATFORM_ACTION_TO_TRANSITION_TO_BIOS    4\r
+#define ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS                5\r
+#define ACPI_FUNCTION_SUBMIT_PREFERRED_USER_LANGUAGE               6\r
+#define ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2                     7\r
+#define ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST     8\r
+\r
+//\r
+// The return code for Get User Confirmation Status for Operation\r
+//\r
+#define PP_REQUEST_NOT_IMPLEMENTED                                 0\r
+#define PP_REQUEST_BIOS_ONLY                                       1\r
+#define PP_REQUEST_BLOCKED                                         2\r
+#define PP_REQUEST_ALLOWED_AND_PPUSER_REQUIRED                     3\r
+#define PP_REQUEST_ALLOWED_AND_PPUSER_NOT_REQUIRED                 4\r
+\r
+//\r
+// The return code for Sumbit TPM Request to Pre-OS Environment\r
+// and Sumbit TPM Request to Pre-OS Environment 2\r
+//\r
+#define PP_SUBMIT_REQUEST_SUCCESS                                  0\r
+#define PP_SUBMIT_REQUEST_NOT_IMPLEMENTED                          1\r
+#define PP_SUBMIT_REQUEST_GENERAL_FAILURE                          2\r
+#define PP_SUBMIT_REQUEST_BLOCKED_BY_BIOS_SETTINGS                 3\r
+\r
+\r
+//\r
+// The definition for TCG MOR\r
+//\r
+#define ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE                   1\r
+#define ACPI_FUNCTION_PTS_CLEAR_MOR_BIT                            2\r
+\r
+//\r
+// The return code for Memory Clear Interface Functions\r
+//\r
+#define MOR_REQUEST_SUCCESS                                        0\r
+#define MOR_REQUEST_GENERAL_FAILURE                                1\r
+\r
+#endif  // __TCG_SMM_H__\r
diff --git a/SecurityPkg/Tcg/TrEESmm/TrEESmm.inf b/SecurityPkg/Tcg/TrEESmm/TrEESmm.inf
new file mode 100644 (file)
index 0000000..bb251d4
--- /dev/null
@@ -0,0 +1,71 @@
+## @file\r
+#  This driver implements TPM2 definition block in ACPI table and \r
+#  registers SMI callback functions for TrEE physical presence and \r
+#  MemoryClear to handle the requests from ACPI method.\r
+#\r
+#  Caution: This module requires additional review when modified.\r
+#  This driver will have external input - variable and ACPINvs data in SMM mode.\r
+#  This external input must be validated carefully to avoid security issue.\r
+#\r
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = TrEESmm\r
+  FILE_GUID                      = 114B7105-6CC9-453c-BADC-16DF227BB4EF\r
+  MODULE_TYPE                    = DXE_SMM_DRIVER\r
+  PI_SPECIFICATION_VERSION       = 0x0001000A\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = InitializeTcgSmm\r
+\r
+[Sources]\r
+  TrEESmm.h\r
+  TrEESmm.c\r
+  Tpm.asl\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  UefiDriverEntryPoint\r
+  SmmServicesTableLib\r
+  UefiBootServicesTableLib\r
+  DebugLib\r
+  DxeServicesLib\r
+  TpmMeasurementLib\r
+  Tpm2DeviceLib\r
+\r
+[Guids]\r
+  gEfiTrEEPhysicalPresenceGuid\r
+  gEfiMemoryOverwriteControlDataGuid\r
+  gEfiTpmDeviceInstanceTpm20DtpmGuid\r
+\r
+[Protocols]\r
+  gEfiSmmSwDispatch2ProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSmmVariableProtocolGuid                   # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision\r
+\r
+[Depex]\r
+  gEfiAcpiTableProtocolGuid AND\r
+  gEfiSmmSwDispatch2ProtocolGuid AND\r
+  gEfiSmmVariableProtocolGuid\r
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Measurement.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Measurement.c
new file mode 100644 (file)
index 0000000..41e9b6f
--- /dev/null
@@ -0,0 +1,255 @@
+/** @file\r
+  Measure TrEE required variable.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Guid/ImageAuthentication.h>\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+\r
+typedef struct {\r
+  CHAR16                                 *VariableName;\r
+  EFI_GUID                               *VendorGuid;\r
+} VARIABLE_TYPE;\r
+\r
+VARIABLE_TYPE  mVariableType[] = {\r
+  {EFI_SECURE_BOOT_MODE_NAME,    &gEfiGlobalVariableGuid},\r
+  {EFI_PLATFORM_KEY_NAME,        &gEfiGlobalVariableGuid},\r
+  {EFI_KEY_EXCHANGE_KEY_NAME,    &gEfiGlobalVariableGuid},\r
+  {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},\r
+  {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},\r
+};\r
+\r
+/**\r
+  This function will return if this variable is SecureBootPolicy Variable.\r
+\r
+  @param[in]  VariableName      A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+\r
+  @retval TRUE  This is SecureBootPolicy Variable\r
+  @retval FALSE This is not SecureBootPolicy Variable\r
+**/\r
+BOOLEAN\r
+IsSecureBootPolicyVariable (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  )\r
+{\r
+  UINTN   Index;\r
+\r
+  for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
+    if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) && \r
+        (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {\r
+      return TRUE;\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+  @param[in]  VarData           The content of the variable data.  \r
+  @param[in]  VarSize           The size of the variable data.  \r
\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MeasureVariable (\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  IN      VOID                      *VarData,\r
+  IN      UINTN                     VarSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             VarNameLength;\r
+  EFI_VARIABLE_DATA_TREE            *VarLog;\r
+  UINT32                            VarLogSize;\r
+\r
+  ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));\r
+\r
+  VarNameLength      = StrLen (VarName);\r
+  VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
+                        - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
+\r
+  VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize);\r
+  if (VarLog == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName));\r
+  VarLog->UnicodeNameLength  = VarNameLength;\r
+  VarLog->VariableDataLength = VarSize;\r
+  CopyMem (\r
+     VarLog->UnicodeName,\r
+     VarName,\r
+     VarNameLength * sizeof (*VarName)\r
+     );\r
+  if (VarSize != 0) {\r
+    CopyMem (\r
+       (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
+       VarData,\r
+       VarSize\r
+       );\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "AuthVariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));\r
+  DEBUG ((EFI_D_ERROR, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
+\r
+  Status = TpmMeasureAndLogData (\r
+             7,\r
+             EV_EFI_VARIABLE_DRIVER_CONFIG,\r
+             VarLog,\r
+             VarLogSize,\r
+             VarLog,\r
+             VarLogSize\r
+             );\r
+  FreePool (VarLog);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Returns the status whether get the variable success. The function retrieves \r
+  variable  through the UEFI Runtime Service GetVariable().  The \r
+  returned buffer is allocated using AllocatePool().  The caller is responsible\r
+  for freeing this buffer with FreePool().\r
+\r
+  This API is only invoked in boot time. It may NOT be invoked at runtime.\r
+\r
+  @param[in]  Name  The pointer to a Null-terminated Unicode string.\r
+  @param[in]  Guid  The pointer to an EFI_GUID structure\r
+  @param[out] Value The buffer point saved the variable info.\r
+  @param[out] Size  The buffer size of the variable.\r
+\r
+  @return EFI_OUT_OF_RESOURCES      Allocate buffer failed.\r
+  @return EFI_SUCCESS               Find the specified variable.\r
+  @return Others Errors             Return errors from call to gRT->GetVariable.\r
+\r
+**/\r
+EFI_STATUS\r
+InternalGetVariable (\r
+  IN CONST CHAR16    *Name,\r
+  IN CONST EFI_GUID  *Guid,\r
+  OUT VOID           **Value,\r
+  OUT UINTN          *Size\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       BufferSize;\r
+\r
+  //\r
+  // Try to get the variable size.\r
+  //\r
+  BufferSize = 0;\r
+  *Value     = NULL;\r
+  if (Size != NULL) {\r
+    *Size  = 0;\r
+  }\r
+  \r
+  Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Allocate buffer to get the variable.\r
+  //\r
+  *Value = AllocatePool (BufferSize);\r
+  ASSERT (*Value != NULL);\r
+  if (*Value == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Get the variable data.\r
+  //\r
+  Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool(*Value);\r
+    *Value = NULL;\r
+  }\r
+\r
+  if (Size != NULL) {\r
+    *Size = BufferSize;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  SecureBoot Hook for SetVariable.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             VariableDataSize;\r
+  VOID                              *VariableData;\r
+\r
+  if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) {\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // We should NOT use Data and DataSize here,because it may include signature,\r
+  // or is just partial with append attributes, or is deleted.\r
+  // We should GetVariable again, to get full variable content.\r
+  //\r
+  Status = InternalGetVariable (\r
+             VariableName,\r
+             VendorGuid,\r
+             &VariableData,\r
+             &VariableDataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    VariableData     = NULL;\r
+    VariableDataSize = 0;\r
+  }\r
+\r
+  Status = MeasureVariable (\r
+             VariableName,\r
+             VendorGuid,\r
+             VariableData,\r
+             VariableDataSize\r
+             );\r
+  DEBUG ((EFI_D_ERROR, "MeasureBootPolicyVariable - %r\n", Status));\r
+\r
+  if (VariableData != NULL) {\r
+    FreePool (VariableData);\r
+  }\r
+\r
+  return ;\r
+}\r
index c99cd2310eefb2bed1f056232943f470a1c900f2..a0419f080de75ab5ec211117c966a5d9c1a63660 100644 (file)
@@ -104,6 +104,20 @@ GLOBAL_VARIABLE_ENTRY mGlobalVariableList2[] = {
   {L"Key####",                               VARIABLE_ATTRIBUTE_NV_BS_RT},\r
 };\r
 \r
+/**\r
+\r
+  SecureBoot Hook for auth variable update.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  );\r
+\r
 /**\r
   Routine used to track statistical information about variable usage.\r
   The data is stored in the EFI system table so it can be accessed later.\r
@@ -2981,6 +2995,15 @@ Done:
   InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);\r
   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
+  if (!AtRuntime ()) {\r
+    if (!EFI_ERROR (Status)) {\r
+      SecureBootHook (\r
+        VariableName,\r
+        VendorGuid\r
+        );\r
+    }\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
index 7f8c28ec72341864f48ee4a1ed482aaf34db1a04..47064647fcfe61dccdd943ba86bedfd5e6dc2af9 100644 (file)
@@ -39,6 +39,7 @@
   Variable.h\r
   AuthService.c\r
   AuthService.h\r
+  Measurement.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
@@ -61,6 +62,7 @@
   BaseCryptLib\r
   PlatformSecureLib\r
   HobLib\r
+  TpmMeasurementLib\r
 \r
 [Protocols]\r
   gEfiFirmwareVolumeBlockProtocolGuid           ## SOMETIMES_CONSUMES\r
index eaef8d182c8a49f7361d11ae075b1764dce31e46..4ac582d49b54dc73c9e799881648ae20b9f52c7f 100644 (file)
@@ -50,6 +50,23 @@ UINTN                                                mVariableBufferPayloadSize;
 extern BOOLEAN                                       mEndOfDxe;\r
 extern BOOLEAN                                       mEnableLocking;\r
 \r
+/**\r
+  SecureBoot Hook for SetVariable.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  )\r
+{\r
+  return ;\r
+}\r
+\r
 /**\r
 \r
   This code sets variable in storage blocks (Volatile or Non-Volatile).\r
index 7011343872d9a7c9586b377464d148da46149fb9..f550c67beec62162edc3e14eaf90e04131c98435 100644 (file)
@@ -57,6 +57,20 @@ UINTN                            mVariableBufferPayloadSize;
 EFI_LOCK                         mVariableServicesLock;\r
 EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;\r
 \r
+/**\r
+  SecureBoot Hook for SetVariable.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  );\r
+\r
 /**\r
   Acquires lock only at boot time. Simply returns at runtime.\r
 \r
@@ -545,6 +559,15 @@ RuntimeServiceSetVariable (
 \r
 Done:\r
   ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+  if (!EfiAtRuntime ()) {\r
+    if (!EFI_ERROR (Status)) {\r
+      SecureBootHook (\r
+        VariableName,\r
+        VendorGuid\r
+        );\r
+    }\r
+  }\r
   return Status;\r
 }\r
 \r
index a28702765b4a677c51012ab8101fc7d32776012b..807e99a7815580401a9da6d98882dc2fc406a458 100644 (file)
@@ -38,6 +38,7 @@
 \r
 [Sources]\r
   VariableSmmRuntimeDxe.c\r
+  Measurement.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
@@ -53,6 +54,7 @@
   DxeServicesTableLib\r
   UefiDriverEntryPoint\r
   PcdLib  \r
+  TpmMeasurementLib\r
 \r
 [Protocols]\r
   gEfiVariableWriteArchProtocolGuid             ## ALWAYS_PRODUCES\r
@@ -64,6 +66,7 @@
 [Guids]\r
   gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event\r
   gSmmVariableWriteGuid\r
+  gEfiImageSecurityDatabaseGuid\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize\r