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