]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TrEEPei/TrEEPei.c
Handle TPM device error and avoid deadloop in BDS.
[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
6f785cfc 4Copyright (c) 2013 - 2015, 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
b5412eac 65EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;\r
c1d93242
JY
66UINT32 mMeasuredBaseFvIndex = 0;\r
67\r
b5412eac 68EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;\r
c1d93242
JY
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
387208ab
SZ
115 {\r
116 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
117 &gEfiPeiFirmwareVolumeInfo2PpiGuid,\r
118 FirmwareVolmeInfoPpiNotifyCallback \r
119 },\r
c1d93242
JY
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
c1d93242
JY
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
6f785cfc
JY
297 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
298 return EFI_DEVICE_ERROR;\r
299 }\r
300\r
c1d93242
JY
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
6f785cfc
JY
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
c1d93242
JY
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
c1d93242
JY
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
387208ab 517 UINTN Index;\r
c1d93242
JY
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
387208ab
SZ
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
c1d93242
JY
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
b5412eac
DG
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
c1d93242
JY
590 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {\r
591 Status = MeasureCRTMVersion ();\r
c1d93242
JY
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
c1d93242
JY
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