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