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