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 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <IndustryStandard/UefiTcgPlatform.h>
19 #include <Ppi/FirmwareVolumeInfo.h>
20 #include <Ppi/FirmwareVolumeInfo2.h>
21 #include <Ppi/TpmInitialized.h>
22 #include <Ppi/FirmwareVolume.h>
23 #include <Ppi/EndOfPeiPhase.h>
24 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
25 #include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
27 #include <Guid/TcgEventHob.h>
28 #include <Guid/MeasuredFvHob.h>
29 #include <Guid/TpmInstance.h>
31 #include <Library/DebugLib.h>
32 #include <Library/BaseMemoryLib.h>
33 #include <Library/PeiServicesLib.h>
34 #include <Library/PeimEntryPoint.h>
35 #include <Library/Tpm2CommandLib.h>
36 #include <Library/Tpm2DeviceLib.h>
37 #include <Library/HashLib.h>
38 #include <Library/HobLib.h>
39 #include <Library/PcdLib.h>
40 #include <Library/PeiServicesTablePointerLib.h>
41 #include <Protocol/Tcg2Protocol.h>
42 #include <Library/PerformanceLib.h>
43 #include <Library/MemoryAllocationLib.h>
44 #include <Library/ReportStatusCodeLib.h>
45 #include <Library/ResetSystemLib.h>
47 #define PERF_ID_TCG2_PEI 0x3080
51 EFI_TCG2_EVENT_LOG_FORMAT LogFormat
;
52 } TCG2_EVENT_INFO_STRUCT
;
54 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo
[] = {
55 {&gTcgEventEntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
},
56 {&gTcgEvent2EntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
},
59 BOOLEAN mImageInMemory
= FALSE
;
60 EFI_PEI_FILE_HANDLE mFileHandle
;
62 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
63 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
64 &gPeiTpmInitializedPpiGuid
,
68 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
69 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
70 &gPeiTpmInitializationDonePpiGuid
,
74 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
75 UINT32 mMeasuredBaseFvIndex
= 0;
77 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
78 UINT32 mMeasuredChildFvIndex
= 0;
81 Measure and record the Firmware Volum Information once FvInfoPPI install.
83 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
84 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
85 @param[in] Ppi Address of the PPI that was installed.
87 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
88 @return Others Fail to measure FV.
93 FirmwareVolmeInfoPpiNotifyCallback (
94 IN EFI_PEI_SERVICES
**PeiServices
,
95 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
100 Record all measured Firmware Volum Information into a Guid Hob
102 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
103 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
104 @param[in] Ppi Address of the PPI that was installed.
106 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
107 @return Others Fail to measure FV.
112 EndofPeiSignalNotifyCallBack (
113 IN EFI_PEI_SERVICES
**PeiServices
,
114 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
118 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
120 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
121 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
122 FirmwareVolmeInfoPpiNotifyCallback
125 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
126 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
127 FirmwareVolmeInfoPpiNotifyCallback
130 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
131 &gEfiEndOfPeiSignalPpiGuid
,
132 EndofPeiSignalNotifyCallBack
138 Record all measured Firmware Volum Information into a Guid Hob
139 Guid Hob payload layout is
141 UINT32 *************************** FIRMWARE_BLOB number
142 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
144 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
145 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
146 @param[in] Ppi Address of the PPI that was installed.
148 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
149 @return Others Fail to measure FV.
154 EndofPeiSignalNotifyCallBack (
155 IN EFI_PEI_SERVICES
**PeiServices
,
156 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
160 MEASURED_HOB_DATA
*MeasuredHobData
;
162 MeasuredHobData
= NULL
;
164 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid
);
167 // Create a Guid hob to save all measured Fv
169 MeasuredHobData
= BuildGuidHob(
171 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
174 if (MeasuredHobData
!= NULL
){
176 // Save measured FV info enty number
178 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
181 // Save measured base Fv info
183 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
186 // Save measured child Fv info
188 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
191 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid
);
197 Make sure that the current PCR allocations, the TPM supported PCRs,
198 and the PcdTpm2HashMask are all in agreement.
201 SyncPcrAllocationsAndPcrMask (
206 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
207 UINT32 TpmActivePcrBanks
;
208 UINT32 NewTpmActivePcrBanks
;
210 UINT32 NewTpm2PcrMask
;
212 DEBUG ((EFI_D_ERROR
, "SyncPcrAllocationsAndPcrMask!\n"));
215 // Determine the current TPM support and the Platform PCR mask.
217 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &TpmActivePcrBanks
);
218 ASSERT_EFI_ERROR (Status
);
220 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
221 if (Tpm2PcrMask
== 0) {
223 // if PcdTPm2HashMask is zero, use ActivePcr setting
225 PcdSet32S (PcdTpm2HashMask
, TpmActivePcrBanks
);
226 Tpm2PcrMask
= TpmActivePcrBanks
;
230 // Find the intersection of Pcd support and TPM support.
231 // If banks are missing from the TPM support that are in the PCD, update the PCD.
232 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
236 // If there are active PCR banks that are not supported by the Platform mask,
237 // update the TPM allocations and reboot the machine.
239 if ((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) {
240 NewTpmActivePcrBanks
= TpmActivePcrBanks
& Tpm2PcrMask
;
242 DEBUG ((EFI_D_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
243 if (NewTpmActivePcrBanks
== 0) {
244 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
247 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
248 if (EFI_ERROR (Status
)) {
250 // We can't do much here, but we hope that this doesn't happen.
252 DEBUG ((EFI_D_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
253 ASSERT_EFI_ERROR (Status
);
256 // Need reset system, since we just called Tpm2PcrAllocateBanks().
263 // If there are any PCRs that claim support in the Platform mask that are
264 // not supported by the TPM, update the mask.
266 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
267 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
269 DEBUG ((EFI_D_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
270 if (NewTpm2PcrMask
== 0) {
271 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
275 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
276 ASSERT_EFI_ERROR (Status
);
281 Add a new entry to the Event Log.
283 @param[in] DigestList A list of digest.
284 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
285 @param[in] NewEventData Pointer to the new event data.
287 @retval EFI_SUCCESS The new event log entry was added.
288 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
292 IN TPML_DIGEST_VALUES
*DigestList
,
293 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
294 IN UINT8
*NewEventData
300 EFI_STATUS RetStatus
;
301 UINT32 SupportedEventLogs
;
302 TCG_PCR_EVENT2
*TcgPcrEvent2
;
305 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
307 RetStatus
= EFI_SUCCESS
;
308 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
309 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
310 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
311 switch (mTcg2EventInfo
[Index
].LogFormat
) {
312 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
313 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
314 if (!EFI_ERROR (Status
)) {
315 HobData
= BuildGuidHob (
316 &gTcgEventEntryHobGuid
,
317 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
319 if (HobData
== NULL
) {
320 RetStatus
= EFI_OUT_OF_RESOURCES
;
324 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
325 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
326 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
329 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
331 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
332 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
334 HobData
= BuildGuidHob (
335 &gTcgEvent2EntryHobGuid
,
336 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
338 if (HobData
== NULL
) {
339 RetStatus
= EFI_OUT_OF_RESOURCES
;
343 TcgPcrEvent2
= HobData
;
344 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
345 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
346 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
347 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
348 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
349 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
350 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
360 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
361 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
362 added into the Event Log.
364 @param[in] Flags Bitmap providing additional information.
365 @param[in] HashData Physical address of the start of the data buffer
366 to be hashed, extended, and logged.
367 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
368 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
369 @param[in] NewEventData Pointer to the new event data.
371 @retval EFI_SUCCESS Operation completed successfully.
372 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
373 @retval EFI_DEVICE_ERROR The command was unsuccessful.
380 IN UINTN HashDataLen
,
381 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
382 IN UINT8
*NewEventData
386 TPML_DIGEST_VALUES DigestList
;
388 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
389 return EFI_DEVICE_ERROR
;
392 Status
= HashAndExtend (
393 NewEventHdr
->PCRIndex
,
398 if (!EFI_ERROR (Status
)) {
399 if ((Flags
& EFI_TCG2_EXTEND_ONLY
) == 0) {
400 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
404 if (Status
== EFI_DEVICE_ERROR
) {
405 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
406 BuildGuidHob (&gTpmErrorHobGuid
,0);
408 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
409 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
417 Measure CRTM version.
419 @retval EFI_SUCCESS Operation completed successfully.
420 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
421 @retval EFI_DEVICE_ERROR The command was unsuccessful.
429 TCG_PCR_EVENT_HDR TcgEventHdr
;
432 // Use FirmwareVersion string to represent CRTM version.
433 // OEMs should get real CRTM version string and measure it.
436 TcgEventHdr
.PCRIndex
= 0;
437 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
438 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
440 return HashLogExtendEvent (
442 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
443 TcgEventHdr
.EventSize
,
445 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
451 Add it into the measured FV list after the FV is measured successfully.
453 @param[in] FvBase Base address of FV image.
454 @param[in] FvLength Length of FV image.
456 @retval EFI_SUCCESS Fv image is measured successfully
457 or it has been already measured.
458 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
459 @retval EFI_DEVICE_ERROR The command was unsuccessful.
464 IN EFI_PHYSICAL_ADDRESS FvBase
,
470 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
471 TCG_PCR_EVENT_HDR TcgEventHdr
;
474 TPML_DIGEST_VALUES DigestList
;
476 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
477 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
478 HASH_INFO
*PreHashInfo
;
482 // Check Excluded FV list
486 Status
= PeiServicesLocatePpi(
487 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
490 (VOID
**)&MeasurementExcludedFvPpi
492 if (!EFI_ERROR(Status
)) {
493 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
494 if (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
495 && MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
) {
496 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
497 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
504 } while (!EFI_ERROR(Status
));
507 // Check measured FV list
509 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
510 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
&& mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
) {
511 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
512 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
518 // Check pre-hashed FV list
521 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
523 Status
= PeiServicesLocatePpi (
524 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
527 (VOID
**)&PrehashedFvPpi
529 if (!EFI_ERROR(Status
) && PrehashedFvPpi
->FvBase
== FvBase
&& PrehashedFvPpi
->FvLength
== FvLength
) {
530 ZeroMem (&DigestList
, sizeof(TPML_DIGEST_VALUES
));
533 // The FV is prehashed, check against TPM hash mask
535 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
536 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
537 DEBUG((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
538 HashAlgoMask
= GetHashMaskFromAlgo(PreHashInfo
->HashAlgoId
);
539 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
541 // Hash is required, copy it to DigestList
543 WriteUnaligned16(&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
545 &DigestList
.digests
[DigestCount
].digest
,
547 PreHashInfo
->HashSize
551 // Clean the corresponding Hash Algo mask bit
553 Tpm2HashMask
&= ~HashAlgoMask
;
555 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
558 WriteUnaligned32(&DigestList
.count
, DigestCount
);
563 } while (!EFI_ERROR(Status
));
566 // Init the log event for FV measurement
568 FvBlob
.BlobBase
= FvBase
;
569 FvBlob
.BlobLength
= FvLength
;
570 TcgEventHdr
.PCRIndex
= 0;
571 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
572 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
574 if (Tpm2HashMask
== 0) {
576 // FV pre-hash algos comply with current TPM hash requirement
577 // Skip hashing step in measure, only extend DigestList to PCR and log event
579 Status
= Tpm2PcrExtend(
584 if (!EFI_ERROR(Status
)) {
585 Status
= LogHashEvent (&DigestList
, &TcgEventHdr
, (UINT8
*) &FvBlob
);
586 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
587 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
588 } else if (Status
== EFI_DEVICE_ERROR
) {
589 BuildGuidHob (&gTpmErrorHobGuid
,0);
591 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
592 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
597 // Hash the FV, extend digest to the TPM and log TCG event
599 Status
= HashLogExtendEvent (
601 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
602 (UINTN
) FvBlob
.BlobLength
,
606 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
607 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
610 if (EFI_ERROR(Status
)) {
611 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
616 // Add new FV into the measured FV list.
618 ASSERT (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
619 if (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
620 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
621 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
622 mMeasuredBaseFvIndex
++;
631 @retval EFI_SUCCESS Operation completed successfully.
632 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
633 @retval EFI_DEVICE_ERROR The command was unsuccessful.
642 EFI_PEI_FV_HANDLE VolumeHandle
;
643 EFI_FV_INFO VolumeInfo
;
644 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
646 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
649 // Only measure BFV at the very beginning. Other parts of Static Core Root of
650 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
651 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
652 // reported by platform will be installed with Fv Info Ppi
653 // This firmware volume measure policy can be modified/enhanced by special
654 // platform for special CRTM TPM measuring.
656 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
657 ASSERT_EFI_ERROR (Status
);
660 // Measure and record the firmware volume that is dispatched by PeiCore
662 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
663 ASSERT_EFI_ERROR (Status
);
665 // Locate the corresponding FV_PPI according to founded FV's format guid
667 Status
= PeiServicesLocatePpi (
668 &VolumeInfo
.FvFormat
,
673 ASSERT_EFI_ERROR (Status
);
675 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
677 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
683 Measure and record the Firmware Volum Information once FvInfoPPI install.
685 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
686 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
687 @param[in] Ppi Address of the PPI that was installed.
689 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
690 @return Others Fail to measure FV.
695 FirmwareVolmeInfoPpiNotifyCallback (
696 IN EFI_PEI_SERVICES
**PeiServices
,
697 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
701 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
703 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
706 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
709 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
711 Status
= PeiServicesLocatePpi (
717 if (EFI_ERROR (Status
)) {
722 // This is an FV from an FFS file, and the parent FV must have already been measured,
723 // No need to measure twice, so just record the FV and return
725 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
727 ASSERT (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
728 if (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
730 // Check whether FV is in the measured child FV list.
732 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
733 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
737 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
738 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
739 mMeasuredChildFvIndex
++;
744 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
748 Do measurement after memory is ready.
750 @param[in] PeiServices Describes the list of possible PEI Services.
752 @retval EFI_SUCCESS Operation completed successfully.
753 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
754 @retval EFI_DEVICE_ERROR The command was unsuccessful.
759 IN EFI_PEI_SERVICES
**PeiServices
764 mMeasuredBaseFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
765 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
766 mMeasuredChildFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
767 ASSERT (mMeasuredChildFvInfo
!= NULL
);
769 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
770 Status
= MeasureCRTMVersion ();
773 Status
= MeasureMainBios ();
774 if (EFI_ERROR(Status
)) {
780 // for the FvInfoPpi services to measure and record
781 // the additional Fvs to TPM
783 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
784 ASSERT_EFI_ERROR (Status
);
790 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
792 @param[in] PCRIndex PCR index.
794 @retval EFI_SUCCESS Operation completed successfully.
795 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
799 MeasureSeparatorEventWithError (
800 IN TPM_PCRINDEX PCRIndex
803 TCG_PCR_EVENT_HDR TcgEvent
;
807 // Use EventData 0x1 to indicate there is error.
810 TcgEvent
.PCRIndex
= PCRIndex
;
811 TcgEvent
.EventType
= EV_SEPARATOR
;
812 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
813 return HashLogExtendEvent(0,(UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
817 Entry point of this module.
819 @param[in] FileHandle Handle of the file being invoked.
820 @param[in] PeiServices Describes the list of possible PEI Services.
828 IN EFI_PEI_FILE_HANDLE FileHandle
,
829 IN CONST EFI_PEI_SERVICES
**PeiServices
834 EFI_BOOT_MODE BootMode
;
835 TPM_PCRINDEX PcrIndex
;
836 BOOLEAN S3ErrorReport
;
838 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
839 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
840 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
841 return EFI_UNSUPPORTED
;
844 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
845 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
846 return EFI_DEVICE_ERROR
;
849 Status
= PeiServicesGetBootMode (&BootMode
);
850 ASSERT_EFI_ERROR (Status
);
853 // In S3 path, skip shadow logic. no measurement is required
855 if (BootMode
!= BOOT_ON_S3_RESUME
) {
856 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
857 if (Status
== EFI_ALREADY_STARTED
) {
858 mImageInMemory
= TRUE
;
859 mFileHandle
= FileHandle
;
860 } else if (Status
== EFI_NOT_FOUND
) {
861 ASSERT_EFI_ERROR (Status
);
865 if (!mImageInMemory
) {
867 // Initialize TPM device
869 Status
= Tpm2RequestUseTpm ();
870 if (EFI_ERROR (Status
)) {
871 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
875 S3ErrorReport
= FALSE
;
876 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
877 if (BootMode
== BOOT_ON_S3_RESUME
) {
878 Status
= Tpm2Startup (TPM_SU_STATE
);
879 if (EFI_ERROR (Status
) ) {
880 Status
= Tpm2Startup (TPM_SU_CLEAR
);
881 if (!EFI_ERROR(Status
)) {
882 S3ErrorReport
= TRUE
;
886 Status
= Tpm2Startup (TPM_SU_CLEAR
);
888 if (EFI_ERROR (Status
) ) {
894 // Update Tpm2HashMask according to PCR bank.
896 SyncPcrAllocationsAndPcrMask ();
900 // The system firmware that resumes from S3 MUST deal with a
901 // TPM2_Startup error appropriately.
902 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
903 // configuring the device securely by taking actions like extending a
904 // separator with an error digest (0x01) into PCRs 0 through 7.
906 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
907 Status
= MeasureSeparatorEventWithError (PcrIndex
);
908 if (EFI_ERROR (Status
)) {
909 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
915 // TpmSelfTest is optional on S3 path, skip it to save S3 time
917 if (BootMode
!= BOOT_ON_S3_RESUME
) {
918 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
919 Status
= Tpm2SelfTest (NO
);
920 if (EFI_ERROR (Status
)) {
927 // Only intall TpmInitializedPpi on success
929 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
930 ASSERT_EFI_ERROR (Status
);
933 if (mImageInMemory
) {
934 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
939 if (EFI_ERROR (Status
)) {
940 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
941 BuildGuidHob (&gTpmErrorHobGuid
,0);
943 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
944 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
948 // Always intall TpmInitializationDonePpi no matter success or fail.
949 // Other driver can know TPM initialization state by TpmInitializedPpi.
951 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
952 ASSERT_EFI_ERROR (Status2
);