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