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