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