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 PcdTcg2HashAlgorithmBitmap and the PcdTpm2HashMask are all in agreement.
258 SyncPcrAllocationsAndPcrMask (
263 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
264 EFI_TCG2_EVENT_ALGORITHM_BITMAP BiosHashAlgorithmBitmap
;
265 UINT32 TpmActivePcrBanks
;
266 UINT32 NewTpmActivePcrBanks
;
268 UINT32 NewTpm2PcrMask
;
270 DEBUG ((DEBUG_ERROR
, "SyncPcrAllocationsAndPcrMask!\n"));
273 // Determine the current TPM support and the Platform PCR mask.
275 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &TpmActivePcrBanks
);
276 ASSERT_EFI_ERROR (Status
);
278 DEBUG ((DEBUG_INFO
, "Tpm2GetCapabilitySupportedAndActivePcrs - TpmHashAlgorithmBitmap: 0x%08x\n", TpmHashAlgorithmBitmap
));
279 DEBUG ((DEBUG_INFO
, "Tpm2GetCapabilitySupportedAndActivePcrs - TpmActivePcrBanks 0x%08x\n", TpmActivePcrBanks
));
281 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
282 if (Tpm2PcrMask
== 0) {
284 // If PcdTpm2HashMask is zero, use ActivePcr setting.
285 // Only when PcdTpm2HashMask is initialized to 0, will it be updated to current Active Pcrs.
287 PcdSet32S (PcdTpm2HashMask
, TpmActivePcrBanks
);
288 Tpm2PcrMask
= TpmActivePcrBanks
;
291 DEBUG ((DEBUG_INFO
, "Tpm2PcrMask 0x%08x\n", Tpm2PcrMask
));
294 // The Active PCRs in the TPM need to be a strict subset of the hashing algorithms supported by BIOS.
296 // * Find the intersection of Pcd support and TPM active PCRs. If banks are missing from the TPM support
297 // that are in the PCD, update the PCD.
298 // * Find intersection of TPM Active PCRs and BIOS supported algorithms. If there are active PCR banks
299 // that are not supported by the platform, update the TPM allocations and reboot.
300 // Note: When the HashLibBaseCryptoRouter solution is used, the hash algorithm support from BIOS is reported
301 // by Tcg2HashAlgorithmBitmap, which is populated by HashLib instances at runtime.
302 BiosHashAlgorithmBitmap
= PcdGet32 (PcdTcg2HashAlgorithmBitmap
);
303 DEBUG ((DEBUG_INFO
, "Tcg2HashAlgorithmBitmap: 0x%08x\n", BiosHashAlgorithmBitmap
));
305 if (((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) ||
306 ((TpmActivePcrBanks
& BiosHashAlgorithmBitmap
) != TpmActivePcrBanks
))
308 DEBUG ((DEBUG_INFO
, "TpmActivePcrBanks & Tpm2PcrMask = 0x%08x\n", (TpmActivePcrBanks
& Tpm2PcrMask
)));
309 DEBUG ((DEBUG_INFO
, "TpmActivePcrBanks & BiosHashAlgorithmBitmap = 0x%08x\n", (TpmActivePcrBanks
& BiosHashAlgorithmBitmap
)));
310 NewTpmActivePcrBanks
= TpmActivePcrBanks
;
311 NewTpmActivePcrBanks
&= Tpm2PcrMask
;
312 NewTpmActivePcrBanks
&= BiosHashAlgorithmBitmap
;
313 DEBUG ((DEBUG_INFO
, "NewTpmActivePcrBanks 0x%08x\n", NewTpmActivePcrBanks
));
315 DEBUG ((DEBUG_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
317 if (NewTpmActivePcrBanks
== 0) {
318 DEBUG ((DEBUG_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
321 DEBUG ((DEBUG_ERROR
, "Tpm2PcrAllocateBanks (TpmHashAlgorithmBitmap: 0x%08x, NewTpmActivePcrBanks: 0x%08x)\n", TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
));
322 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
323 if (EFI_ERROR (Status
)) {
325 // We can't do much here, but we hope that this doesn't happen.
327 DEBUG ((DEBUG_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
328 ASSERT_EFI_ERROR (Status
);
332 // Need reset system, since we just called Tpm2PcrAllocateBanks().
339 // If there are any PCRs that claim support in the Platform mask that are
340 // not supported by the TPM, update the mask.
342 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
343 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
345 DEBUG ((DEBUG_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
346 if (NewTpm2PcrMask
== 0) {
347 DEBUG ((DEBUG_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
351 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
352 DEBUG ((DEBUG_ERROR
, "Set PcdTpm2Hash Mask to 0x%08x\n", NewTpm2PcrMask
));
353 ASSERT_EFI_ERROR (Status
);
358 Add a new entry to the Event Log.
360 @param[in] DigestList A list of digest.
361 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
362 @param[in] NewEventData Pointer to the new event data.
364 @retval EFI_SUCCESS The new event log entry was added.
365 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
369 IN TPML_DIGEST_VALUES
*DigestList
,
370 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
371 IN UINT8
*NewEventData
377 EFI_STATUS RetStatus
;
378 UINT32 SupportedEventLogs
;
379 TCG_PCR_EVENT2
*TcgPcrEvent2
;
382 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
384 RetStatus
= EFI_SUCCESS
;
385 for (Index
= 0; Index
< sizeof (mTcg2EventInfo
)/sizeof (mTcg2EventInfo
[0]); Index
++) {
386 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
387 DEBUG ((DEBUG_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
388 switch (mTcg2EventInfo
[Index
].LogFormat
) {
389 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
390 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
391 if (!EFI_ERROR (Status
)) {
392 HobData
= BuildGuidHob (
393 &gTcgEventEntryHobGuid
,
394 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
396 if (HobData
== NULL
) {
397 RetStatus
= EFI_OUT_OF_RESOURCES
;
401 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
402 HobData
= (VOID
*)((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
403 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
407 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
409 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
410 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
412 HobData
= BuildGuidHob (
413 &gTcgEvent2EntryHobGuid
,
414 sizeof (TcgPcrEvent2
->PCRIndex
) + sizeof (TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof (TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
416 if (HobData
== NULL
) {
417 RetStatus
= EFI_OUT_OF_RESOURCES
;
421 TcgPcrEvent2
= HobData
;
422 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
423 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
424 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
425 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
426 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof (TcgPcrEvent2
->EventSize
));
427 DigestBuffer
= DigestBuffer
+ sizeof (TcgPcrEvent2
->EventSize
);
428 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
438 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
439 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
440 added into the Event Log.
442 @param[in] This Indicates the calling context
443 @param[in] Flags Bitmap providing additional information.
444 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
445 start of the data buffer to be hashed, extended, and logged.
446 If BIT0 of Flags is 1, it is physical address of the
447 start of the pre-hash data buffter to be extended, and logged.
448 The pre-hash data format is TPML_DIGEST_VALUES.
449 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
450 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
451 @param[in] NewEventData Pointer to the new event data.
453 @retval EFI_SUCCESS Operation completed successfully.
454 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
455 @retval EFI_DEVICE_ERROR The command was unsuccessful.
461 IN EDKII_TCG_PPI
*This
,
464 IN UINTN HashDataLen
,
465 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
466 IN UINT8
*NewEventData
470 TPML_DIGEST_VALUES DigestList
;
472 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
473 return EFI_DEVICE_ERROR
;
476 if (((Flags
& EDKII_TCG_PRE_HASH
) != 0) || ((Flags
& EDKII_TCG_PRE_HASH_LOG_ONLY
) != 0)) {
477 ZeroMem (&DigestList
, sizeof (DigestList
));
478 CopyMem (&DigestList
, HashData
, sizeof (DigestList
));
479 Status
= EFI_SUCCESS
;
480 if ((Flags
& EDKII_TCG_PRE_HASH
) != 0 ) {
481 Status
= Tpm2PcrExtend (
482 NewEventHdr
->PCRIndex
,
487 Status
= HashAndExtend (
488 NewEventHdr
->PCRIndex
,
495 if (!EFI_ERROR (Status
)) {
496 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
499 if (Status
== EFI_DEVICE_ERROR
) {
500 DEBUG ((DEBUG_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
501 BuildGuidHob (&gTpmErrorHobGuid
, 0);
503 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
504 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
512 Measure CRTM version.
514 @retval EFI_SUCCESS Operation completed successfully.
515 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
516 @retval EFI_DEVICE_ERROR The command was unsuccessful.
524 TCG_PCR_EVENT_HDR TcgEventHdr
;
527 // Use FirmwareVersion string to represent CRTM version.
528 // OEMs should get real CRTM version string and measure it.
531 TcgEventHdr
.PCRIndex
= 0;
532 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
533 TcgEventHdr
.EventSize
= (UINT32
)StrSize ((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
535 return HashLogExtendEvent (
538 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
539 TcgEventHdr
.EventSize
,
541 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
546 Get the FvName from the FV header.
548 Causion: The FV is untrusted input.
550 @param[in] FvBase Base address of FV image.
551 @param[in] FvLength Length of FV image.
553 @return FvName pointer
554 @retval NULL FvName is NOT found
558 IN EFI_PHYSICAL_ADDRESS FvBase
,
562 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
563 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
565 if (FvBase
>= MAX_ADDRESS
) {
569 if (FvLength
>= MAX_ADDRESS
- FvBase
) {
573 if (FvLength
< sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) {
577 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
578 if (FvHeader
->ExtHeaderOffset
< sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) {
582 if (FvHeader
->ExtHeaderOffset
+ sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER
) > FvLength
) {
586 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(UINTN
)(FvBase
+ FvHeader
->ExtHeaderOffset
);
588 return &FvExtHeader
->FvName
;
593 Add it into the measured FV list after the FV is measured successfully.
595 @param[in] FvBase Base address of FV image.
596 @param[in] FvLength Length of FV image.
598 @retval EFI_SUCCESS Fv image is measured successfully
599 or it has been already measured.
600 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
601 @retval EFI_DEVICE_ERROR The command was unsuccessful.
606 IN EFI_PHYSICAL_ADDRESS FvBase
,
612 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
613 FV_HANDOFF_TABLE_POINTERS2 FvBlob2
;
616 TCG_PCR_EVENT_HDR TcgEventHdr
;
619 TPML_DIGEST_VALUES DigestList
;
621 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
622 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
623 HASH_INFO
*PreHashInfo
;
625 EFI_PHYSICAL_ADDRESS FvOrgBase
;
626 EFI_PHYSICAL_ADDRESS FvDataBase
;
627 EFI_PEI_HOB_POINTERS Hob
;
628 EDKII_MIGRATED_FV_INFO
*MigratedFvInfo
;
631 // Check Excluded FV list
635 Status
= PeiServicesLocatePpi (
636 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
639 (VOID
**)&MeasurementExcludedFvPpi
641 if (!EFI_ERROR (Status
)) {
642 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
643 if ( (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
)
644 && (MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
))
646 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
647 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
654 } while (!EFI_ERROR (Status
));
657 // Check measured FV list
659 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
660 if ((mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
) && (mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
)) {
661 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
662 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
668 // Check pre-hashed FV list
671 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
673 Status
= PeiServicesLocatePpi (
674 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
677 (VOID
**)&PrehashedFvPpi
679 if (!EFI_ERROR (Status
) && (PrehashedFvPpi
->FvBase
== FvBase
) && (PrehashedFvPpi
->FvLength
== FvLength
)) {
680 ZeroMem (&DigestList
, sizeof (TPML_DIGEST_VALUES
));
683 // The FV is prehashed, check against TPM hash mask
685 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
686 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
687 DEBUG ((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
688 HashAlgoMask
= GetHashMaskFromAlgo (PreHashInfo
->HashAlgoId
);
689 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
691 // Hash is required, copy it to DigestList
693 WriteUnaligned16 (&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
695 &DigestList
.digests
[DigestCount
].digest
,
697 PreHashInfo
->HashSize
701 // Clean the corresponding Hash Algo mask bit
703 Tpm2HashMask
&= ~HashAlgoMask
;
706 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
709 WriteUnaligned32 (&DigestList
.count
, DigestCount
);
715 } while (!EFI_ERROR (Status
));
718 // Search the matched migration FV info
722 Hob
.Raw
= GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid
);
723 while (Hob
.Raw
!= NULL
) {
724 MigratedFvInfo
= GET_GUID_HOB_DATA (Hob
);
725 if ((MigratedFvInfo
->FvNewBase
== (UINT32
)FvBase
) && (MigratedFvInfo
->FvLength
== (UINT32
)FvLength
)) {
727 // Found the migrated FV info
729 FvOrgBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)MigratedFvInfo
->FvOrgBase
;
730 FvDataBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)MigratedFvInfo
->FvDataBase
;
734 Hob
.Raw
= GET_NEXT_HOB (Hob
);
735 Hob
.Raw
= GetNextGuidHob (&gEdkiiMigratedFvInfoGuid
, Hob
.Raw
);
739 // Init the log event for FV measurement
741 if (PcdGet32 (PcdTcgPfpMeasurementRevision
) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105
) {
742 FvBlob2
.BlobDescriptionSize
= sizeof (FvBlob2
.BlobDescription
);
743 CopyMem (FvBlob2
.BlobDescription
, FV_HANDOFF_TABLE_DESC
, sizeof (FvBlob2
.BlobDescription
));
744 FvName
= GetFvName (FvBase
, FvLength
);
745 if (FvName
!= NULL
) {
746 AsciiSPrint ((CHAR8
*)FvBlob2
.BlobDescription
, sizeof (FvBlob2
.BlobDescription
), "Fv(%g)", FvName
);
749 FvBlob2
.BlobBase
= FvOrgBase
;
750 FvBlob2
.BlobLength
= FvLength
;
751 TcgEventHdr
.PCRIndex
= 0;
752 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB2
;
753 TcgEventHdr
.EventSize
= sizeof (FvBlob2
);
754 EventData
= &FvBlob2
;
756 FvBlob
.BlobBase
= FvOrgBase
;
757 FvBlob
.BlobLength
= FvLength
;
758 TcgEventHdr
.PCRIndex
= 0;
759 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
760 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
764 if (Tpm2HashMask
== 0) {
766 // FV pre-hash algos comply with current TPM hash requirement
767 // Skip hashing step in measure, only extend DigestList to PCR and log event
769 Status
= HashLogExtendEvent (
772 (UINT8
*)&DigestList
, // HashData
773 (UINTN
)sizeof (DigestList
), // HashDataLen
774 &TcgEventHdr
, // EventHdr
775 EventData
// EventData
777 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase
));
778 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength
));
781 // Hash the FV, extend digest to the TPM and log TCG event
783 Status
= HashLogExtendEvent (
786 (UINT8
*)(UINTN
)FvDataBase
, // HashData
787 (UINTN
)FvLength
, // HashDataLen
788 &TcgEventHdr
, // EventHdr
789 EventData
// EventData
791 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
792 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
795 if (EFI_ERROR (Status
)) {
796 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
801 // Add new FV into the measured FV list.
803 if (mMeasuredBaseFvIndex
>= mMeasuredMaxBaseFvIndex
) {
804 mMeasuredBaseFvInfo
= ReallocatePool (
805 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxBaseFvIndex
,
806 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
809 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
810 mMeasuredMaxBaseFvIndex
= mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
813 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
814 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
815 mMeasuredBaseFvIndex
++;
823 @retval EFI_SUCCESS Operation completed successfully.
824 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
825 @retval EFI_DEVICE_ERROR The command was unsuccessful.
834 EFI_PEI_FV_HANDLE VolumeHandle
;
835 EFI_FV_INFO VolumeInfo
;
836 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
838 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
841 // Only measure BFV at the very beginning. Other parts of Static Core Root of
842 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
843 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
844 // reported by platform will be installed with Fv Info Ppi
845 // This firmware volume measure policy can be modified/enhanced by special
846 // platform for special CRTM TPM measuring.
848 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
849 ASSERT_EFI_ERROR (Status
);
852 // Measure and record the firmware volume that is dispatched by PeiCore
854 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
855 ASSERT_EFI_ERROR (Status
);
857 // Locate the corresponding FV_PPI according to founded FV's format guid
859 Status
= PeiServicesLocatePpi (
860 &VolumeInfo
.FvFormat
,
865 ASSERT_EFI_ERROR (Status
);
867 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
)(UINTN
)VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
869 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
875 Measure and record the Firmware Volume Information once FvInfoPPI install.
877 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
878 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
879 @param[in] Ppi Address of the PPI that was installed.
881 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
882 @return Others Fail to measure FV.
887 FirmwareVolumeInfoPpiNotifyCallback (
888 IN EFI_PEI_SERVICES
**PeiServices
,
889 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
893 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
895 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
898 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*)Ppi
;
901 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
903 Status
= PeiServicesLocatePpi (
909 if (EFI_ERROR (Status
)) {
914 // This is an FV from an FFS file, and the parent FV must have already been measured,
915 // No need to measure twice, so just record the FV and return
917 if ((Fv
->ParentFvName
!= NULL
) || (Fv
->ParentFileName
!= NULL
)) {
918 if (mMeasuredChildFvIndex
>= mMeasuredMaxChildFvIndex
) {
919 mMeasuredChildFvInfo
= ReallocatePool (
920 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxChildFvIndex
,
921 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
924 ASSERT (mMeasuredChildFvInfo
!= NULL
);
925 mMeasuredMaxChildFvIndex
= mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
929 // Check whether FV is in the measured child FV list.
931 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
932 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
)(UINTN
)Fv
->FvInfo
) {
937 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Fv
->FvInfo
;
938 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
939 mMeasuredChildFvIndex
++;
943 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Fv
->FvInfo
, Fv
->FvInfoSize
);
947 Do measurement after memory is ready.
949 @param[in] PeiServices Describes the list of possible PEI Services.
951 @retval EFI_SUCCESS Operation completed successfully.
952 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
953 @retval EFI_DEVICE_ERROR The command was unsuccessful.
958 IN EFI_PEI_SERVICES
**PeiServices
964 // install Tcg Services
966 Status
= PeiServicesInstallPpi (&mTcgPpiList
);
967 ASSERT_EFI_ERROR (Status
);
969 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
970 Status
= MeasureCRTMVersion ();
973 Status
= MeasureMainBios ();
974 if (EFI_ERROR (Status
)) {
980 // for the FvInfoPpi services to measure and record
981 // the additional Fvs to TPM
983 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
984 ASSERT_EFI_ERROR (Status
);
990 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
992 @param[in] PCRIndex PCR index.
994 @retval EFI_SUCCESS Operation completed successfully.
995 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
999 MeasureSeparatorEventWithError (
1000 IN TPM_PCRINDEX PCRIndex
1003 TCG_PCR_EVENT_HDR TcgEvent
;
1007 // Use EventData 0x1 to indicate there is error.
1010 TcgEvent
.PCRIndex
= PCRIndex
;
1011 TcgEvent
.EventType
= EV_SEPARATOR
;
1012 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
1013 return HashLogExtendEvent (&mEdkiiTcgPpi
, 0, (UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
, (UINT8
*)&EventData
);
1017 Entry point of this module.
1019 @param[in] FileHandle Handle of the file being invoked.
1020 @param[in] PeiServices Describes the list of possible PEI Services.
1028 IN EFI_PEI_FILE_HANDLE FileHandle
,
1029 IN CONST EFI_PEI_SERVICES
**PeiServices
1034 EFI_BOOT_MODE BootMode
;
1035 TPM_PCRINDEX PcrIndex
;
1036 BOOLEAN S3ErrorReport
;
1038 if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
1039 CompareGuid (PcdGetPtr (PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
))
1041 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
1042 return EFI_UNSUPPORTED
;
1045 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1046 DEBUG ((DEBUG_ERROR
, "TPM2 error!\n"));
1047 return EFI_DEVICE_ERROR
;
1050 Status
= PeiServicesGetBootMode (&BootMode
);
1051 ASSERT_EFI_ERROR (Status
);
1054 // In S3 path, skip shadow logic. no measurement is required
1056 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1057 Status
= (**PeiServices
).RegisterForShadow (FileHandle
);
1058 if (Status
== EFI_ALREADY_STARTED
) {
1059 mImageInMemory
= TRUE
;
1060 mFileHandle
= FileHandle
;
1061 } else if (Status
== EFI_NOT_FOUND
) {
1062 ASSERT_EFI_ERROR (Status
);
1066 if (!mImageInMemory
) {
1068 // Initialize TPM device
1070 Status
= Tpm2RequestUseTpm ();
1071 if (EFI_ERROR (Status
)) {
1072 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
1076 S3ErrorReport
= FALSE
;
1077 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
1078 if (BootMode
== BOOT_ON_S3_RESUME
) {
1079 Status
= Tpm2Startup (TPM_SU_STATE
);
1080 if (EFI_ERROR (Status
)) {
1081 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1082 if (!EFI_ERROR (Status
)) {
1083 S3ErrorReport
= TRUE
;
1087 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1090 if (EFI_ERROR (Status
)) {
1096 // Update Tpm2HashMask according to PCR bank.
1098 SyncPcrAllocationsAndPcrMask ();
1100 if (S3ErrorReport
) {
1102 // The system firmware that resumes from S3 MUST deal with a
1103 // TPM2_Startup error appropriately.
1104 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
1105 // configuring the device securely by taking actions like extending a
1106 // separator with an error digest (0x01) into PCRs 0 through 7.
1108 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1109 Status
= MeasureSeparatorEventWithError (PcrIndex
);
1110 if (EFI_ERROR (Status
)) {
1111 DEBUG ((DEBUG_ERROR
, "Separator Event with Error not Measured. Error!\n"));
1117 // TpmSelfTest is optional on S3 path, skip it to save S3 time
1119 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1120 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
1121 Status
= Tpm2SelfTest (NO
);
1122 if (EFI_ERROR (Status
)) {
1128 DEBUG_CODE_BEGIN ();
1130 // Peek into TPM PCR 00 before any BIOS measurement.
1132 Tpm2PcrReadForActiveBank (00, NULL
);
1136 // Only install TpmInitializedPpi on success
1138 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
1139 ASSERT_EFI_ERROR (Status
);
1142 if (mImageInMemory
) {
1143 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
1148 if (EFI_ERROR (Status
)) {
1149 DEBUG ((DEBUG_ERROR
, "TPM2 error! Build Hob\n"));
1150 BuildGuidHob (&gTpmErrorHobGuid
, 0);
1151 REPORT_STATUS_CODE (
1152 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1153 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
1158 // Always install TpmInitializationDonePpi no matter success or fail.
1159 // Other driver can know TPM initialization state by TpmInitializedPpi.
1161 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
1162 ASSERT_EFI_ERROR (Status2
);