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>
40 #include <Library/PrintLib.h>
42 #define PERF_ID_TCG2_PEI 0x3080
46 EFI_TCG2_EVENT_LOG_FORMAT LogFormat
;
47 } TCG2_EVENT_INFO_STRUCT
;
49 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo
[] = {
50 {&gTcgEventEntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
},
51 {&gTcgEvent2EntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
},
54 BOOLEAN mImageInMemory
= FALSE
;
55 EFI_PEI_FILE_HANDLE mFileHandle
;
57 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
58 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
59 &gPeiTpmInitializedPpiGuid
,
63 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
64 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
65 &gPeiTpmInitializationDonePpiGuid
,
70 // Number of firmware blobs to grow by each time we run out of room
72 #define FIRMWARE_BLOB_GROWTH_STEP 4
74 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
75 UINT32 mMeasuredMaxBaseFvIndex
= 0;
76 UINT32 mMeasuredBaseFvIndex
= 0;
78 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
79 UINT32 mMeasuredMaxChildFvIndex
= 0;
80 UINT32 mMeasuredChildFvIndex
= 0;
84 #define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"
86 UINT8 BlobDescriptionSize
;
87 UINT8 BlobDescription
[sizeof(FV_HANDOFF_TABLE_DESC
)];
88 EFI_PHYSICAL_ADDRESS BlobBase
;
90 } FV_HANDOFF_TABLE_POINTERS2
;
95 Measure and record the Firmware Volume Information once FvInfoPPI install.
97 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
98 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
99 @param[in] Ppi Address of the PPI that was installed.
101 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
102 @return Others Fail to measure FV.
107 FirmwareVolumeInfoPpiNotifyCallback (
108 IN EFI_PEI_SERVICES
**PeiServices
,
109 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
114 Record all measured Firmware Volume Information into a Guid Hob
116 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
117 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
118 @param[in] Ppi Address of the PPI that was installed.
120 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
121 @return Others Fail to measure FV.
126 EndofPeiSignalNotifyCallBack (
127 IN EFI_PEI_SERVICES
**PeiServices
,
128 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
132 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
134 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
135 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
136 FirmwareVolumeInfoPpiNotifyCallback
139 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
140 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
141 FirmwareVolumeInfoPpiNotifyCallback
144 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
145 &gEfiEndOfPeiSignalPpiGuid
,
146 EndofPeiSignalNotifyCallBack
152 Record all measured Firmware Volume Information into a Guid Hob
153 Guid Hob payload layout is
155 UINT32 *************************** FIRMWARE_BLOB number
156 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
158 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
159 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
160 @param[in] Ppi Address of the PPI that was installed.
162 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
163 @return Others Fail to measure FV.
168 EndofPeiSignalNotifyCallBack (
169 IN EFI_PEI_SERVICES
**PeiServices
,
170 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
174 MEASURED_HOB_DATA
*MeasuredHobData
;
176 MeasuredHobData
= NULL
;
178 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid
);
181 // Create a Guid hob to save all measured Fv
183 MeasuredHobData
= BuildGuidHob(
185 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
188 if (MeasuredHobData
!= NULL
){
190 // Save measured FV info enty number
192 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
195 // Save measured base Fv info
197 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
200 // Save measured child Fv info
202 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
205 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid
);
211 Make sure that the current PCR allocations, the TPM supported PCRs,
212 and the PcdTpm2HashMask are all in agreement.
215 SyncPcrAllocationsAndPcrMask (
220 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
221 UINT32 TpmActivePcrBanks
;
222 UINT32 NewTpmActivePcrBanks
;
224 UINT32 NewTpm2PcrMask
;
226 DEBUG ((EFI_D_ERROR
, "SyncPcrAllocationsAndPcrMask!\n"));
229 // Determine the current TPM support and the Platform PCR mask.
231 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &TpmActivePcrBanks
);
232 ASSERT_EFI_ERROR (Status
);
234 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
235 if (Tpm2PcrMask
== 0) {
237 // if PcdTPm2HashMask is zero, use ActivePcr setting
239 PcdSet32S (PcdTpm2HashMask
, TpmActivePcrBanks
);
240 Tpm2PcrMask
= TpmActivePcrBanks
;
244 // Find the intersection of Pcd support and TPM support.
245 // If banks are missing from the TPM support that are in the PCD, update the PCD.
246 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
250 // If there are active PCR banks that are not supported by the Platform mask,
251 // update the TPM allocations and reboot the machine.
253 if ((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) {
254 NewTpmActivePcrBanks
= TpmActivePcrBanks
& Tpm2PcrMask
;
256 DEBUG ((EFI_D_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
257 if (NewTpmActivePcrBanks
== 0) {
258 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
261 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
262 if (EFI_ERROR (Status
)) {
264 // We can't do much here, but we hope that this doesn't happen.
266 DEBUG ((EFI_D_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
267 ASSERT_EFI_ERROR (Status
);
270 // Need reset system, since we just called Tpm2PcrAllocateBanks().
277 // If there are any PCRs that claim support in the Platform mask that are
278 // not supported by the TPM, update the mask.
280 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
281 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
283 DEBUG ((EFI_D_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
284 if (NewTpm2PcrMask
== 0) {
285 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
289 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
290 ASSERT_EFI_ERROR (Status
);
295 Add a new entry to the Event Log.
297 @param[in] DigestList A list of digest.
298 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
299 @param[in] NewEventData Pointer to the new event data.
301 @retval EFI_SUCCESS The new event log entry was added.
302 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
306 IN TPML_DIGEST_VALUES
*DigestList
,
307 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
308 IN UINT8
*NewEventData
314 EFI_STATUS RetStatus
;
315 UINT32 SupportedEventLogs
;
316 TCG_PCR_EVENT2
*TcgPcrEvent2
;
319 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
321 RetStatus
= EFI_SUCCESS
;
322 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
323 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
324 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
325 switch (mTcg2EventInfo
[Index
].LogFormat
) {
326 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
327 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
328 if (!EFI_ERROR (Status
)) {
329 HobData
= BuildGuidHob (
330 &gTcgEventEntryHobGuid
,
331 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
333 if (HobData
== NULL
) {
334 RetStatus
= EFI_OUT_OF_RESOURCES
;
338 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
339 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
340 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
343 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
345 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
346 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
348 HobData
= BuildGuidHob (
349 &gTcgEvent2EntryHobGuid
,
350 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
352 if (HobData
== NULL
) {
353 RetStatus
= EFI_OUT_OF_RESOURCES
;
357 TcgPcrEvent2
= HobData
;
358 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
359 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
360 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
361 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
362 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
363 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
364 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
374 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
375 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
376 added into the Event Log.
378 @param[in] Flags Bitmap providing additional information.
379 @param[in] HashData Physical address of the start of the data buffer
380 to be hashed, extended, and logged.
381 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
382 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
383 @param[in] NewEventData Pointer to the new event data.
385 @retval EFI_SUCCESS Operation completed successfully.
386 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
387 @retval EFI_DEVICE_ERROR The command was unsuccessful.
394 IN UINTN HashDataLen
,
395 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
396 IN UINT8
*NewEventData
400 TPML_DIGEST_VALUES DigestList
;
402 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
403 return EFI_DEVICE_ERROR
;
406 Status
= HashAndExtend (
407 NewEventHdr
->PCRIndex
,
412 if (!EFI_ERROR (Status
)) {
413 if ((Flags
& EFI_TCG2_EXTEND_ONLY
) == 0) {
414 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
418 if (Status
== EFI_DEVICE_ERROR
) {
419 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
420 BuildGuidHob (&gTpmErrorHobGuid
,0);
422 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
423 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
431 Measure CRTM version.
433 @retval EFI_SUCCESS Operation completed successfully.
434 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
435 @retval EFI_DEVICE_ERROR The command was unsuccessful.
443 TCG_PCR_EVENT_HDR TcgEventHdr
;
446 // Use FirmwareVersion string to represent CRTM version.
447 // OEMs should get real CRTM version string and measure it.
450 TcgEventHdr
.PCRIndex
= 0;
451 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
452 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
454 return HashLogExtendEvent (
456 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
457 TcgEventHdr
.EventSize
,
459 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
464 Get the FvName from the FV header.
466 Causion: The FV is untrusted input.
468 @param[in] FvBase Base address of FV image.
469 @param[in] FvLength Length of FV image.
471 @return FvName pointer
472 @retval NULL FvName is NOT found
476 IN EFI_PHYSICAL_ADDRESS FvBase
,
480 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
481 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
483 if (FvBase
>= MAX_ADDRESS
) {
486 if (FvLength
>= MAX_ADDRESS
- FvBase
) {
489 if (FvLength
< sizeof(EFI_FIRMWARE_VOLUME_HEADER
)) {
493 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
494 if (FvHeader
->ExtHeaderOffset
< sizeof(EFI_FIRMWARE_VOLUME_HEADER
)) {
497 if (FvHeader
->ExtHeaderOffset
+ sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER
) > FvLength
) {
500 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(UINTN
)(FvBase
+ FvHeader
->ExtHeaderOffset
);
502 return &FvExtHeader
->FvName
;
507 Add it into the measured FV list after the FV is measured successfully.
509 @param[in] FvBase Base address of FV image.
510 @param[in] FvLength Length of FV image.
512 @retval EFI_SUCCESS Fv image is measured successfully
513 or it has been already measured.
514 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
515 @retval EFI_DEVICE_ERROR The command was unsuccessful.
520 IN EFI_PHYSICAL_ADDRESS FvBase
,
526 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
527 FV_HANDOFF_TABLE_POINTERS2 FvBlob2
;
530 TCG_PCR_EVENT_HDR TcgEventHdr
;
533 TPML_DIGEST_VALUES DigestList
;
535 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
536 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
537 HASH_INFO
*PreHashInfo
;
541 // Check Excluded FV list
545 Status
= PeiServicesLocatePpi(
546 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
549 (VOID
**)&MeasurementExcludedFvPpi
551 if (!EFI_ERROR(Status
)) {
552 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
553 if (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
554 && MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
) {
555 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
556 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
563 } while (!EFI_ERROR(Status
));
566 // Check measured FV list
568 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
569 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
&& mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
) {
570 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
571 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
577 // Check pre-hashed FV list
580 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
582 Status
= PeiServicesLocatePpi (
583 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
586 (VOID
**)&PrehashedFvPpi
588 if (!EFI_ERROR(Status
) && PrehashedFvPpi
->FvBase
== FvBase
&& PrehashedFvPpi
->FvLength
== FvLength
) {
589 ZeroMem (&DigestList
, sizeof(TPML_DIGEST_VALUES
));
592 // The FV is prehashed, check against TPM hash mask
594 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
595 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
596 DEBUG((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
597 HashAlgoMask
= GetHashMaskFromAlgo(PreHashInfo
->HashAlgoId
);
598 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
600 // Hash is required, copy it to DigestList
602 WriteUnaligned16(&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
604 &DigestList
.digests
[DigestCount
].digest
,
606 PreHashInfo
->HashSize
610 // Clean the corresponding Hash Algo mask bit
612 Tpm2HashMask
&= ~HashAlgoMask
;
614 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
617 WriteUnaligned32(&DigestList
.count
, DigestCount
);
622 } while (!EFI_ERROR(Status
));
625 // Init the log event for FV measurement
627 if (PcdGet32(PcdTcgPfpMeasurementRevision
) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105
) {
628 FvBlob2
.BlobDescriptionSize
= sizeof(FvBlob2
.BlobDescription
);
629 CopyMem (FvBlob2
.BlobDescription
, FV_HANDOFF_TABLE_DESC
, sizeof(FvBlob2
.BlobDescription
));
630 FvName
= GetFvName (FvBase
, FvLength
);
631 if (FvName
!= NULL
) {
632 AsciiSPrint ((CHAR8
*)FvBlob2
.BlobDescription
, sizeof(FvBlob2
.BlobDescription
), "Fv(%g)", FvName
);
634 FvBlob2
.BlobBase
= FvBase
;
635 FvBlob2
.BlobLength
= FvLength
;
636 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB2
;
637 TcgEventHdr
.EventSize
= sizeof (FvBlob2
);
638 EventData
= &FvBlob2
;
640 FvBlob
.BlobBase
= FvBase
;
641 FvBlob
.BlobLength
= FvLength
;
642 TcgEventHdr
.PCRIndex
= 0;
643 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
644 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
648 if (Tpm2HashMask
== 0) {
650 // FV pre-hash algos comply with current TPM hash requirement
651 // Skip hashing step in measure, only extend DigestList to PCR and log event
653 Status
= Tpm2PcrExtend(
658 if (!EFI_ERROR(Status
)) {
659 Status
= LogHashEvent (&DigestList
, &TcgEventHdr
, EventData
);
660 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase
));
661 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength
));
662 } else if (Status
== EFI_DEVICE_ERROR
) {
663 BuildGuidHob (&gTpmErrorHobGuid
,0);
665 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
666 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
671 // Hash the FV, extend digest to the TPM and log TCG event
673 Status
= HashLogExtendEvent (
675 (UINT8
*) (UINTN
) FvBase
, // HashData
676 (UINTN
) FvLength
, // HashDataLen
677 &TcgEventHdr
, // EventHdr
678 EventData
// EventData
680 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
681 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
684 if (EFI_ERROR(Status
)) {
685 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
690 // Add new FV into the measured FV list.
692 if (mMeasuredBaseFvIndex
>= mMeasuredMaxBaseFvIndex
) {
693 mMeasuredBaseFvInfo
= ReallocatePool (
694 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxBaseFvIndex
,
695 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
698 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
699 mMeasuredMaxBaseFvIndex
= mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
702 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
703 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
704 mMeasuredBaseFvIndex
++;
712 @retval EFI_SUCCESS Operation completed successfully.
713 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
714 @retval EFI_DEVICE_ERROR The command was unsuccessful.
723 EFI_PEI_FV_HANDLE VolumeHandle
;
724 EFI_FV_INFO VolumeInfo
;
725 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
727 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
730 // Only measure BFV at the very beginning. Other parts of Static Core Root of
731 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
732 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
733 // reported by platform will be installed with Fv Info Ppi
734 // This firmware volume measure policy can be modified/enhanced by special
735 // platform for special CRTM TPM measuring.
737 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
738 ASSERT_EFI_ERROR (Status
);
741 // Measure and record the firmware volume that is dispatched by PeiCore
743 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
744 ASSERT_EFI_ERROR (Status
);
746 // Locate the corresponding FV_PPI according to founded FV's format guid
748 Status
= PeiServicesLocatePpi (
749 &VolumeInfo
.FvFormat
,
754 ASSERT_EFI_ERROR (Status
);
756 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
758 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
764 Measure and record the Firmware Volume Information once FvInfoPPI install.
766 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
767 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
768 @param[in] Ppi Address of the PPI that was installed.
770 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
771 @return Others Fail to measure FV.
776 FirmwareVolumeInfoPpiNotifyCallback (
777 IN EFI_PEI_SERVICES
**PeiServices
,
778 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
782 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
784 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
787 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
790 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
792 Status
= PeiServicesLocatePpi (
798 if (EFI_ERROR (Status
)) {
803 // This is an FV from an FFS file, and the parent FV must have already been measured,
804 // No need to measure twice, so just record the FV and return
806 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
808 if (mMeasuredChildFvIndex
>= mMeasuredMaxChildFvIndex
) {
809 mMeasuredChildFvInfo
= ReallocatePool (
810 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxChildFvIndex
,
811 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
814 ASSERT (mMeasuredChildFvInfo
!= NULL
);
815 mMeasuredMaxChildFvIndex
= mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
818 // Check whether FV is in the measured child FV list.
820 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
821 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
825 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
826 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
827 mMeasuredChildFvIndex
++;
831 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
835 Do measurement after memory is ready.
837 @param[in] PeiServices Describes the list of possible PEI Services.
839 @retval EFI_SUCCESS Operation completed successfully.
840 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
841 @retval EFI_DEVICE_ERROR The command was unsuccessful.
846 IN EFI_PEI_SERVICES
**PeiServices
851 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
852 Status
= MeasureCRTMVersion ();
855 Status
= MeasureMainBios ();
856 if (EFI_ERROR(Status
)) {
862 // for the FvInfoPpi services to measure and record
863 // the additional Fvs to TPM
865 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
866 ASSERT_EFI_ERROR (Status
);
872 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
874 @param[in] PCRIndex PCR index.
876 @retval EFI_SUCCESS Operation completed successfully.
877 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
881 MeasureSeparatorEventWithError (
882 IN TPM_PCRINDEX PCRIndex
885 TCG_PCR_EVENT_HDR TcgEvent
;
889 // Use EventData 0x1 to indicate there is error.
892 TcgEvent
.PCRIndex
= PCRIndex
;
893 TcgEvent
.EventType
= EV_SEPARATOR
;
894 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
895 return HashLogExtendEvent(0,(UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
899 Entry point of this module.
901 @param[in] FileHandle Handle of the file being invoked.
902 @param[in] PeiServices Describes the list of possible PEI Services.
910 IN EFI_PEI_FILE_HANDLE FileHandle
,
911 IN CONST EFI_PEI_SERVICES
**PeiServices
916 EFI_BOOT_MODE BootMode
;
917 TPM_PCRINDEX PcrIndex
;
918 BOOLEAN S3ErrorReport
;
920 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
921 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
922 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
923 return EFI_UNSUPPORTED
;
926 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
927 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
928 return EFI_DEVICE_ERROR
;
931 Status
= PeiServicesGetBootMode (&BootMode
);
932 ASSERT_EFI_ERROR (Status
);
935 // In S3 path, skip shadow logic. no measurement is required
937 if (BootMode
!= BOOT_ON_S3_RESUME
) {
938 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
939 if (Status
== EFI_ALREADY_STARTED
) {
940 mImageInMemory
= TRUE
;
941 mFileHandle
= FileHandle
;
942 } else if (Status
== EFI_NOT_FOUND
) {
943 ASSERT_EFI_ERROR (Status
);
947 if (!mImageInMemory
) {
949 // Initialize TPM device
951 Status
= Tpm2RequestUseTpm ();
952 if (EFI_ERROR (Status
)) {
953 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
957 S3ErrorReport
= FALSE
;
958 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
959 if (BootMode
== BOOT_ON_S3_RESUME
) {
960 Status
= Tpm2Startup (TPM_SU_STATE
);
961 if (EFI_ERROR (Status
) ) {
962 Status
= Tpm2Startup (TPM_SU_CLEAR
);
963 if (!EFI_ERROR(Status
)) {
964 S3ErrorReport
= TRUE
;
968 Status
= Tpm2Startup (TPM_SU_CLEAR
);
970 if (EFI_ERROR (Status
) ) {
976 // Update Tpm2HashMask according to PCR bank.
978 SyncPcrAllocationsAndPcrMask ();
982 // The system firmware that resumes from S3 MUST deal with a
983 // TPM2_Startup error appropriately.
984 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
985 // configuring the device securely by taking actions like extending a
986 // separator with an error digest (0x01) into PCRs 0 through 7.
988 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
989 Status
= MeasureSeparatorEventWithError (PcrIndex
);
990 if (EFI_ERROR (Status
)) {
991 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
997 // TpmSelfTest is optional on S3 path, skip it to save S3 time
999 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1000 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
1001 Status
= Tpm2SelfTest (NO
);
1002 if (EFI_ERROR (Status
)) {
1009 // Only intall TpmInitializedPpi on success
1011 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
1012 ASSERT_EFI_ERROR (Status
);
1015 if (mImageInMemory
) {
1016 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
1021 if (EFI_ERROR (Status
)) {
1022 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
1023 BuildGuidHob (&gTpmErrorHobGuid
,0);
1024 REPORT_STATUS_CODE (
1025 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1026 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
1030 // Always intall TpmInitializationDonePpi no matter success or fail.
1031 // Other driver can know TPM initialization state by TpmInitializedPpi.
1033 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
1034 ASSERT_EFI_ERROR (Status2
);