2 Initialize TPM2 device and measure FVs before handing off control to DXE.
4 Copyright (c) 2015 - 2020, 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
196 Record all measured Firmware Volume Information into a Guid Hob
197 Guid Hob payload layout is
199 UINT32 *************************** FIRMWARE_BLOB number
200 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
202 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
203 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
204 @param[in] Ppi Address of the PPI that was installed.
206 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
207 @return Others Fail to measure FV.
212 EndofPeiSignalNotifyCallBack (
213 IN EFI_PEI_SERVICES
**PeiServices
,
214 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
218 MEASURED_HOB_DATA
*MeasuredHobData
;
220 MeasuredHobData
= NULL
;
222 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid
);
225 // Create a Guid hob to save all measured Fv
227 MeasuredHobData
= BuildGuidHob(
229 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
232 if (MeasuredHobData
!= NULL
){
234 // Save measured FV info enty number
236 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
239 // Save measured base Fv info
241 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
244 // Save measured child Fv info
246 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
249 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid
);
255 Make sure that the current PCR allocations, the TPM supported PCRs,
256 and the PcdTpm2HashMask are all in agreement.
259 SyncPcrAllocationsAndPcrMask (
264 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
265 UINT32 TpmActivePcrBanks
;
266 UINT32 NewTpmActivePcrBanks
;
268 UINT32 NewTpm2PcrMask
;
270 DEBUG ((EFI_D_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 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
279 if (Tpm2PcrMask
== 0) {
281 // if PcdTPm2HashMask is zero, use ActivePcr setting
283 PcdSet32S (PcdTpm2HashMask
, TpmActivePcrBanks
);
284 Tpm2PcrMask
= TpmActivePcrBanks
;
288 // Find the intersection of Pcd support and TPM support.
289 // If banks are missing from the TPM support that are in the PCD, update the PCD.
290 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
294 // If there are active PCR banks that are not supported by the Platform mask,
295 // update the TPM allocations and reboot the machine.
297 if ((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) {
298 NewTpmActivePcrBanks
= TpmActivePcrBanks
& Tpm2PcrMask
;
300 DEBUG ((EFI_D_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
301 if (NewTpmActivePcrBanks
== 0) {
302 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
305 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
306 if (EFI_ERROR (Status
)) {
308 // We can't do much here, but we hope that this doesn't happen.
310 DEBUG ((EFI_D_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
311 ASSERT_EFI_ERROR (Status
);
314 // Need reset system, since we just called Tpm2PcrAllocateBanks().
321 // If there are any PCRs that claim support in the Platform mask that are
322 // not supported by the TPM, update the mask.
324 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
325 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
327 DEBUG ((EFI_D_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
328 if (NewTpm2PcrMask
== 0) {
329 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
333 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
334 ASSERT_EFI_ERROR (Status
);
339 Add a new entry to the Event Log.
341 @param[in] DigestList A list of digest.
342 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
343 @param[in] NewEventData Pointer to the new event data.
345 @retval EFI_SUCCESS The new event log entry was added.
346 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
350 IN TPML_DIGEST_VALUES
*DigestList
,
351 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
352 IN UINT8
*NewEventData
358 EFI_STATUS RetStatus
;
359 UINT32 SupportedEventLogs
;
360 TCG_PCR_EVENT2
*TcgPcrEvent2
;
363 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
365 RetStatus
= EFI_SUCCESS
;
366 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
367 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
368 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
369 switch (mTcg2EventInfo
[Index
].LogFormat
) {
370 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
371 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
372 if (!EFI_ERROR (Status
)) {
373 HobData
= BuildGuidHob (
374 &gTcgEventEntryHobGuid
,
375 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
377 if (HobData
== NULL
) {
378 RetStatus
= EFI_OUT_OF_RESOURCES
;
382 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
383 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
384 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
387 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
389 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
390 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
392 HobData
= BuildGuidHob (
393 &gTcgEvent2EntryHobGuid
,
394 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
396 if (HobData
== NULL
) {
397 RetStatus
= EFI_OUT_OF_RESOURCES
;
401 TcgPcrEvent2
= HobData
;
402 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
403 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
404 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
405 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
406 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
407 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
408 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
418 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
419 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
420 added into the Event Log.
422 @param[in] This Indicates the calling context
423 @param[in] Flags Bitmap providing additional information.
424 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
425 start of the data buffer to be hashed, extended, and logged.
426 If BIT0 of Flags is 1, it is physical address of the
427 start of the pre-hash data buffter to be extended, and logged.
428 The pre-hash data format is TPML_DIGEST_VALUES.
429 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
430 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
431 @param[in] NewEventData Pointer to the new event data.
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.
441 IN EDKII_TCG_PPI
*This
,
444 IN UINTN HashDataLen
,
445 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
446 IN UINT8
*NewEventData
450 TPML_DIGEST_VALUES DigestList
;
452 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
453 return EFI_DEVICE_ERROR
;
456 if ((Flags
& EDKII_TCG_PRE_HASH
) != 0 || (Flags
& EDKII_TCG_PRE_HASH_LOG_ONLY
) != 0) {
457 ZeroMem (&DigestList
, sizeof(DigestList
));
458 CopyMem (&DigestList
, HashData
, sizeof(DigestList
));
459 Status
= EFI_SUCCESS
;
460 if ((Flags
& EDKII_TCG_PRE_HASH
) !=0 ) {
461 Status
= Tpm2PcrExtend (
462 NewEventHdr
->PCRIndex
,
467 Status
= HashAndExtend (
468 NewEventHdr
->PCRIndex
,
474 if (!EFI_ERROR (Status
)) {
475 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
478 if (Status
== EFI_DEVICE_ERROR
) {
479 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
480 BuildGuidHob (&gTpmErrorHobGuid
,0);
482 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
483 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
491 Measure CRTM version.
493 @retval EFI_SUCCESS Operation completed successfully.
494 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
495 @retval EFI_DEVICE_ERROR The command was unsuccessful.
503 TCG_PCR_EVENT_HDR TcgEventHdr
;
506 // Use FirmwareVersion string to represent CRTM version.
507 // OEMs should get real CRTM version string and measure it.
510 TcgEventHdr
.PCRIndex
= 0;
511 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
512 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
514 return HashLogExtendEvent (
517 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
518 TcgEventHdr
.EventSize
,
520 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
525 Get the FvName from the FV header.
527 Causion: The FV is untrusted input.
529 @param[in] FvBase Base address of FV image.
530 @param[in] FvLength Length of FV image.
532 @return FvName pointer
533 @retval NULL FvName is NOT found
537 IN EFI_PHYSICAL_ADDRESS FvBase
,
541 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
542 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
544 if (FvBase
>= MAX_ADDRESS
) {
547 if (FvLength
>= MAX_ADDRESS
- FvBase
) {
550 if (FvLength
< sizeof(EFI_FIRMWARE_VOLUME_HEADER
)) {
554 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
555 if (FvHeader
->ExtHeaderOffset
< sizeof(EFI_FIRMWARE_VOLUME_HEADER
)) {
558 if (FvHeader
->ExtHeaderOffset
+ sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER
) > FvLength
) {
561 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(UINTN
)(FvBase
+ FvHeader
->ExtHeaderOffset
);
563 return &FvExtHeader
->FvName
;
568 Add it into the measured FV list after the FV is measured successfully.
570 @param[in] FvBase Base address of FV image.
571 @param[in] FvLength Length of FV image.
573 @retval EFI_SUCCESS Fv image is measured successfully
574 or it has been already measured.
575 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
576 @retval EFI_DEVICE_ERROR The command was unsuccessful.
581 IN EFI_PHYSICAL_ADDRESS FvBase
,
587 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
588 FV_HANDOFF_TABLE_POINTERS2 FvBlob2
;
591 TCG_PCR_EVENT_HDR TcgEventHdr
;
594 TPML_DIGEST_VALUES DigestList
;
596 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
597 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
598 HASH_INFO
*PreHashInfo
;
600 EFI_PHYSICAL_ADDRESS FvOrgBase
;
601 EFI_PHYSICAL_ADDRESS FvDataBase
;
602 EFI_PEI_HOB_POINTERS Hob
;
603 EDKII_MIGRATED_FV_INFO
*MigratedFvInfo
;
606 // Check Excluded FV list
610 Status
= PeiServicesLocatePpi(
611 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
614 (VOID
**)&MeasurementExcludedFvPpi
616 if (!EFI_ERROR(Status
)) {
617 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
618 if (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
619 && MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
) {
620 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
621 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
628 } while (!EFI_ERROR(Status
));
631 // Check measured FV list
633 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
634 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
&& mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
) {
635 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
636 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
642 // Check pre-hashed FV list
645 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
647 Status
= PeiServicesLocatePpi (
648 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
651 (VOID
**)&PrehashedFvPpi
653 if (!EFI_ERROR(Status
) && PrehashedFvPpi
->FvBase
== FvBase
&& PrehashedFvPpi
->FvLength
== FvLength
) {
654 ZeroMem (&DigestList
, sizeof(TPML_DIGEST_VALUES
));
657 // The FV is prehashed, check against TPM hash mask
659 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
660 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
661 DEBUG((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
662 HashAlgoMask
= GetHashMaskFromAlgo(PreHashInfo
->HashAlgoId
);
663 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
665 // Hash is required, copy it to DigestList
667 WriteUnaligned16(&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
669 &DigestList
.digests
[DigestCount
].digest
,
671 PreHashInfo
->HashSize
675 // Clean the corresponding Hash Algo mask bit
677 Tpm2HashMask
&= ~HashAlgoMask
;
679 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
682 WriteUnaligned32(&DigestList
.count
, DigestCount
);
687 } while (!EFI_ERROR(Status
));
690 // Search the matched migration FV info
694 Hob
.Raw
= GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid
);
695 while (Hob
.Raw
!= NULL
) {
696 MigratedFvInfo
= GET_GUID_HOB_DATA (Hob
);
697 if ((MigratedFvInfo
->FvNewBase
== (UINT32
) FvBase
) && (MigratedFvInfo
->FvLength
== (UINT32
) FvLength
)) {
699 // Found the migrated FV info
701 FvOrgBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) MigratedFvInfo
->FvOrgBase
;
702 FvDataBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) MigratedFvInfo
->FvDataBase
;
705 Hob
.Raw
= GET_NEXT_HOB (Hob
);
706 Hob
.Raw
= GetNextGuidHob (&gEdkiiMigratedFvInfoGuid
, Hob
.Raw
);
710 // Init the log event for FV measurement
712 if (PcdGet32(PcdTcgPfpMeasurementRevision
) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105
) {
713 FvBlob2
.BlobDescriptionSize
= sizeof(FvBlob2
.BlobDescription
);
714 CopyMem (FvBlob2
.BlobDescription
, FV_HANDOFF_TABLE_DESC
, sizeof(FvBlob2
.BlobDescription
));
715 FvName
= GetFvName (FvBase
, FvLength
);
716 if (FvName
!= NULL
) {
717 AsciiSPrint ((CHAR8
*)FvBlob2
.BlobDescription
, sizeof(FvBlob2
.BlobDescription
), "Fv(%g)", FvName
);
719 FvBlob2
.BlobBase
= FvOrgBase
;
720 FvBlob2
.BlobLength
= FvLength
;
721 TcgEventHdr
.PCRIndex
= 0;
722 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB2
;
723 TcgEventHdr
.EventSize
= sizeof (FvBlob2
);
724 EventData
= &FvBlob2
;
726 FvBlob
.BlobBase
= FvOrgBase
;
727 FvBlob
.BlobLength
= FvLength
;
728 TcgEventHdr
.PCRIndex
= 0;
729 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
730 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
734 if (Tpm2HashMask
== 0) {
736 // FV pre-hash algos comply with current TPM hash requirement
737 // Skip hashing step in measure, only extend DigestList to PCR and log event
739 Status
= HashLogExtendEvent (
742 (UINT8
*) &DigestList
, // HashData
743 (UINTN
) sizeof(DigestList
), // HashDataLen
744 &TcgEventHdr
, // EventHdr
745 EventData
// EventData
747 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase
));
748 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength
));
751 // Hash the FV, extend digest to the TPM and log TCG event
753 Status
= HashLogExtendEvent (
756 (UINT8
*) (UINTN
) FvDataBase
, // HashData
757 (UINTN
) FvLength
, // HashDataLen
758 &TcgEventHdr
, // EventHdr
759 EventData
// EventData
761 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
762 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
765 if (EFI_ERROR(Status
)) {
766 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
771 // Add new FV into the measured FV list.
773 if (mMeasuredBaseFvIndex
>= mMeasuredMaxBaseFvIndex
) {
774 mMeasuredBaseFvInfo
= ReallocatePool (
775 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxBaseFvIndex
,
776 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
779 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
780 mMeasuredMaxBaseFvIndex
= mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
783 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
784 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
785 mMeasuredBaseFvIndex
++;
793 @retval EFI_SUCCESS Operation completed successfully.
794 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
795 @retval EFI_DEVICE_ERROR The command was unsuccessful.
804 EFI_PEI_FV_HANDLE VolumeHandle
;
805 EFI_FV_INFO VolumeInfo
;
806 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
808 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
811 // Only measure BFV at the very beginning. Other parts of Static Core Root of
812 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
813 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
814 // reported by platform will be installed with Fv Info Ppi
815 // This firmware volume measure policy can be modified/enhanced by special
816 // platform for special CRTM TPM measuring.
818 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
819 ASSERT_EFI_ERROR (Status
);
822 // Measure and record the firmware volume that is dispatched by PeiCore
824 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
825 ASSERT_EFI_ERROR (Status
);
827 // Locate the corresponding FV_PPI according to founded FV's format guid
829 Status
= PeiServicesLocatePpi (
830 &VolumeInfo
.FvFormat
,
835 ASSERT_EFI_ERROR (Status
);
837 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
839 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
845 Measure and record the Firmware Volume Information once FvInfoPPI install.
847 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
848 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
849 @param[in] Ppi Address of the PPI that was installed.
851 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
852 @return Others Fail to measure FV.
857 FirmwareVolumeInfoPpiNotifyCallback (
858 IN EFI_PEI_SERVICES
**PeiServices
,
859 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
863 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
865 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
868 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
871 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
873 Status
= PeiServicesLocatePpi (
879 if (EFI_ERROR (Status
)) {
884 // This is an FV from an FFS file, and the parent FV must have already been measured,
885 // No need to measure twice, so just record the FV and return
887 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
889 if (mMeasuredChildFvIndex
>= mMeasuredMaxChildFvIndex
) {
890 mMeasuredChildFvInfo
= ReallocatePool (
891 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxChildFvIndex
,
892 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
895 ASSERT (mMeasuredChildFvInfo
!= NULL
);
896 mMeasuredMaxChildFvIndex
= mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
899 // Check whether FV is in the measured child FV list.
901 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
902 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
906 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
907 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
908 mMeasuredChildFvIndex
++;
912 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
916 Do measurement after memory is ready.
918 @param[in] PeiServices Describes the list of possible PEI Services.
920 @retval EFI_SUCCESS Operation completed successfully.
921 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
922 @retval EFI_DEVICE_ERROR The command was unsuccessful.
927 IN EFI_PEI_SERVICES
**PeiServices
933 // install Tcg Services
935 Status
= PeiServicesInstallPpi (&mTcgPpiList
);
936 ASSERT_EFI_ERROR (Status
);
938 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
939 Status
= MeasureCRTMVersion ();
942 Status
= MeasureMainBios ();
943 if (EFI_ERROR(Status
)) {
949 // for the FvInfoPpi services to measure and record
950 // the additional Fvs to TPM
952 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
953 ASSERT_EFI_ERROR (Status
);
959 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
961 @param[in] PCRIndex PCR index.
963 @retval EFI_SUCCESS Operation completed successfully.
964 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
968 MeasureSeparatorEventWithError (
969 IN TPM_PCRINDEX PCRIndex
972 TCG_PCR_EVENT_HDR TcgEvent
;
976 // Use EventData 0x1 to indicate there is error.
979 TcgEvent
.PCRIndex
= PCRIndex
;
980 TcgEvent
.EventType
= EV_SEPARATOR
;
981 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
982 return HashLogExtendEvent(&mEdkiiTcgPpi
, 0, (UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
986 Entry point of this module.
988 @param[in] FileHandle Handle of the file being invoked.
989 @param[in] PeiServices Describes the list of possible PEI Services.
997 IN EFI_PEI_FILE_HANDLE FileHandle
,
998 IN CONST EFI_PEI_SERVICES
**PeiServices
1003 EFI_BOOT_MODE BootMode
;
1004 TPM_PCRINDEX PcrIndex
;
1005 BOOLEAN S3ErrorReport
;
1007 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
1008 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
1009 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
1010 return EFI_UNSUPPORTED
;
1013 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1014 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
1015 return EFI_DEVICE_ERROR
;
1018 Status
= PeiServicesGetBootMode (&BootMode
);
1019 ASSERT_EFI_ERROR (Status
);
1022 // In S3 path, skip shadow logic. no measurement is required
1024 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1025 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
1026 if (Status
== EFI_ALREADY_STARTED
) {
1027 mImageInMemory
= TRUE
;
1028 mFileHandle
= FileHandle
;
1029 } else if (Status
== EFI_NOT_FOUND
) {
1030 ASSERT_EFI_ERROR (Status
);
1034 if (!mImageInMemory
) {
1036 // Initialize TPM device
1038 Status
= Tpm2RequestUseTpm ();
1039 if (EFI_ERROR (Status
)) {
1040 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
1044 S3ErrorReport
= FALSE
;
1045 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
1046 if (BootMode
== BOOT_ON_S3_RESUME
) {
1047 Status
= Tpm2Startup (TPM_SU_STATE
);
1048 if (EFI_ERROR (Status
) ) {
1049 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1050 if (!EFI_ERROR(Status
)) {
1051 S3ErrorReport
= TRUE
;
1055 Status
= Tpm2Startup (TPM_SU_CLEAR
);
1057 if (EFI_ERROR (Status
) ) {
1063 // Update Tpm2HashMask according to PCR bank.
1065 SyncPcrAllocationsAndPcrMask ();
1067 if (S3ErrorReport
) {
1069 // The system firmware that resumes from S3 MUST deal with a
1070 // TPM2_Startup error appropriately.
1071 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
1072 // configuring the device securely by taking actions like extending a
1073 // separator with an error digest (0x01) into PCRs 0 through 7.
1075 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1076 Status
= MeasureSeparatorEventWithError (PcrIndex
);
1077 if (EFI_ERROR (Status
)) {
1078 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
1084 // TpmSelfTest is optional on S3 path, skip it to save S3 time
1086 if (BootMode
!= BOOT_ON_S3_RESUME
) {
1087 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
1088 Status
= Tpm2SelfTest (NO
);
1089 if (EFI_ERROR (Status
)) {
1096 // Only install TpmInitializedPpi on success
1098 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
1099 ASSERT_EFI_ERROR (Status
);
1102 if (mImageInMemory
) {
1103 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
1108 if (EFI_ERROR (Status
)) {
1109 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
1110 BuildGuidHob (&gTpmErrorHobGuid
,0);
1111 REPORT_STATUS_CODE (
1112 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1113 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
1117 // Always install TpmInitializationDonePpi no matter success or fail.
1118 // Other driver can know TPM initialization state by TpmInitializedPpi.
1120 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
1121 ASSERT_EFI_ERROR (Status2
);