]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
SecurityPkg: Debug code to audit BIOS TPM extend operations
[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 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 UINT32 TpmActivePcrBanks;
265 UINT32 NewTpmActivePcrBanks;
266 UINT32 Tpm2PcrMask;
267 UINT32 NewTpm2PcrMask;
268
269 DEBUG ((DEBUG_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));
270
271 //
272 // Determine the current TPM support and the Platform PCR mask.
273 //
274 Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &TpmActivePcrBanks);
275 ASSERT_EFI_ERROR (Status);
276
277 Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
278 if (Tpm2PcrMask == 0) {
279 //
280 // if PcdTPm2HashMask is zero, use ActivePcr setting
281 //
282 PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
283 Tpm2PcrMask = TpmActivePcrBanks;
284 }
285
286 //
287 // Find the intersection of Pcd support and TPM support.
288 // If banks are missing from the TPM support that are in the PCD, update the PCD.
289 // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
290 //
291
292 //
293 // If there are active PCR banks that are not supported by the Platform mask,
294 // update the TPM allocations and reboot the machine.
295 //
296 if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) {
297 NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask;
298
299 DEBUG ((DEBUG_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
300 if (NewTpmActivePcrBanks == 0) {
301 DEBUG ((DEBUG_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
302 ASSERT (FALSE);
303 } else {
304 Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap, NewTpmActivePcrBanks);
305 if (EFI_ERROR (Status)) {
306 //
307 // We can't do much here, but we hope that this doesn't happen.
308 //
309 DEBUG ((DEBUG_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__));
310 ASSERT_EFI_ERROR (Status);
311 }
312
313 //
314 // Need reset system, since we just called Tpm2PcrAllocateBanks().
315 //
316 ResetCold ();
317 }
318 }
319
320 //
321 // If there are any PCRs that claim support in the Platform mask that are
322 // not supported by the TPM, update the mask.
323 //
324 if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) {
325 NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap;
326
327 DEBUG ((DEBUG_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));
328 if (NewTpm2PcrMask == 0) {
329 DEBUG ((DEBUG_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
330 ASSERT (FALSE);
331 }
332
333 Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);
334 ASSERT_EFI_ERROR (Status);
335 }
336 }
337
338 /**
339 Add a new entry to the Event Log.
340
341 @param[in] DigestList A list of digest.
342 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
343 @param[in] NewEventData Pointer to the new event data.
344
345 @retval EFI_SUCCESS The new event log entry was added.
346 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
347 **/
348 EFI_STATUS
349 LogHashEvent (
350 IN TPML_DIGEST_VALUES *DigestList,
351 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
352 IN UINT8 *NewEventData
353 )
354 {
355 VOID *HobData;
356 EFI_STATUS Status;
357 UINTN Index;
358 EFI_STATUS RetStatus;
359 UINT32 SupportedEventLogs;
360 TCG_PCR_EVENT2 *TcgPcrEvent2;
361 UINT8 *DigestBuffer;
362
363 SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
364
365 RetStatus = EFI_SUCCESS;
366 for (Index = 0; Index < sizeof (mTcg2EventInfo)/sizeof (mTcg2EventInfo[0]); Index++) {
367 if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
368 DEBUG ((DEBUG_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));
369 switch (mTcg2EventInfo[Index].LogFormat) {
370 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
371 Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
372 if (!EFI_ERROR (Status)) {
373 HobData = BuildGuidHob (
374 &gTcgEventEntryHobGuid,
375 sizeof (*NewEventHdr) + NewEventHdr->EventSize
376 );
377 if (HobData == NULL) {
378 RetStatus = EFI_OUT_OF_RESOURCES;
379 break;
380 }
381
382 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
383 HobData = (VOID *)((UINT8 *)HobData + sizeof (*NewEventHdr));
384 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
385 }
386
387 break;
388 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
389 //
390 // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
391 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
392 //
393 HobData = BuildGuidHob (
394 &gTcgEvent2EntryHobGuid,
395 sizeof (TcgPcrEvent2->PCRIndex) + sizeof (TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof (TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
396 );
397 if (HobData == NULL) {
398 RetStatus = EFI_OUT_OF_RESOURCES;
399 break;
400 }
401
402 TcgPcrEvent2 = HobData;
403 TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
404 TcgPcrEvent2->EventType = NewEventHdr->EventType;
405 DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
406 DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));
407 CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof (TcgPcrEvent2->EventSize));
408 DigestBuffer = DigestBuffer + sizeof (TcgPcrEvent2->EventSize);
409 CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
410 break;
411 }
412 }
413 }
414
415 return RetStatus;
416 }
417
418 /**
419 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
420 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
421 added into the Event Log.
422
423 @param[in] This Indicates the calling context
424 @param[in] Flags Bitmap providing additional information.
425 @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
426 start of the data buffer to be hashed, extended, and logged.
427 If BIT0 of Flags is 1, it is physical address of the
428 start of the pre-hash data buffter to be extended, and logged.
429 The pre-hash data format is TPML_DIGEST_VALUES.
430 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
431 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
432 @param[in] NewEventData Pointer to the new event data.
433
434 @retval EFI_SUCCESS Operation completed successfully.
435 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
436 @retval EFI_DEVICE_ERROR The command was unsuccessful.
437
438 **/
439 EFI_STATUS
440 EFIAPI
441 HashLogExtendEvent (
442 IN EDKII_TCG_PPI *This,
443 IN UINT64 Flags,
444 IN UINT8 *HashData,
445 IN UINTN HashDataLen,
446 IN TCG_PCR_EVENT_HDR *NewEventHdr,
447 IN UINT8 *NewEventData
448 )
449 {
450 EFI_STATUS Status;
451 TPML_DIGEST_VALUES DigestList;
452
453 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
454 return EFI_DEVICE_ERROR;
455 }
456
457 if (((Flags & EDKII_TCG_PRE_HASH) != 0) || ((Flags & EDKII_TCG_PRE_HASH_LOG_ONLY) != 0)) {
458 ZeroMem (&DigestList, sizeof (DigestList));
459 CopyMem (&DigestList, HashData, sizeof (DigestList));
460 Status = EFI_SUCCESS;
461 if ((Flags & EDKII_TCG_PRE_HASH) != 0 ) {
462 Status = Tpm2PcrExtend (
463 NewEventHdr->PCRIndex,
464 &DigestList
465 );
466 }
467 } else {
468 Status = HashAndExtend (
469 NewEventHdr->PCRIndex,
470 HashData,
471 HashDataLen,
472 &DigestList
473 );
474 }
475
476 if (!EFI_ERROR (Status)) {
477 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
478 }
479
480 if (Status == EFI_DEVICE_ERROR) {
481 DEBUG ((DEBUG_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
482 BuildGuidHob (&gTpmErrorHobGuid, 0);
483 REPORT_STATUS_CODE (
484 EFI_ERROR_CODE | EFI_ERROR_MINOR,
485 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
486 );
487 }
488
489 return Status;
490 }
491
492 /**
493 Measure CRTM version.
494
495 @retval EFI_SUCCESS Operation completed successfully.
496 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
497 @retval EFI_DEVICE_ERROR The command was unsuccessful.
498
499 **/
500 EFI_STATUS
501 MeasureCRTMVersion (
502 VOID
503 )
504 {
505 TCG_PCR_EVENT_HDR TcgEventHdr;
506
507 //
508 // Use FirmwareVersion string to represent CRTM version.
509 // OEMs should get real CRTM version string and measure it.
510 //
511
512 TcgEventHdr.PCRIndex = 0;
513 TcgEventHdr.EventType = EV_S_CRTM_VERSION;
514 TcgEventHdr.EventSize = (UINT32)StrSize ((CHAR16 *)PcdGetPtr (PcdFirmwareVersionString));
515
516 return HashLogExtendEvent (
517 &mEdkiiTcgPpi,
518 0,
519 (UINT8 *)PcdGetPtr (PcdFirmwareVersionString),
520 TcgEventHdr.EventSize,
521 &TcgEventHdr,
522 (UINT8 *)PcdGetPtr (PcdFirmwareVersionString)
523 );
524 }
525
526 /**
527 Get the FvName from the FV header.
528
529 Causion: The FV is untrusted input.
530
531 @param[in] FvBase Base address of FV image.
532 @param[in] FvLength Length of FV image.
533
534 @return FvName pointer
535 @retval NULL FvName is NOT found
536 **/
537 VOID *
538 GetFvName (
539 IN EFI_PHYSICAL_ADDRESS FvBase,
540 IN UINT64 FvLength
541 )
542 {
543 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
544 EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
545
546 if (FvBase >= MAX_ADDRESS) {
547 return NULL;
548 }
549
550 if (FvLength >= MAX_ADDRESS - FvBase) {
551 return NULL;
552 }
553
554 if (FvLength < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {
555 return NULL;
556 }
557
558 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;
559 if (FvHeader->ExtHeaderOffset < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {
560 return NULL;
561 }
562
563 if (FvHeader->ExtHeaderOffset + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) {
564 return NULL;
565 }
566
567 FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset);
568
569 return &FvExtHeader->FvName;
570 }
571
572 /**
573 Measure FV image.
574 Add it into the measured FV list after the FV is measured successfully.
575
576 @param[in] FvBase Base address of FV image.
577 @param[in] FvLength Length of FV image.
578
579 @retval EFI_SUCCESS Fv image is measured successfully
580 or it has been already measured.
581 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
582 @retval EFI_DEVICE_ERROR The command was unsuccessful.
583
584 **/
585 EFI_STATUS
586 MeasureFvImage (
587 IN EFI_PHYSICAL_ADDRESS FvBase,
588 IN UINT64 FvLength
589 )
590 {
591 UINT32 Index;
592 EFI_STATUS Status;
593 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
594 FV_HANDOFF_TABLE_POINTERS2 FvBlob2;
595 VOID *EventData;
596 VOID *FvName;
597 TCG_PCR_EVENT_HDR TcgEventHdr;
598 UINT32 Instance;
599 UINT32 Tpm2HashMask;
600 TPML_DIGEST_VALUES DigestList;
601 UINT32 DigestCount;
602 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
603 EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI *PrehashedFvPpi;
604 HASH_INFO *PreHashInfo;
605 UINT32 HashAlgoMask;
606 EFI_PHYSICAL_ADDRESS FvOrgBase;
607 EFI_PHYSICAL_ADDRESS FvDataBase;
608 EFI_PEI_HOB_POINTERS Hob;
609 EDKII_MIGRATED_FV_INFO *MigratedFvInfo;
610
611 //
612 // Check Excluded FV list
613 //
614 Instance = 0;
615 do {
616 Status = PeiServicesLocatePpi (
617 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
618 Instance,
619 NULL,
620 (VOID **)&MeasurementExcludedFvPpi
621 );
622 if (!EFI_ERROR (Status)) {
623 for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index++) {
624 if ( (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase)
625 && (MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength))
626 {
627 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
628 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
629 return EFI_SUCCESS;
630 }
631 }
632
633 Instance++;
634 }
635 } while (!EFI_ERROR (Status));
636
637 //
638 // Check measured FV list
639 //
640 for (Index = 0; Index < mMeasuredBaseFvIndex; Index++) {
641 if ((mMeasuredBaseFvInfo[Index].BlobBase == FvBase) && (mMeasuredBaseFvInfo[Index].BlobLength == FvLength)) {
642 DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
643 DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));
644 return EFI_SUCCESS;
645 }
646 }
647
648 //
649 // Check pre-hashed FV list
650 //
651 Instance = 0;
652 Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
653 do {
654 Status = PeiServicesLocatePpi (
655 &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
656 Instance,
657 NULL,
658 (VOID **)&PrehashedFvPpi
659 );
660 if (!EFI_ERROR (Status) && (PrehashedFvPpi->FvBase == FvBase) && (PrehashedFvPpi->FvLength == FvLength)) {
661 ZeroMem (&DigestList, sizeof (TPML_DIGEST_VALUES));
662
663 //
664 // The FV is prehashed, check against TPM hash mask
665 //
666 PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
667 for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
668 DEBUG ((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
669 HashAlgoMask = GetHashMaskFromAlgo (PreHashInfo->HashAlgoId);
670 if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
671 //
672 // Hash is required, copy it to DigestList
673 //
674 WriteUnaligned16 (&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
675 CopyMem (
676 &DigestList.digests[DigestCount].digest,
677 PreHashInfo + 1,
678 PreHashInfo->HashSize
679 );
680 DigestCount++;
681 //
682 // Clean the corresponding Hash Algo mask bit
683 //
684 Tpm2HashMask &= ~HashAlgoMask;
685 }
686
687 PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
688 }
689
690 WriteUnaligned32 (&DigestList.count, DigestCount);
691
692 break;
693 }
694
695 Instance++;
696 } while (!EFI_ERROR (Status));
697
698 //
699 // Search the matched migration FV info
700 //
701 FvOrgBase = FvBase;
702 FvDataBase = FvBase;
703 Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
704 while (Hob.Raw != NULL) {
705 MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
706 if ((MigratedFvInfo->FvNewBase == (UINT32)FvBase) && (MigratedFvInfo->FvLength == (UINT32)FvLength)) {
707 //
708 // Found the migrated FV info
709 //
710 FvOrgBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MigratedFvInfo->FvOrgBase;
711 FvDataBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MigratedFvInfo->FvDataBase;
712 break;
713 }
714
715 Hob.Raw = GET_NEXT_HOB (Hob);
716 Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
717 }
718
719 //
720 // Init the log event for FV measurement
721 //
722 if (PcdGet32 (PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105) {
723 FvBlob2.BlobDescriptionSize = sizeof (FvBlob2.BlobDescription);
724 CopyMem (FvBlob2.BlobDescription, FV_HANDOFF_TABLE_DESC, sizeof (FvBlob2.BlobDescription));
725 FvName = GetFvName (FvBase, FvLength);
726 if (FvName != NULL) {
727 AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "Fv(%g)", FvName);
728 }
729
730 FvBlob2.BlobBase = FvOrgBase;
731 FvBlob2.BlobLength = FvLength;
732 TcgEventHdr.PCRIndex = 0;
733 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
734 TcgEventHdr.EventSize = sizeof (FvBlob2);
735 EventData = &FvBlob2;
736 } else {
737 FvBlob.BlobBase = FvOrgBase;
738 FvBlob.BlobLength = FvLength;
739 TcgEventHdr.PCRIndex = 0;
740 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
741 TcgEventHdr.EventSize = sizeof (FvBlob);
742 EventData = &FvBlob;
743 }
744
745 if (Tpm2HashMask == 0) {
746 //
747 // FV pre-hash algos comply with current TPM hash requirement
748 // Skip hashing step in measure, only extend DigestList to PCR and log event
749 //
750 Status = HashLogExtendEvent (
751 &mEdkiiTcgPpi,
752 EDKII_TCG_PRE_HASH,
753 (UINT8 *)&DigestList, // HashData
754 (UINTN)sizeof (DigestList), // HashDataLen
755 &TcgEventHdr, // EventHdr
756 EventData // EventData
757 );
758 DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase));
759 DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength));
760 } else {
761 //
762 // Hash the FV, extend digest to the TPM and log TCG event
763 //
764 Status = HashLogExtendEvent (
765 &mEdkiiTcgPpi,
766 0,
767 (UINT8 *)(UINTN)FvDataBase, // HashData
768 (UINTN)FvLength, // HashDataLen
769 &TcgEventHdr, // EventHdr
770 EventData // EventData
771 );
772 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBase));
773 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvLength));
774 }
775
776 if (EFI_ERROR (Status)) {
777 DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
778 return Status;
779 }
780
781 //
782 // Add new FV into the measured FV list.
783 //
784 if (mMeasuredBaseFvIndex >= mMeasuredMaxBaseFvIndex) {
785 mMeasuredBaseFvInfo = ReallocatePool (
786 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxBaseFvIndex,
787 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
788 mMeasuredBaseFvInfo
789 );
790 ASSERT (mMeasuredBaseFvInfo != NULL);
791 mMeasuredMaxBaseFvIndex = mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
792 }
793
794 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;
795 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
796 mMeasuredBaseFvIndex++;
797
798 return Status;
799 }
800
801 /**
802 Measure main BIOS.
803
804 @retval EFI_SUCCESS Operation completed successfully.
805 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
806 @retval EFI_DEVICE_ERROR The command was unsuccessful.
807
808 **/
809 EFI_STATUS
810 MeasureMainBios (
811 VOID
812 )
813 {
814 EFI_STATUS Status;
815 EFI_PEI_FV_HANDLE VolumeHandle;
816 EFI_FV_INFO VolumeInfo;
817 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
818
819 PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
820
821 //
822 // Only measure BFV at the very beginning. Other parts of Static Core Root of
823 // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
824 // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
825 // reported by platform will be installed with Fv Info Ppi
826 // This firmware volume measure policy can be modified/enhanced by special
827 // platform for special CRTM TPM measuring.
828 //
829 Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);
830 ASSERT_EFI_ERROR (Status);
831
832 //
833 // Measure and record the firmware volume that is dispatched by PeiCore
834 //
835 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
836 ASSERT_EFI_ERROR (Status);
837 //
838 // Locate the corresponding FV_PPI according to founded FV's format guid
839 //
840 Status = PeiServicesLocatePpi (
841 &VolumeInfo.FvFormat,
842 0,
843 NULL,
844 (VOID **)&FvPpi
845 );
846 ASSERT_EFI_ERROR (Status);
847
848 Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)VolumeInfo.FvStart, VolumeInfo.FvSize);
849
850 PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
851
852 return Status;
853 }
854
855 /**
856 Measure and record the Firmware Volume Information once FvInfoPPI install.
857
858 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
859 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
860 @param[in] Ppi Address of the PPI that was installed.
861
862 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
863 @return Others Fail to measure FV.
864
865 **/
866 EFI_STATUS
867 EFIAPI
868 FirmwareVolumeInfoPpiNotifyCallback (
869 IN EFI_PEI_SERVICES **PeiServices,
870 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
871 IN VOID *Ppi
872 )
873 {
874 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
875 EFI_STATUS Status;
876 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
877 UINTN Index;
878
879 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;
880
881 //
882 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
883 //
884 Status = PeiServicesLocatePpi (
885 &Fv->FvFormat,
886 0,
887 NULL,
888 (VOID **)&FvPpi
889 );
890 if (EFI_ERROR (Status)) {
891 return EFI_SUCCESS;
892 }
893
894 //
895 // This is an FV from an FFS file, and the parent FV must have already been measured,
896 // No need to measure twice, so just record the FV and return
897 //
898 if ((Fv->ParentFvName != NULL) || (Fv->ParentFileName != NULL)) {
899 if (mMeasuredChildFvIndex >= mMeasuredMaxChildFvIndex) {
900 mMeasuredChildFvInfo = ReallocatePool (
901 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxChildFvIndex,
902 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
903 mMeasuredChildFvInfo
904 );
905 ASSERT (mMeasuredChildFvInfo != NULL);
906 mMeasuredMaxChildFvIndex = mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
907 }
908
909 //
910 // Check whether FV is in the measured child FV list.
911 //
912 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
913 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo) {
914 return EFI_SUCCESS;
915 }
916 }
917
918 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo;
919 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
920 mMeasuredChildFvIndex++;
921 return EFI_SUCCESS;
922 }
923
924 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo, Fv->FvInfoSize);
925 }
926
927 /**
928 Do measurement after memory is ready.
929
930 @param[in] PeiServices Describes the list of possible PEI Services.
931
932 @retval EFI_SUCCESS Operation completed successfully.
933 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
934 @retval EFI_DEVICE_ERROR The command was unsuccessful.
935
936 **/
937 EFI_STATUS
938 PeimEntryMP (
939 IN EFI_PEI_SERVICES **PeiServices
940 )
941 {
942 EFI_STATUS Status;
943
944 //
945 // install Tcg Services
946 //
947 Status = PeiServicesInstallPpi (&mTcgPpiList);
948 ASSERT_EFI_ERROR (Status);
949
950 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
951 Status = MeasureCRTMVersion ();
952 }
953
954 Status = MeasureMainBios ();
955 if (EFI_ERROR (Status)) {
956 return Status;
957 }
958
959 //
960 // Post callbacks:
961 // for the FvInfoPpi services to measure and record
962 // the additional Fvs to TPM
963 //
964 Status = PeiServicesNotifyPpi (&mNotifyList[0]);
965 ASSERT_EFI_ERROR (Status);
966
967 return Status;
968 }
969
970 /**
971 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
972
973 @param[in] PCRIndex PCR index.
974
975 @retval EFI_SUCCESS Operation completed successfully.
976 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
977
978 **/
979 EFI_STATUS
980 MeasureSeparatorEventWithError (
981 IN TPM_PCRINDEX PCRIndex
982 )
983 {
984 TCG_PCR_EVENT_HDR TcgEvent;
985 UINT32 EventData;
986
987 //
988 // Use EventData 0x1 to indicate there is error.
989 //
990 EventData = 0x1;
991 TcgEvent.PCRIndex = PCRIndex;
992 TcgEvent.EventType = EV_SEPARATOR;
993 TcgEvent.EventSize = (UINT32)sizeof (EventData);
994 return HashLogExtendEvent (&mEdkiiTcgPpi, 0, (UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent, (UINT8 *)&EventData);
995 }
996
997 /**
998 Entry point of this module.
999
1000 @param[in] FileHandle Handle of the file being invoked.
1001 @param[in] PeiServices Describes the list of possible PEI Services.
1002
1003 @return Status.
1004
1005 **/
1006 EFI_STATUS
1007 EFIAPI
1008 PeimEntryMA (
1009 IN EFI_PEI_FILE_HANDLE FileHandle,
1010 IN CONST EFI_PEI_SERVICES **PeiServices
1011 )
1012 {
1013 EFI_STATUS Status;
1014 EFI_STATUS Status2;
1015 EFI_BOOT_MODE BootMode;
1016 TPM_PCRINDEX PcrIndex;
1017 BOOLEAN S3ErrorReport;
1018
1019 if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
1020 CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid))
1021 {
1022 DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n"));
1023 return EFI_UNSUPPORTED;
1024 }
1025
1026 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
1027 DEBUG ((DEBUG_ERROR, "TPM2 error!\n"));
1028 return EFI_DEVICE_ERROR;
1029 }
1030
1031 Status = PeiServicesGetBootMode (&BootMode);
1032 ASSERT_EFI_ERROR (Status);
1033
1034 //
1035 // In S3 path, skip shadow logic. no measurement is required
1036 //
1037 if (BootMode != BOOT_ON_S3_RESUME) {
1038 Status = (**PeiServices).RegisterForShadow (FileHandle);
1039 if (Status == EFI_ALREADY_STARTED) {
1040 mImageInMemory = TRUE;
1041 mFileHandle = FileHandle;
1042 } else if (Status == EFI_NOT_FOUND) {
1043 ASSERT_EFI_ERROR (Status);
1044 }
1045 }
1046
1047 if (!mImageInMemory) {
1048 //
1049 // Initialize TPM device
1050 //
1051 Status = Tpm2RequestUseTpm ();
1052 if (EFI_ERROR (Status)) {
1053 DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));
1054 goto Done;
1055 }
1056
1057 S3ErrorReport = FALSE;
1058 if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
1059 if (BootMode == BOOT_ON_S3_RESUME) {
1060 Status = Tpm2Startup (TPM_SU_STATE);
1061 if (EFI_ERROR (Status)) {
1062 Status = Tpm2Startup (TPM_SU_CLEAR);
1063 if (!EFI_ERROR (Status)) {
1064 S3ErrorReport = TRUE;
1065 }
1066 }
1067 } else {
1068 Status = Tpm2Startup (TPM_SU_CLEAR);
1069 }
1070
1071 if (EFI_ERROR (Status)) {
1072 goto Done;
1073 }
1074 }
1075
1076 //
1077 // Update Tpm2HashMask according to PCR bank.
1078 //
1079 SyncPcrAllocationsAndPcrMask ();
1080
1081 if (S3ErrorReport) {
1082 //
1083 // The system firmware that resumes from S3 MUST deal with a
1084 // TPM2_Startup error appropriately.
1085 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
1086 // configuring the device securely by taking actions like extending a
1087 // separator with an error digest (0x01) into PCRs 0 through 7.
1088 //
1089 for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
1090 Status = MeasureSeparatorEventWithError (PcrIndex);
1091 if (EFI_ERROR (Status)) {
1092 DEBUG ((DEBUG_ERROR, "Separator Event with Error not Measured. Error!\n"));
1093 }
1094 }
1095 }
1096
1097 //
1098 // TpmSelfTest is optional on S3 path, skip it to save S3 time
1099 //
1100 if (BootMode != BOOT_ON_S3_RESUME) {
1101 if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
1102 Status = Tpm2SelfTest (NO);
1103 if (EFI_ERROR (Status)) {
1104 goto Done;
1105 }
1106 }
1107 }
1108
1109 DEBUG_CODE_BEGIN ();
1110 //
1111 // Peek into TPM PCR 00 before any BIOS measurement.
1112 //
1113 Tpm2PcrReadForActiveBank (00, NULL);
1114 DEBUG_CODE_END ();
1115
1116 //
1117 // Only install TpmInitializedPpi on success
1118 //
1119 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
1120 ASSERT_EFI_ERROR (Status);
1121 }
1122
1123 if (mImageInMemory) {
1124 Status = PeimEntryMP ((EFI_PEI_SERVICES **)PeiServices);
1125 return Status;
1126 }
1127
1128 Done:
1129 if (EFI_ERROR (Status)) {
1130 DEBUG ((DEBUG_ERROR, "TPM2 error! Build Hob\n"));
1131 BuildGuidHob (&gTpmErrorHobGuid, 0);
1132 REPORT_STATUS_CODE (
1133 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1134 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
1135 );
1136 }
1137
1138 //
1139 // Always install TpmInitializationDonePpi no matter success or fail.
1140 // Other driver can know TPM initialization state by TpmInitializedPpi.
1141 //
1142 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
1143 ASSERT_EFI_ERROR (Status2);
1144
1145 return Status;
1146 }