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