+/** @file\r
+ This module implements TrEE Protocol.\r
+ \r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <IndustryStandard/SmBios.h>\r
+#include <IndustryStandard/TcpaAcpi.h>\r
+\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/SmBios.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/TcgEventHob.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/EventExitBootServiceFailed.h>\r
+#include <Guid/ImageAuthentication.h>\r
+#include <Guid/TpmInstance.h>\r
+\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/AcpiTable.h>\r
+#include <Protocol/MpService.h>\r
+#include <Protocol/VariableWrite.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Library/PerformanceLib.h>\r
+\r
+#define PERF_ID_TREE_DXE 0x3120\r
+\r
+typedef struct {\r
+ CHAR16 *VariableName;\r
+ EFI_GUID *VendorGuid;\r
+} VARIABLE_TYPE;\r
+\r
+#define EFI_TCG_LOG_AREA_SIZE 0x10000\r
+\r
+#define TREE_DEFAULT_MAX_COMMAND_SIZE 0x1000\r
+#define TREE_DEFAULT_MAX_RESPONSE_SIZE 0x1000\r
+\r
+typedef struct {\r
+ EFI_GUID *EventGuid;\r
+ TREE_EVENT_LOG_FORMAT LogFormat;\r
+ UINT32 BootHashAlg;\r
+ UINT16 DigestAlgID;\r
+ TPMI_ALG_HASH TpmHashAlgo;\r
+} TREE_EVENT_INFO_STRUCT;\r
+\r
+TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {\r
+ {&gTcgEventEntryHobGuid, TREE_EVENT_LOG_FORMAT_TCG_1_2, TREE_BOOT_HASH_ALG_SHA1, 0, TPM_ALG_SHA1},\r
+};\r
+\r
+#define TCG_EVENT_LOG_AREA_COUNT_MAX 5\r
+\r
+typedef struct {\r
+ TREE_EVENT_LOG_FORMAT EventLogFormat;\r
+ EFI_PHYSICAL_ADDRESS Lasa;\r
+ UINT64 Laml;\r
+ UINTN EventLogSize;\r
+ UINT8 *LastEvent;\r
+ BOOLEAN EventLogStarted;\r
+ BOOLEAN EventLogTruncated;\r
+} TCG_EVENT_LOG_AREA_STRUCT;\r
+\r
+typedef struct _TCG_DXE_DATA {\r
+ TREE_BOOT_SERVICE_CAPABILITY BsCap;\r
+ EFI_TCG_CLIENT_ACPI_TABLE *TcgClientAcpiTable;\r
+ EFI_TCG_SERVER_ACPI_TABLE *TcgServerAcpiTable;\r
+ TCG_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[TCG_EVENT_LOG_AREA_COUNT_MAX];\r
+} TCG_DXE_DATA;\r
+\r
+EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate = {\r
+ {\r
+ EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
+ sizeof (mTcgClientAcpiTemplate),\r
+ 0x02 //Revision\r
+ //\r
+ // Compiler initializes the remaining bytes to 0\r
+ // These fields should be filled in in production\r
+ //\r
+ },\r
+ 0, // 0 for PC Client Platform Class\r
+ 0, // Log Area Max Length\r
+ (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1) // Log Area Start Address\r
+};\r
+\r
+//\r
+// The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,\r
+// the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,\r
+// this _UID can be changed and should match with the _UID setting of the TPM \r
+// ACPI device object \r
+//\r
+EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate = {\r
+ {\r
+ EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
+ sizeof (mTcgServerAcpiTemplate),\r
+ 0x02 //Revision\r
+ //\r
+ // Compiler initializes the remaining bytes to 0\r
+ // These fields should be filled in in production\r
+ //\r
+ },\r
+ 1, // 1 for Server Platform Class\r
+ 0, // Reserved\r
+ 0, // Log Area Max Length\r
+ (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address\r
+ 0x0100, // TCG Specification revision 1.0\r
+ 2, // Device Flags\r
+ 0, // Interrupt Flags\r
+ 0, // GPE\r
+ {0}, // Reserved 3 bytes\r
+ 0, // Global System Interrupt\r
+ {\r
+ EFI_ACPI_3_0_SYSTEM_MEMORY,\r
+ 0,\r
+ 0,\r
+ EFI_ACPI_3_0_BYTE,\r
+ 0x0 // Base Address\r
+ },\r
+ 0, // Reserved\r
+ {0}, // Configuration Address\r
+ 0xFF, // ACPI _UID value of the device, can be changed for different platforms\r
+ 0, // ACPI _UID value of the device, can be changed for different platforms\r
+ 0, // ACPI _UID value of the device, can be changed for different platforms\r
+ 0 // ACPI _UID value of the device, can be changed for different platforms\r
+};\r
+\r
+TCG_DXE_DATA mTcgDxeData = {\r
+ {\r
+ sizeof (TREE_BOOT_SERVICE_CAPABILITY_1_0), // Size\r
+ { 1, 0 }, // StructureVersion\r
+ { 1, 0 }, // ProtocolVersion\r
+ TREE_BOOT_HASH_ALG_SHA1, // HashAlgorithmBitmap\r
+ TREE_EVENT_LOG_FORMAT_TCG_1_2, // SupportedEventLogs\r
+ TRUE, // TrEEPresentFlag\r
+ TREE_DEFAULT_MAX_COMMAND_SIZE, // MaxCommandSize\r
+ TREE_DEFAULT_MAX_RESPONSE_SIZE, // MaxResponseSize\r
+ 0 // ManufacturerID\r
+ },\r
+ &mTcgClientAcpiTemplate,\r
+ &mTcgServerAcpiTemplate,\r
+};\r
+\r
+UINTN mBootAttempts = 0;\r
+CHAR16 mBootVarName[] = L"BootOrder";\r
+\r
+VARIABLE_TYPE mVariableType[] = {\r
+ {EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid},\r
+ {EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid},\r
+ {EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid},\r
+ {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid},\r
+ {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},\r
+};\r
+\r
+EFI_HANDLE mImageHandle;\r
+\r
+/**\r
+ Measure PE image into TPM log based on the authenticode image hashing in\r
+ PE/COFF Specification 8.0 Appendix A.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ PE/COFF image is external input, so this function will validate its data structure\r
+ within this image buffer before use.\r
+\r
+ @param[in] PCRIndex TPM PCR index\r
+ @param[in] ImageAddress Start address of image buffer.\r
+ @param[in] ImageSize Image size\r
+ @param[out] DigestList Digeest list of this image.\r
+\r
+ @retval EFI_SUCCESS Successfully measure image.\r
+ @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.\r
+ @retval other error value\r
+**/\r
+EFI_STATUS\r
+MeasurePeImageAndExtend (\r
+ IN UINT32 PCRIndex,\r
+ IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
+ IN UINTN ImageSize,\r
+ OUT TPML_DIGEST_VALUES *DigestList\r
+ );\r
+\r
+/**\r
+\r
+ This function dump raw data.\r
+\r
+ @param Data raw data\r
+ @param Size raw data size\r
+\r
+**/\r
+VOID\r
+InternalDumpData (\r
+ IN UINT8 *Data,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ UINTN Index;\r
+ for (Index = 0; Index < Size; Index++) {\r
+ DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index]));\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ This function dump raw data with colume format.\r
+\r
+ @param Data raw data\r
+ @param Size raw data size\r
+\r
+**/\r
+VOID\r
+InternalDumpHex (\r
+ IN UINT8 *Data,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ UINTN Left;\r
+\r
+#define COLUME_SIZE (16 * 2)\r
+\r
+ Count = Size / COLUME_SIZE;\r
+ Left = Size % COLUME_SIZE;\r
+ for (Index = 0; Index < Count; Index++) {\r
+ DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));\r
+ InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+ }\r
+\r
+ if (Left != 0) {\r
+ DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));\r
+ InternalDumpData (Data + Index * COLUME_SIZE, Left);\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+ }\r
+}\r
+\r
+/**\r
+ Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function\r
+ Caller is responsible to free LocationBuf.\r
+\r
+ @param[out] LocationBuf Returns Processor Location Buffer.\r
+ @param[out] Num Returns processor number.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_UNSUPPORTED MpService protocol not found.\r
+\r
+**/\r
+EFI_STATUS\r
+GetProcessorsCpuLocation (\r
+ OUT EFI_CPU_PHYSICAL_LOCATION **LocationBuf,\r
+ OUT UINTN *Num\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MP_SERVICES_PROTOCOL *MpProtocol;\r
+ UINTN ProcessorNum;\r
+ UINTN EnabledProcessorNum;\r
+ EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
+ EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
+ UINTN Index;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // MP protocol is not installed\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = MpProtocol->GetNumberOfProcessors(\r
+ MpProtocol,\r
+ &ProcessorNum,\r
+ &EnabledProcessorNum\r
+ );\r
+ if (EFI_ERROR(Status)){\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->AllocatePool(\r
+ EfiBootServicesData,\r
+ sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
+ (VOID **) &ProcessorLocBuf\r
+ );\r
+ if (EFI_ERROR(Status)){\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get each processor Location info\r
+ //\r
+ for (Index = 0; Index < ProcessorNum; Index++) {\r
+ Status = MpProtocol->GetProcessorInfo(\r
+ MpProtocol,\r
+ Index,\r
+ &ProcessorInfo\r
+ );\r
+ if (EFI_ERROR(Status)){\r
+ FreePool(ProcessorLocBuf);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get all Processor Location info & measure\r
+ //\r
+ CopyMem(\r
+ &ProcessorLocBuf[Index],\r
+ &ProcessorInfo.Location,\r
+ sizeof(EFI_CPU_PHYSICAL_LOCATION)\r
+ );\r
+ }\r
+\r
+ *LocationBuf = ProcessorLocBuf;\r
+ *Num = ProcessorNum;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The EFI_TREE_PROTOCOL GetCapability function call provides protocol\r
+ capability information and state information about the TrEE.\r
+\r
+ @param[in] This Indicates the calling context\r
+ @param[in, out] ProtocolCapability The caller allocates memory for a TREE_BOOT_SERVICE_CAPABILITY\r
+ structure and sets the size field to the size of the structure allocated.\r
+ The callee fills in the fields with the EFI protocol capability information\r
+ and the current TrEE state information up to the number of fields which\r
+ fit within the size of the structure passed in.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
+ The ProtocolCapability variable will not be populated. \r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
+ The ProtocolCapability variable will not be populated.\r
+ @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response.\r
+ It will be partially populated (required Size field will be set). \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeGetCapability (\r
+ IN EFI_TREE_PROTOCOL *This,\r
+ IN OUT TREE_BOOT_SERVICE_CAPABILITY *ProtocolCapability\r
+ )\r
+{\r
+ DEBUG ((EFI_D_ERROR, "TreeGetCapability ...\n"));\r
+\r
+ if ((This == NULL) || (ProtocolCapability == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ProtocolCapability->Size < mTcgDxeData.BsCap.Size) {\r
+ ProtocolCapability->Size = mTcgDxeData.BsCap.Size;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, mTcgDxeData.BsCap.Size);\r
+ DEBUG ((EFI_D_ERROR, "TreeGetCapability - %r\n", EFI_SUCCESS));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function dump event log.\r
+\r
+ @param[in] EventLogFormat The type of the event log for which the information is requested.\r
+ @param[in] EventLogLocation A pointer to the memory address of the event log.\r
+ @param[in] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
+ address of the start of the last entry in the event log in memory.\r
+**/\r
+VOID\r
+DumpEventLog (\r
+ IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
+ IN EFI_PHYSICAL_ADDRESS EventLogLocation,\r
+ IN EFI_PHYSICAL_ADDRESS EventLogLastEntry\r
+ )\r
+{\r
+ TCG_PCR_EVENT_HDR *EventHdr;\r
+ UINTN Index;\r
+\r
+ DEBUG ((EFI_D_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));\r
+ \r
+ switch (EventLogFormat) {\r
+ case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
+ EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;\r
+ while ((UINTN)EventHdr <= EventLogLastEntry) {\r
+ DEBUG ((EFI_D_INFO, " Event:\n"));\r
+ DEBUG ((EFI_D_INFO, " PCRIndex - %d\n", EventHdr->PCRIndex));\r
+ DEBUG ((EFI_D_INFO, " EventType - 0x%08x\n", EventHdr->EventType));\r
+ DEBUG ((EFI_D_INFO, " Digest - "));\r
+ for (Index = 0; Index < sizeof(TCG_DIGEST); Index++) {\r
+ DEBUG ((EFI_D_INFO, "%02x ", EventHdr->Digest.digest[Index]));\r
+ }\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+ DEBUG ((EFI_D_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize));\r
+ InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);\r
+ EventHdr = (TCG_PCR_EVENT_HDR *)((UINTN)EventHdr + sizeof(TCG_PCR_EVENT_HDR) + EventHdr->EventSize);\r
+ }\r
+ break;\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ The EFI_TREE_PROTOCOL Get Event Log function call allows a caller to\r
+ retrieve the address of a given event log and its last entry. \r
+\r
+ @param[in] This Indicates the calling context\r
+ @param[in] EventLogFormat The type of the event log for which the information is requested.\r
+ @param[out] EventLogLocation A pointer to the memory address of the event log.\r
+ @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
+ address of the start of the last entry in the event log in memory.\r
+ @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would\r
+ have exceeded the area allocated for events, this value is set to TRUE.\r
+ Otherwise, the value will be FALSE and the Event Log will be complete.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect\r
+ (e.g. asking for an event log whose format is not supported).\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeGetEventLog (\r
+ IN EFI_TREE_PROTOCOL *This,\r
+ IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,\r
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry,\r
+ OUT BOOLEAN *EventLogTruncated\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ DEBUG ((EFI_D_ERROR, "TreeGetEventLog ...\n"));\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+ if (EventLogLocation != NULL) {\r
+ *EventLogLocation = 0;\r
+ }\r
+ if (EventLogLastEntry != NULL) {\r
+ *EventLogLastEntry = 0;\r
+ }\r
+ if (EventLogTruncated != NULL) {\r
+ *EventLogTruncated = FALSE;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EventLogLocation != NULL) {\r
+ *EventLogLocation = mTcgDxeData.EventLogAreaStruct[Index].Lasa;\r
+ DEBUG ((EFI_D_ERROR, "TreeGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));\r
+ }\r
+\r
+ if (EventLogLastEntry != NULL) {\r
+ if (!mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted) {\r
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
+ } else {\r
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].LastEvent;\r
+ }\r
+ DEBUG ((EFI_D_ERROR, "TreeGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));\r
+ }\r
+\r
+ if (EventLogTruncated != NULL) {\r
+ *EventLogTruncated = mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated;\r
+ DEBUG ((EFI_D_ERROR, "TreeGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));\r
+ }\r
+\r
+ DEBUG ((EFI_D_ERROR, "TreeGetEventLog - %r\n", EFI_SUCCESS));\r
+\r
+ // Dump Event Log for debug purpose\r
+ if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {\r
+ DumpEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add a new entry to the Event Log.\r
+\r
+ @param[in, out] EventLogPtr Pointer to the Event Log data. \r
+ @param[in, out] LogSize Size of the Event Log. \r
+ @param[in] MaxSize Maximum size of the Event Log.\r
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. \r
+ @param[in] NewEventHdrSize New event header size.\r
+ @param[in] NewEventData Pointer to the new event data. \r
+ @param[in] NewEventSize New event data size.\r
+ \r
+ @retval EFI_SUCCESS The new event log entry was added.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgCommLogEvent (\r
+ IN OUT UINT8 **EventLogPtr,\r
+ IN OUT UINTN *LogSize,\r
+ IN UINTN MaxSize,\r
+ IN VOID *NewEventHdr,\r
+ IN UINT32 NewEventHdrSize,\r
+ IN UINT8 *NewEventData,\r
+ IN UINT32 NewEventSize\r
+ )\r
+{\r
+ UINTN NewLogSize;\r
+\r
+ if (NewEventSize > MAX_ADDRESS - NewEventHdrSize) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLogSize = NewEventHdrSize + NewEventSize;\r
+\r
+ if (NewLogSize > MAX_ADDRESS - *LogSize) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (NewLogSize + *LogSize > MaxSize) {\r
+ DEBUG ((EFI_D_INFO, " MaxSize - 0x%x\n", MaxSize));\r
+ DEBUG ((EFI_D_INFO, " NewLogSize - 0x%x\n", NewLogSize));\r
+ DEBUG ((EFI_D_INFO, " LogSize - 0x%x\n", *LogSize));\r
+ DEBUG ((EFI_D_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *EventLogPtr += *LogSize;\r
+ *LogSize += NewLogSize;\r
+ CopyMem (*EventLogPtr, NewEventHdr, NewEventHdrSize);\r
+ CopyMem (\r
+ *EventLogPtr + NewEventHdrSize,\r
+ NewEventData,\r
+ NewEventSize\r
+ );\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add a new entry to the Event Log.\r
+\r
+ @param[in] EventLogFormat The type of the event log for which the information is requested.\r
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. \r
+ @param[in] NewEventHdrSize New event header size.\r
+ @param[in] NewEventData Pointer to the new event data. \r
+ @param[in] NewEventSize New event data size.\r
+\r
+ @retval EFI_SUCCESS The new event log entry was added.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgDxeLogEvent (\r
+ IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
+ IN VOID *NewEventHdr,\r
+ IN UINT32 NewEventHdrSize,\r
+ IN UINT8 *NewEventData,\r
+ IN UINT32 NewEventSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated) {\r
+ return EFI_VOLUME_FULL;\r
+ }\r
+\r
+ mTcgDxeData.EventLogAreaStruct[Index].LastEvent = (UINT8*)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].Lasa;\r
+ Status = TcgCommLogEvent (\r
+ &mTcgDxeData.EventLogAreaStruct[Index].LastEvent,\r
+ &mTcgDxeData.EventLogAreaStruct[Index].EventLogSize,\r
+ (UINTN)mTcgDxeData.EventLogAreaStruct[Index].Laml,\r
+ NewEventHdr,\r
+ NewEventHdrSize,\r
+ NewEventData,\r
+ NewEventSize\r
+ );\r
+ \r
+ if (Status == EFI_DEVICE_ERROR) {\r
+ return EFI_DEVICE_ERROR;\r
+ } else if (Status == EFI_OUT_OF_RESOURCES) {\r
+ mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated = TRUE;\r
+ return EFI_VOLUME_FULL;\r
+ } else if (Status == EFI_SUCCESS) {\r
+ mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted = TRUE;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function return hash algorithm from event log format.\r
+\r
+ @param[in] EventLogFormat Event log format.\r
+\r
+ @return hash algorithm.\r
+**/\r
+TPMI_ALG_HASH\r
+TrEEGetHashAlgoFromLogFormat (\r
+ IN TREE_EVENT_LOG_FORMAT EventLogFormat\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {\r
+ return mTreeEventInfo[Index].TpmHashAlgo;\r
+ }\r
+ }\r
+ return TPM_ALG_SHA1;\r
+}\r
+\r
+/**\r
+ This function return hash algorithm ID from event log format.\r
+\r
+ @param[in] EventLogFormat Event log format.\r
+\r
+ @return hash algorithm ID.\r
+**/\r
+UINT16\r
+TrEEGetAlgIDFromLogFormat (\r
+ IN TREE_EVENT_LOG_FORMAT EventLogFormat\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {\r
+ return mTreeEventInfo[Index].DigestAlgID;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+/**\r
+ This function return boot hash algorithm from event log format.\r
+\r
+ @param[in] EventLogFormat Event log format.\r
+\r
+ @return boot hash algorithm.\r
+**/\r
+UINT32\r
+TrEEGetBootHashAlgFromLogFormat (\r
+ IN TREE_EVENT_LOG_FORMAT EventLogFormat\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {\r
+ return mTreeEventInfo[Index].BootHashAlg;\r
+ }\r
+ }\r
+ return TREE_BOOT_HASH_ALG_SHA1;\r
+}\r
+\r
+/**\r
+ This function get digest from digest list.\r
+\r
+ @param HashAlg digest algorithm\r
+ @param DigestList digest list\r
+ @param Digest digest\r
+\r
+ @retval EFI_SUCCESS Sha1Digest is found and returned.\r
+ @retval EFI_NOT_FOUND Sha1Digest is not found.\r
+**/\r
+EFI_STATUS\r
+Tpm2GetDigestFromDigestList (\r
+ IN TPMI_ALG_HASH HashAlg,\r
+ IN TPML_DIGEST_VALUES *DigestList,\r
+ IN VOID *Digest\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 DigestSize;\r
+\r
+ DigestSize = GetHashSizeFromAlgo (HashAlg);\r
+ for (Index = 0; Index < DigestList->count; Index++) {\r
+ if (DigestList->digests[Index].hashAlg == HashAlg) {\r
+ CopyMem (\r
+ Digest,\r
+ &DigestList->digests[Index].digest,\r
+ DigestSize\r
+ );\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Add a new entry to the Event Log.\r
+\r
+ @param[in] DigestList A list of digest.\r
+ @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
+ @param[in] NewEventData Pointer to the new event data.\r
+\r
+ @retval EFI_SUCCESS The new event log entry was added.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
+**/\r
+EFI_STATUS\r
+TcgDxeLogHashEvent (\r
+ IN TPML_DIGEST_VALUES *DigestList,\r
+ IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
+ IN UINT8 *NewEventData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ UINTN Index;\r
+ EFI_STATUS RetStatus;\r
+\r
+ RetStatus = EFI_SUCCESS;\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));\r
+ switch (mTreeEventInfo[Index].LogFormat) {\r
+ case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
+ Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Enter critical region\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+ Status = TcgDxeLogEvent (\r
+ mTreeEventInfo[Index].LogFormat,\r
+ NewEventHdr,\r
+ sizeof(TCG_PCR_EVENT_HDR),\r
+ NewEventData,\r
+ NewEventHdr->EventSize\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ RetStatus = Status;\r
+ }\r
+ gBS->RestoreTPL (OldTpl);\r
+ //\r
+ // Exit critical region\r
+ //\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ return RetStatus;\r
+}\r
+\r
+/**\r
+ Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
+ and add an entry to the Event Log.\r
+\r
+ @param[in] Flags Bitmap providing additional information.\r
+ @param[in] HashData Physical address of the start of the data buffer \r
+ to be hashed, extended, and logged.\r
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
+ @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. \r
+ @param[in] NewEventData Pointer to the new event data. \r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgDxeHashLogExtendEvent (\r
+ IN UINT64 Flags,\r
+ IN UINT8 *HashData,\r
+ IN UINT64 HashDataLen,\r
+ IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
+ IN UINT8 *NewEventData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TPML_DIGEST_VALUES DigestList;\r
+\r
+ Status = HashAndExtend (\r
+ NewEventHdr->PCRIndex,\r
+ HashData,\r
+ (UINTN)HashDataLen,\r
+ &DigestList\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
+ Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The EFI_TREE_PROTOCOL HashLogExtendEvent function call provides callers with\r
+ an opportunity to extend and optionally log events without requiring\r
+ knowledge of actual TPM commands. \r
+ The extend operation will occur even if this function cannot create an event\r
+ log entry (e.g. due to the event log being full). \r
+\r
+ @param[in] This Indicates the calling context\r
+ @param[in] Flags Bitmap providing additional information.\r
+ @param[in] DataToHash Physical address of the start of the data buffer to be hashed. \r
+ @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash.\r
+ @param[in] Event Pointer to data buffer containing information about the event.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
+ @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
+ @retval EFI_UNSUPPORTED The PE/COFF image type is not supported.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeHashLogExtendEvent (\r
+ IN EFI_TREE_PROTOCOL *This,\r
+ IN UINT64 Flags,\r
+ IN EFI_PHYSICAL_ADDRESS DataToHash,\r
+ IN UINT64 DataToHashLen,\r
+ IN TrEE_EVENT *Event\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TCG_PCR_EVENT_HDR NewEventHdr;\r
+ TPML_DIGEST_VALUES DigestList;\r
+\r
+ DEBUG ((EFI_D_ERROR, "TreeHashLogExtendEvent ...\n"));\r
+\r
+ if ((This == NULL) || (DataToHash == 0) || (Event == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (Event->Size < Event->Header.HeaderSize + sizeof(UINT32)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Event->Header.PCRIndex > MAX_PCR_INDEX) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ NewEventHdr.PCRIndex = Event->Header.PCRIndex;\r
+ NewEventHdr.EventType = Event->Header.EventType;\r
+ NewEventHdr.EventSize = Event->Size - sizeof(UINT32) - Event->Header.HeaderSize;\r
+ if ((Flags & PE_COFF_IMAGE) != 0) {\r
+ Status = MeasurePeImageAndExtend (\r
+ NewEventHdr.PCRIndex,\r
+ DataToHash,\r
+ (UINTN)DataToHashLen,\r
+ &DigestList\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
+ Status = TcgDxeLogHashEvent (&DigestList, &NewEventHdr, Event->Event);\r
+ }\r
+ }\r
+ } else {\r
+ Status = TcgDxeHashLogExtendEvent (\r
+ Flags,\r
+ (UINT8 *) (UINTN) DataToHash,\r
+ DataToHashLen,\r
+ &NewEventHdr,\r
+ Event->Event\r
+ );\r
+ }\r
+ DEBUG ((EFI_D_ERROR, "TreeHashLogExtendEvent - %r\n", Status));\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This service enables the sending of commands to the TrEE.\r
+\r
+ @param[in] This Indicates the calling context\r
+ @param[in] InputParameterBlockSize Size of the TrEE input parameter block.\r
+ @param[in] InputParameterBlock Pointer to the TrEE input parameter block.\r
+ @param[in] OutputParameterBlockSize Size of the TrEE output parameter block.\r
+ @param[in] OutputParameterBlock Pointer to the TrEE output parameter block.\r
+\r
+ @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received.\r
+ @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
+ @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TreeSubmitCommand (\r
+ IN EFI_TREE_PROTOCOL *This,\r
+ IN UINT32 InputParameterBlockSize,\r
+ IN UINT8 *InputParameterBlock,\r
+ IN UINT32 OutputParameterBlockSize,\r
+ IN UINT8 *OutputParameterBlock\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((EFI_D_ERROR, "TreeSubmitCommand ...\n"));\r
+\r
+ if ((This == NULL) ||\r
+ (InputParameterBlockSize == 0) || (InputParameterBlock == NULL) ||\r
+ (OutputParameterBlockSize == 0) || (OutputParameterBlock == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (InputParameterBlockSize >= mTcgDxeData.BsCap.MaxCommandSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (OutputParameterBlockSize >= mTcgDxeData.BsCap.MaxResponseSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = Tpm2SubmitCommand (\r
+ InputParameterBlockSize,\r
+ InputParameterBlock,\r
+ &OutputParameterBlockSize,\r
+ OutputParameterBlock\r
+ );\r
+ DEBUG ((EFI_D_ERROR, "TreeSubmitCommand - %r\n", Status));\r
+ return Status;\r
+}\r
+\r
+\r
+EFI_TREE_PROTOCOL mTreeProtocol = {\r
+ TreeGetCapability,\r
+ TreeGetEventLog,\r
+ TreeHashLogExtendEvent,\r
+ TreeSubmitCommand\r
+};\r
+\r
+/**\r
+ Initialize the Event Log and log events passed from the PEI phase.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+SetupEventLog (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *TcgEvent;\r
+ EFI_PEI_HOB_POINTERS GuidHob;\r
+ EFI_PHYSICAL_ADDRESS Lasa;\r
+ UINTN Index;\r
+\r
+ DEBUG ((EFI_D_INFO, "SetupEventLog\n"));\r
+\r
+ //\r
+ // 1. Create Log Area\r
+ //\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ mTcgDxeData.EventLogAreaStruct[Index].EventLogFormat = mTreeEventInfo[Index].LogFormat;\r
+ Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE),\r
+ &Lasa\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ mTcgDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
+ mTcgDxeData.EventLogAreaStruct[Index].Laml = EFI_TCG_LOG_AREA_SIZE;\r
+ //\r
+ // To initialize them as 0xFF is recommended \r
+ // because the OS can know the last entry for that.\r
+ //\r
+ SetMem ((VOID *)(UINTN)Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF);\r
+ }\r
+\r
+ //\r
+ // 2. Create ACPI table for TCG1.2 only\r
+ //\r
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
+ mTcgClientAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
+ mTcgClientAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;\r
+ } else {\r
+ mTcgServerAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
+ mTcgServerAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;\r
+ }\r
+\r
+ //\r
+ // 3. Sync data from PEI to DXE\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
+ GuidHob.Raw = GetHobList ();\r
+ Status = EFI_SUCCESS;\r
+ while (!EFI_ERROR (Status) && \r
+ (GuidHob.Raw = GetNextGuidHob (mTreeEventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) {\r
+ TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid);\r
+ GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
+ switch (mTreeEventInfo[Index].LogFormat) {\r
+ case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
+ Status = TcgDxeLogEvent (\r
+ mTreeEventInfo[Index].LogFormat,\r
+ TcgEvent,\r
+ sizeof(TCG_PCR_EVENT_HDR),\r
+ ((TCG_PCR_EVENT*)TcgEvent)->Event,\r
+ ((TCG_PCR_EVENT_HDR*)TcgEvent)->EventSize\r
+ );\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Measure and log an action string, and extend the measurement result into PCR[5].\r
+\r
+ @param[in] String A specific string that indicates an Action event. \r
+ \r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+TcgMeasureAction (\r
+ IN CHAR8 *String\r
+ )\r
+{\r
+ TCG_PCR_EVENT_HDR TcgEvent;\r
+\r
+ TcgEvent.PCRIndex = 5;\r
+ TcgEvent.EventType = EV_EFI_ACTION;\r
+ TcgEvent.EventSize = (UINT32)AsciiStrLen (String);\r
+ return TcgDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8*)String,\r
+ TcgEvent.EventSize,\r
+ &TcgEvent,\r
+ (UINT8 *) String\r
+ );\r
+}\r
+\r
+/**\r
+ Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureHandoffTables (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTable;\r
+ TCG_PCR_EVENT_HDR TcgEvent;\r
+ EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
+ UINTN ProcessorNum;\r
+ EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
+\r
+ //\r
+ // Measure SMBIOS with EV_EFI_HANDOFF_TABLES to PCR[1]\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiSmbiosTableGuid,\r
+ (VOID **) &SmbiosTable\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ ASSERT (SmbiosTable != NULL);\r
+\r
+ TcgEvent.PCRIndex = 1;\r
+ TcgEvent.EventType = EV_EFI_HANDOFF_TABLES;\r
+ TcgEvent.EventSize = sizeof (HandoffTables);\r
+\r
+ HandoffTables.NumberOfTables = 1;\r
+ HandoffTables.TableEntry[0].VendorGuid = gEfiSmbiosTableGuid;\r
+ HandoffTables.TableEntry[0].VendorTable = SmbiosTable;\r
+\r
+ DEBUG ((DEBUG_INFO, "The Smbios Table starts at: 0x%x\n", SmbiosTable->TableAddress));\r
+ DEBUG ((DEBUG_INFO, "The Smbios Table size: 0x%x\n", SmbiosTable->TableLength));\r
+\r
+ Status = TcgDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8*)(UINTN)SmbiosTable->TableAddress,\r
+ SmbiosTable->TableLength,\r
+ &TcgEvent,\r
+ (UINT8*)&HandoffTables\r
+ );\r
+ }\r
+\r
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
+ //\r
+ // Tcg Server spec. \r
+ // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
+ //\r
+ Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);\r
+\r
+ if (!EFI_ERROR(Status)){\r
+ TcgEvent.PCRIndex = 1;\r
+ TcgEvent.EventType = EV_TABLE_OF_DEVICES;\r
+ TcgEvent.EventSize = sizeof (HandoffTables);\r
+\r
+ HandoffTables.NumberOfTables = 1;\r
+ HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
+ HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
+\r
+ Status = TcgDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8*)(UINTN)ProcessorLocBuf,\r
+ sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
+ &TcgEvent,\r
+ (UINT8*)&HandoffTables\r
+ );\r
+\r
+ FreePool(ProcessorLocBuf);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Measure and log Separator event, and extend the measurement result into a specific PCR.\r
+\r
+ @param[in] PCRIndex PCR index. \r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureSeparatorEvent (\r
+ IN TPM_PCRINDEX PCRIndex\r
+ )\r
+{\r
+ TCG_PCR_EVENT_HDR TcgEvent;\r
+ UINT32 EventData;\r
+\r
+ DEBUG ((EFI_D_ERROR, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex));\r
+\r
+ EventData = 0;\r
+ TcgEvent.PCRIndex = PCRIndex;\r
+ TcgEvent.EventType = EV_SEPARATOR;\r
+ TcgEvent.EventSize = (UINT32)sizeof (EventData);\r
+ return TcgDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)&EventData,\r
+ sizeof (EventData),\r
+ &TcgEvent,\r
+ (UINT8 *)&EventData\r
+ );\r
+}\r
+\r
+/**\r
+ Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
+\r
+ @param[in] PCRIndex PCR Index. \r
+ @param[in] EventType Event type. \r
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
+ @param[in] VendorGuid A unique identifier for the vendor.\r
+ @param[in] VarData The content of the variable data. \r
+ @param[in] VarSize The size of the variable data. \r
+ \r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureVariable (\r
+ IN TPM_PCRINDEX PCRIndex,\r
+ IN TCG_EVENTTYPE EventType,\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN VOID *VarData,\r
+ IN UINTN VarSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TCG_PCR_EVENT_HDR TcgEvent;\r
+ UINTN VarNameLength;\r
+ EFI_VARIABLE_DATA_TREE *VarLog;\r
+\r
+ ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));\r
+\r
+ DEBUG ((EFI_D_ERROR, "TrEEDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType));\r
+ DEBUG ((EFI_D_ERROR, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
+\r
+ VarNameLength = StrLen (VarName);\r
+ TcgEvent.PCRIndex = PCRIndex;\r
+ TcgEvent.EventType = EventType;\r
+ TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
+ - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
+\r
+ VarLog = (EFI_VARIABLE_DATA_TREE*)AllocatePool (TcgEvent.EventSize);\r
+ if (VarLog == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ VarLog->VariableName = *VendorGuid;\r
+ VarLog->UnicodeNameLength = VarNameLength;\r
+ VarLog->VariableDataLength = VarSize;\r
+ CopyMem (\r
+ VarLog->UnicodeName,\r
+ VarName,\r
+ VarNameLength * sizeof (*VarName)\r
+ );\r
+ if (VarSize != 0) {\r
+ CopyMem (\r
+ (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
+ VarData,\r
+ VarSize\r
+ );\r
+ }\r
+\r
+ if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
+ //\r
+ // Digest is the event data (EFI_VARIABLE_DATA_TREE)\r
+ //\r
+ Status = TcgDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8*)VarLog,\r
+ TcgEvent.EventSize,\r
+ &TcgEvent,\r
+ (UINT8*)VarLog\r
+ );\r
+ } else {\r
+ Status = TcgDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8*)VarData,\r
+ VarSize,\r
+ &TcgEvent,\r
+ (UINT8*)VarLog\r
+ );\r
+ }\r
+ FreePool (VarLog);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Read then Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
+\r
+ @param[in] PCRIndex PCR Index. \r
+ @param[in] EventType Event type. \r
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
+ @param[in] VendorGuid A unique identifier for the vendor.\r
+ @param[out] VarSize The size of the variable data. \r
+ @param[out] VarData Pointer to the content of the variable. \r
+ \r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadAndMeasureVariable (\r
+ IN TPM_PCRINDEX PCRIndex,\r
+ IN TCG_EVENTTYPE EventType,\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VarSize,\r
+ OUT VOID **VarData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize);\r
+ if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // It is valid case, so we need handle it.\r
+ //\r
+ *VarData = NULL;\r
+ *VarSize = 0;\r
+ }\r
+ } else {\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ ASSERT (*VarData != NULL);\r
+ }\r
+\r
+ Status = MeasureVariable (\r
+ PCRIndex,\r
+ EventType,\r
+ VarName,\r
+ VendorGuid,\r
+ *VarData,\r
+ *VarSize\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].\r
+\r
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
+ @param[in] VendorGuid A unique identifier for the vendor.\r
+ @param[out] VarSize The size of the variable data. \r
+ @param[out] VarData Pointer to the content of the variable. \r
+ \r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadAndMeasureBootVariable (\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VarSize,\r
+ OUT VOID **VarData\r
+ )\r
+{\r
+ return ReadAndMeasureVariable (\r
+ 5,\r
+ EV_EFI_VARIABLE_BOOT,\r
+ VarName,\r
+ VendorGuid,\r
+ VarSize,\r
+ VarData\r
+ );\r
+}\r
+\r
+/**\r
+ Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7].\r
+\r
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
+ @param[in] VendorGuid A unique identifier for the vendor.\r
+ @param[out] VarSize The size of the variable data. \r
+ @param[out] VarData Pointer to the content of the variable. \r
+ \r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadAndMeasureSecureVariable (\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VarSize,\r
+ OUT VOID **VarData\r
+ )\r
+{\r
+ return ReadAndMeasureVariable (\r
+ 7,\r
+ EV_EFI_VARIABLE_DRIVER_CONFIG,\r
+ VarName,\r
+ VendorGuid,\r
+ VarSize,\r
+ VarData\r
+ );\r
+}\r
+\r
+/**\r
+ Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
+\r
+ The EFI boot variables are BootOrder and Boot#### variables.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureAllBootVariables (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 *BootOrder;\r
+ UINTN BootCount;\r
+ UINTN Index;\r
+ VOID *BootVarData;\r
+ UINTN Size;\r
+\r
+ Status = ReadAndMeasureBootVariable (\r
+ mBootVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootCount,\r
+ (VOID **) &BootOrder\r
+ );\r
+ if (Status == EFI_NOT_FOUND) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ ASSERT (BootOrder != NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (BootOrder);\r
+ return Status;\r
+ }\r
+\r
+ BootCount /= sizeof (*BootOrder);\r
+ for (Index = 0; Index < BootCount; Index++) {\r
+ UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
+ Status = ReadAndMeasureBootVariable (\r
+ mBootVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ &Size,\r
+ &BootVarData\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ FreePool (BootVarData);\r
+ }\r
+ }\r
+\r
+ FreePool (BootOrder);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR.\r
+\r
+ The EFI boot variables are BootOrder and Boot#### variables.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureAllSecureVariables (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *Data;\r
+ UINTN DataSize;\r
+ UINTN Index;\r
+\r
+ Status = EFI_NOT_FOUND;\r
+ for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
+ Status = ReadAndMeasureSecureVariable (\r
+ mVariableType[Index].VariableName,\r
+ mVariableType[Index].VendorGuid,\r
+ &DataSize,\r
+ &Data\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+MeasureLaunchOfFirmwareDebugger (\r
+ VOID\r
+ )\r
+{\r
+ TCG_PCR_EVENT_HDR TcgEvent;\r
+\r
+ TcgEvent.PCRIndex = 7;\r
+ TcgEvent.EventType = EV_EFI_ACTION;\r
+ TcgEvent.EventSize = sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
+ return TcgDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
+ sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
+ &TcgEvent,\r
+ (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING\r
+ );\r
+}\r
+\r
+/**\r
+ Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR.\r
+\r
+ Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed)\r
+ - The contents of the SecureBoot variable\r
+ - The contents of the PK variable\r
+ - The contents of the KEK variable\r
+ - The contents of the EFI_IMAGE_SECURITY_DATABASE variable\r
+ - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable\r
+ - Separator\r
+ - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path\r
+\r
+ NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE,\r
+ EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3].\r
+\r
+ @param[in] Event Event whose notification function is being invoked\r
+ @param[in] Context Pointer to the notification function's context\r
+**/\r
+VOID\r
+EFIAPI\r
+MeasureSecureBootPolicy (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *Protocol;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ if (PcdGetBool (PcdFirmwareDebuggerInitialized)) {\r
+ Status = MeasureLaunchOfFirmwareDebugger ();\r
+ DEBUG ((EFI_D_ERROR, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
+ }\r
+\r
+ Status = MeasureAllSecureVariables ();\r
+ DEBUG ((EFI_D_ERROR, "MeasureAllSecureVariables - %r\n", Status));\r
+\r
+ //\r
+ // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure)\r
+ // and ImageVerification (Authority)\r
+ // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So\r
+ // the Authority measurement happen before ReadToBoot event.\r
+ //\r
+ Status = MeasureSeparatorEvent (7);\r
+ DEBUG ((EFI_D_ERROR, "MeasureSeparatorEvent - %r\n", Status));\r
+ return ;\r
+}\r
+\r
+/**\r
+ Ready to Boot Event notification handler.\r
+\r
+ Sequence of OS boot events is measured in this event notification handler.\r
+\r
+ @param[in] Event Event whose notification function is being invoked\r
+ @param[in] Context Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnReadyToBoot (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TPM_PCRINDEX PcrIndex;\r
+\r
+ PERF_START_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE);\r
+ if (mBootAttempts == 0) {\r
+\r
+ //\r
+ // Measure handoff tables.\r
+ //\r
+ Status = MeasureHandoffTables ();\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));\r
+ }\r
+\r
+ //\r
+ // Measure BootOrder & Boot#### variables.\r
+ //\r
+ Status = MeasureAllBootVariables ();\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));\r
+ }\r
+\r
+ //\r
+ // 1. This is the first boot attempt.\r
+ //\r
+ Status = TcgMeasureAction (\r
+ EFI_CALLING_EFI_APPLICATION\r
+ );\r
+\r
+ //\r
+ // 2. Draw a line between pre-boot env and entering post-boot env.\r
+ // PCR[7] is already done.\r
+ //\r
+ for (PcrIndex = 0; PcrIndex < 7; PcrIndex++) {\r
+ Status = MeasureSeparatorEvent (PcrIndex);\r
+ }\r
+\r
+ //\r
+ // 3. Measure GPT. It would be done in SAP driver.\r
+ //\r
+\r
+ //\r
+ // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
+ //\r
+\r
+ //\r
+ // 5. Read & Measure variable. BootOrder already measured.\r
+ //\r
+ } else {\r
+ //\r
+ // 6. Not first attempt, meaning a return from last attempt\r
+ //\r
+ Status = TcgMeasureAction (\r
+ EFI_RETURNING_FROM_EFI_APPLICATOIN\r
+ );\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "TPM2 TrEEDxe Measure Data when ReadyToBoot\n"));\r
+ //\r
+ // Increase boot attempt counter.\r
+ //\r
+ mBootAttempts++;\r
+ PERF_END_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE + 1);\r
+}\r
+\r
+/**\r
+ Install TCG ACPI Table when ACPI Table Protocol is available.\r
+\r
+ A system's firmware uses an ACPI table to identify the system's TCG capabilities \r
+ to the Post-Boot environment. The information in this ACPI table is not guaranteed \r
+ to be valid until the Host Platform transitions from pre-boot state to post-boot state. \r
+\r
+ @param[in] Event Event whose notification function is being invoked\r
+ @param[in] Context Pointer to the notification function's context\r
+**/\r
+VOID\r
+EFIAPI\r
+InstallAcpiTable (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ UINTN TableKey;\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
+ UINT8 Checksum;\r
+ UINT64 OemTableId;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
+ CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));\r
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+ CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+ mTcgClientAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+ mTcgClientAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+ mTcgClientAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+ //\r
+ // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
+ // service of the ACPI table protocol to install it.\r
+ //\r
+ Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));\r
+ mTcgClientAcpiTemplate.Header.Checksum = Checksum;\r
+\r
+ Status = AcpiTable->InstallAcpiTable (\r
+ AcpiTable,\r
+ &mTcgClientAcpiTemplate,\r
+ sizeof (mTcgClientAcpiTemplate),\r
+ &TableKey\r
+ );\r
+ } else {\r
+ CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));\r
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+ CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+ mTcgServerAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+ mTcgServerAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+ mTcgServerAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+ //\r
+ // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
+ // service of the ACPI table protocol to install it.\r
+ //\r
+ Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));\r
+ mTcgServerAcpiTemplate.Header.Checksum = Checksum;\r
+\r
+ mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress);\r
+ Status = AcpiTable->InstallAcpiTable (\r
+ AcpiTable,\r
+ &mTcgServerAcpiTemplate,\r
+ sizeof (mTcgServerAcpiTemplate),\r
+ &TableKey\r
+ );\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Exit Boot Services Event notification handler.\r
+\r
+ Measure invocation and success of ExitBootServices.\r
+\r
+ @param[in] Event Event whose notification function is being invoked\r
+ @param[in] Context Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnExitBootServices (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Measure invocation of ExitBootServices,\r
+ //\r
+ Status = TcgMeasureAction (\r
+ EFI_EXIT_BOOT_SERVICES_INVOCATION\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Measure success of ExitBootServices\r
+ //\r
+ Status = TcgMeasureAction (\r
+ EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Exit Boot Services Failed Event notification handler.\r
+\r
+ Measure Failure of ExitBootServices.\r
+\r
+ @param[in] Event Event whose notification function is being invoked\r
+ @param[in] Context Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnExitBootServicesFailed (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Measure Failure of ExitBootServices,\r
+ //\r
+ Status = TcgMeasureAction (\r
+ EFI_EXIT_BOOT_SERVICES_FAILED\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+}\r
+\r
+/**\r
+ The function install TrEE protocol.\r
+ \r
+ @retval EFI_SUCCESS TrEE protocol is installed.\r
+ @retval other Some error occurs.\r
+**/\r
+EFI_STATUS\r
+InstallTrEE (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+\r
+ Handle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Handle,\r
+ &gEfiTrEEProtocolGuid,\r
+ &mTreeProtocol,\r
+ NULL\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The driver's entry point. It publishes EFI TrEE Protocol.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+ \r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverEntry (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT Event;\r
+ VOID *Registration;\r
+ UINT32 MaxCommandSize;\r
+ UINT32 MaxResponseSize;\r
+ TPML_PCR_SELECTION Pcrs;\r
+ UINTN Index;\r
+ UINT32 TpmHashAlgorithmBitmap;\r
+\r
+ mImageHandle = ImageHandle;\r
+\r
+ if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
+ CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
+ DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = Tpm2RequestUseTpm ();\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "TPM not detected!\n"));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Fill information\r
+ //\r
+ DEBUG ((EFI_D_ERROR, "TrEE.ProtocolVersion - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor));\r
+ DEBUG ((EFI_D_ERROR, "TrEE.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor));\r
+\r
+ Status = Tpm2GetCapabilityManufactureID (&mTcgDxeData.BsCap.ManufacturerID);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID fail!\n"));\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID));\r
+ }\r
+\r
+ DEBUG_CODE (\r
+ UINT32 FirmwareVersion1;\r
+ UINT32 FirmwareVersion2;\r
+\r
+ Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n"));\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2));\r
+ }\r
+ );\r
+\r
+ Status = Tpm2GetCapabilityMaxCommandResponseSize (&MaxCommandSize, &MaxResponseSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n"));\r
+ } else {\r
+ mTcgDxeData.BsCap.MaxCommandSize = (UINT16)MaxCommandSize;\r
+ mTcgDxeData.BsCap.MaxResponseSize = (UINT16)MaxResponseSize;\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize));\r
+ }\r
+\r
+ Status = Tpm2GetCapabilityPcrs (&Pcrs);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));\r
+ TpmHashAlgorithmBitmap = TREE_BOOT_HASH_ALG_SHA1;\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));\r
+ TpmHashAlgorithmBitmap = 0;\r
+ for (Index = 0; Index < Pcrs.count; Index++) {\r
+ DEBUG ((EFI_D_ERROR, "hash - %x\n", Pcrs.pcrSelections[Index].hash));\r
+ switch (Pcrs.pcrSelections[Index].hash) {\r
+ case TPM_ALG_SHA1:\r
+ TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA1;\r
+ break;\r
+ case TPM_ALG_SHA256:\r
+ TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA256;\r
+ break;\r
+ case TPM_ALG_SHA384:\r
+ TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA384;\r
+ break;\r
+ case TPM_ALG_SHA512:\r
+ TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA512;\r
+ break;\r
+ case TPM_ALG_SM3_256:\r
+ // TBD: Spec not define TREE_BOOT_HASH_ALG_SM3_256 yet\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ DEBUG ((EFI_D_ERROR, "TPM.HashAlgorithmBitmap - 0x%08x\n", TpmHashAlgorithmBitmap));\r
+\r
+ DEBUG ((EFI_D_ERROR, "TrEE.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs));\r
+ mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap;\r
+ DEBUG ((EFI_D_ERROR, "TrEE.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap));\r
+\r
+ if (mTcgDxeData.BsCap.TrEEPresentFlag) {\r
+ //\r
+ // Setup the log area and copy event log from hob list to it\r
+ //\r
+ Status = SetupEventLog ();\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Measure handoff tables, Boot#### variables etc.\r
+ //\r
+ Status = EfiCreateEventReadyToBootEx (\r
+ TPL_CALLBACK,\r
+ OnReadyToBoot,\r
+ NULL,\r
+ &Event\r
+ );\r
+\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ OnExitBootServices,\r
+ NULL,\r
+ &gEfiEventExitBootServicesGuid,\r
+ &Event\r
+ );\r
+\r
+ //\r
+ // Measure Exit Boot Service failed \r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ OnExitBootServicesFailed,\r
+ NULL,\r
+ &gEventExitBootServicesFailedGuid,\r
+ &Event\r
+ );\r
+\r
+ //\r
+ // Create event callback, because we need access variable on SecureBootPolicyVariable\r
+ // We should use VariableWriteArch instead of VariableArch, because Variable driver\r
+ // may update SecureBoot value based on last setting.\r
+ //\r
+ EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration);\r
+ }\r
+\r
+ //\r
+ // Install ACPI Table\r
+ //\r
+ EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
+\r
+ //\r
+ // Install TrEEProtocol\r
+ //\r
+ Status = InstallTrEE ();\r
+ DEBUG ((EFI_D_ERROR, "InstallTrEE - %r\n", Status));\r
+\r
+ return Status;\r
+}\r