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