2 Initialize TPM2 device and measure FVs before handing off control to DXE.
4 Copyright (c) 2015 - 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/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/Tcg2PhysicalPresenceLib.h>
46 #define PERF_ID_TCG2_PEI 0x3080
50 EFI_TCG2_EVENT_LOG_FORMAT LogFormat
;
51 } TCG2_EVENT_INFO_STRUCT
;
53 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo
[] = {
54 {&gTcgEventEntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
},
55 {&gTcgEvent2EntryHobGuid
, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
},
58 BOOLEAN mImageInMemory
= FALSE
;
59 EFI_PEI_FILE_HANDLE mFileHandle
;
61 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
62 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
63 &gPeiTpmInitializedPpiGuid
,
67 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList
= {
68 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
69 &gPeiTpmInitializationDonePpiGuid
,
73 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
74 UINT32 mMeasuredBaseFvIndex
= 0;
76 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
77 UINT32 mMeasuredChildFvIndex
= 0;
80 Measure and record the Firmware Volum Information once FvInfoPPI install.
82 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
83 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
84 @param[in] Ppi Address of the PPI that was installed.
86 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
87 @return Others Fail to measure FV.
92 FirmwareVolmeInfoPpiNotifyCallback (
93 IN EFI_PEI_SERVICES
**PeiServices
,
94 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
99 Record all measured Firmware Volum Information into a Guid Hob
101 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
102 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
103 @param[in] Ppi Address of the PPI that was installed.
105 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
106 @return Others Fail to measure FV.
111 EndofPeiSignalNotifyCallBack (
112 IN EFI_PEI_SERVICES
**PeiServices
,
113 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
117 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
119 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
120 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
121 FirmwareVolmeInfoPpiNotifyCallback
124 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
125 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
126 FirmwareVolmeInfoPpiNotifyCallback
129 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
130 &gEfiEndOfPeiSignalPpiGuid
,
131 EndofPeiSignalNotifyCallBack
135 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*mMeasurementExcludedFvPpi
;
138 This function get digest from digest list.
140 @param HashAlg digest algorithm
141 @param DigestList digest list
144 @retval EFI_SUCCESS Sha1Digest is found and returned.
145 @retval EFI_NOT_FOUND Sha1Digest is not found.
148 Tpm2GetDigestFromDigestList (
149 IN TPMI_ALG_HASH HashAlg
,
150 IN TPML_DIGEST_VALUES
*DigestList
,
157 DigestSize
= GetHashSizeFromAlgo (HashAlg
);
158 for (Index
= 0; Index
< DigestList
->count
; Index
++) {
159 if (DigestList
->digests
[Index
].hashAlg
== HashAlg
) {
162 &DigestList
->digests
[Index
].digest
,
169 return EFI_NOT_FOUND
;
173 Record all measured Firmware Volum Information into a Guid Hob
174 Guid Hob payload layout is
176 UINT32 *************************** FIRMWARE_BLOB number
177 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
179 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
180 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
181 @param[in] Ppi Address of the PPI that was installed.
183 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
184 @return Others Fail to measure FV.
189 EndofPeiSignalNotifyCallBack (
190 IN EFI_PEI_SERVICES
**PeiServices
,
191 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
195 MEASURED_HOB_DATA
*MeasuredHobData
;
197 MeasuredHobData
= NULL
;
200 // Create a Guid hob to save all measured Fv
202 MeasuredHobData
= BuildGuidHob(
204 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
207 if (MeasuredHobData
!= NULL
){
209 // Save measured FV info enty number
211 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
214 // Save measured base Fv info
216 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
219 // Save measured child Fv info
221 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
228 Check if buffer is all zero.
230 @param[in] Buffer Buffer to be checked.
231 @param[in] BufferSize Size of buffer to be checked.
233 @retval TRUE Buffer is all zero.
234 @retval FALSE Buffer is not all zero.
237 InternalIsZeroBuffer (
246 for (Index
= 0; Index
< BufferSize
; Index
++) {
247 if (BufferData
[Index
] != 0) {
255 Get TPML_DIGEST_VALUES data size.
257 @param[in] DigestList TPML_DIGEST_VALUES data.
259 @return TPML_DIGEST_VALUES data size.
263 IN TPML_DIGEST_VALUES
*DigestList
270 TotalSize
= sizeof(DigestList
->count
);
271 for (Index
= 0; Index
< DigestList
->count
; Index
++) {
272 DigestSize
= GetHashSizeFromAlgo (DigestList
->digests
[Index
].hashAlg
);
273 TotalSize
+= sizeof(DigestList
->digests
[Index
].hashAlg
) + DigestSize
;
280 Return if hash alg is supported in TPM PCR bank.
282 @param HashAlg Hash algorithm to be checked.
284 @retval TRUE Hash algorithm is supported.
285 @retval FALSE Hash algorithm is not supported.
288 IsHashAlgSupportedInPcrBank (
289 IN TPMI_ALG_HASH HashAlg
292 UINT32 ActivePcrBanks
;
294 ActivePcrBanks
= PcdGet32 (PcdTpm2HashMask
);
297 if ((ActivePcrBanks
& EFI_TCG2_BOOT_HASH_ALG_SHA1
) != 0) {
302 if ((ActivePcrBanks
& EFI_TCG2_BOOT_HASH_ALG_SHA256
) != 0) {
307 if ((ActivePcrBanks
& EFI_TCG2_BOOT_HASH_ALG_SHA384
) != 0) {
312 if ((ActivePcrBanks
& EFI_TCG2_BOOT_HASH_ALG_SHA512
) != 0) {
316 case TPM_ALG_SM3_256
:
317 if ((ActivePcrBanks
& EFI_TCG2_BOOT_HASH_ALG_SM3_256
) != 0) {
327 Copy TPML_DIGEST_VALUES into a buffer
329 @param[in,out] Buffer Buffer to hold TPML_DIGEST_VALUES.
330 @param[in] DigestList TPML_DIGEST_VALUES to be copied.
332 @return The end of buffer to hold TPML_DIGEST_VALUES.
335 CopyDigestListToBuffer (
337 IN TPML_DIGEST_VALUES
*DigestList
343 CopyMem (Buffer
, &DigestList
->count
, sizeof(DigestList
->count
));
344 Buffer
= (UINT8
*)Buffer
+ sizeof(DigestList
->count
);
345 for (Index
= 0; Index
< DigestList
->count
; Index
++) {
346 if (!IsHashAlgSupportedInPcrBank (DigestList
->digests
[Index
].hashAlg
)) {
347 DEBUG ((EFI_D_ERROR
, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList
->digests
[Index
].hashAlg
));
350 CopyMem (Buffer
, &DigestList
->digests
[Index
].hashAlg
, sizeof(DigestList
->digests
[Index
].hashAlg
));
351 Buffer
= (UINT8
*)Buffer
+ sizeof(DigestList
->digests
[Index
].hashAlg
);
352 DigestSize
= GetHashSizeFromAlgo (DigestList
->digests
[Index
].hashAlg
);
353 CopyMem (Buffer
, &DigestList
->digests
[Index
].digest
, DigestSize
);
354 Buffer
= (UINT8
*)Buffer
+ DigestSize
;
361 Set Tpm2HashMask PCD value according to TPM2 PCR bank.
369 UINT32 ActivePcrBanks
;
370 TPML_PCR_SELECTION Pcrs
;
373 DEBUG ((EFI_D_ERROR
, "SetTpm2HashMask!\n"));
375 Status
= Tpm2GetCapabilityPcrs (&Pcrs
);
376 if (EFI_ERROR (Status
)) {
377 DEBUG ((EFI_D_ERROR
, "Tpm2GetCapabilityPcrs fail!\n"));
378 ActivePcrBanks
= EFI_TCG2_BOOT_HASH_ALG_SHA1
;
380 DEBUG ((EFI_D_INFO
, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs
.count
));
382 for (Index
= 0; Index
< Pcrs
.count
; Index
++) {
383 DEBUG ((EFI_D_INFO
, "hash - %x\n", Pcrs
.pcrSelections
[Index
].hash
));
384 switch (Pcrs
.pcrSelections
[Index
].hash
) {
386 if (!InternalIsZeroBuffer (Pcrs
.pcrSelections
[Index
].pcrSelect
, Pcrs
.pcrSelections
[Index
].sizeofSelect
)) {
387 ActivePcrBanks
|= EFI_TCG2_BOOT_HASH_ALG_SHA1
;
391 if (!InternalIsZeroBuffer (Pcrs
.pcrSelections
[Index
].pcrSelect
, Pcrs
.pcrSelections
[Index
].sizeofSelect
)) {
392 ActivePcrBanks
|= EFI_TCG2_BOOT_HASH_ALG_SHA256
;
396 if (!InternalIsZeroBuffer (Pcrs
.pcrSelections
[Index
].pcrSelect
, Pcrs
.pcrSelections
[Index
].sizeofSelect
)) {
397 ActivePcrBanks
|= EFI_TCG2_BOOT_HASH_ALG_SHA384
;
401 if (!InternalIsZeroBuffer (Pcrs
.pcrSelections
[Index
].pcrSelect
, Pcrs
.pcrSelections
[Index
].sizeofSelect
)) {
402 ActivePcrBanks
|= EFI_TCG2_BOOT_HASH_ALG_SHA512
;
405 case TPM_ALG_SM3_256
:
406 if (!InternalIsZeroBuffer (Pcrs
.pcrSelections
[Index
].pcrSelect
, Pcrs
.pcrSelections
[Index
].sizeofSelect
)) {
407 ActivePcrBanks
|= EFI_TCG2_BOOT_HASH_ALG_SM3_256
;
413 Status
= PcdSet32S (PcdTpm2HashMask
, ActivePcrBanks
);
414 ASSERT_EFI_ERROR (Status
);
418 Add a new entry to the Event Log.
420 @param[in] DigestList A list of digest.
421 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
422 @param[in] NewEventData Pointer to the new event data.
424 @retval EFI_SUCCESS The new event log entry was added.
425 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
429 IN TPML_DIGEST_VALUES
*DigestList
,
430 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
431 IN UINT8
*NewEventData
437 EFI_STATUS RetStatus
;
438 UINT32 SupportedEventLogs
;
439 TCG_PCR_EVENT2
*TcgPcrEvent2
;
442 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
444 RetStatus
= EFI_SUCCESS
;
445 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
446 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
447 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
448 switch (mTcg2EventInfo
[Index
].LogFormat
) {
449 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
450 Status
= Tpm2GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
451 if (!EFI_ERROR (Status
)) {
452 HobData
= BuildGuidHob (
453 &gTcgEventEntryHobGuid
,
454 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
456 if (HobData
== NULL
) {
457 RetStatus
= EFI_OUT_OF_RESOURCES
;
461 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
462 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
463 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
466 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
467 HobData
= BuildGuidHob (
468 &gTcgEvent2EntryHobGuid
,
469 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
471 if (HobData
== NULL
) {
472 RetStatus
= EFI_OUT_OF_RESOURCES
;
476 TcgPcrEvent2
= HobData
;
477 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
478 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
479 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
480 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
);
481 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
482 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
483 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
493 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
494 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
495 added into the Event Log.
497 @param[in] Flags Bitmap providing additional information.
498 @param[in] HashData Physical address of the start of the data buffer
499 to be hashed, extended, and logged.
500 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
501 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
502 @param[in] NewEventData Pointer to the new event data.
504 @retval EFI_SUCCESS Operation completed successfully.
505 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
506 @retval EFI_DEVICE_ERROR The command was unsuccessful.
513 IN UINTN HashDataLen
,
514 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
515 IN UINT8
*NewEventData
519 TPML_DIGEST_VALUES DigestList
;
521 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
522 return EFI_DEVICE_ERROR
;
525 Status
= HashAndExtend (
526 NewEventHdr
->PCRIndex
,
531 if (!EFI_ERROR (Status
)) {
532 if ((Flags
& EFI_TCG2_EXTEND_ONLY
) == 0) {
533 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
537 if (Status
== EFI_DEVICE_ERROR
) {
538 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
539 BuildGuidHob (&gTpmErrorHobGuid
,0);
541 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
542 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
550 Measure CRTM version.
552 @retval EFI_SUCCESS Operation completed successfully.
553 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
554 @retval EFI_DEVICE_ERROR The command was unsuccessful.
562 TCG_PCR_EVENT_HDR TcgEventHdr
;
565 // Use FirmwareVersion string to represent CRTM version.
566 // OEMs should get real CRTM version string and measure it.
569 TcgEventHdr
.PCRIndex
= 0;
570 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
571 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
573 return HashLogExtendEvent (
575 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
576 TcgEventHdr
.EventSize
,
578 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
584 Add it into the measured FV list after the FV is measured successfully.
586 @param[in] FvBase Base address of FV image.
587 @param[in] FvLength Length of FV image.
589 @retval EFI_SUCCESS Fv image is measured successfully
590 or it has been already measured.
591 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
592 @retval EFI_DEVICE_ERROR The command was unsuccessful.
597 IN EFI_PHYSICAL_ADDRESS FvBase
,
603 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
604 TCG_PCR_EVENT_HDR TcgEventHdr
;
607 // Check if it is in Excluded FV list
609 if (mMeasurementExcludedFvPpi
!= NULL
) {
610 for (Index
= 0; Index
< mMeasurementExcludedFvPpi
->Count
; Index
++) {
611 if (mMeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
) {
612 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
613 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
620 // Check whether FV is in the measured FV list.
622 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
623 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
) {
629 // Measure and record the FV to the TPM
631 FvBlob
.BlobBase
= FvBase
;
632 FvBlob
.BlobLength
= FvLength
;
634 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
635 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
637 TcgEventHdr
.PCRIndex
= 0;
638 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
639 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
641 Status
= HashLogExtendEvent (
643 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
644 (UINTN
) FvBlob
.BlobLength
,
650 // Add new FV into the measured FV list.
652 ASSERT (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
653 if (mMeasuredBaseFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
654 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
655 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
656 mMeasuredBaseFvIndex
++;
665 @retval EFI_SUCCESS Operation completed successfully.
666 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
667 @retval EFI_DEVICE_ERROR The command was unsuccessful.
677 EFI_PEI_FV_HANDLE VolumeHandle
;
678 EFI_FV_INFO VolumeInfo
;
679 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
681 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
685 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
686 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
687 // platform for special CRTM TPM measuring.
689 Status
= PeiServicesFfsFindNextVolume (FvInstances
, &VolumeHandle
);
690 if (EFI_ERROR (Status
)) {
695 // Measure and record the firmware volume that is dispatched by PeiCore
697 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
698 ASSERT_EFI_ERROR (Status
);
700 // Locate the corresponding FV_PPI according to founded FV's format guid
702 Status
= PeiServicesLocatePpi (
703 &VolumeInfo
.FvFormat
,
708 if (!EFI_ERROR (Status
)) {
709 MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
714 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
720 Measure and record the Firmware Volum Information once FvInfoPPI install.
722 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
723 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
724 @param[in] Ppi Address of the PPI that was installed.
726 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
727 @return Others Fail to measure FV.
732 FirmwareVolmeInfoPpiNotifyCallback (
733 IN EFI_PEI_SERVICES
**PeiServices
,
734 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
738 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
740 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
743 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
746 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
748 Status
= PeiServicesLocatePpi (
754 if (EFI_ERROR (Status
)) {
759 // This is an FV from an FFS file, and the parent FV must have already been measured,
760 // No need to measure twice, so just record the FV and return
762 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
764 ASSERT (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
));
765 if (mMeasuredChildFvIndex
< PcdGet32 (PcdPeiCoreMaxFvSupported
)) {
767 // Check whether FV is in the measured child FV list.
769 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
770 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
774 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
775 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
776 mMeasuredChildFvIndex
++;
781 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
785 Do measurement after memory is ready.
787 @param[in] PeiServices Describes the list of possible PEI Services.
789 @retval EFI_SUCCESS Operation completed successfully.
790 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
791 @retval EFI_DEVICE_ERROR The command was unsuccessful.
796 IN EFI_PEI_SERVICES
**PeiServices
801 Status
= PeiServicesLocatePpi (
802 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
805 (VOID
**)&mMeasurementExcludedFvPpi
807 // Do not check status, because it is optional
809 mMeasuredBaseFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
810 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
811 mMeasuredChildFvInfo
= (EFI_PLATFORM_FIRMWARE_BLOB
*) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * PcdGet32 (PcdPeiCoreMaxFvSupported
));
812 ASSERT (mMeasuredChildFvInfo
!= NULL
);
814 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
815 Status
= MeasureCRTMVersion ();
818 Status
= MeasureMainBios ();
822 // for the FvInfoPpi services to measure and record
823 // the additional Fvs to TPM
825 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
826 ASSERT_EFI_ERROR (Status
);
832 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
834 @param[in] PCRIndex PCR index.
836 @retval EFI_SUCCESS Operation completed successfully.
837 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
841 MeasureSeparatorEventWithError (
842 IN TPM_PCRINDEX PCRIndex
845 TCG_PCR_EVENT_HDR TcgEvent
;
849 // Use EventData 0x1 to indicate there is error.
852 TcgEvent
.PCRIndex
= PCRIndex
;
853 TcgEvent
.EventType
= EV_SEPARATOR
;
854 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
855 return HashLogExtendEvent(0,(UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
859 Entry point of this module.
861 @param[in] FileHandle Handle of the file being invoked.
862 @param[in] PeiServices Describes the list of possible PEI Services.
870 IN EFI_PEI_FILE_HANDLE FileHandle
,
871 IN CONST EFI_PEI_SERVICES
**PeiServices
876 EFI_BOOT_MODE BootMode
;
877 TPM_PCRINDEX PcrIndex
;
878 BOOLEAN S3ErrorReport
;
880 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
881 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
882 DEBUG ((EFI_D_ERROR
, "No TPM2 instance required!\n"));
883 return EFI_UNSUPPORTED
;
886 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
887 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
888 return EFI_DEVICE_ERROR
;
891 Status
= PeiServicesGetBootMode (&BootMode
);
892 ASSERT_EFI_ERROR (Status
);
895 // In S3 path, skip shadow logic. no measurement is required
897 if (BootMode
!= BOOT_ON_S3_RESUME
) {
898 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
899 if (Status
== EFI_ALREADY_STARTED
) {
900 mImageInMemory
= TRUE
;
901 mFileHandle
= FileHandle
;
902 } else if (Status
== EFI_NOT_FOUND
) {
903 ASSERT_EFI_ERROR (Status
);
907 if (!mImageInMemory
) {
909 // Initialize TPM device
911 Status
= Tpm2RequestUseTpm ();
912 if (EFI_ERROR (Status
)) {
913 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
917 S3ErrorReport
= FALSE
;
918 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
919 if (BootMode
== BOOT_ON_S3_RESUME
) {
920 Status
= Tpm2Startup (TPM_SU_STATE
);
921 if (EFI_ERROR (Status
) ) {
922 Status
= Tpm2Startup (TPM_SU_CLEAR
);
923 if (!EFI_ERROR(Status
)) {
924 S3ErrorReport
= TRUE
;
928 Status
= Tpm2Startup (TPM_SU_CLEAR
);
930 if (EFI_ERROR (Status
) ) {
936 // Update Tpm2HashMask according to PCR bank.
942 // The system firmware that resumes from S3 MUST deal with a
943 // TPM2_Startup error appropriately.
944 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
945 // configuring the device securely by taking actions like extending a
946 // separator with an error digest (0x01) into PCRs 0 through 7.
948 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
949 Status
= MeasureSeparatorEventWithError (PcrIndex
);
950 if (EFI_ERROR (Status
)) {
951 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
957 // TpmSelfTest is optional on S3 path, skip it to save S3 time
959 if (BootMode
!= BOOT_ON_S3_RESUME
) {
960 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
961 Status
= Tpm2SelfTest (NO
);
962 if (EFI_ERROR (Status
)) {
969 // Only intall TpmInitializedPpi on success
971 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
972 ASSERT_EFI_ERROR (Status
);
975 if (mImageInMemory
) {
976 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
981 if (EFI_ERROR (Status
)) {
982 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
983 BuildGuidHob (&gTpmErrorHobGuid
,0);
985 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
986 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
990 // Always intall TpmInitializationDonePpi no matter success or fail.
991 // Other driver can know TPM initialization state by TpmInitializedPpi.
993 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
994 ASSERT_EFI_ERROR (Status2
);