2 Pei Core Main Entry Point
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi
= {
12 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
13 &gEfiPeiMemoryDiscoveredPpiGuid
,
18 /// Pei service instance
20 EFI_PEI_SERVICES gPs
= {
22 PEI_SERVICES_SIGNATURE
,
23 PEI_SERVICES_REVISION
,
24 sizeof (EFI_PEI_SERVICES
),
41 PeiFfsFindSectionData
,
46 (EFI_PEI_COPY_MEM
)CopyMem
,
47 (EFI_PEI_SET_MEM
)SetMem
,
53 &gPeiDefaultPciCfg2Ppi
,
59 PeiFfsFindSectionData3
,
66 Shadow PeiCore module from flash to installed memory.
68 @param PrivateData PeiCore's private data structure
70 @return PeiCore function address after shadowing.
72 PEICORE_FUNCTION_POINTER
74 IN PEI_CORE_INSTANCE
*PrivateData
77 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
78 EFI_PHYSICAL_ADDRESS EntryPoint
;
80 UINT32 AuthenticationState
;
82 EFI_PEI_CORE_FV_LOCATION_PPI
*PeiCoreFvLocationPpi
;
85 PeiCoreFileHandle
= NULL
;
87 // Default PeiCore is in BFV
91 // Find the PEI Core either from EFI_PEI_CORE_FV_LOCATION_PPI indicated FV or BFV
93 Status
= PeiServicesLocatePpi (
94 &gEfiPeiCoreFvLocationPpiGuid
,
97 (VOID
**)&PeiCoreFvLocationPpi
99 if (!EFI_ERROR (Status
) && (PeiCoreFvLocationPpi
->PeiCoreFvLocation
!= NULL
)) {
101 // If PeiCoreFvLocation present, the PEI Core should be found from indicated FV
103 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
104 if (PrivateData
->Fv
[Index
].FvHandle
== PeiCoreFvLocationPpi
->PeiCoreFvLocation
) {
105 PeiCoreFvIndex
= Index
;
110 ASSERT (Index
< PrivateData
->FvCount
);
114 // Find PEI Core from the given FV index
116 Status
= PrivateData
->Fv
[PeiCoreFvIndex
].FvPpi
->FindFileByType (
117 PrivateData
->Fv
[PeiCoreFvIndex
].FvPpi
,
118 EFI_FV_FILETYPE_PEI_CORE
,
119 PrivateData
->Fv
[PeiCoreFvIndex
].FvHandle
,
122 ASSERT_EFI_ERROR (Status
);
125 // Shadow PEI Core into memory so it will run faster
127 Status
= PeiLoadImage (
128 GetPeiServicesTablePointer (),
129 *((EFI_PEI_FILE_HANDLE
*)&PeiCoreFileHandle
),
130 PEIM_STATE_REGISTER_FOR_SHADOW
,
134 ASSERT_EFI_ERROR (Status
);
137 // Compute the PeiCore's function address after shadowed PeiCore.
138 // _ModuleEntryPoint is PeiCore main function entry
140 return (PEICORE_FUNCTION_POINTER
)((UINTN
)EntryPoint
+ (UINTN
)PeiCore
- (UINTN
)_ModuleEntryPoint
);
144 This routine is invoked by main entry of PeiMain module during transition
145 from SEC to PEI. After switching stack in the PEI core, it will restart
146 with the old core data.
148 @param SecCoreDataPtr Points to a data structure containing information about the PEI core's operating
149 environment, such as the size and location of temporary RAM, the stack location and
151 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
152 An empty PPI list consists of a single descriptor with the end-tag
153 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
154 phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
155 that both the PEI Foundation and any modules can leverage the associated service
156 calls and/or code in these early PPIs
157 @param Data Pointer to old core data that is used to initialize the
159 If NULL, it is first PeiCore entering.
165 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreDataPtr
,
166 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
,
170 PEI_CORE_INSTANCE PrivateData
;
171 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
172 EFI_SEC_PEI_HAND_OFF NewSecCoreData
;
174 PEI_CORE_TEMP_POINTERS TempPtr
;
175 PEI_CORE_INSTANCE
*OldCoreData
;
176 EFI_PEI_CPU_IO_PPI
*CpuIo
;
177 EFI_PEI_PCI_CFG2_PPI
*PciCfg
;
178 EFI_HOB_HANDOFF_INFO_TABLE
*HandoffInformationTable
;
179 EFI_PEI_TEMPORARY_RAM_DONE_PPI
*TemporaryRamDonePpi
;
183 // Retrieve context passed into PEI Core
185 OldCoreData
= (PEI_CORE_INSTANCE
*)Data
;
186 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)SecCoreDataPtr
;
189 // Perform PEI Core phase specific actions.
191 if (OldCoreData
== NULL
) {
193 // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available.
195 ZeroMem (&PrivateData
, sizeof (PEI_CORE_INSTANCE
));
196 PrivateData
.Signature
= PEI_CORE_HANDLE_SIGNATURE
;
197 CopyMem (&PrivateData
.ServiceTableShadow
, &gPs
, sizeof (gPs
));
200 // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet.
202 if (OldCoreData
->ShadowedPeiCore
== NULL
) {
204 // Fixup the PeiCore's private data
206 OldCoreData
->Ps
= &OldCoreData
->ServiceTableShadow
;
207 OldCoreData
->CpuIo
= &OldCoreData
->ServiceTableShadow
.CpuIo
;
208 if (OldCoreData
->HeapOffsetPositive
) {
209 OldCoreData
->HobList
.Raw
= (VOID
*)(OldCoreData
->HobList
.Raw
+ OldCoreData
->HeapOffset
);
210 if (OldCoreData
->UnknownFvInfo
!= NULL
) {
211 OldCoreData
->UnknownFvInfo
= (PEI_CORE_UNKNOW_FORMAT_FV_INFO
*)((UINT8
*)OldCoreData
->UnknownFvInfo
+ OldCoreData
->HeapOffset
);
214 if (OldCoreData
->CurrentFvFileHandles
!= NULL
) {
215 OldCoreData
->CurrentFvFileHandles
= (EFI_PEI_FILE_HANDLE
*)((UINT8
*)OldCoreData
->CurrentFvFileHandles
+ OldCoreData
->HeapOffset
);
218 if (OldCoreData
->PpiData
.PpiList
.PpiPtrs
!= NULL
) {
219 OldCoreData
->PpiData
.PpiList
.PpiPtrs
= (PEI_PPI_LIST_POINTERS
*)((UINT8
*)OldCoreData
->PpiData
.PpiList
.PpiPtrs
+ OldCoreData
->HeapOffset
);
222 if (OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
!= NULL
) {
223 OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
= (PEI_PPI_LIST_POINTERS
*)((UINT8
*)OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
+ OldCoreData
->HeapOffset
);
226 if (OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
!= NULL
) {
227 OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
= (PEI_PPI_LIST_POINTERS
*)((UINT8
*)OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
+ OldCoreData
->HeapOffset
);
230 OldCoreData
->Fv
= (PEI_CORE_FV_HANDLE
*)((UINT8
*)OldCoreData
->Fv
+ OldCoreData
->HeapOffset
);
231 for (Index
= 0; Index
< OldCoreData
->FvCount
; Index
++) {
232 if (OldCoreData
->Fv
[Index
].PeimState
!= NULL
) {
233 OldCoreData
->Fv
[Index
].PeimState
= (UINT8
*)OldCoreData
->Fv
[Index
].PeimState
+ OldCoreData
->HeapOffset
;
236 if (OldCoreData
->Fv
[Index
].FvFileHandles
!= NULL
) {
237 OldCoreData
->Fv
[Index
].FvFileHandles
= (EFI_PEI_FILE_HANDLE
*)((UINT8
*)OldCoreData
->Fv
[Index
].FvFileHandles
+ OldCoreData
->HeapOffset
);
241 OldCoreData
->TempFileGuid
= (EFI_GUID
*)((UINT8
*)OldCoreData
->TempFileGuid
+ OldCoreData
->HeapOffset
);
242 OldCoreData
->TempFileHandles
= (EFI_PEI_FILE_HANDLE
*)((UINT8
*)OldCoreData
->TempFileHandles
+ OldCoreData
->HeapOffset
);
244 OldCoreData
->HobList
.Raw
= (VOID
*)(OldCoreData
->HobList
.Raw
- OldCoreData
->HeapOffset
);
245 if (OldCoreData
->UnknownFvInfo
!= NULL
) {
246 OldCoreData
->UnknownFvInfo
= (PEI_CORE_UNKNOW_FORMAT_FV_INFO
*)((UINT8
*)OldCoreData
->UnknownFvInfo
- OldCoreData
->HeapOffset
);
249 if (OldCoreData
->CurrentFvFileHandles
!= NULL
) {
250 OldCoreData
->CurrentFvFileHandles
= (EFI_PEI_FILE_HANDLE
*)((UINT8
*)OldCoreData
->CurrentFvFileHandles
- OldCoreData
->HeapOffset
);
253 if (OldCoreData
->PpiData
.PpiList
.PpiPtrs
!= NULL
) {
254 OldCoreData
->PpiData
.PpiList
.PpiPtrs
= (PEI_PPI_LIST_POINTERS
*)((UINT8
*)OldCoreData
->PpiData
.PpiList
.PpiPtrs
- OldCoreData
->HeapOffset
);
257 if (OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
!= NULL
) {
258 OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
= (PEI_PPI_LIST_POINTERS
*)((UINT8
*)OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
- OldCoreData
->HeapOffset
);
261 if (OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
!= NULL
) {
262 OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
= (PEI_PPI_LIST_POINTERS
*)((UINT8
*)OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
- OldCoreData
->HeapOffset
);
265 OldCoreData
->Fv
= (PEI_CORE_FV_HANDLE
*)((UINT8
*)OldCoreData
->Fv
- OldCoreData
->HeapOffset
);
266 for (Index
= 0; Index
< OldCoreData
->FvCount
; Index
++) {
267 if (OldCoreData
->Fv
[Index
].PeimState
!= NULL
) {
268 OldCoreData
->Fv
[Index
].PeimState
= (UINT8
*)OldCoreData
->Fv
[Index
].PeimState
- OldCoreData
->HeapOffset
;
271 if (OldCoreData
->Fv
[Index
].FvFileHandles
!= NULL
) {
272 OldCoreData
->Fv
[Index
].FvFileHandles
= (EFI_PEI_FILE_HANDLE
*)((UINT8
*)OldCoreData
->Fv
[Index
].FvFileHandles
- OldCoreData
->HeapOffset
);
276 OldCoreData
->TempFileGuid
= (EFI_GUID
*)((UINT8
*)OldCoreData
->TempFileGuid
- OldCoreData
->HeapOffset
);
277 OldCoreData
->TempFileHandles
= (EFI_PEI_FILE_HANDLE
*)((UINT8
*)OldCoreData
->TempFileHandles
- OldCoreData
->HeapOffset
);
281 // Fixup for PeiService's address
283 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES
**)&OldCoreData
->Ps
);
286 // Initialize libraries that the PEI Core is linked against
288 ProcessLibraryConstructorList (NULL
, (CONST EFI_PEI_SERVICES
**)&OldCoreData
->Ps
);
291 // Update HandOffHob for new installed permanent memory
293 HandoffInformationTable
= OldCoreData
->HobList
.HandoffInformationTable
;
294 if (OldCoreData
->HeapOffsetPositive
) {
295 HandoffInformationTable
->EfiEndOfHobList
= HandoffInformationTable
->EfiEndOfHobList
+ OldCoreData
->HeapOffset
;
297 HandoffInformationTable
->EfiEndOfHobList
= HandoffInformationTable
->EfiEndOfHobList
- OldCoreData
->HeapOffset
;
300 HandoffInformationTable
->EfiMemoryTop
= OldCoreData
->PhysicalMemoryBegin
+ OldCoreData
->PhysicalMemoryLength
;
301 HandoffInformationTable
->EfiMemoryBottom
= OldCoreData
->PhysicalMemoryBegin
;
302 HandoffInformationTable
->EfiFreeMemoryTop
= OldCoreData
->FreePhysicalMemoryTop
;
303 HandoffInformationTable
->EfiFreeMemoryBottom
= HandoffInformationTable
->EfiEndOfHobList
+ sizeof (EFI_HOB_GENERIC_HEADER
);
306 // We need convert MemoryBaseAddress in memory allocation HOBs
308 ConvertMemoryAllocationHobs (OldCoreData
);
311 // We need convert the PPI descriptor's pointer
313 ConvertPpiPointers (SecCoreData
, OldCoreData
);
316 // After the whole temporary memory is migrated, then we can allocate page in
319 OldCoreData
->PeiMemoryInstalled
= TRUE
;
322 // Indicate that PeiCore reenter
324 OldCoreData
->PeimDispatcherReenter
= TRUE
;
326 if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable
) != 0) && (OldCoreData
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
328 // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
329 // Every bit in the array indicate the status of the corresponding memory page available or not
331 OldCoreData
->PeiCodeMemoryRangeUsageBitMap
= AllocateZeroPool (((PcdGet32 (PcdLoadFixAddressPeiCodePageNumber
)>>6) + 1)*sizeof (UINT64
));
335 // Shadow PEI Core. When permanent memory is available, shadow
336 // PEI Core and PEIMs to get high performance.
338 OldCoreData
->ShadowedPeiCore
= (PEICORE_FUNCTION_POINTER
)(UINTN
)PeiCore
;
339 if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
) ||
340 ((HandoffInformationTable
->BootMode
== BOOT_ON_S3_RESUME
) && PcdGetBool (PcdShadowPeimOnS3Boot
)) ||
341 ((HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
) && PcdGetBool (PcdShadowPeimOnBoot
)))
343 OldCoreData
->ShadowedPeiCore
= ShadowPeiCore (OldCoreData
);
347 // PEI Core has now been shadowed to memory. Restart PEI Core in memory.
349 OldCoreData
->ShadowedPeiCore (SecCoreData
, PpiList
, OldCoreData
);
352 // Should never reach here.
361 // Memory is available to the PEI Core and the PEI Core has been shadowed to memory.
363 CopyMem (&NewSecCoreData
, SecCoreDataPtr
, sizeof (NewSecCoreData
));
364 SecCoreData
= &NewSecCoreData
;
366 CopyMem (&PrivateData
, OldCoreData
, sizeof (PrivateData
));
368 CpuIo
= (VOID
*)PrivateData
.ServiceTableShadow
.CpuIo
;
369 PciCfg
= (VOID
*)PrivateData
.ServiceTableShadow
.PciCfg
;
371 CopyMem (&PrivateData
.ServiceTableShadow
, &gPs
, sizeof (gPs
));
373 PrivateData
.ServiceTableShadow
.CpuIo
= CpuIo
;
374 PrivateData
.ServiceTableShadow
.PciCfg
= PciCfg
;
378 // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory
380 PrivateData
.Ps
= &PrivateData
.ServiceTableShadow
;
383 // Save PeiServicePointer so that it can be retrieved anywhere.
385 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES
**)&PrivateData
.Ps
);
388 // Initialize libraries that the PEI Core is linked against
390 ProcessLibraryConstructorList (NULL
, (CONST EFI_PEI_SERVICES
**)&PrivateData
.Ps
);
393 // Initialize PEI Core Services
395 InitializeMemoryServices (&PrivateData
, SecCoreData
, OldCoreData
);
398 // Update performance measurements
400 if (OldCoreData
== NULL
) {
401 PERF_EVENT ("SEC"); // Means the end of SEC phase.
404 // If first pass, start performance measurement.
406 PERF_CROSSMODULE_BEGIN ("PEI");
407 PERF_INMODULE_BEGIN ("PreMem");
409 PERF_INMODULE_END ("PreMem");
410 PERF_INMODULE_BEGIN ("PostMem");
414 // Complete PEI Core Service initialization
416 InitializeSecurityServices (&PrivateData
.Ps
, OldCoreData
);
417 InitializeDispatcherData (&PrivateData
, OldCoreData
, SecCoreData
);
418 InitializeImageServices (&PrivateData
, OldCoreData
);
421 // Perform PEI Core Phase specific actions
423 if (OldCoreData
== NULL
) {
425 // Report Status Code EFI_SW_PC_INIT
429 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT
)
433 // If SEC provided the PpiList, process it.
435 if (PpiList
!= NULL
) {
436 ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES
**)&PrivateData
.Ps
, PpiList
);
439 if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
)) {
441 // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all
442 // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot
444 DEBUG ((DEBUG_VERBOSE
, "PPI lists before temporary RAM evacuation:\n"));
445 DumpPpiList (&PrivateData
);
448 // Migrate installed content from Temporary RAM to Permanent RAM
450 EvacuateTempRam (&PrivateData
, SecCoreData
);
452 DEBUG ((DEBUG_VERBOSE
, "PPI lists after temporary RAM evacuation:\n"));
453 DumpPpiList (&PrivateData
);
457 // Try to locate Temporary RAM Done Ppi.
459 Status
= PeiServicesLocatePpi (
460 &gEfiTemporaryRamDonePpiGuid
,
463 (VOID
**)&TemporaryRamDonePpi
465 if (!EFI_ERROR (Status
)) {
467 // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete.
469 TemporaryRamDonePpi
->TemporaryRamDone ();
473 // Alert any listeners that there is permanent memory available
475 PERF_INMODULE_BEGIN ("DisMem");
476 Status
= PeiServicesInstallPpi (&mMemoryDiscoveredPpi
);
479 // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
481 ProcessDispatchNotifyList (&PrivateData
);
483 PERF_INMODULE_END ("DisMem");
487 // Call PEIM dispatcher
489 PeiDispatcher (SecCoreData
, &PrivateData
);
491 if (PrivateData
.HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
) {
493 // Check if InstallPeiMemory service was called on non-S3 resume boot path.
495 ASSERT (PrivateData
.PeiMemoryInstalled
== TRUE
);
499 // Measure PEI Core execution time.
501 PERF_INMODULE_END ("PostMem");
504 // Lookup DXE IPL PPI
506 Status
= PeiServicesLocatePpi (
510 (VOID
**)&TempPtr
.DxeIpl
512 ASSERT_EFI_ERROR (Status
);
514 if (EFI_ERROR (Status
)) {
516 // Report status code to indicate DXE IPL PPI could not be found.
519 EFI_ERROR_CODE
| EFI_ERROR_MAJOR
,
520 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND
)
526 // Enter DxeIpl to load Dxe core.
528 DEBUG ((DEBUG_INFO
, "DXE IPL Entry\n"));
529 Status
= TempPtr
.DxeIpl
->Entry (
535 // Should never reach here.
537 ASSERT_EFI_ERROR (Status
);