]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgPei/TcgPei.c
Enhance TCG driver to provide TPM physical presence lifetime lock capability.
[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
5a500332 4Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
0c18794e 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
5a500332 382 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.\r
383 And lock physical presence if needed.\r
0c18794e 384\r
385 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
386 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
387 @param[in] Ppi Address of the PPI that was installed.\r
388\r
389 @retval EFI_SUCCESS Operation completed successfully.\r
390 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.\r
391 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
392\r
393**/\r
394EFI_STATUS\r
395EFIAPI\r
396PhysicalPresencePpiNotifyCallback (\r
397 IN EFI_PEI_SERVICES **PeiServices,\r
398 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
399 IN VOID *Ppi\r
400 )\r
401{\r
402 EFI_STATUS Status;\r
403 PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi;\r
404 BOOLEAN LifetimeLock;\r
405 BOOLEAN CmdEnable;\r
406 TIS_TPM_HANDLE TpmHandle;\r
5a500332 407 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue;\r
0c18794e 408\r
409 TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS;\r
0c18794e 410\r
5a500332 411 Status = TpmCommGetCapability (PeiServices, TpmHandle, NULL, &LifetimeLock, &CmdEnable);\r
412 if (EFI_ERROR (Status)) {\r
413 return Status;\r
0c18794e 414 }\r
415\r
416 //\r
5a500332 417 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.\r
0c18794e 418 //\r
5a500332 419 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !LifetimeLock) {\r
420 //\r
421 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet. \r
422 //\r
423 PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK;\r
424\r
425 if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) {\r
426 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE;\r
427 CmdEnable = TRUE;\r
428 } else {\r
429 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE;\r
430 CmdEnable = FALSE;\r
431 }\r
0c18794e 432\r
5a500332 433 if (PcdGetBool (PcdPhysicalPresenceHwEnable)) {\r
434 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE;\r
435 } else {\r
436 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE;\r
437 } \r
438 \r
439 Status = TpmCommPhysicalPresence (\r
440 PeiServices,\r
441 TpmHandle,\r
442 PhysicalPresenceValue\r
443 );\r
444 if (EFI_ERROR (Status)) {\r
445 return Status;\r
446 }\r
447 }\r
448 \r
449 //\r
450 // 2. Lock physical presence if it is required.\r
451 //\r
452 LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi;\r
453 if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) {\r
454 return EFI_SUCCESS;\r
0c18794e 455 }\r
456\r
457 if (!CmdEnable) {\r
458 if (LifetimeLock) {\r
459 //\r
460 // physicalPresenceCMDEnable is locked, can't change.\r
461 //\r
462 return EFI_ABORTED;\r
463 }\r
464\r
465 //\r
466 // Enable physical presence command\r
467 // It is necessary in order to lock physical presence\r
468 //\r
469 Status = TpmCommPhysicalPresence (\r
470 PeiServices,\r
471 TpmHandle,\r
472 TPM_PHYSICAL_PRESENCE_CMD_ENABLE\r
473 );\r
474 if (EFI_ERROR (Status)) {\r
475 return Status;\r
476 }\r
477 }\r
478\r
479 //\r
480 // Lock physical presence\r
481 // \r
482 Status = TpmCommPhysicalPresence (\r
483 PeiServices,\r
484 TpmHandle,\r
485 TPM_PHYSICAL_PRESENCE_LOCK\r
486 );\r
487 return Status;\r
488}\r
489\r
490/**\r
491 Check if TPM chip is activeated or not.\r
492\r
493 @param[in] PeiServices Describes the list of possible PEI Services.\r
494 @param[in] TpmHandle TPM handle.\r
495\r
496 @retval TRUE TPM is activated.\r
497 @retval FALSE TPM is deactivated.\r
498\r
499**/\r
500BOOLEAN\r
501EFIAPI\r
502IsTpmUsable (\r
503 IN EFI_PEI_SERVICES **PeiServices,\r
504 IN TIS_TPM_HANDLE TpmHandle\r
505 )\r
506{\r
507 EFI_STATUS Status;\r
508 BOOLEAN Deactivated;\r
509\r
510 Status = TpmCommGetCapability (PeiServices, TpmHandle, &Deactivated, NULL, NULL);\r
511 if (EFI_ERROR (Status)) {\r
512 return FALSE;\r
513 }\r
514 return (BOOLEAN)(!Deactivated); \r
515}\r
516\r
517/**\r
518 Do measurement after memory is ready.\r
519\r
520 @param[in] PeiServices Describes the list of possible PEI Services.\r
521\r
522 @retval EFI_SUCCESS Operation completed successfully.\r
523 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
524 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
525\r
526**/\r
527EFI_STATUS\r
528EFIAPI\r
529PeimEntryMP (\r
530 IN EFI_PEI_SERVICES **PeiServices\r
531 )\r
532{\r
533 EFI_STATUS Status;\r
534 TIS_TPM_HANDLE TpmHandle;\r
535\r
536 TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;\r
537 Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);\r
538 if (EFI_ERROR (Status)) {\r
539 return Status;\r
540 }\r
541\r
542 if (IsTpmUsable (PeiServices, TpmHandle)) {\r
543 Status = MeasureCRTMVersion (PeiServices, TpmHandle);\r
544 ASSERT_EFI_ERROR (Status);\r
545\r
546 Status = MeasureMainBios (PeiServices, TpmHandle);\r
547 } \r
548\r
549 //\r
550 // Post callbacks:\r
551 // 1). for the FvInfoPpi services to measure and record\r
552 // the additional Fvs to TPM\r
553 // 2). for the OperatorPresencePpi service to determine whether to \r
554 // lock the TPM\r
555 //\r
556 Status = PeiServicesNotifyPpi (&mNotifyList[0]);\r
557 ASSERT_EFI_ERROR (Status);\r
558\r
559 return Status;\r
560}\r
561\r
562/**\r
563 Entry point of this module.\r
564\r
565 @param[in] FileHandle Handle of the file being invoked.\r
566 @param[in] PeiServices Describes the list of possible PEI Services.\r
567\r
568 @return Status.\r
569\r
570**/\r
571EFI_STATUS\r
572EFIAPI\r
573PeimEntryMA (\r
574 IN EFI_PEI_FILE_HANDLE FileHandle,\r
575 IN CONST EFI_PEI_SERVICES **PeiServices\r
576 )\r
577{\r
578 EFI_STATUS Status;\r
579 EFI_BOOT_MODE BootMode;\r
580 TIS_TPM_HANDLE TpmHandle;\r
581\r
582 if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) {\r
583 return EFI_UNSUPPORTED;\r
584 }\r
585\r
586 Status = (**PeiServices).RegisterForShadow(FileHandle);\r
587 if (Status == EFI_ALREADY_STARTED) {\r
588 mImageInMemory = TRUE;\r
589 } else if (Status == EFI_NOT_FOUND) {\r
590 ASSERT_EFI_ERROR (Status);\r
591 }\r
592\r
593 if (!mImageInMemory) {\r
594 //\r
595 // Initialize TPM device\r
596 //\r
597 Status = PeiServicesGetBootMode (&BootMode);\r
598 ASSERT_EFI_ERROR (Status);\r
599\r
600 TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;\r
601 Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle);\r
602 if (EFI_ERROR (Status)) {\r
603 DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));\r
604 return Status;\r
605 }\r
606\r
607 Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode);\r
608 if (EFI_ERROR (Status) ) {\r
609 return Status;\r
610 }\r
611 Status = TpmCommContinueSelfTest ((EFI_PEI_SERVICES**)PeiServices, TpmHandle);\r
612 if (EFI_ERROR (Status)) {\r
613 return Status;\r
614 }\r
615 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);\r
616 ASSERT_EFI_ERROR (Status);\r
617 }\r
618\r
619 if (mImageInMemory) {\r
620 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);\r
621 if (EFI_ERROR (Status)) {\r
622 return Status;\r
623 }\r
624 }\r
625\r
626 return Status;\r
627}\r