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