1 /** @file
2   Initialize TPM device and measure FVs before handing off control to DXE.
3 
4 Copyright (c) 2005 - 2020, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <PiPei.h>
10 
11 #include <IndustryStandard/Tpm12.h>
12 #include <IndustryStandard/UefiTcgPlatform.h>
13 #include <Ppi/FirmwareVolumeInfo.h>
14 #include <Ppi/FirmwareVolumeInfo2.h>
15 #include <Ppi/LockPhysicalPresence.h>
16 #include <Ppi/TpmInitialized.h>
17 #include <Ppi/FirmwareVolume.h>
18 #include <Ppi/EndOfPeiPhase.h>
19 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.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/HobLib.h>
32 #include <Library/PcdLib.h>
33 #include <Library/PeiServicesTablePointerLib.h>
34 #include <Library/BaseLib.h>
35 #include <Library/MemoryAllocationLib.h>
36 #include <Library/ReportStatusCodeLib.h>
37 #include <Library/Tpm12DeviceLib.h>
38 #include <Library/Tpm12CommandLib.h>
39 #include <Library/BaseCryptLib.h>
40 #include <Library/PerformanceLib.h>
41 
42 BOOLEAN                 mImageInMemory  = FALSE;
43 
44 EFI_PEI_PPI_DESCRIPTOR  mTpmInitializedPpiList = {
45   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
46   &gPeiTpmInitializedPpiGuid,
47   NULL
48 };
49 
50 EFI_PEI_PPI_DESCRIPTOR  mTpmInitializationDonePpiList = {
51   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
52   &gPeiTpmInitializationDonePpiGuid,
53   NULL
54 };
55 
56 /**
57   Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
58   and build a GUIDed HOB recording the event which will be passed to the DXE phase and
59   added into the Event Log.
60 
61   @param[in]      This          Indicates the calling context
62   @param[in]      Flags         Bitmap providing additional information.
63   @param[in]      HashData      Physical address of the start of the data buffer
64                                 to be hashed, extended, and logged.
65   @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData.
66   @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
67   @param[in]      NewEventData  Pointer to the new event data.
68 
69   @retval EFI_SUCCESS           Operation completed successfully.
70   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
71   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
72 
73 **/
74 EFI_STATUS
75 EFIAPI
76 HashLogExtendEvent (
77   IN      EDKII_TCG_PPI             *This,
78   IN      UINT64                    Flags,
79   IN      UINT8                     *HashData,
80   IN      UINTN                     HashDataLen,
81   IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
82   IN      UINT8                     *NewEventData
83   );
84 
85 EDKII_TCG_PPI mEdkiiTcgPpi = {
86   HashLogExtendEvent
87 };
88 
89 EFI_PEI_PPI_DESCRIPTOR  mTcgPpiList = {
90   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
91   &gEdkiiTcgPpiGuid,
92   &mEdkiiTcgPpi
93 };
94 
95 //
96 // Number of firmware blobs to grow by each time we run out of room
97 //
98 #define FIRMWARE_BLOB_GROWTH_STEP 4
99 
100 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;
101 UINT32 mMeasuredMaxBaseFvIndex = 0;
102 UINT32 mMeasuredBaseFvIndex = 0;
103 
104 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;
105 UINT32 mMeasuredMaxChildFvIndex = 0;
106 UINT32 mMeasuredChildFvIndex = 0;
107 
108 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
109 
110 /**
111   Lock physical presence if needed.
112 
113   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
114   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
115   @param[in] Ppi               Address of the PPI that was installed.
116 
117   @retval EFI_SUCCESS          Operation completed successfully.
118 
119 **/
120 EFI_STATUS
121 EFIAPI
122 PhysicalPresencePpiNotifyCallback (
123   IN EFI_PEI_SERVICES              **PeiServices,
124   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
125   IN VOID                          *Ppi
126   );
127 
128 /**
129   Measure and record the Firmware Volume Information once FvInfoPPI install.
130 
131   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
132   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
133   @param[in] Ppi               Address of the PPI that was installed.
134 
135   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
136   @return Others               Fail to measure FV.
137 
138 **/
139 EFI_STATUS
140 EFIAPI
141 FirmwareVolumeInfoPpiNotifyCallback (
142   IN EFI_PEI_SERVICES              **PeiServices,
143   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
144   IN VOID                          *Ppi
145   );
146 
147 /**
148   Record all measured Firmware Volume Information into a Guid Hob
149 
150   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
151   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
152   @param[in] Ppi               Address of the PPI that was installed.
153 
154   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
155   @return Others               Fail to measure FV.
156 
157 **/
158 EFI_STATUS
159 EFIAPI
160 EndofPeiSignalNotifyCallBack (
161   IN EFI_PEI_SERVICES              **PeiServices,
162   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
163   IN VOID                          *Ppi
164   );
165 
166 EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
167   {
168     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
169     &gPeiLockPhysicalPresencePpiGuid,
170     PhysicalPresencePpiNotifyCallback
171   },
172   {
173     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
174     &gEfiPeiFirmwareVolumeInfoPpiGuid,
175     FirmwareVolumeInfoPpiNotifyCallback
176   },
177   {
178     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
179     &gEfiPeiFirmwareVolumeInfo2PpiGuid,
180     FirmwareVolumeInfoPpiNotifyCallback
181   },
182   {
183     (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
184     &gEfiEndOfPeiSignalPpiGuid,
185     EndofPeiSignalNotifyCallBack
186   }
187 };
188 
189 /**
190   Record all measured Firmware Volume Information into a Guid Hob
191   Guid Hob payload layout is
192 
193      UINT32 *************************** FIRMWARE_BLOB number
194      EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
195 
196   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
197   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
198   @param[in] Ppi               Address of the PPI that was installed.
199 
200   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
201   @return Others               Fail to measure FV.
202 
203 **/
204 EFI_STATUS
205 EFIAPI
EndofPeiSignalNotifyCallBack(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)206 EndofPeiSignalNotifyCallBack (
207   IN EFI_PEI_SERVICES              **PeiServices,
208   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
209   IN VOID                          *Ppi
210   )
211 {
212   MEASURED_HOB_DATA *MeasuredHobData;
213 
214   MeasuredHobData = NULL;
215 
216   PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid);
217 
218   //
219   // Create a Guid hob to save all measured Fv
220   //
221   MeasuredHobData = BuildGuidHob(
222                       &gMeasuredFvHobGuid,
223                       sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)
224                       );
225 
226   if (MeasuredHobData != NULL){
227     //
228     // Save measured FV info enty number
229     //
230     MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;
231 
232     //
233     // Save measured base Fv info
234     //
235     CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));
236 
237     //
238     // Save measured child Fv info
239     //
240     CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));
241   }
242 
243   PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid);
244 
245   return EFI_SUCCESS;
246 }
247 
248 /**
249 Single function calculates SHA1 digest value for all raw data. It
250 combines Sha1Init(), Sha1Update() and Sha1Final().
251 
252 @param[in]  Data          Raw data to be digested.
253 @param[in]  DataLen       Size of the raw data.
254 @param[out] Digest        Pointer to a buffer that stores the final digest.
255 
256 @retval     EFI_SUCCESS   Always successfully calculate the final digest.
257 **/
258 EFI_STATUS
259 EFIAPI
TpmCommHashAll(IN CONST UINT8 * Data,IN UINTN DataLen,OUT TPM_DIGEST * Digest)260 TpmCommHashAll (
261   IN  CONST UINT8       *Data,
262   IN        UINTN       DataLen,
263   OUT       TPM_DIGEST  *Digest
264   )
265 {
266   VOID   *Sha1Ctx;
267   UINTN  CtxSize;
268 
269   CtxSize = Sha1GetContextSize ();
270   Sha1Ctx = AllocatePool (CtxSize);
271   ASSERT (Sha1Ctx != NULL);
272 
273   Sha1Init (Sha1Ctx);
274   Sha1Update (Sha1Ctx, Data, DataLen);
275   Sha1Final (Sha1Ctx, (UINT8 *)Digest);
276 
277   FreePool (Sha1Ctx);
278 
279   return EFI_SUCCESS;
280 }
281 
282 /**
283   Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
284   and build a GUIDed HOB recording the event which will be passed to the DXE phase and
285   added into the Event Log.
286 
287   @param[in]      This          Indicates the calling context.
288   @param[in]      Flags         Bitmap providing additional information.
289   @param[in]      HashData      Physical address of the start of the data buffer
290                                 to be hashed, extended, and logged.
291   @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData.
292   @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
293   @param[in]      NewEventData  Pointer to the new event data.
294 
295   @retval EFI_SUCCESS           Operation completed successfully.
296   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
297   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
298 
299 **/
300 EFI_STATUS
301 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)302 HashLogExtendEvent (
303   IN      EDKII_TCG_PPI             *This,
304   IN      UINT64                    Flags,
305   IN      UINT8                     *HashData,
306   IN      UINTN                     HashDataLen,
307   IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
308   IN      UINT8                     *NewEventData
309   )
310 {
311   EFI_STATUS                        Status;
312   VOID                              *HobData;
313 
314   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
315     return EFI_DEVICE_ERROR;
316   }
317 
318   HobData = NULL;
319   if (HashDataLen != 0) {
320     Status = TpmCommHashAll (
321                HashData,
322                HashDataLen,
323                &NewEventHdr->Digest
324                );
325     if (EFI_ERROR (Status)) {
326       goto Done;
327     }
328   }
329 
330   Status = Tpm12Extend (
331              &NewEventHdr->Digest,
332              NewEventHdr->PCRIndex,
333              NULL
334              );
335   if (EFI_ERROR (Status)) {
336     goto Done;
337   }
338 
339   HobData = BuildGuidHob (
340              &gTcgEventEntryHobGuid,
341              sizeof (*NewEventHdr) + NewEventHdr->EventSize
342              );
343   if (HobData == NULL) {
344     Status = EFI_OUT_OF_RESOURCES;
345     goto Done;
346   }
347 
348   CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
349   HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
350   CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
351 
352 Done:
353   if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {
354     DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
355     BuildGuidHob (&gTpmErrorHobGuid,0);
356     REPORT_STATUS_CODE (
357       EFI_ERROR_CODE | EFI_ERROR_MINOR,
358       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
359       );
360     Status = EFI_DEVICE_ERROR;
361   }
362   return Status;
363 }
364 
365 /**
366   Measure CRTM version.
367 
368   @param[in]      PeiServices   Describes the list of possible PEI Services.
369 
370   @retval EFI_SUCCESS           Operation completed successfully.
371   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
372   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
373 
374 **/
375 EFI_STATUS
376 EFIAPI
MeasureCRTMVersion(IN EFI_PEI_SERVICES ** PeiServices)377 MeasureCRTMVersion (
378   IN      EFI_PEI_SERVICES          **PeiServices
379   )
380 {
381   TCG_PCR_EVENT_HDR                 TcgEventHdr;
382 
383   //
384   // Use FirmwareVersion string to represent CRTM version.
385   // OEMs should get real CRTM version string and measure it.
386   //
387 
388   TcgEventHdr.PCRIndex  = 0;
389   TcgEventHdr.EventType = EV_S_CRTM_VERSION;
390   TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
391 
392   return HashLogExtendEvent (
393            &mEdkiiTcgPpi,
394            0,
395            (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
396            TcgEventHdr.EventSize,
397            &TcgEventHdr,
398            (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
399            );
400 }
401 
402 /**
403   Measure FV image.
404   Add it into the measured FV list after the FV is measured successfully.
405 
406   @param[in]  FvBase            Base address of FV image.
407   @param[in]  FvLength          Length of FV image.
408 
409   @retval EFI_SUCCESS           Fv image is measured successfully
410                                 or it has been already measured.
411   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
412   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
413 
414 **/
415 EFI_STATUS
416 EFIAPI
MeasureFvImage(IN EFI_PHYSICAL_ADDRESS FvBase,IN UINT64 FvLength)417 MeasureFvImage (
418   IN EFI_PHYSICAL_ADDRESS           FvBase,
419   IN UINT64                         FvLength
420   )
421 {
422   UINT32                            Index;
423   EFI_STATUS                        Status;
424   EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
425   TCG_PCR_EVENT_HDR                 TcgEventHdr;
426   EFI_PHYSICAL_ADDRESS              FvOrgBase;
427   EFI_PHYSICAL_ADDRESS              FvDataBase;
428   EFI_PEI_HOB_POINTERS              Hob;
429   EDKII_MIGRATED_FV_INFO            *MigratedFvInfo;
430 
431   //
432   // Check if it is in Excluded FV list
433   //
434   if (mMeasurementExcludedFvPpi != NULL) {
435     for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
436       if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
437         DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase));
438         DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength));
439         return EFI_SUCCESS;
440       }
441     }
442   }
443 
444   //
445   // Check whether FV is in the measured FV list.
446   //
447   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
448     if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
449       return EFI_SUCCESS;
450     }
451   }
452 
453   //
454   // Search the matched migration FV info
455   //
456   FvOrgBase  = FvBase;
457   FvDataBase = FvBase;
458   Hob.Raw  = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
459   while (Hob.Raw != NULL) {
460     MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
461     if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) {
462       //
463       // Found the migrated FV info
464       //
465       FvOrgBase  = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase;
466       FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase;
467       break;
468     }
469     Hob.Raw = GET_NEXT_HOB (Hob);
470     Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
471   }
472 
473   //
474   // Measure and record the FV to the TPM
475   //
476   FvBlob.BlobBase   = FvOrgBase;
477   FvBlob.BlobLength = FvLength;
478 
479   DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase));
480   DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength));
481 
482   TcgEventHdr.PCRIndex = 0;
483   TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
484   TcgEventHdr.EventSize = sizeof (FvBlob);
485 
486   Status = HashLogExtendEvent (
487              &mEdkiiTcgPpi,
488              0,
489              (UINT8*) (UINTN) FvDataBase,
490              (UINTN) FvBlob.BlobLength,
491              &TcgEventHdr,
492              (UINT8*) &FvBlob
493              );
494 
495   //
496   // Add new FV into the measured FV list.
497   //
498   if (mMeasuredBaseFvIndex >= mMeasuredMaxBaseFvIndex) {
499     mMeasuredBaseFvInfo = ReallocatePool (
500                             sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxBaseFvIndex,
501                             sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
502                             mMeasuredBaseFvInfo
503                             );
504     ASSERT (mMeasuredBaseFvInfo != NULL);
505     mMeasuredMaxBaseFvIndex = mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
506   }
507 
508   mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase   = FvBase;
509   mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
510   mMeasuredBaseFvIndex++;
511 
512   return Status;
513 }
514 
515 /**
516   Measure main BIOS.
517 
518   @param[in]      PeiServices   Describes the list of possible PEI Services.
519 
520   @retval EFI_SUCCESS           Operation completed successfully.
521   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
522   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
523 
524 **/
525 EFI_STATUS
526 EFIAPI
MeasureMainBios(IN EFI_PEI_SERVICES ** PeiServices)527 MeasureMainBios (
528   IN      EFI_PEI_SERVICES          **PeiServices
529   )
530 {
531   EFI_STATUS                        Status;
532   UINT32                            FvInstances;
533   EFI_PEI_FV_HANDLE                 VolumeHandle;
534   EFI_FV_INFO                       VolumeInfo;
535   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
536 
537   FvInstances    = 0;
538   while (TRUE) {
539     //
540     // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
541     // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
542     // platform for special CRTM TPM measuring.
543     //
544     Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
545     if (EFI_ERROR (Status)) {
546       break;
547     }
548 
549     //
550     // Measure and record the firmware volume that is dispatched by PeiCore
551     //
552     Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
553     ASSERT_EFI_ERROR (Status);
554     //
555     // Locate the corresponding FV_PPI according to founded FV's format guid
556     //
557     Status = PeiServicesLocatePpi (
558                &VolumeInfo.FvFormat,
559                0,
560                NULL,
561                (VOID**)&FvPpi
562                );
563     if (!EFI_ERROR (Status)) {
564       MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
565     }
566 
567     FvInstances++;
568   }
569 
570   return EFI_SUCCESS;
571 }
572 
573 /**
574   Measure and record the Firmware Volume Information once FvInfoPPI install.
575 
576   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
577   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
578   @param[in] Ppi               Address of the PPI that was installed.
579 
580   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
581   @return Others               Fail to measure FV.
582 
583 **/
584 EFI_STATUS
585 EFIAPI
FirmwareVolumeInfoPpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)586 FirmwareVolumeInfoPpiNotifyCallback (
587   IN EFI_PEI_SERVICES               **PeiServices,
588   IN EFI_PEI_NOTIFY_DESCRIPTOR      *NotifyDescriptor,
589   IN VOID                           *Ppi
590   )
591 {
592   EFI_PEI_FIRMWARE_VOLUME_INFO_PPI  *Fv;
593   EFI_STATUS                        Status;
594   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
595   UINTN                             Index;
596 
597   Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
598 
599   //
600   // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
601   //
602   Status = PeiServicesLocatePpi (
603              &Fv->FvFormat,
604              0,
605              NULL,
606              (VOID**)&FvPpi
607              );
608   if (EFI_ERROR (Status)) {
609     return EFI_SUCCESS;
610   }
611 
612   //
613   // This is an FV from an FFS file, and the parent FV must have already been measured,
614   // No need to measure twice, so just record the FV and return
615   //
616   if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
617 
618     if (mMeasuredChildFvIndex >= mMeasuredMaxChildFvIndex) {
619       mMeasuredChildFvInfo = ReallocatePool (
620                                sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxChildFvIndex,
621                                sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
622                                mMeasuredChildFvInfo
623                                );
624       ASSERT (mMeasuredChildFvInfo != NULL);
625       mMeasuredMaxChildFvIndex = mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
626     }
627     //
628     // Check whether FV is in the measured child FV list.
629     //
630     for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
631       if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {
632         return EFI_SUCCESS;
633       }
634     }
635     mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase   = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
636     mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
637     mMeasuredChildFvIndex++;
638     return EFI_SUCCESS;
639   }
640 
641   return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
642 }
643 
644 /**
645   Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.
646   And lock physical presence if needed.
647 
648   @param[in] PeiServices        An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
649   @param[in] NotifyDescriptor   Address of the notification descriptor data structure.
650   @param[in] Ppi                Address of the PPI that was installed.
651 
652   @retval EFI_SUCCESS           Operation completed successfully.
653   @retval EFI_ABORTED           physicalPresenceCMDEnable is locked.
654   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
655 
656 **/
657 EFI_STATUS
658 EFIAPI
PhysicalPresencePpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)659 PhysicalPresencePpiNotifyCallback (
660   IN EFI_PEI_SERVICES               **PeiServices,
661   IN EFI_PEI_NOTIFY_DESCRIPTOR      *NotifyDescriptor,
662   IN VOID                           *Ppi
663   )
664 {
665   EFI_STATUS                        Status;
666   TPM_PERMANENT_FLAGS               TpmPermanentFlags;
667   PEI_LOCK_PHYSICAL_PRESENCE_PPI    *LockPhysicalPresencePpi;
668   TPM_PHYSICAL_PRESENCE             PhysicalPresenceValue;
669 
670   Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);
671   if (EFI_ERROR (Status)) {
672     return Status;
673   }
674 
675   //
676   // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.
677   //
678   if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !TpmPermanentFlags.physicalPresenceLifetimeLock) {
679     //
680     // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.
681     //
682     PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK;
683     TpmPermanentFlags.physicalPresenceLifetimeLock = TRUE;
684 
685     if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) {
686       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE;
687       TpmPermanentFlags.physicalPresenceCMDEnable = TRUE;
688     } else {
689       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE;
690       TpmPermanentFlags.physicalPresenceCMDEnable = FALSE;
691     }
692 
693     if (PcdGetBool (PcdPhysicalPresenceHwEnable)) {
694       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE;
695     } else {
696       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE;
697     }
698 
699     Status = Tpm12PhysicalPresence (
700                PhysicalPresenceValue
701                );
702     if (EFI_ERROR (Status)) {
703       return Status;
704     }
705   }
706 
707   //
708   // 2. Lock physical presence if it is required.
709   //
710   LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi;
711   if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) {
712     return EFI_SUCCESS;
713   }
714 
715   if (!TpmPermanentFlags.physicalPresenceCMDEnable) {
716     if (TpmPermanentFlags.physicalPresenceLifetimeLock) {
717       //
718       // physicalPresenceCMDEnable is locked, can't change.
719       //
720       return EFI_ABORTED;
721     }
722 
723     //
724     // Enable physical presence command
725     // It is necessary in order to lock physical presence
726     //
727     Status = Tpm12PhysicalPresence (
728                TPM_PHYSICAL_PRESENCE_CMD_ENABLE
729                );
730     if (EFI_ERROR (Status)) {
731       return Status;
732     }
733   }
734 
735   //
736   // Lock physical presence
737   //
738   Status = Tpm12PhysicalPresence (
739               TPM_PHYSICAL_PRESENCE_LOCK
740               );
741   return Status;
742 }
743 
744 /**
745   Check if TPM chip is activated or not.
746 
747   @param[in]      PeiServices   Describes the list of possible PEI Services.
748 
749   @retval TRUE    TPM is activated.
750   @retval FALSE   TPM is deactivated.
751 
752 **/
753 BOOLEAN
IsTpmUsable(VOID)754 IsTpmUsable (
755   VOID
756   )
757 {
758   EFI_STATUS           Status;
759   TPM_PERMANENT_FLAGS  TpmPermanentFlags;
760 
761   Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);
762   if (EFI_ERROR (Status)) {
763     return FALSE;
764   }
765   return (BOOLEAN)(!TpmPermanentFlags.deactivated);
766 }
767 
768 /**
769   Do measurement after memory is ready.
770 
771   @param[in]      PeiServices   Describes the list of possible PEI Services.
772 
773   @retval EFI_SUCCESS           Operation completed successfully.
774   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
775   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
776 
777 **/
778 EFI_STATUS
779 EFIAPI
PeimEntryMP(IN EFI_PEI_SERVICES ** PeiServices)780 PeimEntryMP (
781   IN      EFI_PEI_SERVICES          **PeiServices
782   )
783 {
784   EFI_STATUS                        Status;
785 
786   Status = PeiServicesLocatePpi (
787                &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
788                0,
789                NULL,
790                (VOID**)&mMeasurementExcludedFvPpi
791                );
792   // Do not check status, because it is optional
793 
794   Status = Tpm12RequestUseTpm ();
795   if (EFI_ERROR (Status)) {
796     return Status;
797   }
798 
799   if (IsTpmUsable ()) {
800     if (PcdGet8 (PcdTpmScrtmPolicy) == 1) {
801       Status = MeasureCRTMVersion (PeiServices);
802     }
803 
804     Status = MeasureMainBios (PeiServices);
805   }
806 
807   //
808   // Post callbacks:
809   // 1). for the FvInfoPpi services to measure and record
810   // the additional Fvs to TPM
811   // 2). for the OperatorPresencePpi service to determine whether to
812   // lock the TPM
813   //
814   Status = PeiServicesNotifyPpi (&mNotifyList[0]);
815   ASSERT_EFI_ERROR (Status);
816 
817   //
818   // install Tcg Services
819   //
820   Status = PeiServicesInstallPpi (&mTcgPpiList);
821   ASSERT_EFI_ERROR (Status);
822 
823   return Status;
824 }
825 
826 /**
827   Entry point of this module.
828 
829   @param[in] FileHandle   Handle of the file being invoked.
830   @param[in] PeiServices  Describes the list of possible PEI Services.
831 
832   @return Status.
833 
834 **/
835 EFI_STATUS
836 EFIAPI
PeimEntryMA(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)837 PeimEntryMA (
838   IN       EFI_PEI_FILE_HANDLE      FileHandle,
839   IN CONST EFI_PEI_SERVICES         **PeiServices
840   )
841 {
842   EFI_STATUS                        Status;
843   EFI_STATUS                        Status2;
844   EFI_BOOT_MODE                     BootMode;
845 
846   if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
847     DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));
848     return EFI_UNSUPPORTED;
849   }
850 
851   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
852     DEBUG ((EFI_D_ERROR, "TPM error!\n"));
853     return EFI_DEVICE_ERROR;
854   }
855 
856   //
857   // Initialize TPM device
858   //
859   Status = PeiServicesGetBootMode (&BootMode);
860   ASSERT_EFI_ERROR (Status);
861 
862   //
863   // In S3 path, skip shadow logic. no measurement is required
864   //
865   if (BootMode != BOOT_ON_S3_RESUME) {
866     Status = (**PeiServices).RegisterForShadow(FileHandle);
867     if (Status == EFI_ALREADY_STARTED) {
868       mImageInMemory = TRUE;
869     } else if (Status == EFI_NOT_FOUND) {
870       ASSERT_EFI_ERROR (Status);
871     }
872   }
873 
874   if (!mImageInMemory) {
875     Status = Tpm12RequestUseTpm ();
876     if (EFI_ERROR (Status)) {
877       DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));
878       goto Done;
879     }
880 
881     if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {
882       if (BootMode == BOOT_ON_S3_RESUME) {
883         Status = Tpm12Startup (TPM_ST_STATE);
884       } else {
885         Status = Tpm12Startup (TPM_ST_CLEAR);
886       }
887       if (EFI_ERROR (Status) ) {
888         goto Done;
889       }
890     }
891 
892     //
893     // TpmSelfTest is optional on S3 path, skip it to save S3 time
894     //
895     if (BootMode != BOOT_ON_S3_RESUME) {
896       Status = Tpm12ContinueSelfTest ();
897       if (EFI_ERROR (Status)) {
898         goto Done;
899       }
900     }
901 
902     //
903     // Only install TpmInitializedPpi on success
904     //
905     Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
906     ASSERT_EFI_ERROR (Status);
907   }
908 
909   if (mImageInMemory) {
910     Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
911     return Status;
912   }
913 
914 Done:
915   if (EFI_ERROR (Status)) {
916     DEBUG ((EFI_D_ERROR, "TPM error! Build Hob\n"));
917     BuildGuidHob (&gTpmErrorHobGuid,0);
918     REPORT_STATUS_CODE (
919       EFI_ERROR_CODE | EFI_ERROR_MINOR,
920       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
921       );
922   }
923   //
924   // Always install TpmInitializationDonePpi no matter success or fail.
925   // Other driver can know TPM initialization state by TpmInitializedPpi.
926   //
927   Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
928   ASSERT_EFI_ERROR (Status2);
929 
930   return Status;
931 }
932