2 Initialize TPM device and measure FVs before handing off control to DXE.
4 Copyright (c) 2005 - 2018, 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/Tpm12.h>
18 #include <IndustryStandard/UefiTcgPlatform.h>
19 #include <Ppi/FirmwareVolumeInfo.h>
20 #include <Ppi/FirmwareVolumeInfo2.h>
21 #include <Ppi/LockPhysicalPresence.h>
22 #include <Ppi/TpmInitialized.h>
23 #include <Ppi/FirmwareVolume.h>
24 #include <Ppi/EndOfPeiPhase.h>
25 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.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/HobLib.h>
36 #include <Library/PcdLib.h>
37 #include <Library/PeiServicesTablePointerLib.h>
38 #include <Library/BaseLib.h>
39 #include <Library/MemoryAllocationLib.h>
40 #include <Library/ReportStatusCodeLib.h>
41 #include <Library/Tpm12DeviceLib.h>
42 #include <Library/Tpm12CommandLib.h>
43 #include <Library/BaseCryptLib.h>
44 #include <Library/PerformanceLib.h>
46 BOOLEAN mImageInMemory
= FALSE
;
48 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
49 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
50 &gPeiTpmInitializedPpiGuid
,
54 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
55 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
56 &gPeiTpmInitializationDonePpiGuid
,
60 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
61 UINT32 mMeasuredBaseFvIndex
= 0;
63 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
64 UINT32 mMeasuredChildFvIndex
= 0;
66 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*mMeasurementExcludedFvPpi
;
69 Lock physical presence if needed.
71 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
72 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
73 @param[in] Ppi Address of the PPI that was installed.
75 @retval EFI_SUCCESS Operation completed successfully.
80 PhysicalPresencePpiNotifyCallback (
81 IN EFI_PEI_SERVICES
**PeiServices
,
82 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
87 Measure and record the Firmware Volum Information once FvInfoPPI install.
89 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
90 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
91 @param[in] Ppi Address of the PPI that was installed.
93 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
94 @return Others Fail to measure FV.
99 FirmwareVolmeInfoPpiNotifyCallback (
100 IN EFI_PEI_SERVICES
**PeiServices
,
101 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
106 Record all measured Firmware Volum Information into a Guid Hob
108 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
109 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
110 @param[in] Ppi Address of the PPI that was installed.
112 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
113 @return Others Fail to measure FV.
118 EndofPeiSignalNotifyCallBack (
119 IN EFI_PEI_SERVICES
**PeiServices
,
120 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
124 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
126 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
127 &gPeiLockPhysicalPresencePpiGuid
,
128 PhysicalPresencePpiNotifyCallback
131 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
132 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
133 FirmwareVolmeInfoPpiNotifyCallback
136 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
137 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
138 FirmwareVolmeInfoPpiNotifyCallback
141 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
142 &gEfiEndOfPeiSignalPpiGuid
,
143 EndofPeiSignalNotifyCallBack
148 Record all measured Firmware Volum Information into a Guid Hob
149 Guid Hob payload layout is
151 UINT32 *************************** FIRMWARE_BLOB number
152 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
154 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
155 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
156 @param[in] Ppi Address of the PPI that was installed.
158 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
159 @return Others Fail to measure FV.
164 EndofPeiSignalNotifyCallBack (
165 IN EFI_PEI_SERVICES
**PeiServices
,
166 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
170 MEASURED_HOB_DATA
*MeasuredHobData
;
172 MeasuredHobData
= NULL
;
174 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid
);
177 // Create a Guid hob to save all measured Fv
179 MeasuredHobData
= BuildGuidHob(
181 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
184 if (MeasuredHobData
!= NULL
){
186 // Save measured FV info enty number
188 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
191 // Save measured base Fv info
193 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
196 // Save measured child Fv info
198 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
201 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid
);
207 Single function calculates SHA1 digest value for all raw data. It
208 combines Sha1Init(), Sha1Update() and Sha1Final().
210 @param[in] Data Raw data to be digested.
211 @param[in] DataLen Size of the raw data.
212 @param[out] Digest Pointer to a buffer that stores the final digest.
214 @retval EFI_SUCCESS Always successfully calculate the final digest.
219 IN CONST UINT8
*Data
,
221 OUT TPM_DIGEST
*Digest
227 CtxSize
= Sha1GetContextSize ();
228 Sha1Ctx
= AllocatePool (CtxSize
);
229 ASSERT (Sha1Ctx
!= NULL
);
232 Sha1Update (Sha1Ctx
, Data
, DataLen
);
233 Sha1Final (Sha1Ctx
, (UINT8
*)Digest
);
241 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
242 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
243 added into the Event Log.
245 @param[in] PeiServices Describes the list of possible PEI Services.
246 @param[in] HashData Physical address of the start of the data buffer
247 to be hashed, extended, and logged.
248 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
249 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
250 @param[in] NewEventData Pointer to the new event data.
252 @retval EFI_SUCCESS Operation completed successfully.
253 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
254 @retval EFI_DEVICE_ERROR The command was unsuccessful.
259 IN EFI_PEI_SERVICES
**PeiServices
,
261 IN UINTN HashDataLen
,
262 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
263 IN UINT8
*NewEventData
269 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
270 return EFI_DEVICE_ERROR
;
274 if (HashDataLen
!= 0) {
275 Status
= TpmCommHashAll (
280 if (EFI_ERROR (Status
)) {
285 Status
= Tpm12Extend (
286 &NewEventHdr
->Digest
,
287 NewEventHdr
->PCRIndex
,
290 if (EFI_ERROR (Status
)) {
294 HobData
= BuildGuidHob (
295 &gTcgEventEntryHobGuid
,
296 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
298 if (HobData
== NULL
) {
299 Status
= EFI_OUT_OF_RESOURCES
;
303 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
304 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
305 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
308 if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_TIMEOUT
)) {
309 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
310 BuildGuidHob (&gTpmErrorHobGuid
,0);
312 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
313 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
315 Status
= EFI_DEVICE_ERROR
;
321 Measure CRTM version.
323 @param[in] PeiServices Describes the list of possible PEI Services.
325 @retval EFI_SUCCESS Operation completed successfully.
326 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
327 @retval EFI_DEVICE_ERROR The command was unsuccessful.
333 IN EFI_PEI_SERVICES
**PeiServices
336 TCG_PCR_EVENT_HDR TcgEventHdr
;
339 // Use FirmwareVersion string to represent CRTM version.
340 // OEMs should get real CRTM version string and measure it.
343 TcgEventHdr
.PCRIndex
= 0;
344 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
345 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
347 return HashLogExtendEvent (
349 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
350 TcgEventHdr
.EventSize
,
352 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
358 Add it into the measured FV list after the FV is measured successfully.
360 @param[in] FvBase Base address of FV image.
361 @param[in] FvLength Length of FV image.
363 @retval EFI_SUCCESS Fv image is measured successfully
364 or it has been already measured.
365 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
366 @retval EFI_DEVICE_ERROR The command was unsuccessful.
372 IN EFI_PHYSICAL_ADDRESS FvBase
,
378 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
379 TCG_PCR_EVENT_HDR TcgEventHdr
;
382 // Check if it is in Excluded FV list
384 if (mMeasurementExcludedFvPpi
!= NULL
) {
385 for (Index
= 0; Index
< mMeasurementExcludedFvPpi
->Count
; Index
++) {
386 if (mMeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
) {
387 DEBUG ((DEBUG_INFO
, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase
));
388 DEBUG ((DEBUG_INFO
, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength
));
395 // Check whether FV is in the measured FV list.
397 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
398 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
) {
404 // Measure and record the FV to the TPM
406 FvBlob
.BlobBase
= FvBase
;
407 FvBlob
.BlobLength
= FvLength
;
409 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob
.BlobBase
));
410 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob
.BlobLength
));
412 TcgEventHdr
.PCRIndex
= 0;
413 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
414 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
416 Status
= HashLogExtendEvent (
417 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
418 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
419 (UINTN
) FvBlob
.BlobLength
,
425 // Add new FV into the measured FV list.
427 ASSERT (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
428 if (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
429 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
430 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
431 mMeasuredBaseFvIndex
++;
440 @param[in] PeiServices Describes the list of possible PEI Services.
442 @retval EFI_SUCCESS Operation completed successfully.
443 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
444 @retval EFI_DEVICE_ERROR The command was unsuccessful.
450 IN EFI_PEI_SERVICES
**PeiServices
455 EFI_PEI_FV_HANDLE VolumeHandle
;
456 EFI_FV_INFO VolumeInfo
;
457 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
462 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
463 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
464 // platform for special CRTM TPM measuring.
466 Status
= PeiServicesFfsFindNextVolume (FvInstances
, &VolumeHandle
);
467 if (EFI_ERROR (Status
)) {
472 // Measure and record the firmware volume that is dispatched by PeiCore
474 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
475 ASSERT_EFI_ERROR (Status
);
477 // Locate the corresponding FV_PPI according to founded FV's format guid
479 Status
= PeiServicesLocatePpi (
480 &VolumeInfo
.FvFormat
,
485 if (!EFI_ERROR (Status
)) {
486 MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
496 Measure and record the Firmware Volum Information once FvInfoPPI install.
498 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
499 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
500 @param[in] Ppi Address of the PPI that was installed.
502 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
503 @return Others Fail to measure FV.
508 FirmwareVolmeInfoPpiNotifyCallback (
509 IN EFI_PEI_SERVICES
**PeiServices
,
510 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
514 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
516 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
519 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
522 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
524 Status
= PeiServicesLocatePpi (
530 if (EFI_ERROR (Status
)) {
535 // This is an FV from an FFS file, and the parent FV must have already been measured,
536 // No need to measure twice, so just record the FV and return
538 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
540 ASSERT (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
541 if (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
543 // Check whether FV is in the measured child FV list.
545 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
546 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
550 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
551 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
552 mMeasuredChildFvIndex
++;
557 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
561 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.
562 And lock physical presence if needed.
564 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
565 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
566 @param[in] Ppi Address of the PPI that was installed.
568 @retval EFI_SUCCESS Operation completed successfully.
569 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.
570 @retval EFI_DEVICE_ERROR The command was unsuccessful.
575 PhysicalPresencePpiNotifyCallback (
576 IN EFI_PEI_SERVICES
**PeiServices
,
577 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
582 TPM_PERMANENT_FLAGS TpmPermanentFlags
;
583 PEI_LOCK_PHYSICAL_PRESENCE_PPI
*LockPhysicalPresencePpi
;
584 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue
;
586 Status
= Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags
);
587 if (EFI_ERROR (Status
)) {
592 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.
594 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock
) && !TpmPermanentFlags
.physicalPresenceLifetimeLock
) {
596 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.
598 PhysicalPresenceValue
= TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK
;
599 TpmPermanentFlags
.physicalPresenceLifetimeLock
= TRUE
;
601 if (PcdGetBool (PcdPhysicalPresenceCmdEnable
)) {
602 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_ENABLE
;
603 TpmPermanentFlags
.physicalPresenceCMDEnable
= TRUE
;
605 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_DISABLE
;
606 TpmPermanentFlags
.physicalPresenceCMDEnable
= FALSE
;
609 if (PcdGetBool (PcdPhysicalPresenceHwEnable
)) {
610 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_ENABLE
;
612 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_DISABLE
;
615 Status
= Tpm12PhysicalPresence (
616 PhysicalPresenceValue
618 if (EFI_ERROR (Status
)) {
624 // 2. Lock physical presence if it is required.
626 LockPhysicalPresencePpi
= (PEI_LOCK_PHYSICAL_PRESENCE_PPI
*) Ppi
;
627 if (!LockPhysicalPresencePpi
->LockPhysicalPresence ((CONST EFI_PEI_SERVICES
**) PeiServices
)) {
631 if (!TpmPermanentFlags
.physicalPresenceCMDEnable
) {
632 if (TpmPermanentFlags
.physicalPresenceLifetimeLock
) {
634 // physicalPresenceCMDEnable is locked, can't change.
640 // Enable physical presence command
641 // It is necessary in order to lock physical presence
643 Status
= Tpm12PhysicalPresence (
644 TPM_PHYSICAL_PRESENCE_CMD_ENABLE
646 if (EFI_ERROR (Status
)) {
652 // Lock physical presence
654 Status
= Tpm12PhysicalPresence (
655 TPM_PHYSICAL_PRESENCE_LOCK
661 Check if TPM chip is activeated or not.
663 @param[in] PeiServices Describes the list of possible PEI Services.
665 @retval TRUE TPM is activated.
666 @retval FALSE TPM is deactivated.
675 TPM_PERMANENT_FLAGS TpmPermanentFlags
;
677 Status
= Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags
);
678 if (EFI_ERROR (Status
)) {
681 return (BOOLEAN
)(!TpmPermanentFlags
.deactivated
);
685 Do measurement after memory is ready.
687 @param[in] PeiServices Describes the list of possible PEI Services.
689 @retval EFI_SUCCESS Operation completed successfully.
690 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
691 @retval EFI_DEVICE_ERROR The command was unsuccessful.
697 IN EFI_PEI_SERVICES
**PeiServices
702 Status
= PeiServicesLocatePpi (
703 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
706 (VOID
**)&mMeasurementExcludedFvPpi
708 // Do not check status, because it is optional
710 mMeasuredBaseFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
711 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
712 mMeasuredChildFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
713 ASSERT (mMeasuredChildFvInfo
!= NULL
);
715 Status
= Tpm12RequestUseTpm ();
716 if (EFI_ERROR (Status
)) {
720 if (IsTpmUsable ()) {
721 if (PcdGet8 (PcdTpmScrtmPolicy
) == 1) {
722 Status
= MeasureCRTMVersion (PeiServices
);
725 Status
= MeasureMainBios (PeiServices
);
730 // 1). for the FvInfoPpi services to measure and record
731 // the additional Fvs to TPM
732 // 2). for the OperatorPresencePpi service to determine whether to
735 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
736 ASSERT_EFI_ERROR (Status
);
742 Entry point of this module.
744 @param[in] FileHandle Handle of the file being invoked.
745 @param[in] PeiServices Describes the list of possible PEI Services.
753 IN EFI_PEI_FILE_HANDLE FileHandle
,
754 IN CONST EFI_PEI_SERVICES
**PeiServices
759 EFI_BOOT_MODE BootMode
;
761 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
762 DEBUG ((EFI_D_ERROR
, "No TPM12 instance required!\n"));
763 return EFI_UNSUPPORTED
;
766 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
767 DEBUG ((EFI_D_ERROR
, "TPM error!\n"));
768 return EFI_DEVICE_ERROR
;
772 // Initialize TPM device
774 Status
= PeiServicesGetBootMode (&BootMode
);
775 ASSERT_EFI_ERROR (Status
);
778 // In S3 path, skip shadow logic. no measurement is required
780 if (BootMode
!= BOOT_ON_S3_RESUME
) {
781 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
782 if (Status
== EFI_ALREADY_STARTED
) {
783 mImageInMemory
= TRUE
;
784 } else if (Status
== EFI_NOT_FOUND
) {
785 ASSERT_EFI_ERROR (Status
);
789 if (!mImageInMemory
) {
790 Status
= Tpm12RequestUseTpm ();
791 if (EFI_ERROR (Status
)) {
792 DEBUG ((DEBUG_ERROR
, "TPM not detected!\n"));
796 if (PcdGet8 (PcdTpmInitializationPolicy
) == 1) {
797 if (BootMode
== BOOT_ON_S3_RESUME
) {
798 Status
= Tpm12Startup (TPM_ST_STATE
);
800 Status
= Tpm12Startup (TPM_ST_CLEAR
);
802 if (EFI_ERROR (Status
) ) {
808 // TpmSelfTest is optional on S3 path, skip it to save S3 time
810 if (BootMode
!= BOOT_ON_S3_RESUME
) {
811 Status
= Tpm12ContinueSelfTest ();
812 if (EFI_ERROR (Status
)) {
818 // Only intall TpmInitializedPpi on success
820 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
821 ASSERT_EFI_ERROR (Status
);
824 if (mImageInMemory
) {
825 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
830 if (EFI_ERROR (Status
)) {
831 DEBUG ((EFI_D_ERROR
, "TPM error! Build Hob\n"));
832 BuildGuidHob (&gTpmErrorHobGuid
,0);
834 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
835 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
839 // Always intall TpmInitializationDonePpi no matter success or fail.
840 // Other driver can know TPM initialization state by TpmInitializedPpi.
842 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
843 ASSERT_EFI_ERROR (Status2
);