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