]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
SecurityPkg: Change use of EFI_D_* to DEBUG_*
[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
1f6fe5cb 4Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>\r
d7c054f9 5Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>\r
289b714b 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
1abfa4ce
JY
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
1abfa4ce
JY
15#include <Ppi/TpmInitialized.h>\r
16#include <Ppi/FirmwareVolume.h>\r
17#include <Ppi/EndOfPeiPhase.h>\r
18#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>\r
d7c054f9 19#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>\r
1f6fe5cb 20#include <Ppi/Tcg.h>\r
1abfa4ce
JY
21\r
22#include <Guid/TcgEventHob.h>\r
23#include <Guid/MeasuredFvHob.h>\r
24#include <Guid/TpmInstance.h>\r
012809cd 25#include <Guid/MigratedFvInfo.h>\r
1abfa4ce
JY
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
5919a960 41#include <Library/ResetSystemLib.h>\r
0286fe81 42#include <Library/PrintLib.h>\r
1abfa4ce
JY
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
1f6fe5cb
JY
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
aa8c6e2a
SZ
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
1abfa4ce 118EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;\r
aa8c6e2a 119UINT32 mMeasuredMaxBaseFvIndex = 0;\r
1abfa4ce
JY
120UINT32 mMeasuredBaseFvIndex = 0;\r
121\r
122EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;\r
aa8c6e2a 123UINT32 mMeasuredMaxChildFvIndex = 0;\r
1abfa4ce
JY
124UINT32 mMeasuredChildFvIndex = 0;\r
125\r
0286fe81
JY
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
1abfa4ce 138/**\r
d6b926e7 139 Measure and record the Firmware Volume Information once FvInfoPPI install.\r
1abfa4ce
JY
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
d6b926e7 151FirmwareVolumeInfoPpiNotifyCallback (\r
1abfa4ce
JY
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
d6b926e7 158 Record all measured Firmware Volume Information into a Guid Hob\r
1abfa4ce
JY
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
d6b926e7 180 FirmwareVolumeInfoPpiNotifyCallback\r
1abfa4ce
JY
181 },\r
182 {\r
183 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
184 &gEfiPeiFirmwareVolumeInfo2PpiGuid,\r
d6b926e7 185 FirmwareVolumeInfoPpiNotifyCallback\r
1abfa4ce
JY
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
1abfa4ce 194\r
1abfa4ce 195/**\r
d6b926e7 196 Record all measured Firmware Volume Information into a Guid Hob\r
b3548d32 197 Guid Hob payload layout is\r
1abfa4ce
JY
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
b3548d32 217{\r
1abfa4ce
JY
218 MEASURED_HOB_DATA *MeasuredHobData;\r
219\r
220 MeasuredHobData = NULL;\r
221\r
d9c5beb1
DB
222 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid);\r
223\r
1abfa4ce 224 //\r
b3548d32 225 // Create a Guid hob to save all measured Fv\r
1abfa4ce
JY
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
d9c5beb1
DB
249 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid);\r
250\r
1abfa4ce
JY
251 return EFI_SUCCESS;\r
252}\r
253\r
1abfa4ce 254/**\r
5919a960
JY
255 Make sure that the current PCR allocations, the TPM supported PCRs,\r
256 and the PcdTpm2HashMask are all in agreement.\r
1abfa4ce
JY
257**/\r
258VOID\r
5919a960 259SyncPcrAllocationsAndPcrMask (\r
1abfa4ce
JY
260 VOID\r
261 )\r
262{\r
5919a960
JY
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
1abfa4ce 269\r
e905fbb0 270 DEBUG ((DEBUG_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));\r
1abfa4ce 271\r
5919a960
JY
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
d7c054f9
ZC
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
5919a960
JY
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
e905fbb0 300 DEBUG ((DEBUG_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));\r
5919a960 301 if (NewTpmActivePcrBanks == 0) {\r
e905fbb0 302 DEBUG ((DEBUG_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));\r
5919a960
JY
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
e905fbb0 310 DEBUG ((DEBUG_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__));\r
5919a960 311 ASSERT_EFI_ERROR (Status);\r
1abfa4ce 312 }\r
5919a960
JY
313 //\r
314 // Need reset system, since we just called Tpm2PcrAllocateBanks().\r
315 //\r
316 ResetCold();\r
1abfa4ce
JY
317 }\r
318 }\r
5919a960
JY
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
e905fbb0 327 DEBUG ((DEBUG_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));\r
5919a960 328 if (NewTpm2PcrMask == 0) {\r
e905fbb0 329 DEBUG ((DEBUG_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));\r
5919a960
JY
330 ASSERT (FALSE);\r
331 }\r
332\r
333 Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);\r
334 ASSERT_EFI_ERROR (Status);\r
335 }\r
1abfa4ce
JY
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
e905fbb0 368 DEBUG ((DEBUG_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));\r
1abfa4ce
JY
369 switch (mTcg2EventInfo[Index].LogFormat) {\r
370 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:\r
d4b9b2c3 371 Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
1abfa4ce
JY
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
3cabe66b
SZ
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
1abfa4ce
JY
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
f5e34e37 405 DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));\r
1abfa4ce
JY
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
1f6fe5cb 422 @param[in] This Indicates the calling context\r
1abfa4ce 423 @param[in] Flags Bitmap providing additional information.\r
1f6fe5cb
JY
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
1abfa4ce 429 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.\r
b3548d32
LG
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
1abfa4ce
JY
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
1f6fe5cb 439EFIAPI\r
1abfa4ce 440HashLogExtendEvent (\r
1f6fe5cb 441 IN EDKII_TCG_PPI *This,\r
1abfa4ce
JY
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
547067dd 456 if ((Flags & EDKII_TCG_PRE_HASH) != 0 || (Flags & EDKII_TCG_PRE_HASH_LOG_ONLY) != 0) {\r
1f6fe5cb
JY
457 ZeroMem (&DigestList, sizeof(DigestList));\r
458 CopyMem (&DigestList, HashData, sizeof(DigestList));\r
46db105b 459 Status = EFI_SUCCESS;\r
547067dd
QZ
460 if ((Flags & EDKII_TCG_PRE_HASH) !=0 ) {\r
461 Status = Tpm2PcrExtend (\r
462 NewEventHdr->PCRIndex,\r
463 &DigestList\r
464 );\r
465 }\r
1f6fe5cb
JY
466 } else {\r
467 Status = HashAndExtend (\r
468 NewEventHdr->PCRIndex,\r
469 HashData,\r
470 HashDataLen,\r
471 &DigestList\r
472 );\r
473 }\r
1abfa4ce 474 if (!EFI_ERROR (Status)) {\r
1f6fe5cb 475 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
1abfa4ce 476 }\r
b3548d32 477\r
1abfa4ce 478 if (Status == EFI_DEVICE_ERROR) {\r
e905fbb0 479 DEBUG ((DEBUG_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));\r
1abfa4ce
JY
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
1f6fe5cb 515 &mEdkiiTcgPpi,\r
1abfa4ce
JY
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
f9713abe 524/**\r
0286fe81
JY
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
f9713abe 534**/\r
0286fe81
JY
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
1abfa4ce 566/**\r
b3548d32
LG
567 Measure FV image.\r
568 Add it into the measured FV list after the FV is measured successfully.\r
1abfa4ce
JY
569\r
570 @param[in] FvBase Base address of FV image.\r
571 @param[in] FvLength Length of FV image.\r
572\r
b3548d32 573 @retval EFI_SUCCESS Fv image is measured successfully\r
1abfa4ce
JY
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
d7c054f9
ZC
585 UINT32 Index;\r
586 EFI_STATUS Status;\r
587 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;\r
0286fe81
JY
588 FV_HANDOFF_TABLE_POINTERS2 FvBlob2;\r
589 VOID *EventData;\r
590 VOID *FvName;\r
d7c054f9
ZC
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
012809cd
GJ
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
1abfa4ce
JY
604\r
605 //\r
d7c054f9 606 // Check Excluded FV list\r
1abfa4ce 607 //\r
d7c054f9
ZC
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
1abfa4ce 624 }\r
d7c054f9
ZC
625\r
626 Instance++;\r
1abfa4ce 627 }\r
d7c054f9 628 } while (!EFI_ERROR(Status));\r
1abfa4ce
JY
629\r
630 //\r
d7c054f9 631 // Check measured FV list\r
1abfa4ce
JY
632 //\r
633 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {\r
d7c054f9
ZC
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
1abfa4ce
JY
637 return EFI_SUCCESS;\r
638 }\r
639 }\r
d7c054f9 640\r
1abfa4ce 641 //\r
d7c054f9 642 // Check pre-hashed FV list\r
1abfa4ce 643 //\r
d7c054f9
ZC
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
1abfa4ce 681\r
d7c054f9 682 WriteUnaligned32(&DigestList.count, DigestCount);\r
1abfa4ce 683\r
d7c054f9
ZC
684 break;\r
685 }\r
686 Instance++;\r
687 } while (!EFI_ERROR(Status));\r
688\r
012809cd
GJ
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
d7c054f9
ZC
709 //\r
710 // Init the log event for FV measurement\r
711 //\r
0286fe81
JY
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
012809cd 719 FvBlob2.BlobBase = FvOrgBase;\r
0286fe81 720 FvBlob2.BlobLength = FvLength;\r
f45e3a4a 721 TcgEventHdr.PCRIndex = 0;\r
0286fe81
JY
722 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;\r
723 TcgEventHdr.EventSize = sizeof (FvBlob2);\r
724 EventData = &FvBlob2;\r
725 } else {\r
012809cd 726 FvBlob.BlobBase = FvOrgBase;\r
0286fe81
JY
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
1abfa4ce 733\r
d7c054f9
ZC
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
1f6fe5cb
JY
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
d7c054f9 746 );\r
1f6fe5cb
JY
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
d7c054f9
ZC
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
1f6fe5cb 754 &mEdkiiTcgPpi,\r
d7c054f9 755 0,\r
012809cd 756 (UINT8*) (UINTN) FvDataBase, // HashData\r
0286fe81
JY
757 (UINTN) FvLength, // HashDataLen\r
758 &TcgEventHdr, // EventHdr\r
759 EventData // EventData\r
d7c054f9 760 );\r
0286fe81
JY
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
d7c054f9
ZC
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
1abfa4ce
JY
769\r
770 //\r
771 // Add new FV into the measured FV list.\r
772 //\r
aa8c6e2a
SZ
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
1abfa4ce
JY
781 }\r
782\r
aa8c6e2a
SZ
783 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;\r
784 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;\r
785 mMeasuredBaseFvIndex++;\r
786\r
1abfa4ce
JY
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
1abfa4ce
JY
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
1abfa4ce 809\r
d7c054f9
ZC
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
1abfa4ce
JY
839 PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);\r
840\r
d7c054f9 841 return Status;\r
1abfa4ce
JY
842}\r
843\r
844/**\r
d6b926e7 845 Measure and record the Firmware Volume Information once FvInfoPPI install.\r
1abfa4ce
JY
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
d6b926e7 857FirmwareVolumeInfoPpiNotifyCallback (\r
1abfa4ce
JY
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
b3548d32
LG
874 &Fv->FvFormat,\r
875 0,\r
1abfa4ce
JY
876 NULL,\r
877 (VOID**)&FvPpi\r
878 );\r
879 if (EFI_ERROR (Status)) {\r
880 return EFI_SUCCESS;\r
881 }\r
b3548d32 882\r
1abfa4ce
JY
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
b3548d32 888\r
aa8c6e2a
SZ
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
1abfa4ce 904 }\r
1abfa4ce 905 }\r
aa8c6e2a
SZ
906 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;\r
907 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;\r
908 mMeasuredChildFvIndex++;\r
1abfa4ce
JY
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
1f6fe5cb
JY
932 //\r
933 // install Tcg Services\r
934 //\r
935 Status = PeiServicesInstallPpi (&mTcgPpiList);\r
936 ASSERT_EFI_ERROR (Status);\r
937\r
1abfa4ce
JY
938 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {\r
939 Status = MeasureCRTMVersion ();\r
940 }\r
941\r
942 Status = MeasureMainBios ();\r
d7c054f9
ZC
943 if (EFI_ERROR(Status)) {\r
944 return Status;\r
945 }\r
1abfa4ce
JY
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
c2fe66bf
JY
958/**\r
959 Measure and log Separator event with error, and extend the measurement result into a specific PCR.\r
960\r
b3548d32 961 @param[in] PCRIndex PCR index.\r
c2fe66bf
JY
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
1f6fe5cb 982 return HashLogExtendEvent(&mEdkiiTcgPpi, 0, (UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);\r
c2fe66bf
JY
983}\r
984\r
1abfa4ce
JY
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
c2fe66bf
JY
1004 TPM_PCRINDEX PcrIndex;\r
1005 BOOLEAN S3ErrorReport;\r
1abfa4ce
JY
1006\r
1007 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
1008 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
f0f1a3cb 1009 DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n"));\r
1abfa4ce
JY
1010 return EFI_UNSUPPORTED;\r
1011 }\r
1012\r
1013 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
e905fbb0 1014 DEBUG ((DEBUG_ERROR, "TPM2 error!\n"));\r
1abfa4ce
JY
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
c2fe66bf 1044 S3ErrorReport = FALSE;\r
1abfa4ce
JY
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
c2fe66bf
JY
1050 if (!EFI_ERROR(Status)) {\r
1051 S3ErrorReport = TRUE;\r
1052 }\r
1abfa4ce
JY
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
b3548d32 1061\r
1abfa4ce
JY
1062 //\r
1063 // Update Tpm2HashMask according to PCR bank.\r
1064 //\r
5919a960 1065 SyncPcrAllocationsAndPcrMask ();\r
c2fe66bf
JY
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
e905fbb0 1078 DEBUG ((DEBUG_ERROR, "Separator Event with Error not Measured. Error!\n"));\r
c2fe66bf
JY
1079 }\r
1080 }\r
1081 }\r
1082\r
1abfa4ce
JY
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
dd40a1f8 1096 // Only install TpmInitializedPpi on success\r
1abfa4ce
JY
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
e905fbb0 1109 DEBUG ((DEBUG_ERROR, "TPM2 error! Build Hob\n"));\r
1abfa4ce
JY
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
dd40a1f8 1117 // Always install TpmInitializationDonePpi no matter success or fail.\r
1abfa4ce
JY
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