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