]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 - 2021, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <PiPei.h>
11
12 #include <IndustryStandard/UefiTcgPlatform.h>
13 #include <Ppi/FirmwareVolumeInfo.h>
14 #include <Ppi/FirmwareVolumeInfo2.h>
15 #include <Ppi/TpmInitialized.h>
16 #include <Ppi/FirmwareVolume.h>
17 #include <Ppi/EndOfPeiPhase.h>
18 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
19 #include <Ppi/FirmwareVolumeInfoPrehashedFV.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/Tpm2CommandLib.h>
32 #include <Library/Tpm2DeviceLib.h>
33 #include <Library/HashLib.h>
34 #include <Library/HobLib.h>
35 #include <Library/PcdLib.h>
36 #include <Library/PeiServicesTablePointerLib.h>
37 #include <Protocol/Tcg2Protocol.h>
38 #include <Library/PerformanceLib.h>
39 #include <Library/MemoryAllocationLib.h>
40 #include <Library/ReportStatusCodeLib.h>
41 #include <Library/ResetSystemLib.h>
42 #include <Library/PrintLib.h>
43
44 #define PERF_ID_TCG2_PEI 0x3080
45
46 typedef struct {
47 EFI_GUID *EventGuid;
48 EFI_TCG2_EVENT_LOG_FORMAT LogFormat;
49 } TCG2_EVENT_INFO_STRUCT;
50
51 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = {
52 { &gTcgEventEntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 },
53 { &gTcgEvent2EntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 },
54 };
55
56 BOOLEAN mImageInMemory = FALSE;
57 EFI_PEI_FILE_HANDLE mFileHandle;
58
59 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {
60 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
61 &gPeiTpmInitializedPpiGuid,
62 NULL
63 };
64
65 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
66 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
67 &gPeiTpmInitializationDonePpiGuid,
68 NULL
69 };
70
71 /**
72 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
73 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
74 added into the Event Log.
75
76 @param[in] This Indicates the calling context
77 @param[in] Flags Bitmap providing additional information.
78 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
79 start of the data buffer to be hashed, extended, and logged.
80 If BIT0 of Flags is 1, it is physical address of the
81 start of the pre-hash data buffter to be extended, and logged.
82 The pre-hash data format is TPML_DIGEST_VALUES.
83 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
84 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
85 @param[in] NewEventData Pointer to the new event data.
86
87 @retval EFI_SUCCESS Operation completed successfully.
88 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
89 @retval EFI_DEVICE_ERROR The command was unsuccessful.
90
91 **/
92 EFI_STATUS
93 EFIAPI
94 HashLogExtendEvent (
95 IN EDKII_TCG_PPI *This,
96 IN UINT64 Flags,
97 IN UINT8 *HashData,
98 IN UINTN HashDataLen,
99 IN TCG_PCR_EVENT_HDR *NewEventHdr,
100 IN UINT8 *NewEventData
101 );
102
103 EDKII_TCG_PPI mEdkiiTcgPpi = {
104 HashLogExtendEvent
105 };
106
107 EFI_PEI_PPI_DESCRIPTOR mTcgPpiList = {
108 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
109 &gEdkiiTcgPpiGuid,
110 &mEdkiiTcgPpi
111 };
112
113 //
114 // Number of firmware blobs to grow by each time we run out of room
115 //
116 #define FIRMWARE_BLOB_GROWTH_STEP 4
117
118 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;
119 UINT32 mMeasuredMaxBaseFvIndex = 0;
120 UINT32 mMeasuredBaseFvIndex = 0;
121
122 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;
123 UINT32 mMeasuredMaxChildFvIndex = 0;
124 UINT32 mMeasuredChildFvIndex = 0;
125
126 #pragma pack (1)
127
128 #define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"
129 typedef struct {
130 UINT8 BlobDescriptionSize;
131 UINT8 BlobDescription[sizeof (FV_HANDOFF_TABLE_DESC)];
132 EFI_PHYSICAL_ADDRESS BlobBase;
133 UINT64 BlobLength;
134 } FV_HANDOFF_TABLE_POINTERS2;
135
136 #pragma pack ()
137
138 /**
139 Measure and record the Firmware Volume Information once FvInfoPPI install.
140
141 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
142 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
143 @param[in] Ppi Address of the PPI that was installed.
144
145 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
146 @return Others Fail to measure FV.
147
148 **/
149 EFI_STATUS
150 EFIAPI
151 FirmwareVolumeInfoPpiNotifyCallback (
152 IN EFI_PEI_SERVICES **PeiServices,
153 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
154 IN VOID *Ppi
155 );
156
157 /**
158 Record all measured Firmware Volume Information into a Guid Hob
159
160 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
161 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
162 @param[in] Ppi Address of the PPI that was installed.
163
164 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
165 @return Others Fail to measure FV.
166
167 **/
168 EFI_STATUS
169 EFIAPI
170 EndofPeiSignalNotifyCallBack (
171 IN EFI_PEI_SERVICES **PeiServices,
172 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
173 IN VOID *Ppi
174 );
175
176 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
177 {
178 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
179 &gEfiPeiFirmwareVolumeInfoPpiGuid,
180 FirmwareVolumeInfoPpiNotifyCallback
181 },
182 {
183 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
184 &gEfiPeiFirmwareVolumeInfo2PpiGuid,
185 FirmwareVolumeInfoPpiNotifyCallback
186 },
187 {
188 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
189 &gEfiEndOfPeiSignalPpiGuid,
190 EndofPeiSignalNotifyCallBack
191 }
192 };
193
194 /**
195 Record all measured Firmware Volume Information into a Guid Hob
196 Guid Hob payload layout is
197
198 UINT32 *************************** FIRMWARE_BLOB number
199 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
200
201 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
202 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
203 @param[in] Ppi Address of the PPI that was installed.
204
205 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
206 @return Others Fail to measure FV.
207
208 **/
209 EFI_STATUS
210 EFIAPI
211 EndofPeiSignalNotifyCallBack (
212 IN EFI_PEI_SERVICES **PeiServices,
213 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
214 IN VOID *Ppi
215 )
216 {
217 MEASURED_HOB_DATA *MeasuredHobData;
218
219 MeasuredHobData = NULL;
220
221 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid);
222
223 //
224 // Create a Guid hob to save all measured Fv
225 //
226 MeasuredHobData = BuildGuidHob (
227 &gMeasuredFvHobGuid,
228 sizeof (UINTN) + sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)
229 );
230
231 if (MeasuredHobData != NULL) {
232 //
233 // Save measured FV info enty number
234 //
235 MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;
236
237 //
238 // Save measured base Fv info
239 //
240 CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));
241
242 //
243 // Save measured child Fv info
244 //
245 CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex], mMeasuredChildFvInfo, sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));
246 }
247
248 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid);
249
250 return EFI_SUCCESS;
251 }
252
253 /**
254 Make sure that the current PCR allocations, the TPM supported PCRs,
255 PcdTcg2HashAlgorithmBitmap and the PcdTpm2HashMask are all in agreement.
256 **/
257 VOID
258 SyncPcrAllocationsAndPcrMask (
259 VOID
260 )
261 {
262 EFI_STATUS Status;
263 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap;
264 EFI_TCG2_EVENT_ALGORITHM_BITMAP BiosHashAlgorithmBitmap;
265 UINT32 TpmActivePcrBanks;
266 UINT32 NewTpmActivePcrBanks;
267 UINT32 Tpm2PcrMask;
268 UINT32 NewTpm2PcrMask;
269
270 DEBUG ((DEBUG_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));
271
272 //
273 // Determine the current TPM support and the Platform PCR mask.
274 //
275 Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &TpmActivePcrBanks);
276 ASSERT_EFI_ERROR (Status);
277
278 DEBUG ((DEBUG_INFO, "Tpm2GetCapabilitySupportedAndActivePcrs - TpmHashAlgorithmBitmap: 0x%08x\n", TpmHashAlgorithmBitmap));
279 DEBUG ((DEBUG_INFO, "Tpm2GetCapabilitySupportedAndActivePcrs - TpmActivePcrBanks 0x%08x\n", TpmActivePcrBanks));
280
281 Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
282 if (Tpm2PcrMask == 0) {
283 //
284 // If PcdTpm2HashMask is zero, use ActivePcr setting.
285 // Only when PcdTpm2HashMask is initialized to 0, will it be updated to current Active Pcrs.
286 //
287 PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
288 Tpm2PcrMask = TpmActivePcrBanks;
289 }
290
291 DEBUG ((DEBUG_INFO, "Tpm2PcrMask 0x%08x\n", Tpm2PcrMask));
292
293 //
294 // The Active PCRs in the TPM need to be a strict subset of the hashing algorithms supported by BIOS.
295 //
296 // * Find the intersection of Pcd support and TPM active PCRs. If banks are missing from the TPM support
297 // that are in the PCD, update the PCD.
298 // * Find intersection of TPM Active PCRs and BIOS supported algorithms. If there are active PCR banks
299 // that are not supported by the platform, update the TPM allocations and reboot.
300 // Note: When the HashLibBaseCryptoRouter solution is used, the hash algorithm support from BIOS is reported
301 // by Tcg2HashAlgorithmBitmap, which is populated by HashLib instances at runtime.
302 BiosHashAlgorithmBitmap = PcdGet32 (PcdTcg2HashAlgorithmBitmap);
303 DEBUG ((DEBUG_INFO, "Tcg2HashAlgorithmBitmap: 0x%08x\n", BiosHashAlgorithmBitmap));
304
305 if (((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) ||
306 ((TpmActivePcrBanks & BiosHashAlgorithmBitmap) != TpmActivePcrBanks))
307 {
308 DEBUG ((DEBUG_INFO, "TpmActivePcrBanks & Tpm2PcrMask = 0x%08x\n", (TpmActivePcrBanks & Tpm2PcrMask)));
309 DEBUG ((DEBUG_INFO, "TpmActivePcrBanks & BiosHashAlgorithmBitmap = 0x%08x\n", (TpmActivePcrBanks & BiosHashAlgorithmBitmap)));
310 NewTpmActivePcrBanks = TpmActivePcrBanks;
311 NewTpmActivePcrBanks &= Tpm2PcrMask;
312 NewTpmActivePcrBanks &= BiosHashAlgorithmBitmap;
313 DEBUG ((DEBUG_INFO, "NewTpmActivePcrBanks 0x%08x\n", NewTpmActivePcrBanks));
314
315 DEBUG ((DEBUG_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
316
317 if (NewTpmActivePcrBanks == 0) {
318 DEBUG ((DEBUG_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
319 ASSERT (FALSE);
320 } else {
321 DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocateBanks (TpmHashAlgorithmBitmap: 0x%08x, NewTpmActivePcrBanks: 0x%08x)\n", TpmHashAlgorithmBitmap, NewTpmActivePcrBanks));
322 Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap, NewTpmActivePcrBanks);
323 if (EFI_ERROR (Status)) {
324 //
325 // We can't do much here, but we hope that this doesn't happen.
326 //
327 DEBUG ((DEBUG_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__));
328 ASSERT_EFI_ERROR (Status);
329 }
330
331 //
332 // Need reset system, since we just called Tpm2PcrAllocateBanks().
333 //
334 ResetCold ();
335 }
336 }
337
338 //
339 // If there are any PCRs that claim support in the Platform mask that are
340 // not supported by the TPM, update the mask.
341 //
342 if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) {
343 NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap;
344
345 DEBUG ((DEBUG_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));
346 if (NewTpm2PcrMask == 0) {
347 DEBUG ((DEBUG_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
348 ASSERT (FALSE);
349 }
350
351 Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);
352 DEBUG ((DEBUG_ERROR, "Set PcdTpm2Hash Mask to 0x%08x\n", NewTpm2PcrMask));
353 ASSERT_EFI_ERROR (Status);
354 }
355 }
356
357 /**
358 Add a new entry to the Event Log.
359
360 @param[in] DigestList A list of digest.
361 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
362 @param[in] NewEventData Pointer to the new event data.
363
364 @retval EFI_SUCCESS The new event log entry was added.
365 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
366 **/
367 EFI_STATUS
368 LogHashEvent (
369 IN TPML_DIGEST_VALUES *DigestList,
370 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
371 IN UINT8 *NewEventData
372 )
373 {
374 VOID *HobData;
375 EFI_STATUS Status;
376 UINTN Index;
377 EFI_STATUS RetStatus;
378 UINT32 SupportedEventLogs;
379 TCG_PCR_EVENT2 *TcgPcrEvent2;
380 UINT8 *DigestBuffer;
381
382 SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
383
384 RetStatus = EFI_SUCCESS;
385 for (Index = 0; Index < sizeof (mTcg2EventInfo)/sizeof (mTcg2EventInfo[0]); Index++) {
386 if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
387 DEBUG ((DEBUG_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));
388 switch (mTcg2EventInfo[Index].LogFormat) {
389 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
390 Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
391 if (!EFI_ERROR (Status)) {
392 HobData = BuildGuidHob (
393 &gTcgEventEntryHobGuid,
394 sizeof (*NewEventHdr) + NewEventHdr->EventSize
395 );
396 if (HobData == NULL) {
397 RetStatus = EFI_OUT_OF_RESOURCES;
398 break;
399 }
400
401 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
402 HobData = (VOID *)((UINT8 *)HobData + sizeof (*NewEventHdr));
403 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
404 }
405
406 break;
407 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
408 //
409 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
410 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
411 //
412 HobData = BuildGuidHob (
413 &gTcgEvent2EntryHobGuid,
414 sizeof (TcgPcrEvent2->PCRIndex) + sizeof (TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof (TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
415 );
416 if (HobData == NULL) {
417 RetStatus = EFI_OUT_OF_RESOURCES;
418 break;
419 }
420
421 TcgPcrEvent2 = HobData;
422 TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
423 TcgPcrEvent2->EventType = NewEventHdr->EventType;
424 DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
425 DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));
426 CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof (TcgPcrEvent2->EventSize));
427 DigestBuffer = DigestBuffer + sizeof (TcgPcrEvent2->EventSize);
428 CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
429 break;
430 }
431 }
432 }
433
434 return RetStatus;
435 }
436
437 /**
438 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
439 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
440 added into the Event Log.
441
442 @param[in] This Indicates the calling context
443 @param[in] Flags Bitmap providing additional information.
444 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
445 start of the data buffer to be hashed, extended, and logged.
446 If BIT0 of Flags is 1, it is physical address of the
447 start of the pre-hash data buffter to be extended, and logged.
448 The pre-hash data format is TPML_DIGEST_VALUES.
449 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
450 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
451 @param[in] NewEventData Pointer to the new event data.
452
453 @retval EFI_SUCCESS Operation completed successfully.
454 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
455 @retval EFI_DEVICE_ERROR The command was unsuccessful.
456
457 **/
458 EFI_STATUS
459 EFIAPI
460 HashLogExtendEvent (
461 IN EDKII_TCG_PPI *This,
462 IN UINT64 Flags,
463 IN UINT8 *HashData,
464 IN UINTN HashDataLen,
465 IN TCG_PCR_EVENT_HDR *NewEventHdr,
466 IN UINT8 *NewEventData
467 )
468 {
469 EFI_STATUS Status;
470 TPML_DIGEST_VALUES DigestList;
471
472 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
473 return EFI_DEVICE_ERROR;
474 }
475
476 if (((Flags & EDKII_TCG_PRE_HASH) != 0) || ((Flags & EDKII_TCG_PRE_HASH_LOG_ONLY) != 0)) {
477 ZeroMem (&DigestList, sizeof (DigestList));
478 CopyMem (&DigestList, HashData, sizeof (DigestList));
479 Status = EFI_SUCCESS;
480 if ((Flags & EDKII_TCG_PRE_HASH) != 0 ) {
481 Status = Tpm2PcrExtend (
482 NewEventHdr->PCRIndex,
483 &DigestList
484 );
485 }
486 } else {
487 Status = HashAndExtend (
488 NewEventHdr->PCRIndex,
489 HashData,
490 HashDataLen,
491 &DigestList
492 );
493 }
494
495 if (!EFI_ERROR (Status)) {
496 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
497 }
498
499 if (Status == EFI_DEVICE_ERROR) {
500 DEBUG ((DEBUG_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
501 BuildGuidHob (&gTpmErrorHobGuid, 0);
502 REPORT_STATUS_CODE (
503 EFI_ERROR_CODE | EFI_ERROR_MINOR,
504 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
505 );
506 }
507
508 return Status;
509 }
510
511 /**
512 Measure CRTM version.
513
514 @retval EFI_SUCCESS Operation completed successfully.
515 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
516 @retval EFI_DEVICE_ERROR The command was unsuccessful.
517
518 **/
519 EFI_STATUS
520 MeasureCRTMVersion (
521 VOID
522 )
523 {
524 TCG_PCR_EVENT_HDR TcgEventHdr;
525
526 //
527 // Use FirmwareVersion string to represent CRTM version.
528 // OEMs should get real CRTM version string and measure it.
529 //
530
531 TcgEventHdr.PCRIndex = 0;
532 TcgEventHdr.EventType = EV_S_CRTM_VERSION;
533 TcgEventHdr.EventSize = (UINT32)StrSize ((CHAR16 *)PcdGetPtr (PcdFirmwareVersionString));
534
535 return HashLogExtendEvent (
536 &mEdkiiTcgPpi,
537 0,
538 (UINT8 *)PcdGetPtr (PcdFirmwareVersionString),
539 TcgEventHdr.EventSize,
540 &TcgEventHdr,
541 (UINT8 *)PcdGetPtr (PcdFirmwareVersionString)
542 );
543 }
544
545 /**
546 Get the FvName from the FV header.
547
548 Causion: The FV is untrusted input.
549
550 @param[in] FvBase Base address of FV image.
551 @param[in] FvLength Length of FV image.
552
553 @return FvName pointer
554 @retval NULL FvName is NOT found
555 **/
556 VOID *
557 GetFvName (
558 IN EFI_PHYSICAL_ADDRESS FvBase,
559 IN UINT64 FvLength
560 )
561 {
562 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
563 EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
564
565 if (FvBase >= MAX_ADDRESS) {
566 return NULL;
567 }
568
569 if (FvLength >= MAX_ADDRESS - FvBase) {
570 return NULL;
571 }
572
573 if (FvLength < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {
574 return NULL;
575 }
576
577 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;
578 if (FvHeader->ExtHeaderOffset < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {
579 return NULL;
580 }
581
582 if (FvHeader->ExtHeaderOffset + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) {
583 return NULL;
584 }
585
586 FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset);
587
588 return &FvExtHeader->FvName;
589 }
590
591 /**
592 Measure FV image.
593 Add it into the measured FV list after the FV is measured successfully.
594
595 @param[in] FvBase Base address of FV image.
596 @param[in] FvLength Length of FV image.
597
598 @retval EFI_SUCCESS Fv image is measured successfully
599 or it has been already measured.
600 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
601 @retval EFI_DEVICE_ERROR The command was unsuccessful.
602
603 **/
604 EFI_STATUS
605 MeasureFvImage (
606 IN EFI_PHYSICAL_ADDRESS FvBase,
607 IN UINT64 FvLength
608 )
609 {
610 UINT32 Index;
611 EFI_STATUS Status;
612 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
613 FV_HANDOFF_TABLE_POINTERS2 FvBlob2;
614 VOID *EventData;
615 VOID *FvName;
616 TCG_PCR_EVENT_HDR TcgEventHdr;
617 UINT32 Instance;
618 UINT32 Tpm2HashMask;
619 TPML_DIGEST_VALUES DigestList;
620 UINT32 DigestCount;
621 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
622 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI *PrehashedFvPpi;
623 HASH_INFO *PreHashInfo;
624 UINT32 HashAlgoMask;
625 EFI_PHYSICAL_ADDRESS FvOrgBase;
626 EFI_PHYSICAL_ADDRESS FvDataBase;
627 EFI_PEI_HOB_POINTERS Hob;
628 EDKII_MIGRATED_FV_INFO *MigratedFvInfo;
629
630 //
631 // Check Excluded FV list
632 //
633 Instance = 0;
634 do {
635 Status = PeiServicesLocatePpi (
636 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
637 Instance,
638 NULL,
639 (VOID **)&MeasurementExcludedFvPpi
640 );
641 if (!EFI_ERROR (Status)) {
642 for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index++) {
643 if ( (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase)
644 && (MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength))
645 {
646 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
647 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
648 return EFI_SUCCESS;
649 }
650 }
651
652 Instance++;
653 }
654 } while (!EFI_ERROR (Status));
655
656 //
657 // Check measured FV list
658 //
659 for (Index = 0; Index < mMeasuredBaseFvIndex; Index++) {
660 if ((mMeasuredBaseFvInfo[Index].BlobBase == FvBase) && (mMeasuredBaseFvInfo[Index].BlobLength == FvLength)) {
661 DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
662 DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));
663 return EFI_SUCCESS;
664 }
665 }
666
667 //
668 // Check pre-hashed FV list
669 //
670 Instance = 0;
671 Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
672 do {
673 Status = PeiServicesLocatePpi (
674 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
675 Instance,
676 NULL,
677 (VOID **)&PrehashedFvPpi
678 );
679 if (!EFI_ERROR (Status) && (PrehashedFvPpi->FvBase == FvBase) && (PrehashedFvPpi->FvLength == FvLength)) {
680 ZeroMem (&DigestList, sizeof (TPML_DIGEST_VALUES));
681
682 //
683 // The FV is prehashed, check against TPM hash mask
684 //
685 PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
686 for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
687 DEBUG ((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
688 HashAlgoMask = GetHashMaskFromAlgo (PreHashInfo->HashAlgoId);
689 if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
690 //
691 // Hash is required, copy it to DigestList
692 //
693 WriteUnaligned16 (&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
694 CopyMem (
695 &DigestList.digests[DigestCount].digest,
696 PreHashInfo + 1,
697 PreHashInfo->HashSize
698 );
699 DigestCount++;
700 //
701 // Clean the corresponding Hash Algo mask bit
702 //
703 Tpm2HashMask &= ~HashAlgoMask;
704 }
705
706 PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
707 }
708
709 WriteUnaligned32 (&DigestList.count, DigestCount);
710
711 break;
712 }
713
714 Instance++;
715 } while (!EFI_ERROR (Status));
716
717 //
718 // Search the matched migration FV info
719 //
720 FvOrgBase = FvBase;
721 FvDataBase = FvBase;
722 Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
723 while (Hob.Raw != NULL) {
724 MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
725 if ((MigratedFvInfo->FvNewBase == (UINT32)FvBase) && (MigratedFvInfo->FvLength == (UINT32)FvLength)) {
726 //
727 // Found the migrated FV info
728 //
729 FvOrgBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MigratedFvInfo->FvOrgBase;
730 FvDataBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MigratedFvInfo->FvDataBase;
731 break;
732 }
733
734 Hob.Raw = GET_NEXT_HOB (Hob);
735 Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
736 }
737
738 //
739 // Init the log event for FV measurement
740 //
741 if (PcdGet32 (PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105) {
742 FvBlob2.BlobDescriptionSize = sizeof (FvBlob2.BlobDescription);
743 CopyMem (FvBlob2.BlobDescription, FV_HANDOFF_TABLE_DESC, sizeof (FvBlob2.BlobDescription));
744 FvName = GetFvName (FvBase, FvLength);
745 if (FvName != NULL) {
746 AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "Fv(%g)", FvName);
747 }
748
749 FvBlob2.BlobBase = FvOrgBase;
750 FvBlob2.BlobLength = FvLength;
751 TcgEventHdr.PCRIndex = 0;
752 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
753 TcgEventHdr.EventSize = sizeof (FvBlob2);
754 EventData = &FvBlob2;
755 } else {
756 FvBlob.BlobBase = FvOrgBase;
757 FvBlob.BlobLength = FvLength;
758 TcgEventHdr.PCRIndex = 0;
759 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
760 TcgEventHdr.EventSize = sizeof (FvBlob);
761 EventData = &FvBlob;
762 }
763
764 if (Tpm2HashMask == 0) {
765 //
766 // FV pre-hash algos comply with current TPM hash requirement
767 // Skip hashing step in measure, only extend DigestList to PCR and log event
768 //
769 Status = HashLogExtendEvent (
770 &mEdkiiTcgPpi,
771 EDKII_TCG_PRE_HASH,
772 (UINT8 *)&DigestList, // HashData
773 (UINTN)sizeof (DigestList), // HashDataLen
774 &TcgEventHdr, // EventHdr
775 EventData // EventData
776 );
777 DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase));
778 DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength));
779 } else {
780 //
781 // Hash the FV, extend digest to the TPM and log TCG event
782 //
783 Status = HashLogExtendEvent (
784 &mEdkiiTcgPpi,
785 0,
786 (UINT8 *)(UINTN)FvDataBase, // HashData
787 (UINTN)FvLength, // HashDataLen
788 &TcgEventHdr, // EventHdr
789 EventData // EventData
790 );
791 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase));
792 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength));
793 }
794
795 if (EFI_ERROR (Status)) {
796 DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
797 return Status;
798 }
799
800 //
801 // Add new FV into the measured FV list.
802 //
803 if (mMeasuredBaseFvIndex >= mMeasuredMaxBaseFvIndex) {
804 mMeasuredBaseFvInfo = ReallocatePool (
805 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxBaseFvIndex,
806 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
807 mMeasuredBaseFvInfo
808 );
809 ASSERT (mMeasuredBaseFvInfo != NULL);
810 mMeasuredMaxBaseFvIndex = mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
811 }
812
813 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;
814 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
815 mMeasuredBaseFvIndex++;
816
817 return Status;
818 }
819
820 /**
821 Measure main BIOS.
822
823 @retval EFI_SUCCESS Operation completed successfully.
824 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
825 @retval EFI_DEVICE_ERROR The command was unsuccessful.
826
827 **/
828 EFI_STATUS
829 MeasureMainBios (
830 VOID
831 )
832 {
833 EFI_STATUS Status;
834 EFI_PEI_FV_HANDLE VolumeHandle;
835 EFI_FV_INFO VolumeInfo;
836 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
837
838 PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
839
840 //
841 // Only measure BFV at the very beginning. Other parts of Static Core Root of
842 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
843 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
844 // reported by platform will be installed with Fv Info Ppi
845 // This firmware volume measure policy can be modified/enhanced by special
846 // platform for special CRTM TPM measuring.
847 //
848 Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);
849 ASSERT_EFI_ERROR (Status);
850
851 //
852 // Measure and record the firmware volume that is dispatched by PeiCore
853 //
854 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
855 ASSERT_EFI_ERROR (Status);
856 //
857 // Locate the corresponding FV_PPI according to founded FV's format guid
858 //
859 Status = PeiServicesLocatePpi (
860 &VolumeInfo.FvFormat,
861 0,
862 NULL,
863 (VOID **)&FvPpi
864 );
865 ASSERT_EFI_ERROR (Status);
866
867 Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)VolumeInfo.FvStart, VolumeInfo.FvSize);
868
869 PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
870
871 return Status;
872 }
873
874 /**
875 Measure and record the Firmware Volume Information once FvInfoPPI install.
876
877 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
878 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
879 @param[in] Ppi Address of the PPI that was installed.
880
881 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
882 @return Others Fail to measure FV.
883
884 **/
885 EFI_STATUS
886 EFIAPI
887 FirmwareVolumeInfoPpiNotifyCallback (
888 IN EFI_PEI_SERVICES **PeiServices,
889 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
890 IN VOID *Ppi
891 )
892 {
893 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
894 EFI_STATUS Status;
895 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
896 UINTN Index;
897
898 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;
899
900 //
901 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
902 //
903 Status = PeiServicesLocatePpi (
904 &Fv->FvFormat,
905 0,
906 NULL,
907 (VOID **)&FvPpi
908 );
909 if (EFI_ERROR (Status)) {
910 return EFI_SUCCESS;
911 }
912
913 //
914 // This is an FV from an FFS file, and the parent FV must have already been measured,
915 // No need to measure twice, so just record the FV and return
916 //
917 if ((Fv->ParentFvName != NULL) || (Fv->ParentFileName != NULL)) {
918 if (mMeasuredChildFvIndex >= mMeasuredMaxChildFvIndex) {
919 mMeasuredChildFvInfo = ReallocatePool (
920 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxChildFvIndex,
921 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
922 mMeasuredChildFvInfo
923 );
924 ASSERT (mMeasuredChildFvInfo != NULL);
925 mMeasuredMaxChildFvIndex = mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
926 }
927
928 //
929 // Check whether FV is in the measured child FV list.
930 //
931 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
932 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo) {
933 return EFI_SUCCESS;
934 }
935 }
936
937 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo;
938 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
939 mMeasuredChildFvIndex++;
940 return EFI_SUCCESS;
941 }
942
943 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo, Fv->FvInfoSize);
944 }
945
946 /**
947 Do measurement after memory is ready.
948
949 @param[in] PeiServices Describes the list of possible PEI Services.
950
951 @retval EFI_SUCCESS Operation completed successfully.
952 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
953 @retval EFI_DEVICE_ERROR The command was unsuccessful.
954
955 **/
956 EFI_STATUS
957 PeimEntryMP (
958 IN EFI_PEI_SERVICES **PeiServices
959 )
960 {
961 EFI_STATUS Status;
962
963 //
964 // install Tcg Services
965 //
966 Status = PeiServicesInstallPpi (&mTcgPpiList);
967 ASSERT_EFI_ERROR (Status);
968
969 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
970 Status = MeasureCRTMVersion ();
971 }
972
973 Status = MeasureMainBios ();
974 if (EFI_ERROR (Status)) {
975 return Status;
976 }
977
978 //
979 // Post callbacks:
980 // for the FvInfoPpi services to measure and record
981 // the additional Fvs to TPM
982 //
983 Status = PeiServicesNotifyPpi (&mNotifyList[0]);
984 ASSERT_EFI_ERROR (Status);
985
986 return Status;
987 }
988
989 /**
990 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
991
992 @param[in] PCRIndex PCR index.
993
994 @retval EFI_SUCCESS Operation completed successfully.
995 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
996
997 **/
998 EFI_STATUS
999 MeasureSeparatorEventWithError (
1000 IN TPM_PCRINDEX PCRIndex
1001 )
1002 {
1003 TCG_PCR_EVENT_HDR TcgEvent;
1004 UINT32 EventData;
1005
1006 //
1007 // Use EventData 0x1 to indicate there is error.
1008 //
1009 EventData = 0x1;
1010 TcgEvent.PCRIndex = PCRIndex;
1011 TcgEvent.EventType = EV_SEPARATOR;
1012 TcgEvent.EventSize = (UINT32)sizeof (EventData);
1013 return HashLogExtendEvent (&mEdkiiTcgPpi, 0, (UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent, (UINT8 *)&EventData);
1014 }
1015
1016 /**
1017 Entry point of this module.
1018
1019 @param[in] FileHandle Handle of the file being invoked.
1020 @param[in] PeiServices Describes the list of possible PEI Services.
1021
1022 @return Status.
1023
1024 **/
1025 EFI_STATUS
1026 EFIAPI
1027 PeimEntryMA (
1028 IN EFI_PEI_FILE_HANDLE FileHandle,
1029 IN CONST EFI_PEI_SERVICES **PeiServices
1030 )
1031 {
1032 EFI_STATUS Status;
1033 EFI_STATUS Status2;
1034 EFI_BOOT_MODE BootMode;
1035 TPM_PCRINDEX PcrIndex;
1036 BOOLEAN S3ErrorReport;
1037
1038 if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
1039 CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid))
1040 {
1041 DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n"));
1042 return EFI_UNSUPPORTED;
1043 }
1044
1045 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
1046 DEBUG ((DEBUG_ERROR, "TPM2 error!\n"));
1047 return EFI_DEVICE_ERROR;
1048 }
1049
1050 Status = PeiServicesGetBootMode (&BootMode);
1051 ASSERT_EFI_ERROR (Status);
1052
1053 //
1054 // In S3 path, skip shadow logic. no measurement is required
1055 //
1056 if (BootMode != BOOT_ON_S3_RESUME) {
1057 Status = (**PeiServices).RegisterForShadow (FileHandle);
1058 if (Status == EFI_ALREADY_STARTED) {
1059 mImageInMemory = TRUE;
1060 mFileHandle = FileHandle;
1061 } else if (Status == EFI_NOT_FOUND) {
1062 ASSERT_EFI_ERROR (Status);
1063 }
1064 }
1065
1066 if (!mImageInMemory) {
1067 //
1068 // Initialize TPM device
1069 //
1070 Status = Tpm2RequestUseTpm ();
1071 if (EFI_ERROR (Status)) {
1072 DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));
1073 goto Done;
1074 }
1075
1076 S3ErrorReport = FALSE;
1077 if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
1078 if (BootMode == BOOT_ON_S3_RESUME) {
1079 Status = Tpm2Startup (TPM_SU_STATE);
1080 if (EFI_ERROR (Status)) {
1081 Status = Tpm2Startup (TPM_SU_CLEAR);
1082 if (!EFI_ERROR (Status)) {
1083 S3ErrorReport = TRUE;
1084 }
1085 }
1086 } else {
1087 Status = Tpm2Startup (TPM_SU_CLEAR);
1088 }
1089
1090 if (EFI_ERROR (Status)) {
1091 goto Done;
1092 }
1093 }
1094
1095 //
1096 // Update Tpm2HashMask according to PCR bank.
1097 //
1098 SyncPcrAllocationsAndPcrMask ();
1099
1100 if (S3ErrorReport) {
1101 //
1102 // The system firmware that resumes from S3 MUST deal with a
1103 // TPM2_Startup error appropriately.
1104 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
1105 // configuring the device securely by taking actions like extending a
1106 // separator with an error digest (0x01) into PCRs 0 through 7.
1107 //
1108 for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
1109 Status = MeasureSeparatorEventWithError (PcrIndex);
1110 if (EFI_ERROR (Status)) {
1111 DEBUG ((DEBUG_ERROR, "Separator Event with Error not Measured. Error!\n"));
1112 }
1113 }
1114 }
1115
1116 //
1117 // TpmSelfTest is optional on S3 path, skip it to save S3 time
1118 //
1119 if (BootMode != BOOT_ON_S3_RESUME) {
1120 if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
1121 Status = Tpm2SelfTest (NO);
1122 if (EFI_ERROR (Status)) {
1123 goto Done;
1124 }
1125 }
1126 }
1127
1128 DEBUG_CODE_BEGIN ();
1129 //
1130 // Peek into TPM PCR 00 before any BIOS measurement.
1131 //
1132 Tpm2PcrReadForActiveBank (00, NULL);
1133 DEBUG_CODE_END ();
1134
1135 //
1136 // Only install TpmInitializedPpi on success
1137 //
1138 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
1139 ASSERT_EFI_ERROR (Status);
1140 }
1141
1142 if (mImageInMemory) {
1143 Status = PeimEntryMP ((EFI_PEI_SERVICES **)PeiServices);
1144 return Status;
1145 }
1146
1147 Done:
1148 if (EFI_ERROR (Status)) {
1149 DEBUG ((DEBUG_ERROR, "TPM2 error! Build Hob\n"));
1150 BuildGuidHob (&gTpmErrorHobGuid, 0);
1151 REPORT_STATUS_CODE (
1152 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1153 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
1154 );
1155 }
1156
1157 //
1158 // Always install TpmInitializationDonePpi no matter success or fail.
1159 // Other driver can know TPM initialization state by TpmInitializedPpi.
1160 //
1161 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
1162 ASSERT_EFI_ERROR (Status2);
1163
1164 return Status;
1165 }