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