1 /** @file
2   Initialize TPM2 device and measure FVs before handing off control to DXE.
3 
4 Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include <PiPei.h>
11 
12 #include <IndustryStandard/UefiTcgPlatform.h>
13 #include <Ppi/FirmwareVolumeInfo.h>
14 #include <Ppi/FirmwareVolumeInfo2.h>
15 #include <Ppi/TpmInitialized.h>
16 #include <Ppi/FirmwareVolume.h>
17 #include <Ppi/EndOfPeiPhase.h>
18 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
19 #include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
20 #include <Ppi/Tcg.h>
21 
22 #include <Guid/TcgEventHob.h>
23 #include <Guid/MeasuredFvHob.h>
24 #include <Guid/TpmInstance.h>
25 #include <Guid/MigratedFvInfo.h>
26 
27 #include <Library/DebugLib.h>
28 #include <Library/BaseMemoryLib.h>
29 #include <Library/PeiServicesLib.h>
30 #include <Library/PeimEntryPoint.h>
31 #include <Library/Tpm2CommandLib.h>
32 #include <Library/Tpm2DeviceLib.h>
33 #include <Library/HashLib.h>
34 #include <Library/HobLib.h>
35 #include <Library/PcdLib.h>
36 #include <Library/PeiServicesTablePointerLib.h>
37 #include <Protocol/Tcg2Protocol.h>
38 #include <Library/PerformanceLib.h>
39 #include <Library/MemoryAllocationLib.h>
40 #include <Library/ReportStatusCodeLib.h>
41 #include <Library/ResetSystemLib.h>
42 #include <Library/PrintLib.h>
43 
44 #define PERF_ID_TCG2_PEI  0x3080
45 
46 typedef struct {
47   EFI_GUID                   *EventGuid;
48   EFI_TCG2_EVENT_LOG_FORMAT  LogFormat;
49 } TCG2_EVENT_INFO_STRUCT;
50 
51 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = {
52   {&gTcgEventEntryHobGuid,   EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2},
53   {&gTcgEvent2EntryHobGuid,  EFI_TCG2_EVENT_LOG_FORMAT_TCG_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 /**
72   Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
73   and build a GUIDed HOB recording the event which will be passed to the DXE phase and
74   added into the Event Log.
75 
76   @param[in]      This          Indicates the calling context
77   @param[in]      Flags         Bitmap providing additional information.
78   @param[in]      HashData      If BIT0 of Flags is 0, it is physical address of the
79                                 start of the data buffer to be hashed, extended, and logged.
80                                 If BIT0 of Flags is 1, it is physical address of the
81                                 start of the pre-hash data buffter to be extended, and logged.
82                                 The pre-hash data format is TPML_DIGEST_VALUES.
83   @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData.
84   @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
85   @param[in]      NewEventData  Pointer to the new event data.
86 
87   @retval EFI_SUCCESS           Operation completed successfully.
88   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
89   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
90 
91 **/
92 EFI_STATUS
93 EFIAPI
94 HashLogExtendEvent (
95   IN      EDKII_TCG_PPI             *This,
96   IN      UINT64                    Flags,
97   IN      UINT8                     *HashData,
98   IN      UINTN                     HashDataLen,
99   IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
100   IN      UINT8                     *NewEventData
101   );
102 
103 EDKII_TCG_PPI mEdkiiTcgPpi = {
104   HashLogExtendEvent
105 };
106 
107 EFI_PEI_PPI_DESCRIPTOR  mTcgPpiList = {
108   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
109   &gEdkiiTcgPpiGuid,
110   &mEdkiiTcgPpi
111 };
112 
113 //
114 // Number of firmware blobs to grow by each time we run out of room
115 //
116 #define FIRMWARE_BLOB_GROWTH_STEP 4
117 
118 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;
119 UINT32 mMeasuredMaxBaseFvIndex = 0;
120 UINT32 mMeasuredBaseFvIndex = 0;
121 
122 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;
123 UINT32 mMeasuredMaxChildFvIndex = 0;
124 UINT32 mMeasuredChildFvIndex = 0;
125 
126 #pragma pack (1)
127 
128 #define FV_HANDOFF_TABLE_DESC  "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"
129 typedef struct {
130   UINT8                             BlobDescriptionSize;
131   UINT8                             BlobDescription[sizeof(FV_HANDOFF_TABLE_DESC)];
132   EFI_PHYSICAL_ADDRESS              BlobBase;
133   UINT64                            BlobLength;
134 } FV_HANDOFF_TABLE_POINTERS2;
135 
136 #pragma pack ()
137 
138 /**
139   Measure and record the Firmware Volume Information once FvInfoPPI install.
140 
141   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
142   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
143   @param[in] Ppi               Address of the PPI that was installed.
144 
145   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
146   @return Others               Fail to measure FV.
147 
148 **/
149 EFI_STATUS
150 EFIAPI
151 FirmwareVolumeInfoPpiNotifyCallback (
152   IN EFI_PEI_SERVICES              **PeiServices,
153   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
154   IN VOID                          *Ppi
155   );
156 
157 /**
158   Record all measured Firmware Volume Information into a Guid Hob
159 
160   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
161   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
162   @param[in] Ppi               Address of the PPI that was installed.
163 
164   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
165   @return Others               Fail to measure FV.
166 
167 **/
168 EFI_STATUS
169 EFIAPI
170 EndofPeiSignalNotifyCallBack (
171   IN EFI_PEI_SERVICES              **PeiServices,
172   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
173   IN VOID                          *Ppi
174   );
175 
176 EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
177   {
178     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
179     &gEfiPeiFirmwareVolumeInfoPpiGuid,
180     FirmwareVolumeInfoPpiNotifyCallback
181   },
182   {
183     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
184     &gEfiPeiFirmwareVolumeInfo2PpiGuid,
185     FirmwareVolumeInfoPpiNotifyCallback
186   },
187   {
188     (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
189     &gEfiEndOfPeiSignalPpiGuid,
190     EndofPeiSignalNotifyCallBack
191   }
192 };
193 
194 
195 /**
196   Record all measured Firmware Volume Information into a Guid Hob
197   Guid Hob payload layout is
198 
199      UINT32 *************************** FIRMWARE_BLOB number
200      EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
201 
202   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
203   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
204   @param[in] Ppi               Address of the PPI that was installed.
205 
206   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
207   @return Others               Fail to measure FV.
208 
209 **/
210 EFI_STATUS
211 EFIAPI
EndofPeiSignalNotifyCallBack(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)212 EndofPeiSignalNotifyCallBack (
213   IN EFI_PEI_SERVICES              **PeiServices,
214   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
215   IN VOID                          *Ppi
216   )
217 {
218   MEASURED_HOB_DATA *MeasuredHobData;
219 
220   MeasuredHobData = NULL;
221 
222   PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid);
223 
224   //
225   // Create a Guid hob to save all measured Fv
226   //
227   MeasuredHobData = BuildGuidHob(
228                       &gMeasuredFvHobGuid,
229                       sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)
230                       );
231 
232   if (MeasuredHobData != NULL){
233     //
234     // Save measured FV info enty number
235     //
236     MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;
237 
238     //
239     // Save measured base Fv info
240     //
241     CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));
242 
243     //
244     // Save measured child Fv info
245     //
246     CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));
247   }
248 
249   PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid);
250 
251   return EFI_SUCCESS;
252 }
253 
254 /**
255   Make sure that the current PCR allocations, the TPM supported PCRs,
256   and the PcdTpm2HashMask are all in agreement.
257 **/
258 VOID
SyncPcrAllocationsAndPcrMask(VOID)259 SyncPcrAllocationsAndPcrMask (
260   VOID
261   )
262 {
263   EFI_STATUS                        Status;
264   EFI_TCG2_EVENT_ALGORITHM_BITMAP   TpmHashAlgorithmBitmap;
265   UINT32                            TpmActivePcrBanks;
266   UINT32                            NewTpmActivePcrBanks;
267   UINT32                            Tpm2PcrMask;
268   UINT32                            NewTpm2PcrMask;
269 
270   DEBUG ((EFI_D_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));
271 
272   //
273   // Determine the current TPM support and the Platform PCR mask.
274   //
275   Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &TpmActivePcrBanks);
276   ASSERT_EFI_ERROR (Status);
277 
278   Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
279   if (Tpm2PcrMask == 0) {
280     //
281     // if PcdTPm2HashMask is zero, use ActivePcr setting
282     //
283     PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
284     Tpm2PcrMask = TpmActivePcrBanks;
285   }
286 
287   //
288   // Find the intersection of Pcd support and TPM support.
289   // If banks are missing from the TPM support that are in the PCD, update the PCD.
290   // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
291   //
292 
293   //
294   // If there are active PCR banks that are not supported by the Platform mask,
295   // update the TPM allocations and reboot the machine.
296   //
297   if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) {
298     NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask;
299 
300     DEBUG ((EFI_D_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
301     if (NewTpmActivePcrBanks == 0) {
302       DEBUG ((EFI_D_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
303       ASSERT (FALSE);
304     } else {
305       Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap, NewTpmActivePcrBanks);
306       if (EFI_ERROR (Status)) {
307         //
308         // We can't do much here, but we hope that this doesn't happen.
309         //
310         DEBUG ((EFI_D_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__));
311         ASSERT_EFI_ERROR (Status);
312       }
313       //
314       // Need reset system, since we just called Tpm2PcrAllocateBanks().
315       //
316       ResetCold();
317     }
318   }
319 
320   //
321   // If there are any PCRs that claim support in the Platform mask that are
322   // not supported by the TPM, update the mask.
323   //
324   if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) {
325     NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap;
326 
327     DEBUG ((EFI_D_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));
328     if (NewTpm2PcrMask == 0) {
329       DEBUG ((EFI_D_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
330       ASSERT (FALSE);
331     }
332 
333     Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);
334     ASSERT_EFI_ERROR (Status);
335   }
336 }
337 
338 /**
339   Add a new entry to the Event Log.
340 
341   @param[in]     DigestList    A list of digest.
342   @param[in,out] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
343   @param[in]     NewEventData  Pointer to the new event data.
344 
345   @retval EFI_SUCCESS           The new event log entry was added.
346   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
347 **/
348 EFI_STATUS
LogHashEvent(IN TPML_DIGEST_VALUES * DigestList,IN OUT TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)349 LogHashEvent (
350   IN TPML_DIGEST_VALUES             *DigestList,
351   IN OUT  TCG_PCR_EVENT_HDR         *NewEventHdr,
352   IN      UINT8                     *NewEventData
353   )
354 {
355   VOID                              *HobData;
356   EFI_STATUS                        Status;
357   UINTN                             Index;
358   EFI_STATUS                        RetStatus;
359   UINT32                            SupportedEventLogs;
360   TCG_PCR_EVENT2                    *TcgPcrEvent2;
361   UINT8                             *DigestBuffer;
362 
363   SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
364 
365   RetStatus = EFI_SUCCESS;
366   for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) {
367     if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
368       DEBUG ((EFI_D_INFO, "  LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));
369       switch (mTcg2EventInfo[Index].LogFormat) {
370       case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
371         Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
372         if (!EFI_ERROR (Status)) {
373           HobData = BuildGuidHob (
374                      &gTcgEventEntryHobGuid,
375                      sizeof (*NewEventHdr) + NewEventHdr->EventSize
376                      );
377           if (HobData == NULL) {
378             RetStatus = EFI_OUT_OF_RESOURCES;
379             break;
380           }
381 
382           CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
383           HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
384           CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
385         }
386         break;
387       case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
388         //
389         // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
390         // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
391         //
392         HobData = BuildGuidHob (
393                    &gTcgEvent2EntryHobGuid,
394                    sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
395                    );
396         if (HobData == NULL) {
397           RetStatus = EFI_OUT_OF_RESOURCES;
398           break;
399         }
400 
401         TcgPcrEvent2 = HobData;
402         TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
403         TcgPcrEvent2->EventType = NewEventHdr->EventType;
404         DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
405         DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));
406         CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize));
407         DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);
408         CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
409         break;
410       }
411     }
412   }
413 
414   return RetStatus;
415 }
416 
417 /**
418   Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
419   and build a GUIDed HOB recording the event which will be passed to the DXE phase and
420   added into the Event Log.
421 
422   @param[in]      This          Indicates the calling context
423   @param[in]      Flags         Bitmap providing additional information.
424   @param[in]      HashData      If BIT0 of Flags is 0, it is physical address of the
425                                 start of the data buffer to be hashed, extended, and logged.
426                                 If BIT0 of Flags is 1, it is physical address of the
427                                 start of the pre-hash data buffter to be extended, and logged.
428                                 The pre-hash data format is TPML_DIGEST_VALUES.
429   @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData.
430   @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
431   @param[in]      NewEventData  Pointer to the new event data.
432 
433   @retval EFI_SUCCESS           Operation completed successfully.
434   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
435   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
436 
437 **/
438 EFI_STATUS
439 EFIAPI
HashLogExtendEvent(IN EDKII_TCG_PPI * This,IN UINT64 Flags,IN UINT8 * HashData,IN UINTN HashDataLen,IN TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)440 HashLogExtendEvent (
441   IN      EDKII_TCG_PPI             *This,
442   IN      UINT64                    Flags,
443   IN      UINT8                     *HashData,
444   IN      UINTN                     HashDataLen,
445   IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
446   IN      UINT8                     *NewEventData
447   )
448 {
449   EFI_STATUS                        Status;
450   TPML_DIGEST_VALUES                DigestList;
451 
452   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
453     return EFI_DEVICE_ERROR;
454   }
455 
456   if ((Flags & EDKII_TCG_PRE_HASH) != 0 || (Flags & EDKII_TCG_PRE_HASH_LOG_ONLY) != 0) {
457     ZeroMem (&DigestList, sizeof(DigestList));
458     CopyMem (&DigestList, HashData, sizeof(DigestList));
459     Status = EFI_SUCCESS;
460     if ((Flags & EDKII_TCG_PRE_HASH) !=0 ) {
461       Status = Tpm2PcrExtend (
462                NewEventHdr->PCRIndex,
463                &DigestList
464                );
465     }
466   } else {
467     Status = HashAndExtend (
468                NewEventHdr->PCRIndex,
469                HashData,
470                HashDataLen,
471                &DigestList
472                );
473   }
474   if (!EFI_ERROR (Status)) {
475     Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
476   }
477 
478   if (Status == EFI_DEVICE_ERROR) {
479     DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
480     BuildGuidHob (&gTpmErrorHobGuid,0);
481     REPORT_STATUS_CODE (
482       EFI_ERROR_CODE | EFI_ERROR_MINOR,
483       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
484       );
485   }
486 
487   return Status;
488 }
489 
490 /**
491   Measure CRTM version.
492 
493   @retval EFI_SUCCESS           Operation completed successfully.
494   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
495   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
496 
497 **/
498 EFI_STATUS
MeasureCRTMVersion(VOID)499 MeasureCRTMVersion (
500   VOID
501   )
502 {
503   TCG_PCR_EVENT_HDR                 TcgEventHdr;
504 
505   //
506   // Use FirmwareVersion string to represent CRTM version.
507   // OEMs should get real CRTM version string and measure it.
508   //
509 
510   TcgEventHdr.PCRIndex  = 0;
511   TcgEventHdr.EventType = EV_S_CRTM_VERSION;
512   TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
513 
514   return HashLogExtendEvent (
515            &mEdkiiTcgPpi,
516            0,
517            (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
518            TcgEventHdr.EventSize,
519            &TcgEventHdr,
520            (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
521            );
522 }
523 
524 /**
525   Get the FvName from the FV header.
526 
527   Causion: The FV is untrusted input.
528 
529   @param[in]  FvBase            Base address of FV image.
530   @param[in]  FvLength          Length of FV image.
531 
532   @return FvName pointer
533   @retval NULL   FvName is NOT found
534 **/
535 VOID *
GetFvName(IN EFI_PHYSICAL_ADDRESS FvBase,IN UINT64 FvLength)536 GetFvName (
537   IN EFI_PHYSICAL_ADDRESS           FvBase,
538   IN UINT64                         FvLength
539   )
540 {
541   EFI_FIRMWARE_VOLUME_HEADER      *FvHeader;
542   EFI_FIRMWARE_VOLUME_EXT_HEADER  *FvExtHeader;
543 
544   if (FvBase >= MAX_ADDRESS) {
545     return NULL;
546   }
547   if (FvLength >= MAX_ADDRESS - FvBase) {
548     return NULL;
549   }
550   if (FvLength < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
551     return NULL;
552   }
553 
554   FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;
555   if (FvHeader->ExtHeaderOffset < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
556     return NULL;
557   }
558   if (FvHeader->ExtHeaderOffset + sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) {
559     return NULL;
560   }
561   FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset);
562 
563   return &FvExtHeader->FvName;
564 }
565 
566 /**
567   Measure FV image.
568   Add it into the measured FV list after the FV is measured successfully.
569 
570   @param[in]  FvBase            Base address of FV image.
571   @param[in]  FvLength          Length of FV image.
572 
573   @retval EFI_SUCCESS           Fv image is measured successfully
574                                 or it has been already measured.
575   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
576   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
577 
578 **/
579 EFI_STATUS
MeasureFvImage(IN EFI_PHYSICAL_ADDRESS FvBase,IN UINT64 FvLength)580 MeasureFvImage (
581   IN EFI_PHYSICAL_ADDRESS           FvBase,
582   IN UINT64                         FvLength
583   )
584 {
585   UINT32                                                Index;
586   EFI_STATUS                                            Status;
587   EFI_PLATFORM_FIRMWARE_BLOB                            FvBlob;
588   FV_HANDOFF_TABLE_POINTERS2                            FvBlob2;
589   VOID                                                  *EventData;
590   VOID                                                  *FvName;
591   TCG_PCR_EVENT_HDR                                     TcgEventHdr;
592   UINT32                                                Instance;
593   UINT32                                                Tpm2HashMask;
594   TPML_DIGEST_VALUES                                    DigestList;
595   UINT32                                                DigestCount;
596   EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
597   EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI       *PrehashedFvPpi;
598   HASH_INFO                                             *PreHashInfo;
599   UINT32                                                HashAlgoMask;
600   EFI_PHYSICAL_ADDRESS                                  FvOrgBase;
601   EFI_PHYSICAL_ADDRESS                                  FvDataBase;
602   EFI_PEI_HOB_POINTERS                                  Hob;
603   EDKII_MIGRATED_FV_INFO                                *MigratedFvInfo;
604 
605   //
606   // Check Excluded FV list
607   //
608   Instance = 0;
609   do {
610     Status = PeiServicesLocatePpi(
611                  &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
612                  Instance,
613                  NULL,
614                  (VOID**)&MeasurementExcludedFvPpi
615                  );
616     if (!EFI_ERROR(Status)) {
617       for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index ++) {
618         if (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase
619          && MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength) {
620           DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
621           DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
622           return EFI_SUCCESS;
623         }
624       }
625 
626       Instance++;
627     }
628   } while (!EFI_ERROR(Status));
629 
630   //
631   // Check measured FV list
632   //
633   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
634     if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase && mMeasuredBaseFvInfo[Index].BlobLength == FvLength) {
635       DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
636       DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));
637       return EFI_SUCCESS;
638     }
639   }
640 
641   //
642   // Check pre-hashed FV list
643   //
644   Instance     = 0;
645   Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
646   do {
647     Status = PeiServicesLocatePpi (
648                &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
649                Instance,
650                NULL,
651                (VOID**)&PrehashedFvPpi
652                );
653     if (!EFI_ERROR(Status) && PrehashedFvPpi->FvBase == FvBase && PrehashedFvPpi->FvLength == FvLength) {
654       ZeroMem (&DigestList, sizeof(TPML_DIGEST_VALUES));
655 
656       //
657       // The FV is prehashed, check against TPM hash mask
658       //
659       PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
660       for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
661         DEBUG((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
662         HashAlgoMask = GetHashMaskFromAlgo(PreHashInfo->HashAlgoId);
663         if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
664           //
665           // Hash is required, copy it to DigestList
666           //
667           WriteUnaligned16(&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
668           CopyMem (
669             &DigestList.digests[DigestCount].digest,
670             PreHashInfo + 1,
671             PreHashInfo->HashSize
672             );
673           DigestCount++;
674           //
675           // Clean the corresponding Hash Algo mask bit
676           //
677           Tpm2HashMask &= ~HashAlgoMask;
678         }
679         PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
680       }
681 
682       WriteUnaligned32(&DigestList.count, DigestCount);
683 
684       break;
685     }
686     Instance++;
687   } while (!EFI_ERROR(Status));
688 
689   //
690   // Search the matched migration FV info
691   //
692   FvOrgBase  = FvBase;
693   FvDataBase = FvBase;
694   Hob.Raw  = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
695   while (Hob.Raw != NULL) {
696     MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
697     if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) {
698       //
699       // Found the migrated FV info
700       //
701       FvOrgBase  = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase;
702       FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase;
703       break;
704     }
705     Hob.Raw = GET_NEXT_HOB (Hob);
706     Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
707   }
708 
709   //
710   // Init the log event for FV measurement
711   //
712   if (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105) {
713     FvBlob2.BlobDescriptionSize = sizeof(FvBlob2.BlobDescription);
714     CopyMem (FvBlob2.BlobDescription, FV_HANDOFF_TABLE_DESC, sizeof(FvBlob2.BlobDescription));
715     FvName = GetFvName (FvBase, FvLength);
716     if (FvName != NULL) {
717       AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName);
718     }
719     FvBlob2.BlobBase      = FvOrgBase;
720     FvBlob2.BlobLength    = FvLength;
721     TcgEventHdr.PCRIndex  = 0;
722     TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
723     TcgEventHdr.EventSize = sizeof (FvBlob2);
724     EventData             = &FvBlob2;
725   } else {
726     FvBlob.BlobBase       = FvOrgBase;
727     FvBlob.BlobLength     = FvLength;
728     TcgEventHdr.PCRIndex  = 0;
729     TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
730     TcgEventHdr.EventSize = sizeof (FvBlob);
731     EventData             = &FvBlob;
732   }
733 
734   if (Tpm2HashMask == 0) {
735     //
736     // FV pre-hash algos comply with current TPM hash requirement
737     // Skip hashing step in measure, only extend DigestList to PCR and log event
738     //
739     Status = HashLogExtendEvent (
740                &mEdkiiTcgPpi,
741                EDKII_TCG_PRE_HASH,
742                (UINT8*) &DigestList,        // HashData
743                (UINTN) sizeof(DigestList),  // HashDataLen
744                &TcgEventHdr,                // EventHdr
745                EventData                    // EventData
746                );
747     DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase));
748     DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength));
749   } else {
750     //
751     // Hash the FV, extend digest to the TPM and log TCG event
752     //
753     Status = HashLogExtendEvent (
754                &mEdkiiTcgPpi,
755                0,
756                (UINT8*) (UINTN) FvDataBase, // HashData
757                (UINTN) FvLength,        // HashDataLen
758                &TcgEventHdr,            // EventHdr
759                EventData                // EventData
760                );
761     DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase));
762     DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength));
763   }
764 
765   if (EFI_ERROR(Status)) {
766     DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
767     return Status;
768   }
769 
770   //
771   // Add new FV into the measured FV list.
772   //
773   if (mMeasuredBaseFvIndex >= mMeasuredMaxBaseFvIndex) {
774     mMeasuredBaseFvInfo = ReallocatePool (
775                             sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxBaseFvIndex,
776                             sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
777                             mMeasuredBaseFvInfo
778                             );
779     ASSERT (mMeasuredBaseFvInfo != NULL);
780     mMeasuredMaxBaseFvIndex = mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
781   }
782 
783   mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase   = FvBase;
784   mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
785   mMeasuredBaseFvIndex++;
786 
787   return Status;
788 }
789 
790 /**
791   Measure main BIOS.
792 
793   @retval EFI_SUCCESS           Operation completed successfully.
794   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
795   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
796 
797 **/
798 EFI_STATUS
MeasureMainBios(VOID)799 MeasureMainBios (
800   VOID
801   )
802 {
803   EFI_STATUS                        Status;
804   EFI_PEI_FV_HANDLE                 VolumeHandle;
805   EFI_FV_INFO                       VolumeInfo;
806   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
807 
808   PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
809 
810   //
811   // Only measure BFV at the very beginning. Other parts of Static Core Root of
812   // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
813   // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
814   // reported by platform will be installed with Fv Info Ppi
815   // This firmware volume measure policy can be modified/enhanced by special
816   // platform for special CRTM TPM measuring.
817   //
818   Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);
819   ASSERT_EFI_ERROR (Status);
820 
821   //
822   // Measure and record the firmware volume that is dispatched by PeiCore
823   //
824   Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
825   ASSERT_EFI_ERROR (Status);
826   //
827   // Locate the corresponding FV_PPI according to founded FV's format guid
828   //
829   Status = PeiServicesLocatePpi (
830              &VolumeInfo.FvFormat,
831              0,
832              NULL,
833              (VOID**)&FvPpi
834              );
835   ASSERT_EFI_ERROR (Status);
836 
837   Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
838 
839   PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
840 
841   return Status;
842 }
843 
844 /**
845   Measure and record the Firmware Volume Information once FvInfoPPI install.
846 
847   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
848   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
849   @param[in] Ppi               Address of the PPI that was installed.
850 
851   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
852   @return Others               Fail to measure FV.
853 
854 **/
855 EFI_STATUS
856 EFIAPI
FirmwareVolumeInfoPpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)857 FirmwareVolumeInfoPpiNotifyCallback (
858   IN EFI_PEI_SERVICES               **PeiServices,
859   IN EFI_PEI_NOTIFY_DESCRIPTOR      *NotifyDescriptor,
860   IN VOID                           *Ppi
861   )
862 {
863   EFI_PEI_FIRMWARE_VOLUME_INFO_PPI  *Fv;
864   EFI_STATUS                        Status;
865   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
866   UINTN                             Index;
867 
868   Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
869 
870   //
871   // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
872   //
873   Status = PeiServicesLocatePpi (
874              &Fv->FvFormat,
875              0,
876              NULL,
877              (VOID**)&FvPpi
878              );
879   if (EFI_ERROR (Status)) {
880     return EFI_SUCCESS;
881   }
882 
883   //
884   // This is an FV from an FFS file, and the parent FV must have already been measured,
885   // No need to measure twice, so just record the FV and return
886   //
887   if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
888 
889     if (mMeasuredChildFvIndex >= mMeasuredMaxChildFvIndex) {
890       mMeasuredChildFvInfo = ReallocatePool (
891                                sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxChildFvIndex,
892                                sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
893                                mMeasuredChildFvInfo
894                                );
895       ASSERT (mMeasuredChildFvInfo != NULL);
896       mMeasuredMaxChildFvIndex = mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
897     }
898     //
899     // Check whether FV is in the measured child FV list.
900     //
901     for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
902       if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {
903         return EFI_SUCCESS;
904       }
905     }
906     mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase   = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
907     mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
908     mMeasuredChildFvIndex++;
909     return EFI_SUCCESS;
910   }
911 
912   return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
913 }
914 
915 /**
916   Do measurement after memory is ready.
917 
918   @param[in]      PeiServices   Describes the list of possible PEI Services.
919 
920   @retval EFI_SUCCESS           Operation completed successfully.
921   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
922   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
923 
924 **/
925 EFI_STATUS
PeimEntryMP(IN EFI_PEI_SERVICES ** PeiServices)926 PeimEntryMP (
927   IN      EFI_PEI_SERVICES          **PeiServices
928   )
929 {
930   EFI_STATUS                        Status;
931 
932   //
933   // install Tcg Services
934   //
935   Status = PeiServicesInstallPpi (&mTcgPpiList);
936   ASSERT_EFI_ERROR (Status);
937 
938   if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
939     Status = MeasureCRTMVersion ();
940   }
941 
942   Status = MeasureMainBios ();
943   if (EFI_ERROR(Status)) {
944     return Status;
945   }
946 
947   //
948   // Post callbacks:
949   // for the FvInfoPpi services to measure and record
950   // the additional Fvs to TPM
951   //
952   Status = PeiServicesNotifyPpi (&mNotifyList[0]);
953   ASSERT_EFI_ERROR (Status);
954 
955   return Status;
956 }
957 
958 /**
959   Measure and log Separator event with error, and extend the measurement result into a specific PCR.
960 
961   @param[in] PCRIndex         PCR index.
962 
963   @retval EFI_SUCCESS         Operation completed successfully.
964   @retval EFI_DEVICE_ERROR    The operation was unsuccessful.
965 
966 **/
967 EFI_STATUS
MeasureSeparatorEventWithError(IN TPM_PCRINDEX PCRIndex)968 MeasureSeparatorEventWithError (
969   IN      TPM_PCRINDEX              PCRIndex
970   )
971 {
972   TCG_PCR_EVENT_HDR                 TcgEvent;
973   UINT32                            EventData;
974 
975   //
976   // Use EventData 0x1 to indicate there is error.
977   //
978   EventData = 0x1;
979   TcgEvent.PCRIndex  = PCRIndex;
980   TcgEvent.EventType = EV_SEPARATOR;
981   TcgEvent.EventSize = (UINT32)sizeof (EventData);
982   return HashLogExtendEvent(&mEdkiiTcgPpi, 0, (UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);
983 }
984 
985 /**
986   Entry point of this module.
987 
988   @param[in] FileHandle   Handle of the file being invoked.
989   @param[in] PeiServices  Describes the list of possible PEI Services.
990 
991   @return Status.
992 
993 **/
994 EFI_STATUS
995 EFIAPI
PeimEntryMA(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)996 PeimEntryMA (
997   IN       EFI_PEI_FILE_HANDLE      FileHandle,
998   IN CONST EFI_PEI_SERVICES         **PeiServices
999   )
1000 {
1001   EFI_STATUS                        Status;
1002   EFI_STATUS                        Status2;
1003   EFI_BOOT_MODE                     BootMode;
1004   TPM_PCRINDEX                      PcrIndex;
1005   BOOLEAN                           S3ErrorReport;
1006 
1007   if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
1008       CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
1009     DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n"));
1010     return EFI_UNSUPPORTED;
1011   }
1012 
1013   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
1014     DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));
1015     return EFI_DEVICE_ERROR;
1016   }
1017 
1018   Status = PeiServicesGetBootMode (&BootMode);
1019   ASSERT_EFI_ERROR (Status);
1020 
1021   //
1022   // In S3 path, skip shadow logic. no measurement is required
1023   //
1024   if (BootMode != BOOT_ON_S3_RESUME) {
1025     Status = (**PeiServices).RegisterForShadow(FileHandle);
1026     if (Status == EFI_ALREADY_STARTED) {
1027       mImageInMemory = TRUE;
1028       mFileHandle = FileHandle;
1029     } else if (Status == EFI_NOT_FOUND) {
1030       ASSERT_EFI_ERROR (Status);
1031     }
1032   }
1033 
1034   if (!mImageInMemory) {
1035     //
1036     // Initialize TPM device
1037     //
1038     Status = Tpm2RequestUseTpm ();
1039     if (EFI_ERROR (Status)) {
1040       DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));
1041       goto Done;
1042     }
1043 
1044     S3ErrorReport = FALSE;
1045     if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
1046       if (BootMode == BOOT_ON_S3_RESUME) {
1047         Status = Tpm2Startup (TPM_SU_STATE);
1048         if (EFI_ERROR (Status) ) {
1049           Status = Tpm2Startup (TPM_SU_CLEAR);
1050           if (!EFI_ERROR(Status)) {
1051             S3ErrorReport = TRUE;
1052           }
1053         }
1054       } else {
1055         Status = Tpm2Startup (TPM_SU_CLEAR);
1056       }
1057       if (EFI_ERROR (Status) ) {
1058         goto Done;
1059       }
1060     }
1061 
1062     //
1063     // Update Tpm2HashMask according to PCR bank.
1064     //
1065     SyncPcrAllocationsAndPcrMask ();
1066 
1067     if (S3ErrorReport) {
1068       //
1069       // The system firmware that resumes from S3 MUST deal with a
1070       // TPM2_Startup error appropriately.
1071       // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
1072       // configuring the device securely by taking actions like extending a
1073       // separator with an error digest (0x01) into PCRs 0 through 7.
1074       //
1075       for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
1076         Status = MeasureSeparatorEventWithError (PcrIndex);
1077         if (EFI_ERROR (Status)) {
1078           DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured. Error!\n"));
1079         }
1080       }
1081     }
1082 
1083     //
1084     // TpmSelfTest is optional on S3 path, skip it to save S3 time
1085     //
1086     if (BootMode != BOOT_ON_S3_RESUME) {
1087       if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
1088         Status = Tpm2SelfTest (NO);
1089         if (EFI_ERROR (Status)) {
1090           goto Done;
1091         }
1092       }
1093     }
1094 
1095     //
1096     // Only install TpmInitializedPpi on success
1097     //
1098     Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
1099     ASSERT_EFI_ERROR (Status);
1100   }
1101 
1102   if (mImageInMemory) {
1103     Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
1104     return Status;
1105   }
1106 
1107 Done:
1108   if (EFI_ERROR (Status)) {
1109     DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n"));
1110     BuildGuidHob (&gTpmErrorHobGuid,0);
1111     REPORT_STATUS_CODE (
1112       EFI_ERROR_CODE | EFI_ERROR_MINOR,
1113       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
1114       );
1115   }
1116   //
1117   // Always install TpmInitializationDonePpi no matter success or fail.
1118   // Other driver can know TPM initialization state by TpmInitializedPpi.
1119   //
1120   Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
1121   ASSERT_EFI_ERROR (Status2);
1122 
1123   return Status;
1124 }
1125