2 Initialize TPM2 device and measure FVs before handing off control to DXE.
4 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <IndustryStandard/UefiTcgPlatform.h>
18 #include <Ppi/FirmwareVolumeInfo.h>
19 #include <Ppi/FirmwareVolumeInfo2.h>
20 #include <Ppi/LockPhysicalPresence.h>
21 #include <Ppi/TpmInitialized.h>
22 #include <Ppi/FirmwareVolume.h>
23 #include <Ppi/EndOfPeiPhase.h>
24 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
26 #include <Guid/TcgEventHob.h>
27 #include <Guid/MeasuredFvHob.h>
28 #include <Guid/TpmInstance.h>
30 #include <Library/DebugLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/PeiServicesLib.h>
33 #include <Library/PeimEntryPoint.h>
34 #include <Library/Tpm2CommandLib.h>
35 #include <Library/Tpm2DeviceLib.h>
36 #include <Library/HashLib.h>
37 #include <Library/HobLib.h>
38 #include <Library/PcdLib.h>
39 #include <Library/PeiServicesTablePointerLib.h>
40 #include <Protocol/Tcg2Protocol.h>
41 #include <Library/PerformanceLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/ReportStatusCodeLib.h>
44 #include <Library/ResetSystemLib.h>
45 #include <Library/Tcg2PhysicalPresenceLib.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
136 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*mMeasurementExcludedFvPpi
;
139 Record all measured Firmware Volum 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
;
166 // Create a Guid hob to save all measured Fv
168 MeasuredHobData
= BuildGuidHob(
170 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
173 if (MeasuredHobData
!= NULL
){
175 // Save measured FV info enty number
177 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
180 // Save measured base Fv info
182 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
185 // Save measured child Fv info
187 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
194 Make sure that the current PCR allocations, the TPM supported PCRs,
195 and the PcdTpm2HashMask are all in agreement.
198 SyncPcrAllocationsAndPcrMask (
203 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
204 UINT32 TpmActivePcrBanks
;
205 UINT32 NewTpmActivePcrBanks
;
207 UINT32 NewTpm2PcrMask
;
209 DEBUG ((EFI_D_ERROR
, "SyncPcrAllocationsAndPcrMask!\n"));
212 // Determine the current TPM support and the Platform PCR mask.
214 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &TpmActivePcrBanks
);
215 ASSERT_EFI_ERROR (Status
);
217 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
220 // Find the intersection of Pcd support and TPM support.
221 // If banks are missing from the TPM support that are in the PCD, update the PCD.
222 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
226 // If there are active PCR banks that are not supported by the Platform mask,
227 // update the TPM allocations and reboot the machine.
229 if ((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) {
230 NewTpmActivePcrBanks
= TpmActivePcrBanks
& Tpm2PcrMask
;
232 DEBUG ((EFI_D_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
233 if (NewTpmActivePcrBanks
== 0) {
234 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
237 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
238 if (EFI_ERROR (Status
)) {
240 // We can't do much here, but we hope that this doesn't happen.
242 DEBUG ((EFI_D_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
243 ASSERT_EFI_ERROR (Status
);
246 // Need reset system, since we just called Tpm2PcrAllocateBanks().
253 // If there are any PCRs that claim support in the Platform mask that are
254 // not supported by the TPM, update the mask.
256 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
257 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
259 DEBUG ((EFI_D_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
260 if (NewTpm2PcrMask
== 0) {
261 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
265 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
266 ASSERT_EFI_ERROR (Status
);
271 Add a new entry to the Event Log.
273 @param[in] DigestList A list of digest.
274 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
275 @param[in] NewEventData Pointer to the new event data.
277 @retval EFI_SUCCESS The new event log entry was added.
278 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
282 IN TPML_DIGEST_VALUES
*DigestList
,
283 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
284 IN UINT8
*NewEventData
290 EFI_STATUS RetStatus
;
291 UINT32 SupportedEventLogs
;
292 TCG_PCR_EVENT2
*TcgPcrEvent2
;
295 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
297 RetStatus
= EFI_SUCCESS
;
298 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
299 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
300 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
301 switch (mTcg2EventInfo
[Index
].LogFormat
) {
302 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
303 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
304 if (!EFI_ERROR (Status
)) {
305 HobData
= BuildGuidHob (
306 &gTcgEventEntryHobGuid
,
307 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
309 if (HobData
== NULL
) {
310 RetStatus
= EFI_OUT_OF_RESOURCES
;
314 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
315 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
316 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
319 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
321 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
322 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
324 HobData
= BuildGuidHob (
325 &gTcgEvent2EntryHobGuid
,
326 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
328 if (HobData
== NULL
) {
329 RetStatus
= EFI_OUT_OF_RESOURCES
;
333 TcgPcrEvent2
= HobData
;
334 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
335 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
336 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
337 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
338 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
339 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
340 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
350 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
351 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
352 added into the Event Log.
354 @param[in] Flags Bitmap providing additional information.
355 @param[in] HashData Physical address of the start of the data buffer
356 to be hashed, extended, and logged.
357 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
358 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
359 @param[in] NewEventData Pointer to the new event data.
361 @retval EFI_SUCCESS Operation completed successfully.
362 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
363 @retval EFI_DEVICE_ERROR The command was unsuccessful.
370 IN UINTN HashDataLen
,
371 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
372 IN UINT8
*NewEventData
376 TPML_DIGEST_VALUES DigestList
;
378 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
379 return EFI_DEVICE_ERROR
;
382 Status
= HashAndExtend (
383 NewEventHdr
->PCRIndex
,
388 if (!EFI_ERROR (Status
)) {
389 if ((Flags
& EFI_TCG2_EXTEND_ONLY
) == 0) {
390 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
394 if (Status
== EFI_DEVICE_ERROR
) {
395 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
396 BuildGuidHob (&gTpmErrorHobGuid
,0);
398 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
399 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
407 Measure CRTM version.
409 @retval EFI_SUCCESS Operation completed successfully.
410 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
411 @retval EFI_DEVICE_ERROR The command was unsuccessful.
419 TCG_PCR_EVENT_HDR TcgEventHdr
;
422 // Use FirmwareVersion string to represent CRTM version.
423 // OEMs should get real CRTM version string and measure it.
426 TcgEventHdr
.PCRIndex
= 0;
427 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
428 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
430 return HashLogExtendEvent (
432 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
433 TcgEventHdr
.EventSize
,
435 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
441 Add it into the measured FV list after the FV is measured successfully.
443 @param[in] FvBase Base address of FV image.
444 @param[in] FvLength Length of FV image.
446 @retval EFI_SUCCESS Fv image is measured successfully
447 or it has been already measured.
448 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
449 @retval EFI_DEVICE_ERROR The command was unsuccessful.
454 IN EFI_PHYSICAL_ADDRESS FvBase
,
460 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
461 TCG_PCR_EVENT_HDR TcgEventHdr
;
464 // Check if it is in Excluded FV list
466 if (mMeasurementExcludedFvPpi
!= NULL
) {
467 for (Index
= 0; Index
< mMeasurementExcludedFvPpi
->Count
; Index
++) {
468 if (mMeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
) {
469 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
470 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
477 // Check whether FV is in the measured FV list.
479 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
480 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
) {
486 // Measure and record the FV to the TPM
488 FvBlob
.BlobBase
= FvBase
;
489 FvBlob
.BlobLength
= FvLength
;
491 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
492 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
494 TcgEventHdr
.PCRIndex
= 0;
495 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
496 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
498 Status
= HashLogExtendEvent (
500 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
501 (UINTN
) FvBlob
.BlobLength
,
507 // Add new FV into the measured FV list.
509 ASSERT (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
510 if (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
511 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
512 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
513 mMeasuredBaseFvIndex
++;
522 @retval EFI_SUCCESS Operation completed successfully.
523 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
524 @retval EFI_DEVICE_ERROR The command was unsuccessful.
534 EFI_PEI_FV_HANDLE VolumeHandle
;
535 EFI_FV_INFO VolumeInfo
;
536 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
538 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
542 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
543 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
544 // platform for special CRTM TPM measuring.
546 Status
= PeiServicesFfsFindNextVolume (FvInstances
, &VolumeHandle
);
547 if (EFI_ERROR (Status
)) {
552 // Measure and record the firmware volume that is dispatched by PeiCore
554 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
555 ASSERT_EFI_ERROR (Status
);
557 // Locate the corresponding FV_PPI according to founded FV's format guid
559 Status
= PeiServicesLocatePpi (
560 &VolumeInfo
.FvFormat
,
565 if (!EFI_ERROR (Status
)) {
566 MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
571 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
577 Measure and record the Firmware Volum Information once FvInfoPPI install.
579 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
580 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
581 @param[in] Ppi Address of the PPI that was installed.
583 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
584 @return Others Fail to measure FV.
589 FirmwareVolmeInfoPpiNotifyCallback (
590 IN EFI_PEI_SERVICES
**PeiServices
,
591 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
595 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
597 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
600 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
603 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
605 Status
= PeiServicesLocatePpi (
611 if (EFI_ERROR (Status
)) {
616 // This is an FV from an FFS file, and the parent FV must have already been measured,
617 // No need to measure twice, so just record the FV and return
619 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
621 ASSERT (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
622 if (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
624 // Check whether FV is in the measured child FV list.
626 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
627 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
631 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
632 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
633 mMeasuredChildFvIndex
++;
638 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
642 Do measurement after memory is ready.
644 @param[in] PeiServices Describes the list of possible PEI Services.
646 @retval EFI_SUCCESS Operation completed successfully.
647 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
648 @retval EFI_DEVICE_ERROR The command was unsuccessful.
653 IN EFI_PEI_SERVICES
**PeiServices
658 Status
= PeiServicesLocatePpi (
659 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
662 (VOID
**)&mMeasurementExcludedFvPpi
664 // Do not check status, because it is optional
666 mMeasuredBaseFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
667 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
668 mMeasuredChildFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
669 ASSERT (mMeasuredChildFvInfo
!= NULL
);
671 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
672 Status
= MeasureCRTMVersion ();
675 Status
= MeasureMainBios ();
679 // for the FvInfoPpi services to measure and record
680 // the additional Fvs to TPM
682 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
683 ASSERT_EFI_ERROR (Status
);
689 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
691 @param[in] PCRIndex PCR index.
693 @retval EFI_SUCCESS Operation completed successfully.
694 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
698 MeasureSeparatorEventWithError (
699 IN TPM_PCRINDEX PCRIndex
702 TCG_PCR_EVENT_HDR TcgEvent
;
706 // Use EventData 0x1 to indicate there is error.
709 TcgEvent
.PCRIndex
= PCRIndex
;
710 TcgEvent
.EventType
= EV_SEPARATOR
;
711 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
712 return HashLogExtendEvent(0,(UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
716 Entry point of this module.
718 @param[in] FileHandle Handle of the file being invoked.
719 @param[in] PeiServices Describes the list of possible PEI Services.
727 IN EFI_PEI_FILE_HANDLE FileHandle
,
728 IN CONST EFI_PEI_SERVICES
**PeiServices
733 EFI_BOOT_MODE BootMode
;
734 TPM_PCRINDEX PcrIndex
;
735 BOOLEAN S3ErrorReport
;
737 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
738 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
739 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
740 return EFI_UNSUPPORTED
;
743 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
744 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
745 return EFI_DEVICE_ERROR
;
748 Status
= PeiServicesGetBootMode (&BootMode
);
749 ASSERT_EFI_ERROR (Status
);
752 // In S3 path, skip shadow logic. no measurement is required
754 if (BootMode
!= BOOT_ON_S3_RESUME
) {
755 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
756 if (Status
== EFI_ALREADY_STARTED
) {
757 mImageInMemory
= TRUE
;
758 mFileHandle
= FileHandle
;
759 } else if (Status
== EFI_NOT_FOUND
) {
760 ASSERT_EFI_ERROR (Status
);
764 if (!mImageInMemory
) {
766 // Initialize TPM device
768 Status
= Tpm2RequestUseTpm ();
769 if (EFI_ERROR (Status
)) {
770 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
774 S3ErrorReport
= FALSE
;
775 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
776 if (BootMode
== BOOT_ON_S3_RESUME
) {
777 Status
= Tpm2Startup (TPM_SU_STATE
);
778 if (EFI_ERROR (Status
) ) {
779 Status
= Tpm2Startup (TPM_SU_CLEAR
);
780 if (!EFI_ERROR(Status
)) {
781 S3ErrorReport
= TRUE
;
785 Status
= Tpm2Startup (TPM_SU_CLEAR
);
787 if (EFI_ERROR (Status
) ) {
793 // Update Tpm2HashMask according to PCR bank.
795 SyncPcrAllocationsAndPcrMask ();
799 // The system firmware that resumes from S3 MUST deal with a
800 // TPM2_Startup error appropriately.
801 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
802 // configuring the device securely by taking actions like extending a
803 // separator with an error digest (0x01) into PCRs 0 through 7.
805 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
806 Status
= MeasureSeparatorEventWithError (PcrIndex
);
807 if (EFI_ERROR (Status
)) {
808 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
814 // TpmSelfTest is optional on S3 path, skip it to save S3 time
816 if (BootMode
!= BOOT_ON_S3_RESUME
) {
817 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
818 Status
= Tpm2SelfTest (NO
);
819 if (EFI_ERROR (Status
)) {
826 // Only intall TpmInitializedPpi on success
828 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
829 ASSERT_EFI_ERROR (Status
);
832 if (mImageInMemory
) {
833 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
838 if (EFI_ERROR (Status
)) {
839 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
840 BuildGuidHob (&gTpmErrorHobGuid
,0);
842 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
843 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
847 // Always intall TpmInitializationDonePpi no matter success or fail.
848 // Other driver can know TPM initialization state by TpmInitializedPpi.
850 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
851 ASSERT_EFI_ERROR (Status2
);