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