• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Tpm2GetDigestFromDigestList(IN TPMI_ALG_HASH HashAlg,IN TPML_DIGEST_VALUES * DigestList,IN VOID * Digest)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
EndofPeiSignalNotifyCallBack(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)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
LogHashEvent(IN TPML_DIGEST_VALUES * DigestList,IN OUT TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)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
HashLogExtendEvent(IN UINT64 Flags,IN UINT8 * HashData,IN UINTN HashDataLen,IN TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)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
MeasureCRTMVersion(VOID)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
MeasureFvImage(IN EFI_PHYSICAL_ADDRESS FvBase,IN UINT64 FvLength)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
MeasureMainBios(VOID)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
FirmwareVolmeInfoPpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)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
PeimEntryMP(IN EFI_PEI_SERVICES ** PeiServices)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
PeimEntryMA(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)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 }
726