#\r
# Cc Measurement Protocol for Td guest\r
#\r
- OvmfPkg/IntelTdx/TdTcg2Dxe/TdTcg2Dxe.inf {\r
+ SecurityPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf {\r
<LibraryClasses>\r
HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf\r
NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf\r
#\r
# EFI_CC_MEASUREMENT_PROTOCOL\r
#\r
-INF OvmfPkg/IntelTdx/TdTcg2Dxe/TdTcg2Dxe.inf\r
+INF SecurityPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf\r
\r
################################################################################\r
\r
+++ /dev/null
-/** @file\r
- This module implements measuring PeCoff image for Tcg2 Protocol.\r
-\r
- Caution: This file requires additional review when modified.\r
- This driver will have external input - PE/COFF image.\r
- This external input must be validated carefully to avoid security issue like\r
- buffer overflow, integer overflow.\r
-\r
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <PiDxe.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/PeCoffLib.h>\r
-#include <Library/HashLib.h>\r
-\r
-UINTN mTcg2DxeImageSize = 0;\r
-\r
-/**\r
- Reads contents of a PE/COFF image in memory buffer.\r
-\r
- Caution: This function may receive untrusted input.\r
- PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
- read is within the image buffer.\r
-\r
- @param FileHandle Pointer to the file handle to read the PE/COFF image.\r
- @param FileOffset Offset into the PE/COFF image to begin the read operation.\r
- @param ReadSize On input, the size in bytes of the requested read operation.\r
- On output, the number of bytes actually read.\r
- @param Buffer Output buffer that contains the data read from the PE/COFF image.\r
-\r
- @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcg2DxeImageRead (\r
- IN VOID *FileHandle,\r
- IN UINTN FileOffset,\r
- IN OUT UINTN *ReadSize,\r
- OUT VOID *Buffer\r
- )\r
-{\r
- UINTN EndPosition;\r
-\r
- if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EndPosition = FileOffset + *ReadSize;\r
- if (EndPosition > mTcg2DxeImageSize) {\r
- *ReadSize = (UINT32)(mTcg2DxeImageSize - FileOffset);\r
- }\r
-\r
- if (FileOffset >= mTcg2DxeImageSize) {\r
- *ReadSize = 0;\r
- }\r
-\r
- CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Measure PE image into TPM log based on the authenticode image hashing in\r
- PE/COFF Specification 8.0 Appendix A.\r
-\r
- Caution: This function may receive untrusted input.\r
- PE/COFF image is external input, so this function will validate its data structure\r
- within this image buffer before use.\r
-\r
- Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
-\r
- @param[in] RtmrIndex Rtmr index\r
- @param[in] ImageAddress Start address of image buffer.\r
- @param[in] ImageSize Image size\r
- @param[out] DigestList Digest 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 RtmrIndex,\r
- IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
- IN UINTN ImageSize,\r
- OUT TPML_DIGEST_VALUES *DigestList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_IMAGE_DOS_HEADER *DosHdr;\r
- UINT32 PeCoffHeaderOffset;\r
- EFI_IMAGE_SECTION_HEADER *Section;\r
- UINT8 *HashBase;\r
- UINTN HashSize;\r
- UINTN SumOfBytesHashed;\r
- EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
- UINTN Index;\r
- UINTN Pos;\r
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
- UINT32 NumberOfRvaAndSizes;\r
- UINT32 CertSize;\r
- HASH_HANDLE HashHandle;\r
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
-\r
- HashHandle = 0xFFFFFFFF; // Know bad value\r
-\r
- Status = EFI_UNSUPPORTED;\r
- SectionHeader = NULL;\r
-\r
- //\r
- // Check PE/COFF image\r
- //\r
- ZeroMem (&ImageContext, sizeof (ImageContext));\r
- ImageContext.Handle = (VOID *)(UINTN)ImageAddress;\r
- mTcg2DxeImageSize = ImageSize;\r
- ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)Tcg2DxeImageRead;\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
- DEBUG ((DEBUG_INFO, "Tcg2Dxe: PeImage invalid. Cannot retrieve image information.\n"));\r
- goto Finish;\r
- }\r
-\r
- DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;\r
- PeCoffHeaderOffset = 0;\r
- if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
- PeCoffHeaderOffset = DosHdr->e_lfanew;\r
- }\r
-\r
- Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);\r
- if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Finish;\r
- }\r
-\r
- //\r
- // PE/COFF Image Measurement\r
- //\r
- // NOTE: The following codes/steps are based upon the authenticode image hashing in\r
- // PE/COFF Specification 8.0 Appendix A.\r
- //\r
- //\r
-\r
- // 1. Load the image header into memory.\r
-\r
- // 2. Initialize a SHA hash context.\r
-\r
- Status = HashStart (&HashHandle);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
-\r
- //\r
- // Measuring PE/COFF Image Header;\r
- // But CheckSum field and SECURITY data directory (certificate) are excluded\r
- //\r
-\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 (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
- //\r
- // Use PE32 offset\r
- //\r
- NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
- HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
- } else {\r
- //\r
- // Use PE32+ offset\r
- //\r
- NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
- HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
- }\r
-\r
- Status = HashUpdate (HashHandle, HashBase, HashSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
-\r
- //\r
- // 5. Skip over the image checksum (it occupies a single ULONG).\r
- //\r
- if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
- //\r
- // 6. Since there is no Cert Directory in optional header, hash everything\r
- // from the end of the checksum to the end of image header.\r
- //\r
- if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
- //\r
- // Use PE32 offset.\r
- //\r
- HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
- } else {\r
- //\r
- // Use PE32+ offset.\r
- //\r
- HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
- }\r
-\r
- if (HashSize != 0) {\r
- Status = HashUpdate (HashHandle, HashBase, HashSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
- }\r
- } else {\r
- //\r
- // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
- //\r
- if (Hdr.Pe32->OptionalHeader.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)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
- } else {\r
- //\r
- // Use PE32+ offset\r
- //\r
- HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
- }\r
-\r
- if (HashSize != 0) {\r
- Status = HashUpdate (HashHandle, HashBase, HashSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
- }\r
-\r
- //\r
- // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
- // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
- //\r
- if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
- //\r
- // Use PE32 offset\r
- //\r
- HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
- HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
- } else {\r
- //\r
- // Use PE32+ offset\r
- //\r
- HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
- HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
- }\r
-\r
- if (HashSize != 0) {\r
- Status = HashUpdate (HashHandle, HashBase, HashSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // 10. Set the SUM_OF_BYTES_HASHED to the size of the header\r
- //\r
- if (Hdr.Pe32->OptionalHeader.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
-\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
-\r
- HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData;\r
- HashSize = (UINTN)Section->SizeOfRawData;\r
-\r
- Status = HashUpdate (HashHandle, HashBase, HashSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
-\r
- SumOfBytesHashed += HashSize;\r
- }\r
-\r
- //\r
- // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
- // data in the file that needs to be added to the hash. This data begins\r
- // at file offset SUM_OF_BYTES_HASHED and its length is:\r
- // FileSize - (CertDirectory->Size)\r
- //\r
- if (ImageSize > SumOfBytesHashed) {\r
- HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed;\r
-\r
- if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
- CertSize = 0;\r
- } else {\r
- if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
- //\r
- // Use PE32 offset.\r
- //\r
- CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
- } else {\r
- //\r
- // Use PE32+ offset.\r
- //\r
- CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
- }\r
- }\r
-\r
- if (ImageSize > CertSize + SumOfBytesHashed) {\r
- HashSize = (UINTN)(ImageSize - CertSize - SumOfBytesHashed);\r
-\r
- Status = HashUpdate (HashHandle, HashBase, HashSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
- } else if (ImageSize < CertSize + SumOfBytesHashed) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Finish;\r
- }\r
- }\r
-\r
- //\r
- // 17. Finalize the SHA hash.\r
- //\r
- Status = HashCompleteAndExtend (HashHandle, RtmrIndex, NULL, 0, DigestList);\r
- if (EFI_ERROR (Status)) {\r
- goto Finish;\r
- }\r
-\r
-Finish:\r
- if (SectionHeader != NULL) {\r
- FreePool (SectionHeader);\r
- }\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
- This module implements EFI TD Protocol.\r
-\r
- Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <PiDxe.h>\r
-#include <IndustryStandard/Acpi.h>\r
-#include <IndustryStandard/PeImage.h>\r
-#include <IndustryStandard/TcpaAcpi.h>\r
-\r
-#include <Guid/GlobalVariable.h>\r
-#include <Guid/HobList.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/MpService.h>\r
-#include <Protocol/VariableWrite.h>\r
-#include <Protocol/Tcg2Protocol.h>\r
-#include <Protocol/TrEEProtocol.h>\r
-#include <Protocol/ResetNotification.h>\r
-#include <Protocol/AcpiTable.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/PcdLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/HashLib.h>\r
-#include <Library/PerformanceLib.h>\r
-#include <Library/ReportStatusCodeLib.h>\r
-#include <Library/TpmMeasurementLib.h>\r
-\r
-#include <Protocol/CcMeasurement.h>\r
-#include <Guid/CcEventHob.h>\r
-#include <Library/TdxLib.h>\r
-\r
-#define PERF_ID_CC_TCG2_DXE 0x3130\r
-\r
-#define CC_EVENT_LOG_AREA_COUNT_MAX 1\r
-#define CC_MR_INDEX_0_MRTD 0\r
-#define CC_MR_INDEX_1_RTMR0 1\r
-#define CC_MR_INDEX_2_RTMR1 2\r
-#define CC_MR_INDEX_3_RTMR2 3\r
-#define CC_MR_INDEX_INVALID 4\r
-\r
-typedef struct {\r
- CHAR16 *VariableName;\r
- EFI_GUID *VendorGuid;\r
-} VARIABLE_TYPE;\r
-\r
-typedef struct {\r
- EFI_GUID *EventGuid;\r
- EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
-} CC_EVENT_INFO_STRUCT;\r
-\r
-typedef struct {\r
- EFI_CC_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
- UINTN Next800155EventOffset;\r
-} CC_EVENT_LOG_AREA_STRUCT;\r
-\r
-typedef struct _TDX_DXE_DATA {\r
- EFI_CC_BOOT_SERVICE_CAPABILITY BsCap;\r
- CC_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
- BOOLEAN GetEventLogCalled[CC_EVENT_LOG_AREA_COUNT_MAX];\r
- CC_EVENT_LOG_AREA_STRUCT FinalEventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
- EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable[CC_EVENT_LOG_AREA_COUNT_MAX];\r
-} TDX_DXE_DATA;\r
-\r
-typedef struct {\r
- TPMI_ALG_HASH HashAlgo;\r
- UINT16 HashSize;\r
- UINT32 HashMask;\r
-} TDX_HASH_INFO;\r
-\r
-//\r
-//\r
-CC_EVENT_INFO_STRUCT mCcEventInfo[] = {\r
- { &gCcEventEntryHobGuid, EFI_CC_EVENT_LOG_FORMAT_TCG_2 },\r
-};\r
-\r
-TDX_DXE_DATA mTdxDxeData = {\r
- {\r
- sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY), // Size\r
- { 1, 1 }, // StructureVersion\r
- { 1, 1 }, // ProtocolVersion\r
- EFI_CC_BOOT_HASH_ALG_SHA384, // HashAlgorithmBitmap\r
- EFI_CC_EVENT_LOG_FORMAT_TCG_2, // SupportedEventLogs\r
- { 2, 0 } // {CC_TYPE, CC_SUBTYPE}\r
- },\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_CC_EVENTLOG_ACPI_TABLE mTdxEventlogAcpiTemplate = {\r
- {\r
- EFI_CC_EVENTLOG_ACPI_TABLE_SIGNATURE,\r
- sizeof (mTdxEventlogAcpiTemplate),\r
- EFI_CC_EVENTLOG_ACPI_TABLE_REVISION,\r
- //\r
- // Compiler initializes the remaining bytes to 0\r
- // These fields should be filled in production\r
- //\r
- },\r
- { EFI_CC_TYPE_TDX, 0 }, // CcType\r
- 0, // rsvd\r
- 0, // laml\r
- 0, // lasa\r
-};\r
-\r
-//\r
-// Supported Hash list in Td guest.\r
-// Currently SHA384 is supported.\r
-//\r
-TDX_HASH_INFO mHashInfo[] = {\r
- { TPM_ALG_SHA384, SHA384_DIGEST_SIZE, HASH_ALG_SHA384 }\r
-};\r
-\r
-/**\r
- Get hash size based on Algo\r
-\r
- @param[in] HashAlgo Hash Algorithm Id.\r
-\r
- @return Size of the hash.\r
-**/\r
-UINT16\r
-GetHashSizeFromAlgo (\r
- IN TPMI_ALG_HASH HashAlgo\r
- )\r
-{\r
- UINTN Index;\r
-\r
- for (Index = 0; Index < sizeof (mHashInfo)/sizeof (mHashInfo[0]); Index++) {\r
- if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
- return mHashInfo[Index].HashSize;\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-/**\r
- Get hash mask based on Algo\r
-\r
- @param[in] HashAlgo Hash Algorithm Id.\r
-\r
- @return Hash mask.\r
-**/\r
-UINT32\r
-GetHashMaskFromAlgo (\r
- IN TPMI_ALG_HASH HashAlgo\r
- )\r
-{\r
- UINTN Index;\r
-\r
- for (Index = 0; Index < ARRAY_SIZE (mHashInfo); Index++) {\r
- if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
- return mHashInfo[Index].HashMask;\r
- }\r
- }\r
-\r
- ASSERT (FALSE);\r
- return 0;\r
-}\r
-\r
-/**\r
- Copy TPML_DIGEST_VALUES into a buffer\r
-\r
- @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
- @param[in] DigestList TPML_DIGEST_VALUES to be copied.\r
- @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
-\r
- @return The end of buffer to hold TPML_DIGEST_VALUES.\r
-**/\r
-VOID *\r
-CopyDigestListToBuffer (\r
- IN OUT VOID *Buffer,\r
- IN TPML_DIGEST_VALUES *DigestList,\r
- IN UINT32 HashAlgorithmMask\r
- )\r
-{\r
- UINTN Index;\r
- UINT16 DigestSize;\r
- UINT32 DigestListCount;\r
- UINT32 *DigestListCountPtr;\r
-\r
- DigestListCountPtr = (UINT32 *)Buffer;\r
- DigestListCount = 0;\r
- Buffer = (UINT8 *)Buffer + sizeof (DigestList->count);\r
- for (Index = 0; Index < DigestList->count; Index++) {\r
- if ((DigestList->digests[Index].hashAlg & HashAlgorithmMask) == 0) {\r
- DEBUG ((DEBUG_ERROR, "WARNING: TD Event log has HashAlg unsupported (0x%x)\n", DigestList->digests[Index].hashAlg));\r
- continue;\r
- }\r
-\r
- CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof (DigestList->digests[Index].hashAlg));\r
- Buffer = (UINT8 *)Buffer + sizeof (DigestList->digests[Index].hashAlg);\r
- DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);\r
- CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);\r
- Buffer = (UINT8 *)Buffer + DigestSize;\r
- DigestListCount++;\r
- }\r
-\r
- WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
-\r
- return Buffer;\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
- Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
-\r
- @param[in] RtmrIndex RTMR index\r
- @param[in] ImageAddress Start address of image buffer.\r
- @param[in] ImageSize Image size\r
- @param[out] DigestList Digest 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 RtmrIndex,\r
- IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
- IN UINTN ImageSize,\r
- OUT TPML_DIGEST_VALUES *DigestList\r
- );\r
-\r
-#define COLUME_SIZE (16 * 2)\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
-\r
- for (Index = 0; Index < Size; Index++) {\r
- DEBUG ((DEBUG_INFO, Index == COLUME_SIZE/2 ? " | %02x" : " %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
- Count = Size / COLUME_SIZE;\r
- Left = Size % COLUME_SIZE;\r
- for (Index = 0; Index < Count; Index++) {\r
- DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
- InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);\r
- DEBUG ((DEBUG_INFO, "\n"));\r
- }\r
-\r
- if (Left != 0) {\r
- DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
- InternalDumpData (Data + Index * COLUME_SIZE, Left);\r
- DEBUG ((DEBUG_INFO, "\n"));\r
- }\r
-}\r
-\r
-/**\r
-\r
- This function initialize TD_EVENT_HDR for EV_NO_ACTION\r
- Event Type other than EFI Specification ID event. The behavior is defined\r
- by TCG PC Client PFP Spec. Section 9.3.4 EV_NO_ACTION Event Types\r
-\r
- @param[in, out] NoActionEvent Event Header of EV_NO_ACTION Event\r
- @param[in] EventSize Event Size of the EV_NO_ACTION Event\r
-\r
-**/\r
-VOID\r
-InitNoActionEvent (\r
- IN OUT CC_EVENT_HDR *NoActionEvent,\r
- IN UINT32 EventSize\r
- )\r
-{\r
- UINT32 DigestListCount;\r
- TPMI_ALG_HASH HashAlgId;\r
- UINT8 *DigestBuffer;\r
-\r
- DigestBuffer = (UINT8 *)NoActionEvent->Digests.digests;\r
- DigestListCount = 0;\r
-\r
- NoActionEvent->MrIndex = 0;\r
- NoActionEvent->EventType = EV_NO_ACTION;\r
-\r
- //\r
- // Set Hash count & hashAlg accordingly, while Digest.digests[n].digest to all 0\r
- //\r
- ZeroMem (&NoActionEvent->Digests, sizeof (NoActionEvent->Digests));\r
-\r
- if ((mTdxDxeData.BsCap.HashAlgorithmBitmap & EFI_CC_BOOT_HASH_ALG_SHA384) != 0) {\r
- HashAlgId = TPM_ALG_SHA384;\r
- CopyMem (DigestBuffer, &HashAlgId, sizeof (TPMI_ALG_HASH));\r
- DigestBuffer += sizeof (TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId);\r
- DigestListCount++;\r
- }\r
-\r
- //\r
- // Set Digests Count\r
- //\r
- WriteUnaligned32 ((UINT32 *)&NoActionEvent->Digests.count, DigestListCount);\r
-\r
- //\r
- // Set Event Size\r
- //\r
- WriteUnaligned32 ((UINT32 *)DigestBuffer, EventSize);\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_CC_MEASUREMENT_PROTOCOL GetCapability function call provides protocol\r
- capability information and state information.\r
-\r
- @param[in] This Indicates the calling context\r
- @param[in, out] ProtocolCapability The caller allocates memory for a EFI_CC_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 EFI TCG2 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
-TdGetCapability (\r
- IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
- IN OUT EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability\r
- )\r
-{\r
- DEBUG ((DEBUG_VERBOSE, "TdGetCapability\n"));\r
-\r
- if ((This == NULL) || (ProtocolCapability == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- CopyMem (ProtocolCapability, &mTdxDxeData.BsCap, sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY));\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- This function dump PCR event.\r
- TD Event log reuse the TCG PCR Event spec.\r
- The first event in the event log is the SHA1 log format.\r
- There is only ONE TCG_PCR_EVENT in TD Event log.\r
-\r
- @param[in] EventHdr TCG PCR event structure.\r
-**/\r
-VOID\r
-DumpPcrEvent (\r
- IN TCG_PCR_EVENT_HDR *EventHdr\r
- )\r
-{\r
- UINTN Index;\r
-\r
- DEBUG ((DEBUG_INFO, " Event:\n"));\r
- DEBUG ((DEBUG_INFO, " MrIndex - %d\n", EventHdr->PCRIndex));\r
- DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", EventHdr->EventType));\r
- DEBUG ((DEBUG_INFO, " Digest - "));\r
- for (Index = 0; Index < sizeof (TCG_DIGEST); Index++) {\r
- DEBUG ((DEBUG_INFO, "%02x ", EventHdr->Digest.digest[Index]));\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "\n"));\r
- DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize));\r
- InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);\r
-}\r
-\r
-/**\r
- This function dump TCG_EfiSpecIDEventStruct.\r
-\r
- @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
-**/\r
-VOID\r
-DumpTcgEfiSpecIdEventStruct (\r
- IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
- )\r
-{\r
- TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
- UINTN Index;\r
- UINT8 *VendorInfoSize;\r
- UINT8 *VendorInfo;\r
- UINT32 NumberOfAlgorithms;\r
-\r
- DEBUG ((DEBUG_INFO, " TCG_EfiSpecIDEventStruct:\n"));\r
- DEBUG ((DEBUG_INFO, " signature - '"));\r
- for (Index = 0; Index < sizeof (TcgEfiSpecIdEventStruct->signature); Index++) {\r
- DEBUG ((DEBUG_INFO, "%c", TcgEfiSpecIdEventStruct->signature[Index]));\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "'\n"));\r
- DEBUG ((DEBUG_INFO, " platformClass - 0x%08x\n", TcgEfiSpecIdEventStruct->platformClass));\r
- DEBUG ((DEBUG_INFO, " specVersion - %d.%d%d\n", TcgEfiSpecIdEventStruct->specVersionMajor, TcgEfiSpecIdEventStruct->specVersionMinor, TcgEfiSpecIdEventStruct->specErrata));\r
- DEBUG ((DEBUG_INFO, " uintnSize - 0x%02x\n", TcgEfiSpecIdEventStruct->uintnSize));\r
-\r
- CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
- DEBUG ((DEBUG_INFO, " NumberOfAlgorithms - 0x%08x\n", NumberOfAlgorithms));\r
-\r
- DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
- for (Index = 0; Index < NumberOfAlgorithms; Index++) {\r
- DEBUG ((DEBUG_INFO, " digest(%d)\n", Index));\r
- DEBUG ((DEBUG_INFO, " algorithmId - 0x%04x\n", DigestSize[Index].algorithmId));\r
- DEBUG ((DEBUG_INFO, " digestSize - 0x%04x\n", DigestSize[Index].digestSize));\r
- }\r
-\r
- VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
- DEBUG ((DEBUG_INFO, " VendorInfoSize - 0x%02x\n", *VendorInfoSize));\r
- VendorInfo = VendorInfoSize + 1;\r
- DEBUG ((DEBUG_INFO, " VendorInfo - "));\r
- for (Index = 0; Index < *VendorInfoSize; Index++) {\r
- DEBUG ((DEBUG_INFO, "%02x ", VendorInfo[Index]));\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "\n"));\r
-}\r
-\r
-/**\r
- This function get size of TCG_EfiSpecIDEventStruct.\r
-\r
- @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
-**/\r
-UINTN\r
-GetTcgEfiSpecIdEventStructSize (\r
- IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
- )\r
-{\r
- TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
- UINT8 *VendorInfoSize;\r
- UINT32 NumberOfAlgorithms;\r
-\r
- CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
-\r
- DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
- VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
- return sizeof (TCG_EfiSpecIDEventStruct) + sizeof (UINT32) + (NumberOfAlgorithms * sizeof (TCG_EfiSpecIdEventAlgorithmSize)) + sizeof (UINT8) + (*VendorInfoSize);\r
-}\r
-\r
-/**\r
- This function dump TD Event (including the Digests).\r
-\r
- @param[in] CcEvent TD Event structure.\r
-**/\r
-VOID\r
-DumpCcEvent (\r
- IN CC_EVENT *CcEvent\r
- )\r
-{\r
- UINT32 DigestIndex;\r
- UINT32 DigestCount;\r
- TPMI_ALG_HASH HashAlgo;\r
- UINT32 DigestSize;\r
- UINT8 *DigestBuffer;\r
- UINT32 EventSize;\r
- UINT8 *EventBuffer;\r
-\r
- DEBUG ((DEBUG_INFO, "Cc Event:\n"));\r
- DEBUG ((DEBUG_INFO, " MrIndex - %d\n", CcEvent->MrIndex));\r
- DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", CcEvent->EventType));\r
- DEBUG ((DEBUG_INFO, " DigestCount: 0x%08x\n", CcEvent->Digests.count));\r
-\r
- DigestCount = CcEvent->Digests.count;\r
- HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
- DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
- for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
- DEBUG ((DEBUG_INFO, " HashAlgo : 0x%04x\n", HashAlgo));\r
- DEBUG ((DEBUG_INFO, " Digest(%d): \n", DigestIndex));\r
- DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
- InternalDumpHex (DigestBuffer, DigestSize);\r
- //\r
- // Prepare next\r
- //\r
- CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
- DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
- }\r
-\r
- DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
-\r
- CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
- DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventSize));\r
- EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
- InternalDumpHex (EventBuffer, EventSize);\r
- DEBUG ((DEBUG_INFO, "\n"));\r
-}\r
-\r
-/**\r
- This function returns size of Td Table event.\r
-\r
- @param[in] CcEvent Td Table event structure.\r
-\r
- @return size of Td event.\r
-**/\r
-UINTN\r
-GetCcEventSize (\r
- IN CC_EVENT *CcEvent\r
- )\r
-{\r
- UINT32 DigestIndex;\r
- UINT32 DigestCount;\r
- TPMI_ALG_HASH HashAlgo;\r
- UINT32 DigestSize;\r
- UINT8 *DigestBuffer;\r
- UINT32 EventSize;\r
- UINT8 *EventBuffer;\r
-\r
- DigestCount = CcEvent->Digests.count;\r
- HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
- DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
- for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
- DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
- //\r
- // Prepare next\r
- //\r
- CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
- DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
- }\r
-\r
- DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
-\r
- CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
- EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
-\r
- return (UINTN)EventBuffer + EventSize - (UINTN)CcEvent;\r
-}\r
-\r
-/**\r
- This function dump CC event log.\r
- TDVF only supports EFI_CC_EVENT_LOG_FORMAT_TCG_2\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
- @param[in] FinalEventsTable A pointer to the memory address of the final event table.\r
-**/\r
-VOID\r
-DumpCcEventLog (\r
- IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
- IN EFI_PHYSICAL_ADDRESS EventLogLocation,\r
- IN EFI_PHYSICAL_ADDRESS EventLogLastEntry,\r
- IN EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable\r
- )\r
-{\r
- TCG_PCR_EVENT_HDR *EventHdr;\r
- CC_EVENT *CcEvent;\r
- TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
- UINTN NumberOfEvents;\r
-\r
- DEBUG ((DEBUG_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));\r
- ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
-\r
- //\r
- // Dump first event.\r
- // The first event is always the TCG_PCR_EVENT_HDR\r
- // After this event is a TCG_EfiSpecIDEventStruct\r
- //\r
- EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;\r
- DumpPcrEvent (EventHdr);\r
-\r
- TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)(EventHdr + 1);\r
- DumpTcgEfiSpecIdEventStruct (TcgEfiSpecIdEventStruct);\r
-\r
- //\r
- // Then the CcEvent (Its structure is similar to TCG_PCR_EVENT2)\r
- //\r
- CcEvent = (CC_EVENT *)((UINTN)TcgEfiSpecIdEventStruct + GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct));\r
- while ((UINTN)CcEvent <= EventLogLastEntry) {\r
- DumpCcEvent (CcEvent);\r
- CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
- }\r
-\r
- if (FinalEventsTable == NULL) {\r
- DEBUG ((DEBUG_INFO, "FinalEventsTable: NOT FOUND\n"));\r
- } else {\r
- DEBUG ((DEBUG_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable));\r
- DEBUG ((DEBUG_INFO, " Version: (0x%x)\n", FinalEventsTable->Version));\r
- DEBUG ((DEBUG_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents));\r
-\r
- CcEvent = (CC_EVENT *)(UINTN)(FinalEventsTable + 1);\r
- for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) {\r
- DumpCcEvent (CcEvent);\r
- CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
- }\r
- }\r
-\r
- return;\r
-}\r
-\r
-/**\r
- The EFI_CC_MEASUREMENT_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
-TdGetEventLog (\r
- IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
- IN EFI_CC_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 = 0;\r
-\r
- DEBUG ((DEBUG_INFO, "TdGetEventLog ... (0x%x)\n", EventLogFormat));\r
- ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
-\r
- if (EventLogLocation != NULL) {\r
- *EventLogLocation = mTdxDxeData.EventLogAreaStruct[Index].Lasa;\r
- DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));\r
- }\r
-\r
- if (EventLogLastEntry != NULL) {\r
- if (!mTdxDxeData.EventLogAreaStruct[Index].EventLogStarted) {\r
- *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
- } else {\r
- *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTdxDxeData.EventLogAreaStruct[Index].LastEvent;\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));\r
- }\r
-\r
- if (EventLogTruncated != NULL) {\r
- *EventLogTruncated = mTdxDxeData.EventLogAreaStruct[Index].EventLogTruncated;\r
- DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "TdGetEventLog - %r\n", EFI_SUCCESS));\r
-\r
- // Dump Event Log for debug purpose\r
- if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {\r
- DumpCcEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry, mTdxDxeData.FinalEventsTable[Index]);\r
- }\r
-\r
- //\r
- // All events generated after the invocation of EFI_TCG2_GET_EVENT_LOG SHALL be stored\r
- // in an instance of an EFI_CONFIGURATION_TABLE named by the VendorGuid of EFI_TCG2_FINAL_EVENTS_TABLE_GUID.\r
- //\r
- mTdxDxeData.GetEventLogCalled[Index] = TRUE;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Return if this is a Tcg800155PlatformIdEvent.\r
-\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 TRUE This is a Tcg800155PlatformIdEvent.\r
- @retval FALSE This is NOT a Tcg800155PlatformIdEvent.\r
-\r
-**/\r
-BOOLEAN\r
-Is800155Event (\r
- IN VOID *NewEventHdr,\r
- IN UINT32 NewEventHdrSize,\r
- IN UINT8 *NewEventData,\r
- IN UINT32 NewEventSize\r
- )\r
-{\r
- if ((((TCG_PCR_EVENT2_HDR *)NewEventHdr)->EventType == EV_NO_ACTION) &&\r
- (NewEventSize >= sizeof (TCG_Sp800_155_PlatformId_Event2)) &&\r
- (CompareMem (\r
- NewEventData,\r
- TCG_Sp800_155_PlatformId_Event2_SIGNATURE,\r
- sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1\r
- ) == 0))\r
- {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Add a new entry to the Event Log.\r
-\r
- @param[in, out] EventLogAreaStruct The event log area data structure\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 CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct,\r
- IN VOID *NewEventHdr,\r
- IN UINT32 NewEventHdrSize,\r
- IN UINT8 *NewEventData,\r
- IN UINT32 NewEventSize\r
- )\r
-{\r
- UINTN NewLogSize;\r
- BOOLEAN Record800155Event;\r
- CC_EVENT_HDR *CcEventHdr;\r
-\r
- CcEventHdr = (CC_EVENT_HDR *)NewEventHdr;\r
- DEBUG ((DEBUG_VERBOSE, "Td: Try to log event. Index = %d, EventType = 0x%x\n", CcEventHdr->MrIndex, CcEventHdr->EventType));\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 - EventLogAreaStruct->EventLogSize) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- if (NewLogSize + EventLogAreaStruct->EventLogSize > EventLogAreaStruct->Laml) {\r
- DEBUG ((DEBUG_INFO, " Laml - 0x%x\n", EventLogAreaStruct->Laml));\r
- DEBUG ((DEBUG_INFO, " NewLogSize - 0x%x\n", NewLogSize));\r
- DEBUG ((DEBUG_INFO, " LogSize - 0x%x\n", EventLogAreaStruct->EventLogSize));\r
- DEBUG ((DEBUG_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Check 800-155 event\r
- // Record to 800-155 event offset only.\r
- // If the offset is 0, no need to record.\r
- //\r
- Record800155Event = Is800155Event (NewEventHdr, NewEventHdrSize, NewEventData, NewEventSize);\r
- if (Record800155Event) {\r
- DEBUG ((DEBUG_INFO, "It is 800155Event.\n"));\r
-\r
- if (EventLogAreaStruct->Next800155EventOffset != 0) {\r
- CopyMem (\r
- (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewLogSize,\r
- (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
- EventLogAreaStruct->EventLogSize - EventLogAreaStruct->Next800155EventOffset\r
- );\r
-\r
- CopyMem (\r
- (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
- NewEventHdr,\r
- NewEventHdrSize\r
- );\r
- CopyMem (\r
- (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewEventHdrSize,\r
- NewEventData,\r
- NewEventSize\r
- );\r
-\r
- EventLogAreaStruct->Next800155EventOffset += NewLogSize;\r
- EventLogAreaStruct->LastEvent += NewLogSize;\r
- EventLogAreaStruct->EventLogSize += NewLogSize;\r
- }\r
-\r
- return EFI_SUCCESS;\r
- }\r
-\r
- EventLogAreaStruct->LastEvent = (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->EventLogSize;\r
- EventLogAreaStruct->EventLogSize += NewLogSize;\r
-\r
- CopyMem (EventLogAreaStruct->LastEvent, NewEventHdr, NewEventHdrSize);\r
- CopyMem (\r
- EventLogAreaStruct->LastEvent + NewEventHdrSize,\r
- NewEventData,\r
- NewEventSize\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- According to UEFI Spec 2.10 Section 38.4.1:\r
- The following table shows the TPM PCR index mapping and CC event log measurement\r
- register index interpretation for Intel TDX, where MRTD means Trust Domain Measurement\r
- Register and RTMR means Runtime Measurement Register\r
-\r
- // TPM PCR Index | CC Measurement Register Index | TDX-measurement register\r
- // ------------------------------------------------------------------------\r
- // 0 | 0 | MRTD\r
- // 1, 7 | 1 | RTMR[0]\r
- // 2~6 | 2 | RTMR[1]\r
- // 8~15 | 3 | RTMR[2]\r
-\r
- @param[in] PCRIndex Index of the TPM PCR\r
-\r
- @retval UINT32 Index of the CC Event Log Measurement Register Index\r
- @retval CC_MR_INDEX_INVALID Invalid MR Index\r
-**/\r
-UINT32\r
-EFIAPI\r
-MapPcrToMrIndex (\r
- IN UINT32 PCRIndex\r
- )\r
-{\r
- UINT32 MrIndex;\r
-\r
- if (PCRIndex > 15) {\r
- ASSERT (FALSE);\r
- return CC_MR_INDEX_INVALID;\r
- }\r
-\r
- MrIndex = 0;\r
- if (PCRIndex == 0) {\r
- MrIndex = CC_MR_INDEX_0_MRTD;\r
- } else if ((PCRIndex == 1) || (PCRIndex == 7)) {\r
- MrIndex = CC_MR_INDEX_1_RTMR0;\r
- } else if ((PCRIndex >= 2) && (PCRIndex <= 6)) {\r
- MrIndex = CC_MR_INDEX_2_RTMR1;\r
- } else if ((PCRIndex >= 8) && (PCRIndex <= 15)) {\r
- MrIndex = CC_MR_INDEX_3_RTMR2;\r
- }\r
-\r
- return MrIndex;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-TdMapPcrToMrIndex (\r
- IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
- IN UINT32 PCRIndex,\r
- OUT UINT32 *MrIndex\r
- )\r
-{\r
- if (MrIndex == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *MrIndex = MapPcrToMrIndex (PCRIndex);\r
-\r
- return *MrIndex == CC_MR_INDEX_INVALID ? EFI_INVALID_PARAMETER : 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
-TdxDxeLogEvent (\r
- IN EFI_CC_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
- CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct;\r
-\r
- if (EventLogFormat != EFI_CC_EVENT_LOG_FORMAT_TCG_2) {\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Index = 0;\r
-\r
- //\r
- // Record to normal event log\r
- //\r
- EventLogAreaStruct = &mTdxDxeData.EventLogAreaStruct[Index];\r
-\r
- if (EventLogAreaStruct->EventLogTruncated) {\r
- return EFI_VOLUME_FULL;\r
- }\r
-\r
- Status = TcgCommLogEvent (\r
- EventLogAreaStruct,\r
- NewEventHdr,\r
- NewEventHdrSize,\r
- NewEventData,\r
- NewEventSize\r
- );\r
-\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- EventLogAreaStruct->EventLogTruncated = TRUE;\r
- return EFI_VOLUME_FULL;\r
- } else if (Status == EFI_SUCCESS) {\r
- EventLogAreaStruct->EventLogStarted = TRUE;\r
- }\r
-\r
- //\r
- // If GetEventLog is called, record to FinalEventsTable, too.\r
- //\r
- if (mTdxDxeData.GetEventLogCalled[Index]) {\r
- if (mTdxDxeData.FinalEventsTable[Index] == NULL) {\r
- //\r
- // no need for FinalEventsTable\r
- //\r
- return EFI_SUCCESS;\r
- }\r
-\r
- EventLogAreaStruct = &mTdxDxeData.FinalEventLogAreaStruct[Index];\r
-\r
- if (EventLogAreaStruct->EventLogTruncated) {\r
- return EFI_VOLUME_FULL;\r
- }\r
-\r
- Status = TcgCommLogEvent (\r
- EventLogAreaStruct,\r
- NewEventHdr,\r
- NewEventHdrSize,\r
- NewEventData,\r
- NewEventSize\r
- );\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- EventLogAreaStruct->EventLogTruncated = TRUE;\r
- return EFI_VOLUME_FULL;\r
- } else if (Status == EFI_SUCCESS) {\r
- EventLogAreaStruct->EventLogStarted = TRUE;\r
- //\r
- // Increase the NumberOfEvents in FinalEventsTable\r
- //\r
- (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents++;\r
- DEBUG ((DEBUG_INFO, "FinalEventsTable->NumberOfEvents - 0x%x\n", (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents));\r
- DEBUG ((DEBUG_INFO, " Size - 0x%x\n", (UINTN)EventLogAreaStruct->EventLogSize));\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Get TPML_DIGEST_VALUES compact binary buffer size.\r
-\r
- @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
-\r
- @return TPML_DIGEST_VALUES compact binary buffer size.\r
-**/\r
-UINT32\r
-GetDigestListBinSize (\r
- IN VOID *DigestListBin\r
- )\r
-{\r
- UINTN Index;\r
- UINT16 DigestSize;\r
- UINT32 TotalSize;\r
- UINT32 Count;\r
- TPMI_ALG_HASH HashAlg;\r
-\r
- Count = ReadUnaligned32 (DigestListBin);\r
- TotalSize = sizeof (Count);\r
- DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
- for (Index = 0; Index < Count; Index++) {\r
- HashAlg = ReadUnaligned16 (DigestListBin);\r
- TotalSize += sizeof (HashAlg);\r
- DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
-\r
- DigestSize = GetHashSizeFromAlgo (HashAlg);\r
- TotalSize += DigestSize;\r
- DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
- }\r
-\r
- return TotalSize;\r
-}\r
-\r
-/**\r
- Copy TPML_DIGEST_VALUES compact binary into a buffer\r
-\r
- @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
- @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
- @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
- @param[out] HashAlgorithmMaskCopied Pointer to HASH bits corresponding to the digests copied.\r
-\r
- @return The end of buffer to hold TPML_DIGEST_VALUES compact binary.\r
-**/\r
-VOID *\r
-CopyDigestListBinToBuffer (\r
- IN OUT VOID *Buffer,\r
- IN VOID *DigestListBin,\r
- IN UINT32 HashAlgorithmMask,\r
- OUT UINT32 *HashAlgorithmMaskCopied\r
- )\r
-{\r
- UINTN Index;\r
- UINT16 DigestSize;\r
- UINT32 Count;\r
- TPMI_ALG_HASH HashAlg;\r
- UINT32 DigestListCount;\r
- UINT32 *DigestListCountPtr;\r
-\r
- DigestListCountPtr = (UINT32 *)Buffer;\r
- DigestListCount = 0;\r
- *HashAlgorithmMaskCopied = 0;\r
-\r
- Count = ReadUnaligned32 (DigestListBin);\r
- Buffer = (UINT8 *)Buffer + sizeof (Count);\r
- DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
- for (Index = 0; Index < Count; Index++) {\r
- HashAlg = ReadUnaligned16 (DigestListBin);\r
- DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
- DigestSize = GetHashSizeFromAlgo (HashAlg);\r
-\r
- if ((HashAlg & HashAlgorithmMask) != 0) {\r
- CopyMem (Buffer, &HashAlg, sizeof (HashAlg));\r
- Buffer = (UINT8 *)Buffer + sizeof (HashAlg);\r
- CopyMem (Buffer, DigestListBin, DigestSize);\r
- Buffer = (UINT8 *)Buffer + DigestSize;\r
- DigestListCount++;\r
- (*HashAlgorithmMaskCopied) |= GetHashMaskFromAlgo (HashAlg);\r
- } else {\r
- DEBUG ((DEBUG_ERROR, "WARNING: CopyDigestListBinToBuffer Event log has HashAlg unsupported by PCR bank (0x%x)\n", HashAlg));\r
- }\r
-\r
- DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
- }\r
-\r
- WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
-\r
- return Buffer;\r
-}\r
-\r
-/**\r
- Add a new entry to the Event Log. The call chain is like below:\r
- TdxDxeLogHashEvent -> TdxDxeLogEvent -> TcgCommonLogEvent\r
-\r
- Before this function is called, the event information (including the digest)\r
- is ready.\r
-\r
- @param[in] DigestList A list of digest.\r
- @param[in,out] NewEventHdr Pointer to a TD_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
-TdxDxeLogHashEvent (\r
- IN TPML_DIGEST_VALUES *DigestList,\r
- IN OUT CC_EVENT_HDR *NewEventHdr,\r
- IN UINT8 *NewEventData\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS RetStatus;\r
- CC_EVENT CcEvent;\r
- UINT8 *DigestBuffer;\r
- UINT32 *EventSizePtr;\r
- EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
-\r
- RetStatus = EFI_SUCCESS;\r
- LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
-\r
- ZeroMem (&CcEvent, sizeof (CcEvent));\r
- CcEvent.MrIndex = NewEventHdr->MrIndex;\r
- CcEvent.EventType = NewEventHdr->EventType;\r
- DigestBuffer = (UINT8 *)&CcEvent.Digests;\r
- EventSizePtr = CopyDigestListToBuffer (DigestBuffer, DigestList, HASH_ALG_SHA384);\r
- CopyMem (EventSizePtr, &NewEventHdr->EventSize, sizeof (NewEventHdr->EventSize));\r
-\r
- //\r
- // Enter critical region\r
- //\r
- OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
- Status = TdxDxeLogEvent (\r
- LogFormat,\r
- &CcEvent,\r
- sizeof (CcEvent.MrIndex) + sizeof (CcEvent.EventType) + GetDigestListBinSize (DigestBuffer) + sizeof (CcEvent.EventSize),\r
- NewEventData,\r
- NewEventHdr->EventSize\r
- );\r
- if (Status != EFI_SUCCESS) {\r
- RetStatus = Status;\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return RetStatus;\r
-}\r
-\r
-/**\r
- Do a hash operation on a data buffer, extend a specific RTMR 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 TD_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
-TdxDxeHashLogExtendEvent (\r
- IN UINT64 Flags,\r
- IN UINT8 *HashData,\r
- IN UINT64 HashDataLen,\r
- IN OUT CC_EVENT_HDR *NewEventHdr,\r
- IN UINT8 *NewEventData\r
- )\r
-{\r
- EFI_STATUS Status;\r
- TPML_DIGEST_VALUES DigestList;\r
- CC_EVENT_HDR NoActionEvent;\r
-\r
- if (NewEventHdr->EventType == EV_NO_ACTION) {\r
- //\r
- // Do not do RTMR extend for EV_NO_ACTION\r
- //\r
- Status = EFI_SUCCESS;\r
- InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize);\r
- if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
- Status = TdxDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData);\r
- }\r
-\r
- return Status;\r
- }\r
-\r
- //\r
- // According to UEFI Spec 2.10 Section 38.4.1 the mapping between MrIndex and Intel\r
- // TDX Measurement Register is:\r
- // MrIndex 0 <--> MRTD\r
- // MrIndex 1-3 <--> RTMR[0-2]\r
- // Only the RMTR registers can be extended in TDVF by HashAndExtend. So MrIndex will\r
- // decreased by 1 before it is sent to HashAndExtend.\r
- //\r
- Status = HashAndExtend (\r
- NewEventHdr->MrIndex - 1,\r
- HashData,\r
- (UINTN)HashDataLen,\r
- &DigestList\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
- Status = TdxDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- The EFI_CC_MEASUREMENT_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
-TdHashLogExtendEvent (\r
- IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
- IN UINT64 Flags,\r
- IN EFI_PHYSICAL_ADDRESS DataToHash,\r
- IN UINT64 DataToHashLen,\r
- IN EFI_CC_EVENT *CcEvent\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CC_EVENT_HDR NewEventHdr;\r
- TPML_DIGEST_VALUES DigestList;\r
-\r
- DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent ...\n"));\r
-\r
- if ((This == NULL) || (CcEvent == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Do not check hash data size for EV_NO_ACTION event.\r
- //\r
- if ((CcEvent->Header.EventType != EV_NO_ACTION) && (DataToHash == 0)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (CcEvent->Size < CcEvent->Header.HeaderSize + sizeof (UINT32)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (CcEvent->Header.MrIndex == CC_MR_INDEX_0_MRTD) {\r
- DEBUG ((DEBUG_ERROR, "%a: MRTD cannot be extended in TDVF.\n", __FUNCTION__));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (CcEvent->Header.MrIndex >= CC_MR_INDEX_INVALID) {\r
- DEBUG ((DEBUG_ERROR, "%a: MrIndex is invalid. (%d)\n", __FUNCTION__, CcEvent->Header.MrIndex));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- NewEventHdr.MrIndex = CcEvent->Header.MrIndex;\r
- NewEventHdr.EventType = CcEvent->Header.EventType;\r
- NewEventHdr.EventSize = CcEvent->Size - sizeof (UINT32) - CcEvent->Header.HeaderSize;\r
- if ((Flags & EFI_CC_FLAG_PE_COFF_IMAGE) != 0) {\r
- //\r
- // According to UEFI Spec 2.10 Section 38.4.1 the mapping between MrIndex and Intel\r
- // TDX Measurement Register is:\r
- // MrIndex 0 <--> MRTD\r
- // MrIndex 1-3 <--> RTMR[0-2]\r
- // Only the RMTR registers can be extended in TDVF by HashAndExtend. So MrIndex will\r
- // decreased by 1 before it is sent to MeasurePeImageAndExtend.\r
- //\r
- Status = MeasurePeImageAndExtend (\r
- NewEventHdr.MrIndex - 1,\r
- DataToHash,\r
- (UINTN)DataToHashLen,\r
- &DigestList\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
- Status = TdxDxeLogHashEvent (&DigestList, &NewEventHdr, CcEvent->Event);\r
- }\r
- }\r
- } else {\r
- Status = TdxDxeHashLogExtendEvent (\r
- Flags,\r
- (UINT8 *)(UINTN)DataToHash,\r
- DataToHashLen,\r
- &NewEventHdr,\r
- CcEvent->Event\r
- );\r
- }\r
-\r
- DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent - %r\n", Status));\r
- return Status;\r
-}\r
-\r
-EFI_CC_MEASUREMENT_PROTOCOL mTdProtocol = {\r
- TdGetCapability,\r
- TdGetEventLog,\r
- TdHashLogExtendEvent,\r
- TdMapPcrToMrIndex,\r
-};\r
-\r
-#define TD_HASH_COUNT 1\r
-#define TEMP_BUF_LEN (sizeof(TCG_EfiSpecIDEventStruct) + sizeof(UINT32) \\r
- + (TD_HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8))\r
-\r
-/**\r
- Initialize the TD 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
-SetupCcEventLog (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PHYSICAL_ADDRESS Lasa;\r
- UINTN Index;\r
- TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
- UINT8 TempBuf[TEMP_BUF_LEN];\r
- TCG_PCR_EVENT_HDR SpecIdEvent;\r
- TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
- TCG_EfiSpecIdEventAlgorithmSize *TempDigestSize;\r
- UINT8 *VendorInfoSize;\r
- UINT32 NumberOfAlgorithms;\r
- EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
- EFI_PEI_HOB_POINTERS GuidHob;\r
- CC_EVENT_HDR NoActionEvent;\r
-\r
- Status = EFI_SUCCESS;\r
- DEBUG ((DEBUG_INFO, "SetupCcEventLog\n"));\r
-\r
- Index = 0;\r
- LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
-\r
- //\r
- // 1. Create Log Area\r
- //\r
- mTdxDxeData.EventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
-\r
- // allocate pages for TD Event log\r
- Status = gBS->AllocatePages (\r
- AllocateAnyPages,\r
- EfiACPIMemoryNVS,\r
- EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
- &Lasa\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- mTdxDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
- mTdxDxeData.EventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
- mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = 0;\r
-\r
- //\r
- // Report TD event log address and length, so that they can be reported in\r
- // TD ACPI table. Ignore the return status, because those fields are optional.\r
- //\r
- PcdSet32S (PcdCcEventlogAcpiTableLaml, (UINT32)mTdxDxeData.EventLogAreaStruct[Index].Laml);\r
- PcdSet64S (PcdCcEventlogAcpiTableLasa, mTdxDxeData.EventLogAreaStruct[Index].Lasa);\r
-\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, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
-\r
- //\r
- // Create first entry for Log Header Entry Data\r
- //\r
-\r
- //\r
- // TcgEfiSpecIdEventStruct\r
- //\r
- TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)TempBuf;\r
- CopyMem (TcgEfiSpecIdEventStruct->signature, TCG_EfiSpecIDEventStruct_SIGNATURE_03, sizeof (TcgEfiSpecIdEventStruct->signature));\r
-\r
- TcgEfiSpecIdEventStruct->platformClass = PcdGet8 (PcdTpmPlatformClass);\r
-\r
- TcgEfiSpecIdEventStruct->specVersionMajor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2;\r
- TcgEfiSpecIdEventStruct->specVersionMinor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2;\r
- TcgEfiSpecIdEventStruct->specErrata = TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2;\r
- TcgEfiSpecIdEventStruct->uintnSize = sizeof (UINTN)/sizeof (UINT32);\r
- NumberOfAlgorithms = 0;\r
- DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct\r
- + sizeof (*TcgEfiSpecIdEventStruct)\r
- + sizeof (NumberOfAlgorithms));\r
-\r
- TempDigestSize = DigestSize;\r
- TempDigestSize += NumberOfAlgorithms;\r
- TempDigestSize->algorithmId = TPM_ALG_SHA384;\r
- TempDigestSize->digestSize = SHA384_DIGEST_SIZE;\r
- NumberOfAlgorithms++;\r
-\r
- CopyMem (TcgEfiSpecIdEventStruct + 1, &NumberOfAlgorithms, sizeof (NumberOfAlgorithms));\r
- TempDigestSize = DigestSize;\r
- TempDigestSize += NumberOfAlgorithms;\r
- VendorInfoSize = (UINT8 *)TempDigestSize;\r
- *VendorInfoSize = 0;\r
-\r
- SpecIdEvent.PCRIndex = 1; // PCRIndex 0 maps to MrIndex 1\r
- SpecIdEvent.EventType = EV_NO_ACTION;\r
- ZeroMem (&SpecIdEvent.Digest, sizeof (SpecIdEvent.Digest));\r
- SpecIdEvent.EventSize = (UINT32)GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct);\r
-\r
- //\r
- // TD Event log re-use the spec of TCG2 Event log.\r
- // Log TcgEfiSpecIdEventStruct as the first Event. Event format is TCG_PCR_EVENT.\r
- // TCG EFI Protocol Spec. Section 5.3 Event Log Header\r
- // TCG PC Client PFP spec. Section 9.2 Measurement Event Entries and Log\r
- //\r
- Status = TdxDxeLogEvent (\r
- LogFormat,\r
- &SpecIdEvent,\r
- sizeof (SpecIdEvent),\r
- (UINT8 *)TcgEfiSpecIdEventStruct,\r
- SpecIdEvent.EventSize\r
- );\r
- //\r
- // record the offset at the end of 800-155 event.\r
- // the future 800-155 event can be inserted here.\r
- //\r
- mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = mTdxDxeData.EventLogAreaStruct[Index].EventLogSize;\r
-\r
- //\r
- // Tcg800155PlatformIdEvent. Event format is TCG_PCR_EVENT2\r
- //\r
- GuidHob.Guid = GetFirstGuidHob (&gTcg800155PlatformIdEventHobGuid);\r
- while (GuidHob.Guid != NULL) {\r
- InitNoActionEvent (&NoActionEvent, GET_GUID_HOB_DATA_SIZE (GuidHob.Guid));\r
-\r
- Status = TdxDxeLogEvent (\r
- LogFormat,\r
- &NoActionEvent,\r
- sizeof (NoActionEvent.MrIndex) + sizeof (NoActionEvent.EventType) + GetDigestListBinSize (&NoActionEvent.Digests) + sizeof (NoActionEvent.EventSize),\r
- GET_GUID_HOB_DATA (GuidHob.Guid),\r
- GET_GUID_HOB_DATA_SIZE (GuidHob.Guid)\r
- );\r
-\r
- GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
- GuidHob.Guid = GetNextGuidHob (&gTcg800155PlatformIdEventHobGuid, GuidHob.Guid);\r
- }\r
-\r
- //\r
- // 2. Create Final Log Area\r
- //\r
- Status = gBS->AllocatePages (\r
- AllocateAnyPages,\r
- EfiACPIMemoryNVS,\r
- EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcg2FinalLogAreaLen)),\r
- &Lasa\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcg2FinalLogAreaLen), 0xFF);\r
-\r
- //\r
- // Initialize\r
- //\r
- mTdxDxeData.FinalEventsTable[Index] = (VOID *)(UINTN)Lasa;\r
- (mTdxDxeData.FinalEventsTable[Index])->Version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION;\r
- (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents = 0;\r
-\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa = Lasa + sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcg2FinalLogAreaLen) - sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0;\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].LastEvent = (VOID *)(UINTN)mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa;\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE;\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE;\r
- mTdxDxeData.FinalEventLogAreaStruct[Index].Next800155EventOffset = 0;\r
-\r
- //\r
- // Install to configuration table for EFI_CC_EVENT_LOG_FORMAT_TCG_2\r
- //\r
- Status = gBS->InstallConfigurationTable (&gEfiCcFinalEventsTableGuid, (VOID *)mTdxDxeData.FinalEventsTable[Index]);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Measure and log an action string, and extend the measurement result into RTMR.\r
-\r
- @param[in] MrIndex MrIndex to extend\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
-TdMeasureAction (\r
- IN UINT32 MrIndex,\r
- IN CHAR8 *String\r
- )\r
-{\r
- CC_EVENT_HDR CcEvent;\r
-\r
- CcEvent.MrIndex = MrIndex;\r
- CcEvent.EventType = EV_EFI_ACTION;\r
- CcEvent.EventSize = (UINT32)AsciiStrLen (String);\r
- return TdxDxeHashLogExtendEvent (\r
- 0,\r
- (UINT8 *)String,\r
- CcEvent.EventSize,\r
- &CcEvent,\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
- CC_EVENT_HDR CcEvent;\r
- EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
- UINTN ProcessorNum;\r
- EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
-\r
- ProcessorLocBuf = NULL;\r
- Status = EFI_SUCCESS;\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
- CcEvent.MrIndex = MapPcrToMrIndex (1);\r
- CcEvent.EventType = EV_TABLE_OF_DEVICES;\r
- CcEvent.EventSize = sizeof (HandoffTables);\r
-\r
- HandoffTables.NumberOfTables = 1;\r
- HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
- HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
-\r
- Status = TdxDxeHashLogExtendEvent (\r
- 0,\r
- (UINT8 *)(UINTN)ProcessorLocBuf,\r
- sizeof (EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
- &CcEvent,\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 UINT32 MrIndex\r
- )\r
-{\r
- CC_EVENT_HDR CcEvent;\r
- UINT32 EventData;\r
-\r
- DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent to Rtmr - %d\n", MrIndex));\r
-\r
- EventData = 0;\r
- CcEvent.MrIndex = MrIndex;\r
- CcEvent.EventType = EV_SEPARATOR;\r
- CcEvent.EventSize = (UINT32)sizeof (EventData);\r
-\r
- return TdxDxeHashLogExtendEvent (\r
- 0,\r
- (UINT8 *)&EventData,\r
- sizeof (EventData),\r
- &CcEvent,\r
- (UINT8 *)&EventData\r
- );\r
-}\r
-\r
-/**\r
- Measure and log an EFI variable, and extend the measurement result into a specific RTMR.\r
-\r
- @param[in] MrIndex RTMR 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 UINT32 MrIndex,\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
- CC_EVENT_HDR CcEvent;\r
- UINTN VarNameLength;\r
- UEFI_VARIABLE_DATA *VarLog;\r
-\r
- DEBUG ((DEBUG_INFO, "TdTcg2Dxe: MeasureVariable (Rtmr - %x, EventType - %x, ", (UINTN)MrIndex, (UINTN)EventType));\r
- DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
-\r
- VarNameLength = StrLen (VarName);\r
- CcEvent.MrIndex = MrIndex;\r
- CcEvent.EventType = EventType;\r
-\r
- CcEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
- - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
-\r
- VarLog = (UEFI_VARIABLE_DATA *)AllocatePool (CcEvent.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) && (VarData != NULL)) {\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 (UEFI_VARIABLE_DATA)\r
- //\r
- Status = TdxDxeHashLogExtendEvent (\r
- 0,\r
- (UINT8 *)VarLog,\r
- CcEvent.EventSize,\r
- &CcEvent,\r
- (UINT8 *)VarLog\r
- );\r
- } else {\r
- ASSERT (VarData != NULL);\r
- Status = TdxDxeHashLogExtendEvent (\r
- 0,\r
- (UINT8 *)VarData,\r
- VarSize,\r
- &CcEvent,\r
- (UINT8 *)VarLog\r
- );\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 RTMR.\r
-\r
- @param[in] MrIndex RTMR 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 UINT32 MrIndex,\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
- //\r
- // if status error, VarData is freed and set NULL by GetVariable2\r
- //\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_FOUND;\r
- }\r
- }\r
-\r
- Status = MeasureVariable (\r
- MrIndex,\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[1].\r
-according to TCG PC Client PFP spec 0021 Section 2.4.4.2\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
- //\r
- // Boot variables are measured into (PCR[5]) RTMR[1],\r
- // details in section 8.1 of TDVF design guide.\r
- //\r
- return ReadAndMeasureVariable (\r
- MapPcrToMrIndex (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
- MapPcrToMrIndex (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) || (BootOrder == NULL)) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
- //\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
- //\r
- // Measure DBT if present and not empty\r
- //\r
- Status = GetVariable2 (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, &Data, &DataSize);\r
- if (!EFI_ERROR (Status)) {\r
- Status = MeasureVariable (\r
- MapPcrToMrIndex (7),\r
- EV_EFI_VARIABLE_DRIVER_CONFIG,\r
- EFI_IMAGE_SECURITY_DATABASE2,\r
- &gEfiImageSecurityDatabaseGuid,\r
- Data,\r
- DataSize\r
- );\r
- FreePool (Data);\r
- } else {\r
- DEBUG ((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2));\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
- CC_EVENT_HDR CcEvent;\r
-\r
- CcEvent.MrIndex = MapPcrToMrIndex (7);\r
- CcEvent.EventType = EV_EFI_ACTION;\r
- CcEvent.EventSize = sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
- return TdxDxeHashLogExtendEvent (\r
- 0,\r
- (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
- sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
- &CcEvent,\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 ((DEBUG_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
- }\r
-\r
- Status = MeasureAllSecureVariables ();\r
- DEBUG ((DEBUG_INFO, "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 (MapPcrToMrIndex (7));\r
- DEBUG ((DEBUG_INFO, "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
-\r
- PERF_START_EX (mImageHandle, "EventRec", "TdTcg2Dxe", 0, PERF_ID_CC_TCG2_DXE);\r
- if (mBootAttempts == 0) {\r
- //\r
- // Measure handoff tables.\r
- //\r
- Status = MeasureHandoffTables ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_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 ((DEBUG_ERROR, "Boot Variables not Measured. Error!\n"));\r
- }\r
-\r
- //\r
- // 1. This is the first boot attempt.\r
- //\r
- Status = TdMeasureAction (\r
- MapPcrToMrIndex (4),\r
- EFI_CALLING_EFI_APPLICATION\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", 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 RTMR[0]) is already done.\r
- //\r
- Status = MeasureSeparatorEvent (1);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Separator Event not Measured. Error!\n"));\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 = TdMeasureAction (\r
- MapPcrToMrIndex (4),\r
- EFI_RETURNING_FROM_EFI_APPLICATION\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION));\r
- }\r
-\r
- //\r
- // 7. Next boot attempt, measure "Calling EFI Application from Boot Option" again\r
- // TCG PC Client PFP spec Section 2.4.4.5 Step 4\r
- //\r
- Status = TdMeasureAction (\r
- MapPcrToMrIndex (4),\r
- EFI_CALLING_EFI_APPLICATION\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
- }\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "TdTcg2Dxe Measure Data when ReadyToBoot\n"));\r
- //\r
- // Increase boot attempt counter.\r
- //\r
- mBootAttempts++;\r
- PERF_END_EX (mImageHandle, "EventRec", "Tcg2Dxe", 0, PERF_ID_CC_TCG2_DXE + 1);\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 = TdMeasureAction (\r
- MapPcrToMrIndex (5),\r
- EFI_EXIT_BOOT_SERVICES_INVOCATION\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
- }\r
-\r
- //\r
- // Measure success of ExitBootServices\r
- //\r
- Status = TdMeasureAction (\r
- MapPcrToMrIndex (5),\r
- EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
- }\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 = TdMeasureAction (\r
- MapPcrToMrIndex (5),\r
- EFI_EXIT_BOOT_SERVICES_FAILED\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-SyncCcEvent (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PEI_HOB_POINTERS GuidHob;\r
- VOID *CcEvent;\r
- VOID *DigestListBin;\r
- UINT32 DigestListBinSize;\r
- UINT8 *Event;\r
- UINT32 EventSize;\r
- EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
-\r
- DEBUG ((DEBUG_INFO, "Sync Cc event from SEC\n"));\r
-\r
- Status = EFI_SUCCESS;\r
- LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
- GuidHob.Guid = GetFirstGuidHob (&gCcEventEntryHobGuid);\r
-\r
- while (!EFI_ERROR (Status) && GuidHob.Guid != NULL) {\r
- CcEvent = AllocateCopyPool (GET_GUID_HOB_DATA_SIZE (GuidHob.Guid), GET_GUID_HOB_DATA (GuidHob.Guid));\r
- if (CcEvent == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
- GuidHob.Guid = GetNextGuidHob (&gCcEventEntryHobGuid, GuidHob.Guid);\r
-\r
- DigestListBin = (UINT8 *)CcEvent + sizeof (UINT32) + sizeof (TCG_EVENTTYPE);\r
- DigestListBinSize = GetDigestListBinSize (DigestListBin);\r
-\r
- //\r
- // Event size.\r
- //\r
- EventSize = *(UINT32 *)((UINT8 *)DigestListBin + DigestListBinSize);\r
- Event = (UINT8 *)DigestListBin + DigestListBinSize + sizeof (UINT32);\r
-\r
- //\r
- // Log the event\r
- //\r
- Status = TdxDxeLogEvent (\r
- LogFormat,\r
- CcEvent,\r
- sizeof (UINT32) + sizeof (TCG_EVENTTYPE) + DigestListBinSize + sizeof (UINT32),\r
- Event,\r
- EventSize\r
- );\r
-\r
- DumpCcEvent ((CC_EVENT *)CcEvent);\r
- FreePool (CcEvent);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Install TDVF ACPI Table when ACPI Table Protocol is available.\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
- UINT64 OemTableId;\r
-\r
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "TD: AcpiTableProtocol is not installed. %r\n", Status));\r
- return;\r
- }\r
-\r
- mTdxEventlogAcpiTemplate.Laml = (UINT64)PcdGet32 (PcdCcEventlogAcpiTableLaml);\r
- mTdxEventlogAcpiTemplate.Lasa = PcdGet64 (PcdCcEventlogAcpiTableLasa);\r
- CopyMem (mTdxEventlogAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTdxEventlogAcpiTemplate.Header.OemId));\r
- OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
- CopyMem (&mTdxEventlogAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
- mTdxEventlogAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
- mTdxEventlogAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
- mTdxEventlogAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
-\r
- //\r
- // Construct ACPI Table\r
- Status = AcpiTable->InstallAcpiTable (\r
- AcpiTable,\r
- &mTdxEventlogAcpiTemplate,\r
- mTdxEventlogAcpiTemplate.Header.Length,\r
- &TableKey\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- DEBUG ((DEBUG_INFO, "TDVF Eventlog ACPI Table is installed.\n"));\r
-}\r
-\r
-/**\r
- The function install TdTcg2 protocol.\r
-\r
- @retval EFI_SUCCESS TdTcg2 protocol is installed.\r
- @retval other Some error occurs.\r
-**/\r
-EFI_STATUS\r
-InstallCcMeasurementProtocol (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
-\r
- Handle = NULL;\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Handle,\r
- &gEfiCcMeasurementProtocolGuid,\r
- &mTdProtocol,\r
- NULL\r
- );\r
- DEBUG ((DEBUG_INFO, "CcProtocol: Install %r\n", Status));\r
- return Status;\r
-}\r
-\r
-/**\r
- The driver's entry point. It publishes EFI Tcg2 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
-\r
- if (!TdIsEnabled ()) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- mImageHandle = ImageHandle;\r
-\r
- //\r
- // Fill information\r
- //\r
- // ASSERT (TD_EVENT_LOG_AREA_COUNT_MAX == sizeof(mTEventInfo)/sizeof(mTcg2EventInfo[0]));\r
-\r
- mTdxDxeData.BsCap.Size = sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY);\r
- mTdxDxeData.BsCap.ProtocolVersion.Major = 1;\r
- mTdxDxeData.BsCap.ProtocolVersion.Minor = 0;\r
- mTdxDxeData.BsCap.StructureVersion.Major = 1;\r
- mTdxDxeData.BsCap.StructureVersion.Minor = 0;\r
-\r
- //\r
- // Get supported PCR and current Active PCRs\r
- // For TD gueset HA384 is supported.\r
- //\r
- mTdxDxeData.BsCap.HashAlgorithmBitmap = HASH_ALG_SHA384;\r
-\r
- // TD guest only supports EFI_TCG2_EVENT_LOG_FORMAT_TCG_2\r
- mTdxDxeData.BsCap.SupportedEventLogs = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
-\r
- //\r
- // Setup the log area and copy event log from hob list to it\r
- //\r
- Status = SetupCcEventLog ();\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Status = SyncCcEvent ();\r
- ASSERT_EFI_ERROR (Status);\r
- }\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
- // Install CcMeasurementProtocol\r
- //\r
- Status = InstallCcMeasurementProtocol ();\r
- DEBUG ((DEBUG_INFO, "InstallCcMeasurementProtocol - %r\n", Status));\r
-\r
- if (Status == EFI_SUCCESS) {\r
- //\r
- // Create event callback to install CC EventLog ACPI Table\r
- EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
- }\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-## @file\r
-#\r
-# Produces EFI_CC_MEASUREMENT_PROTOCOL and measure boot environment\r
-#\r
-#\r
-# Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>\r
-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-##\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = TdTcg2Dxe\r
- FILE_GUID = F062221E-C607-44C2-B0B4-C3886331D351\r
- MODULE_TYPE = DXE_DRIVER\r
- VERSION_STRING = 1.0\r
- ENTRY_POINT = DriverEntry\r
-\r
-#\r
-# The following information is for reference only and not required by the build tools.\r
-#\r
-# VALID_ARCHITECTURES = X64\r
-#\r
-\r
-[Sources]\r
- TdTcg2Dxe.c\r
- MeasureBootPeCoff.c\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
- SecurityPkg/SecurityPkg.dec\r
- CryptoPkg/CryptoPkg.dec\r
- OvmfPkg/OvmfPkg.dec\r
-\r
-[LibraryClasses]\r
- MemoryAllocationLib\r
- BaseLib\r
- UefiBootServicesTableLib\r
- HobLib\r
- UefiDriverEntryPoint\r
- UefiRuntimeServicesTableLib\r
- BaseMemoryLib\r
- DebugLib\r
- PrintLib\r
- UefiLib\r
- HashLib\r
- PerformanceLib\r
- ReportStatusCodeLib\r
- PeCoffLib\r
- TpmMeasurementLib\r
- TdxLib\r
-\r
-[Guids]\r
- ## SOMETIMES_CONSUMES ## Variable:L"SecureBoot"\r
- ## SOMETIMES_CONSUMES ## Variable:L"PK"\r
- ## SOMETIMES_CONSUMES ## Variable:L"KEK"\r
- ## SOMETIMES_CONSUMES ## Variable:L"BootXXXX"\r
- gEfiGlobalVariableGuid\r
-\r
- ## SOMETIMES_CONSUMES ## Variable:L"db"\r
- ## SOMETIMES_CONSUMES ## Variable:L"dbx"\r
- gEfiImageSecurityDatabaseGuid\r
-\r
- # gTcgEventEntryHobGuid ## SOMETIMES_CONSUMES ## HOB\r
- gEfiEventExitBootServicesGuid ## CONSUMES ## Event\r
- gEventExitBootServicesFailedGuid ## SOMETIMES_CONSUMES ## Event\r
-\r
- gCcEventEntryHobGuid ## SOMETIMES_CONSUMES ## HOB\r
- gTcg800155PlatformIdEventHobGuid ## SOMETIMES_CONSUMES ## HOB\r
- gEfiCcFinalEventsTableGuid ## PRODUCES\r
-\r
-[Protocols]\r
- gEfiCcMeasurementProtocolGuid ## PRODUCES\r
- gEfiMpServiceProtocolGuid ## SOMETIMES_CONSUMES\r
- gEfiVariableWriteArchProtocolGuid ## NOTIFY\r
- gEfiResetNotificationProtocolGuid ## CONSUMES\r
- gEfiAcpiTableProtocolGuid ## NOTIFY\r
-\r
-[Pcd]\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass ## SOMETIMES_CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdFirmwareDebuggerInitialized ## SOMETIMES_CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeSubClassTpmDevice ## SOMETIMES_CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTcg2NumberOfPCRBanks ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTcgLogAreaMinLen ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTcg2FinalLogAreaLen ## CONSUMES\r
- gUefiOvmfPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLaml ## PRODUCES\r
- gUefiOvmfPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLasa ## PRODUCES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES\r
-\r
-[Depex]\r
- # According to PcdTpm2AcpiTableRev definition in SecurityPkg.dec\r
- # This PCD should be configured at DynamicHii or DynamicHiiEx.\r
- # So, this PCD read operation depends on GetVariable service.\r
- # Add VariableArch protocol dependency to make sure PCD read works.\r
- gEfiVariableArchProtocolGuid AND gEfiAcpiTableProtocolGuid\r
# 2 - set by GOP Driver.\r
gUefiOvmfPkgTokenSpaceGuid.PcdVideoResolutionSource|0|UINT8|0x64\r
\r
- ## This PCD records LAML field in CC EVENTLOG ACPI table.\r
- gUefiOvmfPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLaml|0|UINT32|0x66\r
-\r
- ## This PCD records LASA field in CC EVENTLOG ACPI table.\r
- gUefiOvmfPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLasa|0|UINT64|0x67\r
-\r
[PcdsFeatureFlag]\r
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c\r
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d\r
# @Prompt Tpm2AcpiTableLasa LASA field in TPM2 ACPI table.\r
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa|0|UINT64|0x00010023\r
\r
+ ## This PCD records LAML field in CC EVENTLOG ACPI table.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLaml|0|UINT32|0x00010025\r
+\r
+ ## This PCD records LASA field in CC EVENTLOG ACPI table.\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLasa|0|UINT64|0x00010026\r
+\r
[UserExtensions.TianoCore."ExtraFiles"]\r
SecurityPkgExtra.uni\r
[Components.X64]\r
SecurityPkg/Library/HashLibTdx/HashLibTdx.inf\r
SecurityPkg/Library/SecTpmMeasurementLib/SecTpmMeasurementLibTdx.inf\r
+ SecurityPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf {\r
+ <LibraryClasses>\r
+ HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf\r
+ NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf\r
+ }\r
\r
[Components.IA32, Components.X64]\r
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
--- /dev/null
+/** @file\r
+ This module implements measuring PeCoff image for Tcg2 Protocol.\r
+\r
+ Caution: This file requires additional review when modified.\r
+ This driver will have external input - PE/COFF image.\r
+ This external input must be validated carefully to avoid security issue like\r
+ buffer overflow, integer overflow.\r
+\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/HashLib.h>\r
+\r
+UINTN mTcg2DxeImageSize = 0;\r
+\r
+/**\r
+ Reads contents of a PE/COFF image in memory buffer.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
+ read is within the image buffer.\r
+\r
+ @param FileHandle Pointer to the file handle to read the PE/COFF image.\r
+ @param FileOffset Offset into the PE/COFF image to begin the read operation.\r
+ @param ReadSize On input, the size in bytes of the requested read operation.\r
+ On output, the number of bytes actually read.\r
+ @param Buffer Output buffer that contains the data read from the PE/COFF image.\r
+\r
+ @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tcg2DxeImageRead (\r
+ IN VOID *FileHandle,\r
+ IN UINTN FileOffset,\r
+ IN OUT UINTN *ReadSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ UINTN EndPosition;\r
+\r
+ if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ EndPosition = FileOffset + *ReadSize;\r
+ if (EndPosition > mTcg2DxeImageSize) {\r
+ *ReadSize = (UINT32)(mTcg2DxeImageSize - FileOffset);\r
+ }\r
+\r
+ if (FileOffset >= mTcg2DxeImageSize) {\r
+ *ReadSize = 0;\r
+ }\r
+\r
+ CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Measure PE image into TPM log based on the authenticode image hashing in\r
+ PE/COFF Specification 8.0 Appendix A.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ PE/COFF image is external input, so this function will validate its data structure\r
+ within this image buffer before use.\r
+\r
+ Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
+\r
+ @param[in] RtmrIndex Rtmr index\r
+ @param[in] ImageAddress Start address of image buffer.\r
+ @param[in] ImageSize Image size\r
+ @param[out] DigestList Digest 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 RtmrIndex,\r
+ IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
+ IN UINTN ImageSize,\r
+ OUT TPML_DIGEST_VALUES *DigestList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_DOS_HEADER *DosHdr;\r
+ UINT32 PeCoffHeaderOffset;\r
+ EFI_IMAGE_SECTION_HEADER *Section;\r
+ UINT8 *HashBase;\r
+ UINTN HashSize;\r
+ UINTN SumOfBytesHashed;\r
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
+ UINTN Index;\r
+ UINTN Pos;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+ UINT32 NumberOfRvaAndSizes;\r
+ UINT32 CertSize;\r
+ HASH_HANDLE HashHandle;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+\r
+ HashHandle = 0xFFFFFFFF; // Know bad value\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ SectionHeader = NULL;\r
+\r
+ //\r
+ // Check PE/COFF image\r
+ //\r
+ ZeroMem (&ImageContext, sizeof (ImageContext));\r
+ ImageContext.Handle = (VOID *)(UINTN)ImageAddress;\r
+ mTcg2DxeImageSize = ImageSize;\r
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)Tcg2DxeImageRead;\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
+ DEBUG ((DEBUG_INFO, "Tcg2Dxe: PeImage invalid. Cannot retrieve image information.\n"));\r
+ goto Finish;\r
+ }\r
+\r
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;\r
+ PeCoffHeaderOffset = 0;\r
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+ PeCoffHeaderOffset = DosHdr->e_lfanew;\r
+ }\r
+\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);\r
+ if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Finish;\r
+ }\r
+\r
+ //\r
+ // PE/COFF Image Measurement\r
+ //\r
+ // NOTE: The following codes/steps are based upon the authenticode image hashing in\r
+ // PE/COFF Specification 8.0 Appendix A.\r
+ //\r
+ //\r
+\r
+ // 1. Load the image header into memory.\r
+\r
+ // 2. Initialize a SHA hash context.\r
+\r
+ Status = HashStart (&HashHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+\r
+ //\r
+ // Measuring PE/COFF Image Header;\r
+ // But CheckSum field and SECURITY data directory (certificate) are excluded\r
+ //\r
+\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 (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset\r
+ //\r
+ NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+ HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
+ } else {\r
+ //\r
+ // Use PE32+ offset\r
+ //\r
+ NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+ HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
+ }\r
+\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+\r
+ //\r
+ // 5. Skip over the image checksum (it occupies a single ULONG).\r
+ //\r
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+ //\r
+ // 6. Since there is no Cert Directory in optional header, hash everything\r
+ // from the end of the checksum to the end of image header.\r
+ //\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset.\r
+ //\r
+ HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+ HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset.\r
+ //\r
+ HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+ HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
+ }\r
+\r
+ if (HashSize != 0) {\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
+ //\r
+ if (Hdr.Pe32->OptionalHeader.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)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
+ } else {\r
+ //\r
+ // Use PE32+ offset\r
+ //\r
+ HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+ HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
+ }\r
+\r
+ if (HashSize != 0) {\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+ }\r
+\r
+ //\r
+ // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
+ // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
+ //\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset\r
+ //\r
+ HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+ HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
+ } else {\r
+ //\r
+ // Use PE32+ offset\r
+ //\r
+ HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+ HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
+ }\r
+\r
+ if (HashSize != 0) {\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // 10. Set the SUM_OF_BYTES_HASHED to the size of the header\r
+ //\r
+ if (Hdr.Pe32->OptionalHeader.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
+\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
+\r
+ HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData;\r
+ HashSize = (UINTN)Section->SizeOfRawData;\r
+\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+\r
+ SumOfBytesHashed += HashSize;\r
+ }\r
+\r
+ //\r
+ // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
+ // data in the file that needs to be added to the hash. This data begins\r
+ // at file offset SUM_OF_BYTES_HASHED and its length is:\r
+ // FileSize - (CertDirectory->Size)\r
+ //\r
+ if (ImageSize > SumOfBytesHashed) {\r
+ HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed;\r
+\r
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+ CertSize = 0;\r
+ } else {\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Use PE32 offset.\r
+ //\r
+ CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+ } else {\r
+ //\r
+ // Use PE32+ offset.\r
+ //\r
+ CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+ }\r
+ }\r
+\r
+ if (ImageSize > CertSize + SumOfBytesHashed) {\r
+ HashSize = (UINTN)(ImageSize - CertSize - SumOfBytesHashed);\r
+\r
+ Status = HashUpdate (HashHandle, HashBase, HashSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+ } else if (ImageSize < CertSize + SumOfBytesHashed) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Finish;\r
+ }\r
+ }\r
+\r
+ //\r
+ // 17. Finalize the SHA hash.\r
+ //\r
+ Status = HashCompleteAndExtend (HashHandle, RtmrIndex, NULL, 0, DigestList);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
+\r
+Finish:\r
+ if (SectionHeader != NULL) {\r
+ FreePool (SectionHeader);\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ This module implements EFI TD Protocol.\r
+\r
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <IndustryStandard/TcpaAcpi.h>\r
+\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/HobList.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/MpService.h>\r
+#include <Protocol/VariableWrite.h>\r
+#include <Protocol/Tcg2Protocol.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+#include <Protocol/ResetNotification.h>\r
+#include <Protocol/AcpiTable.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/PcdLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+\r
+#include <Protocol/CcMeasurement.h>\r
+#include <Guid/CcEventHob.h>\r
+#include <Library/TdxLib.h>\r
+\r
+#define PERF_ID_CC_TCG2_DXE 0x3130\r
+\r
+#define CC_EVENT_LOG_AREA_COUNT_MAX 1\r
+#define CC_MR_INDEX_0_MRTD 0\r
+#define CC_MR_INDEX_1_RTMR0 1\r
+#define CC_MR_INDEX_2_RTMR1 2\r
+#define CC_MR_INDEX_3_RTMR2 3\r
+#define CC_MR_INDEX_INVALID 4\r
+\r
+typedef struct {\r
+ CHAR16 *VariableName;\r
+ EFI_GUID *VendorGuid;\r
+} VARIABLE_TYPE;\r
+\r
+typedef struct {\r
+ EFI_GUID *EventGuid;\r
+ EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
+} CC_EVENT_INFO_STRUCT;\r
+\r
+typedef struct {\r
+ EFI_CC_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
+ UINTN Next800155EventOffset;\r
+} CC_EVENT_LOG_AREA_STRUCT;\r
+\r
+typedef struct _TDX_DXE_DATA {\r
+ EFI_CC_BOOT_SERVICE_CAPABILITY BsCap;\r
+ CC_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
+ BOOLEAN GetEventLogCalled[CC_EVENT_LOG_AREA_COUNT_MAX];\r
+ CC_EVENT_LOG_AREA_STRUCT FinalEventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
+ EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable[CC_EVENT_LOG_AREA_COUNT_MAX];\r
+} TDX_DXE_DATA;\r
+\r
+typedef struct {\r
+ TPMI_ALG_HASH HashAlgo;\r
+ UINT16 HashSize;\r
+ UINT32 HashMask;\r
+} TDX_HASH_INFO;\r
+\r
+//\r
+//\r
+CC_EVENT_INFO_STRUCT mCcEventInfo[] = {\r
+ { &gCcEventEntryHobGuid, EFI_CC_EVENT_LOG_FORMAT_TCG_2 },\r
+};\r
+\r
+TDX_DXE_DATA mTdxDxeData = {\r
+ {\r
+ sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY), // Size\r
+ { 1, 1 }, // StructureVersion\r
+ { 1, 1 }, // ProtocolVersion\r
+ EFI_CC_BOOT_HASH_ALG_SHA384, // HashAlgorithmBitmap\r
+ EFI_CC_EVENT_LOG_FORMAT_TCG_2, // SupportedEventLogs\r
+ { 2, 0 } // {CC_TYPE, CC_SUBTYPE}\r
+ },\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_CC_EVENTLOG_ACPI_TABLE mTdxEventlogAcpiTemplate = {\r
+ {\r
+ EFI_CC_EVENTLOG_ACPI_TABLE_SIGNATURE,\r
+ sizeof (mTdxEventlogAcpiTemplate),\r
+ EFI_CC_EVENTLOG_ACPI_TABLE_REVISION,\r
+ //\r
+ // Compiler initializes the remaining bytes to 0\r
+ // These fields should be filled in production\r
+ //\r
+ },\r
+ { EFI_CC_TYPE_TDX, 0 }, // CcType\r
+ 0, // rsvd\r
+ 0, // laml\r
+ 0, // lasa\r
+};\r
+\r
+//\r
+// Supported Hash list in Td guest.\r
+// Currently SHA384 is supported.\r
+//\r
+TDX_HASH_INFO mHashInfo[] = {\r
+ { TPM_ALG_SHA384, SHA384_DIGEST_SIZE, HASH_ALG_SHA384 }\r
+};\r
+\r
+/**\r
+ Get hash size based on Algo\r
+\r
+ @param[in] HashAlgo Hash Algorithm Id.\r
+\r
+ @return Size of the hash.\r
+**/\r
+UINT16\r
+GetHashSizeFromAlgo (\r
+ IN TPMI_ALG_HASH HashAlgo\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < sizeof (mHashInfo)/sizeof (mHashInfo[0]); Index++) {\r
+ if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
+ return mHashInfo[Index].HashSize;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+/**\r
+ Get hash mask based on Algo\r
+\r
+ @param[in] HashAlgo Hash Algorithm Id.\r
+\r
+ @return Hash mask.\r
+**/\r
+UINT32\r
+GetHashMaskFromAlgo (\r
+ IN TPMI_ALG_HASH HashAlgo\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < ARRAY_SIZE (mHashInfo); Index++) {\r
+ if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
+ return mHashInfo[Index].HashMask;\r
+ }\r
+ }\r
+\r
+ ASSERT (FALSE);\r
+ return 0;\r
+}\r
+\r
+/**\r
+ Copy TPML_DIGEST_VALUES into a buffer\r
+\r
+ @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
+ @param[in] DigestList TPML_DIGEST_VALUES to be copied.\r
+ @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
+\r
+ @return The end of buffer to hold TPML_DIGEST_VALUES.\r
+**/\r
+VOID *\r
+CopyDigestListToBuffer (\r
+ IN OUT VOID *Buffer,\r
+ IN TPML_DIGEST_VALUES *DigestList,\r
+ IN UINT32 HashAlgorithmMask\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 DigestSize;\r
+ UINT32 DigestListCount;\r
+ UINT32 *DigestListCountPtr;\r
+\r
+ DigestListCountPtr = (UINT32 *)Buffer;\r
+ DigestListCount = 0;\r
+ Buffer = (UINT8 *)Buffer + sizeof (DigestList->count);\r
+ for (Index = 0; Index < DigestList->count; Index++) {\r
+ if ((DigestList->digests[Index].hashAlg & HashAlgorithmMask) == 0) {\r
+ DEBUG ((DEBUG_ERROR, "WARNING: TD Event log has HashAlg unsupported (0x%x)\n", DigestList->digests[Index].hashAlg));\r
+ continue;\r
+ }\r
+\r
+ CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof (DigestList->digests[Index].hashAlg));\r
+ Buffer = (UINT8 *)Buffer + sizeof (DigestList->digests[Index].hashAlg);\r
+ DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);\r
+ CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);\r
+ Buffer = (UINT8 *)Buffer + DigestSize;\r
+ DigestListCount++;\r
+ }\r
+\r
+ WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
+\r
+ return Buffer;\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
+ Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
+\r
+ @param[in] RtmrIndex RTMR index\r
+ @param[in] ImageAddress Start address of image buffer.\r
+ @param[in] ImageSize Image size\r
+ @param[out] DigestList Digest 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 RtmrIndex,\r
+ IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
+ IN UINTN ImageSize,\r
+ OUT TPML_DIGEST_VALUES *DigestList\r
+ );\r
+\r
+#define COLUME_SIZE (16 * 2)\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
+\r
+ for (Index = 0; Index < Size; Index++) {\r
+ DEBUG ((DEBUG_INFO, Index == COLUME_SIZE/2 ? " | %02x" : " %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
+ Count = Size / COLUME_SIZE;\r
+ Left = Size % COLUME_SIZE;\r
+ for (Index = 0; Index < Count; Index++) {\r
+ DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
+ InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);\r
+ DEBUG ((DEBUG_INFO, "\n"));\r
+ }\r
+\r
+ if (Left != 0) {\r
+ DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
+ InternalDumpData (Data + Index * COLUME_SIZE, Left);\r
+ DEBUG ((DEBUG_INFO, "\n"));\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ This function initialize TD_EVENT_HDR for EV_NO_ACTION\r
+ Event Type other than EFI Specification ID event. The behavior is defined\r
+ by TCG PC Client PFP Spec. Section 9.3.4 EV_NO_ACTION Event Types\r
+\r
+ @param[in, out] NoActionEvent Event Header of EV_NO_ACTION Event\r
+ @param[in] EventSize Event Size of the EV_NO_ACTION Event\r
+\r
+**/\r
+VOID\r
+InitNoActionEvent (\r
+ IN OUT CC_EVENT_HDR *NoActionEvent,\r
+ IN UINT32 EventSize\r
+ )\r
+{\r
+ UINT32 DigestListCount;\r
+ TPMI_ALG_HASH HashAlgId;\r
+ UINT8 *DigestBuffer;\r
+\r
+ DigestBuffer = (UINT8 *)NoActionEvent->Digests.digests;\r
+ DigestListCount = 0;\r
+\r
+ NoActionEvent->MrIndex = 0;\r
+ NoActionEvent->EventType = EV_NO_ACTION;\r
+\r
+ //\r
+ // Set Hash count & hashAlg accordingly, while Digest.digests[n].digest to all 0\r
+ //\r
+ ZeroMem (&NoActionEvent->Digests, sizeof (NoActionEvent->Digests));\r
+\r
+ if ((mTdxDxeData.BsCap.HashAlgorithmBitmap & EFI_CC_BOOT_HASH_ALG_SHA384) != 0) {\r
+ HashAlgId = TPM_ALG_SHA384;\r
+ CopyMem (DigestBuffer, &HashAlgId, sizeof (TPMI_ALG_HASH));\r
+ DigestBuffer += sizeof (TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId);\r
+ DigestListCount++;\r
+ }\r
+\r
+ //\r
+ // Set Digests Count\r
+ //\r
+ WriteUnaligned32 ((UINT32 *)&NoActionEvent->Digests.count, DigestListCount);\r
+\r
+ //\r
+ // Set Event Size\r
+ //\r
+ WriteUnaligned32 ((UINT32 *)DigestBuffer, EventSize);\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_CC_MEASUREMENT_PROTOCOL GetCapability function call provides protocol\r
+ capability information and state information.\r
+\r
+ @param[in] This Indicates the calling context\r
+ @param[in, out] ProtocolCapability The caller allocates memory for a EFI_CC_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 EFI TCG2 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
+TdGetCapability (\r
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
+ IN OUT EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability\r
+ )\r
+{\r
+ DEBUG ((DEBUG_VERBOSE, "TdGetCapability\n"));\r
+\r
+ if ((This == NULL) || (ProtocolCapability == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (ProtocolCapability, &mTdxDxeData.BsCap, sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function dump PCR event.\r
+ TD Event log reuse the TCG PCR Event spec.\r
+ The first event in the event log is the SHA1 log format.\r
+ There is only ONE TCG_PCR_EVENT in TD Event log.\r
+\r
+ @param[in] EventHdr TCG PCR event structure.\r
+**/\r
+VOID\r
+DumpPcrEvent (\r
+ IN TCG_PCR_EVENT_HDR *EventHdr\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ DEBUG ((DEBUG_INFO, " Event:\n"));\r
+ DEBUG ((DEBUG_INFO, " MrIndex - %d\n", EventHdr->PCRIndex));\r
+ DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", EventHdr->EventType));\r
+ DEBUG ((DEBUG_INFO, " Digest - "));\r
+ for (Index = 0; Index < sizeof (TCG_DIGEST); Index++) {\r
+ DEBUG ((DEBUG_INFO, "%02x ", EventHdr->Digest.digest[Index]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "\n"));\r
+ DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize));\r
+ InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);\r
+}\r
+\r
+/**\r
+ This function dump TCG_EfiSpecIDEventStruct.\r
+\r
+ @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
+**/\r
+VOID\r
+DumpTcgEfiSpecIdEventStruct (\r
+ IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
+ )\r
+{\r
+ TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
+ UINTN Index;\r
+ UINT8 *VendorInfoSize;\r
+ UINT8 *VendorInfo;\r
+ UINT32 NumberOfAlgorithms;\r
+\r
+ DEBUG ((DEBUG_INFO, " TCG_EfiSpecIDEventStruct:\n"));\r
+ DEBUG ((DEBUG_INFO, " signature - '"));\r
+ for (Index = 0; Index < sizeof (TcgEfiSpecIdEventStruct->signature); Index++) {\r
+ DEBUG ((DEBUG_INFO, "%c", TcgEfiSpecIdEventStruct->signature[Index]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "'\n"));\r
+ DEBUG ((DEBUG_INFO, " platformClass - 0x%08x\n", TcgEfiSpecIdEventStruct->platformClass));\r
+ DEBUG ((DEBUG_INFO, " specVersion - %d.%d%d\n", TcgEfiSpecIdEventStruct->specVersionMajor, TcgEfiSpecIdEventStruct->specVersionMinor, TcgEfiSpecIdEventStruct->specErrata));\r
+ DEBUG ((DEBUG_INFO, " uintnSize - 0x%02x\n", TcgEfiSpecIdEventStruct->uintnSize));\r
+\r
+ CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
+ DEBUG ((DEBUG_INFO, " NumberOfAlgorithms - 0x%08x\n", NumberOfAlgorithms));\r
+\r
+ DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
+ for (Index = 0; Index < NumberOfAlgorithms; Index++) {\r
+ DEBUG ((DEBUG_INFO, " digest(%d)\n", Index));\r
+ DEBUG ((DEBUG_INFO, " algorithmId - 0x%04x\n", DigestSize[Index].algorithmId));\r
+ DEBUG ((DEBUG_INFO, " digestSize - 0x%04x\n", DigestSize[Index].digestSize));\r
+ }\r
+\r
+ VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
+ DEBUG ((DEBUG_INFO, " VendorInfoSize - 0x%02x\n", *VendorInfoSize));\r
+ VendorInfo = VendorInfoSize + 1;\r
+ DEBUG ((DEBUG_INFO, " VendorInfo - "));\r
+ for (Index = 0; Index < *VendorInfoSize; Index++) {\r
+ DEBUG ((DEBUG_INFO, "%02x ", VendorInfo[Index]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+/**\r
+ This function get size of TCG_EfiSpecIDEventStruct.\r
+\r
+ @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
+**/\r
+UINTN\r
+GetTcgEfiSpecIdEventStructSize (\r
+ IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
+ )\r
+{\r
+ TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
+ UINT8 *VendorInfoSize;\r
+ UINT32 NumberOfAlgorithms;\r
+\r
+ CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
+\r
+ DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
+ VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
+ return sizeof (TCG_EfiSpecIDEventStruct) + sizeof (UINT32) + (NumberOfAlgorithms * sizeof (TCG_EfiSpecIdEventAlgorithmSize)) + sizeof (UINT8) + (*VendorInfoSize);\r
+}\r
+\r
+/**\r
+ This function dump TD Event (including the Digests).\r
+\r
+ @param[in] CcEvent TD Event structure.\r
+**/\r
+VOID\r
+DumpCcEvent (\r
+ IN CC_EVENT *CcEvent\r
+ )\r
+{\r
+ UINT32 DigestIndex;\r
+ UINT32 DigestCount;\r
+ TPMI_ALG_HASH HashAlgo;\r
+ UINT32 DigestSize;\r
+ UINT8 *DigestBuffer;\r
+ UINT32 EventSize;\r
+ UINT8 *EventBuffer;\r
+\r
+ DEBUG ((DEBUG_INFO, "Cc Event:\n"));\r
+ DEBUG ((DEBUG_INFO, " MrIndex - %d\n", CcEvent->MrIndex));\r
+ DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", CcEvent->EventType));\r
+ DEBUG ((DEBUG_INFO, " DigestCount: 0x%08x\n", CcEvent->Digests.count));\r
+\r
+ DigestCount = CcEvent->Digests.count;\r
+ HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
+ DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
+ for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
+ DEBUG ((DEBUG_INFO, " HashAlgo : 0x%04x\n", HashAlgo));\r
+ DEBUG ((DEBUG_INFO, " Digest(%d): \n", DigestIndex));\r
+ DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
+ InternalDumpHex (DigestBuffer, DigestSize);\r
+ //\r
+ // Prepare next\r
+ //\r
+ CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
+ DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
+ }\r
+\r
+ DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
+\r
+ CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
+ DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventSize));\r
+ EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
+ InternalDumpHex (EventBuffer, EventSize);\r
+ DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+/**\r
+ This function returns size of Td Table event.\r
+\r
+ @param[in] CcEvent Td Table event structure.\r
+\r
+ @return size of Td event.\r
+**/\r
+UINTN\r
+GetCcEventSize (\r
+ IN CC_EVENT *CcEvent\r
+ )\r
+{\r
+ UINT32 DigestIndex;\r
+ UINT32 DigestCount;\r
+ TPMI_ALG_HASH HashAlgo;\r
+ UINT32 DigestSize;\r
+ UINT8 *DigestBuffer;\r
+ UINT32 EventSize;\r
+ UINT8 *EventBuffer;\r
+\r
+ DigestCount = CcEvent->Digests.count;\r
+ HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
+ DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
+ for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
+ DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
+ //\r
+ // Prepare next\r
+ //\r
+ CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
+ DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
+ }\r
+\r
+ DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
+\r
+ CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
+ EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
+\r
+ return (UINTN)EventBuffer + EventSize - (UINTN)CcEvent;\r
+}\r
+\r
+/**\r
+ This function dump CC event log.\r
+ TDVF only supports EFI_CC_EVENT_LOG_FORMAT_TCG_2\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
+ @param[in] FinalEventsTable A pointer to the memory address of the final event table.\r
+**/\r
+VOID\r
+DumpCcEventLog (\r
+ IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
+ IN EFI_PHYSICAL_ADDRESS EventLogLocation,\r
+ IN EFI_PHYSICAL_ADDRESS EventLogLastEntry,\r
+ IN EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable\r
+ )\r
+{\r
+ TCG_PCR_EVENT_HDR *EventHdr;\r
+ CC_EVENT *CcEvent;\r
+ TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
+ UINTN NumberOfEvents;\r
+\r
+ DEBUG ((DEBUG_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));\r
+ ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
+\r
+ //\r
+ // Dump first event.\r
+ // The first event is always the TCG_PCR_EVENT_HDR\r
+ // After this event is a TCG_EfiSpecIDEventStruct\r
+ //\r
+ EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;\r
+ DumpPcrEvent (EventHdr);\r
+\r
+ TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)(EventHdr + 1);\r
+ DumpTcgEfiSpecIdEventStruct (TcgEfiSpecIdEventStruct);\r
+\r
+ //\r
+ // Then the CcEvent (Its structure is similar to TCG_PCR_EVENT2)\r
+ //\r
+ CcEvent = (CC_EVENT *)((UINTN)TcgEfiSpecIdEventStruct + GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct));\r
+ while ((UINTN)CcEvent <= EventLogLastEntry) {\r
+ DumpCcEvent (CcEvent);\r
+ CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
+ }\r
+\r
+ if (FinalEventsTable == NULL) {\r
+ DEBUG ((DEBUG_INFO, "FinalEventsTable: NOT FOUND\n"));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable));\r
+ DEBUG ((DEBUG_INFO, " Version: (0x%x)\n", FinalEventsTable->Version));\r
+ DEBUG ((DEBUG_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents));\r
+\r
+ CcEvent = (CC_EVENT *)(UINTN)(FinalEventsTable + 1);\r
+ for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) {\r
+ DumpCcEvent (CcEvent);\r
+ CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
+ }\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ The EFI_CC_MEASUREMENT_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
+TdGetEventLog (\r
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
+ IN EFI_CC_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 = 0;\r
+\r
+ DEBUG ((DEBUG_INFO, "TdGetEventLog ... (0x%x)\n", EventLogFormat));\r
+ ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
+\r
+ if (EventLogLocation != NULL) {\r
+ *EventLogLocation = mTdxDxeData.EventLogAreaStruct[Index].Lasa;\r
+ DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));\r
+ }\r
+\r
+ if (EventLogLastEntry != NULL) {\r
+ if (!mTdxDxeData.EventLogAreaStruct[Index].EventLogStarted) {\r
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
+ } else {\r
+ *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTdxDxeData.EventLogAreaStruct[Index].LastEvent;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));\r
+ }\r
+\r
+ if (EventLogTruncated != NULL) {\r
+ *EventLogTruncated = mTdxDxeData.EventLogAreaStruct[Index].EventLogTruncated;\r
+ DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "TdGetEventLog - %r\n", EFI_SUCCESS));\r
+\r
+ // Dump Event Log for debug purpose\r
+ if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {\r
+ DumpCcEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry, mTdxDxeData.FinalEventsTable[Index]);\r
+ }\r
+\r
+ //\r
+ // All events generated after the invocation of EFI_TCG2_GET_EVENT_LOG SHALL be stored\r
+ // in an instance of an EFI_CONFIGURATION_TABLE named by the VendorGuid of EFI_TCG2_FINAL_EVENTS_TABLE_GUID.\r
+ //\r
+ mTdxDxeData.GetEventLogCalled[Index] = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Return if this is a Tcg800155PlatformIdEvent.\r
+\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 TRUE This is a Tcg800155PlatformIdEvent.\r
+ @retval FALSE This is NOT a Tcg800155PlatformIdEvent.\r
+\r
+**/\r
+BOOLEAN\r
+Is800155Event (\r
+ IN VOID *NewEventHdr,\r
+ IN UINT32 NewEventHdrSize,\r
+ IN UINT8 *NewEventData,\r
+ IN UINT32 NewEventSize\r
+ )\r
+{\r
+ if ((((TCG_PCR_EVENT2_HDR *)NewEventHdr)->EventType == EV_NO_ACTION) &&\r
+ (NewEventSize >= sizeof (TCG_Sp800_155_PlatformId_Event2)) &&\r
+ (CompareMem (\r
+ NewEventData,\r
+ TCG_Sp800_155_PlatformId_Event2_SIGNATURE,\r
+ sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1\r
+ ) == 0))\r
+ {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Add a new entry to the Event Log.\r
+\r
+ @param[in, out] EventLogAreaStruct The event log area data structure\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 CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct,\r
+ IN VOID *NewEventHdr,\r
+ IN UINT32 NewEventHdrSize,\r
+ IN UINT8 *NewEventData,\r
+ IN UINT32 NewEventSize\r
+ )\r
+{\r
+ UINTN NewLogSize;\r
+ BOOLEAN Record800155Event;\r
+ CC_EVENT_HDR *CcEventHdr;\r
+\r
+ CcEventHdr = (CC_EVENT_HDR *)NewEventHdr;\r
+ DEBUG ((DEBUG_VERBOSE, "Td: Try to log event. Index = %d, EventType = 0x%x\n", CcEventHdr->MrIndex, CcEventHdr->EventType));\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 - EventLogAreaStruct->EventLogSize) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (NewLogSize + EventLogAreaStruct->EventLogSize > EventLogAreaStruct->Laml) {\r
+ DEBUG ((DEBUG_INFO, " Laml - 0x%x\n", EventLogAreaStruct->Laml));\r
+ DEBUG ((DEBUG_INFO, " NewLogSize - 0x%x\n", NewLogSize));\r
+ DEBUG ((DEBUG_INFO, " LogSize - 0x%x\n", EventLogAreaStruct->EventLogSize));\r
+ DEBUG ((DEBUG_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Check 800-155 event\r
+ // Record to 800-155 event offset only.\r
+ // If the offset is 0, no need to record.\r
+ //\r
+ Record800155Event = Is800155Event (NewEventHdr, NewEventHdrSize, NewEventData, NewEventSize);\r
+ if (Record800155Event) {\r
+ DEBUG ((DEBUG_INFO, "It is 800155Event.\n"));\r
+\r
+ if (EventLogAreaStruct->Next800155EventOffset != 0) {\r
+ CopyMem (\r
+ (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewLogSize,\r
+ (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
+ EventLogAreaStruct->EventLogSize - EventLogAreaStruct->Next800155EventOffset\r
+ );\r
+\r
+ CopyMem (\r
+ (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
+ NewEventHdr,\r
+ NewEventHdrSize\r
+ );\r
+ CopyMem (\r
+ (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewEventHdrSize,\r
+ NewEventData,\r
+ NewEventSize\r
+ );\r
+\r
+ EventLogAreaStruct->Next800155EventOffset += NewLogSize;\r
+ EventLogAreaStruct->LastEvent += NewLogSize;\r
+ EventLogAreaStruct->EventLogSize += NewLogSize;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ EventLogAreaStruct->LastEvent = (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->EventLogSize;\r
+ EventLogAreaStruct->EventLogSize += NewLogSize;\r
+\r
+ CopyMem (EventLogAreaStruct->LastEvent, NewEventHdr, NewEventHdrSize);\r
+ CopyMem (\r
+ EventLogAreaStruct->LastEvent + NewEventHdrSize,\r
+ NewEventData,\r
+ NewEventSize\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ According to UEFI Spec 2.10 Section 38.4.1:\r
+ The following table shows the TPM PCR index mapping and CC event log measurement\r
+ register index interpretation for Intel TDX, where MRTD means Trust Domain Measurement\r
+ Register and RTMR means Runtime Measurement Register\r
+\r
+ // TPM PCR Index | CC Measurement Register Index | TDX-measurement register\r
+ // ------------------------------------------------------------------------\r
+ // 0 | 0 | MRTD\r
+ // 1, 7 | 1 | RTMR[0]\r
+ // 2~6 | 2 | RTMR[1]\r
+ // 8~15 | 3 | RTMR[2]\r
+\r
+ @param[in] PCRIndex Index of the TPM PCR\r
+\r
+ @retval UINT32 Index of the CC Event Log Measurement Register Index\r
+ @retval CC_MR_INDEX_INVALID Invalid MR Index\r
+**/\r
+UINT32\r
+EFIAPI\r
+MapPcrToMrIndex (\r
+ IN UINT32 PCRIndex\r
+ )\r
+{\r
+ UINT32 MrIndex;\r
+\r
+ if (PCRIndex > 15) {\r
+ ASSERT (FALSE);\r
+ return CC_MR_INDEX_INVALID;\r
+ }\r
+\r
+ MrIndex = 0;\r
+ if (PCRIndex == 0) {\r
+ MrIndex = CC_MR_INDEX_0_MRTD;\r
+ } else if ((PCRIndex == 1) || (PCRIndex == 7)) {\r
+ MrIndex = CC_MR_INDEX_1_RTMR0;\r
+ } else if ((PCRIndex >= 2) && (PCRIndex <= 6)) {\r
+ MrIndex = CC_MR_INDEX_2_RTMR1;\r
+ } else if ((PCRIndex >= 8) && (PCRIndex <= 15)) {\r
+ MrIndex = CC_MR_INDEX_3_RTMR2;\r
+ }\r
+\r
+ return MrIndex;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TdMapPcrToMrIndex (\r
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
+ IN UINT32 PCRIndex,\r
+ OUT UINT32 *MrIndex\r
+ )\r
+{\r
+ if (MrIndex == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *MrIndex = MapPcrToMrIndex (PCRIndex);\r
+\r
+ return *MrIndex == CC_MR_INDEX_INVALID ? EFI_INVALID_PARAMETER : 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
+TdxDxeLogEvent (\r
+ IN EFI_CC_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
+ CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct;\r
+\r
+ if (EventLogFormat != EFI_CC_EVENT_LOG_FORMAT_TCG_2) {\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Index = 0;\r
+\r
+ //\r
+ // Record to normal event log\r
+ //\r
+ EventLogAreaStruct = &mTdxDxeData.EventLogAreaStruct[Index];\r
+\r
+ if (EventLogAreaStruct->EventLogTruncated) {\r
+ return EFI_VOLUME_FULL;\r
+ }\r
+\r
+ Status = TcgCommLogEvent (\r
+ EventLogAreaStruct,\r
+ NewEventHdr,\r
+ NewEventHdrSize,\r
+ NewEventData,\r
+ NewEventSize\r
+ );\r
+\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ EventLogAreaStruct->EventLogTruncated = TRUE;\r
+ return EFI_VOLUME_FULL;\r
+ } else if (Status == EFI_SUCCESS) {\r
+ EventLogAreaStruct->EventLogStarted = TRUE;\r
+ }\r
+\r
+ //\r
+ // If GetEventLog is called, record to FinalEventsTable, too.\r
+ //\r
+ if (mTdxDxeData.GetEventLogCalled[Index]) {\r
+ if (mTdxDxeData.FinalEventsTable[Index] == NULL) {\r
+ //\r
+ // no need for FinalEventsTable\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ EventLogAreaStruct = &mTdxDxeData.FinalEventLogAreaStruct[Index];\r
+\r
+ if (EventLogAreaStruct->EventLogTruncated) {\r
+ return EFI_VOLUME_FULL;\r
+ }\r
+\r
+ Status = TcgCommLogEvent (\r
+ EventLogAreaStruct,\r
+ NewEventHdr,\r
+ NewEventHdrSize,\r
+ NewEventData,\r
+ NewEventSize\r
+ );\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ EventLogAreaStruct->EventLogTruncated = TRUE;\r
+ return EFI_VOLUME_FULL;\r
+ } else if (Status == EFI_SUCCESS) {\r
+ EventLogAreaStruct->EventLogStarted = TRUE;\r
+ //\r
+ // Increase the NumberOfEvents in FinalEventsTable\r
+ //\r
+ (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents++;\r
+ DEBUG ((DEBUG_INFO, "FinalEventsTable->NumberOfEvents - 0x%x\n", (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents));\r
+ DEBUG ((DEBUG_INFO, " Size - 0x%x\n", (UINTN)EventLogAreaStruct->EventLogSize));\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get TPML_DIGEST_VALUES compact binary buffer size.\r
+\r
+ @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
+\r
+ @return TPML_DIGEST_VALUES compact binary buffer size.\r
+**/\r
+UINT32\r
+GetDigestListBinSize (\r
+ IN VOID *DigestListBin\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 DigestSize;\r
+ UINT32 TotalSize;\r
+ UINT32 Count;\r
+ TPMI_ALG_HASH HashAlg;\r
+\r
+ Count = ReadUnaligned32 (DigestListBin);\r
+ TotalSize = sizeof (Count);\r
+ DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
+ for (Index = 0; Index < Count; Index++) {\r
+ HashAlg = ReadUnaligned16 (DigestListBin);\r
+ TotalSize += sizeof (HashAlg);\r
+ DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
+\r
+ DigestSize = GetHashSizeFromAlgo (HashAlg);\r
+ TotalSize += DigestSize;\r
+ DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
+ }\r
+\r
+ return TotalSize;\r
+}\r
+\r
+/**\r
+ Copy TPML_DIGEST_VALUES compact binary into a buffer\r
+\r
+ @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
+ @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
+ @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
+ @param[out] HashAlgorithmMaskCopied Pointer to HASH bits corresponding to the digests copied.\r
+\r
+ @return The end of buffer to hold TPML_DIGEST_VALUES compact binary.\r
+**/\r
+VOID *\r
+CopyDigestListBinToBuffer (\r
+ IN OUT VOID *Buffer,\r
+ IN VOID *DigestListBin,\r
+ IN UINT32 HashAlgorithmMask,\r
+ OUT UINT32 *HashAlgorithmMaskCopied\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 DigestSize;\r
+ UINT32 Count;\r
+ TPMI_ALG_HASH HashAlg;\r
+ UINT32 DigestListCount;\r
+ UINT32 *DigestListCountPtr;\r
+\r
+ DigestListCountPtr = (UINT32 *)Buffer;\r
+ DigestListCount = 0;\r
+ *HashAlgorithmMaskCopied = 0;\r
+\r
+ Count = ReadUnaligned32 (DigestListBin);\r
+ Buffer = (UINT8 *)Buffer + sizeof (Count);\r
+ DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
+ for (Index = 0; Index < Count; Index++) {\r
+ HashAlg = ReadUnaligned16 (DigestListBin);\r
+ DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
+ DigestSize = GetHashSizeFromAlgo (HashAlg);\r
+\r
+ if ((HashAlg & HashAlgorithmMask) != 0) {\r
+ CopyMem (Buffer, &HashAlg, sizeof (HashAlg));\r
+ Buffer = (UINT8 *)Buffer + sizeof (HashAlg);\r
+ CopyMem (Buffer, DigestListBin, DigestSize);\r
+ Buffer = (UINT8 *)Buffer + DigestSize;\r
+ DigestListCount++;\r
+ (*HashAlgorithmMaskCopied) |= GetHashMaskFromAlgo (HashAlg);\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "WARNING: CopyDigestListBinToBuffer Event log has HashAlg unsupported by PCR bank (0x%x)\n", HashAlg));\r
+ }\r
+\r
+ DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
+ }\r
+\r
+ WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
+\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Add a new entry to the Event Log. The call chain is like below:\r
+ TdxDxeLogHashEvent -> TdxDxeLogEvent -> TcgCommonLogEvent\r
+\r
+ Before this function is called, the event information (including the digest)\r
+ is ready.\r
+\r
+ @param[in] DigestList A list of digest.\r
+ @param[in,out] NewEventHdr Pointer to a TD_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
+TdxDxeLogHashEvent (\r
+ IN TPML_DIGEST_VALUES *DigestList,\r
+ IN OUT CC_EVENT_HDR *NewEventHdr,\r
+ IN UINT8 *NewEventData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS RetStatus;\r
+ CC_EVENT CcEvent;\r
+ UINT8 *DigestBuffer;\r
+ UINT32 *EventSizePtr;\r
+ EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
+\r
+ RetStatus = EFI_SUCCESS;\r
+ LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
+\r
+ ZeroMem (&CcEvent, sizeof (CcEvent));\r
+ CcEvent.MrIndex = NewEventHdr->MrIndex;\r
+ CcEvent.EventType = NewEventHdr->EventType;\r
+ DigestBuffer = (UINT8 *)&CcEvent.Digests;\r
+ EventSizePtr = CopyDigestListToBuffer (DigestBuffer, DigestList, HASH_ALG_SHA384);\r
+ CopyMem (EventSizePtr, &NewEventHdr->EventSize, sizeof (NewEventHdr->EventSize));\r
+\r
+ //\r
+ // Enter critical region\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+ Status = TdxDxeLogEvent (\r
+ LogFormat,\r
+ &CcEvent,\r
+ sizeof (CcEvent.MrIndex) + sizeof (CcEvent.EventType) + GetDigestListBinSize (DigestBuffer) + sizeof (CcEvent.EventSize),\r
+ NewEventData,\r
+ NewEventHdr->EventSize\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ RetStatus = Status;\r
+ }\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return RetStatus;\r
+}\r
+\r
+/**\r
+ Do a hash operation on a data buffer, extend a specific RTMR 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 TD_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
+TdxDxeHashLogExtendEvent (\r
+ IN UINT64 Flags,\r
+ IN UINT8 *HashData,\r
+ IN UINT64 HashDataLen,\r
+ IN OUT CC_EVENT_HDR *NewEventHdr,\r
+ IN UINT8 *NewEventData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TPML_DIGEST_VALUES DigestList;\r
+ CC_EVENT_HDR NoActionEvent;\r
+\r
+ if (NewEventHdr->EventType == EV_NO_ACTION) {\r
+ //\r
+ // Do not do RTMR extend for EV_NO_ACTION\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize);\r
+ if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
+ Status = TdxDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData);\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // According to UEFI Spec 2.10 Section 38.4.1 the mapping between MrIndex and Intel\r
+ // TDX Measurement Register is:\r
+ // MrIndex 0 <--> MRTD\r
+ // MrIndex 1-3 <--> RTMR[0-2]\r
+ // Only the RMTR registers can be extended in TDVF by HashAndExtend. So MrIndex will\r
+ // decreased by 1 before it is sent to HashAndExtend.\r
+ //\r
+ Status = HashAndExtend (\r
+ NewEventHdr->MrIndex - 1,\r
+ HashData,\r
+ (UINTN)HashDataLen,\r
+ &DigestList\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
+ Status = TdxDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The EFI_CC_MEASUREMENT_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
+TdHashLogExtendEvent (\r
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
+ IN UINT64 Flags,\r
+ IN EFI_PHYSICAL_ADDRESS DataToHash,\r
+ IN UINT64 DataToHashLen,\r
+ IN EFI_CC_EVENT *CcEvent\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CC_EVENT_HDR NewEventHdr;\r
+ TPML_DIGEST_VALUES DigestList;\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent ...\n"));\r
+\r
+ if ((This == NULL) || (CcEvent == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Do not check hash data size for EV_NO_ACTION event.\r
+ //\r
+ if ((CcEvent->Header.EventType != EV_NO_ACTION) && (DataToHash == 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (CcEvent->Size < CcEvent->Header.HeaderSize + sizeof (UINT32)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (CcEvent->Header.MrIndex == CC_MR_INDEX_0_MRTD) {\r
+ DEBUG ((DEBUG_ERROR, "%a: MRTD cannot be extended in TDVF.\n", __FUNCTION__));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (CcEvent->Header.MrIndex >= CC_MR_INDEX_INVALID) {\r
+ DEBUG ((DEBUG_ERROR, "%a: MrIndex is invalid. (%d)\n", __FUNCTION__, CcEvent->Header.MrIndex));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ NewEventHdr.MrIndex = CcEvent->Header.MrIndex;\r
+ NewEventHdr.EventType = CcEvent->Header.EventType;\r
+ NewEventHdr.EventSize = CcEvent->Size - sizeof (UINT32) - CcEvent->Header.HeaderSize;\r
+ if ((Flags & EFI_CC_FLAG_PE_COFF_IMAGE) != 0) {\r
+ //\r
+ // According to UEFI Spec 2.10 Section 38.4.1 the mapping between MrIndex and Intel\r
+ // TDX Measurement Register is:\r
+ // MrIndex 0 <--> MRTD\r
+ // MrIndex 1-3 <--> RTMR[0-2]\r
+ // Only the RMTR registers can be extended in TDVF by HashAndExtend. So MrIndex will\r
+ // decreased by 1 before it is sent to MeasurePeImageAndExtend.\r
+ //\r
+ Status = MeasurePeImageAndExtend (\r
+ NewEventHdr.MrIndex - 1,\r
+ DataToHash,\r
+ (UINTN)DataToHashLen,\r
+ &DigestList\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
+ Status = TdxDxeLogHashEvent (&DigestList, &NewEventHdr, CcEvent->Event);\r
+ }\r
+ }\r
+ } else {\r
+ Status = TdxDxeHashLogExtendEvent (\r
+ Flags,\r
+ (UINT8 *)(UINTN)DataToHash,\r
+ DataToHashLen,\r
+ &NewEventHdr,\r
+ CcEvent->Event\r
+ );\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent - %r\n", Status));\r
+ return Status;\r
+}\r
+\r
+EFI_CC_MEASUREMENT_PROTOCOL mTdProtocol = {\r
+ TdGetCapability,\r
+ TdGetEventLog,\r
+ TdHashLogExtendEvent,\r
+ TdMapPcrToMrIndex,\r
+};\r
+\r
+#define TD_HASH_COUNT 1\r
+#define TEMP_BUF_LEN (sizeof(TCG_EfiSpecIDEventStruct) + sizeof(UINT32) \\r
+ + (TD_HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8))\r
+\r
+/**\r
+ Initialize the TD 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
+SetupCcEventLog (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Lasa;\r
+ UINTN Index;\r
+ TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
+ UINT8 TempBuf[TEMP_BUF_LEN];\r
+ TCG_PCR_EVENT_HDR SpecIdEvent;\r
+ TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
+ TCG_EfiSpecIdEventAlgorithmSize *TempDigestSize;\r
+ UINT8 *VendorInfoSize;\r
+ UINT32 NumberOfAlgorithms;\r
+ EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
+ EFI_PEI_HOB_POINTERS GuidHob;\r
+ CC_EVENT_HDR NoActionEvent;\r
+\r
+ Status = EFI_SUCCESS;\r
+ DEBUG ((DEBUG_INFO, "SetupCcEventLog\n"));\r
+\r
+ Index = 0;\r
+ LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
+\r
+ //\r
+ // 1. Create Log Area\r
+ //\r
+ mTdxDxeData.EventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
+\r
+ // allocate pages for TD Event log\r
+ Status = gBS->AllocatePages (\r
+ AllocateAnyPages,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
+ &Lasa\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ mTdxDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
+ mTdxDxeData.EventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
+ mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = 0;\r
+\r
+ //\r
+ // Report TD event log address and length, so that they can be reported in\r
+ // TD ACPI table. Ignore the return status, because those fields are optional.\r
+ //\r
+ PcdSet32S (PcdCcEventlogAcpiTableLaml, (UINT32)mTdxDxeData.EventLogAreaStruct[Index].Laml);\r
+ PcdSet64S (PcdCcEventlogAcpiTableLasa, mTdxDxeData.EventLogAreaStruct[Index].Lasa);\r
+\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, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
+\r
+ //\r
+ // Create first entry for Log Header Entry Data\r
+ //\r
+\r
+ //\r
+ // TcgEfiSpecIdEventStruct\r
+ //\r
+ TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)TempBuf;\r
+ CopyMem (TcgEfiSpecIdEventStruct->signature, TCG_EfiSpecIDEventStruct_SIGNATURE_03, sizeof (TcgEfiSpecIdEventStruct->signature));\r
+\r
+ TcgEfiSpecIdEventStruct->platformClass = PcdGet8 (PcdTpmPlatformClass);\r
+\r
+ TcgEfiSpecIdEventStruct->specVersionMajor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2;\r
+ TcgEfiSpecIdEventStruct->specVersionMinor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2;\r
+ TcgEfiSpecIdEventStruct->specErrata = TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2;\r
+ TcgEfiSpecIdEventStruct->uintnSize = sizeof (UINTN)/sizeof (UINT32);\r
+ NumberOfAlgorithms = 0;\r
+ DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct\r
+ + sizeof (*TcgEfiSpecIdEventStruct)\r
+ + sizeof (NumberOfAlgorithms));\r
+\r
+ TempDigestSize = DigestSize;\r
+ TempDigestSize += NumberOfAlgorithms;\r
+ TempDigestSize->algorithmId = TPM_ALG_SHA384;\r
+ TempDigestSize->digestSize = SHA384_DIGEST_SIZE;\r
+ NumberOfAlgorithms++;\r
+\r
+ CopyMem (TcgEfiSpecIdEventStruct + 1, &NumberOfAlgorithms, sizeof (NumberOfAlgorithms));\r
+ TempDigestSize = DigestSize;\r
+ TempDigestSize += NumberOfAlgorithms;\r
+ VendorInfoSize = (UINT8 *)TempDigestSize;\r
+ *VendorInfoSize = 0;\r
+\r
+ SpecIdEvent.PCRIndex = 1; // PCRIndex 0 maps to MrIndex 1\r
+ SpecIdEvent.EventType = EV_NO_ACTION;\r
+ ZeroMem (&SpecIdEvent.Digest, sizeof (SpecIdEvent.Digest));\r
+ SpecIdEvent.EventSize = (UINT32)GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct);\r
+\r
+ //\r
+ // TD Event log re-use the spec of TCG2 Event log.\r
+ // Log TcgEfiSpecIdEventStruct as the first Event. Event format is TCG_PCR_EVENT.\r
+ // TCG EFI Protocol Spec. Section 5.3 Event Log Header\r
+ // TCG PC Client PFP spec. Section 9.2 Measurement Event Entries and Log\r
+ //\r
+ Status = TdxDxeLogEvent (\r
+ LogFormat,\r
+ &SpecIdEvent,\r
+ sizeof (SpecIdEvent),\r
+ (UINT8 *)TcgEfiSpecIdEventStruct,\r
+ SpecIdEvent.EventSize\r
+ );\r
+ //\r
+ // record the offset at the end of 800-155 event.\r
+ // the future 800-155 event can be inserted here.\r
+ //\r
+ mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = mTdxDxeData.EventLogAreaStruct[Index].EventLogSize;\r
+\r
+ //\r
+ // Tcg800155PlatformIdEvent. Event format is TCG_PCR_EVENT2\r
+ //\r
+ GuidHob.Guid = GetFirstGuidHob (&gTcg800155PlatformIdEventHobGuid);\r
+ while (GuidHob.Guid != NULL) {\r
+ InitNoActionEvent (&NoActionEvent, GET_GUID_HOB_DATA_SIZE (GuidHob.Guid));\r
+\r
+ Status = TdxDxeLogEvent (\r
+ LogFormat,\r
+ &NoActionEvent,\r
+ sizeof (NoActionEvent.MrIndex) + sizeof (NoActionEvent.EventType) + GetDigestListBinSize (&NoActionEvent.Digests) + sizeof (NoActionEvent.EventSize),\r
+ GET_GUID_HOB_DATA (GuidHob.Guid),\r
+ GET_GUID_HOB_DATA_SIZE (GuidHob.Guid)\r
+ );\r
+\r
+ GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
+ GuidHob.Guid = GetNextGuidHob (&gTcg800155PlatformIdEventHobGuid, GuidHob.Guid);\r
+ }\r
+\r
+ //\r
+ // 2. Create Final Log Area\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateAnyPages,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcg2FinalLogAreaLen)),\r
+ &Lasa\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcg2FinalLogAreaLen), 0xFF);\r
+\r
+ //\r
+ // Initialize\r
+ //\r
+ mTdxDxeData.FinalEventsTable[Index] = (VOID *)(UINTN)Lasa;\r
+ (mTdxDxeData.FinalEventsTable[Index])->Version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION;\r
+ (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents = 0;\r
+\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa = Lasa + sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcg2FinalLogAreaLen) - sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0;\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].LastEvent = (VOID *)(UINTN)mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa;\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE;\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE;\r
+ mTdxDxeData.FinalEventLogAreaStruct[Index].Next800155EventOffset = 0;\r
+\r
+ //\r
+ // Install to configuration table for EFI_CC_EVENT_LOG_FORMAT_TCG_2\r
+ //\r
+ Status = gBS->InstallConfigurationTable (&gEfiCcFinalEventsTableGuid, (VOID *)mTdxDxeData.FinalEventsTable[Index]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Measure and log an action string, and extend the measurement result into RTMR.\r
+\r
+ @param[in] MrIndex MrIndex to extend\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
+TdMeasureAction (\r
+ IN UINT32 MrIndex,\r
+ IN CHAR8 *String\r
+ )\r
+{\r
+ CC_EVENT_HDR CcEvent;\r
+\r
+ CcEvent.MrIndex = MrIndex;\r
+ CcEvent.EventType = EV_EFI_ACTION;\r
+ CcEvent.EventSize = (UINT32)AsciiStrLen (String);\r
+ return TdxDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)String,\r
+ CcEvent.EventSize,\r
+ &CcEvent,\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
+ CC_EVENT_HDR CcEvent;\r
+ EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
+ UINTN ProcessorNum;\r
+ EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
+\r
+ ProcessorLocBuf = NULL;\r
+ Status = EFI_SUCCESS;\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
+ CcEvent.MrIndex = MapPcrToMrIndex (1);\r
+ CcEvent.EventType = EV_TABLE_OF_DEVICES;\r
+ CcEvent.EventSize = sizeof (HandoffTables);\r
+\r
+ HandoffTables.NumberOfTables = 1;\r
+ HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
+ HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
+\r
+ Status = TdxDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)(UINTN)ProcessorLocBuf,\r
+ sizeof (EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
+ &CcEvent,\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 UINT32 MrIndex\r
+ )\r
+{\r
+ CC_EVENT_HDR CcEvent;\r
+ UINT32 EventData;\r
+\r
+ DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent to Rtmr - %d\n", MrIndex));\r
+\r
+ EventData = 0;\r
+ CcEvent.MrIndex = MrIndex;\r
+ CcEvent.EventType = EV_SEPARATOR;\r
+ CcEvent.EventSize = (UINT32)sizeof (EventData);\r
+\r
+ return TdxDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)&EventData,\r
+ sizeof (EventData),\r
+ &CcEvent,\r
+ (UINT8 *)&EventData\r
+ );\r
+}\r
+\r
+/**\r
+ Measure and log an EFI variable, and extend the measurement result into a specific RTMR.\r
+\r
+ @param[in] MrIndex RTMR 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 UINT32 MrIndex,\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
+ CC_EVENT_HDR CcEvent;\r
+ UINTN VarNameLength;\r
+ UEFI_VARIABLE_DATA *VarLog;\r
+\r
+ DEBUG ((DEBUG_INFO, "TdTcg2Dxe: MeasureVariable (Rtmr - %x, EventType - %x, ", (UINTN)MrIndex, (UINTN)EventType));\r
+ DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
+\r
+ VarNameLength = StrLen (VarName);\r
+ CcEvent.MrIndex = MrIndex;\r
+ CcEvent.EventType = EventType;\r
+\r
+ CcEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
+ - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
+\r
+ VarLog = (UEFI_VARIABLE_DATA *)AllocatePool (CcEvent.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) && (VarData != NULL)) {\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 (UEFI_VARIABLE_DATA)\r
+ //\r
+ Status = TdxDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)VarLog,\r
+ CcEvent.EventSize,\r
+ &CcEvent,\r
+ (UINT8 *)VarLog\r
+ );\r
+ } else {\r
+ ASSERT (VarData != NULL);\r
+ Status = TdxDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)VarData,\r
+ VarSize,\r
+ &CcEvent,\r
+ (UINT8 *)VarLog\r
+ );\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 RTMR.\r
+\r
+ @param[in] MrIndex RTMR 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 UINT32 MrIndex,\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
+ //\r
+ // if status error, VarData is freed and set NULL by GetVariable2\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+\r
+ Status = MeasureVariable (\r
+ MrIndex,\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[1].\r
+according to TCG PC Client PFP spec 0021 Section 2.4.4.2\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
+ //\r
+ // Boot variables are measured into (PCR[5]) RTMR[1],\r
+ // details in section 8.1 of TDVF design guide.\r
+ //\r
+ return ReadAndMeasureVariable (\r
+ MapPcrToMrIndex (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
+ MapPcrToMrIndex (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) || (BootOrder == NULL)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
+ //\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
+ //\r
+ // Measure DBT if present and not empty\r
+ //\r
+ Status = GetVariable2 (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, &Data, &DataSize);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = MeasureVariable (\r
+ MapPcrToMrIndex (7),\r
+ EV_EFI_VARIABLE_DRIVER_CONFIG,\r
+ EFI_IMAGE_SECURITY_DATABASE2,\r
+ &gEfiImageSecurityDatabaseGuid,\r
+ Data,\r
+ DataSize\r
+ );\r
+ FreePool (Data);\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2));\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
+ CC_EVENT_HDR CcEvent;\r
+\r
+ CcEvent.MrIndex = MapPcrToMrIndex (7);\r
+ CcEvent.EventType = EV_EFI_ACTION;\r
+ CcEvent.EventSize = sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
+ return TdxDxeHashLogExtendEvent (\r
+ 0,\r
+ (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
+ sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
+ &CcEvent,\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 ((DEBUG_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
+ }\r
+\r
+ Status = MeasureAllSecureVariables ();\r
+ DEBUG ((DEBUG_INFO, "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 (MapPcrToMrIndex (7));\r
+ DEBUG ((DEBUG_INFO, "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
+\r
+ PERF_START_EX (mImageHandle, "EventRec", "TdTcg2Dxe", 0, PERF_ID_CC_TCG2_DXE);\r
+ if (mBootAttempts == 0) {\r
+ //\r
+ // Measure handoff tables.\r
+ //\r
+ Status = MeasureHandoffTables ();\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_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 ((DEBUG_ERROR, "Boot Variables not Measured. Error!\n"));\r
+ }\r
+\r
+ //\r
+ // 1. This is the first boot attempt.\r
+ //\r
+ Status = TdMeasureAction (\r
+ MapPcrToMrIndex (4),\r
+ EFI_CALLING_EFI_APPLICATION\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", 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 RTMR[0]) is already done.\r
+ //\r
+ Status = MeasureSeparatorEvent (1);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Separator Event not Measured. Error!\n"));\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 = TdMeasureAction (\r
+ MapPcrToMrIndex (4),\r
+ EFI_RETURNING_FROM_EFI_APPLICATION\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION));\r
+ }\r
+\r
+ //\r
+ // 7. Next boot attempt, measure "Calling EFI Application from Boot Option" again\r
+ // TCG PC Client PFP spec Section 2.4.4.5 Step 4\r
+ //\r
+ Status = TdMeasureAction (\r
+ MapPcrToMrIndex (4),\r
+ EFI_CALLING_EFI_APPLICATION\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
+ }\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "TdTcg2Dxe Measure Data when ReadyToBoot\n"));\r
+ //\r
+ // Increase boot attempt counter.\r
+ //\r
+ mBootAttempts++;\r
+ PERF_END_EX (mImageHandle, "EventRec", "Tcg2Dxe", 0, PERF_ID_CC_TCG2_DXE + 1);\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 = TdMeasureAction (\r
+ MapPcrToMrIndex (5),\r
+ EFI_EXIT_BOOT_SERVICES_INVOCATION\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
+ }\r
+\r
+ //\r
+ // Measure success of ExitBootServices\r
+ //\r
+ Status = TdMeasureAction (\r
+ MapPcrToMrIndex (5),\r
+ EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
+ }\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 = TdMeasureAction (\r
+ MapPcrToMrIndex (5),\r
+ EFI_EXIT_BOOT_SERVICES_FAILED\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+SyncCcEvent (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PEI_HOB_POINTERS GuidHob;\r
+ VOID *CcEvent;\r
+ VOID *DigestListBin;\r
+ UINT32 DigestListBinSize;\r
+ UINT8 *Event;\r
+ UINT32 EventSize;\r
+ EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
+\r
+ DEBUG ((DEBUG_INFO, "Sync Cc event from SEC\n"));\r
+\r
+ Status = EFI_SUCCESS;\r
+ LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
+ GuidHob.Guid = GetFirstGuidHob (&gCcEventEntryHobGuid);\r
+\r
+ while (!EFI_ERROR (Status) && GuidHob.Guid != NULL) {\r
+ CcEvent = AllocateCopyPool (GET_GUID_HOB_DATA_SIZE (GuidHob.Guid), GET_GUID_HOB_DATA (GuidHob.Guid));\r
+ if (CcEvent == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
+ GuidHob.Guid = GetNextGuidHob (&gCcEventEntryHobGuid, GuidHob.Guid);\r
+\r
+ DigestListBin = (UINT8 *)CcEvent + sizeof (UINT32) + sizeof (TCG_EVENTTYPE);\r
+ DigestListBinSize = GetDigestListBinSize (DigestListBin);\r
+\r
+ //\r
+ // Event size.\r
+ //\r
+ EventSize = *(UINT32 *)((UINT8 *)DigestListBin + DigestListBinSize);\r
+ Event = (UINT8 *)DigestListBin + DigestListBinSize + sizeof (UINT32);\r
+\r
+ //\r
+ // Log the event\r
+ //\r
+ Status = TdxDxeLogEvent (\r
+ LogFormat,\r
+ CcEvent,\r
+ sizeof (UINT32) + sizeof (TCG_EVENTTYPE) + DigestListBinSize + sizeof (UINT32),\r
+ Event,\r
+ EventSize\r
+ );\r
+\r
+ DumpCcEvent ((CC_EVENT *)CcEvent);\r
+ FreePool (CcEvent);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Install TDVF ACPI Table when ACPI Table Protocol is available.\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
+ UINT64 OemTableId;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "TD: AcpiTableProtocol is not installed. %r\n", Status));\r
+ return;\r
+ }\r
+\r
+ mTdxEventlogAcpiTemplate.Laml = (UINT64)PcdGet32 (PcdCcEventlogAcpiTableLaml);\r
+ mTdxEventlogAcpiTemplate.Lasa = PcdGet64 (PcdCcEventlogAcpiTableLasa);\r
+ CopyMem (mTdxEventlogAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTdxEventlogAcpiTemplate.Header.OemId));\r
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+ CopyMem (&mTdxEventlogAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+ mTdxEventlogAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+ mTdxEventlogAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+ mTdxEventlogAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+\r
+ //\r
+ // Construct ACPI Table\r
+ Status = AcpiTable->InstallAcpiTable (\r
+ AcpiTable,\r
+ &mTdxEventlogAcpiTemplate,\r
+ mTdxEventlogAcpiTemplate.Header.Length,\r
+ &TableKey\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG ((DEBUG_INFO, "TDVF Eventlog ACPI Table is installed.\n"));\r
+}\r
+\r
+/**\r
+ The function install TdTcg2 protocol.\r
+\r
+ @retval EFI_SUCCESS TdTcg2 protocol is installed.\r
+ @retval other Some error occurs.\r
+**/\r
+EFI_STATUS\r
+InstallCcMeasurementProtocol (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+\r
+ Handle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Handle,\r
+ &gEfiCcMeasurementProtocolGuid,\r
+ &mTdProtocol,\r
+ NULL\r
+ );\r
+ DEBUG ((DEBUG_INFO, "CcProtocol: Install %r\n", Status));\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The driver's entry point. It publishes EFI Tcg2 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
+\r
+ if (!TdIsEnabled ()) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ mImageHandle = ImageHandle;\r
+\r
+ //\r
+ // Fill information\r
+ //\r
+ // ASSERT (TD_EVENT_LOG_AREA_COUNT_MAX == sizeof(mTEventInfo)/sizeof(mTcg2EventInfo[0]));\r
+\r
+ mTdxDxeData.BsCap.Size = sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY);\r
+ mTdxDxeData.BsCap.ProtocolVersion.Major = 1;\r
+ mTdxDxeData.BsCap.ProtocolVersion.Minor = 0;\r
+ mTdxDxeData.BsCap.StructureVersion.Major = 1;\r
+ mTdxDxeData.BsCap.StructureVersion.Minor = 0;\r
+\r
+ //\r
+ // Get supported PCR and current Active PCRs\r
+ // For TD gueset HA384 is supported.\r
+ //\r
+ mTdxDxeData.BsCap.HashAlgorithmBitmap = HASH_ALG_SHA384;\r
+\r
+ // TD guest only supports EFI_TCG2_EVENT_LOG_FORMAT_TCG_2\r
+ mTdxDxeData.BsCap.SupportedEventLogs = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
+\r
+ //\r
+ // Setup the log area and copy event log from hob list to it\r
+ //\r
+ Status = SetupCcEventLog ();\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SyncCcEvent ();\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\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
+ // Install CcMeasurementProtocol\r
+ //\r
+ Status = InstallCcMeasurementProtocol ();\r
+ DEBUG ((DEBUG_INFO, "InstallCcMeasurementProtocol - %r\n", Status));\r
+\r
+ if (Status == EFI_SUCCESS) {\r
+ //\r
+ // Create event callback to install CC EventLog ACPI Table\r
+ EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+## @file\r
+#\r
+# Produces EFI_CC_MEASUREMENT_PROTOCOL and measure boot environment\r
+#\r
+#\r
+# Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = TdTcg2Dxe\r
+ FILE_GUID = F062221E-C607-44C2-B0B4-C3886331D351\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = DriverEntry\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = X64\r
+#\r
+\r
+[Sources]\r
+ TdTcg2Dxe.c\r
+ MeasureBootPeCoff.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+ CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ BaseLib\r
+ UefiBootServicesTableLib\r
+ HobLib\r
+ UefiDriverEntryPoint\r
+ UefiRuntimeServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PrintLib\r
+ UefiLib\r
+ HashLib\r
+ PerformanceLib\r
+ ReportStatusCodeLib\r
+ PeCoffLib\r
+ TpmMeasurementLib\r
+ TdxLib\r
+\r
+[Guids]\r
+ ## SOMETIMES_CONSUMES ## Variable:L"SecureBoot"\r
+ ## SOMETIMES_CONSUMES ## Variable:L"PK"\r
+ ## SOMETIMES_CONSUMES ## Variable:L"KEK"\r
+ ## SOMETIMES_CONSUMES ## Variable:L"BootXXXX"\r
+ gEfiGlobalVariableGuid\r
+\r
+ ## SOMETIMES_CONSUMES ## Variable:L"db"\r
+ ## SOMETIMES_CONSUMES ## Variable:L"dbx"\r
+ gEfiImageSecurityDatabaseGuid\r
+\r
+ # gTcgEventEntryHobGuid ## SOMETIMES_CONSUMES ## HOB\r
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event\r
+ gEventExitBootServicesFailedGuid ## SOMETIMES_CONSUMES ## Event\r
+\r
+ gCcEventEntryHobGuid ## SOMETIMES_CONSUMES ## HOB\r
+ gTcg800155PlatformIdEventHobGuid ## SOMETIMES_CONSUMES ## HOB\r
+ gEfiCcFinalEventsTableGuid ## PRODUCES\r
+\r
+[Protocols]\r
+ gEfiCcMeasurementProtocolGuid ## PRODUCES\r
+ gEfiMpServiceProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiVariableWriteArchProtocolGuid ## NOTIFY\r
+ gEfiResetNotificationProtocolGuid ## CONSUMES\r
+ gEfiAcpiTableProtocolGuid ## NOTIFY\r
+\r
+[Pcd]\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass ## SOMETIMES_CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdFirmwareDebuggerInitialized ## SOMETIMES_CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeSubClassTpmDevice ## SOMETIMES_CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcg2NumberOfPCRBanks ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcgLogAreaMinLen ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcg2FinalLogAreaLen ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLaml ## PRODUCES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdCcEventlogAcpiTableLasa ## PRODUCES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES\r
+\r
+[Depex]\r
+ # According to PcdTpm2AcpiTableRev definition in SecurityPkg.dec\r
+ # This PCD should be configured at DynamicHii or DynamicHiiEx.\r
+ # So, this PCD read operation depends on GetVariable service.\r
+ # Add VariableArch protocol dependency to make sure PCD read works.\r
+ gEfiVariableArchProtocolGuid AND gEfiAcpiTableProtocolGuid\r