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