2 Initialize TPM2 device and measure FVs before handing off control to DXE.
4 Copyright (c) 2015 - 2021, 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>
25 #include <Guid/MigratedFvInfo.h>
27 #include <Library/DebugLib.h>
28 #include <Library/BaseMemoryLib.h>
29 #include <Library/PeiServicesLib.h>
30 #include <Library/PeimEntryPoint.h>
31 #include <Library/Tpm2CommandLib.h>
32 #include <Library/Tpm2DeviceLib.h>
33 #include <Library/HashLib.h>
34 #include <Library/HobLib.h>
35 #include <Library/PcdLib.h>
36 #include <Library/PeiServicesTablePointerLib.h>
37 #include <Protocol/Tcg2Protocol.h>
38 #include <Library/PerformanceLib.h>
39 #include <Library/MemoryAllocationLib.h>
40 #include <Library/ReportStatusCodeLib.h>
41 #include <Library/ResetSystemLib.h>
42 #include <Library/PrintLib.h>
44 #define PERF_ID_TCG2_PEI 0x3080
48 EFI_TCG2_EVENT_LOG_FORMAT LogFormat
;
49 } TCG2_EVENT_INFO_STRUCT
;
51 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo
[] = {
52 { &gTcgEventEntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
},
53 { &gTcgEvent2EntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
},
56 BOOLEAN mImageInMemory
= FALSE
;
57 EFI_PEI_FILE_HANDLE mFileHandle
;
59 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
60 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
61 &gPeiTpmInitializedPpiGuid
,
65 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
66 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
67 &gPeiTpmInitializationDonePpiGuid
,
72 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
73 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
74 added into the Event Log.
76 @param[in] This Indicates the calling context
77 @param[in] Flags Bitmap providing additional information.
78 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
79 start of the data buffer to be hashed, extended, and logged.
80 If BIT0 of Flags is 1, it is physical address of the
81 start of the pre-hash data buffter to be extended, and logged.
82 The pre-hash data format is TPML_DIGEST_VALUES.
83 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
84 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
85 @param[in] NewEventData Pointer to the new event data.
87 @retval EFI_SUCCESS Operation completed successfully.
88 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
89 @retval EFI_DEVICE_ERROR The command was unsuccessful.
95 IN EDKII_TCG_PPI
*This
,
99 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
100 IN UINT8
*NewEventData
103 EDKII_TCG_PPI mEdkiiTcgPpi
= {
107 EFI_PEI_PPI_DESCRIPTOR mTcgPpiList
= {
108 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
114 // Number of firmware blobs to grow by each time we run out of room
116 #define FIRMWARE_BLOB_GROWTH_STEP 4
118 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
119 UINT32 mMeasuredMaxBaseFvIndex
= 0;
120 UINT32 mMeasuredBaseFvIndex
= 0;
122 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
123 UINT32 mMeasuredMaxChildFvIndex
= 0;
124 UINT32 mMeasuredChildFvIndex
= 0;
128 #define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"
130 UINT8 BlobDescriptionSize
;
131 UINT8 BlobDescription
[sizeof (FV_HANDOFF_TABLE_DESC
)];
132 EFI_PHYSICAL_ADDRESS BlobBase
;
134 } FV_HANDOFF_TABLE_POINTERS2
;
139 Measure and record the Firmware Volume Information once FvInfoPPI install.
141 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
142 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
143 @param[in] Ppi Address of the PPI that was installed.
145 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
146 @return Others Fail to measure FV.
151 FirmwareVolumeInfoPpiNotifyCallback (
152 IN EFI_PEI_SERVICES
**PeiServices
,
153 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
158 Record all measured Firmware Volume Information into a Guid Hob
160 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
161 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
162 @param[in] Ppi Address of the PPI that was installed.
164 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
165 @return Others Fail to measure FV.
170 EndofPeiSignalNotifyCallBack (
171 IN EFI_PEI_SERVICES
**PeiServices
,
172 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
176 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
178 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
179 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
180 FirmwareVolumeInfoPpiNotifyCallback
183 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
184 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
185 FirmwareVolumeInfoPpiNotifyCallback
188 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
189 &gEfiEndOfPeiSignalPpiGuid
,
190 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 ((DEBUG_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 ((DEBUG_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
300 if (NewTpmActivePcrBanks
== 0) {
301 DEBUG ((DEBUG_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 ((DEBUG_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
310 ASSERT_EFI_ERROR (Status
);
314 // Need reset system, since we just called Tpm2PcrAllocateBanks().
321 // If there are any PCRs that claim support in the Platform mask that are
322 // not supported by the TPM, update the mask.
324 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
325 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
327 DEBUG ((DEBUG_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
328 if (NewTpm2PcrMask
== 0) {
329 DEBUG ((DEBUG_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
333 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
334 ASSERT_EFI_ERROR (Status
);
339 Add a new entry to the Event Log.
341 @param[in] DigestList A list of digest.
342 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
343 @param[in] NewEventData Pointer to the new event data.
345 @retval EFI_SUCCESS The new event log entry was added.
346 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
350 IN TPML_DIGEST_VALUES
*DigestList
,
351 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
352 IN UINT8
*NewEventData
358 EFI_STATUS RetStatus
;
359 UINT32 SupportedEventLogs
;
360 TCG_PCR_EVENT2
*TcgPcrEvent2
;
363 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
365 RetStatus
= EFI_SUCCESS
;
366 for (Index
= 0; Index
< sizeof (mTcg2EventInfo
)/sizeof (mTcg2EventInfo
[0]); Index
++) {
367 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
368 DEBUG ((DEBUG_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
369 switch (mTcg2EventInfo
[Index
].LogFormat
) {
370 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
371 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
372 if (!EFI_ERROR (Status
)) {
373 HobData
= BuildGuidHob (
374 &gTcgEventEntryHobGuid
,
375 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
377 if (HobData
== NULL
) {
378 RetStatus
= EFI_OUT_OF_RESOURCES
;
382 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
383 HobData
= (VOID
*)((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
384 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
388 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
390 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
391 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
393 HobData
= BuildGuidHob (
394 &gTcgEvent2EntryHobGuid
,
395 sizeof (TcgPcrEvent2
->PCRIndex
) + sizeof (TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof (TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
397 if (HobData
== NULL
) {
398 RetStatus
= EFI_OUT_OF_RESOURCES
;
402 TcgPcrEvent2
= HobData
;
403 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
404 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
405 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
406 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
407 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof (TcgPcrEvent2
->EventSize
));
408 DigestBuffer
= DigestBuffer
+ sizeof (TcgPcrEvent2
->EventSize
);
409 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
419 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
420 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
421 added into the Event Log.
423 @param[in] This Indicates the calling context
424 @param[in] Flags Bitmap providing additional information.
425 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
426 start of the data buffer to be hashed, extended, and logged.
427 If BIT0 of Flags is 1, it is physical address of the
428 start of the pre-hash data buffter to be extended, and logged.
429 The pre-hash data format is TPML_DIGEST_VALUES.
430 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
431 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
432 @param[in] NewEventData Pointer to the new event data.
434 @retval EFI_SUCCESS Operation completed successfully.
435 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
436 @retval EFI_DEVICE_ERROR The command was unsuccessful.
442 IN EDKII_TCG_PPI
*This
,
445 IN UINTN HashDataLen
,
446 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
447 IN UINT8
*NewEventData
451 TPML_DIGEST_VALUES DigestList
;
453 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
454 return EFI_DEVICE_ERROR
;
457 if (((Flags
& EDKII_TCG_PRE_HASH
) != 0) || ((Flags
& EDKII_TCG_PRE_HASH_LOG_ONLY
) != 0)) {
458 ZeroMem (&DigestList
, sizeof (DigestList
));
459 CopyMem (&DigestList
, HashData
, sizeof (DigestList
));
460 Status
= EFI_SUCCESS
;
461 if ((Flags
& EDKII_TCG_PRE_HASH
) != 0 ) {
462 Status
= Tpm2PcrExtend (
463 NewEventHdr
->PCRIndex
,
468 Status
= HashAndExtend (
469 NewEventHdr
->PCRIndex
,
476 if (!EFI_ERROR (Status
)) {
477 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
480 if (Status
== EFI_DEVICE_ERROR
) {
481 DEBUG ((DEBUG_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
482 BuildGuidHob (&gTpmErrorHobGuid
, 0);
484 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
485 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
493 Measure CRTM version.
495 @retval EFI_SUCCESS Operation completed successfully.
496 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
497 @retval EFI_DEVICE_ERROR The command was unsuccessful.
505 TCG_PCR_EVENT_HDR TcgEventHdr
;
508 // Use FirmwareVersion string to represent CRTM version.
509 // OEMs should get real CRTM version string and measure it.
512 TcgEventHdr
.PCRIndex
= 0;
513 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
514 TcgEventHdr
.EventSize
= (UINT32
)StrSize ((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
516 return HashLogExtendEvent (
519 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
520 TcgEventHdr
.EventSize
,
522 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
527 Get the FvName from the FV header.
529 Causion: The FV is untrusted input.
531 @param[in] FvBase Base address of FV image.
532 @param[in] FvLength Length of FV image.
534 @return FvName pointer
535 @retval NULL FvName is NOT found
539 IN EFI_PHYSICAL_ADDRESS FvBase
,
543 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
544 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
546 if (FvBase
>= MAX_ADDRESS
) {
550 if (FvLength
>= MAX_ADDRESS
- FvBase
) {
554 if (FvLength
< sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) {
558 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
559 if (FvHeader
->ExtHeaderOffset
< sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) {
563 if (FvHeader
->ExtHeaderOffset
+ sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER
) > FvLength
) {
567 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(UINTN
)(FvBase
+ FvHeader
->ExtHeaderOffset
);
569 return &FvExtHeader
->FvName
;
574 Add it into the measured FV list after the FV is measured successfully.
576 @param[in] FvBase Base address of FV image.
577 @param[in] FvLength Length of FV image.
579 @retval EFI_SUCCESS Fv image is measured successfully
580 or it has been already measured.
581 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
582 @retval EFI_DEVICE_ERROR The command was unsuccessful.
587 IN EFI_PHYSICAL_ADDRESS FvBase
,
593 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
594 FV_HANDOFF_TABLE_POINTERS2 FvBlob2
;
597 TCG_PCR_EVENT_HDR TcgEventHdr
;
600 TPML_DIGEST_VALUES DigestList
;
602 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
603 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
604 HASH_INFO
*PreHashInfo
;
606 EFI_PHYSICAL_ADDRESS FvOrgBase
;
607 EFI_PHYSICAL_ADDRESS FvDataBase
;
608 EFI_PEI_HOB_POINTERS Hob
;
609 EDKII_MIGRATED_FV_INFO
*MigratedFvInfo
;
612 // Check Excluded FV list
616 Status
= PeiServicesLocatePpi (
617 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
620 (VOID
**)&MeasurementExcludedFvPpi
622 if (!EFI_ERROR (Status
)) {
623 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
624 if ( (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
)
625 && (MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
))
627 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
628 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
635 } while (!EFI_ERROR (Status
));
638 // Check measured FV list
640 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
641 if ((mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
) && (mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
)) {
642 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
643 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
649 // Check pre-hashed FV list
652 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
654 Status
= PeiServicesLocatePpi (
655 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
658 (VOID
**)&PrehashedFvPpi
660 if (!EFI_ERROR (Status
) && (PrehashedFvPpi
->FvBase
== FvBase
) && (PrehashedFvPpi
->FvLength
== FvLength
)) {
661 ZeroMem (&DigestList
, sizeof (TPML_DIGEST_VALUES
));
664 // The FV is prehashed, check against TPM hash mask
666 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
667 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
668 DEBUG ((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
669 HashAlgoMask
= GetHashMaskFromAlgo (PreHashInfo
->HashAlgoId
);
670 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
672 // Hash is required, copy it to DigestList
674 WriteUnaligned16 (&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
676 &DigestList
.digests
[DigestCount
].digest
,
678 PreHashInfo
->HashSize
682 // Clean the corresponding Hash Algo mask bit
684 Tpm2HashMask
&= ~HashAlgoMask
;
687 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
690 WriteUnaligned32 (&DigestList
.count
, DigestCount
);
696 } while (!EFI_ERROR (Status
));
699 // Search the matched migration FV info
703 Hob
.Raw
= GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid
);
704 while (Hob
.Raw
!= NULL
) {
705 MigratedFvInfo
= GET_GUID_HOB_DATA (Hob
);
706 if ((MigratedFvInfo
->FvNewBase
== (UINT32
)FvBase
) && (MigratedFvInfo
->FvLength
== (UINT32
)FvLength
)) {
708 // Found the migrated FV info
710 FvOrgBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)MigratedFvInfo
->FvOrgBase
;
711 FvDataBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)MigratedFvInfo
->FvDataBase
;
715 Hob
.Raw
= GET_NEXT_HOB (Hob
);
716 Hob
.Raw
= GetNextGuidHob (&gEdkiiMigratedFvInfoGuid
, Hob
.Raw
);
720 // Init the log event for FV measurement
722 if (PcdGet32 (PcdTcgPfpMeasurementRevision
) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105
) {
723 FvBlob2
.BlobDescriptionSize
= sizeof (FvBlob2
.BlobDescription
);
724 CopyMem (FvBlob2
.BlobDescription
, FV_HANDOFF_TABLE_DESC
, sizeof (FvBlob2
.BlobDescription
));
725 FvName
= GetFvName (FvBase
, FvLength
);
726 if (FvName
!= NULL
) {
727 AsciiSPrint ((CHAR8
*)FvBlob2
.BlobDescription
, sizeof (FvBlob2
.BlobDescription
), "Fv(%g)", FvName
);
730 FvBlob2
.BlobBase
= FvOrgBase
;
731 FvBlob2
.BlobLength
= FvLength
;
732 TcgEventHdr
.PCRIndex
= 0;
733 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB2
;
734 TcgEventHdr
.EventSize
= sizeof (FvBlob2
);
735 EventData
= &FvBlob2
;
737 FvBlob
.BlobBase
= FvOrgBase
;
738 FvBlob
.BlobLength
= FvLength
;
739 TcgEventHdr
.PCRIndex
= 0;
740 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
741 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
745 if (Tpm2HashMask
== 0) {
747 // FV pre-hash algos comply with current TPM hash requirement
748 // Skip hashing step in measure, only extend DigestList to PCR and log event
750 Status
= HashLogExtendEvent (
753 (UINT8
*)&DigestList
, // HashData
754 (UINTN
)sizeof (DigestList
), // HashDataLen
755 &TcgEventHdr
, // EventHdr
756 EventData
// EventData
758 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase
));
759 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength
));
762 // Hash the FV, extend digest to the TPM and log TCG event
764 Status
= HashLogExtendEvent (
767 (UINT8
*)(UINTN
)FvDataBase
, // HashData
768 (UINTN
)FvLength
, // HashDataLen
769 &TcgEventHdr
, // EventHdr
770 EventData
// EventData
772 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
773 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
776 if (EFI_ERROR (Status
)) {
777 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
782 // Add new FV into the measured FV list.
784 if (mMeasuredBaseFvIndex
>= mMeasuredMaxBaseFvIndex
) {
785 mMeasuredBaseFvInfo
= ReallocatePool (
786 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxBaseFvIndex
,
787 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
790 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
791 mMeasuredMaxBaseFvIndex
= mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
794 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
795 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
796 mMeasuredBaseFvIndex
++;
804 @retval EFI_SUCCESS Operation completed successfully.
805 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
806 @retval EFI_DEVICE_ERROR The command was unsuccessful.
815 EFI_PEI_FV_HANDLE VolumeHandle
;
816 EFI_FV_INFO VolumeInfo
;
817 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
819 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
822 // Only measure BFV at the very beginning. Other parts of Static Core Root of
823 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
824 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
825 // reported by platform will be installed with Fv Info Ppi
826 // This firmware volume measure policy can be modified/enhanced by special
827 // platform for special CRTM TPM measuring.
829 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
830 ASSERT_EFI_ERROR (Status
);
833 // Measure and record the firmware volume that is dispatched by PeiCore
835 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
836 ASSERT_EFI_ERROR (Status
);
838 // Locate the corresponding FV_PPI according to founded FV's format guid
840 Status
= PeiServicesLocatePpi (
841 &VolumeInfo
.FvFormat
,
846 ASSERT_EFI_ERROR (Status
);
848 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
)(UINTN
)VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
850 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
856 Measure and record the Firmware Volume Information once FvInfoPPI install.
858 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
859 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
860 @param[in] Ppi Address of the PPI that was installed.
862 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
863 @return Others Fail to measure FV.
868 FirmwareVolumeInfoPpiNotifyCallback (
869 IN EFI_PEI_SERVICES
**PeiServices
,
870 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
874 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
876 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
879 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*)Ppi
;
882 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
884 Status
= PeiServicesLocatePpi (
890 if (EFI_ERROR (Status
)) {
895 // This is an FV from an FFS file, and the parent FV must have already been measured,
896 // No need to measure twice, so just record the FV and return
898 if ((Fv
->ParentFvName
!= NULL
) || (Fv
->ParentFileName
!= NULL
)) {
899 if (mMeasuredChildFvIndex
>= mMeasuredMaxChildFvIndex
) {
900 mMeasuredChildFvInfo
= ReallocatePool (
901 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxChildFvIndex
,
902 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
905 ASSERT (mMeasuredChildFvInfo
!= NULL
);
906 mMeasuredMaxChildFvIndex
= mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
910 // Check whether FV is in the measured child FV list.
912 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
913 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
)(UINTN
)Fv
->FvInfo
) {
918 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Fv
->FvInfo
;
919 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
920 mMeasuredChildFvIndex
++;
924 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Fv
->FvInfo
, Fv
->FvInfoSize
);
928 Do measurement after memory is ready.
930 @param[in] PeiServices Describes the list of possible PEI Services.
932 @retval EFI_SUCCESS Operation completed successfully.
933 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
934 @retval EFI_DEVICE_ERROR The command was unsuccessful.
939 IN EFI_PEI_SERVICES
**PeiServices
945 // install Tcg Services
947 Status
= PeiServicesInstallPpi (&mTcgPpiList
);
948 ASSERT_EFI_ERROR (Status
);
950 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
951 Status
= MeasureCRTMVersion ();
954 Status
= MeasureMainBios ();
955 if (EFI_ERROR (Status
)) {
961 // for the FvInfoPpi services to measure and record
962 // the additional Fvs to TPM
964 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
965 ASSERT_EFI_ERROR (Status
);
971 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
973 @param[in] PCRIndex PCR index.
975 @retval EFI_SUCCESS Operation completed successfully.
976 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
980 MeasureSeparatorEventWithError (
981 IN TPM_PCRINDEX PCRIndex
984 TCG_PCR_EVENT_HDR TcgEvent
;
988 // Use EventData 0x1 to indicate there is error.
991 TcgEvent
.PCRIndex
= PCRIndex
;
992 TcgEvent
.EventType
= EV_SEPARATOR
;
993 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
994 return HashLogExtendEvent (&mEdkiiTcgPpi
, 0, (UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
, (UINT8
*)&EventData
);
998 Entry point of this module.
1000 @param[in] FileHandle Handle of the file being invoked.
1001 @param[in] PeiServices Describes the list of possible PEI Services.
1009 IN EFI_PEI_FILE_HANDLE FileHandle
,
1010 IN CONST EFI_PEI_SERVICES
**PeiServices
1015 EFI_BOOT_MODE BootMode
;
1016 TPM_PCRINDEX PcrIndex
;
1017 BOOLEAN S3ErrorReport
;
1019 if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
1020 CompareGuid (PcdGetPtr (PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
))
1022 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
1023 return EFI_UNSUPPORTED
;
1026 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1027 DEBUG ((DEBUG_ERROR
, "TPM2 error!\n"));
1028 return EFI_DEVICE_ERROR
;
1031 Status
= PeiServicesGetBootMode (&BootMode
);
1032 ASSERT_EFI_ERROR (Status
);
1035 // In S3 path, skip shadow logic. no measurement is required
1037 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1038 Status
= (**PeiServices
).RegisterForShadow (FileHandle
);
1039 if (Status
== EFI_ALREADY_STARTED
) {
1040 mImageInMemory
= TRUE
;
1041 mFileHandle
= FileHandle
;
1042 } else if (Status
== EFI_NOT_FOUND
) {
1043 ASSERT_EFI_ERROR (Status
);
1047 if (!mImageInMemory
) {
1049 // Initialize TPM device
1051 Status
= Tpm2RequestUseTpm ();
1052 if (EFI_ERROR (Status
)) {
1053 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
1057 S3ErrorReport
= FALSE
;
1058 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
1059 if (BootMode
== BOOT_ON_S3_RESUME
) {
1060 Status
= Tpm2Startup (TPM_SU_STATE
);
1061 if (EFI_ERROR (Status
)) {
1062 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1063 if (!EFI_ERROR (Status
)) {
1064 S3ErrorReport
= TRUE
;
1068 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1071 if (EFI_ERROR (Status
)) {
1077 // Update Tpm2HashMask according to PCR bank.
1079 SyncPcrAllocationsAndPcrMask ();
1081 if (S3ErrorReport
) {
1083 // The system firmware that resumes from S3 MUST deal with a
1084 // TPM2_Startup error appropriately.
1085 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
1086 // configuring the device securely by taking actions like extending a
1087 // separator with an error digest (0x01) into PCRs 0 through 7.
1089 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1090 Status
= MeasureSeparatorEventWithError (PcrIndex
);
1091 if (EFI_ERROR (Status
)) {
1092 DEBUG ((DEBUG_ERROR
, "Separator Event with Error not Measured. Error!\n"));
1098 // TpmSelfTest is optional on S3 path, skip it to save S3 time
1100 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1101 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
1102 Status
= Tpm2SelfTest (NO
);
1103 if (EFI_ERROR (Status
)) {
1109 DEBUG_CODE_BEGIN ();
1111 // Peek into TPM PCR 00 before any BIOS measurement.
1113 Tpm2PcrReadForActiveBank (00, NULL
);
1117 // Only install TpmInitializedPpi on success
1119 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
1120 ASSERT_EFI_ERROR (Status
);
1123 if (mImageInMemory
) {
1124 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
1129 if (EFI_ERROR (Status
)) {
1130 DEBUG ((DEBUG_ERROR
, "TPM2 error! Build Hob\n"));
1131 BuildGuidHob (&gTpmErrorHobGuid
, 0);
1132 REPORT_STATUS_CODE (
1133 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1134 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
1139 // Always install TpmInitializationDonePpi no matter success or fail.
1140 // Other driver can know TPM initialization state by TpmInitializedPpi.
1142 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
1143 ASSERT_EFI_ERROR (Status2
);