2 Initialize TPM2 device and measure FVs before handing off control to DXE.
4 Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <IndustryStandard/UefiTcgPlatform.h>
13 #include <Ppi/FirmwareVolumeInfo.h>
14 #include <Ppi/FirmwareVolumeInfo2.h>
15 #include <Ppi/TpmInitialized.h>
16 #include <Ppi/FirmwareVolume.h>
17 #include <Ppi/EndOfPeiPhase.h>
18 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
19 #include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
22 #include <Guid/TcgEventHob.h>
23 #include <Guid/MeasuredFvHob.h>
24 #include <Guid/TpmInstance.h>
26 #include <Library/DebugLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/PeiServicesLib.h>
29 #include <Library/PeimEntryPoint.h>
30 #include <Library/Tpm2CommandLib.h>
31 #include <Library/Tpm2DeviceLib.h>
32 #include <Library/HashLib.h>
33 #include <Library/HobLib.h>
34 #include <Library/PcdLib.h>
35 #include <Library/PeiServicesTablePointerLib.h>
36 #include <Protocol/Tcg2Protocol.h>
37 #include <Library/PerformanceLib.h>
38 #include <Library/MemoryAllocationLib.h>
39 #include <Library/ReportStatusCodeLib.h>
40 #include <Library/ResetSystemLib.h>
41 #include <Library/PrintLib.h>
43 #define PERF_ID_TCG2_PEI 0x3080
47 EFI_TCG2_EVENT_LOG_FORMAT LogFormat
;
48 } TCG2_EVENT_INFO_STRUCT
;
50 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo
[] = {
51 {&gTcgEventEntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
},
52 {&gTcgEvent2EntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
},
55 BOOLEAN mImageInMemory
= FALSE
;
56 EFI_PEI_FILE_HANDLE mFileHandle
;
58 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
59 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
60 &gPeiTpmInitializedPpiGuid
,
64 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
65 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
66 &gPeiTpmInitializationDonePpiGuid
,
71 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
72 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
73 added into the Event Log.
75 @param[in] This Indicates the calling context
76 @param[in] Flags Bitmap providing additional information.
77 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
78 start of the data buffer to be hashed, extended, and logged.
79 If BIT0 of Flags is 1, it is physical address of the
80 start of the pre-hash data buffter to be extended, and logged.
81 The pre-hash data format is TPML_DIGEST_VALUES.
82 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
83 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
84 @param[in] NewEventData Pointer to the new event data.
86 @retval EFI_SUCCESS Operation completed successfully.
87 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
88 @retval EFI_DEVICE_ERROR The command was unsuccessful.
94 IN EDKII_TCG_PPI
*This
,
98 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
99 IN UINT8
*NewEventData
102 EDKII_TCG_PPI mEdkiiTcgPpi
= {
106 EFI_PEI_PPI_DESCRIPTOR mTcgPpiList
= {
107 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
113 // Number of firmware blobs to grow by each time we run out of room
115 #define FIRMWARE_BLOB_GROWTH_STEP 4
117 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
118 UINT32 mMeasuredMaxBaseFvIndex
= 0;
119 UINT32 mMeasuredBaseFvIndex
= 0;
121 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
122 UINT32 mMeasuredMaxChildFvIndex
= 0;
123 UINT32 mMeasuredChildFvIndex
= 0;
127 #define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"
129 UINT8 BlobDescriptionSize
;
130 UINT8 BlobDescription
[sizeof(FV_HANDOFF_TABLE_DESC
)];
131 EFI_PHYSICAL_ADDRESS BlobBase
;
133 } FV_HANDOFF_TABLE_POINTERS2
;
138 Measure and record the Firmware Volume Information once FvInfoPPI install.
140 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
141 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
142 @param[in] Ppi Address of the PPI that was installed.
144 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
145 @return Others Fail to measure FV.
150 FirmwareVolumeInfoPpiNotifyCallback (
151 IN EFI_PEI_SERVICES
**PeiServices
,
152 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
157 Record all measured Firmware Volume Information into a Guid Hob
159 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
160 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
161 @param[in] Ppi Address of the PPI that was installed.
163 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
164 @return Others Fail to measure FV.
169 EndofPeiSignalNotifyCallBack (
170 IN EFI_PEI_SERVICES
**PeiServices
,
171 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
175 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
177 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
178 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
179 FirmwareVolumeInfoPpiNotifyCallback
182 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
183 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
184 FirmwareVolumeInfoPpiNotifyCallback
187 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
188 &gEfiEndOfPeiSignalPpiGuid
,
189 EndofPeiSignalNotifyCallBack
195 Record all measured Firmware Volume Information into a Guid Hob
196 Guid Hob payload layout is
198 UINT32 *************************** FIRMWARE_BLOB number
199 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
201 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
202 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
203 @param[in] Ppi Address of the PPI that was installed.
205 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
206 @return Others Fail to measure FV.
211 EndofPeiSignalNotifyCallBack (
212 IN EFI_PEI_SERVICES
**PeiServices
,
213 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
217 MEASURED_HOB_DATA
*MeasuredHobData
;
219 MeasuredHobData
= NULL
;
221 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid
);
224 // Create a Guid hob to save all measured Fv
226 MeasuredHobData
= BuildGuidHob(
228 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
231 if (MeasuredHobData
!= NULL
){
233 // Save measured FV info enty number
235 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
238 // Save measured base Fv info
240 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
243 // Save measured child Fv info
245 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
248 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid
);
254 Make sure that the current PCR allocations, the TPM supported PCRs,
255 and the PcdTpm2HashMask are all in agreement.
258 SyncPcrAllocationsAndPcrMask (
263 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
264 UINT32 TpmActivePcrBanks
;
265 UINT32 NewTpmActivePcrBanks
;
267 UINT32 NewTpm2PcrMask
;
269 DEBUG ((EFI_D_ERROR
, "SyncPcrAllocationsAndPcrMask!\n"));
272 // Determine the current TPM support and the Platform PCR mask.
274 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &TpmActivePcrBanks
);
275 ASSERT_EFI_ERROR (Status
);
277 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
278 if (Tpm2PcrMask
== 0) {
280 // if PcdTPm2HashMask is zero, use ActivePcr setting
282 PcdSet32S (PcdTpm2HashMask
, TpmActivePcrBanks
);
283 Tpm2PcrMask
= TpmActivePcrBanks
;
287 // Find the intersection of Pcd support and TPM support.
288 // If banks are missing from the TPM support that are in the PCD, update the PCD.
289 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
293 // If there are active PCR banks that are not supported by the Platform mask,
294 // update the TPM allocations and reboot the machine.
296 if ((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) {
297 NewTpmActivePcrBanks
= TpmActivePcrBanks
& Tpm2PcrMask
;
299 DEBUG ((EFI_D_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
300 if (NewTpmActivePcrBanks
== 0) {
301 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
304 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
305 if (EFI_ERROR (Status
)) {
307 // We can't do much here, but we hope that this doesn't happen.
309 DEBUG ((EFI_D_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
310 ASSERT_EFI_ERROR (Status
);
313 // Need reset system, since we just called Tpm2PcrAllocateBanks().
320 // If there are any PCRs that claim support in the Platform mask that are
321 // not supported by the TPM, update the mask.
323 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
324 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
326 DEBUG ((EFI_D_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
327 if (NewTpm2PcrMask
== 0) {
328 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
332 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
333 ASSERT_EFI_ERROR (Status
);
338 Add a new entry to the Event Log.
340 @param[in] DigestList A list of digest.
341 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
342 @param[in] NewEventData Pointer to the new event data.
344 @retval EFI_SUCCESS The new event log entry was added.
345 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
349 IN TPML_DIGEST_VALUES
*DigestList
,
350 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
351 IN UINT8
*NewEventData
357 EFI_STATUS RetStatus
;
358 UINT32 SupportedEventLogs
;
359 TCG_PCR_EVENT2
*TcgPcrEvent2
;
362 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
364 RetStatus
= EFI_SUCCESS
;
365 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
366 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
367 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
368 switch (mTcg2EventInfo
[Index
].LogFormat
) {
369 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
370 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
371 if (!EFI_ERROR (Status
)) {
372 HobData
= BuildGuidHob (
373 &gTcgEventEntryHobGuid
,
374 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
376 if (HobData
== NULL
) {
377 RetStatus
= EFI_OUT_OF_RESOURCES
;
381 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
382 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
383 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
386 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
388 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
389 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
391 HobData
= BuildGuidHob (
392 &gTcgEvent2EntryHobGuid
,
393 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
395 if (HobData
== NULL
) {
396 RetStatus
= EFI_OUT_OF_RESOURCES
;
400 TcgPcrEvent2
= HobData
;
401 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
402 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
403 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
404 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
405 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
406 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
407 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
417 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
418 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
419 added into the Event Log.
421 @param[in] This Indicates the calling context
422 @param[in] Flags Bitmap providing additional information.
423 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
424 start of the data buffer to be hashed, extended, and logged.
425 If BIT0 of Flags is 1, it is physical address of the
426 start of the pre-hash data buffter to be extended, and logged.
427 The pre-hash data format is TPML_DIGEST_VALUES.
428 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
429 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
430 @param[in] NewEventData Pointer to the new event data.
432 @retval EFI_SUCCESS Operation completed successfully.
433 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
434 @retval EFI_DEVICE_ERROR The command was unsuccessful.
440 IN EDKII_TCG_PPI
*This
,
443 IN UINTN HashDataLen
,
444 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
445 IN UINT8
*NewEventData
449 TPML_DIGEST_VALUES DigestList
;
451 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
452 return EFI_DEVICE_ERROR
;
455 if(Flags
& EDKII_TCG_PRE_HASH
) {
456 ZeroMem (&DigestList
, sizeof(DigestList
));
457 CopyMem (&DigestList
, HashData
, sizeof(DigestList
));
458 Status
= Tpm2PcrExtend (
463 Status
= HashAndExtend (
464 NewEventHdr
->PCRIndex
,
470 if (!EFI_ERROR (Status
)) {
471 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
474 if (Status
== EFI_DEVICE_ERROR
) {
475 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
476 BuildGuidHob (&gTpmErrorHobGuid
,0);
478 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
479 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
487 Measure CRTM version.
489 @retval EFI_SUCCESS Operation completed successfully.
490 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
491 @retval EFI_DEVICE_ERROR The command was unsuccessful.
499 TCG_PCR_EVENT_HDR TcgEventHdr
;
502 // Use FirmwareVersion string to represent CRTM version.
503 // OEMs should get real CRTM version string and measure it.
506 TcgEventHdr
.PCRIndex
= 0;
507 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
508 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
510 return HashLogExtendEvent (
513 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
514 TcgEventHdr
.EventSize
,
516 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
521 Get the FvName from the FV header.
523 Causion: The FV is untrusted input.
525 @param[in] FvBase Base address of FV image.
526 @param[in] FvLength Length of FV image.
528 @return FvName pointer
529 @retval NULL FvName is NOT found
533 IN EFI_PHYSICAL_ADDRESS FvBase
,
537 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
538 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
540 if (FvBase
>= MAX_ADDRESS
) {
543 if (FvLength
>= MAX_ADDRESS
- FvBase
) {
546 if (FvLength
< sizeof(EFI_FIRMWARE_VOLUME_HEADER
)) {
550 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
551 if (FvHeader
->ExtHeaderOffset
< sizeof(EFI_FIRMWARE_VOLUME_HEADER
)) {
554 if (FvHeader
->ExtHeaderOffset
+ sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER
) > FvLength
) {
557 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(UINTN
)(FvBase
+ FvHeader
->ExtHeaderOffset
);
559 return &FvExtHeader
->FvName
;
564 Add it into the measured FV list after the FV is measured successfully.
566 @param[in] FvBase Base address of FV image.
567 @param[in] FvLength Length of FV image.
569 @retval EFI_SUCCESS Fv image is measured successfully
570 or it has been already measured.
571 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
572 @retval EFI_DEVICE_ERROR The command was unsuccessful.
577 IN EFI_PHYSICAL_ADDRESS FvBase
,
583 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
584 FV_HANDOFF_TABLE_POINTERS2 FvBlob2
;
587 TCG_PCR_EVENT_HDR TcgEventHdr
;
590 TPML_DIGEST_VALUES DigestList
;
592 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
593 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
594 HASH_INFO
*PreHashInfo
;
598 // Check Excluded FV list
602 Status
= PeiServicesLocatePpi(
603 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
606 (VOID
**)&MeasurementExcludedFvPpi
608 if (!EFI_ERROR(Status
)) {
609 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
610 if (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
611 && MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
) {
612 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
613 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
620 } while (!EFI_ERROR(Status
));
623 // Check measured FV list
625 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
626 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
&& mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
) {
627 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
628 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
634 // Check pre-hashed FV list
637 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
639 Status
= PeiServicesLocatePpi (
640 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
643 (VOID
**)&PrehashedFvPpi
645 if (!EFI_ERROR(Status
) && PrehashedFvPpi
->FvBase
== FvBase
&& PrehashedFvPpi
->FvLength
== FvLength
) {
646 ZeroMem (&DigestList
, sizeof(TPML_DIGEST_VALUES
));
649 // The FV is prehashed, check against TPM hash mask
651 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
652 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
653 DEBUG((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
654 HashAlgoMask
= GetHashMaskFromAlgo(PreHashInfo
->HashAlgoId
);
655 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
657 // Hash is required, copy it to DigestList
659 WriteUnaligned16(&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
661 &DigestList
.digests
[DigestCount
].digest
,
663 PreHashInfo
->HashSize
667 // Clean the corresponding Hash Algo mask bit
669 Tpm2HashMask
&= ~HashAlgoMask
;
671 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
674 WriteUnaligned32(&DigestList
.count
, DigestCount
);
679 } while (!EFI_ERROR(Status
));
682 // Init the log event for FV measurement
684 if (PcdGet32(PcdTcgPfpMeasurementRevision
) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105
) {
685 FvBlob2
.BlobDescriptionSize
= sizeof(FvBlob2
.BlobDescription
);
686 CopyMem (FvBlob2
.BlobDescription
, FV_HANDOFF_TABLE_DESC
, sizeof(FvBlob2
.BlobDescription
));
687 FvName
= GetFvName (FvBase
, FvLength
);
688 if (FvName
!= NULL
) {
689 AsciiSPrint ((CHAR8
*)FvBlob2
.BlobDescription
, sizeof(FvBlob2
.BlobDescription
), "Fv(%g)", FvName
);
691 FvBlob2
.BlobBase
= FvBase
;
692 FvBlob2
.BlobLength
= FvLength
;
693 TcgEventHdr
.PCRIndex
= 0;
694 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB2
;
695 TcgEventHdr
.EventSize
= sizeof (FvBlob2
);
696 EventData
= &FvBlob2
;
698 FvBlob
.BlobBase
= FvBase
;
699 FvBlob
.BlobLength
= FvLength
;
700 TcgEventHdr
.PCRIndex
= 0;
701 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
702 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
706 if (Tpm2HashMask
== 0) {
708 // FV pre-hash algos comply with current TPM hash requirement
709 // Skip hashing step in measure, only extend DigestList to PCR and log event
711 Status
= HashLogExtendEvent (
714 (UINT8
*) &DigestList
, // HashData
715 (UINTN
) sizeof(DigestList
), // HashDataLen
716 &TcgEventHdr
, // EventHdr
717 EventData
// EventData
719 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase
));
720 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength
));
723 // Hash the FV, extend digest to the TPM and log TCG event
725 Status
= HashLogExtendEvent (
728 (UINT8
*) (UINTN
) FvBase
, // HashData
729 (UINTN
) FvLength
, // HashDataLen
730 &TcgEventHdr
, // EventHdr
731 EventData
// EventData
733 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
734 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
737 if (EFI_ERROR(Status
)) {
738 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
743 // Add new FV into the measured FV list.
745 if (mMeasuredBaseFvIndex
>= mMeasuredMaxBaseFvIndex
) {
746 mMeasuredBaseFvInfo
= ReallocatePool (
747 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxBaseFvIndex
,
748 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
751 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
752 mMeasuredMaxBaseFvIndex
= mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
755 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
756 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
757 mMeasuredBaseFvIndex
++;
765 @retval EFI_SUCCESS Operation completed successfully.
766 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
767 @retval EFI_DEVICE_ERROR The command was unsuccessful.
776 EFI_PEI_FV_HANDLE VolumeHandle
;
777 EFI_FV_INFO VolumeInfo
;
778 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
780 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
783 // Only measure BFV at the very beginning. Other parts of Static Core Root of
784 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
785 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
786 // reported by platform will be installed with Fv Info Ppi
787 // This firmware volume measure policy can be modified/enhanced by special
788 // platform for special CRTM TPM measuring.
790 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
791 ASSERT_EFI_ERROR (Status
);
794 // Measure and record the firmware volume that is dispatched by PeiCore
796 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
797 ASSERT_EFI_ERROR (Status
);
799 // Locate the corresponding FV_PPI according to founded FV's format guid
801 Status
= PeiServicesLocatePpi (
802 &VolumeInfo
.FvFormat
,
807 ASSERT_EFI_ERROR (Status
);
809 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
811 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
817 Measure and record the Firmware Volume Information once FvInfoPPI install.
819 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
820 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
821 @param[in] Ppi Address of the PPI that was installed.
823 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
824 @return Others Fail to measure FV.
829 FirmwareVolumeInfoPpiNotifyCallback (
830 IN EFI_PEI_SERVICES
**PeiServices
,
831 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
835 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
837 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
840 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
843 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
845 Status
= PeiServicesLocatePpi (
851 if (EFI_ERROR (Status
)) {
856 // This is an FV from an FFS file, and the parent FV must have already been measured,
857 // No need to measure twice, so just record the FV and return
859 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
861 if (mMeasuredChildFvIndex
>= mMeasuredMaxChildFvIndex
) {
862 mMeasuredChildFvInfo
= ReallocatePool (
863 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxChildFvIndex
,
864 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
867 ASSERT (mMeasuredChildFvInfo
!= NULL
);
868 mMeasuredMaxChildFvIndex
= mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
871 // Check whether FV is in the measured child FV list.
873 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
874 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
878 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
879 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
880 mMeasuredChildFvIndex
++;
884 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
888 Do measurement after memory is ready.
890 @param[in] PeiServices Describes the list of possible PEI Services.
892 @retval EFI_SUCCESS Operation completed successfully.
893 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
894 @retval EFI_DEVICE_ERROR The command was unsuccessful.
899 IN EFI_PEI_SERVICES
**PeiServices
905 // install Tcg Services
907 Status
= PeiServicesInstallPpi (&mTcgPpiList
);
908 ASSERT_EFI_ERROR (Status
);
910 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
911 Status
= MeasureCRTMVersion ();
914 Status
= MeasureMainBios ();
915 if (EFI_ERROR(Status
)) {
921 // for the FvInfoPpi services to measure and record
922 // the additional Fvs to TPM
924 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
925 ASSERT_EFI_ERROR (Status
);
931 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
933 @param[in] PCRIndex PCR index.
935 @retval EFI_SUCCESS Operation completed successfully.
936 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
940 MeasureSeparatorEventWithError (
941 IN TPM_PCRINDEX PCRIndex
944 TCG_PCR_EVENT_HDR TcgEvent
;
948 // Use EventData 0x1 to indicate there is error.
951 TcgEvent
.PCRIndex
= PCRIndex
;
952 TcgEvent
.EventType
= EV_SEPARATOR
;
953 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
954 return HashLogExtendEvent(&mEdkiiTcgPpi
, 0, (UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
958 Entry point of this module.
960 @param[in] FileHandle Handle of the file being invoked.
961 @param[in] PeiServices Describes the list of possible PEI Services.
969 IN EFI_PEI_FILE_HANDLE FileHandle
,
970 IN CONST EFI_PEI_SERVICES
**PeiServices
975 EFI_BOOT_MODE BootMode
;
976 TPM_PCRINDEX PcrIndex
;
977 BOOLEAN S3ErrorReport
;
979 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
980 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
981 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
982 return EFI_UNSUPPORTED
;
985 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
986 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
987 return EFI_DEVICE_ERROR
;
990 Status
= PeiServicesGetBootMode (&BootMode
);
991 ASSERT_EFI_ERROR (Status
);
994 // In S3 path, skip shadow logic. no measurement is required
996 if (BootMode
!= BOOT_ON_S3_RESUME
) {
997 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
998 if (Status
== EFI_ALREADY_STARTED
) {
999 mImageInMemory
= TRUE
;
1000 mFileHandle
= FileHandle
;
1001 } else if (Status
== EFI_NOT_FOUND
) {
1002 ASSERT_EFI_ERROR (Status
);
1006 if (!mImageInMemory
) {
1008 // Initialize TPM device
1010 Status
= Tpm2RequestUseTpm ();
1011 if (EFI_ERROR (Status
)) {
1012 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
1016 S3ErrorReport
= FALSE
;
1017 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
1018 if (BootMode
== BOOT_ON_S3_RESUME
) {
1019 Status
= Tpm2Startup (TPM_SU_STATE
);
1020 if (EFI_ERROR (Status
) ) {
1021 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1022 if (!EFI_ERROR(Status
)) {
1023 S3ErrorReport
= TRUE
;
1027 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1029 if (EFI_ERROR (Status
) ) {
1035 // Update Tpm2HashMask according to PCR bank.
1037 SyncPcrAllocationsAndPcrMask ();
1039 if (S3ErrorReport
) {
1041 // The system firmware that resumes from S3 MUST deal with a
1042 // TPM2_Startup error appropriately.
1043 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
1044 // configuring the device securely by taking actions like extending a
1045 // separator with an error digest (0x01) into PCRs 0 through 7.
1047 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1048 Status
= MeasureSeparatorEventWithError (PcrIndex
);
1049 if (EFI_ERROR (Status
)) {
1050 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
1056 // TpmSelfTest is optional on S3 path, skip it to save S3 time
1058 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1059 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
1060 Status
= Tpm2SelfTest (NO
);
1061 if (EFI_ERROR (Status
)) {
1068 // Only install TpmInitializedPpi on success
1070 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
1071 ASSERT_EFI_ERROR (Status
);
1074 if (mImageInMemory
) {
1075 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
1080 if (EFI_ERROR (Status
)) {
1081 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
1082 BuildGuidHob (&gTpmErrorHobGuid
,0);
1083 REPORT_STATUS_CODE (
1084 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1085 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
1089 // Always install TpmInitializationDonePpi no matter success or fail.
1090 // Other driver can know TPM initialization state by TpmInitializedPpi.
1092 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
1093 ASSERT_EFI_ERROR (Status2
);