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