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