2 Initialize TPM2 device and measure FVs before handing off control to DXE.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <IndustryStandard/UefiTcgPlatform.h>
19 #include <Ppi/FirmwareVolumeInfo.h>
20 #include <Ppi/FirmwareVolumeInfo2.h>
21 #include <Ppi/TpmInitialized.h>
22 #include <Ppi/FirmwareVolume.h>
23 #include <Ppi/EndOfPeiPhase.h>
24 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
25 #include <Ppi/FirmwareVolumeInfoPrehashedFV.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/Tpm2CommandLib.h>
36 #include <Library/Tpm2DeviceLib.h>
37 #include <Library/HashLib.h>
38 #include <Library/HobLib.h>
39 #include <Library/PcdLib.h>
40 #include <Library/PeiServicesTablePointerLib.h>
41 #include <Protocol/Tcg2Protocol.h>
42 #include <Library/PerformanceLib.h>
43 #include <Library/MemoryAllocationLib.h>
44 #include <Library/ReportStatusCodeLib.h>
45 #include <Library/ResetSystemLib.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
,
75 // Number of firmware blobs to grow by each time we run out of room
77 #define FIRMWARE_BLOB_GROWTH_STEP 4
79 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredBaseFvInfo
;
80 UINT32 mMeasuredMaxBaseFvIndex
= 0;
81 UINT32 mMeasuredBaseFvIndex
= 0;
83 EFI_PLATFORM_FIRMWARE_BLOB
*mMeasuredChildFvInfo
;
84 UINT32 mMeasuredMaxChildFvIndex
= 0;
85 UINT32 mMeasuredChildFvIndex
= 0;
88 Measure and record the Firmware Volum Information once FvInfoPPI install.
90 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
91 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
92 @param[in] Ppi Address of the PPI that was installed.
94 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
95 @return Others Fail to measure FV.
100 FirmwareVolmeInfoPpiNotifyCallback (
101 IN EFI_PEI_SERVICES
**PeiServices
,
102 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
107 Record all measured Firmware Volum Information into a Guid Hob
109 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
110 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
111 @param[in] Ppi Address of the PPI that was installed.
113 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
114 @return Others Fail to measure FV.
119 EndofPeiSignalNotifyCallBack (
120 IN EFI_PEI_SERVICES
**PeiServices
,
121 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
125 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
127 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
128 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
129 FirmwareVolmeInfoPpiNotifyCallback
132 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
133 &gEfiPeiFirmwareVolumeInfo2PpiGuid
,
134 FirmwareVolmeInfoPpiNotifyCallback
137 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
138 &gEfiEndOfPeiSignalPpiGuid
,
139 EndofPeiSignalNotifyCallBack
145 Record all measured Firmware Volum Information into a Guid Hob
146 Guid Hob payload layout is
148 UINT32 *************************** FIRMWARE_BLOB number
149 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
151 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
152 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
153 @param[in] Ppi Address of the PPI that was installed.
155 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
156 @return Others Fail to measure FV.
161 EndofPeiSignalNotifyCallBack (
162 IN EFI_PEI_SERVICES
**PeiServices
,
163 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
167 MEASURED_HOB_DATA
*MeasuredHobData
;
169 MeasuredHobData
= NULL
;
171 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid
);
174 // Create a Guid hob to save all measured Fv
176 MeasuredHobData
= BuildGuidHob(
178 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
181 if (MeasuredHobData
!= NULL
){
183 // Save measured FV info enty number
185 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
188 // Save measured base Fv info
190 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
193 // Save measured child Fv info
195 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
198 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid
);
204 Make sure that the current PCR allocations, the TPM supported PCRs,
205 and the PcdTpm2HashMask are all in agreement.
208 SyncPcrAllocationsAndPcrMask (
213 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
214 UINT32 TpmActivePcrBanks
;
215 UINT32 NewTpmActivePcrBanks
;
217 UINT32 NewTpm2PcrMask
;
219 DEBUG ((EFI_D_ERROR
, "SyncPcrAllocationsAndPcrMask!\n"));
222 // Determine the current TPM support and the Platform PCR mask.
224 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &TpmActivePcrBanks
);
225 ASSERT_EFI_ERROR (Status
);
227 Tpm2PcrMask
= PcdGet32 (PcdTpm2HashMask
);
228 if (Tpm2PcrMask
== 0) {
230 // if PcdTPm2HashMask is zero, use ActivePcr setting
232 PcdSet32S (PcdTpm2HashMask
, TpmActivePcrBanks
);
233 Tpm2PcrMask
= TpmActivePcrBanks
;
237 // Find the intersection of Pcd support and TPM support.
238 // If banks are missing from the TPM support that are in the PCD, update the PCD.
239 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
243 // If there are active PCR banks that are not supported by the Platform mask,
244 // update the TPM allocations and reboot the machine.
246 if ((TpmActivePcrBanks
& Tpm2PcrMask
) != TpmActivePcrBanks
) {
247 NewTpmActivePcrBanks
= TpmActivePcrBanks
& Tpm2PcrMask
;
249 DEBUG ((EFI_D_INFO
, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__
, TpmActivePcrBanks
, NewTpmActivePcrBanks
));
250 if (NewTpmActivePcrBanks
== 0) {
251 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
254 Status
= Tpm2PcrAllocateBanks (NULL
, (UINT32
)TpmHashAlgorithmBitmap
, NewTpmActivePcrBanks
);
255 if (EFI_ERROR (Status
)) {
257 // We can't do much here, but we hope that this doesn't happen.
259 DEBUG ((EFI_D_ERROR
, "%a - Failed to reallocate PCRs!\n", __FUNCTION__
));
260 ASSERT_EFI_ERROR (Status
);
263 // Need reset system, since we just called Tpm2PcrAllocateBanks().
270 // If there are any PCRs that claim support in the Platform mask that are
271 // not supported by the TPM, update the mask.
273 if ((Tpm2PcrMask
& TpmHashAlgorithmBitmap
) != Tpm2PcrMask
) {
274 NewTpm2PcrMask
= Tpm2PcrMask
& TpmHashAlgorithmBitmap
;
276 DEBUG ((EFI_D_INFO
, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__
, Tpm2PcrMask
, NewTpm2PcrMask
));
277 if (NewTpm2PcrMask
== 0) {
278 DEBUG ((EFI_D_ERROR
, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__
));
282 Status
= PcdSet32S (PcdTpm2HashMask
, NewTpm2PcrMask
);
283 ASSERT_EFI_ERROR (Status
);
288 Add a new entry to the Event Log.
290 @param[in] DigestList A list of digest.
291 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
292 @param[in] NewEventData Pointer to the new event data.
294 @retval EFI_SUCCESS The new event log entry was added.
295 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
299 IN TPML_DIGEST_VALUES
*DigestList
,
300 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
301 IN UINT8
*NewEventData
307 EFI_STATUS RetStatus
;
308 UINT32 SupportedEventLogs
;
309 TCG_PCR_EVENT2
*TcgPcrEvent2
;
312 SupportedEventLogs
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
| EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
314 RetStatus
= EFI_SUCCESS
;
315 for (Index
= 0; Index
< sizeof(mTcg2EventInfo
)/sizeof(mTcg2EventInfo
[0]); Index
++) {
316 if ((SupportedEventLogs
& mTcg2EventInfo
[Index
].LogFormat
) != 0) {
317 DEBUG ((EFI_D_INFO
, " LogFormat - 0x%08x\n", mTcg2EventInfo
[Index
].LogFormat
));
318 switch (mTcg2EventInfo
[Index
].LogFormat
) {
319 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
:
320 Status
= GetDigestFromDigestList (TPM_ALG_SHA1
, DigestList
, &NewEventHdr
->Digest
);
321 if (!EFI_ERROR (Status
)) {
322 HobData
= BuildGuidHob (
323 &gTcgEventEntryHobGuid
,
324 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
326 if (HobData
== NULL
) {
327 RetStatus
= EFI_OUT_OF_RESOURCES
;
331 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
332 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
333 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
336 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
:
338 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
339 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
341 HobData
= BuildGuidHob (
342 &gTcgEvent2EntryHobGuid
,
343 sizeof(TcgPcrEvent2
->PCRIndex
) + sizeof(TcgPcrEvent2
->EventType
) + GetDigestListSize (DigestList
) + sizeof(TcgPcrEvent2
->EventSize
) + NewEventHdr
->EventSize
345 if (HobData
== NULL
) {
346 RetStatus
= EFI_OUT_OF_RESOURCES
;
350 TcgPcrEvent2
= HobData
;
351 TcgPcrEvent2
->PCRIndex
= NewEventHdr
->PCRIndex
;
352 TcgPcrEvent2
->EventType
= NewEventHdr
->EventType
;
353 DigestBuffer
= (UINT8
*)&TcgPcrEvent2
->Digest
;
354 DigestBuffer
= CopyDigestListToBuffer (DigestBuffer
, DigestList
, PcdGet32 (PcdTpm2HashMask
));
355 CopyMem (DigestBuffer
, &NewEventHdr
->EventSize
, sizeof(TcgPcrEvent2
->EventSize
));
356 DigestBuffer
= DigestBuffer
+ sizeof(TcgPcrEvent2
->EventSize
);
357 CopyMem (DigestBuffer
, NewEventData
, NewEventHdr
->EventSize
);
367 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
368 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
369 added into the Event Log.
371 @param[in] Flags Bitmap providing additional information.
372 @param[in] HashData Physical address of the start of the data buffer
373 to be hashed, extended, and logged.
374 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
375 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
376 @param[in] NewEventData Pointer to the new event data.
378 @retval EFI_SUCCESS Operation completed successfully.
379 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
380 @retval EFI_DEVICE_ERROR The command was unsuccessful.
387 IN UINTN HashDataLen
,
388 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
389 IN UINT8
*NewEventData
393 TPML_DIGEST_VALUES DigestList
;
395 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
396 return EFI_DEVICE_ERROR
;
399 Status
= HashAndExtend (
400 NewEventHdr
->PCRIndex
,
405 if (!EFI_ERROR (Status
)) {
406 if ((Flags
& EFI_TCG2_EXTEND_ONLY
) == 0) {
407 Status
= LogHashEvent (&DigestList
, NewEventHdr
, NewEventData
);
411 if (Status
== EFI_DEVICE_ERROR
) {
412 DEBUG ((EFI_D_ERROR
, "HashLogExtendEvent - %r. Disable TPM.\n", Status
));
413 BuildGuidHob (&gTpmErrorHobGuid
,0);
415 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
416 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
424 Measure CRTM version.
426 @retval EFI_SUCCESS Operation completed successfully.
427 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
428 @retval EFI_DEVICE_ERROR The command was unsuccessful.
436 TCG_PCR_EVENT_HDR TcgEventHdr
;
439 // Use FirmwareVersion string to represent CRTM version.
440 // OEMs should get real CRTM version string and measure it.
443 TcgEventHdr
.PCRIndex
= 0;
444 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
445 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
447 return HashLogExtendEvent (
449 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
450 TcgEventHdr
.EventSize
,
452 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
458 Add it into the measured FV list after the FV is measured successfully.
460 @param[in] FvBase Base address of FV image.
461 @param[in] FvLength Length of FV image.
463 @retval EFI_SUCCESS Fv image is measured successfully
464 or it has been already measured.
465 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
466 @retval EFI_DEVICE_ERROR The command was unsuccessful.
471 IN EFI_PHYSICAL_ADDRESS FvBase
,
477 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
478 TCG_PCR_EVENT_HDR TcgEventHdr
;
481 TPML_DIGEST_VALUES DigestList
;
483 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI
*MeasurementExcludedFvPpi
;
484 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI
*PrehashedFvPpi
;
485 HASH_INFO
*PreHashInfo
;
489 // Check Excluded FV list
493 Status
= PeiServicesLocatePpi(
494 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid
,
497 (VOID
**)&MeasurementExcludedFvPpi
499 if (!EFI_ERROR(Status
)) {
500 for (Index
= 0; Index
< MeasurementExcludedFvPpi
->Count
; Index
++) {
501 if (MeasurementExcludedFvPpi
->Fv
[Index
].FvBase
== FvBase
502 && MeasurementExcludedFvPpi
->Fv
[Index
].FvLength
== FvLength
) {
503 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase
));
504 DEBUG ((DEBUG_INFO
, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength
));
511 } while (!EFI_ERROR(Status
));
514 // Check measured FV list
516 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
517 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
&& mMeasuredBaseFvInfo
[Index
].BlobLength
== FvLength
) {
518 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase
));
519 DEBUG ((DEBUG_INFO
, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength
));
525 // Check pre-hashed FV list
528 Tpm2HashMask
= PcdGet32 (PcdTpm2HashMask
);
530 Status
= PeiServicesLocatePpi (
531 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid
,
534 (VOID
**)&PrehashedFvPpi
536 if (!EFI_ERROR(Status
) && PrehashedFvPpi
->FvBase
== FvBase
&& PrehashedFvPpi
->FvLength
== FvLength
) {
537 ZeroMem (&DigestList
, sizeof(TPML_DIGEST_VALUES
));
540 // The FV is prehashed, check against TPM hash mask
542 PreHashInfo
= (HASH_INFO
*)(PrehashedFvPpi
+ 1);
543 for (Index
= 0, DigestCount
= 0; Index
< PrehashedFvPpi
->Count
; Index
++) {
544 DEBUG((DEBUG_INFO
, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo
->HashAlgoId
));
545 HashAlgoMask
= GetHashMaskFromAlgo(PreHashInfo
->HashAlgoId
);
546 if ((Tpm2HashMask
& HashAlgoMask
) != 0 ) {
548 // Hash is required, copy it to DigestList
550 WriteUnaligned16(&(DigestList
.digests
[DigestCount
].hashAlg
), PreHashInfo
->HashAlgoId
);
552 &DigestList
.digests
[DigestCount
].digest
,
554 PreHashInfo
->HashSize
558 // Clean the corresponding Hash Algo mask bit
560 Tpm2HashMask
&= ~HashAlgoMask
;
562 PreHashInfo
= (HASH_INFO
*)((UINT8
*)(PreHashInfo
+ 1) + PreHashInfo
->HashSize
);
565 WriteUnaligned32(&DigestList
.count
, DigestCount
);
570 } while (!EFI_ERROR(Status
));
573 // Init the log event for FV measurement
575 FvBlob
.BlobBase
= FvBase
;
576 FvBlob
.BlobLength
= FvLength
;
577 TcgEventHdr
.PCRIndex
= 0;
578 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
579 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
581 if (Tpm2HashMask
== 0) {
583 // FV pre-hash algos comply with current TPM hash requirement
584 // Skip hashing step in measure, only extend DigestList to PCR and log event
586 Status
= Tpm2PcrExtend(
591 if (!EFI_ERROR(Status
)) {
592 Status
= LogHashEvent (&DigestList
, &TcgEventHdr
, (UINT8
*) &FvBlob
);
593 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
594 DEBUG ((DEBUG_INFO
, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
595 } else if (Status
== EFI_DEVICE_ERROR
) {
596 BuildGuidHob (&gTpmErrorHobGuid
,0);
598 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
599 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
604 // Hash the FV, extend digest to the TPM and log TCG event
606 Status
= HashLogExtendEvent (
608 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
609 (UINTN
) FvBlob
.BlobLength
,
613 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob
.BlobBase
));
614 DEBUG ((DEBUG_INFO
, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob
.BlobLength
));
617 if (EFI_ERROR(Status
)) {
618 DEBUG ((DEBUG_ERROR
, "The FV which failed to be measured starts at: 0x%x\n", FvBase
));
623 // Add new FV into the measured FV list.
625 if (mMeasuredBaseFvIndex
>= mMeasuredMaxBaseFvIndex
) {
626 mMeasuredBaseFvInfo
= ReallocatePool (
627 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxBaseFvIndex
,
628 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
631 ASSERT (mMeasuredBaseFvInfo
!= NULL
);
632 mMeasuredMaxBaseFvIndex
= mMeasuredMaxBaseFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
635 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
636 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
637 mMeasuredBaseFvIndex
++;
645 @retval EFI_SUCCESS Operation completed successfully.
646 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
647 @retval EFI_DEVICE_ERROR The command was unsuccessful.
656 EFI_PEI_FV_HANDLE VolumeHandle
;
657 EFI_FV_INFO VolumeInfo
;
658 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
660 PERF_START_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
);
663 // Only measure BFV at the very beginning. Other parts of Static Core Root of
664 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
665 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
666 // reported by platform will be installed with Fv Info Ppi
667 // This firmware volume measure policy can be modified/enhanced by special
668 // platform for special CRTM TPM measuring.
670 Status
= PeiServicesFfsFindNextVolume (0, &VolumeHandle
);
671 ASSERT_EFI_ERROR (Status
);
674 // Measure and record the firmware volume that is dispatched by PeiCore
676 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
677 ASSERT_EFI_ERROR (Status
);
679 // Locate the corresponding FV_PPI according to founded FV's format guid
681 Status
= PeiServicesLocatePpi (
682 &VolumeInfo
.FvFormat
,
687 ASSERT_EFI_ERROR (Status
);
689 Status
= MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
691 PERF_END_EX (mFileHandle
, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI
+ 1);
697 Measure and record the Firmware Volum Information once FvInfoPPI install.
699 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
700 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
701 @param[in] Ppi Address of the PPI that was installed.
703 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
704 @return Others Fail to measure FV.
709 FirmwareVolmeInfoPpiNotifyCallback (
710 IN EFI_PEI_SERVICES
**PeiServices
,
711 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
715 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
717 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
720 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
723 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
725 Status
= PeiServicesLocatePpi (
731 if (EFI_ERROR (Status
)) {
736 // This is an FV from an FFS file, and the parent FV must have already been measured,
737 // No need to measure twice, so just record the FV and return
739 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
741 if (mMeasuredChildFvIndex
>= mMeasuredMaxChildFvIndex
) {
742 mMeasuredChildFvInfo
= ReallocatePool (
743 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * mMeasuredMaxChildFvIndex
,
744 sizeof (EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
),
747 ASSERT (mMeasuredChildFvInfo
!= NULL
);
748 mMeasuredMaxChildFvIndex
= mMeasuredMaxChildFvIndex
+ FIRMWARE_BLOB_GROWTH_STEP
;
751 // Check whether FV is in the measured child FV list.
753 for (Index
= 0; Index
< mMeasuredChildFvIndex
; Index
++) {
754 if (mMeasuredChildFvInfo
[Index
].BlobBase
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
) {
758 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
759 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
760 mMeasuredChildFvIndex
++;
764 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
768 Do measurement after memory is ready.
770 @param[in] PeiServices Describes the list of possible PEI Services.
772 @retval EFI_SUCCESS Operation completed successfully.
773 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
774 @retval EFI_DEVICE_ERROR The command was unsuccessful.
779 IN EFI_PEI_SERVICES
**PeiServices
784 if (PcdGet8 (PcdTpm2ScrtmPolicy
) == 1) {
785 Status
= MeasureCRTMVersion ();
788 Status
= MeasureMainBios ();
789 if (EFI_ERROR(Status
)) {
795 // for the FvInfoPpi services to measure and record
796 // the additional Fvs to TPM
798 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
799 ASSERT_EFI_ERROR (Status
);
805 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
807 @param[in] PCRIndex PCR index.
809 @retval EFI_SUCCESS Operation completed successfully.
810 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
814 MeasureSeparatorEventWithError (
815 IN TPM_PCRINDEX PCRIndex
818 TCG_PCR_EVENT_HDR TcgEvent
;
822 // Use EventData 0x1 to indicate there is error.
825 TcgEvent
.PCRIndex
= PCRIndex
;
826 TcgEvent
.EventType
= EV_SEPARATOR
;
827 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
828 return HashLogExtendEvent(0,(UINT8
*)&EventData
, TcgEvent
.EventSize
, &TcgEvent
,(UINT8
*)&EventData
);
832 Entry point of this module.
834 @param[in] FileHandle Handle of the file being invoked.
835 @param[in] PeiServices Describes the list of possible PEI Services.
843 IN EFI_PEI_FILE_HANDLE FileHandle
,
844 IN CONST EFI_PEI_SERVICES
**PeiServices
849 EFI_BOOT_MODE BootMode
;
850 TPM_PCRINDEX PcrIndex
;
851 BOOLEAN S3ErrorReport
;
853 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceNoneGuid
) ||
854 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
855 DEBUG ((DEBUG_INFO
, "No TPM2 instance required!\n"));
856 return EFI_UNSUPPORTED
;
859 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
860 DEBUG ((EFI_D_ERROR
, "TPM2 error!\n"));
861 return EFI_DEVICE_ERROR
;
864 Status
= PeiServicesGetBootMode (&BootMode
);
865 ASSERT_EFI_ERROR (Status
);
868 // In S3 path, skip shadow logic. no measurement is required
870 if (BootMode
!= BOOT_ON_S3_RESUME
) {
871 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
872 if (Status
== EFI_ALREADY_STARTED
) {
873 mImageInMemory
= TRUE
;
874 mFileHandle
= FileHandle
;
875 } else if (Status
== EFI_NOT_FOUND
) {
876 ASSERT_EFI_ERROR (Status
);
880 if (!mImageInMemory
) {
882 // Initialize TPM device
884 Status
= Tpm2RequestUseTpm ();
885 if (EFI_ERROR (Status
)) {
886 DEBUG ((DEBUG_ERROR
, "TPM2 not detected!\n"));
890 S3ErrorReport
= FALSE
;
891 if (PcdGet8 (PcdTpm2InitializationPolicy
) == 1) {
892 if (BootMode
== BOOT_ON_S3_RESUME
) {
893 Status
= Tpm2Startup (TPM_SU_STATE
);
894 if (EFI_ERROR (Status
) ) {
895 Status
= Tpm2Startup (TPM_SU_CLEAR
);
896 if (!EFI_ERROR(Status
)) {
897 S3ErrorReport
= TRUE
;
901 Status
= Tpm2Startup (TPM_SU_CLEAR
);
903 if (EFI_ERROR (Status
) ) {
909 // Update Tpm2HashMask according to PCR bank.
911 SyncPcrAllocationsAndPcrMask ();
915 // The system firmware that resumes from S3 MUST deal with a
916 // TPM2_Startup error appropriately.
917 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
918 // configuring the device securely by taking actions like extending a
919 // separator with an error digest (0x01) into PCRs 0 through 7.
921 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
922 Status
= MeasureSeparatorEventWithError (PcrIndex
);
923 if (EFI_ERROR (Status
)) {
924 DEBUG ((EFI_D_ERROR
, "Separator Event with Error not Measured. Error!\n"));
930 // TpmSelfTest is optional on S3 path, skip it to save S3 time
932 if (BootMode
!= BOOT_ON_S3_RESUME
) {
933 if (PcdGet8 (PcdTpm2SelfTestPolicy
) == 1) {
934 Status
= Tpm2SelfTest (NO
);
935 if (EFI_ERROR (Status
)) {
942 // Only intall TpmInitializedPpi on success
944 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
945 ASSERT_EFI_ERROR (Status
);
948 if (mImageInMemory
) {
949 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
954 if (EFI_ERROR (Status
)) {
955 DEBUG ((EFI_D_ERROR
, "TPM2 error! Build Hob\n"));
956 BuildGuidHob (&gTpmErrorHobGuid
,0);
958 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
959 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
963 // Always intall TpmInitializationDonePpi no matter success or fail.
964 // Other driver can know TPM initialization state by TpmInitializedPpi.
966 Status2
= PeiServicesInstallPpi (&mTpmInitializationDonePpiList
);
967 ASSERT_EFI_ERROR (Status2
);