2 Initialize TPM device and measure FVs before handing off control to DXE.
4 Copyright (c) 2005 - 2016, 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>
44 BOOLEAN mImageInMemory
= FALSE
;
46 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
47 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
48 &gPeiTpmInitializedPpiGuid
,
52 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
53 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
54 &gPeiTpmInitializationDonePpiGuid
,
58 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
59 UINT32 mMeasuredBaseFvIndex
= 0;
61 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
62 UINT32 mMeasuredChildFvIndex
= 0;
64 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*mMeasurementExcludedFvPpi
;
67 Lock physical presence if needed.
69 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
70 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
71 @param[in] Ppi Address of the PPI that was installed.
73 @retval EFI_SUCCESS Operation completed successfully.
78 PhysicalPresencePpiNotifyCallback (
79 IN EFI_PEI_SERVICES
**PeiServices
,
80 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
85 Measure and record the Firmware Volum Information once FvInfoPPI install.
87 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
88 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
89 @param[in] Ppi Address of the PPI that was installed.
91 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
92 @return Others Fail to measure FV.
97 FirmwareVolmeInfoPpiNotifyCallback (
98 IN EFI_PEI_SERVICES
**PeiServices
,
99 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
104 Record all measured Firmware Volum Information into a Guid Hob
106 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
107 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
108 @param[in] Ppi Address of the PPI that was installed.
110 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
111 @return Others Fail to measure FV.
116 EndofPeiSignalNotifyCallBack (
117 IN EFI_PEI_SERVICES
**PeiServices
,
118 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
122 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
124 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
125 &gPeiLockPhysicalPresencePpiGuid
,
126 PhysicalPresencePpiNotifyCallback
129 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
130 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
131 FirmwareVolmeInfoPpiNotifyCallback
134 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
135 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
136 FirmwareVolmeInfoPpiNotifyCallback
139 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
140 &gEfiEndOfPeiSignalPpiGuid
,
141 EndofPeiSignalNotifyCallBack
146 Record all measured Firmware Volum Information into a Guid Hob
147 Guid Hob payload layout is
149 UINT32 *************************** FIRMWARE_BLOB number
150 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
152 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
153 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
154 @param[in] Ppi Address of the PPI that was installed.
156 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
157 @return Others Fail to measure FV.
162 EndofPeiSignalNotifyCallBack (
163 IN EFI_PEI_SERVICES
**PeiServices
,
164 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
168 MEASURED_HOB_DATA
*MeasuredHobData
;
170 MeasuredHobData
= NULL
;
173 // Create a Guid hob to save all measured Fv
175 MeasuredHobData
= BuildGuidHob(
177 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
180 if (MeasuredHobData
!= NULL
){
182 // Save measured FV info enty number
184 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
187 // Save measured base Fv info
189 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
192 // Save measured child Fv info
194 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
201 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
202 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
203 added into the Event Log.
205 @param[in] PeiServices Describes the list of possible PEI Services.
206 @param[in] HashData Physical address of the start of the data buffer
207 to be hashed, extended, and logged.
208 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
209 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
210 @param[in] NewEventData Pointer to the new event data.
212 @retval EFI_SUCCESS Operation completed successfully.
213 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
214 @retval EFI_DEVICE_ERROR The command was unsuccessful.
219 IN EFI_PEI_SERVICES
**PeiServices
,
221 IN UINTN HashDataLen
,
222 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
223 IN UINT8
*NewEventData
229 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
230 return EFI_DEVICE_ERROR
;
234 if (HashDataLen
!= 0) {
235 Status
= TpmCommHashAll (
240 if (EFI_ERROR (Status
)) {
245 Status
= TpmCommExtend (
247 &NewEventHdr
->Digest
,
248 NewEventHdr
->PCRIndex
,
251 if (EFI_ERROR (Status
)) {
255 HobData
= BuildGuidHob (
256 &gTcgEventEntryHobGuid
,
257 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
259 if (HobData
== NULL
) {
260 Status
= EFI_OUT_OF_RESOURCES
;
264 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
265 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
266 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
269 if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_TIMEOUT
)) {
270 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
271 BuildGuidHob (&gTpmErrorHobGuid
,0);
273 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
274 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
276 Status
= EFI_DEVICE_ERROR
;
282 Measure CRTM version.
284 @param[in] PeiServices Describes the list of possible PEI Services.
286 @retval EFI_SUCCESS Operation completed successfully.
287 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
288 @retval EFI_DEVICE_ERROR The command was unsuccessful.
294 IN EFI_PEI_SERVICES
**PeiServices
297 TCG_PCR_EVENT_HDR TcgEventHdr
;
300 // Use FirmwareVersion string to represent CRTM version.
301 // OEMs should get real CRTM version string and measure it.
304 TcgEventHdr
.PCRIndex
= 0;
305 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
306 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
308 return HashLogExtendEvent (
310 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
311 TcgEventHdr
.EventSize
,
313 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
319 Add it into the measured FV list after the FV is measured successfully.
321 @param[in] FvBase Base address of FV image.
322 @param[in] FvLength Length of FV image.
324 @retval EFI_SUCCESS Fv image is measured successfully
325 or it has been already measured.
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_PHYSICAL_ADDRESS FvBase
,
339 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
340 TCG_PCR_EVENT_HDR TcgEventHdr
;
343 // Check if it is in Excluded FV list
345 if (mMeasurementExcludedFvPpi
!= NULL
) {
346 for (Index
= 0; Index
< mMeasurementExcludedFvPpi
->Count
; Index
++) {
347 if (mMeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
) {
348 DEBUG ((DEBUG_INFO
, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase
));
349 DEBUG ((DEBUG_INFO
, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength
));
356 // Check whether FV is in the measured FV list.
358 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
359 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
) {
365 // Measure and record the FV to the TPM
367 FvBlob
.BlobBase
= FvBase
;
368 FvBlob
.BlobLength
= FvLength
;
370 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob
.BlobBase
));
371 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob
.BlobLength
));
373 TcgEventHdr
.PCRIndex
= 0;
374 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
375 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
377 Status
= HashLogExtendEvent (
378 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
379 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
380 (UINTN
) FvBlob
.BlobLength
,
386 // Add new FV into the measured FV list.
388 ASSERT (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
389 if (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
390 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
391 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
392 mMeasuredBaseFvIndex
++;
401 @param[in] PeiServices Describes the list of possible PEI Services.
403 @retval EFI_SUCCESS Operation completed successfully.
404 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
405 @retval EFI_DEVICE_ERROR The command was unsuccessful.
411 IN EFI_PEI_SERVICES
**PeiServices
416 EFI_PEI_FV_HANDLE VolumeHandle
;
417 EFI_FV_INFO VolumeInfo
;
418 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
423 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
424 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
425 // platform for special CRTM TPM measuring.
427 Status
= PeiServicesFfsFindNextVolume (FvInstances
, &VolumeHandle
);
428 if (EFI_ERROR (Status
)) {
433 // Measure and record the firmware volume that is dispatched by PeiCore
435 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
436 ASSERT_EFI_ERROR (Status
);
438 // Locate the corresponding FV_PPI according to founded FV's format guid
440 Status
= PeiServicesLocatePpi (
441 &VolumeInfo
.FvFormat
,
446 if (!EFI_ERROR (Status
)) {
447 MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
457 Measure and record the Firmware Volum Information once FvInfoPPI install.
459 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
460 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
461 @param[in] Ppi Address of the PPI that was installed.
463 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
464 @return Others Fail to measure FV.
469 FirmwareVolmeInfoPpiNotifyCallback (
470 IN EFI_PEI_SERVICES
**PeiServices
,
471 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
475 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
477 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
480 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
483 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
485 Status
= PeiServicesLocatePpi (
491 if (EFI_ERROR (Status
)) {
496 // This is an FV from an FFS file, and the parent FV must have already been measured,
497 // No need to measure twice, so just record the FV and return
499 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
501 ASSERT (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
502 if (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
504 // Check whether FV is in the measured child FV list.
506 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
507 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
511 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
512 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
513 mMeasuredChildFvIndex
++;
518 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
522 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.
523 And lock physical presence if needed.
525 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
526 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
527 @param[in] Ppi Address of the PPI that was installed.
529 @retval EFI_SUCCESS Operation completed successfully.
530 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.
531 @retval EFI_DEVICE_ERROR The command was unsuccessful.
536 PhysicalPresencePpiNotifyCallback (
537 IN EFI_PEI_SERVICES
**PeiServices
,
538 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
543 PEI_LOCK_PHYSICAL_PRESENCE_PPI
*LockPhysicalPresencePpi
;
544 BOOLEAN LifetimeLock
;
546 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue
;
548 Status
= TpmCommGetCapability (PeiServices
, NULL
, &LifetimeLock
, &CmdEnable
);
549 if (EFI_ERROR (Status
)) {
554 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.
556 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock
) && !LifetimeLock
) {
558 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.
560 PhysicalPresenceValue
= TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK
;
562 if (PcdGetBool (PcdPhysicalPresenceCmdEnable
)) {
563 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_ENABLE
;
566 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_DISABLE
;
570 if (PcdGetBool (PcdPhysicalPresenceHwEnable
)) {
571 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_ENABLE
;
573 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_DISABLE
;
576 Status
= TpmCommPhysicalPresence (
578 PhysicalPresenceValue
580 if (EFI_ERROR (Status
)) {
586 // 2. Lock physical presence if it is required.
588 LockPhysicalPresencePpi
= (PEI_LOCK_PHYSICAL_PRESENCE_PPI
*) Ppi
;
589 if (!LockPhysicalPresencePpi
->LockPhysicalPresence ((CONST EFI_PEI_SERVICES
**) PeiServices
)) {
596 // physicalPresenceCMDEnable is locked, can't change.
602 // Enable physical presence command
603 // It is necessary in order to lock physical presence
605 Status
= TpmCommPhysicalPresence (
607 TPM_PHYSICAL_PRESENCE_CMD_ENABLE
609 if (EFI_ERROR (Status
)) {
615 // Lock physical presence
617 Status
= TpmCommPhysicalPresence (
619 TPM_PHYSICAL_PRESENCE_LOCK
625 Check if TPM chip is activeated or not.
627 @param[in] PeiServices Describes the list of possible PEI Services.
629 @retval TRUE TPM is activated.
630 @retval FALSE TPM is deactivated.
636 IN EFI_PEI_SERVICES
**PeiServices
642 Status
= TpmCommGetCapability (PeiServices
, &Deactivated
, NULL
, NULL
);
643 if (EFI_ERROR (Status
)) {
646 return (BOOLEAN
)(!Deactivated
);
650 Do measurement after memory is ready.
652 @param[in] PeiServices Describes the list of possible PEI Services.
654 @retval EFI_SUCCESS Operation completed successfully.
655 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
656 @retval EFI_DEVICE_ERROR The command was unsuccessful.
662 IN EFI_PEI_SERVICES
**PeiServices
667 Status
= PeiServicesLocatePpi (
668 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
671 (VOID
**)&mMeasurementExcludedFvPpi
673 // Do not check status, because it is optional
675 mMeasuredBaseFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
676 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
677 mMeasuredChildFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
678 ASSERT (mMeasuredChildFvInfo
!= NULL
);
680 Status
= Tpm12RequestUseTpm ();
681 if (EFI_ERROR (Status
)) {
685 if (IsTpmUsable (PeiServices
)) {
686 if (PcdGet8 (PcdTpmScrtmPolicy
) == 1) {
687 Status
= MeasureCRTMVersion (PeiServices
);
690 Status
= MeasureMainBios (PeiServices
);
695 // 1). for the FvInfoPpi services to measure and record
696 // the additional Fvs to TPM
697 // 2). for the OperatorPresencePpi service to determine whether to
700 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
701 ASSERT_EFI_ERROR (Status
);
707 Entry point of this module.
709 @param[in] FileHandle Handle of the file being invoked.
710 @param[in] PeiServices Describes the list of possible PEI Services.
718 IN EFI_PEI_FILE_HANDLE FileHandle
,
719 IN CONST EFI_PEI_SERVICES
**PeiServices
724 EFI_BOOT_MODE BootMode
;
726 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
727 DEBUG ((EFI_D_ERROR
, "No TPM12 instance required!\n"));
728 return EFI_UNSUPPORTED
;
731 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
732 DEBUG ((EFI_D_ERROR
, "TPM error!\n"));
733 return EFI_DEVICE_ERROR
;
737 // Initialize TPM device
739 Status
= PeiServicesGetBootMode (&BootMode
);
740 ASSERT_EFI_ERROR (Status
);
743 // In S3 path, skip shadow logic. no measurement is required
745 if (BootMode
!= BOOT_ON_S3_RESUME
) {
746 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
747 if (Status
== EFI_ALREADY_STARTED
) {
748 mImageInMemory
= TRUE
;
749 } else if (Status
== EFI_NOT_FOUND
) {
750 ASSERT_EFI_ERROR (Status
);
754 if (!mImageInMemory
) {
755 Status
= Tpm12RequestUseTpm ();
756 if (EFI_ERROR (Status
)) {
757 DEBUG ((DEBUG_ERROR
, "TPM not detected!\n"));
761 if (PcdGet8 (PcdTpmInitializationPolicy
) == 1) {
762 Status
= TpmCommStartup ((EFI_PEI_SERVICES
**)PeiServices
, BootMode
);
763 if (EFI_ERROR (Status
) ) {
769 // TpmSelfTest is optional on S3 path, skip it to save S3 time
771 if (BootMode
!= BOOT_ON_S3_RESUME
) {
772 Status
= TpmCommContinueSelfTest ((EFI_PEI_SERVICES
**)PeiServices
);
773 if (EFI_ERROR (Status
)) {
779 // Only intall TpmInitializedPpi on success
781 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
782 ASSERT_EFI_ERROR (Status
);
785 if (mImageInMemory
) {
786 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
791 if (EFI_ERROR (Status
)) {
792 DEBUG ((EFI_D_ERROR
, "TPM error! Build Hob\n"));
793 BuildGuidHob (&gTpmErrorHobGuid
,0);
795 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
796 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
800 // Always intall TpmInitializationDonePpi no matter success or fail.
801 // Other driver can know TPM initialization state by TpmInitializedPpi.
803 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
804 ASSERT_EFI_ERROR (Status2
);