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