]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
SecurityPkg Tcg2Pei: Add comments into LogHashEvent()
[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 //
321 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
322 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
323 //
324 HobData = BuildGuidHob (
325 &gTcgEvent2EntryHobGuid,
326 sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
327 );
328 if (HobData == NULL) {
329 RetStatus = EFI_OUT_OF_RESOURCES;
330 break;
331 }
332
333 TcgPcrEvent2 = HobData;
334 TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
335 TcgPcrEvent2->EventType = NewEventHdr->EventType;
336 DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
337 DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));
338 CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize));
339 DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);
340 CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
341 break;
342 }
343 }
344 }
345
346 return RetStatus;
347 }
348
349 /**
350 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
351 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
352 added into the Event Log.
353
354 @param[in] Flags Bitmap providing additional information.
355 @param[in] HashData Physical address of the start of the data buffer
356 to be hashed, extended, and logged.
357 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
358 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
359 @param[in] NewEventData Pointer to the new event data.
360
361 @retval EFI_SUCCESS Operation completed successfully.
362 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
363 @retval EFI_DEVICE_ERROR The command was unsuccessful.
364
365 **/
366 EFI_STATUS
367 HashLogExtendEvent (
368 IN UINT64 Flags,
369 IN UINT8 *HashData,
370 IN UINTN HashDataLen,
371 IN TCG_PCR_EVENT_HDR *NewEventHdr,
372 IN UINT8 *NewEventData
373 )
374 {
375 EFI_STATUS Status;
376 TPML_DIGEST_VALUES DigestList;
377
378 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
379 return EFI_DEVICE_ERROR;
380 }
381
382 Status = HashAndExtend (
383 NewEventHdr->PCRIndex,
384 HashData,
385 HashDataLen,
386 &DigestList
387 );
388 if (!EFI_ERROR (Status)) {
389 if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) {
390 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
391 }
392 }
393
394 if (Status == EFI_DEVICE_ERROR) {
395 DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
396 BuildGuidHob (&gTpmErrorHobGuid,0);
397 REPORT_STATUS_CODE (
398 EFI_ERROR_CODE | EFI_ERROR_MINOR,
399 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
400 );
401 }
402
403 return Status;
404 }
405
406 /**
407 Measure CRTM version.
408
409 @retval EFI_SUCCESS Operation completed successfully.
410 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
411 @retval EFI_DEVICE_ERROR The command was unsuccessful.
412
413 **/
414 EFI_STATUS
415 MeasureCRTMVersion (
416 VOID
417 )
418 {
419 TCG_PCR_EVENT_HDR TcgEventHdr;
420
421 //
422 // Use FirmwareVersion string to represent CRTM version.
423 // OEMs should get real CRTM version string and measure it.
424 //
425
426 TcgEventHdr.PCRIndex = 0;
427 TcgEventHdr.EventType = EV_S_CRTM_VERSION;
428 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
429
430 return HashLogExtendEvent (
431 0,
432 (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
433 TcgEventHdr.EventSize,
434 &TcgEventHdr,
435 (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
436 );
437 }
438
439 /**
440 Measure FV image.
441 Add it into the measured FV list after the FV is measured successfully.
442
443 @param[in] FvBase Base address of FV image.
444 @param[in] FvLength Length of FV image.
445
446 @retval EFI_SUCCESS Fv image is measured successfully
447 or it has been already measured.
448 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
449 @retval EFI_DEVICE_ERROR The command was unsuccessful.
450
451 **/
452 EFI_STATUS
453 MeasureFvImage (
454 IN EFI_PHYSICAL_ADDRESS FvBase,
455 IN UINT64 FvLength
456 )
457 {
458 UINT32 Index;
459 EFI_STATUS Status;
460 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
461 TCG_PCR_EVENT_HDR TcgEventHdr;
462
463 //
464 // Check if it is in Excluded FV list
465 //
466 if (mMeasurementExcludedFvPpi != NULL) {
467 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
468 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
469 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
470 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
471 return EFI_SUCCESS;
472 }
473 }
474 }
475
476 //
477 // Check whether FV is in the measured FV list.
478 //
479 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
480 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
481 return EFI_SUCCESS;
482 }
483 }
484
485 //
486 // Measure and record the FV to the TPM
487 //
488 FvBlob.BlobBase = FvBase;
489 FvBlob.BlobLength = FvLength;
490
491 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
492 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
493
494 TcgEventHdr.PCRIndex = 0;
495 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
496 TcgEventHdr.EventSize = sizeof (FvBlob);
497
498 Status = HashLogExtendEvent (
499 0,
500 (UINT8*) (UINTN) FvBlob.BlobBase,
501 (UINTN) FvBlob.BlobLength,
502 &TcgEventHdr,
503 (UINT8*) &FvBlob
504 );
505
506 //
507 // Add new FV into the measured FV list.
508 //
509 ASSERT (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
510 if (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
511 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;
512 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
513 mMeasuredBaseFvIndex++;
514 }
515
516 return Status;
517 }
518
519 /**
520 Measure main BIOS.
521
522 @retval EFI_SUCCESS Operation completed successfully.
523 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
524 @retval EFI_DEVICE_ERROR The command was unsuccessful.
525
526 **/
527 EFI_STATUS
528 MeasureMainBios (
529 VOID
530 )
531 {
532 EFI_STATUS Status;
533 UINT32 FvInstances;
534 EFI_PEI_FV_HANDLE VolumeHandle;
535 EFI_FV_INFO VolumeInfo;
536 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
537
538 PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
539 FvInstances = 0;
540 while (TRUE) {
541 //
542 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
543 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
544 // platform for special CRTM TPM measuring.
545 //
546 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
547 if (EFI_ERROR (Status)) {
548 break;
549 }
550
551 //
552 // Measure and record the firmware volume that is dispatched by PeiCore
553 //
554 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
555 ASSERT_EFI_ERROR (Status);
556 //
557 // Locate the corresponding FV_PPI according to founded FV's format guid
558 //
559 Status = PeiServicesLocatePpi (
560 &VolumeInfo.FvFormat,
561 0,
562 NULL,
563 (VOID**)&FvPpi
564 );
565 if (!EFI_ERROR (Status)) {
566 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
567 }
568
569 FvInstances++;
570 }
571 PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
572
573 return EFI_SUCCESS;
574 }
575
576 /**
577 Measure and record the Firmware Volum Information once FvInfoPPI install.
578
579 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
580 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
581 @param[in] Ppi Address of the PPI that was installed.
582
583 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
584 @return Others Fail to measure FV.
585
586 **/
587 EFI_STATUS
588 EFIAPI
589 FirmwareVolmeInfoPpiNotifyCallback (
590 IN EFI_PEI_SERVICES **PeiServices,
591 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
592 IN VOID *Ppi
593 )
594 {
595 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
596 EFI_STATUS Status;
597 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
598 UINTN Index;
599
600 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
601
602 //
603 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
604 //
605 Status = PeiServicesLocatePpi (
606 &Fv->FvFormat,
607 0,
608 NULL,
609 (VOID**)&FvPpi
610 );
611 if (EFI_ERROR (Status)) {
612 return EFI_SUCCESS;
613 }
614
615 //
616 // This is an FV from an FFS file, and the parent FV must have already been measured,
617 // No need to measure twice, so just record the FV and return
618 //
619 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
620
621 ASSERT (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
622 if (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
623 //
624 // Check whether FV is in the measured child FV list.
625 //
626 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
627 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {
628 return EFI_SUCCESS;
629 }
630 }
631 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
632 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
633 mMeasuredChildFvIndex++;
634 }
635 return EFI_SUCCESS;
636 }
637
638 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
639 }
640
641 /**
642 Do measurement after memory is ready.
643
644 @param[in] PeiServices Describes the list of possible PEI Services.
645
646 @retval EFI_SUCCESS Operation completed successfully.
647 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
648 @retval EFI_DEVICE_ERROR The command was unsuccessful.
649
650 **/
651 EFI_STATUS
652 PeimEntryMP (
653 IN EFI_PEI_SERVICES **PeiServices
654 )
655 {
656 EFI_STATUS Status;
657
658 Status = PeiServicesLocatePpi (
659 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
660 0,
661 NULL,
662 (VOID**)&mMeasurementExcludedFvPpi
663 );
664 // Do not check status, because it is optional
665
666 mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
667 ASSERT (mMeasuredBaseFvInfo != NULL);
668 mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
669 ASSERT (mMeasuredChildFvInfo != NULL);
670
671 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
672 Status = MeasureCRTMVersion ();
673 }
674
675 Status = MeasureMainBios ();
676
677 //
678 // Post callbacks:
679 // for the FvInfoPpi services to measure and record
680 // the additional Fvs to TPM
681 //
682 Status = PeiServicesNotifyPpi (&mNotifyList[0]);
683 ASSERT_EFI_ERROR (Status);
684
685 return Status;
686 }
687
688 /**
689 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
690
691 @param[in] PCRIndex PCR index.
692
693 @retval EFI_SUCCESS Operation completed successfully.
694 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
695
696 **/
697 EFI_STATUS
698 MeasureSeparatorEventWithError (
699 IN TPM_PCRINDEX PCRIndex
700 )
701 {
702 TCG_PCR_EVENT_HDR TcgEvent;
703 UINT32 EventData;
704
705 //
706 // Use EventData 0x1 to indicate there is error.
707 //
708 EventData = 0x1;
709 TcgEvent.PCRIndex = PCRIndex;
710 TcgEvent.EventType = EV_SEPARATOR;
711 TcgEvent.EventSize = (UINT32)sizeof (EventData);
712 return HashLogExtendEvent(0,(UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);
713 }
714
715 /**
716 Entry point of this module.
717
718 @param[in] FileHandle Handle of the file being invoked.
719 @param[in] PeiServices Describes the list of possible PEI Services.
720
721 @return Status.
722
723 **/
724 EFI_STATUS
725 EFIAPI
726 PeimEntryMA (
727 IN EFI_PEI_FILE_HANDLE FileHandle,
728 IN CONST EFI_PEI_SERVICES **PeiServices
729 )
730 {
731 EFI_STATUS Status;
732 EFI_STATUS Status2;
733 EFI_BOOT_MODE BootMode;
734 TPM_PCRINDEX PcrIndex;
735 BOOLEAN S3ErrorReport;
736
737 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
738 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
739 DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));
740 return EFI_UNSUPPORTED;
741 }
742
743 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
744 DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));
745 return EFI_DEVICE_ERROR;
746 }
747
748 Status = PeiServicesGetBootMode (&BootMode);
749 ASSERT_EFI_ERROR (Status);
750
751 //
752 // In S3 path, skip shadow logic. no measurement is required
753 //
754 if (BootMode != BOOT_ON_S3_RESUME) {
755 Status = (**PeiServices).RegisterForShadow(FileHandle);
756 if (Status == EFI_ALREADY_STARTED) {
757 mImageInMemory = TRUE;
758 mFileHandle = FileHandle;
759 } else if (Status == EFI_NOT_FOUND) {
760 ASSERT_EFI_ERROR (Status);
761 }
762 }
763
764 if (!mImageInMemory) {
765 //
766 // Initialize TPM device
767 //
768 Status = Tpm2RequestUseTpm ();
769 if (EFI_ERROR (Status)) {
770 DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));
771 goto Done;
772 }
773
774 S3ErrorReport = FALSE;
775 if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
776 if (BootMode == BOOT_ON_S3_RESUME) {
777 Status = Tpm2Startup (TPM_SU_STATE);
778 if (EFI_ERROR (Status) ) {
779 Status = Tpm2Startup (TPM_SU_CLEAR);
780 if (!EFI_ERROR(Status)) {
781 S3ErrorReport = TRUE;
782 }
783 }
784 } else {
785 Status = Tpm2Startup (TPM_SU_CLEAR);
786 }
787 if (EFI_ERROR (Status) ) {
788 goto Done;
789 }
790 }
791
792 //
793 // Update Tpm2HashMask according to PCR bank.
794 //
795 SyncPcrAllocationsAndPcrMask ();
796
797 if (S3ErrorReport) {
798 //
799 // The system firmware that resumes from S3 MUST deal with a
800 // TPM2_Startup error appropriately.
801 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
802 // configuring the device securely by taking actions like extending a
803 // separator with an error digest (0x01) into PCRs 0 through 7.
804 //
805 for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
806 Status = MeasureSeparatorEventWithError (PcrIndex);
807 if (EFI_ERROR (Status)) {
808 DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured. Error!\n"));
809 }
810 }
811 }
812
813 //
814 // TpmSelfTest is optional on S3 path, skip it to save S3 time
815 //
816 if (BootMode != BOOT_ON_S3_RESUME) {
817 if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
818 Status = Tpm2SelfTest (NO);
819 if (EFI_ERROR (Status)) {
820 goto Done;
821 }
822 }
823 }
824
825 //
826 // Only intall TpmInitializedPpi on success
827 //
828 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
829 ASSERT_EFI_ERROR (Status);
830 }
831
832 if (mImageInMemory) {
833 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
834 return Status;
835 }
836
837 Done:
838 if (EFI_ERROR (Status)) {
839 DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n"));
840 BuildGuidHob (&gTpmErrorHobGuid,0);
841 REPORT_STATUS_CODE (
842 EFI_ERROR_CODE | EFI_ERROR_MINOR,
843 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
844 );
845 }
846 //
847 // Always intall TpmInitializationDonePpi no matter success or fail.
848 // Other driver can know TPM initialization state by TpmInitializedPpi.
849 //
850 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
851 ASSERT_EFI_ERROR (Status2);
852
853 return Status;
854 }