]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgPei/TcgPei.c
Add security package to repository.
[mirror_edk2.git] / SecurityPkg / Tcg / TcgPei / TcgPei.c
CommitLineData
0c18794e 1/** @file\r
2 Initialize TPM device and measure FVs before handing off control to DXE.\r
3\r
4Copyright (c) 2005 - 2011, 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/Tpm12.h>\r
18#include <IndustryStandard/UefiTcgPlatform.h>\r
19#include <Ppi/FirmwareVolumeInfo.h>\r
20#include <Ppi/LockPhysicalPresence.h>\r
21#include <Ppi/TpmInitialized.h>\r
22#include <Ppi/FirmwareVolume.h>\r
23#include <Guid/TcgEventHob.h>\r
24#include <Library/DebugLib.h>\r
25#include <Library/BaseMemoryLib.h>\r
26#include <Library/PeiServicesLib.h>\r
27#include <Library/PeimEntryPoint.h>\r
28#include <Library/TpmCommLib.h>\r
29#include <Library/HobLib.h>\r
30#include <Library/PcdLib.h>\r
31#include <Library/PeiServicesTablePointerLib.h>\r
32\r
33#include "TpmComm.h"\r
34\r
35BOOLEAN mImageInMemory = FALSE;\r
36\r
37EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {\r
38 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
39 &gPeiTpmInitializedPpiGuid,\r
40 NULL\r
41};\r
42\r
43/**\r
44 Lock physical presence if needed.\r
45\r
46 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
47 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
48 @param[in] Ppi Address of the PPI that was installed.\r
49\r
50 @retval EFI_SUCCESS Operation completed successfully.\r
51\r
52**/\r
53EFI_STATUS\r
54EFIAPI\r
55PhysicalPresencePpiNotifyCallback (\r
56 IN EFI_PEI_SERVICES **PeiServices,\r
57 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
58 IN VOID *Ppi\r
59 );\r
60\r
61/**\r
62 Measure and record the Firmware Volum Information once FvInfoPPI install.\r
63\r
64 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
65 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
66 @param[in] Ppi Address of the PPI that was installed.\r
67\r
68 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
69 @return Others Fail to measure FV.\r
70\r
71**/\r
72EFI_STATUS\r
73EFIAPI\r
74FirmwareVolmeInfoPpiNotifyCallback (\r
75 IN EFI_PEI_SERVICES **PeiServices,\r
76 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
77 IN VOID *Ppi\r
78 );\r
79\r
80EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {\r
81 {\r
82 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
83 &gPeiLockPhysicalPresencePpiGuid,\r
84 PhysicalPresencePpiNotifyCallback\r
85 },\r
86 {\r
87 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
88 &gEfiPeiFirmwareVolumeInfoPpiGuid,\r
89 FirmwareVolmeInfoPpiNotifyCallback \r
90 }\r
91};\r
92\r
93CHAR8 mSCrtmVersion[] = "{D20BC7C6-A1A5-415c-AE85-38290AB6BE04}";\r
94\r
95EFI_PLATFORM_FIRMWARE_BLOB mMeasuredFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];\r
96UINT32 mMeasuredFvIndex = 0;\r
97\r
98/**\r
99 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
100 and build a GUIDed HOB recording the event which will be passed to the DXE phase and\r
101 added into the Event Log.\r
102\r
103 @param[in] PeiServices Describes the list of possible PEI Services.\r
104 @param[in] HashData Physical address of the start of the data buffer \r
105 to be hashed, extended, and logged.\r
106 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.\r
107 @param[in] TpmHandle TPM handle.\r
108 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. \r
109 @param[in] NewEventData Pointer to the new event data. \r
110\r
111 @retval EFI_SUCCESS Operation completed successfully.\r
112 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
113 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
114\r
115**/\r
116EFI_STATUS\r
117HashLogExtendEvent (\r
118 IN EFI_PEI_SERVICES **PeiServices,\r
119 IN UINT8 *HashData,\r
120 IN UINTN HashDataLen,\r
121 IN TIS_TPM_HANDLE TpmHandle,\r
122 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
123 IN UINT8 *NewEventData\r
124 )\r
125{\r
126 EFI_STATUS Status;\r
127 VOID *HobData;\r
128\r
129 HobData = NULL;\r
130 if (HashDataLen != 0) {\r
131 Status = TpmCommHashAll (\r
132 HashData,\r
133 HashDataLen,\r
134 &NewEventHdr->Digest\r
135 );\r
136 ASSERT_EFI_ERROR (Status);\r
137 }\r
138\r
139 Status = TpmCommExtend (\r
140 PeiServices,\r
141 TpmHandle,\r
142 &NewEventHdr->Digest,\r
143 NewEventHdr->PCRIndex,\r
144 NULL\r
145 );\r
146 ASSERT_EFI_ERROR (Status);\r
147\r
148 HobData = BuildGuidHob (\r
149 &gTcgEventEntryHobGuid,\r
150 sizeof (*NewEventHdr) + NewEventHdr->EventSize\r
151 );\r
152 if (HobData == NULL) {\r
153 return EFI_OUT_OF_RESOURCES;\r
154 }\r
155\r
156 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));\r
157 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));\r
158 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);\r
159 return EFI_SUCCESS;\r
160}\r
161\r
162/**\r
163 Measure CRTM version.\r
164\r
165 @param[in] PeiServices Describes the list of possible PEI Services.\r
166 @param[in] TpmHandle TPM handle.\r
167\r
168 @retval EFI_SUCCESS Operation completed successfully.\r
169 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
170 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
171\r
172**/\r
173EFI_STATUS\r
174EFIAPI\r
175MeasureCRTMVersion (\r
176 IN EFI_PEI_SERVICES **PeiServices,\r
177 IN TIS_TPM_HANDLE TpmHandle\r
178 )\r
179{\r
180 TCG_PCR_EVENT_HDR TcgEventHdr;\r
181\r
182 //\r
183 // Here, only a static GUID is measured instead of real CRTM version.\r
184 // OEMs should get real CRTM version string and measure it.\r
185 //\r
186\r
187 TcgEventHdr.PCRIndex = 0;\r
188 TcgEventHdr.EventType = EV_S_CRTM_VERSION;\r
189 TcgEventHdr.EventSize = sizeof (mSCrtmVersion);\r
190 return HashLogExtendEvent (\r
191 PeiServices,\r
192 (UINT8*)&mSCrtmVersion,\r
193 TcgEventHdr.EventSize,\r
194 TpmHandle,\r
195 &TcgEventHdr,\r
196 (UINT8*)&mSCrtmVersion\r
197 );\r
198}\r
199\r
200/**\r
201 Measure FV image. \r
202 Add it into the measured FV list after the FV is measured successfully. \r
203\r
204 @param[in] FvBase Base address of FV image.\r
205 @param[in] FvLength Length of FV image.\r
206\r
207 @retval EFI_SUCCESS Fv image is measured successfully \r
208 or it has been already measured.\r
209 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
210 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
211\r
212**/\r
213EFI_STATUS\r
214EFIAPI\r
215MeasureFvImage (\r
216 IN EFI_PHYSICAL_ADDRESS FvBase,\r
217 IN UINT64 FvLength\r
218 )\r
219{\r
220 UINT32 Index;\r
221 EFI_STATUS Status;\r
222 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;\r
223 TCG_PCR_EVENT_HDR TcgEventHdr;\r
224 TIS_TPM_HANDLE TpmHandle;\r
225\r
226 TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS;\r
227\r
228 //\r
229 // Check whether FV is in the measured FV list.\r
230 //\r
231 for (Index = 0; Index < mMeasuredFvIndex; Index ++) {\r
232 if (mMeasuredFvInfo[Index].BlobBase == FvBase) {\r
233 return EFI_SUCCESS;\r
234 }\r
235 }\r
236 \r
237 //\r
238 // Measure and record the FV to the TPM\r
239 //\r
240 FvBlob.BlobBase = FvBase;\r
241 FvBlob.BlobLength = FvLength;\r
242\r
243 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase));\r
244 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength));\r
245\r
246 TcgEventHdr.PCRIndex = 0;\r
247 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;\r
248 TcgEventHdr.EventSize = sizeof (FvBlob);\r
249\r
250 Status = HashLogExtendEvent (\r
251 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),\r
252 (UINT8*) (UINTN) FvBlob.BlobBase,\r
253 (UINTN) FvBlob.BlobLength,\r
254 TpmHandle,\r
255 &TcgEventHdr,\r
256 (UINT8*) &FvBlob\r
257 );\r
258 ASSERT_EFI_ERROR (Status);\r
259\r
260 //\r
261 // Add new FV into the measured FV list.\r
262 //\r
263 ASSERT (mMeasuredFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported));\r
264 if (mMeasuredFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
265 mMeasuredFvInfo[mMeasuredFvIndex].BlobBase = FvBase;\r
266 mMeasuredFvInfo[mMeasuredFvIndex++].BlobLength = FvLength;\r
267 }\r
268\r
269 return Status;\r
270}\r
271\r
272/**\r
273 Measure main BIOS.\r
274\r
275 @param[in] PeiServices Describes the list of possible PEI Services.\r
276 @param[in] TpmHandle TPM handle.\r
277\r
278 @retval EFI_SUCCESS Operation completed successfully.\r
279 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
280 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
281\r
282**/\r
283EFI_STATUS\r
284EFIAPI\r
285MeasureMainBios (\r
286 IN EFI_PEI_SERVICES **PeiServices,\r
287 IN TIS_TPM_HANDLE TpmHandle\r
288 )\r
289{\r
290 EFI_STATUS Status;\r
291 UINT32 FvInstances;\r
292 EFI_PEI_FV_HANDLE VolumeHandle;\r
293 EFI_FV_INFO VolumeInfo;\r
294 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
295 \r
296 FvInstances = 0;\r
297 while (TRUE) {\r
298 //\r
299 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement\r
300 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special\r
301 // platform for special CRTM TPM measuring.\r
302 //\r
303 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);\r
304 if (EFI_ERROR (Status)) {\r
305 break;\r
306 }\r
307 \r
308 //\r
309 // Measure and record the firmware volume that is dispatched by PeiCore\r
310 //\r
311 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);\r
312 ASSERT_EFI_ERROR (Status);\r
313 //\r
314 // Locate the corresponding FV_PPI according to founded FV's format guid\r
315 //\r
316 Status = PeiServicesLocatePpi (\r
317 &VolumeInfo.FvFormat, \r
318 0, \r
319 NULL,\r
320 (VOID**)&FvPpi\r
321 );\r
322 if (!EFI_ERROR (Status)) {\r
323 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);\r
324 }\r
325\r
326 FvInstances++;\r
327 }\r
328\r
329 return EFI_SUCCESS;\r
330}\r
331\r
332/**\r
333 Measure and record the Firmware Volum Information once FvInfoPPI install.\r
334\r
335 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
336 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
337 @param[in] Ppi Address of the PPI that was installed.\r
338\r
339 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
340 @return Others Fail to measure FV.\r
341\r
342**/\r
343EFI_STATUS\r
344EFIAPI\r
345FirmwareVolmeInfoPpiNotifyCallback (\r
346 IN EFI_PEI_SERVICES **PeiServices,\r
347 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
348 IN VOID *Ppi\r
349 )\r
350{\r
351 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;\r
352 EFI_STATUS Status;\r
353 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
354\r
355 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;\r
356\r
357 //\r
358 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.\r
359 //\r
360 Status = PeiServicesLocatePpi (\r
361 &Fv->FvFormat, \r
362 0, \r
363 NULL,\r
364 (VOID**)&FvPpi\r
365 );\r
366 if (EFI_ERROR (Status)) {\r
367 return EFI_SUCCESS;\r
368 }\r
369 \r
370 //\r
371 // This is an FV from an FFS file, and the parent FV must have already been measured,\r
372 // No need to measure twice, so just returns\r
373 //\r
374 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {\r
375 return EFI_SUCCESS;\r
376 }\r
377\r
378 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);\r
379}\r
380\r
381/**\r
382 Lock physical presence if needed.\r
383\r
384 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
385 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
386 @param[in] Ppi Address of the PPI that was installed.\r
387\r
388 @retval EFI_SUCCESS Operation completed successfully.\r
389 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.\r
390 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
391\r
392**/\r
393EFI_STATUS\r
394EFIAPI\r
395PhysicalPresencePpiNotifyCallback (\r
396 IN EFI_PEI_SERVICES **PeiServices,\r
397 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
398 IN VOID *Ppi\r
399 )\r
400{\r
401 EFI_STATUS Status;\r
402 PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi;\r
403 BOOLEAN LifetimeLock;\r
404 BOOLEAN CmdEnable;\r
405 TIS_TPM_HANDLE TpmHandle;\r
406\r
407 TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS;\r
408 LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi;\r
409\r
410 if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) {\r
411 return EFI_SUCCESS;\r
412 }\r
413\r
414 //\r
415 // Lock TPM physical presence.\r
416 //\r
417\r
418 Status = TpmCommGetCapability (PeiServices, TpmHandle, NULL, &LifetimeLock, &CmdEnable);\r
419 if (EFI_ERROR (Status)) {\r
420 return Status;\r
421 }\r
422\r
423 if (!CmdEnable) {\r
424 if (LifetimeLock) {\r
425 //\r
426 // physicalPresenceCMDEnable is locked, can't change.\r
427 //\r
428 return EFI_ABORTED;\r
429 }\r
430\r
431 //\r
432 // Enable physical presence command\r
433 // It is necessary in order to lock physical presence\r
434 //\r
435 Status = TpmCommPhysicalPresence (\r
436 PeiServices,\r
437 TpmHandle,\r
438 TPM_PHYSICAL_PRESENCE_CMD_ENABLE\r
439 );\r
440 if (EFI_ERROR (Status)) {\r
441 return Status;\r
442 }\r
443 }\r
444\r
445 //\r
446 // Lock physical presence\r
447 // \r
448 Status = TpmCommPhysicalPresence (\r
449 PeiServices,\r
450 TpmHandle,\r
451 TPM_PHYSICAL_PRESENCE_LOCK\r
452 );\r
453 return Status;\r
454}\r
455\r
456/**\r
457 Check if TPM chip is activeated or not.\r
458\r
459 @param[in] PeiServices Describes the list of possible PEI Services.\r
460 @param[in] TpmHandle TPM handle.\r
461\r
462 @retval TRUE TPM is activated.\r
463 @retval FALSE TPM is deactivated.\r
464\r
465**/\r
466BOOLEAN\r
467EFIAPI\r
468IsTpmUsable (\r
469 IN EFI_PEI_SERVICES **PeiServices,\r
470 IN TIS_TPM_HANDLE TpmHandle\r
471 )\r
472{\r
473 EFI_STATUS Status;\r
474 BOOLEAN Deactivated;\r
475\r
476 Status = TpmCommGetCapability (PeiServices, TpmHandle, &Deactivated, NULL, NULL);\r
477 if (EFI_ERROR (Status)) {\r
478 return FALSE;\r
479 }\r
480 return (BOOLEAN)(!Deactivated); \r
481}\r
482\r
483/**\r
484 Do measurement after memory is ready.\r
485\r
486 @param[in] PeiServices Describes the list of possible PEI Services.\r
487\r
488 @retval EFI_SUCCESS Operation completed successfully.\r
489 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
490 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
491\r
492**/\r
493EFI_STATUS\r
494EFIAPI\r
495PeimEntryMP (\r
496 IN EFI_PEI_SERVICES **PeiServices\r
497 )\r
498{\r
499 EFI_STATUS Status;\r
500 TIS_TPM_HANDLE TpmHandle;\r
501\r
502 TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;\r
503 Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);\r
504 if (EFI_ERROR (Status)) {\r
505 return Status;\r
506 }\r
507\r
508 if (IsTpmUsable (PeiServices, TpmHandle)) {\r
509 Status = MeasureCRTMVersion (PeiServices, TpmHandle);\r
510 ASSERT_EFI_ERROR (Status);\r
511\r
512 Status = MeasureMainBios (PeiServices, TpmHandle);\r
513 } \r
514\r
515 //\r
516 // Post callbacks:\r
517 // 1). for the FvInfoPpi services to measure and record\r
518 // the additional Fvs to TPM\r
519 // 2). for the OperatorPresencePpi service to determine whether to \r
520 // lock the TPM\r
521 //\r
522 Status = PeiServicesNotifyPpi (&mNotifyList[0]);\r
523 ASSERT_EFI_ERROR (Status);\r
524\r
525 return Status;\r
526}\r
527\r
528/**\r
529 Entry point of this module.\r
530\r
531 @param[in] FileHandle Handle of the file being invoked.\r
532 @param[in] PeiServices Describes the list of possible PEI Services.\r
533\r
534 @return Status.\r
535\r
536**/\r
537EFI_STATUS\r
538EFIAPI\r
539PeimEntryMA (\r
540 IN EFI_PEI_FILE_HANDLE FileHandle,\r
541 IN CONST EFI_PEI_SERVICES **PeiServices\r
542 )\r
543{\r
544 EFI_STATUS Status;\r
545 EFI_BOOT_MODE BootMode;\r
546 TIS_TPM_HANDLE TpmHandle;\r
547\r
548 if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {\r
549 return EFI_UNSUPPORTED;\r
550 }\r
551\r
552 Status = (**PeiServices).RegisterForShadow(FileHandle);\r
553 if (Status == EFI_ALREADY_STARTED) {\r
554 mImageInMemory = TRUE;\r
555 } else if (Status == EFI_NOT_FOUND) {\r
556 ASSERT_EFI_ERROR (Status);\r
557 }\r
558\r
559 if (!mImageInMemory) {\r
560 //\r
561 // Initialize TPM device\r
562 //\r
563 Status = PeiServicesGetBootMode (&BootMode);\r
564 ASSERT_EFI_ERROR (Status);\r
565\r
566 TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;\r
567 Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);\r
568 if (EFI_ERROR (Status)) {\r
569 DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));\r
570 return Status;\r
571 }\r
572\r
573 Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode);\r
574 if (EFI_ERROR (Status) ) {\r
575 return Status;\r
576 }\r
577 Status = TpmCommContinueSelfTest ((EFI_PEI_SERVICES**)PeiServices, TpmHandle);\r
578 if (EFI_ERROR (Status)) {\r
579 return Status;\r
580 }\r
581 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);\r
582 ASSERT_EFI_ERROR (Status);\r
583 }\r
584\r
585 if (mImageInMemory) {\r
586 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);\r
587 if (EFI_ERROR (Status)) {\r
588 return Status;\r
589 }\r
590 }\r
591\r
592 return Status;\r
593}\r