--- /dev/null
+/** @file\r
+ If the Variable services have PcdVariableCollectStatistics set to TRUE then \r
+ this utility will print out the statistics information. You can use console \r
+ redirection to capture the data.\r
+ \r
+Copyright (c) 2009 - 2011, 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/UefiLib.h>\r
+#include <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Guid/AuthenticatedVariableFormat.h>\r
+#include <Guid/SmmVariableCommon.h>\r
+#include <Protocol/SmmCommunication.h>\r
+#include <Protocol/SmmVariable.h>\r
+\r
+#define EFI_VARIABLE_GUID \\r
+ { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d } }\r
+\r
+EFI_GUID mEfiVariableGuid = EFI_VARIABLE_GUID;\r
+EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;\r
+\r
+/**\r
+\r
+ This function get the variable statistics data from SMM variable driver. \r
+\r
+ @param[in, out] SmmCommunicateHeader In input, a pointer to a collection of data that will\r
+ be passed into an SMM environment. In output, a pointer \r
+ to a collection of data that comes from an SMM environment.\r
+ @param[in, out] SmmCommunicateSize The size of the SmmCommunicateHeader.\r
+ \r
+ @retval EFI_SUCCESS Get the statistics data information.\r
+ @retval EFI_NOT_FOUND Not found.\r
+ @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetVariableStatisticsData (\r
+ IN OUT EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader,\r
+ IN OUT UINTN *SmmCommunicateSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
+\r
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
+ SmmCommunicateHeader->MessageLength = *SmmCommunicateSize - OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
+\r
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) &SmmCommunicateHeader->Data[0];\r
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_STATISTICS;\r
+ \r
+ Status = mSmmCommunication->Communicate (mSmmCommunication, SmmCommunicateHeader, SmmCommunicateSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ Status = SmmVariableFunctionHeader->ReturnStatus; \r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+ This function get and print the variable statistics data from SMM variable driver. \r
+ \r
+ @retval EFI_SUCCESS Print the statistics information successfully.\r
+ @retval EFI_NOT_FOUND Not found the statistics information.\r
+\r
+**/\r
+EFI_STATUS\r
+PrintInfoFromSmm (\r
+ VOID \r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_INFO_ENTRY *VariableInfo;\r
+ EFI_SMM_COMMUNICATE_HEADER *CommBuffer;\r
+ UINTN RealCommSize;\r
+ UINTN CommSize;\r
+ SMM_VARIABLE_COMMUNICATE_HEADER *FunctionHeader;\r
+ EFI_SMM_VARIABLE_PROTOCOL *Smmvariable;\r
+ \r
+\r
+ Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &Smmvariable);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } \r
+\r
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
+ RealCommSize = CommSize;\r
+ CommBuffer = AllocateZeroPool (CommSize);\r
+ ASSERT (CommBuffer != NULL);\r
+ \r
+ Print (L"Non-Volatile SMM Variables:\n");\r
+ do {\r
+ Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (CommBuffer);\r
+ CommBuffer = AllocateZeroPool (CommSize);\r
+ ASSERT (CommBuffer != NULL);\r
+ RealCommSize = CommSize;\r
+ Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
+ }\r
+\r
+ if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) { \r
+ break;\r
+ }\r
+\r
+ if (CommSize < RealCommSize) {\r
+ CommSize = RealCommSize;\r
+ }\r
+\r
+ FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;\r
+ VariableInfo = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;\r
+\r
+ if (!VariableInfo->Volatile) {\r
+ Print (\r
+ L"%g R%03d(%03d) W%03d D%03d:%s\n", \r
+ &VariableInfo->VendorGuid, \r
+ VariableInfo->ReadCount,\r
+ VariableInfo->CacheCount,\r
+ VariableInfo->WriteCount,\r
+ VariableInfo->DeleteCount,\r
+ (CHAR16 *)(VariableInfo + 1)\r
+ );\r
+ }\r
+ } while (TRUE);\r
+ \r
+ Print (L"Volatile SMM Variables:\n");\r
+ ZeroMem (CommBuffer, CommSize);\r
+ do {\r
+ Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (CommBuffer);\r
+ CommBuffer = AllocateZeroPool (CommSize);\r
+ ASSERT (CommBuffer != NULL);\r
+ RealCommSize = CommSize;\r
+ Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
+ }\r
+\r
+ if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) { \r
+ break;\r
+ }\r
+\r
+ if (CommSize < RealCommSize) {\r
+ CommSize = RealCommSize;\r
+ }\r
+\r
+ FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;\r
+ VariableInfo = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;\r
+\r
+ if (VariableInfo->Volatile) {\r
+ Print (\r
+ L"%g R%03d(%03d) W%03d D%03d:%s\n", \r
+ &VariableInfo->VendorGuid, \r
+ VariableInfo->ReadCount,\r
+ VariableInfo->CacheCount,\r
+ VariableInfo->WriteCount,\r
+ VariableInfo->DeleteCount,\r
+ (CHAR16 *)(VariableInfo + 1)\r
+ );\r
+ }\r
+ } while (TRUE);\r
+\r
+ FreePool (CommBuffer); \r
+ return Status;\r
+}\r
+\r
+/**\r
+ The user Entry Point for Application. The user code starts with this function\r
+ as the real entry point for the image goes into a library that calls this \r
+ 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 other Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UefiMain (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_INFO_ENTRY *VariableInfo;\r
+ VARIABLE_INFO_ENTRY *Entry;\r
+\r
+ Status = EfiGetSystemConfigurationTable (&mEfiVariableGuid, (VOID **)&Entry);\r
+ if (EFI_ERROR (Status) || (Entry == NULL)) {\r
+ Status = EfiGetSystemConfigurationTable (&gEfiAuthenticatedVariableGuid, (VOID **)&Entry);\r
+ }\r
+\r
+ if (EFI_ERROR (Status) || (Entry == NULL)) {\r
+ Status = PrintInfoFromSmm ();\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } \r
+\r
+ if (!EFI_ERROR (Status) && (Entry != NULL)) {\r
+ Print (L"Non-Volatile EFI Variables:\n");\r
+ VariableInfo = Entry;\r
+ do {\r
+ if (!VariableInfo->Volatile) {\r
+ Print (\r
+ L"%g R%03d(%03d) W%03d D%03d:%s\n", \r
+ &VariableInfo->VendorGuid, \r
+ VariableInfo->ReadCount,\r
+ VariableInfo->CacheCount,\r
+ VariableInfo->WriteCount,\r
+ VariableInfo->DeleteCount,\r
+ VariableInfo->Name\r
+ );\r
+ }\r
+\r
+ VariableInfo = VariableInfo->Next;\r
+ } while (VariableInfo != NULL);\r
+\r
+ Print (L"Volatile EFI Variables:\n");\r
+ VariableInfo = Entry;\r
+ do {\r
+ if (VariableInfo->Volatile) {\r
+ Print (\r
+ L"%g R%03d(%03d) W%03d D%03d:%s\n", \r
+ &VariableInfo->VendorGuid, \r
+ VariableInfo->ReadCount,\r
+ VariableInfo->CacheCount,\r
+ VariableInfo->WriteCount,\r
+ VariableInfo->DeleteCount,\r
+ VariableInfo->Name\r
+ );\r
+ }\r
+ VariableInfo = VariableInfo->Next;\r
+ } while (VariableInfo != NULL);\r
+\r
+ } else {\r
+ Print (L"Warning: Variable Dxe driver doesn't enable the feature of statistical information!\n");\r
+ Print (L"If you want to see this info, please:\n");\r
+ Print (L" 1. Set PcdVariableCollectStatistics as TRUE\n");\r
+ Print (L" 2. Rebuild Variable Dxe driver\n");\r
+ Print (L" 3. Run \"VariableInfo\" cmd again\n");\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+## @file\r
+# This is a shell application that will display statistical information \r
+# about variable usage.\r
+# Note that if Variable Dxe driver doesn't enable the feature by setting \r
+# PcdVariableCollectStatistics as TRUE, The application will not display \r
+# variable statistical information.\r
+#\r
+# Copyright (c) 2009 - 2011, 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 = VariableInfo\r
+ FILE_GUID = B9EF901F-A2A2-4fc8-8D2B-3A2E07B301CC\r
+ MODULE_TYPE = UEFI_APPLICATION\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = UefiMain\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
+ VariableInfo.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiApplicationEntryPoint\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ MemoryAllocationLib\r
+\r
+[Protocols]\r
+ gEfiSmmCommunicationProtocolGuid\r
+ gEfiSmmVariableProtocolGuid\r
+ \r
+[Guids]\r
+ gEfiAuthenticatedVariableGuid ## CONSUMES ## Configuration Table Guid\r
+ \r
--- /dev/null
+/** @file\r
+ The variable data structures are related to EDKII-specific \r
+ implementation of UEFI authenticated variables.\r
+ AuthenticatedVariableFormat.h defines variable data headers \r
+ and variable storage region headers.\r
+\r
+Copyright (c) 2009 - 2011, 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 __AUTHENTICATED_VARIABLE_FORMAT_H__\r
+#define __AUTHENTICATED_VARIABLE_FORMAT_H__\r
+\r
+#define EFI_AUTHENTICATED_VARIABLE_GUID \\r
+ { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }\r
+\r
+extern EFI_GUID gEfiAuthenticatedVariableGuid;\r
+\r
+///\r
+/// Alignment of variable name and data, according to the architecture:\r
+/// * For IA-32 and Intel(R) 64 architectures: 1.\r
+/// * For IA-64 architecture: 8.\r
+///\r
+#if defined (MDE_CPU_IPF)\r
+#define ALIGNMENT 8\r
+#else\r
+#define ALIGNMENT 1\r
+#endif\r
+\r
+//\r
+// GET_PAD_SIZE calculates the miminal pad bytes needed to make the current pad size satisfy the alignment requirement.\r
+//\r
+#if (ALIGNMENT == 1)\r
+#define GET_PAD_SIZE(a) (0)\r
+#else\r
+#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1))\r
+#endif\r
+\r
+///\r
+/// Alignment of Variable Data Header in Variable Store region.\r
+///\r
+#define HEADER_ALIGNMENT 4\r
+#define HEADER_ALIGN(Header) (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1)))\r
+\r
+///\r
+/// Status of Variable Store Region.\r
+///\r
+typedef enum {\r
+ EfiRaw,\r
+ EfiValid,\r
+ EfiInvalid,\r
+ EfiUnknown\r
+} VARIABLE_STORE_STATUS;\r
+\r
+#pragma pack(1)\r
+\r
+#define VARIABLE_STORE_SIGNATURE EFI_AUTHENTICATED_VARIABLE_GUID\r
+\r
+///\r
+/// Variable Store Header Format and State.\r
+///\r
+#define VARIABLE_STORE_FORMATTED 0x5a\r
+#define VARIABLE_STORE_HEALTHY 0xfe\r
+\r
+///\r
+/// Variable Store region header.\r
+///\r
+typedef struct {\r
+ ///\r
+ /// Variable store region signature.\r
+ ///\r
+ EFI_GUID Signature;\r
+ ///\r
+ /// Size of entire variable store, \r
+ /// including size of variable store header but not including the size of FvHeader.\r
+ ///\r
+ UINT32 Size;\r
+ ///\r
+ /// Variable region format state.\r
+ ///\r
+ UINT8 Format;\r
+ ///\r
+ /// Variable region healthy state.\r
+ ///\r
+ UINT8 State;\r
+ UINT16 Reserved;\r
+ UINT32 Reserved1;\r
+} VARIABLE_STORE_HEADER;\r
+\r
+///\r
+/// Variable data start flag.\r
+///\r
+#define VARIABLE_DATA 0x55AA\r
+\r
+///\r
+/// Variable State flags.\r
+///\r
+#define VAR_IN_DELETED_TRANSITION 0xfe ///< Variable is in obsolete transition.\r
+#define VAR_DELETED 0xfd ///< Variable is obsolete.\r
+#define VAR_HEADER_VALID_ONLY 0x7f ///< Variable header has been valid.\r
+#define VAR_ADDED 0x3f ///< Variable has been completely added.\r
+\r
+///\r
+/// Single Variable Data Header Structure.\r
+///\r
+typedef struct {\r
+ ///\r
+ /// Variable Data Start Flag.\r
+ ///\r
+ UINT16 StartId;\r
+ ///\r
+ /// Variable State defined above.\r
+ ///\r
+ UINT8 State;\r
+ UINT8 Reserved;\r
+ ///\r
+ /// Attributes of variable defined in UEFI specification.\r
+ ///\r
+ UINT32 Attributes;\r
+ ///\r
+ /// Associated monotonic count value against replay attack.\r
+ ///\r
+ UINT64 MonotonicCount;\r
+ ///\r
+ /// Associated TimeStamp value against replay attack. \r
+ ///\r
+ EFI_TIME TimeStamp;\r
+ ///\r
+ /// Index of associated public key in database.\r
+ ///\r
+ UINT32 PubKeyIndex;\r
+ ///\r
+ /// Size of variable null-terminated Unicode string name.\r
+ ///\r
+ UINT32 NameSize;\r
+ ///\r
+ /// Size of the variable data without this header.\r
+ ///\r
+ UINT32 DataSize;\r
+ ///\r
+ /// A unique identifier for the vendor that produces and consumes this varaible.\r
+ ///\r
+ EFI_GUID VendorGuid;\r
+} VARIABLE_HEADER;\r
+\r
+#pragma pack()\r
+\r
+typedef struct _VARIABLE_INFO_ENTRY VARIABLE_INFO_ENTRY;\r
+\r
+///\r
+/// This structure contains the variable list that is put in EFI system table.\r
+/// The variable driver collects all variables that were used at boot service time and produces this list.\r
+/// This is an optional feature to dump all used variables in shell environment. \r
+///\r
+struct _VARIABLE_INFO_ENTRY {\r
+ VARIABLE_INFO_ENTRY *Next; ///< Pointer to next entry.\r
+ EFI_GUID VendorGuid; ///< Guid of Variable.\r
+ CHAR16 *Name; ///< Name of Variable. \r
+ UINT32 Attributes; ///< Attributes of variable defined in UEFI spec.\r
+ UINT32 ReadCount; ///< Number of times to read this variable.\r
+ UINT32 WriteCount; ///< Number of times to write this variable.\r
+ UINT32 DeleteCount; ///< Number of times to delete this variable.\r
+ UINT32 CacheCount; ///< Number of times that cache hits this variable.\r
+ BOOLEAN Volatile; ///< TRUE if volatile, FALSE if non-volatile.\r
+};\r
+\r
+#endif // __AUTHENTICATED_VARIABLE_FORMAT_H__\r
--- /dev/null
+/** @file\r
+ Define the variable data structures used for TCG physical presence.\r
+ The TPM request from firmware or OS is saved to variable. And it is\r
+ cleared after it is processed in the next boot cycle. The TPM response \r
+ is saved to variable.\r
+\r
+Copyright (c) 2006 - 2011, 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 __PHYSICAL_PRESENCE_DATA_GUID_H__\r
+#define __PHYSICAL_PRESENCE_DATA_GUID_H__\r
+\r
+#define EFI_PHYSICAL_PRESENCE_DATA_GUID \\r
+ { \\r
+ 0xf6499b1, 0xe9ad, 0x493d, { 0xb9, 0xc2, 0x2f, 0x90, 0x81, 0x5c, 0x6c, 0xbc }\\r
+ }\r
+\r
+#define PHYSICAL_PRESENCE_VARIABLE L"PhysicalPresence"\r
+\r
+typedef struct {\r
+ UINT8 PPRequest; ///< Physical Presence request command.\r
+ UINT8 LastPPRequest;\r
+ UINT32 PPResponse;\r
+ UINT8 Flags;\r
+} EFI_PHYSICAL_PRESENCE;\r
+\r
+//\r
+// The definition bit of the flags\r
+//\r
+#define FLAG_NO_PPI_PROVISION BIT0\r
+#define FLAG_NO_PPI_CLEAR BIT1\r
+#define FLAG_NO_PPI_MAINTENANCE BIT2\r
+#define FLAG_RESET_TRACK BIT3\r
+\r
+#define H2NS(x) ((((x) << 8) | ((x) >> 8)) & 0xffff)\r
+#define H2NL(x) (H2NS ((x) >> 16) | (H2NS ((x) & 0xffff) << 16))\r
+\r
+//\r
+// The definition of physical presence operation actions\r
+//\r
+#define NO_ACTION 0\r
+#define ENABLE 1\r
+#define DISABLE 2\r
+#define ACTIVATE 3\r
+#define DEACTIVATE 4 \r
+#define CLEAR 5\r
+#define ENABLE_ACTIVATE 6\r
+#define DEACTIVATE_DISABLE 7\r
+#define SET_OWNER_INSTALL_TRUE 8\r
+#define SET_OWNER_INSTALL_FALSE 9\r
+#define ENABLE_ACTIVATE_OWNER_TRUE 10\r
+#define DEACTIVATE_DISABLE_OWNER_FALSE 11\r
+#define DEFERRED_PP_UNOWNERED_FIELD_UPGRADE 12\r
+#define SET_OPERATOR_AUTH 13\r
+#define CLEAR_ENABLE_ACTIVATE 14\r
+#define SET_NO_PPI_PROVISION_FALSE 15\r
+#define SET_NO_PPI_PROVISION_TRUE 16\r
+#define SET_NO_PPI_CLEAR_FALSE 17\r
+#define SET_NO_PPI_CLEAR_TRUE 18\r
+#define SET_NO_PPI_MAINTENANCE_FALSE 19\r
+#define SET_NO_PPI_MAINTENANCE_TRUE 20\r
+#define ENABLE_ACTIVATE_CLEAR 21\r
+#define ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE 22\r
+\r
+extern EFI_GUID gEfiPhysicalPresenceGuid;\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ GUID for SecurityPkg PCD Token Space.\r
+\r
+Copyright (c) 2009 - 2010, 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 _SECURITYPKG_TOKEN_SPACE_GUID_H_\r
+#define _SECURITYPKG_TOKEN_SPACE_GUID_H_\r
+\r
+#define SECURITYPKG_TOKEN_SPACE_GUID \\r
+ { \\r
+ 0xd3fb176, 0x9569, 0x4d51, { 0xa3, 0xef, 0x7d, 0x61, 0xc6, 0x4f, 0xea, 0xba } \\r
+ }\r
+\r
+extern EFI_GUID gEfiSecurityPkgTokenSpaceGuid;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Defines the HOB GUID used to pass a TCG_PCR_EVENT from a TPM PEIM to \r
+ a TPM DXE Driver. A GUIDed HOB is generated for each measurement \r
+ made in the PEI Phase.\r
+ \r
+Copyright (c) 2007 - 2010, 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 _TCG_EVENT_HOB_H_\r
+#define _TCG_EVENT_HOB_H_\r
+\r
+///\r
+/// The Global ID of a GUIDed HOB used to pass a TCG_PCR_EVENT from a TPM PEIM to a TPM DXE Driver.\r
+///\r
+#define EFI_TCG_EVENT_HOB_GUID \\r
+ { \\r
+ 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 } \\r
+ }\r
+\r
+extern EFI_GUID gTcgEventEntryHobGuid;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Provides a secure platform-specific method to clear PK(Platform Key).\r
+\r
+Copyright (c) 2011, 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 __PLATFORM_SECURE_LIB_H__\r
+#define __PLATFORM_SECURE_LIB_H__\r
+\r
+\r
+/**\r
+\r
+ This function detects whether a secure platform-specific method to clear PK(Platform Key)\r
+ is configured by platform owner. This method is provided for users force to clear PK \r
+ in case incorrect enrollment mis-haps.\r
+ \r
+ UEFI231 spec chapter 27.5.2 stipulates: The platform key may also be cleared using \r
+ a secure platform-specific method. In this case, the global variable SetupMode \r
+ must also be updated to 1.\r
+\r
+ NOTE THAT: This function cannot depend on any EFI Variable Service since they are\r
+ not available when this function is called in AuthenticateVariable driver.\r
+ \r
+ @retval TRUE The Platform owner wants to force clear PK.\r
+ @retval FALSE The Platform owner doesn't want to force clear PK. \r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ForceClearPK (\r
+ VOID\r
+ );\r
+\r
+#endif
\ No newline at end of file
--- /dev/null
+/** @file\r
+ Ihis library is only intended to be used by TPM modules.\r
+ It provides basic TPM Interface Specification (TIS) and Command functions.\r
+\r
+Copyright (c) 2005 - 2011, 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_COMM_LIB_H_\r
+#define _TPM_COMM_LIB_H_\r
+\r
+#include <IndustryStandard/Tpm12.h>\r
+\r
+typedef EFI_HANDLE TIS_TPM_HANDLE;\r
+\r
+///\r
+/// TPM register base address.\r
+///\r
+#define TPM_BASE_ADDRESS 0xfed40000\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; // 24\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
+// TCG Platform Type based on TCG ACPI Specification Version 1.00\r
+//\r
+#define TCG_PLATFORM_TYPE_CLIENT 0\r
+#define TCG_PLATFORM_TYPE_SERVER 1\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_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 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
+/**\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
+/**\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
+/**\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_D.\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
+/**\r
+ Single function calculates SHA1 digest value for all raw data. It\r
+ combines Sha1Init(), Sha1Update() and Sha1Final().\r
+\r
+ @param[in] Data Raw data to be digested.\r
+ @param[in] DataLen Size of the raw data.\r
+ @param[out] Digest Pointer to a buffer that stores the final digest.\r
+ \r
+ @retval EFI_SUCCESS Always successfully calculate the final digest.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TpmCommHashAll (\r
+ IN CONST UINT8 *Data,\r
+ IN UINTN DataLen,\r
+ OUT TPM_DIGEST *Digest\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ This file defines the lock physical Presence PPI. This PPI is \r
+ produced by a platform specific PEIM and consumed by the TPM \r
+ PEIM.\r
+\r
+Copyright (c) 2011, 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 __PEI_LOCK_PHYSICAL_PRESENCE_H__\r
+#define __PEI_LOCK_PHYSICAL_PRESENCE_H__\r
+\r
+///\r
+/// Global ID for the PEI_LOCK_PHYSICAL_PRESENCE_PPI_GUID. \r
+///\r
+#define PEI_LOCK_PHYSICAL_PRESENCE_PPI_GUID \\r
+ { \\r
+ 0xef9aefe5, 0x2bd3, 0x4031, { 0xaf, 0x7d, 0x5e, 0xfe, 0x5a, 0xbb, 0x9a, 0xd } \\r
+ }\r
+\r
+///\r
+/// Forward declaration for the PEI_LOCK_PHYSICAL_PRESENCE_PPI\r
+///\r
+typedef struct _PEI_LOCK_PHYSICAL_PRESENCE_PPI PEI_LOCK_PHYSICAL_PRESENCE_PPI;\r
+\r
+/**\r
+ This interface returns whether TPM physical presence needs be locked.\r
+\r
+ @param[in] PeiServices The pointer to the PEI Services Table.\r
+\r
+ @retval TRUE The TPM physical presence should be locked.\r
+ @retval FALSE The TPM physical presence cannot be locked.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *PEI_LOCK_PHYSICAL_PRESENCE)(\r
+ IN CONST EFI_PEI_SERVICES **PeiServices\r
+);\r
+\r
+///\r
+/// This service abstracts TPM physical presence lock interface. It is necessary for \r
+/// safety to convey this information to the TPM driver so that TPM physical presence \r
+/// can be locked as early as possible. This PPI is produced by a platform specific \r
+/// PEIM and consumed by the TPM PEIM.\r
+///\r
+struct _PEI_LOCK_PHYSICAL_PRESENCE_PPI {\r
+ PEI_LOCK_PHYSICAL_PRESENCE LockPhysicalPresence;\r
+};\r
+\r
+extern EFI_GUID gPeiLockPhysicalPresencePpiGuid;\r
+\r
+#endif // __PEI_LOCK_PHYSICAL_PRESENCE_H__
\ No newline at end of file
--- /dev/null
+/** @file\r
+ Tag GUID that must be installed by the TPM PEIM after the TPM hardware is\r
+ initialized. PEIMs that must execute after TPM hardware initialization\r
+ may use this GUID in their dependency expressions.\r
+ \r
+Copyright (c) 2008 - 2010, 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 _PEI_TPM_INITIALIZED_PPI_H_\r
+#define _PEI_TPM_INITIALIZED_PPI_H_\r
+\r
+///\r
+/// Global ID for the PEI_TPM_INITIALIZED_PPI which always uses a NULL interface. \r
+///\r
+#define PEI_TPM_INITIALIZED_PPI_GUID \\r
+ { \\r
+ 0xe9db0d58, 0xd48d, 0x47f6, 0x9c, 0x6e, 0x6f, 0x40, 0xe8, 0x6c, 0x7b, 0x41 \\r
+ }\r
+\r
+extern EFI_GUID gPeiTpmInitializedPpiGuid;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Implement defer image load services for user identification in UEFI2.2.\r
+\r
+Copyright (c) 2009 - 2011, 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 "DxeDeferImageLoadLib.h"\r
+\r
+//\r
+// Handle for the Deferred Image Load Protocol instance produced by this driver.\r
+//\r
+EFI_HANDLE mDeferredImageHandle = NULL;\r
+BOOLEAN mIsProtocolInstalled = FALSE;\r
+EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
+DEFERRED_IMAGE_TABLE mDeferredImage = {\r
+ 0, // Deferred image count\r
+ NULL // The deferred image info\r
+};\r
+\r
+EFI_DEFERRED_IMAGE_LOAD_PROTOCOL gDeferredImageLoad = {\r
+ GetDefferedImageInfo\r
+};\r
+\r
+/**\r
+ Get the image type.\r
+\r
+ @param[in] File This is a pointer to the device path of the file\r
+ that is being dispatched. \r
+\r
+ @return UINT32 Image Type \r
+\r
+**/\r
+UINT32\r
+GetFileType (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DeviceHandle; \r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ //\r
+ // First check to see if File is from a Firmware Volume\r
+ //\r
+ DeviceHandle = NULL;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ &TempDevicePath,\r
+ &DeviceHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return IMAGE_FROM_FV;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Next check to see if File is from a Block I/O device\r
+ //\r
+ DeviceHandle = NULL;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiBlockIoProtocolGuid,\r
+ &TempDevicePath,\r
+ &DeviceHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ BlockIo = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle,\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlockIo,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status) && BlockIo != NULL) {\r
+ if (BlockIo->Media != NULL) {\r
+ if (BlockIo->Media->RemovableMedia) {\r
+ //\r
+ // Block I/O is present and specifies the media is removable\r
+ //\r
+ return IMAGE_FROM_REMOVABLE_MEDIA;\r
+ } else {\r
+ //\r
+ // Block I/O is present and specifies the media is not removable\r
+ //\r
+ return IMAGE_FROM_FIXED_MEDIA;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // File is not in a Firmware Volume or on a Block I/O device, so check to see if \r
+ // the device path supports the Simple File System Protocol.\r
+ //\r
+ DeviceHandle = NULL;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ &TempDevicePath,\r
+ &DeviceHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Simple File System is present without Block I/O, so assume media is fixed.\r
+ //\r
+ return IMAGE_FROM_FIXED_MEDIA;\r
+ }\r
+\r
+ //\r
+ // File is not from an FV, Block I/O or Simple File System, so the only options\r
+ // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC. \r
+ //\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ while (!IsDevicePathEndType (TempDevicePath)) {\r
+ switch (DevicePathType (TempDevicePath)) {\r
+ \r
+ case MEDIA_DEVICE_PATH:\r
+ if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {\r
+ return IMAGE_FROM_OPTION_ROM;\r
+ }\r
+ break;\r
+\r
+ case MESSAGING_DEVICE_PATH:\r
+ if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {\r
+ return IMAGE_FROM_REMOVABLE_MEDIA;\r
+ } \r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+ }\r
+ return IMAGE_UNKNOWN; \r
+}\r
+\r
+\r
+/**\r
+ Get current user's access right.\r
+\r
+ @param[out] AccessControl Points to the user's access control data, the\r
+ caller should free data buffer.\r
+ @param[in] AccessType The type of user access control.\r
+\r
+ @retval EFI_SUCCESS Get current user access control successfully\r
+ @retval others Fail to get current user access control\r
+\r
+**/\r
+EFI_STATUS\r
+GetAccessControl (\r
+ OUT EFI_USER_INFO_ACCESS_CONTROL **AccessControl,\r
+ IN UINT32 AccessType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_USER_INFO_HANDLE UserInfo;\r
+ EFI_USER_INFO *Info;\r
+ UINTN InfoSize;\r
+ EFI_USER_INFO_ACCESS_CONTROL *Access;\r
+ EFI_USER_PROFILE_HANDLE CurrentUser;\r
+ UINTN CheckLen;\r
+ EFI_USER_MANAGER_PROTOCOL *UserManager;\r
+\r
+ CurrentUser = NULL;\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiUserManagerProtocolGuid,\r
+ NULL,\r
+ (VOID **) &UserManager\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ \r
+ //\r
+ // Get current user access information.\r
+ //\r
+ UserManager->Current (UserManager, &CurrentUser);\r
+\r
+ UserInfo = NULL;\r
+ Info = NULL;\r
+ InfoSize = 0;\r
+ while (TRUE) {\r
+ //\r
+ // Get next user information.\r
+ //\r
+ Status = UserManager->GetNextInfo (UserManager, CurrentUser, &UserInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = UserManager->GetInfo (\r
+ UserManager,\r
+ CurrentUser,\r
+ UserInfo,\r
+ Info,\r
+ &InfoSize\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ if (Info != NULL) {\r
+ FreePool (Info);\r
+ }\r
+ Info = AllocateZeroPool (InfoSize);\r
+ ASSERT (Info != NULL);\r
+ Status = UserManager->GetInfo (\r
+ UserManager,\r
+ CurrentUser,\r
+ UserInfo,\r
+ Info,\r
+ &InfoSize\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ \r
+ ASSERT (Info != NULL);\r
+ if (Info->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) {\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Get specified access information.\r
+ //\r
+ CheckLen = 0;\r
+ while (CheckLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {\r
+ Access = (EFI_USER_INFO_ACCESS_CONTROL *) ((UINT8 *) (Info + 1) + CheckLen);\r
+ if ((Access->Type == AccessType)) {\r
+ *AccessControl = AllocateZeroPool (Access->Size);\r
+ ASSERT (*AccessControl != NULL);\r
+ CopyMem (*AccessControl, Access, Access->Size);\r
+ FreePool (Info);\r
+ return EFI_SUCCESS;\r
+ }\r
+ CheckLen += Access->Size;\r
+ }\r
+ }\r
+ \r
+ if (Info != NULL) {\r
+ FreePool (Info);\r
+ }\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Convert the '/' to '\' in the specified string.\r
+\r
+ @param[in, out] Str Points to the string to convert.\r
+\r
+**/\r
+VOID\r
+ConvertDPStr (\r
+ IN OUT EFI_STRING Str \r
+ )\r
+{\r
+ INTN Count;\r
+ INTN Index;\r
+ \r
+ Count = StrSize(Str) / 2 - 1;\r
+\r
+ if (Count < 4) {\r
+ return;\r
+ }\r
+ \r
+ //\r
+ // Convert device path string.\r
+ //\r
+ Index = Count - 1;\r
+ while (Index > 0) {\r
+ //\r
+ // Find the last '/'.\r
+ //\r
+ for (Index = Count - 1; Index > 0; Index--) {\r
+ if (Str[Index] == L'/')\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check next char.\r
+ //\r
+ if (Str[Index + 1] == L'\\')\r
+ return;\r
+ \r
+ Str[Index] = L'\\';\r
+ \r
+ //\r
+ // Check previous char.\r
+ //\r
+ if ((Index > 0) && (Str[Index - 1] == L'\\')) {\r
+ CopyMem (&Str[Index - 1], &Str[Index], (UINTN) ((Count - Index + 1) * sizeof (CHAR16)));\r
+ return;\r
+ }\r
+ Index--;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Check whether the DevicePath2 is identical with DevicePath1, or identical with\r
+ DevicePath1's child device path.\r
+\r
+ If DevicePath2 is identical with DevicePath1, or with DevicePath1's child device\r
+ path, then TRUE returned. Otherwise, FALSE is returned.\r
+ \r
+ If DevicePath1 is NULL, then ASSERT().\r
+ If DevicePath2 is NULL, then ASSERT().\r
+\r
+ @param[in] DevicePath1 A pointer to a device path.\r
+ @param[in] DevicePath2 A pointer to a device path.\r
+\r
+ @retval TRUE Two device paths are identical , or DevicePath2 is \r
+ DevicePath1's child device path.\r
+ @retval FALSE Two device paths are not identical, and DevicePath2 \r
+ is not DevicePath1's child device path.\r
+\r
+**/\r
+BOOLEAN\r
+CheckDevicePath (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING DevicePathStr1;\r
+ EFI_STRING DevicePathStr2;\r
+ UINTN StrLen1;\r
+ UINTN StrLen2;\r
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText;\r
+ BOOLEAN DevicePathEqual;\r
+\r
+ ASSERT (DevicePath1 != NULL);\r
+ ASSERT (DevicePath2 != NULL);\r
+ \r
+ DevicePathEqual = FALSE;\r
+ DevicePathText = NULL;\r
+ Status = gBS->LocateProtocol ( \r
+ &gEfiDevicePathToTextProtocolGuid,\r
+ NULL,\r
+ (VOID **) &DevicePathText\r
+ );\r
+ ASSERT (Status == EFI_SUCCESS);\r
+ \r
+ //\r
+ // Get first device path string.\r
+ //\r
+ DevicePathStr1 = DevicePathText->ConvertDevicePathToText (DevicePath1, TRUE, TRUE);\r
+ ConvertDPStr (DevicePathStr1);\r
+ //\r
+ // Get second device path string.\r
+ //\r
+ DevicePathStr2 = DevicePathText->ConvertDevicePathToText (DevicePath2, TRUE, TRUE);\r
+ ConvertDPStr (DevicePathStr2);\r
+ \r
+ //\r
+ // Compare device path string.\r
+ //\r
+ StrLen1 = StrSize (DevicePathStr1);\r
+ StrLen2 = StrSize (DevicePathStr2);\r
+ if (StrLen1 > StrLen2) {\r
+ DevicePathEqual = FALSE;\r
+ goto Done;\r
+ }\r
+ \r
+ if (CompareMem (DevicePathStr1, DevicePathStr2, StrLen1) == 0) {\r
+ DevicePathEqual = TRUE;\r
+ }\r
+\r
+Done:\r
+ FreePool (DevicePathStr1);\r
+ FreePool (DevicePathStr2);\r
+ return DevicePathEqual;\r
+}\r
+\r
+\r
+/**\r
+ Check whether the image pointed to by DevicePath is in the device path list \r
+ specified by AccessType. \r
+\r
+ @param[in] DevicePath Points to device path.\r
+ @param[in] AccessType The type of user access control.\r
+ \r
+ @retval TURE The DevicePath is in the specified List.\r
+ @retval FALSE The DevicePath is not in the specified List.\r
+\r
+**/\r
+BOOLEAN\r
+IsDevicePathInList (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN UINT32 AccessType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_USER_INFO_ACCESS_CONTROL *Access;\r
+ EFI_DEVICE_PATH_PROTOCOL *Path;\r
+ UINTN OffSet; \r
+\r
+ Status = GetAccessControl (&Access, AccessType);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ } \r
+\r
+ OffSet = 0;\r
+ while (OffSet < Access->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
+ Path = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)(Access + 1) + OffSet); \r
+ if (CheckDevicePath (Path, DevicePath)) {\r
+ //\r
+ // The device path is found in list.\r
+ //\r
+ FreePool (Access);\r
+ return TRUE;\r
+ } \r
+ OffSet += GetDevicePathSize (Path);\r
+ }\r
+ \r
+ FreePool (Access);\r
+ return FALSE; \r
+}\r
+\r
+\r
+/**\r
+ Check whether the image pointed to by DevicePath is permitted to load. \r
+\r
+ @param[in] DevicePath Points to device path\r
+ \r
+ @retval TURE The image pointed by DevicePath is permitted to load.\r
+ @retval FALSE The image pointed by DevicePath is forbidden to load.\r
+\r
+**/\r
+BOOLEAN\r
+VerifyDevicePath (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_PERMIT_LOAD)) {\r
+ //\r
+ // This access control overrides any restrictions put in place by the \r
+ // EFI_USER_INFO_ACCESS_FORBID_LOAD record.\r
+ //\r
+ return TRUE;\r
+ }\r
+ \r
+ if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_FORBID_LOAD)) {\r
+ //\r
+ // The device path is found in the forbidden list.\r
+ //\r
+ return FALSE;\r
+ }\r
+ \r
+ return TRUE; \r
+}\r
+\r
+\r
+/**\r
+ Check the image pointed by DevicePath is a boot option or not. \r
+\r
+ @param[in] DevicePath Points to device path.\r
+ \r
+ @retval TURE The image pointed by DevicePath is a boot option.\r
+ @retval FALSE The image pointed by DevicePath is not a boot option.\r
+\r
+**/\r
+BOOLEAN\r
+IsBootOption (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 *BootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINTN Index;\r
+ CHAR16 StrTemp[20];\r
+ UINT8 *OptionBuffer;\r
+ UINT8 *OptionPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
+ \r
+ //\r
+ // Get BootOrder\r
+ //\r
+ BootOrderListSize = 0;\r
+ BootOrderList = NULL; \r
+ Status = gRT->GetVariable (\r
+ L"BootOrder", \r
+ &gEfiGlobalVariableGuid, \r
+ NULL, \r
+ &BootOrderListSize, \r
+ NULL\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ BootOrderList = AllocateZeroPool (BootOrderListSize);\r
+ ASSERT (BootOrderList != NULL);\r
+ Status = gRT->GetVariable (\r
+ L"BootOrder", \r
+ &gEfiGlobalVariableGuid, \r
+ NULL, \r
+ &BootOrderListSize, \r
+ BootOrderList\r
+ );\r
+ }\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // No Boot option\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ OptionBuffer = NULL;\r
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+ //\r
+ // Try to find the DevicePath in BootOption\r
+ //\r
+ UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);\r
+ OptionBuffer = GetEfiGlobalVariable (StrTemp);\r
+ if (OptionBuffer == NULL) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check whether the image is forbidden.\r
+ //\r
+ \r
+ OptionPtr = OptionBuffer;\r
+ //\r
+ // Skip attribute.\r
+ //\r
+ OptionPtr += sizeof (UINT32);\r
+\r
+ //\r
+ // Skip device path length.\r
+ //\r
+ OptionPtr += sizeof (UINT16);\r
+\r
+ //\r
+ // Skip descript string\r
+ //\r
+ OptionPtr += StrSize ((UINT16 *) OptionPtr);\r
+ \r
+ //\r
+ // Now OptionPtr points to Device Path.\r
+ //\r
+ OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) OptionPtr;\r
+\r
+ if (CheckDevicePath (DevicePath, OptionDevicePath)) {\r
+ FreePool (OptionBuffer);\r
+ OptionBuffer = NULL;\r
+ return TRUE;\r
+ }\r
+ FreePool (OptionBuffer);\r
+ OptionBuffer = NULL;\r
+ }\r
+\r
+ if (BootOrderList != NULL) {\r
+ FreePool (BootOrderList);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Add the image info to a deferred image list.\r
+\r
+ @param[in] ImageDevicePath A pointer to the device path of a image. \r
+ @param[in] Image Points to the first byte of the image, or NULL if the \r
+ image is not available.\r
+ @param[in] ImageSize The size of the image, or 0 if the image is not available.\r
+ \r
+**/\r
+VOID\r
+PutDefferedImageInfo (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,\r
+ IN VOID *Image,\r
+ IN UINTN ImageSize\r
+ )\r
+{\r
+ DEFERRED_IMAGE_INFO *CurImageInfo;\r
+ UINTN PathSize;\r
+\r
+ //\r
+ // Expand memory for the new deferred image.\r
+ //\r
+ if (mDeferredImage.Count == 0) {\r
+ mDeferredImage.ImageInfo = AllocatePool (sizeof (DEFERRED_IMAGE_INFO));\r
+ ASSERT (mDeferredImage.ImageInfo != NULL);\r
+ } else {\r
+ CurImageInfo = AllocatePool ((mDeferredImage.Count + 1) * sizeof (DEFERRED_IMAGE_INFO));\r
+ ASSERT (CurImageInfo != NULL);\r
+ \r
+ CopyMem (\r
+ CurImageInfo, \r
+ mDeferredImage.ImageInfo,\r
+ mDeferredImage.Count * sizeof (DEFERRED_IMAGE_INFO)\r
+ );\r
+ FreePool (mDeferredImage.ImageInfo);\r
+ mDeferredImage.ImageInfo = CurImageInfo;\r
+ }\r
+ mDeferredImage.Count++;\r
+ \r
+ //\r
+ // Save the deferred image information.\r
+ //\r
+ CurImageInfo = &mDeferredImage.ImageInfo[mDeferredImage.Count - 1];\r
+ PathSize = GetDevicePathSize (ImageDevicePath);\r
+ CurImageInfo->ImageDevicePath = AllocateZeroPool (PathSize);\r
+ ASSERT (CurImageInfo->ImageDevicePath != NULL);\r
+ CopyMem (CurImageInfo->ImageDevicePath, ImageDevicePath, PathSize);\r
+\r
+ CurImageInfo->Image = Image;\r
+ CurImageInfo->ImageSize = ImageSize;\r
+ CurImageInfo->BootOption = IsBootOption (ImageDevicePath);\r
+}\r
+\r
+\r
+/**\r
+ Returns information about a deferred image.\r
+\r
+ This function returns information about a single deferred image. The deferred images are \r
+ numbered consecutively, starting with 0. If there is no image which corresponds to \r
+ ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by \r
+ iteratively calling this function until EFI_NOT_FOUND is returned.\r
+ Image may be NULL and ImageSize set to 0 if the decision to defer execution was made \r
+ because of the location of the executable image, rather than its actual contents. \r
+\r
+ @param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL.\r
+ @param[in] ImageIndex Zero-based index of the deferred index.\r
+ @param[out] ImageDevicePath On return, points to a pointer to the device path of the image. \r
+ The device path should not be freed by the caller. \r
+ @param[out] Image On return, points to the first byte of the image or NULL if the \r
+ image is not available. The image should not be freed by the caller\r
+ unless LoadImage() has been successfully called. \r
+ @param[out] ImageSize On return, the size of the image, or 0 if the image is not available.\r
+ @param[out] BootOption On return, points to TRUE if the image was intended as a boot option \r
+ or FALSE if it was not intended as a boot option. \r
+ \r
+ @retval EFI_SUCCESS Image information returned successfully.\r
+ @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image.\r
+ @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or \r
+ BootOption is NULL.\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDefferedImageInfo (\r
+ IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This,\r
+ IN UINTN ImageIndex,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath,\r
+ OUT VOID **Image,\r
+ OUT UINTN *ImageSize,\r
+ OUT BOOLEAN *BootOption\r
+ )\r
+{\r
+ DEFERRED_IMAGE_INFO *ReqImageInfo;\r
+\r
+ //\r
+ // Check the parameter.\r
+ //\r
+\r
+ if ((This == NULL) || (ImageSize == NULL) || (Image == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if ((ImageDevicePath == NULL) || (BootOption == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ImageIndex >= mDeferredImage.Count) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ \r
+ //\r
+ // Get the request deferred image.\r
+ // \r
+ ReqImageInfo = &mDeferredImage.ImageInfo[ImageIndex];\r
+ \r
+ *ImageDevicePath = ReqImageInfo->ImageDevicePath;\r
+ *Image = ReqImageInfo->Image;\r
+ *ImageSize = ReqImageInfo->ImageSize;\r
+ *BootOption = ReqImageInfo->BootOption;\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Provides the service of deferring image load based on platform policy control,\r
+ and installs Deferred Image Load Protocol.\r
+\r
+ @param[in] AuthenticationStatus This is the authentication status returned from the \r
+ security measurement services for the input file.\r
+ @param[in] File This is a pointer to the device path of the file that\r
+ is being dispatched. This will optionally be used for\r
+ 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
+\r
+ @retval EFI_SUCCESS The file specified by File did authenticate, and the\r
+ platform policy dictates that the DXE Core may use File.\r
+ @retval EFI_INVALID_PARAMETER File is NULL.\r
+ @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
+ the platform policy dictates that File should be placed\r
+ in the untrusted state. A file may be promoted from\r
+ the untrusted to the trusted state at a future time\r
+ with a call to the Trust() DXE Service.\r
+ @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and\r
+ the platform policy dictates that File should not be\r
+ used for any purpose.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeDeferImageLoadHandler (\r
+ IN UINT32 AuthenticationStatus,\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,\r
+ IN VOID *FileBuffer,\r
+ IN UINTN FileSize\r
+ )\r
+\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_USER_PROFILE_HANDLE CurrentUser;\r
+ UINT32 Policy;\r
+ UINT32 FileType;\r
+\r
+ if (File == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check whether user has a logon.\r
+ // \r
+ CurrentUser = NULL;\r
+ if (mUserManager != NULL) {\r
+ mUserManager->Current (mUserManager, &CurrentUser);\r
+ if (CurrentUser != NULL) {\r
+ //\r
+ // The user is logon; verify the FilePath by current user access policy.\r
+ //\r
+ if (!VerifyDevicePath (File)) {\r
+ DEBUG ((EFI_D_ERROR, "[Security] The image is forbidden to load!\n"));\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Still no user logon.\r
+ // Check the file type and get policy setting.\r
+ //\r
+ FileType = GetFileType (File);\r
+ Policy = PcdGet32 (PcdDeferImageLoadPolicy);\r
+ if ((Policy & FileType) == FileType) {\r
+ //\r
+ // This file type is secure to load.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ DEBUG ((EFI_D_ERROR, "[Security] No user identified, the image is deferred to load!\n"));\r
+ PutDefferedImageInfo (File, NULL, 0);\r
+\r
+ //\r
+ // Install the Deferred Image Load Protocol onto a new handle.\r
+ //\r
+ if (!mIsProtocolInstalled) {\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mDeferredImageHandle,\r
+ &gEfiDeferredImageLoadProtocolGuid,\r
+ &gDeferredImageLoad,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ mIsProtocolInstalled = TRUE;\r
+ }\r
+\r
+ return EFI_ACCESS_DENIED;\r
+}\r
+\r
+/**\r
+ Locate user manager protocol when user manager is installed. \r
+\r
+ @param[in] Event The Event that is being processed, not used.\r
+ @param[in] Context Event Context, not used. \r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FindUserManagerProtocol (\r
+ IN EFI_EVENT Event,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ gBS->LocateProtocol (\r
+ &gEfiUserManagerProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mUserManager\r
+ );\r
+ \r
+}\r
+\r
+\r
+/**\r
+ Register security handler for deferred image load.\r
+\r
+ @param[in] ImageHandle ImageHandle of the loaded driver.\r
+ @param[in] SystemTable Pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The handlers were registered successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeDeferImageLoadLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ VOID *Registration;\r
+ \r
+ //\r
+ // Register user manager notification function.\r
+ //\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEfiUserManagerProtocolGuid, \r
+ TPL_CALLBACK,\r
+ FindUserManagerProtocol,\r
+ NULL,\r
+ &Registration\r
+ );\r
+ \r
+ return RegisterSecurityHandler (\r
+ DxeDeferImageLoadHandler,\r
+ EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD \r
+ ); \r
+}\r
+\r
+\r
--- /dev/null
+/** @file\r
+ The internal header file includes the common header files, defines\r
+ internal structure and functions used by DeferImageLoadLib.\r
+\r
+Copyright (c) 2009 - 2010, 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 __DEFER_IMAGE_LOAD_LIB_H__\r
+#define __DEFER_IMAGE_LOAD_LIB_H__\r
+\r
+#include <PiDxe.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/SecurityManagementLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/DeferredImageLoad.h>\r
+#include <Protocol/UserCredential.h>\r
+#include <Protocol/UserManager.h>\r
+#include <Protocol/DevicePathToText.h>\r
+\r
+#include <Guid/GlobalVariable.h>\r
+\r
+//\r
+// Image type definitions.\r
+//\r
+#define IMAGE_UNKNOWN 0x00000001\r
+#define IMAGE_FROM_FV 0x00000002\r
+#define IMAGE_FROM_OPTION_ROM 0x00000004\r
+#define IMAGE_FROM_REMOVABLE_MEDIA 0x00000008\r
+#define IMAGE_FROM_FIXED_MEDIA 0x00000010\r
+\r
+//\r
+// The struct to save the deferred image information.\r
+//\r
+typedef struct {\r
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;\r
+ VOID *Image;\r
+ UINTN ImageSize;\r
+ BOOLEAN BootOption;\r
+} DEFERRED_IMAGE_INFO;\r
+\r
+//\r
+// The table to save the deferred image item.\r
+//\r
+typedef struct {\r
+ UINTN Count; ///< deferred image count\r
+ DEFERRED_IMAGE_INFO *ImageInfo; ///< deferred image item\r
+} DEFERRED_IMAGE_TABLE;\r
+\r
+/**\r
+ Returns information about a deferred image.\r
+\r
+ This function returns information about a single deferred image. The deferred images are \r
+ numbered consecutively, starting with 0. If there is no image which corresponds to \r
+ ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by \r
+ iteratively calling this function until EFI_NOT_FOUND is returned.\r
+ Image may be NULL and ImageSize set to 0 if the decision to defer execution was made \r
+ because of the location of the executable image, rather than its actual contents. \r
+\r
+ @param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL.\r
+ @param[in] ImageIndex Zero-based index of the deferred index.\r
+ @param[out] ImageDevicePath On return, points to a pointer to the device path of the image. \r
+ The device path should not be freed by the caller. \r
+ @param[out] Image On return, points to the first byte of the image or NULL if the \r
+ image is not available. The image should not be freed by the caller\r
+ unless LoadImage() has been called successfully. \r
+ @param[out] ImageSize On return, the size of the image, or 0 if the image is not available.\r
+ @param[out] BootOption On return, points to TRUE if the image was intended as a boot option \r
+ or FALSE if it was not intended as a boot option. \r
+ \r
+ @retval EFI_SUCCESS Image information returned successfully.\r
+ @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image.\r
+ @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or \r
+ BootOption is NULL.\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDefferedImageInfo (\r
+ IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This,\r
+ IN UINTN ImageIndex,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath,\r
+ OUT VOID **Image,\r
+ OUT UINTN *ImageSize,\r
+ OUT BOOLEAN *BootOption\r
+ );\r
+ \r
+#endif\r
--- /dev/null
+## @file\r
+# The library instance provides security service of deferring image load.\r
+#\r
+# Copyright (c) 2009 - 2010, 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 = DxeDeferImageLoadLib \r
+ FILE_GUID = 5E2FAE1F-41DA-4fbd-BC81-603CE5CD8497\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION\r
+ CONSTRUCTOR = DxeDeferImageLoadLibConstructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+ DxeDeferImageLoadLib.c\r
+ DxeDeferImageLoadLib.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiRuntimeServicesTableLib\r
+ UefiBootServicesTableLib\r
+ SecurityManagementLib\r
+ MemoryAllocationLib\r
+ DevicePathLib\r
+ BaseMemoryLib\r
+ PrintLib\r
+ DebugLib \r
+ UefiLib\r
+ PcdLib \r
+\r
+[Protocols]\r
+ gEfiFirmwareVolume2ProtocolGuid\r
+ gEfiBlockIoProtocolGuid\r
+ gEfiSimpleFileSystemProtocolGuid\r
+ gEfiUserManagerProtocolGuid\r
+ gEfiDeferredImageLoadProtocolGuid\r
+ gEfiDevicePathToTextProtocolGuid\r
+ \r
+[Guids]\r
+ gEfiGlobalVariableGuid\r
+ \r
+[Pcd]\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdDeferImageLoadPolicy\r
--- /dev/null
+/** @file\r
+ Implement image verification services for secure boot service in UEFI2.3.1.\r
+\r
+Copyright (c) 2009 - 2011, 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 "DxeImageVerificationLib.h"\r
+\r
+EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;\r
+UINTN mImageSize;\r
+UINT32 mPeCoffHeaderOffset; \r
+UINT8 mImageDigest[MAX_DIGEST_SIZE];\r
+UINTN mImageDigestSize;\r
+EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;\r
+UINT8 *mImageBase = NULL;\r
+EFI_GUID mCertType;\r
+\r
+//\r
+// Notify string for authorization UI.\r
+//\r
+CHAR16 mNotifyString1[MAX_NOTIFY_STRING_LEN] = L"Image verification pass but not found in authorized database!";\r
+CHAR16 mNotifyString2[MAX_NOTIFY_STRING_LEN] = L"Launch this image anyway? (Yes/Defer/No)";\r
+//\r
+// Public Exponent of RSA Key.\r
+//\r
+CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };\r
+\r
+\r
+//\r
+// OID ASN.1 Value for Hash Algorithms\r
+//\r
+UINT8 mHashOidValue[] = {\r
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5\r
+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1\r
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224\r
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256\r
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384\r
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512\r
+ };\r
+\r
+HASH_TABLE mHash[] = {\r
+ { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },\r
+ { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },\r
+ { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},\r
+ { L"SHA384", 48, &mHashOidValue[31], 9, NULL, NULL, NULL, NULL },\r
+ { L"SHA512", 64, &mHashOidValue[40], 9, NULL, NULL, NULL, NULL }\r
+};\r
+\r
+\r
+/**\r
+ Get the image type.\r
+\r
+ @param[in] File This is a pointer to the device path of the file that is\r
+ being dispatched. \r
+\r
+ @return UINT32 Image Type \r
+\r
+**/\r
+UINT32\r
+GetImageType (\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DeviceHandle; \r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ //\r
+ // First check to see if File is from a Firmware Volume\r
+ //\r
+ DeviceHandle = NULL;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ &TempDevicePath,\r
+ &DeviceHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return IMAGE_FROM_FV;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Next check to see if File is from a Block I/O device\r
+ //\r
+ DeviceHandle = NULL;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiBlockIoProtocolGuid,\r
+ &TempDevicePath,\r
+ &DeviceHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ BlockIo = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle,\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlockIo,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status) && BlockIo != NULL) {\r
+ if (BlockIo->Media != NULL) {\r
+ if (BlockIo->Media->RemovableMedia) {\r
+ //\r
+ // Block I/O is present and specifies the media is removable\r
+ //\r
+ return IMAGE_FROM_REMOVABLE_MEDIA;\r
+ } else {\r
+ //\r
+ // Block I/O is present and specifies the media is not removable\r
+ //\r
+ return IMAGE_FROM_FIXED_MEDIA;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // File is not in a Firmware Volume or on a Block I/O device, so check to see if \r
+ // the device path supports the Simple File System Protocol.\r
+ //\r
+ DeviceHandle = NULL;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ &TempDevicePath,\r
+ &DeviceHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Simple File System is present without Block I/O, so assume media is fixed.\r
+ //\r
+ return IMAGE_FROM_FIXED_MEDIA;\r
+ }\r
+\r
+ //\r
+ // File is not from an FV, Block I/O or Simple File System, so the only options\r
+ // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC. \r
+ //\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ while (!IsDevicePathEndType (TempDevicePath)) {\r
+ switch (DevicePathType (TempDevicePath)) {\r
+ \r
+ case MEDIA_DEVICE_PATH:\r
+ if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {\r
+ return IMAGE_FROM_OPTION_ROM;\r
+ }\r
+ break;\r
+\r
+ case MESSAGING_DEVICE_PATH:\r
+ if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {\r
+ return IMAGE_FROM_REMOVABLE_MEDIA;\r
+ } \r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+ }\r
+ return IMAGE_UNKNOWN; \r
+}\r
+\r
+/**\r
+ Caculate hash of Pe/Coff image based on the authenticode image hashing in\r
+ PE/COFF Specification 8.0 Appendix A\r
+\r
+ @param[in] HashAlg Hash algorithm type.\r
+ \r
+ @retval TRUE Successfully hash image.\r
+ @retval FALSE Fail in hash image.\r
+\r
+**/\r
+BOOLEAN \r
+HashPeImage (\r
+ IN UINT32 HashAlg\r
+ )\r
+{\r
+ BOOLEAN Status;\r
+ UINT16 Magic;\r
+ EFI_IMAGE_SECTION_HEADER *Section;\r
+ VOID *HashCtx;\r
+ UINTN CtxSize;\r
+ UINT8 *HashBase;\r
+ UINTN HashSize;\r
+ UINTN SumOfBytesHashed;\r
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
+ UINTN Index;\r
+ UINTN Pos;\r
+\r
+ HashCtx = NULL;\r
+ SectionHeader = NULL;\r
+ Status = FALSE;\r
+\r
+ if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
+ return FALSE;\r
+ }\r
+ \r
+ //\r
+ // Initialize context of hash.\r
+ //\r
+ ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
+\r
+ if (HashAlg == HASHALG_SHA1) {\r
+ mImageDigestSize = SHA1_DIGEST_SIZE;\r
+ mCertType = gEfiCertSha1Guid;\r
+ } else if (HashAlg == HASHALG_SHA256) {\r
+ mImageDigestSize = SHA256_DIGEST_SIZE;\r
+ mCertType = gEfiCertSha256Guid;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+\r
+ CtxSize = mHash[HashAlg].GetContextSize();\r
+ \r
+ HashCtx = AllocatePool (CtxSize);\r
+ ASSERT (HashCtx != NULL);\r
+\r
+ // 1. Load the image header into memory.\r
+\r
+ // 2. Initialize a SHA hash context.\r
+ Status = mHash[HashAlg].HashInit(HashCtx);\r
+ \r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Measuring PE/COFF Image Header;\r
+ // But CheckSum field and SECURITY data directory (certificate) are excluded\r
+ //\r
+ Magic = mNtHeader.Pe32->OptionalHeader.Magic;\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 = mImageBase;\r
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset.\r
+ //\r
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset.\r
+ //\r
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+ }\r
+\r
+ Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // 5. Skip over the image checksum (it occupies a single ULONG).\r
+ // 6. Get the address of the beginning of the Cert Directory.\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 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset.\r
+ // \r
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+ }\r
+\r
+ Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+ if (!Status) {\r
+ goto Done;\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 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+ HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset.\r
+ //\r
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+ HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
+ }\r
+\r
+ Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+ if (!Status) {\r
+ goto Done;\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 = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
+ } else {\r
+ //\r
+ // Use PE32+ offset\r
+ //\r
+ SumOfBytesHashed = mNtHeader.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) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
+ ASSERT (SectionHeader != NULL);\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
+ mImageBase +\r
+ mPeCoffHeaderOffset +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
+ );\r
+ for (Index = 0; Index < mNtHeader.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 < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
+ Section = &SectionHeader[Index];\r
+ if (Section->SizeOfRawData == 0) {\r
+ continue;\r
+ }\r
+ HashBase = mImageBase + Section->PointerToRawData;\r
+ HashSize = (UINTN) Section->SizeOfRawData;\r
+\r
+ Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+ if (!Status) {\r
+ goto Done;\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 (mImageSize > SumOfBytesHashed) {\r
+ HashBase = mImageBase + SumOfBytesHashed;\r
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset.\r
+ //\r
+ HashSize = (UINTN)(\r
+ mImageSize -\r
+ mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+ SumOfBytesHashed);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset.\r
+ //\r
+ HashSize = (UINTN)(\r
+ mImageSize -\r
+ mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+ SumOfBytesHashed); \r
+ }\r
+\r
+ Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ }\r
+ Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
+\r
+Done:\r
+ if (HashCtx != NULL) {\r
+ FreePool (HashCtx);\r
+ }\r
+ if (SectionHeader != NULL) {\r
+ FreePool (SectionHeader);\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of \r
+ Pe/Coff image based on the authenticode image hashing in PE/COFF Specification \r
+ 8.0 Appendix A\r
+\r
+ @retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
+ @retval EFI_SUCCESS Hash successfully.\r
+\r
+**/\r
+EFI_STATUS \r
+HashPeImageByType (\r
+ VOID\r
+ )\r
+{\r
+ UINT8 Index;\r
+ WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
+\r
+ PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
+\r
+ for (Index = 0; Index < HASHALG_MAX; Index++) { \r
+ //\r
+ // Check the Hash algorithm in PE/COFF Authenticode.\r
+ // According to PKCS#7 Definition: \r
+ // SignedData ::= SEQUENCE {\r
+ // version Version,\r
+ // digestAlgorithms DigestAlgorithmIdentifiers,\r
+ // contentInfo ContentInfo,\r
+ // .... }\r
+ // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
+ // This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
+ // \r
+ if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == HASHALG_MAX) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
+ //\r
+ if (!HashPeImage(Index)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Returns the size of a given image execution info table in bytes.\r
+\r
+ This function returns the size, in bytes, of the image execution info table specified by\r
+ ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.\r
+\r
+ @param ImageExeInfoTable A pointer to a image execution info table structure.\r
+ \r
+ @retval 0 If ImageExeInfoTable is NULL.\r
+ @retval Others The size of a image execution info table in bytes.\r
+\r
+**/\r
+UINTN\r
+GetImageExeInfoTableSize (\r
+ EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_IMAGE_EXECUTION_INFO *ImageExeInfoItem;\r
+ UINTN TotalSize;\r
+\r
+ if (ImageExeInfoTable == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE));\r
+ TotalSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);\r
+ for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) {\r
+ TotalSize += ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize);\r
+ ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoItem + ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize));\r
+ }\r
+\r
+ return TotalSize;\r
+}\r
+\r
+/**\r
+ Create an Image Execution Information Table entry and add it to system configuration table.\r
+\r
+ @param[in] Action Describes the action taken by the firmware regarding this image.\r
+ @param[in] Name Input a null-terminated, user-friendly name.\r
+ @param[in] DevicePath Input device path pointer.\r
+ @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.\r
+ @param[in] SignatureSize Size of signature.\r
+ \r
+**/\r
+VOID\r
+AddImageExeInfo (\r
+ IN EFI_IMAGE_EXECUTION_ACTION Action, \r
+ IN CHAR16 *Name OPTIONAL, \r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN EFI_SIGNATURE_LIST *Signature OPTIONAL,\r
+ IN UINTN SignatureSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable;\r
+ EFI_IMAGE_EXECUTION_INFO_TABLE *NewImageExeInfoTable;\r
+ EFI_IMAGE_EXECUTION_INFO *ImageExeInfoEntry;\r
+ UINTN ImageExeInfoTableSize;\r
+ UINTN NewImageExeInfoEntrySize;\r
+ UINTN NameStringLen;\r
+ UINTN DevicePathSize;\r
+\r
+ ASSERT (DevicePath != NULL);\r
+ ImageExeInfoTable = NULL;\r
+ NewImageExeInfoTable = NULL;\r
+ ImageExeInfoEntry = NULL;\r
+ NameStringLen = 0;\r
+\r
+ if (Name != NULL) {\r
+ NameStringLen = StrSize (Name);\r
+ }\r
+\r
+ ImageExeInfoTable = NULL;\r
+ EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID**)&ImageExeInfoTable);\r
+ if (ImageExeInfoTable != NULL) {\r
+ //\r
+ // The table has been found!\r
+ // We must enlarge the table to accmodate the new exe info entry.\r
+ //\r
+ ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);\r
+ } else {\r
+ //\r
+ // Not Found!\r
+ // We should create a new table to append to the configuration table.\r
+ //\r
+ ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);\r
+ }\r
+\r
+ DevicePathSize = GetDevicePathSize (DevicePath);\r
+ NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
+ NewImageExeInfoTable = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);\r
+ ASSERT (NewImageExeInfoTable != NULL);\r
+\r
+ if (ImageExeInfoTable != NULL) {\r
+ CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);\r
+ } else {\r
+ NewImageExeInfoTable->NumberOfImages = 0;\r
+ }\r
+ NewImageExeInfoTable->NumberOfImages++;\r
+ ImageExeInfoEntry = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) NewImageExeInfoTable + ImageExeInfoTableSize);\r
+ //\r
+ // Update new item's infomation.\r
+ //\r
+ WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->Action, Action);\r
+ WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->InfoSize, (UINT32) NewImageExeInfoEntrySize);\r
+\r
+ if (Name != NULL) {\r
+ CopyMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), Name, NameStringLen);\r
+ }\r
+ CopyMem (\r
+ (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen,\r
+ DevicePath,\r
+ DevicePathSize\r
+ );\r
+ if (Signature != NULL) {\r
+ CopyMem (\r
+ (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
+ Signature,\r
+ SignatureSize\r
+ );\r
+ }\r
+ //\r
+ // Update/replace the image execution table.\r
+ //\r
+ Status = gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Free Old table data!\r
+ //\r
+ if (ImageExeInfoTable != NULL) {\r
+ FreePool (ImageExeInfoTable);\r
+ }\r
+}\r
+\r
+/**\r
+ Discover if the UEFI image is authorized by user's policy setting.\r
+\r
+ @param[in] Policy Specify platform's policy setting. \r
+\r
+ @retval EFI_ACCESS_DENIED Image is not allowed to run.\r
+ @retval EFI_SECURITY_VIOLATION Image is deferred.\r
+ @retval EFI_SUCCESS Image is authorized to run.\r
+\r
+**/\r
+EFI_STATUS\r
+ImageAuthorization (\r
+ IN UINT32 Policy\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+\r
+ Status = EFI_ACCESS_DENIED;\r
+\r
+ switch (Policy) {\r
+ \r
+ case QUERY_USER_ON_SECURITY_VIOLATION:\r
+ do {\r
+ CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, mNotifyString1, mNotifyString2, NULL);\r
+ if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ } else if (Key.UnicodeChar == L'N' || Key.UnicodeChar == L'n') {\r
+ Status = EFI_ACCESS_DENIED;\r
+ break;\r
+ } else if (Key.UnicodeChar == L'D' || Key.UnicodeChar == L'd') {\r
+ Status = EFI_SECURITY_VIOLATION;\r
+ break;\r
+ }\r
+ } while (TRUE);\r
+ break;\r
+\r
+ case ALLOW_EXECUTE_ON_SECURITY_VIOLATION:\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ case DEFER_EXECUTE_ON_SECURITY_VIOLATION:\r
+ Status = EFI_SECURITY_VIOLATION;\r
+ break;\r
+\r
+ case DENY_EXECUTE_ON_SECURITY_VIOLATION:\r
+ Status = EFI_ACCESS_DENIED;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check whether signature is in specified database.\r
+\r
+ @param[in] VariableName Name of database variable that is searched in.\r
+ @param[in] Signature Pointer to signature that is searched for.\r
+ @param[in] CertType Pointer to hash algrithom.\r
+ @param[in] SignatureSize Size of Signature.\r
+\r
+ @return TRUE Found the signature in the variable database.\r
+ @return FALSE Not found the signature in the variable database.\r
+\r
+**/\r
+BOOLEAN\r
+IsSignatureFoundInDatabase (\r
+ IN CHAR16 *VariableName,\r
+ IN UINT8 *Signature, \r
+ IN EFI_GUID *CertType,\r
+ IN UINTN SignatureSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIGNATURE_LIST *CertList;\r
+ EFI_SIGNATURE_DATA *Cert;\r
+ UINTN DataSize;\r
+ UINT8 *Data;\r
+ UINTN Index;\r
+ UINTN CertCount;\r
+ BOOLEAN IsFound;\r
+ //\r
+ // Read signature database variable.\r
+ //\r
+ IsFound = FALSE;\r
+ Data = NULL;\r
+ DataSize = 0;\r
+ Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return FALSE;\r
+ }\r
+\r
+ Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+ ASSERT (Data != NULL);\r
+\r
+ Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Enumerate all signature data in SigDB to check if executable's signature exists.\r
+ //\r
+ CertList = (EFI_SIGNATURE_LIST *) Data;\r
+ while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
+ CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+ if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, CertType))) {\r
+ for (Index = 0; Index < CertCount; Index++) {\r
+ if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {\r
+ //\r
+ // Find the signature in database.\r
+ //\r
+ IsFound = TRUE;\r
+ break;\r
+ }\r
+\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+ }\r
+\r
+ if (IsFound) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ DataSize -= CertList->SignatureListSize;\r
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+ }\r
+\r
+Done:\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+\r
+ return IsFound;\r
+}\r
+\r
+/**\r
+ Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format .\r
+\r
+ @retval EFI_SUCCESS Image pass verification.\r
+ @retval EFI_SECURITY_VIOLATION Image fail verification.\r
+ @retval other error value\r
+\r
+**/\r
+EFI_STATUS \r
+VerifyCertPkcsSignedData (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN VerifyStatus;\r
+ WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
+ EFI_SIGNATURE_LIST *CertList;\r
+ EFI_SIGNATURE_DATA *Cert;\r
+ UINTN DataSize;\r
+ UINT8 *Data;\r
+ UINT8 *RootCert;\r
+ UINTN RootCertSize;\r
+ UINTN Index;\r
+ UINTN CertCount;\r
+\r
+ Data = NULL;\r
+ CertList = NULL;\r
+ Cert = NULL;\r
+ RootCert = NULL;\r
+ RootCertSize = 0;\r
+ VerifyStatus = FALSE;\r
+ PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
+\r
+ //\r
+ // 1: Find certificate from KEK database and try to verify authenticode struct.\r
+ //\r
+ DataSize = 0;\r
+ Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ Data = (UINT8 *)AllocateZeroPool (DataSize);\r
+ ASSERT (Data != NULL);\r
+\r
+ Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, (VOID *)Data);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Find Cert Enrolled in KEK database to verify the signature in pkcs7 signed data.\r
+ // \r
+ CertList = (EFI_SIGNATURE_LIST *) Data;\r
+ while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
+ if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+ for (Index = 0; Index < CertCount; Index++) {\r
+ //\r
+ // Iterate each Signature Data Node within this CertList for a verify\r
+ // \r
+ RootCert = Cert->SignatureData;\r
+ RootCertSize = CertList->SignatureSize;\r
+ \r
+ //\r
+ // Call AuthenticodeVerify library to Verify Authenticode struct. \r
+ //\r
+ VerifyStatus = AuthenticodeVerify (\r
+ PkcsCertData->CertData,\r
+ mSecDataDir->Size - sizeof(PkcsCertData->Hdr),\r
+ RootCert,\r
+ RootCertSize,\r
+ mImageDigest,\r
+ mImageDigestSize\r
+ );\r
+ \r
+ if (VerifyStatus) {\r
+ goto Done;\r
+ }\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+ } \r
+ }\r
+ DataSize -= CertList->SignatureListSize;\r
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+ }\r
+ }\r
+\r
+ \r
+\r
+ //\r
+ // 2: Find certificate from DB database and try to verify authenticode struct.\r
+ //\r
+ DataSize = 0;\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ Data = (UINT8 *)AllocateZeroPool (DataSize);\r
+ ASSERT (Data != NULL);\r
+\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *)Data);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Find Cert Enrolled in DB database to verify the signature in pkcs7 signed data.\r
+ // \r
+ CertList = (EFI_SIGNATURE_LIST *) Data;\r
+ while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
+ if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+ for (Index = 0; Index < CertCount; Index++) {\r
+ //\r
+ // Iterate each Signature Data Node within this CertList for a verify\r
+ // \r
+ RootCert = Cert->SignatureData;\r
+ RootCertSize = CertList->SignatureSize;\r
+ \r
+ //\r
+ // Call AuthenticodeVerify library to Verify Authenticode struct. \r
+ //\r
+ VerifyStatus = AuthenticodeVerify (\r
+ PkcsCertData->CertData,\r
+ mSecDataDir->Size - sizeof(PkcsCertData->Hdr),\r
+ RootCert,\r
+ RootCertSize,\r
+ mImageDigest,\r
+ mImageDigestSize\r
+ );\r
+ \r
+ if (VerifyStatus) {\r
+ goto Done;\r
+ }\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+ } \r
+ }\r
+ DataSize -= CertList->SignatureListSize;\r
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+ }\r
+ }\r
+\r
+Done:\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+\r
+ if (VerifyStatus) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+}\r
+\r
+/**\r
+ Verify certificate in WIN_CERTIFICATE_UEFI_GUID format. \r
+\r
+ @retval EFI_SUCCESS Image pass verification.\r
+ @retval EFI_SECURITY_VIOLATION Image fail verification.\r
+ @retval other error value\r
+\r
+**/\r
+EFI_STATUS \r
+VerifyCertUefiGuid (\r
+ VOID\r
+ )\r
+{\r
+ BOOLEAN Status;\r
+ WIN_CERTIFICATE_UEFI_GUID *EfiCert;\r
+ EFI_SIGNATURE_LIST *KekList;\r
+ EFI_SIGNATURE_DATA *KekItem;\r
+ EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;\r
+ VOID *Rsa;\r
+ UINTN KekCount;\r
+ UINTN Index;\r
+ UINTN KekDataSize;\r
+ BOOLEAN IsFound;\r
+ EFI_STATUS Result;\r
+\r
+ EfiCert = NULL;\r
+ KekList = NULL;\r
+ KekItem = NULL;\r
+ CertBlock = NULL;\r
+ Rsa = NULL;\r
+ Status = FALSE;\r
+ IsFound = FALSE;\r
+ KekDataSize = 0;\r
+\r
+ EfiCert = (WIN_CERTIFICATE_UEFI_GUID *) (mImageBase + mSecDataDir->VirtualAddress);\r
+ CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) EfiCert->CertData;\r
+ if (!CompareGuid (&EfiCert->CertType, &gEfiCertTypeRsa2048Sha256Guid)) {\r
+ //\r
+ // Invalid Certificate Data Type.\r
+ //\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+\r
+ //\r
+ // Get KEK database variable data size\r
+ //\r
+ Result = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &KekDataSize, NULL);\r
+ if (Result != EFI_BUFFER_TOO_SMALL) {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+\r
+ //\r
+ // Get KEK database variable.\r
+ //\r
+ KekList = GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME);\r
+ if (KekList == NULL) {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+ \r
+ //\r
+ // Enumerate all Kek items in this list to verify the variable certificate data.\r
+ // If anyone is authenticated successfully, it means the variable is correct!\r
+ //\r
+ while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {\r
+ if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {\r
+ KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);\r
+ KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;\r
+ for (Index = 0; Index < KekCount; Index++) {\r
+ if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
+ IsFound = TRUE;\r
+ break;\r
+ }\r
+ KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);\r
+ }\r
+ }\r
+ KekDataSize -= KekList->SignatureListSize;\r
+ KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);\r
+ }\r
+ \r
+ if (!IsFound) {\r
+ //\r
+ // Signed key is not a trust one.\r
+ //\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Now, we found the corresponding security policy.\r
+ // Verify the data payload.\r
+ //\r
+ Rsa = RsaNew ();\r
+ ASSERT (Rsa != NULL);\r
+ // \r
+ // Set RSA Key Components.\r
+ // NOTE: Only N and E are needed to be set as RSA public key for signature verification.\r
+ //\r
+ Status = RsaSetKey (Rsa, RsaKeyN, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Verify the signature.\r
+ //\r
+ Status = RsaPkcs1Verify (\r
+ Rsa, \r
+ mImageDigest, \r
+ mImageDigestSize, \r
+ CertBlock->Signature, \r
+ EFI_CERT_TYPE_RSA2048_SHA256_SIZE\r
+ );\r
+ \r
+Done:\r
+ if (KekList != NULL) {\r
+ FreePool (KekList);\r
+ }\r
+ if (Rsa != NULL ) {\r
+ RsaFree (Rsa);\r
+ }\r
+ if (Status) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+}\r
+\r
+/**\r
+ Provide verification service for signed images, which include both signature validation\r
+ and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and \r
+ MSFT Authenticode type signatures are supported.\r
+ \r
+ In this implementation, only verify external executables when in USER MODE.\r
+ Executables from FV is bypass, so pass in AuthenticationStatus is ignored. \r
+\r
+ @param[in] AuthenticationStatus \r
+ This is the authentication status returned from the security\r
+ measurement services for the 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
+\r
+ @retval EFI_SUCCESS The file specified by File did authenticate, and the\r
+ platform policy dictates that the DXE Core may use File.\r
+ @retval EFI_INVALID_PARAMETER File is NULL.\r
+ @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
+ the platform policy dictates that File should be placed\r
+ in the untrusted state. A file may be promoted from\r
+ the untrusted to the trusted state at a future time\r
+ with a call to the Trust() DXE Service.\r
+ @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and\r
+ the platform policy dictates that File should not be\r
+ used for any purpose.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeImageVerificationHandler (\r
+ IN UINT32 AuthenticationStatus,\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,\r
+ IN VOID *FileBuffer,\r
+ IN UINTN FileSize\r
+ )\r
+\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Magic;\r
+ EFI_IMAGE_DOS_HEADER *DosHdr;\r
+ EFI_STATUS VerifyStatus;\r
+ UINT8 *SetupMode;\r
+ EFI_SIGNATURE_LIST *SignatureList;\r
+ UINTN SignatureListSize;\r
+ EFI_SIGNATURE_DATA *Signature;\r
+ EFI_IMAGE_EXECUTION_ACTION Action;\r
+ WIN_CERTIFICATE *WinCertificate;\r
+ UINT32 Policy;\r
+\r
+ if (File == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ SignatureList = NULL;\r
+ SignatureListSize = 0;\r
+ WinCertificate = NULL;\r
+ Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
+ Status = EFI_ACCESS_DENIED;\r
+ //\r
+ // Check the image type and get policy setting.\r
+ //\r
+ switch (GetImageType (File)) {\r
+ \r
+ case IMAGE_FROM_FV:\r
+ Policy = ALWAYS_EXECUTE;\r
+ break;\r
+\r
+ case IMAGE_FROM_OPTION_ROM:\r
+ Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);\r
+ break;\r
+\r
+ case IMAGE_FROM_REMOVABLE_MEDIA:\r
+ Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);\r
+ break;\r
+\r
+ case IMAGE_FROM_FIXED_MEDIA:\r
+ Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);\r
+ break;\r
+\r
+ default:\r
+ Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION; \r
+ break;\r
+ }\r
+ //\r
+ // If policy is always/never execute, return directly.\r
+ //\r
+ if (Policy == ALWAYS_EXECUTE) {\r
+ return EFI_SUCCESS;\r
+ } else if (Policy == NEVER_EXECUTE) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);\r
+\r
+ //\r
+ // SetupMode doesn't exist means no AuthVar driver is dispatched,\r
+ // skip verification.\r
+ //\r
+ if (SetupMode == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // If platform is in SETUP MODE, skip verification.\r
+ //\r
+ if (*SetupMode == SETUP_MODE) {\r
+ FreePool (SetupMode);\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Read the Dos header.\r
+ //\r
+ ASSERT (FileBuffer != NULL);\r
+ mImageBase = (UINT8 *) FileBuffer;\r
+ mImageSize = FileSize;\r
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) (mImageBase);\r
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+ //\r
+ // DOS image header is present, \r
+ // so read the PE header after the DOS image header.\r
+ //\r
+ mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
+ } else {\r
+ mPeCoffHeaderOffset = 0;\r
+ }\r
+ //\r
+ // Check PE/COFF image.\r
+ //\r
+ mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);\r
+ if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+ //\r
+ // It is not a valid Pe/Coff file.\r
+ //\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset.\r
+ //\r
+ mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+ } else {\r
+ //\r
+ // Use PE32+ offset.\r
+ //\r
+ mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+ }\r
+\r
+ if (mSecDataDir->Size == 0) {\r
+ //\r
+ // This image is not signed.\r
+ //\r
+ Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
+ Status = EFI_ACCESS_DENIED; \r
+ goto Done; \r
+ }\r
+ //\r
+ // Verify signature of executables.\r
+ //\r
+ WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);\r
+\r
+ switch (WinCertificate->wCertificateType) {\r
+ \r
+ case WIN_CERT_TYPE_EFI_GUID:\r
+ //\r
+ // Verify UEFI GUID type.\r
+ // \r
+ if (!HashPeImage (HASHALG_SHA256)) {\r
+ goto Done;\r
+ }\r
+\r
+ VerifyStatus = VerifyCertUefiGuid ();\r
+ break;\r
+\r
+ case WIN_CERT_TYPE_PKCS_SIGNED_DATA:\r
+ //\r
+ // Verify Pkcs signed data type.\r
+ //\r
+ Status = HashPeImageByType();\r
+ if (EFI_ERROR(Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ VerifyStatus = VerifyCertPkcsSignedData ();\r
+\r
+ //\r
+ // For image verification against enrolled certificate(root or intermediate),\r
+ // no need to check image's hash in the allowed database.\r
+ //\r
+ if (!EFI_ERROR (VerifyStatus)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ default:\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ //\r
+ // Get image hash value as executable's signature.\r
+ //\r
+ SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;\r
+ SignatureList = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);\r
+ ASSERT (SignatureList != NULL);\r
+ SignatureList->SignatureHeaderSize = 0;\r
+ SignatureList->SignatureListSize = (UINT32) SignatureListSize;\r
+ SignatureList->SignatureSize = (UINT32) mImageDigestSize;\r
+ CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));\r
+ Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));\r
+ CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);\r
+ //\r
+ // Signature database check after verification.\r
+ //\r
+ if (EFI_ERROR (VerifyStatus)) {\r
+ //\r
+ // Verification failure.\r
+ //\r
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
+ Status = EFI_ACCESS_DENIED;\r
+ } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Signature->SignatureData, &mCertType, mImageDigestSize)) {\r
+ //\r
+ // Executable signature verification passes, but is found in forbidden signature database.\r
+ //\r
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;\r
+ Status = EFI_ACCESS_DENIED;\r
+ } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, Signature->SignatureData, &mCertType, mImageDigestSize)) {\r
+ //\r
+ // Executable signature is found in authorized signature database.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Executable signature verification passes, but cannot be found in authorized signature database.\r
+ // Get platform policy to determine the action.\r
+ //\r
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED;\r
+ Status = ImageAuthorization (Policy);\r
+ }\r
+\r
+Done:\r
+ if (Status != EFI_SUCCESS) {\r
+ //\r
+ // Policy decides to defer or reject the image; add its information in image executable information table.\r
+ //\r
+ AddImageExeInfo (Action, NULL, File, SignatureList, SignatureListSize);\r
+ }\r
+\r
+ if (SignatureList != NULL) {\r
+ FreePool (SignatureList);\r
+ }\r
+\r
+ FreePool (SetupMode);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ When VariableWriteArchProtocol install, create "SecureBoot" variable.\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
+VariableWriteCallBack (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ UINT8 SecureBootMode;\r
+ UINT8 *SecureBootModePtr;\r
+ EFI_STATUS Status;\r
+ VOID *ProtocolPointer;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, &ProtocolPointer);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+ \r
+ //\r
+ // Check whether "SecureBoot" variable exists.\r
+ // If this library is built-in, it means firmware has capability to perform\r
+ // driver signing verification.\r
+ //\r
+ SecureBootModePtr = GetEfiGlobalVariable (EFI_SECURE_BOOT_MODE_NAME);\r
+ if (SecureBootModePtr == NULL) {\r
+ SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
+ //\r
+ // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.\r
+ //\r
+ gRT->SetVariable (\r
+ EFI_SECURE_BOOT_MODE_NAME,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT8),\r
+ &SecureBootMode\r
+ );\r
+ } else {\r
+ FreePool (SecureBootModePtr);\r
+ }\r
+} \r
+\r
+/**\r
+ Register security measurement handler.\r
+\r
+ @param ImageHandle ImageHandle of the loaded driver.\r
+ @param SystemTable Pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The handlers were registered successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeImageVerificationLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ VOID *Registration;\r
+\r
+ //\r
+ // Register callback function upon VariableWriteArchProtocol.\r
+ // \r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEfiVariableWriteArchProtocolGuid,\r
+ TPL_CALLBACK,\r
+ VariableWriteCallBack,\r
+ NULL,\r
+ &Registration\r
+ );\r
+\r
+ return RegisterSecurityHandler (\r
+ DxeImageVerificationHandler,\r
+ EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
+ ); \r
+}\r
--- /dev/null
+/** @file\r
+ The internal header file includes the common header files, defines\r
+ internal structure and functions used by ImageVerificationLib.\r
+\r
+Copyright (c) 2009 - 2011, 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 __IMAGEVERIFICATIONLIB_H__\r
+#define __IMAGEVERIFICATIONLIB_H__\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/SecurityManagementLib.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/VariableWrite.h>\r
+#include <Guid/ImageAuthentication.h>\r
+#include <IndustryStandard/PeImage.h>\r
+\r
+#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256\r
+#define EFI_CERT_TYPE_RSA2048_SIZE 256\r
+#define MAX_NOTIFY_STRING_LEN 64\r
+\r
+//\r
+// Image type definitions\r
+//\r
+#define IMAGE_UNKNOWN 0x00000000\r
+#define IMAGE_FROM_FV 0x00000001\r
+#define IMAGE_FROM_OPTION_ROM 0x00000002\r
+#define IMAGE_FROM_REMOVABLE_MEDIA 0x00000003\r
+#define IMAGE_FROM_FIXED_MEDIA 0x00000004\r
+\r
+//\r
+// Authorization policy bit definition\r
+//\r
+#define ALWAYS_EXECUTE 0x00000000\r
+#define NEVER_EXECUTE 0x00000001\r
+#define ALLOW_EXECUTE_ON_SECURITY_VIOLATION 0x00000002\r
+#define DEFER_EXECUTE_ON_SECURITY_VIOLATION 0x00000003\r
+#define DENY_EXECUTE_ON_SECURITY_VIOLATION 0x00000004\r
+#define QUERY_USER_ON_SECURITY_VIOLATION 0x00000005\r
+\r
+//\r
+// Support hash types\r
+//\r
+#define HASHALG_SHA1 0x00000000\r
+#define HASHALG_SHA224 0x00000001\r
+#define HASHALG_SHA256 0x00000002\r
+#define HASHALG_SHA384 0x00000003\r
+#define HASHALG_SHA512 0x00000004\r
+#define HASHALG_MAX 0x00000005\r
+\r
+//\r
+// Set max digest size as SHA256 Output (32 bytes) by far\r
+//\r
+#define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE \r
+//\r
+//\r
+// PKCS7 Certificate definition\r
+//\r
+typedef struct {\r
+ WIN_CERTIFICATE Hdr;\r
+ UINT8 CertData[1];\r
+} WIN_CERTIFICATE_EFI_PKCS;\r
+\r
+\r
+/**\r
+ Retrieves the size, in bytes, of the context buffer required for hash operations.\r
+\r
+ @return The size, in bytes, of the context buffer required for hash operations.\r
+\r
+**/\r
+typedef\r
+UINTN\r
+(EFIAPI *HASH_GET_CONTEXT_SIZE)(\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Initializes user-supplied memory pointed by HashContext as hash context for\r
+ subsequent use.\r
+\r
+ If HashContext is NULL, then ASSERT().\r
+\r
+ @param[in, out] HashContext Pointer to Context being initialized.\r
+\r
+ @retval TRUE HASH context initialization succeeded.\r
+ @retval FALSE HASH context initialization failed.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_INIT)(\r
+ IN OUT VOID *HashContext\r
+ );\r
+\r
+\r
+/**\r
+ Performs digest on a data buffer of the specified length. This function can\r
+ be called multiple times to compute the digest of long or discontinuous data streams.\r
+\r
+ If HashContext is NULL, then ASSERT().\r
+\r
+ @param[in, out] HashContext Pointer to the MD5 context.\r
+ @param[in] Data Pointer to the buffer containing the data to be hashed.\r
+ @param[in] DataLength Length of Data buffer in bytes.\r
+\r
+ @retval TRUE HASH data digest succeeded.\r
+ @retval FALSE Invalid HASH context. After HashFinal function has been called, the\r
+ HASH context cannot be reused.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_UPDATE)(\r
+ IN OUT VOID *HashContext,\r
+ IN CONST VOID *Data,\r
+ IN UINTN DataLength\r
+ );\r
+\r
+/**\r
+ Completes hash computation and retrieves the digest value into the specified\r
+ memory. After this function has been called, the context cannot be used again.\r
+\r
+ If HashContext is NULL, then ASSERT().\r
+ If HashValue is NULL, then ASSERT().\r
+\r
+ @param[in, out] HashContext Pointer to the MD5 context\r
+ @param[out] HashValue Pointer to a buffer that receives the HASH digest\r
+ value.\r
+\r
+ @retval TRUE HASH digest computation succeeded.\r
+ @retval FALSE HASH digest computation failed.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_FINAL)(\r
+ IN OUT VOID *HashContext,\r
+ OUT UINT8 *HashValue\r
+ );\r
+\r
+\r
+//\r
+// Hash Algorithm Table\r
+//\r
+typedef struct {\r
+ //\r
+ // Name for Hash Algorithm\r
+ //\r
+ CHAR16 *Name;\r
+ //\r
+ // Digest Length\r
+ //\r
+ UINTN DigestLength;\r
+ //\r
+ // Hash Algorithm OID ASN.1 Value\r
+ //\r
+ UINT8 *OidValue;\r
+ //\r
+ // Length of Hash OID Value\r
+ //\r
+ UINTN OidLength;\r
+ //\r
+ // Pointer to Hash GetContentSize function\r
+ //\r
+ HASH_GET_CONTEXT_SIZE GetContextSize;\r
+ //\r
+ // Pointer to Hash Init function\r
+ //\r
+ HASH_INIT HashInit;\r
+ //\r
+ // Pointer to Hash Update function\r
+ //\r
+ HASH_UPDATE HashUpdate;\r
+ //\r
+ // Pointer to Hash Final function\r
+ //\r
+ HASH_FINAL HashFinal;\r
+} HASH_TABLE;\r
+\r
+#endif\r
--- /dev/null
+## @file\r
+# The library instance provides security service of image verification.\r
+# Image verification Library module supports UEFI2.3.1\r
+#\r
+# Copyright (c) 2009 - 2011, 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 = DxeImageVerificationLib \r
+ FILE_GUID = 0CA970E1-43FA-4402-BC0A-81AF336BFFD6\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 = DxeImageVerificationLibConstructor\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
+ DxeImageVerificationLib.c\r
+ DxeImageVerificationLib.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ CryptoPkg/CryptoPkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ BaseLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ UefiRuntimeServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ DevicePathLib\r
+ BaseCryptLib\r
+ SecurityManagementLib\r
+\r
+[Protocols]\r
+ gEfiFirmwareVolume2ProtocolGuid\r
+ gEfiBlockIoProtocolGuid\r
+ gEfiSimpleFileSystemProtocolGuid\r
+ gEfiVariableWriteArchProtocolGuid\r
+ \r
+[Guids]\r
+ gEfiCertTypeRsa2048Sha256Guid\r
+ gEfiImageSecurityDatabaseGuid\r
+ gEfiCertSha1Guid\r
+ gEfiCertSha256Guid\r
+ gEfiCertX509Guid\r
+ gEfiCertRsa2048Guid\r
+ \r
+[Pcd]\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy\r
+\r
+ \r
+\r
+\r
--- /dev/null
+/** @file\r
+ The library instance provides security service of TPM measure boot. \r
+\r
+Copyright (c) 2009 - 2011, 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/TcgService.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/DiskIo.h>\r
+#include <Protocol/DevicePathToText.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
+\r
+//\r
+// Flag to check GPT partition. It only need be measured once.\r
+//\r
+BOOLEAN mMeasureGptTableFlag = FALSE;\r
+EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+UINTN mMeasureGptCount = 0;\r
+\r
+/**\r
+ Reads contents of a PE/COFF image in memory 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
+ImageRead (\r
+ IN VOID *FileHandle,\r
+ IN UINTN FileOffset,\r
+ IN OUT UINTN *ReadSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Measure GPT table data into TPM log.\r
+\r
+ @param TcgProtocol Pointer to the located TCG 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
+TcgMeasureGptTable (\r
+ IN EFI_TCG_PROTOCOL *TcgProtocol,\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
+ TCG_PCR_EVENT *TcgEvent;\r
+ EFI_GPT_DATA *GptData;\r
+ UINT32 EventSize;\r
+ UINT32 EventNumber;\r
+ EFI_PHYSICAL_ADDRESS EventLogLastEntry;\r
+\r
+ if (mMeasureGptCount > 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, &mZeroGuid)) {\r
+ NumberOfPartition++; \r
+ }\r
+ PartitionEntry++;\r
+ }\r
+\r
+ //\r
+ // Parepare Data for Measurement\r
+ // \r
+ EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) \r
+ + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
+ TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));\r
+ if (TcgEvent == NULL) {\r
+ FreePool (PrimaryHeader);\r
+ FreePool (EntryPtr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TcgEvent->PCRIndex = 5;\r
+ TcgEvent->EventType = EV_EFI_GPT_EVENT;\r
+ TcgEvent->EventSize = EventSize;\r
+ GptData = (EFI_GPT_DATA *) TcgEvent->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, &mZeroGuid)) {\r
+ CopyMem (\r
+ (UINT8 *)&GptData->Partitions + NumberOfPartition * sizeof (EFI_PARTITION_ENTRY),\r
+ (UINT8 *)PartitionEntry,\r
+ sizeof (EFI_PARTITION_ENTRY)\r
+ );\r
+ NumberOfPartition++;\r
+ }\r
+ PartitionEntry++;\r
+ }\r
+\r
+ //\r
+ // Measure the GPT data\r
+ //\r
+ EventNumber = 1;\r
+ Status = TcgProtocol->HashLogExtendEvent (\r
+ TcgProtocol,\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData,\r
+ (UINT64) TcgEvent->EventSize,\r
+ TPM_ALG_SHA,\r
+ TcgEvent,\r
+ &EventNumber,\r
+ &EventLogLastEntry\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ mMeasureGptCount++;\r
+ }\r
+\r
+ FreePool (PrimaryHeader);\r
+ FreePool (EntryPtr);\r
+ FreePool (TcgEvent);\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
+ @param[in] TcgProtocol Pointer to the located TCG 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 other error value\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TcgMeasurePeImage (\r
+ IN EFI_TCG_PROTOCOL *TcgProtocol,\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
+ TCG_PCR_EVENT *TcgEvent;\r
+ EFI_IMAGE_LOAD_EVENT *ImageLoad;\r
+ UINT32 FilePathSize;\r
+ VOID *Sha1Ctx;\r
+ UINTN CtxSize;\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, Pos;\r
+ UINT16 Magic;\r
+ UINT32 EventSize;\r
+ UINT32 EventNumber;\r
+ EFI_PHYSICAL_ADDRESS EventLogLastEntry;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+\r
+ Status = EFI_SUCCESS;\r
+ ImageLoad = NULL;\r
+ SectionHeader = NULL;\r
+ Sha1Ctx = NULL;\r
+ FilePathSize = (UINT32) GetDevicePathSize (FilePath);\r
+\r
+ //\r
+ // Determine destination PCR by BootPolicy\r
+ //\r
+ EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;\r
+ TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));\r
+ if (TcgEvent == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TcgEvent->EventSize = EventSize;\r
+ ImageLoad = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event;\r
+\r
+ switch (ImageType) {\r
+ case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
+ TcgEvent->EventType = EV_EFI_BOOT_SERVICES_APPLICATION;\r
+ TcgEvent->PCRIndex = 4;\r
+ break;\r
+ case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
+ TcgEvent->EventType = EV_EFI_BOOT_SERVICES_DRIVER;\r
+ TcgEvent->PCRIndex = 2;\r
+ break;\r
+ case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
+ TcgEvent->EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;\r
+ TcgEvent->PCRIndex = 2;\r
+ break;\r
+ default:\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "TcgMeasurePeImage: Unknown subsystem type %d",\r
+ ImageType\r
+ ));\r
+ ASSERT (FALSE);\r
+ TcgEvent->EventType = ImageType;\r
+ Status = EFI_UNSUPPORTED;\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
+ // 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
+ if (((EFI_TE_IMAGE_HEADER *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset))->Signature\r
+ == EFI_TE_IMAGE_HEADER_SIGNATURE) {\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
+ CtxSize = Sha1GetContextSize ();\r
+ Sha1Ctx = AllocatePool (CtxSize);\r
+ if (Sha1Ctx == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
+\r
+ Sha1Init (Sha1Ctx);\r
+\r
+ //\r
+ // Measuring PE/COFF Image Header;\r
+ // But CheckSum field and SECURITY data directory (certificate) are excluded\r
+ //\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
+ Magic = Hdr.Pe32->OptionalHeader.Magic;\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
+ HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset\r
+ //\r
+ HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+ }\r
+\r
+ Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+\r
+ //\r
+ // 5. Skip over the image checksum (it occupies a single ULONG).\r
+ // 6. Get the address of the beginning of the Cert Directory.\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
+ Sha1Update (Sha1Ctx, HashBase, HashSize);\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 -\r
+ (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) 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 -\r
+ (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress);\r
+ }\r
+ \r
+ Sha1Update (Sha1Ctx, HashBase, HashSize);\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
+ Sha1Update (Sha1Ctx, HashBase, HashSize);\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
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset\r
+ //\r
+ HashSize = (UINTN)(ImageSize -\r
+ Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+ SumOfBytesHashed);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset\r
+ //\r
+ HashSize = (UINTN)(ImageSize -\r
+ Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+ SumOfBytesHashed); \r
+ }\r
+\r
+ Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+ }\r
+\r
+ //\r
+ // 17. Finalize the SHA hash.\r
+ //\r
+ Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest);\r
+\r
+ //\r
+ // Log the PE data\r
+ //\r
+ EventNumber = 1;\r
+ Status = TcgProtocol->HashLogExtendEvent (\r
+ TcgProtocol,\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) NULL,\r
+ 0,\r
+ TPM_ALG_SHA,\r
+ TcgEvent,\r
+ &EventNumber,\r
+ &EventLogLastEntry\r
+ );\r
+\r
+Finish:\r
+ FreePool (TcgEvent);\r
+\r
+ if (SectionHeader != NULL) {\r
+ FreePool (SectionHeader);\r
+ }\r
+\r
+ if (Sha1Ctx != NULL ) {\r
+ FreePool (Sha1Ctx);\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, out] 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
+\r
+ @retval EFI_SUCCESS The file specified by File did authenticate, and the\r
+ platform policy dictates that the DXE Core may use File.\r
+ @retval EFI_INVALID_PARAMETER File is NULL.\r
+ @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
+ the platform policy dictates that File should be placed\r
+ in the untrusted state. A file may be promoted from\r
+ the untrusted to the trusted state at a future time\r
+ with a call to the Trust() DXE Service.\r
+ @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and\r
+ the platform policy dictates that File should not be\r
+ used for any purpose.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeTpmMeasureBootHandler (\r
+ IN OUT UINT32 AuthenticationStatus,\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,\r
+ IN VOID *FileBuffer OPTIONAL,\r
+ IN UINTN FileSize OPTIONAL\r
+ )\r
+{\r
+ EFI_TCG_PROTOCOL *TcgProtocol;\r
+ EFI_STATUS Status;\r
+ TCG_EFI_BOOT_SERVICE_CAPABILITY ProtocolCapability;\r
+ UINT32 TCGFeatureFlags;\r
+ EFI_PHYSICAL_ADDRESS EventLogLocation;\r
+ EFI_PHYSICAL_ADDRESS EventLogLastEntry;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;\r
+ EFI_HANDLE Handle;\r
+ BOOLEAN ApplicationRequired;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+\r
+ if (File == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // TCG protocol is not installed. So, TPM is not present.\r
+ // Don't do any measurement, and directly return EFI_SUCCESS.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability);\r
+ Status = TcgProtocol->StatusCheck (\r
+ TcgProtocol, \r
+ &ProtocolCapability,\r
+ &TCGFeatureFlags,\r
+ &EventLogLocation,\r
+ &EventLogLastEntry\r
+ );\r
+ if (EFI_ERROR (Status) || ProtocolCapability.TPMDeactivatedFlag) {\r
+ //\r
+ // TPM device doesn't work or activate.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Copy File Device Path\r
+ //\r
+ OrigDevicePathNode = DuplicateDevicePath (File);\r
+ ASSERT (OrigDevicePathNode != NULL);\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) && !mMeasureGptTableFlag) {\r
+ //\r
+ // Find the gpt partion on the given devicepath\r
+ //\r
+ DevicePathNode = OrigDevicePathNode;\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 = TcgMeasureGptTable (TcgProtocol, Handle);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // GPT disk check done.\r
+ //\r
+ mMeasureGptTableFlag = 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 FV2 protocol.\r
+ //\r
+ DevicePathNode = OrigDevicePathNode;\r
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &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 image from Firmware image will not be mearsured.\r
+ // Current policy doesn't measure PeImage from Firmware if it is driver\r
+ // If the got PeImage is application, it will be still be measured.\r
+ //\r
+ ApplicationRequired = TRUE;\r
+ }\r
+ \r
+ //\r
+ // File is not found.\r
+ //\r
+ if (FileBuffer == NULL) {\r
+ Status = EFI_SECURITY_VIOLATION;\r
+ goto Finish;\r
+ }\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) ImageRead;\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
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDevicePathToTextProtocolGuid,\r
+ NULL,\r
+ (VOID **) &DevPathToText\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ ToText = DevPathToText->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
+ }\r
+ }\r
+ DEBUG_CODE_END ();\r
+\r
+ //\r
+ // Measure PE image into TPM log.\r
+ //\r
+ Status = TcgMeasurePeImage (\r
+ TcgProtocol,\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer, \r
+ FileSize, \r
+ (UINTN) ImageContext.ImageAddress, \r
+ ImageContext.ImageType, \r
+ DevicePathNode\r
+ );\r
+ }\r
+\r
+ //\r
+ // Done, free the allocated resource.\r
+ //\r
+Finish:\r
+ FreePool (OrigDevicePathNode);\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
+DxeTpmMeasureBootLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ return RegisterSecurityHandler (\r
+ DxeTpmMeasureBootHandler,\r
+ EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
+ );\r
+}\r
--- /dev/null
+## @file\r
+# The library instance provides security service of TPM measure boot.\r
+#\r
+# Copyright (c) 2009 - 2010, 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 = DxeTpmMeasureBootLib\r
+ FILE_GUID = 6C60C7D0-922A-4b7c-87D7-E503EDD73BBF\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 = DxeTpmMeasureBootLibConstructor\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
+ DxeTpmMeasureBootLib.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
+\r
+[Protocols]\r
+ gEfiTcgProtocolGuid ## CONSUMES\r
+ gEfiFirmwareVolume2ProtocolGuid ## CONSUMES\r
+ gEfiBlockIoProtocolGuid ## CONSUMES\r
+ gEfiDiskIoProtocolGuid ## CONSUMES\r
+ gEfiDevicePathToTextProtocolGuid ## SOMETIMES_CONSUMES (Only used in debug mode)\r
--- /dev/null
+/** @file\r
+ Provides a secure platform-specific method to clear PK(Platform Key).\r
+\r
+Copyright (c) 2011, 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
+\r
+ This function detects whether a secure platform-specific method to clear PK(Platform Key)\r
+ is configured by platform owner. This method is provided for users force to clear PK \r
+ in case incorrect enrollment mis-haps.\r
+ \r
+ UEFI231 spec chapter 27.5.2 stipulates: The platform key may also be cleared using \r
+ a secure platform-specific method. In this case, the global variable SetupMode \r
+ must also be updated to 1.\r
+ \r
+ NOTE THAT: This function cannot depend on any EFI Variable Service since they are\r
+ not available when this function is called in AuthenticateVariable driver.\r
+\r
+ @retval TRUE The Platform owner wants to force clear PK.\r
+ @retval FALSE The Platform owner doesn't want to force clear PK. \r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ForceClearPK (\r
+ VOID\r
+ )\r
+{\r
+ return FALSE;\r
+}\r
--- /dev/null
+## @file\r
+# Provides a secure platform-specific method to clear PK(Platform Key).\r
+#\r
+# Copyright (c) 2011, 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 = PlatformSecureLibNull\r
+ FILE_GUID = 7FA68D82-10A4-4e71-9524-D3D9500D3CDF\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = PlatformSecureLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER\r
+\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
+ PlatformSecureLibNull.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
--- /dev/null
+/** @file\r
+ The intenal header file for TpmCommLib.\r
+\r
+Copyright (c) 2006 - 2010, 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 _TPMCOMMLIB_COMMON_HEADER_H_\r
+#define _TPMCOMMLIB_COMMON_HEADER_H_\r
+\r
+#include <PiPei.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/TpmCommLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Basic TIS (TPM Interface Specification) functions.\r
+\r
+Copyright (c) 2005 - 2011, 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 "CommonHeader.h"\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_D.\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_D\r
+ );\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ Basic TPM command functions.\r
+\r
+Copyright (c) 2005 - 2010, 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 "CommonHeader.h"\r
+\r
+/**\r
+ Single function calculates SHA1 digest value for all raw data. It\r
+ combines Sha1Init(), Sha1Update() and Sha1Final().\r
+\r
+ @param[in] Data Raw data to be digested.\r
+ @param[in] DataLen Size of the raw data.\r
+ @param[out] Digest Pointer to a buffer that stores the final digest.\r
+ \r
+ @retval EFI_SUCCESS Always successfully calculate the final digest.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TpmCommHashAll (\r
+ IN CONST UINT8 *Data,\r
+ IN UINTN DataLen,\r
+ OUT TPM_DIGEST *Digest\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
+ Sha1Update (Sha1Ctx, Data, DataLen);\r
+ Sha1Final (Sha1Ctx, (UINT8 *)Digest);\r
+\r
+ FreePool (Sha1Ctx);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+## @file\r
+# TpmCommLib instance implements basis TPM Interface Specification (TIS) and TPM command functions.\r
+#\r
+# Copyright (c) 2006 - 2011, 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 = TpmCommLib\r
+ FILE_GUID = 7d9fe32e-a6a9-4cdf-abff-10cc7f22e1c9\r
+ MODULE_TYPE = PEIM\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = TpmCommLib|DXE_DRIVER UEFI_DRIVER PEIM DXE_SMM_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
+ TisPc.c\r
+ TpmComm.c\r
+ CommonHeader.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+ CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ IoLib\r
+ TimerLib\r
+ BaseCryptLib\r
+ MemoryAllocationLib\r
+ DebugLib\r
+\r
--- /dev/null
+## @file SecurityPkg.dec\r
+# This package includes the security drivers, defintions(including PPIs/PROTOCOLs/GUIDs \r
+# and library classes) and libraries instances.\r
+#\r
+# Copyright (c) 2009 - 2011, 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 which 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
+[Defines]\r
+ DEC_SPECIFICATION = 0x00010005\r
+ PACKAGE_NAME = SecurityPkg\r
+ PACKAGE_GUID = 24369CAC-6AA6-4fb8-88DB-90BF061668AD\r
+ PACKAGE_VERSION = 0.91\r
+\r
+[Includes]\r
+ Include\r
+\r
+[LibraryClasses]\r
+ ## @libraryclass Definitions for common TPM commands as library API for TPM\r
+ # module use.\r
+ TpmCommLib|Include/Library/TpmCommLib.h\r
+\r
+[Guids]\r
+ ## Security package token space guid\r
+ # Include/Guid/SecurityPkgTokenSpace.h\r
+ gEfiSecurityPkgTokenSpaceGuid = { 0xd3fb176, 0x9569, 0x4d51, { 0xa3, 0xef, 0x7d, 0x61, 0xc6, 0x4f, 0xea, 0xba }}\r
+ ## Guid acted as the authenticated variable store header's signature, and to specify the variable list entries put in the EFI system table.\r
+ # Include/Guid/AuthenticatedVariableFormat.h\r
+ gEfiAuthenticatedVariableGuid = { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }\r
+\r
+ ## Include/Guid/TcgEventHob.h\r
+ gTcgEventEntryHobGuid = { 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 }}\r
+\r
+ ## Include/Guid/PhysicalPresenceData.h\r
+ gEfiPhysicalPresenceGuid = { 0xf6499b1, 0xe9ad, 0x493d, { 0xb9, 0xc2, 0x2f, 0x90, 0x81, 0x5c, 0x6c, 0xbc }}\r
+\r
+[Ppis]\r
+ ## Include/Ppi/LockPhysicalPresence.h\r
+ gPeiLockPhysicalPresencePpiGuid = { 0xef9aefe5, 0x2bd3, 0x4031, { 0xaf, 0x7d, 0x5e, 0xfe, 0x5a, 0xbb, 0x9a, 0xd } }\r
+\r
+ ## Include/Ppi/TpmInitialized.h\r
+ gPeiTpmInitializedPpiGuid = { 0xe9db0d58, 0xd48d, 0x47f6, { 0x9c, 0x6e, 0x6f, 0x40, 0xe8, 0x6c, 0x7b, 0x41 }}\r
+\r
+[PcdsFixedAtBuild]\r
+ ## Pcd for OptionRom.\r
+ # Image verification policy settings:\r
+ # ALWAYS_EXECUTE 0x00000000\r
+ # NEVER_EXECUTE 0x00000001\r
+ # ALLOW_EXECUTE_ON_SECURITY_VIOLATION 0x00000002\r
+ # DEFER_EXECUTE_ON_SECURITY_VIOLATION 0x00000003\r
+ # DENY_EXECUTE_ON_SECURITY_VIOLATION 0x00000004\r
+ # QUERY_USER_ON_SECURITY_VIOLATION 0x00000005 \r
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x00|UINT32|0x00000001\r
+ \r
+ ## Pcd for removable media.\r
+ # Removable media include CD-ROM, Floppy, USB and network.\r
+ # Image verification policy settings:\r
+ # ALWAYS_EXECUTE 0x00000000\r
+ # NEVER_EXECUTE 0x00000001\r
+ # ALLOW_EXECUTE_ON_SECURITY_VIOLATION 0x00000002\r
+ # DEFER_EXECUTE_ON_SECURITY_VIOLATION 0x00000003\r
+ # DENY_EXECUTE_ON_SECURITY_VIOLATION 0x00000004\r
+ # QUERY_USER_ON_SECURITY_VIOLATION 0x00000005\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x05|UINT32|0x00000002\r
+ \r
+ ## Pcd for fixed media.\r
+ # Fixed media include hard disk.\r
+ # Image verification policy settings:\r
+ # ALWAYS_EXECUTE 0x00000000\r
+ # NEVER_EXECUTE 0x00000001\r
+ # ALLOW_EXECUTE_ON_SECURITY_VIOLATION 0x00000002\r
+ # DEFER_EXECUTE_ON_SECURITY_VIOLATION 0x00000003\r
+ # DENY_EXECUTE_ON_SECURITY_VIOLATION 0x00000004\r
+ # QUERY_USER_ON_SECURITY_VIOLATION 0x00000005 \r
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x05|UINT32|0x00000003\r
+ \r
+ ## Defer Image Load policy settings.\r
+ # The policy is bitwise. \r
+ # If bit is set, the image from corresponding device will be trust when loading.\r
+ #\r
+ # IMAGE_UNKNOWN 0x00000001\r
+ # IMAGE_FROM_FV 0x00000002\r
+ # IMAGE_FROM_OPTION_ROM 0x00000004\r
+ # IMAGE_FROM_REMOVABLE_MEDIA 0x00000008\r
+ # IMAGE_FROM_FIXED_MEDIA 0x00000010\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdDeferImageLoadPolicy|0x0000001F|UINT32|0x0000004\r
+ \r
+ ## The token file name used to save credential in USB credential provider driver.\r
+ # The specified file should be saved at the root directory of USB storage disk.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedUsbCredentialProviderTokenFileName|L"Token.bin"|VOID*|0x00000005\r
+\r
+ ## The size of Append variable buffer. This buffer is reserved for runtime use, OS can append data into one existing variable.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdMaxAppendVariableSize|0x2000|UINT32|0x30000005 \r
+\r
+ ## This PCD specifies the type of TCG platform that contains TPM chip. \r
+ # This PCD is only avaiable when PcdTpmPhysicalPresence is TRUE.\r
+ # If 0, TCG platform type is PC client.\r
+ # If 1, TCG platform type is server.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass|0|UINT8|0x00000006\r
+\r
+ ## The PCD is used to control whether to support hiding the TPM.\r
+ # If TRUE, PcdHideTpm controls whether to hide the TPM.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport|FALSE|BOOLEAN|0x00000007\r
+ \r
+[PcdsDynamic, PcdsDynamicEx]\r
+ ## The PCD is used to control whether to hide the TPM.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdHideTpm|FALSE|BOOLEAN|0x00010002\r
+\r
+ ## The PCD is used to specify whether or not MOR (MemoryOverwriteControl) feature is enabled.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdMorEnable|FALSE|BOOLEAN|0x00010000\r
+\r
+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]\r
+ ## This PCD indicates the presence or absence of the platform operator.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPhysicalPresence|TRUE|BOOLEAN|0x00010001\r
+\r
--- /dev/null
+## @file\r
+# Security Module Package for All Architectures.\r
+#\r
+# Copyright (c) 2009 - 2011, 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
+[Defines]\r
+ PLATFORM_NAME = SecurityPkg\r
+ PLATFORM_GUID = B2C4614D-AE76-47ba-B876-5988BFED064F\r
+ PLATFORM_VERSION = 0.91\r
+ DSC_SPECIFICATION = 0x00010005\r
+ OUTPUT_DIRECTORY = Build/SecurityPkg\r
+ SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC\r
+ BUILD_TARGETS = DEBUG|RELEASE\r
+ SKUID_IDENTIFIER = DEFAULT\r
+\r
+[LibraryClasses]\r
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf\r
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf \r
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf\r
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
+\r
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf\r
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf\r
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf\r
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf\r
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf\r
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
+ TpmCommLib|SecurityPkg/Library/TpmCommLib/TpmCommLib.inf\r
+ PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf \r
+\r
+[LibraryClasses.common.PEIM]\r
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf\r
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf\r
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf\r
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf\r
+\r
+[LibraryClasses.common.DXE_DRIVER]\r
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf\r
+\r
+[LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_SAL_DRIVER,]\r
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
+ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf\r
+\r
+[LibraryClasses.IPF.DXE_SAL_DRIVER]\r
+ ExtendedSalLib|MdePkg/Library/DxeRuntimeExtendedSalLib/DxeRuntimeExtendedSalLib.inf\r
+\r
+[LibraryClasses.common.DXE_SMM_DRIVER]\r
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf\r
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf\r
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf\r
+ \r
+[Components]\r
+ SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf\r
+ SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf\r
+ SecurityPkg/Library/DxeDeferImageLoadLib/DxeDeferImageLoadLib.inf\r
+ SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf\r
+ SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf\r
+ SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf\r
+ SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf\r
+\r
+ #\r
+ # Application\r
+ #\r
+ SecurityPkg/Application/VariableInfo/VariableInfo.inf\r
+\r
+ #\r
+ # TPM\r
+ #\r
+ SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf\r
+ SecurityPkg/Tcg/TcgPei/TcgPei.inf\r
+ SecurityPkg/Tcg/TcgDxe/TcgDxe.inf\r
+ SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf\r
+ SecurityPkg/Tcg/PhysicalPresenceDxe/PhysicalPresenceDxe.inf\r
+ SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf\r
+ SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf {\r
+ <LibraryClasses>\r
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf\r
+ }\r
+ SecurityPkg/Tcg/TcgSmm/TcgSmm.inf\r
+\r
+[Components.IA32, Components.X64]\r
+ SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf {\r
+ <LibraryClasses>\r
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
+ }\r
+\r
+ SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf\r
+ SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf\r
+\r
+[Components.IPF]\r
+ SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/EsalVariableDxeSal.inf \r
+\r
+[Components.EBC]\r
+# Build only\r
+ SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf \r
+\r
+[BuildOptions]\r
+ MSFT:*_*_IA32_DLINK_FLAGS = /ALIGN:256\r
+ INTEL:*_*_IA32_DLINK_FLAGS = /ALIGN:256\r
+\r
--- /dev/null
+/** @file\r
+ TCG MOR (Memory Overwrite Request) Control Driver.\r
+\r
+ This driver initilize MemoryOverwriteRequestControl variable. It \r
+ will clear MOR_CLEAR_MEMORY_BIT bit if it is set.\r
+\r
+Copyright (c) 2009 - 2011, 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 "TcgMor.h"\r
+\r
+/**\r
+ Entry Point for TCG MOR Control driver.\r
+\r
+ @param[in] ImageHandle Image handle of this driver.\r
+ @param[in] SystemTable A Pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCEESS \r
+ @return Others Some error occurs.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MorDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 MorControl;\r
+ UINTN DataSize;\r
+\r
+ ///\r
+ /// The firmware is required to create the MemoryOverwriteRequestControl UEFI variable.\r
+ ///\r
+\r
+ DataSize = sizeof (MorControl);\r
+ Status = gRT->GetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, \r
+ &gEfiMemoryOverwriteControlDataGuid, \r
+ NULL, \r
+ &DataSize, \r
+ &MorControl\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Set default value to 0\r
+ //\r
+ MorControl = 0;\r
+ } else {\r
+ if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {\r
+ //\r
+ // MorControl is expected, directly return to avoid unnecessary variable operation\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Clear MOR_CLEAR_MEMORY_BIT\r
+ //\r
+ DEBUG ((EFI_D_INFO, "TcgMor: Clear MorClearMemory bit\n"));\r
+ MorControl &= 0xFE;\r
+ }\r
+ \r
+ Status = gRT->SetVariable (\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
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+}\r
+\r
+\r
--- /dev/null
+/** @file\r
+ The header file for TcgMor.\r
+\r
+Copyright (c) 2009, 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 __TCG_MOR_H__\r
+#define __TCG_MOR_H__\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Guid/MemoryOverwriteControl.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#endif\r
+\r
--- /dev/null
+## @file\r
+# Component description file for Memory Overwrite Control driver.\r
+#\r
+# Copyright (c) 2009 - 2011, 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 = TcgMor\r
+ FILE_GUID = AD416CE3-A483-45b1-94C2-4B4E4D575562\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = MorDriverEntryPoint\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
+ TcgMor.c\r
+ TcgMor.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiRuntimeServicesTableLib\r
+ ReportStatusCodeLib\r
+ DebugLib\r
+\r
+[Guids]\r
+ gEfiMemoryOverwriteControlDataGuid # GUID ALWAYS_CONSUMED\r
+\r
+[Depex]\r
+ gEfiVariableArchProtocolGuid AND\r
+ gEfiVariableWriteArchProtocolGuid AND\r
+ gEfiTcgProtocolGuid\r
+\r
--- /dev/null
+/** @file\r
+ This driver checks whether there is pending TPM request. If yes, \r
+ it will display TPM request information and ask for user confirmation.\r
+ The TPM request will be cleared after it is processed. \r
+ \r
+Copyright (c) 2006 - 2011, 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 "PhysicalPresence.h"\r
+\r
+EFI_HII_HANDLE mPpStringPackHandle;\r
+\r
+/**\r
+ Get TPM physical presence permanent flags.\r
+\r
+ @param[out] LifetimeLock Returns physicalPresenceLifetimeLock permanent flag. \r
+ @param[out] CmdEnable Returns physicalPresenceCMDEnable permanent flag.\r
+ \r
+ @retval EFI_SUCCESS Flags were returns successfully.\r
+ @retval other Failed to locate EFI TCG Protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+GetTpmCapability (\r
+ OUT BOOLEAN *LifetimeLock,\r
+ OUT BOOLEAN *CmdEnable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TCG_PROTOCOL *TcgProtocol;\r
+ TPM_RQU_COMMAND_HDR *TpmRqu;\r
+ TPM_RSP_COMMAND_HDR *TpmRsp;\r
+ UINT32 *SendBufPtr;\r
+ UINT8 SendBuffer[sizeof (*TpmRqu) + sizeof (UINT32) * 3];\r
+ TPM_PERMANENT_FLAGS *TpmPermanentFlags;\r
+ UINT8 RecvBuffer[40];\r
+ \r
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Fill request header\r
+ //\r
+ TpmRsp = (TPM_RSP_COMMAND_HDR*)RecvBuffer;\r
+ TpmRqu = (TPM_RQU_COMMAND_HDR*)SendBuffer;\r
+ \r
+ TpmRqu->tag = H2NS (TPM_TAG_RQU_COMMAND);\r
+ TpmRqu->paramSize = H2NL (sizeof (SendBuffer));\r
+ TpmRqu->ordinal = H2NL (TPM_ORD_GetCapability);\r
+\r
+ //\r
+ // Set request parameter\r
+ //\r
+ SendBufPtr = (UINT32*)(TpmRqu + 1);\r
+ WriteUnaligned32 (SendBufPtr++, H2NL (TPM_CAP_FLAG));\r
+ WriteUnaligned32 (SendBufPtr++, H2NL (sizeof (TPM_CAP_FLAG_PERMANENT)));\r
+ WriteUnaligned32 (SendBufPtr, H2NL (TPM_CAP_FLAG_PERMANENT)); \r
+ \r
+ Status = TcgProtocol->PassThroughToTpm (\r
+ TcgProtocol,\r
+ sizeof (SendBuffer),\r
+ (UINT8*)TpmRqu,\r
+ sizeof (RecvBuffer),\r
+ (UINT8*)&RecvBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (TpmRsp->tag == H2NS (TPM_TAG_RSP_COMMAND));\r
+ ASSERT (TpmRsp->returnCode == 0);\r
+ \r
+ TpmPermanentFlags = (TPM_PERMANENT_FLAGS *)&RecvBuffer[sizeof (TPM_RSP_COMMAND_HDR) + sizeof (UINT32)];\r
+ \r
+ if (LifetimeLock != NULL) {\r
+ *LifetimeLock = TpmPermanentFlags->physicalPresenceLifetimeLock;\r
+ }\r
+\r
+ if (CmdEnable != NULL) {\r
+ *CmdEnable = TpmPermanentFlags->physicalPresenceCMDEnable;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Issue TSC_PhysicalPresence command to TPM.\r
+\r
+ @param[in] PhysicalPresence The state to set the TPM's Physical Presence flags. \r
+ \r
+ @retval EFI_SUCCESS TPM executed the command successfully.\r
+ @retval EFI_SECURITY_VIOLATION TPM returned error when executing the command.\r
+ @retval other Failed to locate EFI TCG Protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+TpmPhysicalPresence (\r
+ IN TPM_PHYSICAL_PRESENCE PhysicalPresence\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TCG_PROTOCOL *TcgProtocol;\r
+ TPM_RQU_COMMAND_HDR *TpmRqu;\r
+ TPM_PHYSICAL_PRESENCE *TpmPp;\r
+ TPM_RSP_COMMAND_HDR TpmRsp;\r
+ UINT8 Buffer[sizeof (*TpmRqu) + sizeof (*TpmPp)];\r
+\r
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ TpmRqu = (TPM_RQU_COMMAND_HDR*)Buffer;\r
+ TpmPp = (TPM_PHYSICAL_PRESENCE*)(TpmRqu + 1);\r
+\r
+ TpmRqu->tag = H2NS (TPM_TAG_RQU_COMMAND);\r
+ TpmRqu->paramSize = H2NL (sizeof (Buffer));\r
+ TpmRqu->ordinal = H2NL (TSC_ORD_PhysicalPresence);\r
+ WriteUnaligned16 (TpmPp, (TPM_PHYSICAL_PRESENCE) H2NS (PhysicalPresence)); \r
+\r
+ Status = TcgProtocol->PassThroughToTpm (\r
+ TcgProtocol,\r
+ sizeof (Buffer),\r
+ (UINT8*)TpmRqu,\r
+ sizeof (TpmRsp),\r
+ (UINT8*)&TpmRsp\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (TpmRsp.tag == H2NS (TPM_TAG_RSP_COMMAND));\r
+ if (TpmRsp.returnCode != 0) {\r
+ //\r
+ // If it fails, some requirements may be needed for this command.\r
+ //\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Issue a TPM command for which no additional output data will be returned.\r
+\r
+ @param[in] TcgProtocol EFI TCG Protocol instance. \r
+ @param[in] Ordinal TPM command code. \r
+ @param[in] AdditionalParameterSize Additional parameter size. \r
+ @param[in] AdditionalParameters Pointer to the Additional paramaters. \r
+ \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
+**/\r
+TPM_RESULT\r
+TpmCommandNoReturnData (\r
+ IN EFI_TCG_PROTOCOL *TcgProtocol,\r
+ IN TPM_COMMAND_CODE Ordinal,\r
+ IN UINTN AdditionalParameterSize,\r
+ IN VOID *AdditionalParameters\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TPM_RQU_COMMAND_HDR *TpmRqu;\r
+ TPM_RSP_COMMAND_HDR TpmRsp;\r
+ UINT32 Size;\r
+\r
+ TpmRqu = (TPM_RQU_COMMAND_HDR*)AllocatePool (\r
+ sizeof (*TpmRqu) + AdditionalParameterSize\r
+ );\r
+ if (TpmRqu == NULL) {\r
+ return TPM_PP_BIOS_FAILURE;\r
+ }\r
+\r
+ TpmRqu->tag = H2NS (TPM_TAG_RQU_COMMAND);\r
+ Size = (UINT32)(sizeof (*TpmRqu) + AdditionalParameterSize);\r
+ TpmRqu->paramSize = H2NL (Size);\r
+ TpmRqu->ordinal = H2NL (Ordinal);\r
+ gBS->CopyMem (TpmRqu + 1, AdditionalParameters, AdditionalParameterSize);\r
+\r
+ Status = TcgProtocol->PassThroughToTpm (\r
+ TcgProtocol,\r
+ Size,\r
+ (UINT8*)TpmRqu,\r
+ (UINT32)sizeof (TpmRsp),\r
+ (UINT8*)&TpmRsp\r
+ );\r
+ FreePool (TpmRqu);\r
+ if (EFI_ERROR (Status) || (TpmRsp.tag != H2NS (TPM_TAG_RSP_COMMAND))) {\r
+ return TPM_PP_BIOS_FAILURE;\r
+ }\r
+ return H2NL (TpmRsp.returnCode);\r
+}\r
+\r
+/**\r
+ Execute physical presence operation requested by the OS.\r
+\r
+ @param[in] TcgProtocol EFI TCG Protocol instance. \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
+**/\r
+TPM_RESULT\r
+ExecutePhysicalPresence (\r
+ IN EFI_TCG_PROTOCOL *TcgProtocol,\r
+ IN UINT8 CommandCode,\r
+ IN OUT UINT8 *PpiFlags\r
+ )\r
+{\r
+ BOOLEAN BoolVal;\r
+ TPM_RESULT TpmResponse;\r
+ UINT32 InData[5];\r
+\r
+ switch (CommandCode) {\r
+ case ENABLE:\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_PhysicalEnable,\r
+ 0,\r
+ NULL\r
+ );\r
+\r
+ case DISABLE:\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_PhysicalDisable,\r
+ 0,\r
+ NULL\r
+ );\r
+\r
+ case ACTIVATE:\r
+ BoolVal = FALSE;\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_PhysicalSetDeactivated,\r
+ sizeof (BoolVal),\r
+ &BoolVal\r
+ );\r
+\r
+ case DEACTIVATE:\r
+ BoolVal = TRUE;\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_PhysicalSetDeactivated,\r
+ sizeof (BoolVal),\r
+ &BoolVal\r
+ );\r
+\r
+ case CLEAR:\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_ForceClear,\r
+ 0,\r
+ NULL\r
+ );\r
+\r
+ case ENABLE_ACTIVATE:\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE, PpiFlags);\r
+ if (TpmResponse == 0) {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ACTIVATE, PpiFlags);\r
+ }\r
+ return TpmResponse;\r
+\r
+ case DEACTIVATE_DISABLE:\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, DEACTIVATE, PpiFlags);\r
+ if (TpmResponse == 0) {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, DISABLE, PpiFlags);\r
+ }\r
+ return TpmResponse;\r
+\r
+ case SET_OWNER_INSTALL_TRUE:\r
+ BoolVal = TRUE;\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_SetOwnerInstall,\r
+ sizeof (BoolVal),\r
+ &BoolVal\r
+ );\r
+\r
+ case SET_OWNER_INSTALL_FALSE:\r
+ BoolVal = FALSE;\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_SetOwnerInstall,\r
+ sizeof (BoolVal),\r
+ &BoolVal\r
+ );\r
+\r
+ case ENABLE_ACTIVATE_OWNER_TRUE:\r
+ //\r
+ // ENABLE_ACTIVATE + SET_OWNER_INSTALL_TRUE\r
+ // SET_OWNER_INSTALL_TRUE will be executed atfer reboot\r
+ //\r
+ if ((*PpiFlags & FLAG_RESET_TRACK) == 0) {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);\r
+ *PpiFlags |= FLAG_RESET_TRACK;\r
+ } else {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, SET_OWNER_INSTALL_TRUE, PpiFlags);\r
+ *PpiFlags &= ~FLAG_RESET_TRACK;\r
+ }\r
+ return TpmResponse;\r
+\r
+ case DEACTIVATE_DISABLE_OWNER_FALSE:\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, SET_OWNER_INSTALL_FALSE, PpiFlags);\r
+ if (TpmResponse == 0) {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, DEACTIVATE_DISABLE, PpiFlags);\r
+ }\r
+ return TpmResponse;\r
+\r
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:\r
+ InData[0] = H2NL (TPM_SET_STCLEAR_DATA); // CapabilityArea\r
+ InData[1] = H2NL (sizeof(UINT32)); // SubCapSize\r
+ InData[2] = H2NL (TPM_SD_DEFERREDPHYSICALPRESENCE); // SubCap\r
+ InData[3] = H2NL (sizeof(UINT32)); // SetValueSize\r
+ InData[4] = H2NL (1); // UnownedFieldUpgrade; bit0\r
+ return TpmCommandNoReturnData (\r
+ TcgProtocol,\r
+ TPM_ORD_SetCapability,\r
+ sizeof (UINT32) * 5,\r
+ InData\r
+ );\r
+\r
+ case SET_OPERATOR_AUTH:\r
+ //\r
+ // TPM_SetOperatorAuth\r
+ // This command requires UI to prompt user for Auth data\r
+ // Here it is NOT implemented\r
+ //\r
+ return TPM_PP_BIOS_FAILURE;\r
+\r
+ case CLEAR_ENABLE_ACTIVATE:\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, CLEAR, PpiFlags);\r
+ if (TpmResponse == 0) {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);\r
+ }\r
+ return TpmResponse;\r
+\r
+ case SET_NO_PPI_PROVISION_FALSE:\r
+ *PpiFlags &= ~FLAG_NO_PPI_PROVISION;\r
+ return 0;\r
+\r
+ case SET_NO_PPI_PROVISION_TRUE:\r
+ *PpiFlags |= FLAG_NO_PPI_PROVISION;\r
+ return 0;\r
+\r
+ case SET_NO_PPI_CLEAR_FALSE:\r
+ *PpiFlags &= ~FLAG_NO_PPI_CLEAR;\r
+ return 0;\r
+\r
+ case SET_NO_PPI_CLEAR_TRUE:\r
+ *PpiFlags |= FLAG_NO_PPI_CLEAR;\r
+ return 0;\r
+\r
+ case SET_NO_PPI_MAINTENANCE_FALSE:\r
+ *PpiFlags &= ~FLAG_NO_PPI_MAINTENANCE;\r
+ return 0;\r
+\r
+ case SET_NO_PPI_MAINTENANCE_TRUE:\r
+ *PpiFlags |= FLAG_NO_PPI_MAINTENANCE;\r
+ return 0;\r
+ \r
+ case ENABLE_ACTIVATE_CLEAR:\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);\r
+ if (TpmResponse == 0) {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, CLEAR, PpiFlags);\r
+ }\r
+ return TpmResponse;\r
+\r
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:\r
+ //\r
+ // ENABLE_ACTIVATE + CLEAR_ENABLE_ACTIVATE\r
+ // CLEAR_ENABLE_ACTIVATE will be executed atfer reboot.\r
+ //\r
+ if ((*PpiFlags & FLAG_RESET_TRACK) == 0) {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, ENABLE_ACTIVATE, PpiFlags);\r
+ *PpiFlags |= FLAG_RESET_TRACK;\r
+ } else {\r
+ TpmResponse = ExecutePhysicalPresence (TcgProtocol, CLEAR_ENABLE_ACTIVATE, PpiFlags);\r
+ *PpiFlags &= ~FLAG_RESET_TRACK;\r
+ } \r
+ return TpmResponse;\r
+\r
+ default:\r
+ ;\r
+ }\r
+ return TPM_PP_BIOS_FAILURE;\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
+**/\r
+BOOLEAN\r
+ReadUserKey (\r
+ IN BOOLEAN CautionKey\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ UINT16 InputKey;\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); \r
+ gBS->RestoreTPL (TPL_APPLICATION);\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
+ gBS->RaiseTPL (OldTpl); \r
+\r
+ if (InputKey != SCAN_ESC) {\r
+ return TRUE;\r
+ }\r
+ \r
+ return FALSE;\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
+UserConfirm (\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
+ mPpStringPackHandle = HiiAddPackages (\r
+ &gEfiPhysicalPresenceGuid,\r
+ NULL,\r
+ PhysicalPresenceDxeStrings,\r
+ NULL\r
+ );\r
+ ASSERT (mPpStringPackHandle != NULL);\r
+\r
+ switch (TpmPpCommand) {\r
+ case ENABLE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL); \r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case DISABLE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DISABLE), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+ \r
+ case ACTIVATE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACTIVATE), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case DEACTIVATE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DEACTIVATE), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1); \r
+ break;\r
+\r
+ case CLEAR:\r
+ CautionKey = TRUE;\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CLEAR), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);\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 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case ENABLE_ACTIVATE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE_ACTIVATE), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case DEACTIVATE_DISABLE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DEACTIVATE_DISABLE), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL); \r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_OFF), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case SET_OWNER_INSTALL_TRUE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ALLOW_TAKE_OWNERSHIP), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL); \r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case SET_OWNER_INSTALL_FALSE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_DISALLOW_TAKE_OWNERSHIP), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL); \r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case ENABLE_ACTIVATE_OWNER_TRUE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_TURN_ON), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case DEACTIVATE_DISABLE_OWNER_FALSE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_TURN_OFF), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL); \r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_OFF), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:\r
+ CautionKey = TRUE;\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_UNOWNED_FIELD_UPGRADE), NULL);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_UPGRADE_HEAD_STR), NULL); \r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+ \r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_MAINTAIN), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case SET_OPERATOR_AUTH:\r
+ //\r
+ // TPM_SetOperatorAuth\r
+ // This command requires UI to prompt user for Auth data\r
+ // Here it is NOT implemented\r
+ //\r
+ break;\r
+\r
+ case CLEAR_ENABLE_ACTIVATE:\r
+ CautionKey = TRUE;\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CLEAR_TURN_ON), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR_CONT), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case SET_NO_PPI_PROVISION_TRUE:\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_PROVISION), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_PPI_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ACCEPT_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_INFO), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case SET_NO_PPI_CLEAR_TRUE:\r
+ CautionKey = TRUE;\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CLEAR), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_PPI_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_CLEAR), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);\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 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_INFO), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case SET_NO_PPI_MAINTENANCE_TRUE:\r
+ CautionKey = TRUE;\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_MAINTAIN), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_PPI_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_MAINTAIN), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NO_PPI_INFO), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case ENABLE_ACTIVATE_CLEAR:\r
+ CautionKey = TRUE;\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);\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 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+ break;\r
+\r
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:\r
+ CautionKey = TRUE;\r
+ TmpStr2 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE), NULL);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_HEAD_STR), NULL);\r
+ UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_NOTE_ON), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_WARNING_CLEAR_CONT), NULL);\r
+ StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
+ FreePool (TmpStr1);\r
+\r
+ TmpStr1 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_CAUTION_KEY), NULL);\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 = HiiGetString (mPpStringPackHandle, STRING_TOKEN (TPM_REJECT_KEY), NULL);\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 (ReadUserKey (CautionKey)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE; \r
+}\r
+\r
+/**\r
+ Check and execute the requested physical presence command.\r
+ \r
+ @param[in, out] TcgPpData Point to the physical presence NV variable.\r
+\r
+**/\r
+VOID\r
+ExecutePendingTpmRequest (\r
+ IN OUT EFI_PHYSICAL_PRESENCE *TcgPpData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TCG_PROTOCOL *TcgProtocol;\r
+ UINTN DataSize;\r
+ UINT8 Flags;\r
+ BOOLEAN RequestConfirmed;\r
+\r
+ Flags = TcgPpData->Flags;\r
+ RequestConfirmed = FALSE; \r
+ switch (TcgPpData->PPRequest) {\r
+ case NO_ACTION:\r
+ return;\r
+ case ENABLE:\r
+ case DISABLE:\r
+ case ACTIVATE:\r
+ case DEACTIVATE:\r
+ case ENABLE_ACTIVATE:\r
+ case DEACTIVATE_DISABLE:\r
+ case SET_OWNER_INSTALL_TRUE:\r
+ case SET_OWNER_INSTALL_FALSE:\r
+ case ENABLE_ACTIVATE_OWNER_TRUE:\r
+ case DEACTIVATE_DISABLE_OWNER_FALSE:\r
+ case SET_OPERATOR_AUTH:\r
+ if ((Flags & FLAG_NO_PPI_PROVISION) != 0) {\r
+ RequestConfirmed = TRUE;\r
+ }\r
+ break;\r
+\r
+ case CLEAR:\r
+ case ENABLE_ACTIVATE_CLEAR:\r
+ if ((Flags & FLAG_NO_PPI_CLEAR) != 0) {\r
+ RequestConfirmed = TRUE;\r
+ }\r
+ break;\r
+\r
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:\r
+ if ((Flags & FLAG_NO_PPI_MAINTENANCE) != 0) {\r
+ RequestConfirmed = TRUE;\r
+ }\r
+ break;\r
+\r
+ case CLEAR_ENABLE_ACTIVATE:\r
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:\r
+ if ((Flags & FLAG_NO_PPI_CLEAR) != 0 && (Flags & FLAG_NO_PPI_PROVISION) != 0) {\r
+ RequestConfirmed = TRUE;\r
+ }\r
+ break; \r
+\r
+ case SET_NO_PPI_PROVISION_FALSE:\r
+ case SET_NO_PPI_CLEAR_FALSE:\r
+ case SET_NO_PPI_MAINTENANCE_FALSE:\r
+ RequestConfirmed = TRUE;\r
+ break;\r
+ }\r
+\r
+ if ((Flags & 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
+ if (!RequestConfirmed) {\r
+ //\r
+ // Print confirm text and wait for approval. \r
+ //\r
+ RequestConfirmed = UserConfirm (TcgPpData->PPRequest);\r
+ }\r
+\r
+ //\r
+ // Execute requested physical presence command.\r
+ //\r
+ TcgPpData->PPResponse = TPM_PP_USER_ABORT;\r
+ if (RequestConfirmed) {\r
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID**) &TcgProtocol);\r
+ ASSERT_EFI_ERROR (Status);\r
+ TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &TcgPpData->Flags);\r
+ }\r
+\r
+ //\r
+ // Clear request\r
+ //\r
+ if ((TcgPpData->Flags & FLAG_RESET_TRACK) == 0) {\r
+ TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
+ TcgPpData->PPRequest = 0; \r
+ }\r
+\r
+ //\r
+ // Save changes\r
+ //\r
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+ Status = gRT->SetVariable (\r
+ PHYSICAL_PRESENCE_VARIABLE,\r
+ &gEfiPhysicalPresenceGuid,\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 ACTIVATE:\r
+ case DEACTIVATE:\r
+ case CLEAR:\r
+ case ENABLE_ACTIVATE:\r
+ case DEACTIVATE_DISABLE:\r
+ case ENABLE_ACTIVATE_OWNER_TRUE:\r
+ case DEACTIVATE_DISABLE_OWNER_FALSE:\r
+ case DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:\r
+ case CLEAR_ENABLE_ACTIVATE:\r
+ case ENABLE_ACTIVATE_CLEAR:\r
+ case ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: \r
+ break;\r
+ default:\r
+ if (TcgPpData->PPRequest != 0) {\r
+ break;\r
+ }\r
+ return;\r
+ }\r
+\r
+ Print (L"Rebooting system to make TPM settings in effect\n");\r
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+ ASSERT (FALSE); \r
+}\r
+\r
+/**\r
+ Check and execute the physical presence command requested and\r
+ Lock physical presence.\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
+ BOOLEAN LifetimeLock;\r
+ BOOLEAN CmdEnable;\r
+ UINTN DataSize;\r
+ EFI_PHYSICAL_PRESENCE TcgPpData;\r
+ \r
+ //\r
+ // Check pending request, if not exist, just return.\r
+ //\r
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+ Status = gRT->GetVariable (\r
+ PHYSICAL_PRESENCE_VARIABLE,\r
+ &gEfiPhysicalPresenceGuid,\r
+ NULL,\r
+ &DataSize,\r
+ &TcgPpData\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", TcgPpData.Flags, TcgPpData.PPRequest));\r
+ \r
+ Status = GetTpmCapability (&LifetimeLock, &CmdEnable);\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+\r
+ if (!CmdEnable) {\r
+ if (LifetimeLock) {\r
+ //\r
+ // physicalPresenceCMDEnable is locked, can't execute physical presence command.\r
+ //\r
+ return ;\r
+ }\r
+ Status = TpmPhysicalPresence (TPM_PHYSICAL_PRESENCE_CMD_ENABLE);\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set operator physical presence flags\r
+ //\r
+ TpmPhysicalPresence (TPM_PHYSICAL_PRESENCE_PRESENT);\r
+ \r
+ //\r
+ // Execute pending TPM request.\r
+ // \r
+ ExecutePendingTpmRequest (&TcgPpData);\r
+ DEBUG ((EFI_D_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse));\r
+\r
+ //\r
+ // Lock physical presence.\r
+ //\r
+ TpmPhysicalPresence (TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK);\r
+}\r
+\r
+/**\r
+ The driver's entry point.\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
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverEntry (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_EVENT Event;\r
+ EFI_STATUS Status;\r
+ UINTN DataSize;\r
+ EFI_PHYSICAL_PRESENCE TcgPpData;\r
+ \r
+ //\r
+ // Initialize physical presence variable exists.\r
+ //\r
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+ Status = gRT->GetVariable (\r
+ PHYSICAL_PRESENCE_VARIABLE,\r
+ &gEfiPhysicalPresenceGuid,\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
+ TcgPpData.Flags |= FLAG_NO_PPI_PROVISION;\r
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+ Status = gRT->SetVariable (\r
+ PHYSICAL_PRESENCE_VARIABLE,\r
+ &gEfiPhysicalPresenceGuid,\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
+ //\r
+ // TPL Level of physical presence should be larger \r
+ // than one of TcgDxe driver (TPL_CALLBACK)\r
+ //\r
+ Status = EfiCreateEventReadyToBootEx (\r
+ TPL_CALLBACK,\r
+ OnReadyToBoot,\r
+ NULL,\r
+ &Event\r
+ );\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ The header file for TPM physical presence driver.\r
+\r
+Copyright (c) 2006 - 2011, 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 __PHYSICAL_PRESENCE_H__\r
+#define __PHYSICAL_PRESENCE_H__\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/TcgService.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/PhysicalPresenceData.h>\r
+\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
+#endif\r
--- /dev/null
+## @file\r
+# Component file for PhysicalPresenceDxe driver.\r
+#\r
+# Copyright (c) 2006 - 2010, 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 = PhysicalPresenceDxe\r
+ FILE_GUID = D85A4A0C-2E73-4491-92E1-DCEFC3882A68\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+\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
+ PhysicalPresence.c\r
+ PhysicalPresence.h\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
+\r
+[Protocols]\r
+ gEfiTcgProtocolGuid\r
+\r
+[Guids]\r
+ gEfiPhysicalPresenceGuid\r
+\r
+[Depex]\r
+ gEfiTcgProtocolGuid AND\r
+ gEfiVariableArchProtocolGuid AND\r
+ gEfiVariableWriteArchProtocolGuid AND\r
+ gEfiResetArchProtocolGuid\r
+\r
--- /dev/null
+/** @file\r
+ This driver produces PEI_LOCK_PHYSICAL_PRESENCE_PPI to indicate \r
+ whether TPM need be locked or not. It can be replaced by a platform \r
+ specific driver.\r
+\r
+Copyright (c) 2005 - 2011, 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 <Ppi/LockPhysicalPresence.h>\r
+#include <Ppi/ReadOnlyVariable2.h>\r
+#include <Guid/PhysicalPresenceData.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+\r
+/**\r
+ This interface returns whether TPM physical presence needs be locked or not.\r
+\r
+ @param[in] PeiServices The pointer to the PEI Services Table.\r
+\r
+ @retval TRUE The TPM physical presence should be locked.\r
+ @retval FALSE The TPM physical presence cannot be locked.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LockTpmPhysicalPresence (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices\r
+ );\r
+\r
+//\r
+// Gobal defintions for lock physical presence PPI and its descriptor.\r
+//\r
+PEI_LOCK_PHYSICAL_PRESENCE_PPI mLockPhysicalPresencePpi = {\r
+ LockTpmPhysicalPresence\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mLockPhysicalPresencePpiList = {\r
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+ &gPeiLockPhysicalPresencePpiGuid,\r
+ &mLockPhysicalPresencePpi\r
+};\r
+\r
+/**\r
+ This interface returns whether TPM physical presence needs be locked or not.\r
+\r
+ @param[in] PeiServices The pointer to the PEI Services Table.\r
+\r
+ @retval TRUE The TPM physical presence should be locked.\r
+ @retval FALSE The TPM physical presence cannot be locked.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LockTpmPhysicalPresence (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;\r
+ UINTN DataSize;\r
+ EFI_PHYSICAL_PRESENCE TcgPpData;\r
+\r
+ //\r
+ // The CRTM has sensed the physical presence assertion of the user. For example, \r
+ // the user has pressed the startup button or inserted a USB dongle. The details \r
+ // of the implementation are vendor-specific. Here we read a PCD value to indicate\r
+ // whether operator physical presence.\r
+ // \r
+ if (!PcdGetBool (PcdTpmPhysicalPresence)) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check the pending TPM requests. Lock TPM physical presence if there is no TPM \r
+ // request. \r
+ //\r
+ Status = PeiServicesLocatePpi (\r
+ &gEfiPeiReadOnlyVariable2PpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID **)&Variable\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+ Status = Variable->GetVariable ( \r
+ Variable, \r
+ PHYSICAL_PRESENCE_VARIABLE,\r
+ &gEfiPhysicalPresenceGuid,\r
+ NULL,\r
+ &DataSize,\r
+ &TcgPpData\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (TcgPpData.PPRequest != 0) {\r
+ return FALSE;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Lock TPM physical presence by default.\r
+ //\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Entry point of this module.\r
+\r
+ It installs lock physical presence PPI. \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 of install lock physical presence PPI.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeimEntry (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN CONST EFI_PEI_SERVICES **PeiServices\r
+ )\r
+{\r
+ return PeiServicesInstallPpi (&mLockPhysicalPresencePpiList);\r
+}\r
--- /dev/null
+## @file\r
+# Component description file for physical presence PEI module.\r
+#\r
+# Copyright (c) 2005 - 2011, 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
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = PhysicalPresencePei\r
+ FILE_GUID = 4FE772E8-FE3E-4086-B638-8C493C490488\r
+ MODULE_TYPE = PEIM\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = PeimEntry\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
+ PhysicalPresencePei.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+ PeimEntryPoint\r
+ PeiServicesLib\r
+\r
+[Ppis]\r
+ gPeiLockPhysicalPresencePpiGuid\r
+ gEfiPeiReadOnlyVariable2PpiGuid\r
+\r
+[Guids]\r
+ gEfiPhysicalPresenceGuid\r
+\r
+[Pcd]\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPhysicalPresence\r
+\r
+[Depex] \r
+ gEfiPeiMemoryDiscoveredPpiGuid AND\r
+ gEfiPeiReadOnlyVariable2PpiGuid AND\r
+ gPeiTpmInitializedPpiGuid\r
--- /dev/null
+/** @file\r
+ VFR file used by the TCG configuration component.\r
+\r
+Copyright (c) 2011, 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 "TcgConfigNvData.h"\r
+\r
+formset\r
+ guid = TCG_CONFIG_PRIVATE_GUID,\r
+ title = STRING_TOKEN(STR_TPM_TITLE),\r
+ help = STRING_TOKEN(STR_TPM_HELP),\r
+ classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,\r
+\r
+ varstore TCG_CONFIGURATION,\r
+ varid = TCG_CONFIGURATION_VARSTORE_ID,\r
+ name = TCG_CONFIGURATION,\r
+ guid = TCG_CONFIG_PRIVATE_GUID;\r
+\r
+ form formid = TCG_CONFIGURATION_FORM_ID,\r
+ title = STRING_TOKEN(STR_TPM_TITLE);\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+ suppressif TRUE;\r
+ checkbox varid = TCG_CONFIGURATION.TpmEnable,\r
+ prompt = STRING_TOKEN(STR_NULL),\r
+ help = STRING_TOKEN(STR_NULL),\r
+ endcheckbox;\r
+ endif;\r
+\r
+ suppressif TRUE;\r
+ checkbox varid = TCG_CONFIGURATION.TpmActivate,\r
+ prompt = STRING_TOKEN(STR_NULL),\r
+ help = STRING_TOKEN(STR_NULL),\r
+ endcheckbox;\r
+ endif;\r
+\r
+ suppressif TRUE;\r
+ checkbox varid = TCG_CONFIGURATION.OriginalHideTpm,\r
+ prompt = STRING_TOKEN(STR_NULL),\r
+ help = STRING_TOKEN(STR_NULL),\r
+ endcheckbox;\r
+ endif;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_TPM_STATE_HELP),\r
+ text = STRING_TOKEN(STR_TPM_STATE_PROMPT),\r
+ text = STRING_TOKEN(STR_TPM_STATE_CONTENT);\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+ label LABEL_TCG_CONFIGURATION_HIDETPM;\r
+\r
+ checkbox varid = TCG_CONFIGURATION.HideTpm,\r
+ questionid = KEY_HIDE_TPM,\r
+ prompt = STRING_TOKEN(STR_HIDE_TPM_PROMPT),\r
+ help = STRING_TOKEN(STR_HIDE_TPM_HELP),\r
+ flags = RESET_REQUIRED,\r
+ endcheckbox;\r
+\r
+ label LABEL_END;\r
+\r
+ grayoutif ideqval TCG_CONFIGURATION.OriginalHideTpm == 1;\r
+ oneof varid = TCG_CONFIGURATION.TpmOperation,\r
+ questionid = KEY_TPM_ACTION,\r
+ prompt = STRING_TOKEN(STR_TPM_OPERATION),\r
+ help = STRING_TOKEN(STR_TPM_OPERATION_HELP),\r
+ flags = INTERACTIVE,\r
+ //\r
+ // Disable (TPM_ORD_PhysicalDisable) command is not available when disabled.\r
+ // Activate/deactivate (TPM_ORD_physicalSetDeactivated) command is not available when disabled.\r
+ //\r
+ suppressif ideqval TCG_CONFIGURATION.TpmEnable == 0;\r
+ option text = STRING_TOKEN(STR_DISABLE), value = DISABLE, flags = 0;\r
+ option text = STRING_TOKEN(STR_TPM_ACTIVATE), value = ACTIVATE, flags = 0;\r
+ option text = STRING_TOKEN(STR_TPM_DEACTIVATE), value = DEACTIVATE, flags = 0;\r
+ option text = STRING_TOKEN(STR_TPM_DEACTIVATE_DISABLE), value = DEACTIVATE_DISABLE, flags = 0;\r
+ endif\r
+ //\r
+ // Clear (TPM_ORD_ForceClear) command is not available when disabled or deactivated. \r
+ //\r
+ suppressif ideqval TCG_CONFIGURATION.TpmEnable == 0 OR\r
+ ideqval TCG_CONFIGURATION.TpmActivate == 0;\r
+ option text = STRING_TOKEN(STR_TPM_CLEAR), value = CLEAR, flags = 0;\r
+ option text = STRING_TOKEN(STR_TPM_CLEAR_ENABLE_ACTIVATE), value = CLEAR_ENABLE_ACTIVATE, flags = 0;\r
+ endif\r
+\r
+ option text = STRING_TOKEN(STR_ENABLE), value = ENABLE, flags = 0;\r
+ option text = STRING_TOKEN(STR_TPM_ENABLE_ACTIVATE), value = ENABLE_ACTIVATE, flags = 0; \r
+ option text = STRING_TOKEN(STR_TPM_ENABLE_ACTIVATE_CLEAR), value = ENABLE_ACTIVATE_CLEAR, flags = 0;\r
+ option text = STRING_TOKEN(STR_TPM_ENABLE_ACTIVATE_CLEAR_E_A), value = ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE, flags = 0;\r
+ endoneof;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+ checkbox varid = TCG_CONFIGURATION.MorState,\r
+ questionid = KEY_TPM_MOR_ENABLE,\r
+ prompt = STRING_TOKEN(STR_MOR_PROMPT),\r
+ help = STRING_TOKEN(STR_MOR_HELP),\r
+ endcheckbox; \r
+ endif;\r
+\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/** @file\r
+ The module entry point for Tcg configuration module.\r
+\r
+Copyright (c) 2011, 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 "TcgConfigImpl.h"\r
+\r
+EFI_GUID gTcgConfigPrivateGuid = TCG_CONFIG_PRIVATE_GUID;\r
+\r
+/**\r
+ The entry point for Tcg 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
+TcgConfigDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TCG_CONFIG_PRIVATE_DATA *PrivateData;\r
+ EFI_TCG_PROTOCOL *TcgProtocol;\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
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ TcgProtocol = NULL;\r
+ }\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ ImageHandle,\r
+ &gTcgConfigPrivateGuid,\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 (TCG_CONFIG_PRIVATE_DATA), &mTcgConfigPrivateDateTemplate);\r
+ if (PrivateData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ PrivateData->TcgProtocol = TcgProtocol;\r
+ PrivateData->HideTpm = PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm);\r
+ \r
+ //\r
+ // Install TCG configuration form\r
+ //\r
+ Status = InstallTcgConfigForm (PrivateData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
+ //\r
+ // Install private GUID.\r
+ // \r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ImageHandle,\r
+ &gTcgConfigPrivateGuid,\r
+ PrivateData,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+ if (PrivateData != NULL) {\r
+ UninstallTcgConfigForm (PrivateData);\r
+ } \r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Unload the Tcg configuration form.\r
+\r
+ @param[in] ImageHandle The driver's image handle.\r
+\r
+ @retval EFI_SUCCESS The Tcg configuration form is unloaded.\r
+ @retval Others Failed to unload the form.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TcgConfigDriverUnload (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TCG_CONFIG_PRIVATE_DATA *PrivateData;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ ImageHandle,\r
+ &gTcgConfigPrivateGuid,\r
+ (VOID **) &PrivateData\r
+ ); \r
+ if (EFI_ERROR (Status)) {\r
+ return Status; \r
+ }\r
+ \r
+ ASSERT (PrivateData->Signature == TCG_CONFIG_PRIVATE_DATA_SIGNATURE);\r
+\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ &ImageHandle,\r
+ &gTcgConfigPrivateGuid,\r
+ PrivateData,\r
+ NULL\r
+ );\r
+ \r
+ UninstallTcgConfigForm (PrivateData);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+## @file\r
+# Component name for Tcg configuration module.\r
+#\r
+# Copyright (c) 2011, 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 = TcgConfigDxe\r
+ FILE_GUID = 1FA4DAFE-FA5D-4d75-BEA6-5863862C520A\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = TcgConfigDriverEntryPoint\r
+ UNLOAD_IMAGE = TcgConfigDriverUnload\r
+\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+ TcgConfigDriver.c\r
+ TcgConfigImpl.c\r
+ TcgConfigImpl.h\r
+ TcgConfig.vfr\r
+ TcgConfigStrings.uni\r
+ TcgConfigNvData.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
+ TpmCommLib\r
+\r
+[Guids]\r
+ gEfiPhysicalPresenceGuid\r
+ gEfiIfrTianoGuid\r
+\r
+[Protocols]\r
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES\r
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES\r
+ gEfiTcgProtocolGuid ## CONSUMES\r
+\r
+[FixedPcd]\r