]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
SecurityPkg Tcg2Pei: Fix GCC build failure caused by 5919a9600e07
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Pei / Tcg2Pei.c
1 /** @file
2 Initialize TPM2 device and measure FVs before handing off control to DXE.
3
4 Copyright (c) 2015 - 2016, 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/UefiTcgPlatform.h>
18 #include <Ppi/FirmwareVolumeInfo.h>
19 #include <Ppi/FirmwareVolumeInfo2.h>
20 #include <Ppi/LockPhysicalPresence.h>
21 #include <Ppi/TpmInitialized.h>
22 #include <Ppi/FirmwareVolume.h>
23 #include <Ppi/EndOfPeiPhase.h>
24 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
25
26 #include <Guid/TcgEventHob.h>
27 #include <Guid/MeasuredFvHob.h>
28 #include <Guid/TpmInstance.h>
29
30 #include <Library/DebugLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/PeiServicesLib.h>
33 #include <Library/PeimEntryPoint.h>
34 #include <Library/Tpm2CommandLib.h>
35 #include <Library/Tpm2DeviceLib.h>
36 #include <Library/HashLib.h>
37 #include <Library/HobLib.h>
38 #include <Library/PcdLib.h>
39 #include <Library/PeiServicesTablePointerLib.h>
40 #include <Protocol/Tcg2Protocol.h>
41 #include <Library/PerformanceLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/ReportStatusCodeLib.h>
44 #include <Library/ResetSystemLib.h>
45 #include <Library/Tcg2PhysicalPresenceLib.h>
46
47 #define PERF_ID_TCG2_PEI 0x3080
48
49 typedef struct {
50 EFI_GUID *EventGuid;
51 EFI_TCG2_EVENT_LOG_FORMAT LogFormat;
52 } TCG2_EVENT_INFO_STRUCT;
53
54 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = {
55 {&gTcgEventEntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2},
56 {&gTcgEvent2EntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2},
57 };
58
59 BOOLEAN mImageInMemory = FALSE;
60 EFI_PEI_FILE_HANDLE mFileHandle;
61
62 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {
63 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
64 &gPeiTpmInitializedPpiGuid,
65 NULL
66 };
67
68 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
69 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
70 &gPeiTpmInitializationDonePpiGuid,
71 NULL
72 };
73
74 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;
75 UINT32 mMeasuredBaseFvIndex = 0;
76
77 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;
78 UINT32 mMeasuredChildFvIndex = 0;
79
80 /**
81 Measure and record the Firmware Volum Information once FvInfoPPI install.
82
83 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
84 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
85 @param[in] Ppi Address of the PPI that was installed.
86
87 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
88 @return Others Fail to measure FV.
89
90 **/
91 EFI_STATUS
92 EFIAPI
93 FirmwareVolmeInfoPpiNotifyCallback (
94 IN EFI_PEI_SERVICES **PeiServices,
95 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
96 IN VOID *Ppi
97 );
98
99 /**
100 Record all measured Firmware Volum Information into a Guid Hob
101
102 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
103 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
104 @param[in] Ppi Address of the PPI that was installed.
105
106 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
107 @return Others Fail to measure FV.
108
109 **/
110 EFI_STATUS
111 EFIAPI
112 EndofPeiSignalNotifyCallBack (
113 IN EFI_PEI_SERVICES **PeiServices,
114 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
115 IN VOID *Ppi
116 );
117
118 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
119 {
120 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
121 &gEfiPeiFirmwareVolumeInfoPpiGuid,
122 FirmwareVolmeInfoPpiNotifyCallback
123 },
124 {
125 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
126 &gEfiPeiFirmwareVolumeInfo2PpiGuid,
127 FirmwareVolmeInfoPpiNotifyCallback
128 },
129 {
130 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
131 &gEfiEndOfPeiSignalPpiGuid,
132 EndofPeiSignalNotifyCallBack
133 }
134 };
135
136 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
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 Make sure that the current PCR allocations, the TPM supported PCRs,
195 and the PcdTpm2HashMask are all in agreement.
196 **/
197 VOID
198 SyncPcrAllocationsAndPcrMask (
199 VOID
200 )
201 {
202 EFI_STATUS Status;
203 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap;
204 UINT32 TpmActivePcrBanks;
205 UINT32 NewTpmActivePcrBanks;
206 UINT32 Tpm2PcrMask;
207 UINT32 NewTpm2PcrMask;
208
209 DEBUG ((EFI_D_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));
210
211 //
212 // Determine the current TPM support and the Platform PCR mask.
213 //
214 Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &TpmActivePcrBanks);
215 ASSERT_EFI_ERROR (Status);
216
217 Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
218
219 //
220 // Find the intersection of Pcd support and TPM support.
221 // If banks are missing from the TPM support that are in the PCD, update the PCD.
222 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
223 //
224
225 //
226 // If there are active PCR banks that are not supported by the Platform mask,
227 // update the TPM allocations and reboot the machine.
228 //
229 if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) {
230 NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask;
231
232 DEBUG ((EFI_D_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
233 if (NewTpmActivePcrBanks == 0) {
234 DEBUG ((EFI_D_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
235 ASSERT (FALSE);
236 } else {
237 Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap, NewTpmActivePcrBanks);
238 if (EFI_ERROR (Status)) {
239 //
240 // We can't do much here, but we hope that this doesn't happen.
241 //
242 DEBUG ((EFI_D_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__));
243 ASSERT_EFI_ERROR (Status);
244 }
245 //
246 // Need reset system, since we just called Tpm2PcrAllocateBanks().
247 //
248 ResetCold();
249 }
250 }
251
252 //
253 // If there are any PCRs that claim support in the Platform mask that are
254 // not supported by the TPM, update the mask.
255 //
256 if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) {
257 NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap;
258
259 DEBUG ((EFI_D_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));
260 if (NewTpm2PcrMask == 0) {
261 DEBUG ((EFI_D_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
262 ASSERT (FALSE);
263 }
264
265 Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);
266 ASSERT_EFI_ERROR (Status);
267 }
268 }
269
270 /**
271 Add a new entry to the Event Log.
272
273 @param[in] DigestList A list of digest.
274 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
275 @param[in] NewEventData Pointer to the new event data.
276
277 @retval EFI_SUCCESS The new event log entry was added.
278 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
279 **/
280 EFI_STATUS
281 LogHashEvent (
282 IN TPML_DIGEST_VALUES *DigestList,
283 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
284 IN UINT8 *NewEventData
285 )
286 {
287 VOID *HobData;
288 EFI_STATUS Status;
289 UINTN Index;
290 EFI_STATUS RetStatus;
291 UINT32 SupportedEventLogs;
292 TCG_PCR_EVENT2 *TcgPcrEvent2;
293 UINT8 *DigestBuffer;
294
295 SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
296
297 RetStatus = EFI_SUCCESS;
298 for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) {
299 if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
300 DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));
301 switch (mTcg2EventInfo[Index].LogFormat) {
302 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
303 Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
304 if (!EFI_ERROR (Status)) {
305 HobData = BuildGuidHob (
306 &gTcgEventEntryHobGuid,
307 sizeof (*NewEventHdr) + NewEventHdr->EventSize
308 );
309 if (HobData == NULL) {
310 RetStatus = EFI_OUT_OF_RESOURCES;
311 break;
312 }
313
314 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
315 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
316 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
317 }
318 break;
319 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
320 HobData = BuildGuidHob (
321 &gTcgEvent2EntryHobGuid,
322 sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
323 );
324 if (HobData == NULL) {
325 RetStatus = EFI_OUT_OF_RESOURCES;
326 break;
327 }
328
329 TcgPcrEvent2 = HobData;
330 TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
331 TcgPcrEvent2->EventType = NewEventHdr->EventType;
332 DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
333 DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));
334 CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize));
335 DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);
336 CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
337 break;
338 }
339 }
340 }
341
342 return RetStatus;
343 }
344
345 /**
346 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
347 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
348 added into the Event Log.
349
350 @param[in] Flags Bitmap providing additional information.
351 @param[in] HashData Physical address of the start of the data buffer
352 to be hashed, extended, and logged.
353 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
354 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
355 @param[in] NewEventData Pointer to the new event data.
356
357 @retval EFI_SUCCESS Operation completed successfully.
358 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
359 @retval EFI_DEVICE_ERROR The command was unsuccessful.
360
361 **/
362 EFI_STATUS
363 HashLogExtendEvent (
364 IN UINT64 Flags,
365 IN UINT8 *HashData,
366 IN UINTN HashDataLen,
367 IN TCG_PCR_EVENT_HDR *NewEventHdr,
368 IN UINT8 *NewEventData
369 )
370 {
371 EFI_STATUS Status;
372 TPML_DIGEST_VALUES DigestList;
373
374 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
375 return EFI_DEVICE_ERROR;
376 }
377
378 Status = HashAndExtend (
379 NewEventHdr->PCRIndex,
380 HashData,
381 HashDataLen,
382 &DigestList
383 );
384 if (!EFI_ERROR (Status)) {
385 if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) {
386 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
387 }
388 }
389
390 if (Status == EFI_DEVICE_ERROR) {
391 DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
392 BuildGuidHob (&gTpmErrorHobGuid,0);
393 REPORT_STATUS_CODE (
394 EFI_ERROR_CODE | EFI_ERROR_MINOR,
395 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
396 );
397 }
398
399 return Status;
400 }
401
402 /**
403 Measure CRTM version.
404
405 @retval EFI_SUCCESS Operation completed successfully.
406 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
407 @retval EFI_DEVICE_ERROR The command was unsuccessful.
408
409 **/
410 EFI_STATUS
411 MeasureCRTMVersion (
412 VOID
413 )
414 {
415 TCG_PCR_EVENT_HDR TcgEventHdr;
416
417 //
418 // Use FirmwareVersion string to represent CRTM version.
419 // OEMs should get real CRTM version string and measure it.
420 //
421
422 TcgEventHdr.PCRIndex = 0;
423 TcgEventHdr.EventType = EV_S_CRTM_VERSION;
424 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
425
426 return HashLogExtendEvent (
427 0,
428 (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
429 TcgEventHdr.EventSize,
430 &TcgEventHdr,
431 (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
432 );
433 }
434
435 /**
436 Measure FV image.
437 Add it into the measured FV list after the FV is measured successfully.
438
439 @param[in] FvBase Base address of FV image.
440 @param[in] FvLength Length of FV image.
441
442 @retval EFI_SUCCESS Fv image is measured successfully
443 or it has been already measured.
444 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
445 @retval EFI_DEVICE_ERROR The command was unsuccessful.
446
447 **/
448 EFI_STATUS
449 MeasureFvImage (
450 IN EFI_PHYSICAL_ADDRESS FvBase,
451 IN UINT64 FvLength
452 )
453 {
454 UINT32 Index;
455 EFI_STATUS Status;
456 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
457 TCG_PCR_EVENT_HDR TcgEventHdr;
458
459 //
460 // Check if it is in Excluded FV list
461 //
462 if (mMeasurementExcludedFvPpi != NULL) {
463 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
464 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
465 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
466 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
467 return EFI_SUCCESS;
468 }
469 }
470 }
471
472 //
473 // Check whether FV is in the measured FV list.
474 //
475 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
476 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
477 return EFI_SUCCESS;
478 }
479 }
480
481 //
482 // Measure and record the FV to the TPM
483 //
484 FvBlob.BlobBase = FvBase;
485 FvBlob.BlobLength = FvLength;
486
487 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
488 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
489
490 TcgEventHdr.PCRIndex = 0;
491 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
492 TcgEventHdr.EventSize = sizeof (FvBlob);
493
494 Status = HashLogExtendEvent (
495 0,
496 (UINT8*) (UINTN) FvBlob.BlobBase,
497 (UINTN) FvBlob.BlobLength,
498 &TcgEventHdr,
499 (UINT8*) &FvBlob
500 );
501
502 //
503 // Add new FV into the measured FV list.
504 //
505 ASSERT (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
506 if (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
507 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;
508 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
509 mMeasuredBaseFvIndex++;
510 }
511
512 return Status;
513 }
514
515 /**
516 Measure main BIOS.
517
518 @retval EFI_SUCCESS Operation completed successfully.
519 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
520 @retval EFI_DEVICE_ERROR The command was unsuccessful.
521
522 **/
523 EFI_STATUS
524 MeasureMainBios (
525 VOID
526 )
527 {
528 EFI_STATUS Status;
529 UINT32 FvInstances;
530 EFI_PEI_FV_HANDLE VolumeHandle;
531 EFI_FV_INFO VolumeInfo;
532 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
533
534 PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
535 FvInstances = 0;
536 while (TRUE) {
537 //
538 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
539 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
540 // platform for special CRTM TPM measuring.
541 //
542 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
543 if (EFI_ERROR (Status)) {
544 break;
545 }
546
547 //
548 // Measure and record the firmware volume that is dispatched by PeiCore
549 //
550 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
551 ASSERT_EFI_ERROR (Status);
552 //
553 // Locate the corresponding FV_PPI according to founded FV's format guid
554 //
555 Status = PeiServicesLocatePpi (
556 &VolumeInfo.FvFormat,
557 0,
558 NULL,
559 (VOID**)&FvPpi
560 );
561 if (!EFI_ERROR (Status)) {
562 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
563 }
564
565 FvInstances++;
566 }
567 PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
568
569 return EFI_SUCCESS;
570 }
571
572 /**
573 Measure and record the Firmware Volum Information once FvInfoPPI install.
574
575 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
576 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
577 @param[in] Ppi Address of the PPI that was installed.
578
579 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
580 @return Others Fail to measure FV.
581
582 **/
583 EFI_STATUS
584 EFIAPI
585 FirmwareVolmeInfoPpiNotifyCallback (
586 IN EFI_PEI_SERVICES **PeiServices,
587 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
588 IN VOID *Ppi
589 )
590 {
591 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
592 EFI_STATUS Status;
593 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
594 UINTN Index;
595
596 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
597
598 //
599 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
600 //
601 Status = PeiServicesLocatePpi (
602 &Fv->FvFormat,
603 0,
604 NULL,
605 (VOID**)&FvPpi
606 );
607 if (EFI_ERROR (Status)) {
608 return EFI_SUCCESS;
609 }
610
611 //
612 // This is an FV from an FFS file, and the parent FV must have already been measured,
613 // No need to measure twice, so just record the FV and return
614 //
615 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
616
617 ASSERT (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
618 if (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
619 //
620 // Check whether FV is in the measured child FV list.
621 //
622 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
623 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {
624 return EFI_SUCCESS;
625 }
626 }
627 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
628 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
629 mMeasuredChildFvIndex++;
630 }
631 return EFI_SUCCESS;
632 }
633
634 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
635 }
636
637 /**
638 Do measurement after memory is ready.
639
640 @param[in] PeiServices Describes the list of possible PEI Services.
641
642 @retval EFI_SUCCESS Operation completed successfully.
643 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
644 @retval EFI_DEVICE_ERROR The command was unsuccessful.
645
646 **/
647 EFI_STATUS
648 PeimEntryMP (
649 IN EFI_PEI_SERVICES **PeiServices
650 )
651 {
652 EFI_STATUS Status;
653
654 Status = PeiServicesLocatePpi (
655 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
656 0,
657 NULL,
658 (VOID**)&mMeasurementExcludedFvPpi
659 );
660 // Do not check status, because it is optional
661
662 mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
663 ASSERT (mMeasuredBaseFvInfo != NULL);
664 mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
665 ASSERT (mMeasuredChildFvInfo != NULL);
666
667 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
668 Status = MeasureCRTMVersion ();
669 }
670
671 Status = MeasureMainBios ();
672
673 //
674 // Post callbacks:
675 // for the FvInfoPpi services to measure and record
676 // the additional Fvs to TPM
677 //
678 Status = PeiServicesNotifyPpi (&mNotifyList[0]);
679 ASSERT_EFI_ERROR (Status);
680
681 return Status;
682 }
683
684 /**
685 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
686
687 @param[in] PCRIndex PCR index.
688
689 @retval EFI_SUCCESS Operation completed successfully.
690 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
691
692 **/
693 EFI_STATUS
694 MeasureSeparatorEventWithError (
695 IN TPM_PCRINDEX PCRIndex
696 )
697 {
698 TCG_PCR_EVENT_HDR TcgEvent;
699 UINT32 EventData;
700
701 //
702 // Use EventData 0x1 to indicate there is error.
703 //
704 EventData = 0x1;
705 TcgEvent.PCRIndex = PCRIndex;
706 TcgEvent.EventType = EV_SEPARATOR;
707 TcgEvent.EventSize = (UINT32)sizeof (EventData);
708 return HashLogExtendEvent(0,(UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);
709 }
710
711 /**
712 Entry point of this module.
713
714 @param[in] FileHandle Handle of the file being invoked.
715 @param[in] PeiServices Describes the list of possible PEI Services.
716
717 @return Status.
718
719 **/
720 EFI_STATUS
721 EFIAPI
722 PeimEntryMA (
723 IN EFI_PEI_FILE_HANDLE FileHandle,
724 IN CONST EFI_PEI_SERVICES **PeiServices
725 )
726 {
727 EFI_STATUS Status;
728 EFI_STATUS Status2;
729 EFI_BOOT_MODE BootMode;
730 TPM_PCRINDEX PcrIndex;
731 BOOLEAN S3ErrorReport;
732
733 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
734 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
735 DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));
736 return EFI_UNSUPPORTED;
737 }
738
739 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
740 DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));
741 return EFI_DEVICE_ERROR;
742 }
743
744 Status = PeiServicesGetBootMode (&BootMode);
745 ASSERT_EFI_ERROR (Status);
746
747 //
748 // In S3 path, skip shadow logic. no measurement is required
749 //
750 if (BootMode != BOOT_ON_S3_RESUME) {
751 Status = (**PeiServices).RegisterForShadow(FileHandle);
752 if (Status == EFI_ALREADY_STARTED) {
753 mImageInMemory = TRUE;
754 mFileHandle = FileHandle;
755 } else if (Status == EFI_NOT_FOUND) {
756 ASSERT_EFI_ERROR (Status);
757 }
758 }
759
760 if (!mImageInMemory) {
761 //
762 // Initialize TPM device
763 //
764 Status = Tpm2RequestUseTpm ();
765 if (EFI_ERROR (Status)) {
766 DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));
767 goto Done;
768 }
769
770 S3ErrorReport = FALSE;
771 if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
772 if (BootMode == BOOT_ON_S3_RESUME) {
773 Status = Tpm2Startup (TPM_SU_STATE);
774 if (EFI_ERROR (Status) ) {
775 Status = Tpm2Startup (TPM_SU_CLEAR);
776 if (!EFI_ERROR(Status)) {
777 S3ErrorReport = TRUE;
778 }
779 }
780 } else {
781 Status = Tpm2Startup (TPM_SU_CLEAR);
782 }
783 if (EFI_ERROR (Status) ) {
784 goto Done;
785 }
786 }
787
788 //
789 // Update Tpm2HashMask according to PCR bank.
790 //
791 SyncPcrAllocationsAndPcrMask ();
792
793 if (S3ErrorReport) {
794 //
795 // The system firmware that resumes from S3 MUST deal with a
796 // TPM2_Startup error appropriately.
797 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
798 // configuring the device securely by taking actions like extending a
799 // separator with an error digest (0x01) into PCRs 0 through 7.
800 //
801 for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
802 Status = MeasureSeparatorEventWithError (PcrIndex);
803 if (EFI_ERROR (Status)) {
804 DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured. Error!\n"));
805 }
806 }
807 }
808
809 //
810 // TpmSelfTest is optional on S3 path, skip it to save S3 time
811 //
812 if (BootMode != BOOT_ON_S3_RESUME) {
813 if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
814 Status = Tpm2SelfTest (NO);
815 if (EFI_ERROR (Status)) {
816 goto Done;
817 }
818 }
819 }
820
821 //
822 // Only intall TpmInitializedPpi on success
823 //
824 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
825 ASSERT_EFI_ERROR (Status);
826 }
827
828 if (mImageInMemory) {
829 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
830 return Status;
831 }
832
833 Done:
834 if (EFI_ERROR (Status)) {
835 DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n"));
836 BuildGuidHob (&gTpmErrorHobGuid,0);
837 REPORT_STATUS_CODE (
838 EFI_ERROR_CODE | EFI_ERROR_MINOR,
839 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
840 );
841 }
842 //
843 // Always intall TpmInitializationDonePpi no matter success or fail.
844 // Other driver can know TPM initialization state by TpmInitializedPpi.
845 //
846 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
847 ASSERT_EFI_ERROR (Status2);
848
849 return Status;
850 }