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