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 <Guid/TcgEventHob.h>
24 #include <Library/DebugLib.h>
25 #include <Library/BaseMemoryLib.h>
26 #include <Library/PeiServicesLib.h>
27 #include <Library/PeimEntryPoint.h>
28 #include <Library/TpmCommLib.h>
29 #include <Library/HobLib.h>
30 #include <Library/PcdLib.h>
31 #include <Library/PeiServicesTablePointerLib.h>
32 #include <Library/BaseLib.h>
36 BOOLEAN mImageInMemory
= FALSE
;
38 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList
= {
39 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
40 &gPeiTpmInitializedPpiGuid
,
45 Lock physical presence if needed.
47 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
48 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
49 @param[in] Ppi Address of the PPI that was installed.
51 @retval EFI_SUCCESS Operation completed successfully.
56 PhysicalPresencePpiNotifyCallback (
57 IN EFI_PEI_SERVICES
**PeiServices
,
58 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
63 Measure and record the Firmware Volum Information once FvInfoPPI install.
65 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
66 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
67 @param[in] Ppi Address of the PPI that was installed.
69 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
70 @return Others Fail to measure FV.
75 FirmwareVolmeInfoPpiNotifyCallback (
76 IN EFI_PEI_SERVICES
**PeiServices
,
77 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
81 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
83 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
84 &gPeiLockPhysicalPresencePpiGuid
,
85 PhysicalPresencePpiNotifyCallback
88 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
89 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
90 FirmwareVolmeInfoPpiNotifyCallback
94 EFI_PLATFORM_FIRMWARE_BLOB mMeasuredFvInfo
[FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)];
95 UINT32 mMeasuredFvIndex
= 0;
98 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
99 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
100 added into the Event Log.
102 @param[in] PeiServices Describes the list of possible PEI Services.
103 @param[in] HashData Physical address of the start of the data buffer
104 to be hashed, extended, and logged.
105 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
106 @param[in] TpmHandle TPM handle.
107 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
108 @param[in] NewEventData Pointer to the new event data.
110 @retval EFI_SUCCESS Operation completed successfully.
111 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
112 @retval EFI_DEVICE_ERROR The command was unsuccessful.
117 IN EFI_PEI_SERVICES
**PeiServices
,
119 IN UINTN HashDataLen
,
120 IN TIS_TPM_HANDLE TpmHandle
,
121 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
122 IN UINT8
*NewEventData
129 if (HashDataLen
!= 0) {
130 Status
= TpmCommHashAll (
135 ASSERT_EFI_ERROR (Status
);
138 Status
= TpmCommExtend (
141 &NewEventHdr
->Digest
,
142 NewEventHdr
->PCRIndex
,
145 ASSERT_EFI_ERROR (Status
);
147 HobData
= BuildGuidHob (
148 &gTcgEventEntryHobGuid
,
149 sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
151 if (HobData
== NULL
) {
152 return EFI_OUT_OF_RESOURCES
;
155 CopyMem (HobData
, NewEventHdr
, sizeof (*NewEventHdr
));
156 HobData
= (VOID
*) ((UINT8
*)HobData
+ sizeof (*NewEventHdr
));
157 CopyMem (HobData
, NewEventData
, NewEventHdr
->EventSize
);
162 Measure CRTM version.
164 @param[in] PeiServices Describes the list of possible PEI Services.
165 @param[in] TpmHandle TPM handle.
167 @retval EFI_SUCCESS Operation completed successfully.
168 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
169 @retval EFI_DEVICE_ERROR The command was unsuccessful.
175 IN EFI_PEI_SERVICES
**PeiServices
,
176 IN TIS_TPM_HANDLE TpmHandle
179 TCG_PCR_EVENT_HDR TcgEventHdr
;
182 // Use FirmwareVersion string to represent CRTM version.
183 // OEMs should get real CRTM version string and measure it.
186 TcgEventHdr
.PCRIndex
= 0;
187 TcgEventHdr
.EventType
= EV_S_CRTM_VERSION
;
188 TcgEventHdr
.EventSize
= StrSize((CHAR16
*)PcdGetPtr (PcdFirmwareVersionString
));
190 return HashLogExtendEvent (
192 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
),
193 TcgEventHdr
.EventSize
,
196 (UINT8
*)PcdGetPtr (PcdFirmwareVersionString
)
202 Add it into the measured FV list after the FV is measured successfully.
204 @param[in] FvBase Base address of FV image.
205 @param[in] FvLength Length of FV image.
207 @retval EFI_SUCCESS Fv image is measured successfully
208 or it has been already measured.
209 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
210 @retval EFI_DEVICE_ERROR The command was unsuccessful.
216 IN EFI_PHYSICAL_ADDRESS FvBase
,
222 EFI_PLATFORM_FIRMWARE_BLOB FvBlob
;
223 TCG_PCR_EVENT_HDR TcgEventHdr
;
224 TIS_TPM_HANDLE TpmHandle
;
226 TpmHandle
= (TIS_TPM_HANDLE
) (UINTN
) TPM_BASE_ADDRESS
;
229 // Check whether FV is in the measured FV list.
231 for (Index
= 0; Index
< mMeasuredFvIndex
; Index
++) {
232 if (mMeasuredFvInfo
[Index
].BlobBase
== FvBase
) {
238 // Measure and record the FV to the TPM
240 FvBlob
.BlobBase
= FvBase
;
241 FvBlob
.BlobLength
= FvLength
;
243 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob
.BlobBase
));
244 DEBUG ((DEBUG_INFO
, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob
.BlobLength
));
246 TcgEventHdr
.PCRIndex
= 0;
247 TcgEventHdr
.EventType
= EV_EFI_PLATFORM_FIRMWARE_BLOB
;
248 TcgEventHdr
.EventSize
= sizeof (FvBlob
);
250 Status
= HashLogExtendEvent (
251 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
252 (UINT8
*) (UINTN
) FvBlob
.BlobBase
,
253 (UINTN
) FvBlob
.BlobLength
,
258 ASSERT_EFI_ERROR (Status
);
261 // Add new FV into the measured FV list.
263 ASSERT (mMeasuredFvIndex
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
));
264 if (mMeasuredFvIndex
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
265 mMeasuredFvInfo
[mMeasuredFvIndex
].BlobBase
= FvBase
;
266 mMeasuredFvInfo
[mMeasuredFvIndex
++].BlobLength
= FvLength
;
275 @param[in] PeiServices Describes the list of possible PEI Services.
276 @param[in] TpmHandle TPM handle.
278 @retval EFI_SUCCESS Operation completed successfully.
279 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
280 @retval EFI_DEVICE_ERROR The command was unsuccessful.
286 IN EFI_PEI_SERVICES
**PeiServices
,
287 IN TIS_TPM_HANDLE TpmHandle
292 EFI_PEI_FV_HANDLE VolumeHandle
;
293 EFI_FV_INFO VolumeInfo
;
294 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
299 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
300 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
301 // platform for special CRTM TPM measuring.
303 Status
= PeiServicesFfsFindNextVolume (FvInstances
, &VolumeHandle
);
304 if (EFI_ERROR (Status
)) {
309 // Measure and record the firmware volume that is dispatched by PeiCore
311 Status
= PeiServicesFfsGetVolumeInfo (VolumeHandle
, &VolumeInfo
);
312 ASSERT_EFI_ERROR (Status
);
314 // Locate the corresponding FV_PPI according to founded FV's format guid
316 Status
= PeiServicesLocatePpi (
317 &VolumeInfo
.FvFormat
,
322 if (!EFI_ERROR (Status
)) {
323 MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) VolumeInfo
.FvStart
, VolumeInfo
.FvSize
);
333 Measure and record the Firmware Volum Information once FvInfoPPI install.
335 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
336 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
337 @param[in] Ppi Address of the PPI that was installed.
339 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
340 @return Others Fail to measure FV.
345 FirmwareVolmeInfoPpiNotifyCallback (
346 IN EFI_PEI_SERVICES
**PeiServices
,
347 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
351 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*Fv
;
353 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
355 Fv
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*) Ppi
;
358 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
360 Status
= PeiServicesLocatePpi (
366 if (EFI_ERROR (Status
)) {
371 // This is an FV from an FFS file, and the parent FV must have already been measured,
372 // No need to measure twice, so just returns
374 if (Fv
->ParentFvName
!= NULL
|| Fv
->ParentFileName
!= NULL
) {
378 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Fv
->FvInfo
, Fv
->FvInfoSize
);
382 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.
383 And lock physical presence if needed.
385 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
386 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
387 @param[in] Ppi Address of the PPI that was installed.
389 @retval EFI_SUCCESS Operation completed successfully.
390 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.
391 @retval EFI_DEVICE_ERROR The command was unsuccessful.
396 PhysicalPresencePpiNotifyCallback (
397 IN EFI_PEI_SERVICES
**PeiServices
,
398 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
403 PEI_LOCK_PHYSICAL_PRESENCE_PPI
*LockPhysicalPresencePpi
;
404 BOOLEAN LifetimeLock
;
406 TIS_TPM_HANDLE TpmHandle
;
407 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue
;
409 TpmHandle
= (TIS_TPM_HANDLE
) (UINTN
) TPM_BASE_ADDRESS
;
411 Status
= TpmCommGetCapability (PeiServices
, TpmHandle
, NULL
, &LifetimeLock
, &CmdEnable
);
412 if (EFI_ERROR (Status
)) {
417 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.
419 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock
) && !LifetimeLock
) {
421 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.
423 PhysicalPresenceValue
= TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK
;
425 if (PcdGetBool (PcdPhysicalPresenceCmdEnable
)) {
426 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_ENABLE
;
429 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_CMD_DISABLE
;
433 if (PcdGetBool (PcdPhysicalPresenceHwEnable
)) {
434 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_ENABLE
;
436 PhysicalPresenceValue
|= TPM_PHYSICAL_PRESENCE_HW_DISABLE
;
439 Status
= TpmCommPhysicalPresence (
442 PhysicalPresenceValue
444 if (EFI_ERROR (Status
)) {
450 // 2. Lock physical presence if it is required.
452 LockPhysicalPresencePpi
= (PEI_LOCK_PHYSICAL_PRESENCE_PPI
*) Ppi
;
453 if (!LockPhysicalPresencePpi
->LockPhysicalPresence ((CONST EFI_PEI_SERVICES
**) PeiServices
)) {
460 // physicalPresenceCMDEnable is locked, can't change.
466 // Enable physical presence command
467 // It is necessary in order to lock physical presence
469 Status
= TpmCommPhysicalPresence (
472 TPM_PHYSICAL_PRESENCE_CMD_ENABLE
474 if (EFI_ERROR (Status
)) {
480 // Lock physical presence
482 Status
= TpmCommPhysicalPresence (
485 TPM_PHYSICAL_PRESENCE_LOCK
491 Check if TPM chip is activeated or not.
493 @param[in] PeiServices Describes the list of possible PEI Services.
494 @param[in] TpmHandle TPM handle.
496 @retval TRUE TPM is activated.
497 @retval FALSE TPM is deactivated.
503 IN EFI_PEI_SERVICES
**PeiServices
,
504 IN TIS_TPM_HANDLE TpmHandle
510 Status
= TpmCommGetCapability (PeiServices
, TpmHandle
, &Deactivated
, NULL
, NULL
);
511 if (EFI_ERROR (Status
)) {
514 return (BOOLEAN
)(!Deactivated
);
518 Do measurement after memory is ready.
520 @param[in] PeiServices Describes the list of possible PEI Services.
522 @retval EFI_SUCCESS Operation completed successfully.
523 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
524 @retval EFI_DEVICE_ERROR The command was unsuccessful.
530 IN EFI_PEI_SERVICES
**PeiServices
534 TIS_TPM_HANDLE TpmHandle
;
536 TpmHandle
= (TIS_TPM_HANDLE
)(UINTN
)TPM_BASE_ADDRESS
;
537 Status
= TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR
)TpmHandle
);
538 if (EFI_ERROR (Status
)) {
542 if (IsTpmUsable (PeiServices
, TpmHandle
)) {
543 Status
= MeasureCRTMVersion (PeiServices
, TpmHandle
);
544 ASSERT_EFI_ERROR (Status
);
546 Status
= MeasureMainBios (PeiServices
, TpmHandle
);
551 // 1). for the FvInfoPpi services to measure and record
552 // the additional Fvs to TPM
553 // 2). for the OperatorPresencePpi service to determine whether to
556 Status
= PeiServicesNotifyPpi (&mNotifyList
[0]);
557 ASSERT_EFI_ERROR (Status
);
563 Entry point of this module.
565 @param[in] FileHandle Handle of the file being invoked.
566 @param[in] PeiServices Describes the list of possible PEI Services.
574 IN EFI_PEI_FILE_HANDLE FileHandle
,
575 IN CONST EFI_PEI_SERVICES
**PeiServices
579 EFI_BOOT_MODE BootMode
;
580 TIS_TPM_HANDLE TpmHandle
;
582 if (PcdGetBool (PcdHideTpmSupport
) && PcdGetBool (PcdHideTpm
)) {
583 return EFI_UNSUPPORTED
;
587 // Initialize TPM device
589 Status
= PeiServicesGetBootMode (&BootMode
);
590 ASSERT_EFI_ERROR (Status
);
593 // In S3 path, skip shadow logic. no measurement is required
595 if (BootMode
!= BOOT_ON_S3_RESUME
) {
596 Status
= (**PeiServices
).RegisterForShadow(FileHandle
);
597 if (Status
== EFI_ALREADY_STARTED
) {
598 mImageInMemory
= TRUE
;
599 } else if (Status
== EFI_NOT_FOUND
) {
600 ASSERT_EFI_ERROR (Status
);
604 if (!mImageInMemory
) {
605 TpmHandle
= (TIS_TPM_HANDLE
)(UINTN
)TPM_BASE_ADDRESS
;
606 Status
= TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR
)TpmHandle
);
607 if (EFI_ERROR (Status
)) {
608 DEBUG ((DEBUG_ERROR
, "TPM not detected!\n"));
612 Status
= TpmCommStartup ((EFI_PEI_SERVICES
**)PeiServices
, TpmHandle
, BootMode
);
613 if (EFI_ERROR (Status
) ) {
616 Status
= TpmCommContinueSelfTest ((EFI_PEI_SERVICES
**)PeiServices
, TpmHandle
);
617 if (EFI_ERROR (Status
)) {
620 Status
= PeiServicesInstallPpi (&mTpmInitializedPpiList
);
621 ASSERT_EFI_ERROR (Status
);
624 if (mImageInMemory
) {
625 Status
= PeimEntryMP ((EFI_PEI_SERVICES
**)PeiServices
);
626 if (EFI_ERROR (Status
)) {