2 Initialize TPM device and measure FVs before handing off control to DXE.
4 Copyright (c) 2005 - 2012, 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/LockPhysicalPresence.h>
21 #include <Ppi/TpmInitialized.h>
22 #include <Ppi/FirmwareVolume.h>
23 #include <Ppi/EndOfPeiPhase.h>
25 #include <Guid/TcgEventHob.h>
26 #include <Guid/MeasuredFvHob.h>
28 #include <Library/DebugLib.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/PeiServicesLib.h>
31 #include <Library/PeimEntryPoint.h>
32 #include <Library/TpmCommLib.h>
33 #include <Library/HobLib.h>
34 #include <Library/PcdLib.h>
35 #include <Library/PeiServicesTablePointerLib.h>
36 #include <Library/BaseLib.h>
40 BOOLEAN mImageInMemory
= FALSE
;
42 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
43 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
44 &gPeiTpmInitializedPpiGuid
,
48 EFI_PLATFORM_FIRMWARE_BLOB mMeasuredBaseFvInfo
[FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)];
49 UINT32 mMeasuredBaseFvIndex
= 0;
51 EFI_PLATFORM_FIRMWARE_BLOB mMeasuredChildFvInfo
[FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)];
52 UINT32 mMeasuredChildFvIndex
= 0;
55 Lock physical presence if needed.
57 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
58 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
59 @param[in] Ppi Address of the PPI that was installed.
61 @retval EFI_SUCCESS Operation completed successfully.
66 PhysicalPresencePpiNotifyCallback (
67 IN EFI_PEI_SERVICES
**PeiServices
,
68 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
73 Measure and record the Firmware Volum Information once FvInfoPPI install.
75 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
76 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
77 @param[in] Ppi Address of the PPI that was installed.
79 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
80 @return Others Fail to measure FV.
85 FirmwareVolmeInfoPpiNotifyCallback (
86 IN EFI_PEI_SERVICES
**PeiServices
,
87 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
92 Record all measured Firmware Volum Information into a Guid Hob
94 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
95 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
96 @param[in] Ppi Address of the PPI that was installed.
98 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
99 @return Others Fail to measure FV.
104 EndofPeiSignalNotifyCallBack (
105 IN EFI_PEI_SERVICES
**PeiServices
,
106 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
110 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
112 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
113 &gPeiLockPhysicalPresencePpiGuid
,
114 PhysicalPresencePpiNotifyCallback
117 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
118 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
119 FirmwareVolmeInfoPpiNotifyCallback
122 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
123 &gEfiEndOfPeiSignalPpiGuid
,
124 EndofPeiSignalNotifyCallBack
129 Record all measured Firmware Volum Information into a Guid Hob
130 Guid Hob payload layout is
132 UINT32 *************************** FIRMWARE_BLOB number
133 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
135 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
136 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
137 @param[in] Ppi Address of the PPI that was installed.
139 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
140 @return Others Fail to measure FV.
145 EndofPeiSignalNotifyCallBack (
146 IN EFI_PEI_SERVICES
**PeiServices
,
147 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
151 MEASURED_HOB_DATA
*MeasuredHobData
;
153 MeasuredHobData
= NULL
;
156 // Create a Guid hob to save all measured Fv
158 MeasuredHobData
= BuildGuidHob(
160 sizeof(UINTN
) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
)
163 if (MeasuredHobData
!= NULL
){
165 // Save measured FV info enty number
167 MeasuredHobData
->Num
= mMeasuredBaseFvIndex
+ mMeasuredChildFvIndex
;
170 // Save measured base Fv info
172 CopyMem (MeasuredHobData
->MeasuredFvBuf
, mMeasuredBaseFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredBaseFvIndex
));
175 // Save measured child Fv info
177 CopyMem (&MeasuredHobData
->MeasuredFvBuf
[mMeasuredBaseFvIndex
] , mMeasuredChildFvInfo
, sizeof(EFI_PLATFORM_FIRMWARE_BLOB
) * (mMeasuredChildFvIndex
));
184 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
185 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
186 added into the Event Log.
188 @param[in] PeiServices Describes the list of possible PEI Services.
189 @param[in] HashData Physical address of the start of the data buffer
190 to be hashed, extended, and logged.
191 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
192 @param[in] TpmHandle TPM handle.
193 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
194 @param[in] NewEventData Pointer to the new event data.
196 @retval EFI_SUCCESS Operation completed successfully.
197 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
198 @retval EFI_DEVICE_ERROR The command was unsuccessful.
203 IN EFI_PEI_SERVICES
**PeiServices
,
205 IN UINTN HashDataLen
,
206 IN TIS_TPM_HANDLE TpmHandle
,
207 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
208 IN UINT8
*NewEventData
215 if (HashDataLen
!= 0) {
216 Status
= TpmCommHashAll (
221 ASSERT_EFI_ERROR (Status
);
224 Status
= TpmCommExtend (
227 &NewEventHdr
->Digest
,
228 NewEventHdr
->PCRIndex
,
231 ASSERT_EFI_ERROR (Status
);
233 HobData
= BuildGuidHob (
234 &gTcgEventEntryHobGuid
,
235 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
237 if (HobData
== NULL
) {
238 return EFI_OUT_OF_RESOURCES
;
241 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
242 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
243 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
248 Measure CRTM version.
250 @param[in] PeiServices Describes the list of possible PEI Services.
251 @param[in] TpmHandle TPM handle.
253 @retval EFI_SUCCESS Operation completed successfully.
254 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
255 @retval EFI_DEVICE_ERROR The command was unsuccessful.
261 IN EFI_PEI_SERVICES
**PeiServices
,
262 IN TIS_TPM_HANDLE TpmHandle
265 TCG_PCR_EVENT_HDR TcgEventHdr
;
268 // Use FirmwareVersion string to represent CRTM version.
269 // OEMs should get real CRTM version string and measure it.
272 TcgEventHdr
.PCRIndex
= 0;
273 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
274 TcgEventHdr
.EventSize
= (UINT32
) StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
276 return HashLogExtendEvent (
278 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
279 TcgEventHdr
.EventSize
,
282 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
288 Add it into the measured FV list after the FV is measured successfully.
290 @param[in] FvBase Base address of FV image.
291 @param[in] FvLength Length of FV image.
293 @retval EFI_SUCCESS Fv image is measured successfully
294 or it has been already measured.
295 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
296 @retval EFI_DEVICE_ERROR The command was unsuccessful.
302 IN EFI_PHYSICAL_ADDRESS FvBase
,
308 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
309 TCG_PCR_EVENT_HDR TcgEventHdr
;
310 TIS_TPM_HANDLE TpmHandle
;
312 TpmHandle
= (TIS_TPM_HANDLE
) (UINTN
) TPM_BASE_ADDRESS
;
315 // Check whether FV is in the measured FV list.
317 for (Index
= 0; Index
< mMeasuredBaseFvIndex
; Index
++) {
318 if (mMeasuredBaseFvInfo
[Index
].BlobBase
== FvBase
) {
324 // Measure and record the FV to the TPM
326 FvBlob
.BlobBase
= FvBase
;
327 FvBlob
.BlobLength
= FvLength
;
329 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob
.BlobBase
));
330 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob
.BlobLength
));
332 TcgEventHdr
.PCRIndex
= 0;
333 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
334 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
336 Status
= HashLogExtendEvent (
337 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
338 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
339 (UINTN
) FvBlob
.BlobLength
,
344 ASSERT_EFI_ERROR (Status
);
347 // Add new FV into the measured FV list.
349 ASSERT (mMeasuredBaseFvIndex
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
));
350 if (mMeasuredBaseFvIndex
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
351 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobBase
= FvBase
;
352 mMeasuredBaseFvInfo
[mMeasuredBaseFvIndex
].BlobLength
= FvLength
;
353 mMeasuredBaseFvIndex
++;
362 @param[in] PeiServices Describes the list of possible PEI Services.
363 @param[in] TpmHandle TPM handle.
365 @retval EFI_SUCCESS Operation completed successfully.
366 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
367 @retval EFI_DEVICE_ERROR The command was unsuccessful.
373 IN EFI_PEI_SERVICES
**PeiServices
,
374 IN TIS_TPM_HANDLE TpmHandle
379 EFI_PEI_FV_HANDLE VolumeHandle
;
380 EFI_FV_INFO VolumeInfo
;
381 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
386 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
387 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
388 // platform for special CRTM TPM measuring.
390 Status
= PeiServicesFfsFindNextVolume (FvInstances
, &VolumeHandle
);
391 if (EFI_ERROR (Status
)) {
396 // Measure and record the firmware volume that is dispatched by PeiCore
398 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
399 ASSERT_EFI_ERROR (Status
);
401 // Locate the corresponding FV_PPI according to founded FV's format guid
403 Status
= PeiServicesLocatePpi (
404 &VolumeInfo
.FvFormat
,
409 if (!EFI_ERROR (Status
)) {
410 MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
420 Measure and record the Firmware Volum Information once FvInfoPPI install.
422 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
423 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
424 @param[in] Ppi Address of the PPI that was installed.
426 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
427 @return Others Fail to measure FV.
432 FirmwareVolmeInfoPpiNotifyCallback (
433 IN EFI_PEI_SERVICES
**PeiServices
,
434 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
438 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
440 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
442 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
445 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
447 Status
= PeiServicesLocatePpi (
453 if (EFI_ERROR (Status
)) {
458 // This is an FV from an FFS file, and the parent FV must have already been measured,
459 // No need to measure twice, so just record the FV and return
461 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
463 ASSERT (mMeasuredChildFvIndex
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
));
464 if (mMeasuredChildFvIndex
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
465 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
;
466 mMeasuredChildFvInfo
[mMeasuredChildFvIndex
].BlobLength
= Fv
->FvInfoSize
;
467 mMeasuredChildFvIndex
++;
472 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
476 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.
477 And lock physical presence if needed.
479 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
480 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
481 @param[in] Ppi Address of the PPI that was installed.
483 @retval EFI_SUCCESS Operation completed successfully.
484 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.
485 @retval EFI_DEVICE_ERROR The command was unsuccessful.
490 PhysicalPresencePpiNotifyCallback (
491 IN EFI_PEI_SERVICES
**PeiServices
,
492 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
497 PEI_LOCK_PHYSICAL_PRESENCE_PPI
*LockPhysicalPresencePpi
;
498 BOOLEAN LifetimeLock
;
500 TIS_TPM_HANDLE TpmHandle
;
501 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue
;
503 TpmHandle
= (TIS_TPM_HANDLE
) (UINTN
) TPM_BASE_ADDRESS
;
505 Status
= TpmCommGetCapability (PeiServices
, TpmHandle
, NULL
, &LifetimeLock
, &CmdEnable
);
506 if (EFI_ERROR (Status
)) {
511 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.
513 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock
) && !LifetimeLock
) {
515 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.
517 PhysicalPresenceValue
= TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK
;
519 if (PcdGetBool (PcdPhysicalPresenceCmdEnable
)) {
520 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_ENABLE
;
523 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_DISABLE
;
527 if (PcdGetBool (PcdPhysicalPresenceHwEnable
)) {
528 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_ENABLE
;
530 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_DISABLE
;
533 Status
= TpmCommPhysicalPresence (
536 PhysicalPresenceValue
538 if (EFI_ERROR (Status
)) {
544 // 2. Lock physical presence if it is required.
546 LockPhysicalPresencePpi
= (PEI_LOCK_PHYSICAL_PRESENCE_PPI
*) Ppi
;
547 if (!LockPhysicalPresencePpi
->LockPhysicalPresence ((CONST EFI_PEI_SERVICES
**) PeiServices
)) {
554 // physicalPresenceCMDEnable is locked, can't change.
560 // Enable physical presence command
561 // It is necessary in order to lock physical presence
563 Status
= TpmCommPhysicalPresence (
566 TPM_PHYSICAL_PRESENCE_CMD_ENABLE
568 if (EFI_ERROR (Status
)) {
574 // Lock physical presence
576 Status
= TpmCommPhysicalPresence (
579 TPM_PHYSICAL_PRESENCE_LOCK
585 Check if TPM chip is activeated or not.
587 @param[in] PeiServices Describes the list of possible PEI Services.
588 @param[in] TpmHandle TPM handle.
590 @retval TRUE TPM is activated.
591 @retval FALSE TPM is deactivated.
597 IN EFI_PEI_SERVICES
**PeiServices
,
598 IN TIS_TPM_HANDLE TpmHandle
604 Status
= TpmCommGetCapability (PeiServices
, TpmHandle
, &Deactivated
, NULL
, NULL
);
605 if (EFI_ERROR (Status
)) {
608 return (BOOLEAN
)(!Deactivated
);
612 Do measurement after memory is ready.
614 @param[in] PeiServices Describes the list of possible PEI Services.
616 @retval EFI_SUCCESS Operation completed successfully.
617 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
618 @retval EFI_DEVICE_ERROR The command was unsuccessful.
624 IN EFI_PEI_SERVICES
**PeiServices
628 TIS_TPM_HANDLE TpmHandle
;
630 TpmHandle
= (TIS_TPM_HANDLE
)(UINTN
)TPM_BASE_ADDRESS
;
631 Status
= TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR
)TpmHandle
);
632 if (EFI_ERROR (Status
)) {
636 if (IsTpmUsable (PeiServices
, TpmHandle
)) {
637 Status
= MeasureCRTMVersion (PeiServices
, TpmHandle
);
638 ASSERT_EFI_ERROR (Status
);
640 Status
= MeasureMainBios (PeiServices
, TpmHandle
);
645 // 1). for the FvInfoPpi services to measure and record
646 // the additional Fvs to TPM
647 // 2). for the OperatorPresencePpi service to determine whether to
650 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
651 ASSERT_EFI_ERROR (Status
);
657 Entry point of this module.
659 @param[in] FileHandle Handle of the file being invoked.
660 @param[in] PeiServices Describes the list of possible PEI Services.
668 IN EFI_PEI_FILE_HANDLE FileHandle
,
669 IN CONST EFI_PEI_SERVICES
**PeiServices
673 EFI_BOOT_MODE BootMode
;
674 TIS_TPM_HANDLE TpmHandle
;
676 if (PcdGetBool (PcdHideTpmSupport
) && PcdGetBool (PcdHideTpm
)) {
677 return EFI_UNSUPPORTED
;
681 // Initialize TPM device
683 Status
= PeiServicesGetBootMode (&BootMode
);
684 ASSERT_EFI_ERROR (Status
);
687 // In S3 path, skip shadow logic. no measurement is required
689 if (BootMode
!= BOOT_ON_S3_RESUME
) {
690 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
691 if (Status
== EFI_ALREADY_STARTED
) {
692 mImageInMemory
= TRUE
;
693 } else if (Status
== EFI_NOT_FOUND
) {
694 ASSERT_EFI_ERROR (Status
);
698 if (!mImageInMemory
) {
699 TpmHandle
= (TIS_TPM_HANDLE
)(UINTN
)TPM_BASE_ADDRESS
;
700 Status
= TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR
)TpmHandle
);
701 if (EFI_ERROR (Status
)) {
702 DEBUG ((DEBUG_ERROR
, "TPM not detected!\n"));
706 Status
= TpmCommStartup ((EFI_PEI_SERVICES
**)PeiServices
, TpmHandle
, BootMode
);
707 if (EFI_ERROR (Status
) ) {
712 // TpmSelfTest is optional on S3 path, skip it to save S3 time
714 if (BootMode
!= BOOT_ON_S3_RESUME
) {
715 Status
= TpmCommContinueSelfTest ((EFI_PEI_SERVICES
**)PeiServices
, TpmHandle
);
716 if (EFI_ERROR (Status
)) {
721 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
722 ASSERT_EFI_ERROR (Status
);
725 if (mImageInMemory
) {
726 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
727 if (EFI_ERROR (Status
)) {