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