2 Initialize TPM2 device and measure FVs before handing off control to DXE.
4 Copyright (c) 2015 - 2018, 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>
21 #include <Guid/TcgEventHob.h>
22 #include <Guid/MeasuredFvHob.h>
23 #include <Guid/TpmInstance.h>
25 #include <Library/DebugLib.h>
26 #include <Library/BaseMemoryLib.h>
27 #include <Library/PeiServicesLib.h>
28 #include <Library/PeimEntryPoint.h>
29 #include <Library/Tpm2CommandLib.h>
30 #include <Library/Tpm2DeviceLib.h>
31 #include <Library/HashLib.h>
32 #include <Library/HobLib.h>
33 #include <Library/PcdLib.h>
34 #include <Library/PeiServicesTablePointerLib.h>
35 #include <Protocol/Tcg2Protocol.h>
36 #include <Library/PerformanceLib.h>
37 #include <Library/MemoryAllocationLib.h>
38 #include <Library/ReportStatusCodeLib.h>
39 #include <Library/ResetSystemLib.h>
41 #define PERF_ID_TCG2_PEI 0x3080
45 EFI_TCG2_EVENT_LOG_FORMAT LogFormat
;
46 } TCG2_EVENT_INFO_STRUCT
;
48 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo
[] = {
49 {&gTcgEventEntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
},
50 {&gTcgEvent2EntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
},
53 BOOLEAN mImageInMemory
= FALSE
;
54 EFI_PEI_FILE_HANDLE mFileHandle
;
56 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
57 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
58 &gPeiTpmInitializedPpiGuid
,
62 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
63 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
64 &gPeiTpmInitializationDonePpiGuid
,
69 // Number of firmware blobs to grow by each time we run out of room
71 #define FIRMWARE_BLOB_GROWTH_STEP 4
73 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
74 UINT32 mMeasuredMaxBaseFvIndex
= 0;
75 UINT32 mMeasuredBaseFvIndex
= 0;
77 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
78 UINT32 mMeasuredMaxChildFvIndex
= 0;
79 UINT32 mMeasuredChildFvIndex
= 0;
82 Measure and record the Firmware Volume Information once FvInfoPPI install.
84 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
85 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
86 @param[in] Ppi Address of the PPI that was installed.
88 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
89 @return Others Fail to measure FV.
94 FirmwareVolumeInfoPpiNotifyCallback (
95 IN EFI_PEI_SERVICES
**PeiServices
,
96 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
101 Record all measured Firmware Volume Information into a Guid Hob
103 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
104 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
105 @param[in] Ppi Address of the PPI that was installed.
107 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
108 @return Others Fail to measure FV.
113 EndofPeiSignalNotifyCallBack (
114 IN EFI_PEI_SERVICES
**PeiServices
,
115 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
119 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
121 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
122 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
123 FirmwareVolumeInfoPpiNotifyCallback
126 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
127 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
128 FirmwareVolumeInfoPpiNotifyCallback
131 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
132 &gEfiEndOfPeiSignalPpiGuid
,
133 EndofPeiSignalNotifyCallBack
139 Record all measured Firmware Volume Information into a Guid Hob
140 Guid Hob payload layout is
142 UINT32 *************************** FIRMWARE_BLOB number
143 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
145 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
146 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
147 @param[in] Ppi Address of the PPI that was installed.
149 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
150 @return Others Fail to measure FV.
155 EndofPeiSignalNotifyCallBack (
156 IN EFI_PEI_SERVICES
**PeiServices
,
157 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
161 MEASURED_HOB_DATA
*MeasuredHobData
;
163 MeasuredHobData
= NULL
;
165 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid
);
168 // Create a Guid hob to save all measured Fv
170 MeasuredHobData
= BuildGuidHob(
172 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
175 if (MeasuredHobData
!= NULL
){
177 // Save measured FV info enty number
179 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
182 // Save measured base Fv info
184 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
187 // Save measured child Fv info
189 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
192 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid
);
198 Make sure that the current PCR allocations, the TPM supported PCRs,
199 and the PcdTpm2HashMask are all in agreement.
202 SyncPcrAllocationsAndPcrMask (
207 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
208 UINT32 TpmActivePcrBanks
;
209 UINT32 NewTpmActivePcrBanks
;
211 UINT32 NewTpm2PcrMask
;
213 DEBUG ((EFI_D_ERROR
, "SyncPcrAllocationsAndPcrMask!\n"));
216 // Determine the current TPM support and the Platform PCR mask.
218 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &TpmActivePcrBanks
);
219 ASSERT_EFI_ERROR (Status
);
221 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
222 if (Tpm2PcrMask
== 0) {
224 // if PcdTPm2HashMask is zero, use ActivePcr setting
226 PcdSet32S (PcdTpm2HashMask
, TpmActivePcrBanks
);
227 Tpm2PcrMask
= TpmActivePcrBanks
;
231 // Find the intersection of Pcd support and TPM support.
232 // If banks are missing from the TPM support that are in the PCD, update the PCD.
233 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
237 // If there are active PCR banks that are not supported by the Platform mask,
238 // update the TPM allocations and reboot the machine.
240 if ((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) {
241 NewTpmActivePcrBanks
= TpmActivePcrBanks
& Tpm2PcrMask
;
243 DEBUG ((EFI_D_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
244 if (NewTpmActivePcrBanks
== 0) {
245 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
248 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
249 if (EFI_ERROR (Status
)) {
251 // We can't do much here, but we hope that this doesn't happen.
253 DEBUG ((EFI_D_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
254 ASSERT_EFI_ERROR (Status
);
257 // Need reset system, since we just called Tpm2PcrAllocateBanks().
264 // If there are any PCRs that claim support in the Platform mask that are
265 // not supported by the TPM, update the mask.
267 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
268 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
270 DEBUG ((EFI_D_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
271 if (NewTpm2PcrMask
== 0) {
272 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
276 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
277 ASSERT_EFI_ERROR (Status
);
282 Add a new entry to the Event Log.
284 @param[in] DigestList A list of digest.
285 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
286 @param[in] NewEventData Pointer to the new event data.
288 @retval EFI_SUCCESS The new event log entry was added.
289 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
293 IN TPML_DIGEST_VALUES
*DigestList
,
294 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
295 IN UINT8
*NewEventData
301 EFI_STATUS RetStatus
;
302 UINT32 SupportedEventLogs
;
303 TCG_PCR_EVENT2
*TcgPcrEvent2
;
306 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
308 RetStatus
= EFI_SUCCESS
;
309 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
310 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
311 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
312 switch (mTcg2EventInfo
[Index
].LogFormat
) {
313 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
314 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
315 if (!EFI_ERROR (Status
)) {
316 HobData
= BuildGuidHob (
317 &gTcgEventEntryHobGuid
,
318 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
320 if (HobData
== NULL
) {
321 RetStatus
= EFI_OUT_OF_RESOURCES
;
325 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
326 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
327 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
330 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
332 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
333 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
335 HobData
= BuildGuidHob (
336 &gTcgEvent2EntryHobGuid
,
337 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
339 if (HobData
== NULL
) {
340 RetStatus
= EFI_OUT_OF_RESOURCES
;
344 TcgPcrEvent2
= HobData
;
345 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
346 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
347 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
348 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
349 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
350 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
351 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
361 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
362 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
363 added into the Event Log.
365 @param[in] Flags Bitmap providing additional information.
366 @param[in] HashData Physical address of the start of the data buffer
367 to be hashed, extended, and logged.
368 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
369 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
370 @param[in] NewEventData Pointer to the new event data.
372 @retval EFI_SUCCESS Operation completed successfully.
373 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
374 @retval EFI_DEVICE_ERROR The command was unsuccessful.
381 IN UINTN HashDataLen
,
382 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
383 IN UINT8
*NewEventData
387 TPML_DIGEST_VALUES DigestList
;
389 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
390 return EFI_DEVICE_ERROR
;
393 Status
= HashAndExtend (
394 NewEventHdr
->PCRIndex
,
399 if (!EFI_ERROR (Status
)) {
400 if ((Flags
& EFI_TCG2_EXTEND_ONLY
) == 0) {
401 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
405 if (Status
== EFI_DEVICE_ERROR
) {
406 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
407 BuildGuidHob (&gTpmErrorHobGuid
,0);
409 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
410 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
418 Measure CRTM version.
420 @retval EFI_SUCCESS Operation completed successfully.
421 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
422 @retval EFI_DEVICE_ERROR The command was unsuccessful.
430 TCG_PCR_EVENT_HDR TcgEventHdr
;
433 // Use FirmwareVersion string to represent CRTM version.
434 // OEMs should get real CRTM version string and measure it.
437 TcgEventHdr
.PCRIndex
= 0;
438 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
439 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
441 return HashLogExtendEvent (
443 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
444 TcgEventHdr
.EventSize
,
446 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
452 Add it into the measured FV list after the FV is measured successfully.
454 @param[in] FvBase Base address of FV image.
455 @param[in] FvLength Length of FV image.
457 @retval EFI_SUCCESS Fv image is measured successfully
458 or it has been already measured.
459 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
460 @retval EFI_DEVICE_ERROR The command was unsuccessful.
465 IN EFI_PHYSICAL_ADDRESS FvBase
,
471 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
472 TCG_PCR_EVENT_HDR TcgEventHdr
;
475 TPML_DIGEST_VALUES DigestList
;
477 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
478 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
479 HASH_INFO
*PreHashInfo
;
483 // Check Excluded FV list
487 Status
= PeiServicesLocatePpi(
488 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
491 (VOID
**)&MeasurementExcludedFvPpi
493 if (!EFI_ERROR(Status
)) {
494 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
495 if (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
496 && MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
) {
497 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
498 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
505 } while (!EFI_ERROR(Status
));
508 // Check measured FV list
510 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
511 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
&& mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
) {
512 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
513 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
519 // Check pre-hashed FV list
522 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
524 Status
= PeiServicesLocatePpi (
525 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
528 (VOID
**)&PrehashedFvPpi
530 if (!EFI_ERROR(Status
) && PrehashedFvPpi
->FvBase
== FvBase
&& PrehashedFvPpi
->FvLength
== FvLength
) {
531 ZeroMem (&DigestList
, sizeof(TPML_DIGEST_VALUES
));
534 // The FV is prehashed, check against TPM hash mask
536 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
537 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
538 DEBUG((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
539 HashAlgoMask
= GetHashMaskFromAlgo(PreHashInfo
->HashAlgoId
);
540 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
542 // Hash is required, copy it to DigestList
544 WriteUnaligned16(&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
546 &DigestList
.digests
[DigestCount
].digest
,
548 PreHashInfo
->HashSize
552 // Clean the corresponding Hash Algo mask bit
554 Tpm2HashMask
&= ~HashAlgoMask
;
556 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
559 WriteUnaligned32(&DigestList
.count
, DigestCount
);
564 } while (!EFI_ERROR(Status
));
567 // Init the log event for FV measurement
569 FvBlob
.BlobBase
= FvBase
;
570 FvBlob
.BlobLength
= FvLength
;
571 TcgEventHdr
.PCRIndex
= 0;
572 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
573 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
575 if (Tpm2HashMask
== 0) {
577 // FV pre-hash algos comply with current TPM hash requirement
578 // Skip hashing step in measure, only extend DigestList to PCR and log event
580 Status
= Tpm2PcrExtend(
585 if (!EFI_ERROR(Status
)) {
586 Status
= LogHashEvent (&DigestList
, &TcgEventHdr
, (UINT8
*) &FvBlob
);
587 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
588 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
589 } else if (Status
== EFI_DEVICE_ERROR
) {
590 BuildGuidHob (&gTpmErrorHobGuid
,0);
592 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
593 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
598 // Hash the FV, extend digest to the TPM and log TCG event
600 Status
= HashLogExtendEvent (
602 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
603 (UINTN
) FvBlob
.BlobLength
,
607 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
608 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
611 if (EFI_ERROR(Status
)) {
612 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
617 // Add new FV into the measured FV list.
619 if (mMeasuredBaseFvIndex
>= mMeasuredMaxBaseFvIndex
) {
620 mMeasuredBaseFvInfo
= ReallocatePool (
621 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxBaseFvIndex
,
622 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
625 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
626 mMeasuredMaxBaseFvIndex
= mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
629 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
630 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
631 mMeasuredBaseFvIndex
++;
639 @retval EFI_SUCCESS Operation completed successfully.
640 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
641 @retval EFI_DEVICE_ERROR The command was unsuccessful.
650 EFI_PEI_FV_HANDLE VolumeHandle
;
651 EFI_FV_INFO VolumeInfo
;
652 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
654 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
657 // Only measure BFV at the very beginning. Other parts of Static Core Root of
658 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
659 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
660 // reported by platform will be installed with Fv Info Ppi
661 // This firmware volume measure policy can be modified/enhanced by special
662 // platform for special CRTM TPM measuring.
664 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
665 ASSERT_EFI_ERROR (Status
);
668 // Measure and record the firmware volume that is dispatched by PeiCore
670 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
671 ASSERT_EFI_ERROR (Status
);
673 // Locate the corresponding FV_PPI according to founded FV's format guid
675 Status
= PeiServicesLocatePpi (
676 &VolumeInfo
.FvFormat
,
681 ASSERT_EFI_ERROR (Status
);
683 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
685 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
691 Measure and record the Firmware Volume Information once FvInfoPPI install.
693 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
694 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
695 @param[in] Ppi Address of the PPI that was installed.
697 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
698 @return Others Fail to measure FV.
703 FirmwareVolumeInfoPpiNotifyCallback (
704 IN EFI_PEI_SERVICES
**PeiServices
,
705 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
709 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
711 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
714 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
717 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
719 Status
= PeiServicesLocatePpi (
725 if (EFI_ERROR (Status
)) {
730 // This is an FV from an FFS file, and the parent FV must have already been measured,
731 // No need to measure twice, so just record the FV and return
733 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
735 if (mMeasuredChildFvIndex
>= mMeasuredMaxChildFvIndex
) {
736 mMeasuredChildFvInfo
= ReallocatePool (
737 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxChildFvIndex
,
738 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
741 ASSERT (mMeasuredChildFvInfo
!= NULL
);
742 mMeasuredMaxChildFvIndex
= mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
745 // Check whether FV is in the measured child FV list.
747 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
748 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
752 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
753 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
754 mMeasuredChildFvIndex
++;
758 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
762 Do measurement after memory is ready.
764 @param[in] PeiServices Describes the list of possible PEI Services.
766 @retval EFI_SUCCESS Operation completed successfully.
767 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
768 @retval EFI_DEVICE_ERROR The command was unsuccessful.
773 IN EFI_PEI_SERVICES
**PeiServices
778 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
779 Status
= MeasureCRTMVersion ();
782 Status
= MeasureMainBios ();
783 if (EFI_ERROR(Status
)) {
789 // for the FvInfoPpi services to measure and record
790 // the additional Fvs to TPM
792 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
793 ASSERT_EFI_ERROR (Status
);
799 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
801 @param[in] PCRIndex PCR index.
803 @retval EFI_SUCCESS Operation completed successfully.
804 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
808 MeasureSeparatorEventWithError (
809 IN TPM_PCRINDEX PCRIndex
812 TCG_PCR_EVENT_HDR TcgEvent
;
816 // Use EventData 0x1 to indicate there is error.
819 TcgEvent
.PCRIndex
= PCRIndex
;
820 TcgEvent
.EventType
= EV_SEPARATOR
;
821 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
822 return HashLogExtendEvent(0,(UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
826 Entry point of this module.
828 @param[in] FileHandle Handle of the file being invoked.
829 @param[in] PeiServices Describes the list of possible PEI Services.
837 IN EFI_PEI_FILE_HANDLE FileHandle
,
838 IN CONST EFI_PEI_SERVICES
**PeiServices
843 EFI_BOOT_MODE BootMode
;
844 TPM_PCRINDEX PcrIndex
;
845 BOOLEAN S3ErrorReport
;
847 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
848 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
849 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
850 return EFI_UNSUPPORTED
;
853 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
854 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
855 return EFI_DEVICE_ERROR
;
858 Status
= PeiServicesGetBootMode (&BootMode
);
859 ASSERT_EFI_ERROR (Status
);
862 // In S3 path, skip shadow logic. no measurement is required
864 if (BootMode
!= BOOT_ON_S3_RESUME
) {
865 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
866 if (Status
== EFI_ALREADY_STARTED
) {
867 mImageInMemory
= TRUE
;
868 mFileHandle
= FileHandle
;
869 } else if (Status
== EFI_NOT_FOUND
) {
870 ASSERT_EFI_ERROR (Status
);
874 if (!mImageInMemory
) {
876 // Initialize TPM device
878 Status
= Tpm2RequestUseTpm ();
879 if (EFI_ERROR (Status
)) {
880 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
884 S3ErrorReport
= FALSE
;
885 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
886 if (BootMode
== BOOT_ON_S3_RESUME
) {
887 Status
= Tpm2Startup (TPM_SU_STATE
);
888 if (EFI_ERROR (Status
) ) {
889 Status
= Tpm2Startup (TPM_SU_CLEAR
);
890 if (!EFI_ERROR(Status
)) {
891 S3ErrorReport
= TRUE
;
895 Status
= Tpm2Startup (TPM_SU_CLEAR
);
897 if (EFI_ERROR (Status
) ) {
903 // Update Tpm2HashMask according to PCR bank.
905 SyncPcrAllocationsAndPcrMask ();
909 // The system firmware that resumes from S3 MUST deal with a
910 // TPM2_Startup error appropriately.
911 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
912 // configuring the device securely by taking actions like extending a
913 // separator with an error digest (0x01) into PCRs 0 through 7.
915 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
916 Status
= MeasureSeparatorEventWithError (PcrIndex
);
917 if (EFI_ERROR (Status
)) {
918 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
924 // TpmSelfTest is optional on S3 path, skip it to save S3 time
926 if (BootMode
!= BOOT_ON_S3_RESUME
) {
927 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
928 Status
= Tpm2SelfTest (NO
);
929 if (EFI_ERROR (Status
)) {
936 // Only intall TpmInitializedPpi on success
938 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
939 ASSERT_EFI_ERROR (Status
);
942 if (mImageInMemory
) {
943 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
948 if (EFI_ERROR (Status
)) {
949 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
950 BuildGuidHob (&gTpmErrorHobGuid
,0);
952 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
953 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
957 // Always intall TpmInitializationDonePpi no matter success or fail.
958 // Other driver can know TPM initialization state by TpmInitializedPpi.
960 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
961 ASSERT_EFI_ERROR (Status2
);