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