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