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