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