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