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