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