--- /dev/null
+/** @file\r
+ This library is used by FSP modules to measure data to TPM.\r
+\r
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Uefi.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/FspWrapperApiLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+#include <Library/FspMeasurementLib.h>\r
+#include <Library/TcgEventLogRecordLib.h>\r
+#include <Library/HashLib.h>\r
+\r
+#include <Ppi/Tcg.h>\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+\r
+/**\r
+ Tpm measure and log data, and extend the measurement result into a specific PCR.\r
+\r
+ @param[in] PcrIndex PCR Index.\r
+ @param[in] EventType Event type.\r
+ @param[in] EventLog Measurement event log.\r
+ @param[in] LogLen Event log length in bytes.\r
+ @param[in] HashData The start of the data buffer to be hashed, extended.\r
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
+ @param[in] Flags Bitmap providing additional information.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_UNSUPPORTED TPM device not available.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TpmMeasureAndLogDataWithFlags (\r
+ IN UINT32 PcrIndex,\r
+ IN UINT32 EventType,\r
+ IN VOID *EventLog,\r
+ IN UINT32 LogLen,\r
+ IN VOID *HashData,\r
+ IN UINT64 HashDataLen,\r
+ IN UINT64 Flags\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDKII_TCG_PPI *TcgPpi;\r
+ TCG_PCR_EVENT_HDR TcgEventHdr;\r
+\r
+ Status = PeiServicesLocatePpi(\r
+ &gEdkiiTcgPpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID**)&TcgPpi\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ TcgEventHdr.PCRIndex = PcrIndex;\r
+ TcgEventHdr.EventType = EventType;\r
+ TcgEventHdr.EventSize = LogLen;\r
+\r
+ Status = TcgPpi->HashLogExtendEvent (\r
+ TcgPpi,\r
+ Flags,\r
+ HashData,\r
+ (UINTN)HashDataLen,\r
+ &TcgEventHdr,\r
+ EventLog\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Measure a FSP FirmwareBlob.\r
+\r
+ @param[in] Description Description for this FirmwareBlob.\r
+ @param[in] FirmwareBlobBase Base address of this FirmwareBlob.\r
+ @param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.\r
+ @param[in] CfgRegionOffset Configuration region offset in bytes.\r
+ @param[in] CfgRegionSize Configuration region in bytes.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_UNSUPPORTED TPM device not available.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+MeasureFspFirmwareBlobWithCfg (\r
+ IN CHAR8 *Description OPTIONAL,\r
+ IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,\r
+ IN UINT64 FirmwareBlobLength,\r
+ IN UINT32 CfgRegionOffset,\r
+ IN UINT32 CfgRegionSize\r
+ )\r
+{\r
+ EFI_PLATFORM_FIRMWARE_BLOB FvBlob, UpdBlob;\r
+ PLATFORM_FIRMWARE_BLOB2_STRUCT FvBlob2, UpdBlob2;\r
+ VOID *FvName;\r
+ UINT32 FvEventType;\r
+ VOID *FvEventLog, *UpdEventLog;\r
+ UINT32 FvEventLogSize, UpdEventLogSize;\r
+ EFI_STATUS Status;\r
+ HASH_HANDLE HashHandle;\r
+ UINT8 *HashBase;\r
+ UINTN HashSize;\r
+ TPML_DIGEST_VALUES DigestList;\r
+\r
+ FvName = TpmMeasurementGetFvName (FirmwareBlobBase, FirmwareBlobLength);\r
+\r
+ if (((Description != NULL) || (FvName != NULL)) &&\r
+ (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) {\r
+ if (Description != NULL) {\r
+ AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "%a", Description);\r
+ AsciiSPrint((CHAR8*)UpdBlob2.BlobDescription, sizeof(UpdBlob2.BlobDescription), "%aUDP", Description);\r
+ } else {\r
+ AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName);\r
+ AsciiSPrint((CHAR8*)UpdBlob2.BlobDescription, sizeof(UpdBlob2.BlobDescription), "(%g)UDP", FvName);\r
+ }\r
+\r
+ FvBlob2.BlobDescriptionSize = sizeof(FvBlob2.BlobDescription);\r
+ FvBlob2.BlobBase = FirmwareBlobBase;\r
+ FvBlob2.BlobLength = FirmwareBlobLength;\r
+ FvEventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;\r
+ FvEventLog = &FvBlob2;\r
+ FvEventLogSize = sizeof(FvBlob2);\r
+\r
+ UpdBlob2.BlobDescriptionSize = sizeof(UpdBlob2.BlobDescription);\r
+ UpdBlob2.BlobBase = CfgRegionOffset;\r
+ UpdBlob2.BlobLength = CfgRegionSize;\r
+ UpdEventLog = &UpdBlob2;\r
+ UpdEventLogSize = sizeof(UpdBlob2);\r
+ } else {\r
+ FvBlob.BlobBase = FirmwareBlobBase;\r
+ FvBlob.BlobLength = FirmwareBlobLength;\r
+ FvEventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;\r
+ FvEventLog = &FvBlob;\r
+ FvEventLogSize = sizeof(FvBlob);\r
+\r
+ UpdBlob.BlobBase = CfgRegionOffset;\r
+ UpdBlob.BlobLength = CfgRegionSize;\r
+ UpdEventLog = &UpdBlob;\r
+ UpdEventLogSize = sizeof(UpdBlob);\r
+ }\r
+\r
+ /** Initialize a SHA hash context. **/\r
+ Status = HashStart (&HashHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "HashStart failed - %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ /** Hash FSP binary before UDP **/\r
+ HashBase = (UINT8 *) (UINTN) FirmwareBlobBase;\r
+ HashSize = (UINTN) CfgRegionOffset;\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ /** Hash FSP binary after UDP **/\r
+ HashBase = (UINT8 *) (UINTN) FirmwareBlobBase + CfgRegionOffset + CfgRegionSize;\r
+ HashSize = (UINTN)(FirmwareBlobLength - CfgRegionOffset - CfgRegionSize);\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ /** Finalize the SHA hash. **/\r
+ Status = HashCompleteAndExtend (HashHandle, 0, NULL, 0, &DigestList);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "HashCompleteAndExtend failed - %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ Status = TpmMeasureAndLogDataWithFlags (\r
+ 0,\r
+ FvEventType,\r
+ FvEventLog,\r
+ FvEventLogSize,\r
+ (UINT8 *) &DigestList,\r
+ (UINTN) sizeof(DigestList),\r
+ EDKII_TCG_PRE_HASH_LOG_ONLY\r
+ );\r
+\r
+ Status = TpmMeasureAndLogData (\r
+ 1,\r
+ EV_PLATFORM_CONFIG_FLAGS,\r
+ UpdEventLog,\r
+ UpdEventLogSize,\r
+ (UINT8 *) (UINTN) FirmwareBlobBase + CfgRegionOffset,\r
+ CfgRegionSize\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Measure a FSP FirmwareBlob.\r
+\r
+ @param[in] PcrIndex PCR Index.\r
+ @param[in] Description Description for this FirmwareBlob.\r
+ @param[in] FirmwareBlobBase Base address of this FirmwareBlob.\r
+ @param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.\r
+\r
+ @retval EFI_SUCCESS Operation completed successfully.\r
+ @retval EFI_UNSUPPORTED TPM device not available.\r
+ @retval EFI_OUT_OF_RESOURCES Out of memory.\r
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MeasureFspFirmwareBlob (\r
+ IN UINT32 PcrIndex,\r
+ IN CHAR8 *Description OPTIONAL,\r
+ IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,\r
+ IN UINT64 FirmwareBlobLength\r
+ )\r
+{\r
+ UINT32 FspMeasureMask;\r
+ FSP_INFO_HEADER *FspHeaderPtr;\r
+\r
+ FspMeasureMask = PcdGet32 (PcdFspMeasurementConfig);\r
+ if ((FspMeasureMask & FSP_MEASURE_FSPUPD) != 0) {\r
+ FspHeaderPtr = (FSP_INFO_HEADER *) FspFindFspHeader (FirmwareBlobBase);\r
+ if (FspHeaderPtr != NULL) {\r
+ return MeasureFspFirmwareBlobWithCfg(Description, FirmwareBlobBase, FirmwareBlobLength,\r
+ FspHeaderPtr->CfgRegionOffset, FspHeaderPtr->CfgRegionSize);\r
+ }\r
+ }\r
+\r
+ return MeasureFirmwareBlob (PcrIndex, Description, FirmwareBlobBase, FirmwareBlobLength);\r
+}\r
+\r