]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/TrEEPei/TrEEPei.c
Add TPM2 implementation.
[mirror_edk2.git] / SecurityPkg / Tcg / TrEEPei / TrEEPei.c
1 /** @file
2 Initialize TPM2 device and measure FVs before handing off control to DXE.
3
4 Copyright (c) 2013, 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
9
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.
12
13 **/
14
15 #include <PiPei.h>
16
17 #include <IndustryStandard/UefiTcgPlatform.h>
18 #include <Ppi/FirmwareVolumeInfo.h>
19 #include <Ppi/LockPhysicalPresence.h>
20 #include <Ppi/TpmInitialized.h>
21 #include <Ppi/FirmwareVolume.h>
22 #include <Ppi/EndOfPeiPhase.h>
23 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
24
25 #include <Guid/TcgEventHob.h>
26 #include <Guid/MeasuredFvHob.h>
27 #include <Guid/TpmInstance.h>
28
29 #include <Library/DebugLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/PeiServicesLib.h>
32 #include <Library/PeimEntryPoint.h>
33 #include <Library/Tpm2CommandLib.h>
34 #include <Library/Tpm2DeviceLib.h>
35 #include <Library/HashLib.h>
36 #include <Library/HobLib.h>
37 #include <Library/PcdLib.h>
38 #include <Library/PeiServicesTablePointerLib.h>
39 #include <Protocol/TrEEProtocol.h>
40 #include <Library/PerformanceLib.h>
41
42 #define PERF_ID_TREE_PEI 0x3080
43
44 typedef struct {
45 EFI_GUID *EventGuid;
46 TREE_EVENT_LOG_FORMAT LogFormat;
47 UINT32 BootHashAlg;
48 UINT16 DigestAlgID;
49 TPMI_ALG_HASH TpmHashAlgo;
50 } TREE_EVENT_INFO_STRUCT;
51
52 TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {
53 {&gTcgEventEntryHobGuid, TREE_EVENT_LOG_FORMAT_TCG_1_2, TREE_BOOT_HASH_ALG_SHA1, 0, TPM_ALG_SHA1},
54 };
55
56 BOOLEAN mImageInMemory = FALSE;
57 EFI_PEI_FILE_HANDLE mFileHandle;
58
59 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {
60 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
61 &gPeiTpmInitializedPpiGuid,
62 NULL
63 };
64
65 EFI_PLATFORM_FIRMWARE_BLOB mMeasuredBaseFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];
66 UINT32 mMeasuredBaseFvIndex = 0;
67
68 EFI_PLATFORM_FIRMWARE_BLOB mMeasuredChildFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];
69 UINT32 mMeasuredChildFvIndex = 0;
70
71 /**
72 Measure and record the Firmware Volum Information once FvInfoPPI install.
73
74 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
75 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
76 @param[in] Ppi Address of the PPI that was installed.
77
78 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
79 @return Others Fail to measure FV.
80
81 **/
82 EFI_STATUS
83 EFIAPI
84 FirmwareVolmeInfoPpiNotifyCallback (
85 IN EFI_PEI_SERVICES **PeiServices,
86 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
87 IN VOID *Ppi
88 );
89
90 /**
91 Record all measured Firmware Volum Information into a Guid Hob
92
93 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
94 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
95 @param[in] Ppi Address of the PPI that was installed.
96
97 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
98 @return Others Fail to measure FV.
99
100 **/
101 EFI_STATUS
102 EFIAPI
103 EndofPeiSignalNotifyCallBack (
104 IN EFI_PEI_SERVICES **PeiServices,
105 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
106 IN VOID *Ppi
107 );
108
109 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
110 {
111 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
112 &gEfiPeiFirmwareVolumeInfoPpiGuid,
113 FirmwareVolmeInfoPpiNotifyCallback
114 },
115 {
116 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
117 &gEfiEndOfPeiSignalPpiGuid,
118 EndofPeiSignalNotifyCallBack
119 }
120 };
121
122 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
123
124 /**
125 This function return hash algorithm from event log format.
126
127 @param[in] EventLogFormat Event log format.
128
129 @return hash algorithm.
130 **/
131 TPMI_ALG_HASH
132 TrEEGetHashAlgoFromLogFormat (
133 IN TREE_EVENT_LOG_FORMAT EventLogFormat
134 )
135 {
136 UINTN Index;
137
138 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {
139 if (mTreeEventInfo[Index].LogFormat == EventLogFormat) {
140 return mTreeEventInfo[Index].TpmHashAlgo;
141 }
142 }
143 return TPM_ALG_SHA1;
144 }
145
146 /**
147 This function get digest from digest list.
148
149 @param HashAlg digest algorithm
150 @param DigestList digest list
151 @param Digest digest
152
153 @retval EFI_SUCCESS Sha1Digest is found and returned.
154 @retval EFI_NOT_FOUND Sha1Digest is not found.
155 **/
156 EFI_STATUS
157 Tpm2GetDigestFromDigestList (
158 IN TPMI_ALG_HASH HashAlg,
159 IN TPML_DIGEST_VALUES *DigestList,
160 IN VOID *Digest
161 )
162 {
163 UINTN Index;
164 UINT16 DigestSize;
165
166 DigestSize = GetHashSizeFromAlgo (HashAlg);
167 for (Index = 0; Index < DigestList->count; Index++) {
168 if (DigestList->digests[Index].hashAlg == HashAlg) {
169 CopyMem (
170 Digest,
171 &DigestList->digests[Index].digest,
172 DigestSize
173 );
174 return EFI_SUCCESS;
175 }
176 }
177
178 return EFI_NOT_FOUND;
179 }
180
181 /**
182 Record all measured Firmware Volum Information into a Guid Hob
183 Guid Hob payload layout is
184
185 UINT32 *************************** FIRMWARE_BLOB number
186 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
187
188 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
189 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
190 @param[in] Ppi Address of the PPI that was installed.
191
192 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
193 @return Others Fail to measure FV.
194
195 **/
196 EFI_STATUS
197 EFIAPI
198 EndofPeiSignalNotifyCallBack (
199 IN EFI_PEI_SERVICES **PeiServices,
200 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
201 IN VOID *Ppi
202 )
203 {
204 MEASURED_HOB_DATA *MeasuredHobData;
205
206 MeasuredHobData = NULL;
207
208 //
209 // Create a Guid hob to save all measured Fv
210 //
211 MeasuredHobData = BuildGuidHob(
212 &gMeasuredFvHobGuid,
213 sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)
214 );
215
216 if (MeasuredHobData != NULL){
217 //
218 // Save measured FV info enty number
219 //
220 MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;
221
222 //
223 // Save measured base Fv info
224 //
225 CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));
226
227 //
228 // Save measured child Fv info
229 //
230 CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));
231 }
232
233 return EFI_SUCCESS;
234 }
235
236 /**
237 Add a new entry to the Event Log.
238
239 @param[in] DigestList A list of digest.
240 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
241 @param[in] NewEventData Pointer to the new event data.
242
243 @retval EFI_SUCCESS The new event log entry was added.
244 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
245 **/
246 EFI_STATUS
247 LogHashEvent (
248 IN TPML_DIGEST_VALUES *DigestList,
249 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
250 IN UINT8 *NewEventData
251 )
252 {
253 VOID *HobData;
254 EFI_STATUS Status;
255 UINTN Index;
256 EFI_STATUS RetStatus;
257
258 RetStatus = EFI_SUCCESS;
259 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {
260 DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));
261 switch (mTreeEventInfo[Index].LogFormat) {
262 case TREE_EVENT_LOG_FORMAT_TCG_1_2:
263 Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
264 if (!EFI_ERROR (Status)) {
265 HobData = BuildGuidHob (
266 &gTcgEventEntryHobGuid,
267 sizeof (*NewEventHdr) + NewEventHdr->EventSize
268 );
269 if (HobData == NULL) {
270 RetStatus = EFI_OUT_OF_RESOURCES;
271 break;
272 }
273
274 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
275 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
276 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
277 }
278 break;
279 }
280 }
281
282 return RetStatus;
283 }
284
285 /**
286 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
287 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
288 added into the Event Log.
289
290 @param[in] Flags Bitmap providing additional information.
291 @param[in] HashData Physical address of the start of the data buffer
292 to be hashed, extended, and logged.
293 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
294 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
295 @param[in] NewEventData Pointer to the new event data.
296
297 @retval EFI_SUCCESS Operation completed successfully.
298 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
299 @retval EFI_DEVICE_ERROR The command was unsuccessful.
300
301 **/
302 EFI_STATUS
303 HashLogExtendEvent (
304 IN UINT64 Flags,
305 IN UINT8 *HashData,
306 IN UINTN HashDataLen,
307 IN TCG_PCR_EVENT_HDR *NewEventHdr,
308 IN UINT8 *NewEventData
309 )
310 {
311 EFI_STATUS Status;
312 TPML_DIGEST_VALUES DigestList;
313
314 Status = HashAndExtend (
315 NewEventHdr->PCRIndex,
316 HashData,
317 HashDataLen,
318 &DigestList
319 );
320 if (!EFI_ERROR (Status)) {
321 if ((Flags & TREE_EXTEND_ONLY) == 0) {
322 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
323 }
324 }
325 return Status;
326 }
327
328 /**
329 Measure CRTM version.
330
331 @retval EFI_SUCCESS Operation completed successfully.
332 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
333 @retval EFI_DEVICE_ERROR The command was unsuccessful.
334
335 **/
336 EFI_STATUS
337 MeasureCRTMVersion (
338 VOID
339 )
340 {
341 TCG_PCR_EVENT_HDR TcgEventHdr;
342
343 //
344 // Use FirmwareVersion string to represent CRTM version.
345 // OEMs should get real CRTM version string and measure it.
346 //
347
348 TcgEventHdr.PCRIndex = 0;
349 TcgEventHdr.EventType = EV_S_CRTM_VERSION;
350 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
351
352 return HashLogExtendEvent (
353 0,
354 (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
355 TcgEventHdr.EventSize,
356 &TcgEventHdr,
357 (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
358 );
359 }
360
361 /**
362 Measure FV image.
363 Add it into the measured FV list after the FV is measured successfully.
364
365 @param[in] FvBase Base address of FV image.
366 @param[in] FvLength Length of FV image.
367
368 @retval EFI_SUCCESS Fv image is measured successfully
369 or it has been already measured.
370 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
371 @retval EFI_DEVICE_ERROR The command was unsuccessful.
372
373 **/
374 EFI_STATUS
375 MeasureFvImage (
376 IN EFI_PHYSICAL_ADDRESS FvBase,
377 IN UINT64 FvLength
378 )
379 {
380 UINT32 Index;
381 EFI_STATUS Status;
382 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
383 TCG_PCR_EVENT_HDR TcgEventHdr;
384
385 //
386 // Check if it is in Excluded FV list
387 //
388 if (mMeasurementExcludedFvPpi != NULL) {
389 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
390 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
391 DEBUG ((DEBUG_INFO, "The FV which is excluded by TrEEPei starts at: 0x%x\n", FvBase));
392 DEBUG ((DEBUG_INFO, "The FV which is excluded by TrEEPei has the size: 0x%x\n", FvLength));
393 return EFI_SUCCESS;
394 }
395 }
396 }
397
398 //
399 // Check whether FV is in the measured FV list.
400 //
401 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
402 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
403 return EFI_SUCCESS;
404 }
405 }
406
407 //
408 // Measure and record the FV to the TPM
409 //
410 FvBlob.BlobBase = FvBase;
411 FvBlob.BlobLength = FvLength;
412
413 DEBUG ((DEBUG_INFO, "The FV which is measured by TrEEPei starts at: 0x%x\n", FvBlob.BlobBase));
414 DEBUG ((DEBUG_INFO, "The FV which is measured by TrEEPei has the size: 0x%x\n", FvBlob.BlobLength));
415
416 TcgEventHdr.PCRIndex = 0;
417 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
418 TcgEventHdr.EventSize = sizeof (FvBlob);
419
420 Status = HashLogExtendEvent (
421 0,
422 (UINT8*) (UINTN) FvBlob.BlobBase,
423 (UINTN) FvBlob.BlobLength,
424 &TcgEventHdr,
425 (UINT8*) &FvBlob
426 );
427 ASSERT_EFI_ERROR (Status);
428
429 //
430 // Add new FV into the measured FV list.
431 //
432 ASSERT (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported));
433 if (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {
434 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;
435 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
436 mMeasuredBaseFvIndex++;
437 }
438
439 return Status;
440 }
441
442 /**
443 Measure main BIOS.
444
445 @retval EFI_SUCCESS Operation completed successfully.
446 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
447 @retval EFI_DEVICE_ERROR The command was unsuccessful.
448
449 **/
450 EFI_STATUS
451 MeasureMainBios (
452 VOID
453 )
454 {
455 EFI_STATUS Status;
456 UINT32 FvInstances;
457 EFI_PEI_FV_HANDLE VolumeHandle;
458 EFI_FV_INFO VolumeInfo;
459 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
460
461 PERF_START_EX (mFileHandle, "EventRec", "TrEEPei", 0, PERF_ID_TREE_PEI);
462 FvInstances = 0;
463 while (TRUE) {
464 //
465 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
466 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
467 // platform for special CRTM TPM measuring.
468 //
469 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
470 if (EFI_ERROR (Status)) {
471 break;
472 }
473
474 //
475 // Measure and record the firmware volume that is dispatched by PeiCore
476 //
477 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
478 ASSERT_EFI_ERROR (Status);
479 //
480 // Locate the corresponding FV_PPI according to founded FV's format guid
481 //
482 Status = PeiServicesLocatePpi (
483 &VolumeInfo.FvFormat,
484 0,
485 NULL,
486 (VOID**)&FvPpi
487 );
488 if (!EFI_ERROR (Status)) {
489 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
490 }
491
492 FvInstances++;
493 }
494 PERF_END_EX (mFileHandle, "EventRec", "TrEEPei", 0, PERF_ID_TREE_PEI + 1);
495
496 return EFI_SUCCESS;
497 }
498
499 /**
500 Measure and record the Firmware Volum Information once FvInfoPPI install.
501
502 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
503 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
504 @param[in] Ppi Address of the PPI that was installed.
505
506 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
507 @return Others Fail to measure FV.
508
509 **/
510 EFI_STATUS
511 EFIAPI
512 FirmwareVolmeInfoPpiNotifyCallback (
513 IN EFI_PEI_SERVICES **PeiServices,
514 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
515 IN VOID *Ppi
516 )
517 {
518 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
519 EFI_STATUS Status;
520 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
521
522 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
523
524 //
525 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
526 //
527 Status = PeiServicesLocatePpi (
528 &Fv->FvFormat,
529 0,
530 NULL,
531 (VOID**)&FvPpi
532 );
533 if (EFI_ERROR (Status)) {
534 return EFI_SUCCESS;
535 }
536
537 //
538 // This is an FV from an FFS file, and the parent FV must have already been measured,
539 // No need to measure twice, so just record the FV and return
540 //
541 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
542
543 ASSERT (mMeasuredChildFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported));
544 if (mMeasuredChildFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {
545 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
546 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
547 mMeasuredChildFvIndex++;
548 }
549 return EFI_SUCCESS;
550 }
551
552 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
553 }
554
555 /**
556 Do measurement after memory is ready.
557
558 @param[in] PeiServices Describes the list of possible PEI Services.
559
560 @retval EFI_SUCCESS Operation completed successfully.
561 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
562 @retval EFI_DEVICE_ERROR The command was unsuccessful.
563
564 **/
565 EFI_STATUS
566 PeimEntryMP (
567 IN EFI_PEI_SERVICES **PeiServices
568 )
569 {
570 EFI_STATUS Status;
571
572 Status = PeiServicesLocatePpi (
573 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
574 0,
575 NULL,
576 (VOID**)&mMeasurementExcludedFvPpi
577 );
578 // Do not check status, because it is optional
579
580 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
581 Status = MeasureCRTMVersion ();
582 ASSERT_EFI_ERROR (Status);
583 }
584
585 Status = MeasureMainBios ();
586
587 //
588 // Post callbacks:
589 // for the FvInfoPpi services to measure and record
590 // the additional Fvs to TPM
591 //
592 Status = PeiServicesNotifyPpi (&mNotifyList[0]);
593 ASSERT_EFI_ERROR (Status);
594
595 return Status;
596 }
597
598 /**
599 Entry point of this module.
600
601 @param[in] FileHandle Handle of the file being invoked.
602 @param[in] PeiServices Describes the list of possible PEI Services.
603
604 @return Status.
605
606 **/
607 EFI_STATUS
608 EFIAPI
609 PeimEntryMA (
610 IN EFI_PEI_FILE_HANDLE FileHandle,
611 IN CONST EFI_PEI_SERVICES **PeiServices
612 )
613 {
614 EFI_STATUS Status;
615 EFI_BOOT_MODE BootMode;
616
617 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
618 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
619 DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));
620 return EFI_UNSUPPORTED;
621 }
622
623 if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {
624 return EFI_UNSUPPORTED;
625 }
626
627 //
628 // Update for Performance optimization
629 //
630 Status = Tpm2RequestUseTpm ();
631 if (EFI_ERROR (Status)) {
632 DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));
633 return Status;
634 }
635
636 Status = PeiServicesGetBootMode (&BootMode);
637 ASSERT_EFI_ERROR (Status);
638
639 //
640 // In S3 path, skip shadow logic. no measurement is required
641 //
642 if (BootMode != BOOT_ON_S3_RESUME) {
643 Status = (**PeiServices).RegisterForShadow(FileHandle);
644 if (Status == EFI_ALREADY_STARTED) {
645 mImageInMemory = TRUE;
646 mFileHandle = FileHandle;
647 } else if (Status == EFI_NOT_FOUND) {
648 ASSERT_EFI_ERROR (Status);
649 }
650 }
651
652 if (!mImageInMemory) {
653 //
654 // Initialize TPM device
655 //
656 if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
657 if (BootMode == BOOT_ON_S3_RESUME) {
658 Status = Tpm2Startup (TPM_SU_STATE);
659 if (EFI_ERROR (Status) ) {
660 Status = Tpm2Startup (TPM_SU_CLEAR);
661 }
662 } else {
663 Status = Tpm2Startup (TPM_SU_CLEAR);
664 }
665 if (EFI_ERROR (Status) ) {
666 return Status;
667 }
668 }
669
670 //
671 // TpmSelfTest is optional on S3 path, skip it to save S3 time
672 //
673 if (BootMode != BOOT_ON_S3_RESUME) {
674 if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
675 Status = Tpm2SelfTest (NO);
676 if (EFI_ERROR (Status)) {
677 return Status;
678 }
679 }
680 }
681
682 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
683 ASSERT_EFI_ERROR (Status);
684 }
685
686 if (mImageInMemory) {
687 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
688 if (EFI_ERROR (Status)) {
689 return Status;
690 }
691 }
692
693 return Status;
694 }