]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TrEEPei/TrEEPei.c
SecurityPkg: Use PcdGet32() to access PcdPeiCoreMaxFvSupported
[mirror_edk2.git] / SecurityPkg / Tcg / TrEEPei / TrEEPei.c
CommitLineData
c1d93242
JY
1/** @file\r
2 Initialize TPM2 device and measure FVs before handing off control to DXE.\r
3\r
e7cbd149 4Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>\r
c1d93242
JY
5This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiPei.h>\r
16\r
17#include <IndustryStandard/UefiTcgPlatform.h>\r
18#include <Ppi/FirmwareVolumeInfo.h>\r
387208ab 19#include <Ppi/FirmwareVolumeInfo2.h>\r
c1d93242
JY
20#include <Ppi/LockPhysicalPresence.h>\r
21#include <Ppi/TpmInitialized.h>\r
22#include <Ppi/FirmwareVolume.h>\r
23#include <Ppi/EndOfPeiPhase.h>\r
24#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>\r
25\r
26#include <Guid/TcgEventHob.h>\r
27#include <Guid/MeasuredFvHob.h>\r
28#include <Guid/TpmInstance.h>\r
29\r
30#include <Library/DebugLib.h>\r
31#include <Library/BaseMemoryLib.h>\r
32#include <Library/PeiServicesLib.h>\r
33#include <Library/PeimEntryPoint.h>\r
34#include <Library/Tpm2CommandLib.h>\r
35#include <Library/Tpm2DeviceLib.h>\r
36#include <Library/HashLib.h>\r
37#include <Library/HobLib.h>\r
38#include <Library/PcdLib.h>\r
39#include <Library/PeiServicesTablePointerLib.h>\r
40#include <Protocol/TrEEProtocol.h>\r
41#include <Library/PerformanceLib.h>\r
b5412eac 42#include <Library/MemoryAllocationLib.h>\r
6f785cfc 43#include <Library/ReportStatusCodeLib.h>\r
c1d93242
JY
44\r
45#define PERF_ID_TREE_PEI 0x3080\r
46\r
47typedef struct {\r
48 EFI_GUID *EventGuid;\r
49 TREE_EVENT_LOG_FORMAT LogFormat;\r
c1d93242
JY
50} TREE_EVENT_INFO_STRUCT;\r
51\r
52TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {\r
6f785cfc 53 {&gTcgEventEntryHobGuid, TREE_EVENT_LOG_FORMAT_TCG_1_2},\r
c1d93242
JY
54};\r
55\r
56BOOLEAN mImageInMemory = FALSE;\r
57EFI_PEI_FILE_HANDLE mFileHandle;\r
58\r
59EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {\r
60 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
61 &gPeiTpmInitializedPpiGuid,\r
62 NULL\r
63};\r
64\r
83a276f6
JY
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
b5412eac 71EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;\r
c1d93242
JY
72UINT32 mMeasuredBaseFvIndex = 0;\r
73\r
b5412eac 74EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;\r
c1d93242
JY
75UINT32 mMeasuredChildFvIndex = 0;\r
76\r
77/**\r
78 Measure and record the Firmware Volum Information once FvInfoPPI install.\r
79\r
80 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
81 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
82 @param[in] Ppi Address of the PPI that was installed.\r
83\r
84 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
85 @return Others Fail to measure FV.\r
86\r
87**/\r
88EFI_STATUS\r
89EFIAPI\r
90FirmwareVolmeInfoPpiNotifyCallback (\r
91 IN EFI_PEI_SERVICES **PeiServices,\r
92 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
93 IN VOID *Ppi\r
94 );\r
95\r
96/**\r
97 Record all measured Firmware Volum Information into a Guid Hob\r
98\r
99 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
100 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
101 @param[in] Ppi Address of the PPI that was installed.\r
102\r
103 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
104 @return Others Fail to measure FV.\r
105\r
106**/\r
107EFI_STATUS\r
108EFIAPI\r
109EndofPeiSignalNotifyCallBack (\r
110 IN EFI_PEI_SERVICES **PeiServices,\r
111 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
112 IN VOID *Ppi\r
113 );\r
114\r
115EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {\r
116 {\r
117 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
118 &gEfiPeiFirmwareVolumeInfoPpiGuid,\r
119 FirmwareVolmeInfoPpiNotifyCallback \r
120 },\r
387208ab
SZ
121 {\r
122 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
123 &gEfiPeiFirmwareVolumeInfo2PpiGuid,\r
124 FirmwareVolmeInfoPpiNotifyCallback \r
125 },\r
c1d93242
JY
126 {\r
127 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
128 &gEfiEndOfPeiSignalPpiGuid,\r
129 EndofPeiSignalNotifyCallBack\r
130 }\r
131};\r
132\r
133EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;\r
134\r
c1d93242
JY
135/**\r
136 This function get digest from digest list.\r
137\r
138 @param HashAlg digest algorithm\r
139 @param DigestList digest list\r
140 @param Digest digest\r
141\r
142 @retval EFI_SUCCESS Sha1Digest is found and returned.\r
143 @retval EFI_NOT_FOUND Sha1Digest is not found.\r
144**/\r
145EFI_STATUS\r
146Tpm2GetDigestFromDigestList (\r
147 IN TPMI_ALG_HASH HashAlg,\r
148 IN TPML_DIGEST_VALUES *DigestList,\r
149 IN VOID *Digest\r
150 )\r
151{\r
152 UINTN Index;\r
153 UINT16 DigestSize;\r
154\r
155 DigestSize = GetHashSizeFromAlgo (HashAlg);\r
156 for (Index = 0; Index < DigestList->count; Index++) {\r
157 if (DigestList->digests[Index].hashAlg == HashAlg) {\r
158 CopyMem (\r
159 Digest,\r
160 &DigestList->digests[Index].digest,\r
161 DigestSize\r
162 );\r
163 return EFI_SUCCESS;\r
164 }\r
165 }\r
166\r
167 return EFI_NOT_FOUND;\r
168}\r
169\r
170/**\r
171 Record all measured Firmware Volum Information into a Guid Hob\r
172 Guid Hob payload layout is \r
173\r
174 UINT32 *************************** FIRMWARE_BLOB number\r
175 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array\r
176\r
177 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
178 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
179 @param[in] Ppi Address of the PPI that was installed.\r
180\r
181 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
182 @return Others Fail to measure FV.\r
183\r
184**/\r
185EFI_STATUS\r
186EFIAPI\r
187EndofPeiSignalNotifyCallBack (\r
188 IN EFI_PEI_SERVICES **PeiServices,\r
189 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
190 IN VOID *Ppi\r
191 )\r
192{ \r
193 MEASURED_HOB_DATA *MeasuredHobData;\r
194\r
195 MeasuredHobData = NULL;\r
196\r
197 //\r
198 // Create a Guid hob to save all measured Fv \r
199 //\r
200 MeasuredHobData = BuildGuidHob(\r
201 &gMeasuredFvHobGuid,\r
202 sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)\r
203 );\r
204\r
205 if (MeasuredHobData != NULL){\r
206 //\r
207 // Save measured FV info enty number\r
208 //\r
209 MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;\r
210\r
211 //\r
212 // Save measured base Fv info\r
213 //\r
214 CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));\r
215\r
216 //\r
217 // Save measured child Fv info\r
218 //\r
219 CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));\r
220 }\r
221\r
222 return EFI_SUCCESS;\r
223}\r
224\r
225/**\r
226 Add a new entry to the Event Log.\r
227\r
228 @param[in] DigestList A list of digest.\r
229 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
230 @param[in] NewEventData Pointer to the new event data.\r
231\r
232 @retval EFI_SUCCESS The new event log entry was added.\r
233 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
234**/\r
235EFI_STATUS\r
236LogHashEvent (\r
237 IN TPML_DIGEST_VALUES *DigestList,\r
238 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
239 IN UINT8 *NewEventData\r
240 )\r
241{\r
242 VOID *HobData;\r
243 EFI_STATUS Status;\r
244 UINTN Index;\r
245 EFI_STATUS RetStatus;\r
246\r
247 RetStatus = EFI_SUCCESS;\r
248 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
249 DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));\r
250 switch (mTreeEventInfo[Index].LogFormat) {\r
251 case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
252 Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
253 if (!EFI_ERROR (Status)) {\r
254 HobData = BuildGuidHob (\r
255 &gTcgEventEntryHobGuid,\r
256 sizeof (*NewEventHdr) + NewEventHdr->EventSize\r
257 );\r
258 if (HobData == NULL) {\r
259 RetStatus = EFI_OUT_OF_RESOURCES;\r
260 break;\r
261 }\r
262\r
263 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));\r
264 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));\r
265 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);\r
266 }\r
267 break;\r
268 }\r
269 }\r
270\r
271 return RetStatus;\r
272}\r
273\r
274/**\r
275 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
276 and build a GUIDed HOB recording the event which will be passed to the DXE phase and\r
277 added into the Event Log.\r
278\r
279 @param[in] Flags Bitmap providing additional information.\r
280 @param[in] HashData Physical address of the start of the data buffer \r
281 to be hashed, extended, and logged.\r
282 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.\r
283 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. \r
284 @param[in] NewEventData Pointer to the new event data. \r
285\r
286 @retval EFI_SUCCESS Operation completed successfully.\r
287 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
288 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
289\r
290**/\r
291EFI_STATUS\r
292HashLogExtendEvent (\r
293 IN UINT64 Flags,\r
294 IN UINT8 *HashData,\r
295 IN UINTN HashDataLen,\r
296 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
297 IN UINT8 *NewEventData\r
298 )\r
299{\r
300 EFI_STATUS Status;\r
301 TPML_DIGEST_VALUES DigestList;\r
302\r
6f785cfc
JY
303 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
304 return EFI_DEVICE_ERROR;\r
305 }\r
306\r
c1d93242
JY
307 Status = HashAndExtend (\r
308 NewEventHdr->PCRIndex,\r
309 HashData,\r
310 HashDataLen,\r
311 &DigestList\r
312 );\r
313 if (!EFI_ERROR (Status)) {\r
314 if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
315 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
316 }\r
317 }\r
6f785cfc
JY
318 \r
319 if (Status == EFI_DEVICE_ERROR) {\r
320 DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));\r
321 BuildGuidHob (&gTpmErrorHobGuid,0);\r
322 REPORT_STATUS_CODE (\r
323 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
324 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
325 );\r
326 }\r
327\r
c1d93242
JY
328 return Status;\r
329}\r
330\r
331/**\r
332 Measure CRTM version.\r
333\r
334 @retval EFI_SUCCESS Operation completed successfully.\r
335 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
336 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
337\r
338**/\r
339EFI_STATUS\r
340MeasureCRTMVersion (\r
341 VOID\r
342 )\r
343{\r
344 TCG_PCR_EVENT_HDR TcgEventHdr;\r
345\r
346 //\r
347 // Use FirmwareVersion string to represent CRTM version.\r
348 // OEMs should get real CRTM version string and measure it.\r
349 //\r
350\r
351 TcgEventHdr.PCRIndex = 0;\r
352 TcgEventHdr.EventType = EV_S_CRTM_VERSION;\r
353 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));\r
354\r
355 return HashLogExtendEvent (\r
356 0,\r
357 (UINT8*)PcdGetPtr (PcdFirmwareVersionString),\r
358 TcgEventHdr.EventSize,\r
359 &TcgEventHdr,\r
360 (UINT8*)PcdGetPtr (PcdFirmwareVersionString)\r
361 );\r
362}\r
363\r
364/**\r
365 Measure FV image. \r
366 Add it into the measured FV list after the FV is measured successfully. \r
367\r
368 @param[in] FvBase Base address of FV image.\r
369 @param[in] FvLength Length of FV image.\r
370\r
371 @retval EFI_SUCCESS Fv image is measured successfully \r
372 or it has been already measured.\r
373 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
374 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
375\r
376**/\r
377EFI_STATUS\r
378MeasureFvImage (\r
379 IN EFI_PHYSICAL_ADDRESS FvBase,\r
380 IN UINT64 FvLength\r
381 )\r
382{\r
383 UINT32 Index;\r
384 EFI_STATUS Status;\r
385 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;\r
386 TCG_PCR_EVENT_HDR TcgEventHdr;\r
387\r
388 //\r
389 // Check if it is in Excluded FV list\r
390 //\r
391 if (mMeasurementExcludedFvPpi != NULL) {\r
392 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {\r
393 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {\r
394 DEBUG ((DEBUG_INFO, "The FV which is excluded by TrEEPei starts at: 0x%x\n", FvBase));\r
395 DEBUG ((DEBUG_INFO, "The FV which is excluded by TrEEPei has the size: 0x%x\n", FvLength));\r
396 return EFI_SUCCESS;\r
397 }\r
398 }\r
399 }\r
400\r
401 //\r
402 // Check whether FV is in the measured FV list.\r
403 //\r
404 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {\r
405 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {\r
406 return EFI_SUCCESS;\r
407 }\r
408 }\r
409 \r
410 //\r
411 // Measure and record the FV to the TPM\r
412 //\r
413 FvBlob.BlobBase = FvBase;\r
414 FvBlob.BlobLength = FvLength;\r
415\r
416 DEBUG ((DEBUG_INFO, "The FV which is measured by TrEEPei starts at: 0x%x\n", FvBlob.BlobBase));\r
417 DEBUG ((DEBUG_INFO, "The FV which is measured by TrEEPei has the size: 0x%x\n", FvBlob.BlobLength));\r
418\r
419 TcgEventHdr.PCRIndex = 0;\r
420 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;\r
421 TcgEventHdr.EventSize = sizeof (FvBlob);\r
422\r
423 Status = HashLogExtendEvent (\r
424 0,\r
425 (UINT8*) (UINTN) FvBlob.BlobBase,\r
426 (UINTN) FvBlob.BlobLength,\r
427 &TcgEventHdr,\r
428 (UINT8*) &FvBlob\r
429 );\r
c1d93242
JY
430\r
431 //\r
432 // Add new FV into the measured FV list.\r
433 //\r
e7cbd149
LG
434 ASSERT (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));\r
435 if (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
c1d93242
JY
436 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;\r
437 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;\r
438 mMeasuredBaseFvIndex++;\r
439 }\r
440\r
441 return Status;\r
442}\r
443\r
444/**\r
445 Measure main BIOS.\r
446\r
447 @retval EFI_SUCCESS Operation completed successfully.\r
448 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
449 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
450\r
451**/\r
452EFI_STATUS\r
453MeasureMainBios (\r
454 VOID\r
455 )\r
456{\r
457 EFI_STATUS Status;\r
458 UINT32 FvInstances;\r
459 EFI_PEI_FV_HANDLE VolumeHandle;\r
460 EFI_FV_INFO VolumeInfo;\r
461 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
462\r
463 PERF_START_EX (mFileHandle, "EventRec", "TrEEPei", 0, PERF_ID_TREE_PEI);\r
464 FvInstances = 0;\r
465 while (TRUE) {\r
466 //\r
467 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement\r
468 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special\r
469 // platform for special CRTM TPM measuring.\r
470 //\r
471 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);\r
472 if (EFI_ERROR (Status)) {\r
473 break;\r
474 }\r
475 \r
476 //\r
477 // Measure and record the firmware volume that is dispatched by PeiCore\r
478 //\r
479 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);\r
480 ASSERT_EFI_ERROR (Status);\r
481 //\r
482 // Locate the corresponding FV_PPI according to founded FV's format guid\r
483 //\r
484 Status = PeiServicesLocatePpi (\r
485 &VolumeInfo.FvFormat, \r
486 0, \r
487 NULL,\r
488 (VOID**)&FvPpi\r
489 );\r
490 if (!EFI_ERROR (Status)) {\r
491 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);\r
492 }\r
493\r
494 FvInstances++;\r
495 }\r
496 PERF_END_EX (mFileHandle, "EventRec", "TrEEPei", 0, PERF_ID_TREE_PEI + 1);\r
497\r
498 return EFI_SUCCESS;\r
499}\r
500\r
501/**\r
502 Measure and record the Firmware Volum Information once FvInfoPPI install.\r
503\r
504 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
505 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
506 @param[in] Ppi Address of the PPI that was installed.\r
507\r
508 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
509 @return Others Fail to measure FV.\r
510\r
511**/\r
512EFI_STATUS\r
513EFIAPI\r
514FirmwareVolmeInfoPpiNotifyCallback (\r
515 IN EFI_PEI_SERVICES **PeiServices,\r
516 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
517 IN VOID *Ppi\r
518 )\r
519{\r
520 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;\r
521 EFI_STATUS Status;\r
522 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
387208ab 523 UINTN Index;\r
c1d93242
JY
524\r
525 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;\r
526\r
527 //\r
528 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.\r
529 //\r
530 Status = PeiServicesLocatePpi (\r
531 &Fv->FvFormat, \r
532 0, \r
533 NULL,\r
534 (VOID**)&FvPpi\r
535 );\r
536 if (EFI_ERROR (Status)) {\r
537 return EFI_SUCCESS;\r
538 }\r
539 \r
540 //\r
541 // This is an FV from an FFS file, and the parent FV must have already been measured,\r
542 // No need to measure twice, so just record the FV and return\r
543 //\r
544 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {\r
545 \r
e7cbd149
LG
546 ASSERT (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));\r
547 if (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
387208ab
SZ
548 //\r
549 // Check whether FV is in the measured child FV list.\r
550 //\r
551 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {\r
552 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {\r
553 return EFI_SUCCESS;\r
554 }\r
555 }\r
c1d93242
JY
556 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;\r
557 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;\r
558 mMeasuredChildFvIndex++;\r
559 }\r
560 return EFI_SUCCESS;\r
561 }\r
562\r
563 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);\r
564}\r
565\r
566/**\r
567 Do measurement after memory is ready.\r
568\r
569 @param[in] PeiServices Describes the list of possible PEI Services.\r
570\r
571 @retval EFI_SUCCESS Operation completed successfully.\r
572 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
573 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
574\r
575**/\r
576EFI_STATUS\r
577PeimEntryMP (\r
578 IN EFI_PEI_SERVICES **PeiServices\r
579 )\r
580{\r
581 EFI_STATUS Status;\r
582\r
583 Status = PeiServicesLocatePpi (\r
584 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, \r
585 0, \r
586 NULL,\r
587 (VOID**)&mMeasurementExcludedFvPpi\r
588 );\r
589 // Do not check status, because it is optional\r
590\r
b5412eac
DG
591 mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));\r
592 ASSERT (mMeasuredBaseFvInfo != NULL);\r
593 mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));\r
594 ASSERT (mMeasuredChildFvInfo != NULL);\r
595 \r
c1d93242
JY
596 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {\r
597 Status = MeasureCRTMVersion ();\r
c1d93242
JY
598 }\r
599\r
600 Status = MeasureMainBios ();\r
601\r
602 //\r
603 // Post callbacks:\r
604 // for the FvInfoPpi services to measure and record\r
605 // the additional Fvs to TPM\r
606 //\r
607 Status = PeiServicesNotifyPpi (&mNotifyList[0]);\r
608 ASSERT_EFI_ERROR (Status);\r
609\r
610 return Status;\r
611}\r
612\r
613/**\r
614 Entry point of this module.\r
615\r
616 @param[in] FileHandle Handle of the file being invoked.\r
617 @param[in] PeiServices Describes the list of possible PEI Services.\r
618\r
619 @return Status.\r
620\r
621**/\r
622EFI_STATUS\r
623EFIAPI\r
624PeimEntryMA (\r
625 IN EFI_PEI_FILE_HANDLE FileHandle,\r
626 IN CONST EFI_PEI_SERVICES **PeiServices\r
627 )\r
628{\r
629 EFI_STATUS Status;\r
83a276f6 630 EFI_STATUS Status2;\r
c1d93242
JY
631 EFI_BOOT_MODE BootMode;\r
632\r
633 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
634 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
635 DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));\r
636 return EFI_UNSUPPORTED;\r
637 }\r
638\r
3dd05ac3
JY
639 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
640 DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));\r
641 return EFI_DEVICE_ERROR;\r
642 }\r
643\r
c1d93242
JY
644 Status = PeiServicesGetBootMode (&BootMode);\r
645 ASSERT_EFI_ERROR (Status);\r
646\r
647 //\r
648 // In S3 path, skip shadow logic. no measurement is required\r
649 //\r
650 if (BootMode != BOOT_ON_S3_RESUME) {\r
651 Status = (**PeiServices).RegisterForShadow(FileHandle);\r
652 if (Status == EFI_ALREADY_STARTED) {\r
653 mImageInMemory = TRUE;\r
654 mFileHandle = FileHandle;\r
655 } else if (Status == EFI_NOT_FOUND) {\r
656 ASSERT_EFI_ERROR (Status);\r
657 }\r
658 }\r
659\r
660 if (!mImageInMemory) {\r
661 //\r
662 // Initialize TPM device\r
663 //\r
83a276f6
JY
664 Status = Tpm2RequestUseTpm ();\r
665 if (EFI_ERROR (Status)) {\r
666 DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));\r
667 goto Done;\r
668 }\r
669\r
c1d93242
JY
670 if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {\r
671 if (BootMode == BOOT_ON_S3_RESUME) {\r
672 Status = Tpm2Startup (TPM_SU_STATE);\r
673 if (EFI_ERROR (Status) ) {\r
674 Status = Tpm2Startup (TPM_SU_CLEAR);\r
675 }\r
676 } else {\r
677 Status = Tpm2Startup (TPM_SU_CLEAR);\r
678 }\r
679 if (EFI_ERROR (Status) ) {\r
83a276f6 680 goto Done;\r
c1d93242
JY
681 }\r
682 }\r
683\r
684 //\r
685 // TpmSelfTest is optional on S3 path, skip it to save S3 time\r
686 //\r
687 if (BootMode != BOOT_ON_S3_RESUME) {\r
688 if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {\r
689 Status = Tpm2SelfTest (NO);\r
690 if (EFI_ERROR (Status)) {\r
83a276f6 691 goto Done;\r
c1d93242
JY
692 }\r
693 }\r
694 }\r
695\r
83a276f6
JY
696 //\r
697 // Only intall TpmInitializedPpi on success\r
698 //\r
c1d93242
JY
699 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);\r
700 ASSERT_EFI_ERROR (Status);\r
701 }\r
702\r
703 if (mImageInMemory) {\r
704 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);\r
83a276f6 705 return Status;\r
c1d93242
JY
706 }\r
707\r
83a276f6 708Done:\r
3dd05ac3
JY
709 if (EFI_ERROR (Status)) {\r
710 DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n"));\r
711 BuildGuidHob (&gTpmErrorHobGuid,0);\r
712 REPORT_STATUS_CODE (\r
713 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
714 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
715 );\r
716 }\r
83a276f6
JY
717 //\r
718 // Always intall TpmInitializationDonePpi no matter success or fail.\r
719 // Other driver can know TPM initialization state by TpmInitializedPpi.\r
720 //\r
721 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);\r
722 ASSERT_EFI_ERROR (Status2);\r
723\r
c1d93242
JY
724 return Status;\r
725}\r