2 Pei Core Main Entry Point
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi
= {
18 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
19 &gEfiPeiMemoryDiscoveredPpiGuid
,
24 /// Pei service instance
26 EFI_PEI_SERVICES gPs
= {
28 PEI_SERVICES_SIGNATURE
,
29 PEI_SERVICES_REVISION
,
30 sizeof (EFI_PEI_SERVICES
),
47 PeiFfsFindSectionData
,
52 (EFI_PEI_COPY_MEM
)CopyMem
,
53 (EFI_PEI_SET_MEM
)SetMem
,
59 &gPeiDefaultPciCfg2Ppi
,
65 PeiFfsFindSectionData3
,
72 Shadow PeiCore module from flash to installed memory.
74 @param PrivateData PeiCore's private data structure
76 @return PeiCore function address after shadowing.
78 PEICORE_FUNCTION_POINTER
80 IN PEI_CORE_INSTANCE
*PrivateData
83 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
84 EFI_PHYSICAL_ADDRESS EntryPoint
;
86 UINT32 AuthenticationState
;
88 EFI_PEI_CORE_FV_LOCATION_PPI
*PeiCoreFvLocationPpi
;
91 PeiCoreFileHandle
= NULL
;
93 // Default PeiCore is in BFV
97 // Find the PEI Core either from EFI_PEI_CORE_FV_LOCATION_PPI indicated FV or BFV
99 Status
= PeiServicesLocatePpi (
100 &gEfiPeiCoreFvLocationPpiGuid
,
103 (VOID
**) &PeiCoreFvLocationPpi
105 if (!EFI_ERROR (Status
) && (PeiCoreFvLocationPpi
->PeiCoreFvLocation
!= NULL
)) {
107 // If PeiCoreFvLocation present, the PEI Core should be found from indicated FV
109 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
110 if (PrivateData
->Fv
[Index
].FvHandle
== PeiCoreFvLocationPpi
->PeiCoreFvLocation
) {
111 PeiCoreFvIndex
= Index
;
115 ASSERT (Index
< PrivateData
->FvCount
);
118 // Find PEI Core from the given FV index
120 Status
= PrivateData
->Fv
[PeiCoreFvIndex
].FvPpi
->FindFileByType (
121 PrivateData
->Fv
[PeiCoreFvIndex
].FvPpi
,
122 EFI_FV_FILETYPE_PEI_CORE
,
123 PrivateData
->Fv
[PeiCoreFvIndex
].FvHandle
,
126 ASSERT_EFI_ERROR (Status
);
129 // Shadow PEI Core into memory so it will run faster
131 Status
= PeiLoadImage (
132 GetPeiServicesTablePointer (),
133 *((EFI_PEI_FILE_HANDLE
*)&PeiCoreFileHandle
),
134 PEIM_STATE_REGISTER_FOR_SHADOW
,
138 ASSERT_EFI_ERROR (Status
);
141 // Compute the PeiCore's function address after shaowed PeiCore.
142 // _ModuleEntryPoint is PeiCore main function entry
144 return (PEICORE_FUNCTION_POINTER
)((UINTN
) EntryPoint
+ (UINTN
) PeiCore
- (UINTN
) _ModuleEntryPoint
);
148 This routine is invoked by main entry of PeiMain module during transition
149 from SEC to PEI. After switching stack in the PEI core, it will restart
150 with the old core data.
152 @param SecCoreDataPtr Points to a data structure containing information about the PEI core's operating
153 environment, such as the size and location of temporary RAM, the stack location and
155 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
156 An empty PPI list consists of a single descriptor with the end-tag
157 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
158 phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
159 that both the PEI Foundation and any modules can leverage the associated service
160 calls and/or code in these early PPIs
161 @param Data Pointer to old core data that is used to initialize the
163 If NULL, it is first PeiCore entering.
169 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreDataPtr
,
170 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
,
174 PEI_CORE_INSTANCE PrivateData
;
175 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
176 EFI_SEC_PEI_HAND_OFF NewSecCoreData
;
178 PEI_CORE_TEMP_POINTERS TempPtr
;
179 PEI_CORE_INSTANCE
*OldCoreData
;
180 EFI_PEI_CPU_IO_PPI
*CpuIo
;
181 EFI_PEI_PCI_CFG2_PPI
*PciCfg
;
182 EFI_HOB_HANDOFF_INFO_TABLE
*HandoffInformationTable
;
183 EFI_PEI_TEMPORARY_RAM_DONE_PPI
*TemporaryRamDonePpi
;
187 // Retrieve context passed into PEI Core
189 OldCoreData
= (PEI_CORE_INSTANCE
*) Data
;
190 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*) SecCoreDataPtr
;
193 // Perform PEI Core phase specific actions.
195 if (OldCoreData
== NULL
) {
197 // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available.
199 ZeroMem (&PrivateData
, sizeof (PEI_CORE_INSTANCE
));
200 PrivateData
.Signature
= PEI_CORE_HANDLE_SIGNATURE
;
201 CopyMem (&PrivateData
.ServiceTableShadow
, &gPs
, sizeof (gPs
));
204 // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet.
206 if (OldCoreData
->ShadowedPeiCore
== NULL
) {
208 // Fixup the PeiCore's private data
210 OldCoreData
->Ps
= &OldCoreData
->ServiceTableShadow
;
211 OldCoreData
->CpuIo
= &OldCoreData
->ServiceTableShadow
.CpuIo
;
212 if (OldCoreData
->HeapOffsetPositive
) {
213 OldCoreData
->HobList
.Raw
= (VOID
*)(OldCoreData
->HobList
.Raw
+ OldCoreData
->HeapOffset
);
214 if (OldCoreData
->UnknownFvInfo
!= NULL
) {
215 OldCoreData
->UnknownFvInfo
= (PEI_CORE_UNKNOW_FORMAT_FV_INFO
*) ((UINT8
*) OldCoreData
->UnknownFvInfo
+ OldCoreData
->HeapOffset
);
217 if (OldCoreData
->CurrentFvFileHandles
!= NULL
) {
218 OldCoreData
->CurrentFvFileHandles
= (EFI_PEI_FILE_HANDLE
*) ((UINT8
*) OldCoreData
->CurrentFvFileHandles
+ OldCoreData
->HeapOffset
);
220 if (OldCoreData
->PpiData
.PpiList
.PpiPtrs
!= NULL
) {
221 OldCoreData
->PpiData
.PpiList
.PpiPtrs
= (PEI_PPI_LIST_POINTERS
*) ((UINT8
*) OldCoreData
->PpiData
.PpiList
.PpiPtrs
+ OldCoreData
->HeapOffset
);
223 if (OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
!= NULL
) {
224 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
);
229 OldCoreData
->Fv
= (PEI_CORE_FV_HANDLE
*) ((UINT8
*) OldCoreData
->Fv
+ OldCoreData
->HeapOffset
);
230 for (Index
= 0; Index
< OldCoreData
->FvCount
; Index
++) {
231 if (OldCoreData
->Fv
[Index
].PeimState
!= NULL
) {
232 OldCoreData
->Fv
[Index
].PeimState
= (UINT8
*) OldCoreData
->Fv
[Index
].PeimState
+ OldCoreData
->HeapOffset
;
234 if (OldCoreData
->Fv
[Index
].FvFileHandles
!= NULL
) {
235 OldCoreData
->Fv
[Index
].FvFileHandles
= (EFI_PEI_FILE_HANDLE
*) ((UINT8
*) OldCoreData
->Fv
[Index
].FvFileHandles
+ OldCoreData
->HeapOffset
);
238 OldCoreData
->TempFileGuid
= (EFI_GUID
*) ((UINT8
*) OldCoreData
->TempFileGuid
+ OldCoreData
->HeapOffset
);
239 OldCoreData
->TempFileHandles
= (EFI_PEI_FILE_HANDLE
*) ((UINT8
*) OldCoreData
->TempFileHandles
+ OldCoreData
->HeapOffset
);
241 OldCoreData
->HobList
.Raw
= (VOID
*)(OldCoreData
->HobList
.Raw
- OldCoreData
->HeapOffset
);
242 if (OldCoreData
->UnknownFvInfo
!= NULL
) {
243 OldCoreData
->UnknownFvInfo
= (PEI_CORE_UNKNOW_FORMAT_FV_INFO
*) ((UINT8
*) OldCoreData
->UnknownFvInfo
- OldCoreData
->HeapOffset
);
245 if (OldCoreData
->CurrentFvFileHandles
!= NULL
) {
246 OldCoreData
->CurrentFvFileHandles
= (EFI_PEI_FILE_HANDLE
*) ((UINT8
*) OldCoreData
->CurrentFvFileHandles
- OldCoreData
->HeapOffset
);
248 if (OldCoreData
->PpiData
.PpiList
.PpiPtrs
!= NULL
) {
249 OldCoreData
->PpiData
.PpiList
.PpiPtrs
= (PEI_PPI_LIST_POINTERS
*) ((UINT8
*) OldCoreData
->PpiData
.PpiList
.PpiPtrs
- OldCoreData
->HeapOffset
);
251 if (OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
!= NULL
) {
252 OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
= (PEI_PPI_LIST_POINTERS
*) ((UINT8
*) OldCoreData
->PpiData
.CallbackNotifyList
.NotifyPtrs
- OldCoreData
->HeapOffset
);
254 if (OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
!= NULL
) {
255 OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
= (PEI_PPI_LIST_POINTERS
*) ((UINT8
*) OldCoreData
->PpiData
.DispatchNotifyList
.NotifyPtrs
- OldCoreData
->HeapOffset
);
257 OldCoreData
->Fv
= (PEI_CORE_FV_HANDLE
*) ((UINT8
*) OldCoreData
->Fv
- OldCoreData
->HeapOffset
);
258 for (Index
= 0; Index
< OldCoreData
->FvCount
; Index
++) {
259 if (OldCoreData
->Fv
[Index
].PeimState
!= NULL
) {
260 OldCoreData
->Fv
[Index
].PeimState
= (UINT8
*) OldCoreData
->Fv
[Index
].PeimState
- OldCoreData
->HeapOffset
;
262 if (OldCoreData
->Fv
[Index
].FvFileHandles
!= NULL
) {
263 OldCoreData
->Fv
[Index
].FvFileHandles
= (EFI_PEI_FILE_HANDLE
*) ((UINT8
*) OldCoreData
->Fv
[Index
].FvFileHandles
- OldCoreData
->HeapOffset
);
266 OldCoreData
->TempFileGuid
= (EFI_GUID
*) ((UINT8
*) OldCoreData
->TempFileGuid
- OldCoreData
->HeapOffset
);
267 OldCoreData
->TempFileHandles
= (EFI_PEI_FILE_HANDLE
*) ((UINT8
*) OldCoreData
->TempFileHandles
- OldCoreData
->HeapOffset
);
271 // Fixup for PeiService's address
273 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES
**)&OldCoreData
->Ps
);
276 // Initialize libraries that the PEI Core is linked against
278 ProcessLibraryConstructorList (NULL
, (CONST EFI_PEI_SERVICES
**)&OldCoreData
->Ps
);
281 // Update HandOffHob for new installed permanent memory
283 HandoffInformationTable
= OldCoreData
->HobList
.HandoffInformationTable
;
284 if (OldCoreData
->HeapOffsetPositive
) {
285 HandoffInformationTable
->EfiEndOfHobList
= HandoffInformationTable
->EfiEndOfHobList
+ OldCoreData
->HeapOffset
;
287 HandoffInformationTable
->EfiEndOfHobList
= HandoffInformationTable
->EfiEndOfHobList
- OldCoreData
->HeapOffset
;
289 HandoffInformationTable
->EfiMemoryTop
= OldCoreData
->PhysicalMemoryBegin
+ OldCoreData
->PhysicalMemoryLength
;
290 HandoffInformationTable
->EfiMemoryBottom
= OldCoreData
->PhysicalMemoryBegin
;
291 HandoffInformationTable
->EfiFreeMemoryTop
= OldCoreData
->FreePhysicalMemoryTop
;
292 HandoffInformationTable
->EfiFreeMemoryBottom
= HandoffInformationTable
->EfiEndOfHobList
+ sizeof (EFI_HOB_GENERIC_HEADER
);
295 // We need convert MemoryBaseAddress in memory allocation HOBs
297 ConvertMemoryAllocationHobs (OldCoreData
);
300 // We need convert the PPI descriptor's pointer
302 ConvertPpiPointers (SecCoreData
, OldCoreData
);
305 // After the whole temporary memory is migrated, then we can allocate page in
308 OldCoreData
->PeiMemoryInstalled
= TRUE
;
311 // Indicate that PeiCore reenter
313 OldCoreData
->PeimDispatcherReenter
= TRUE
;
315 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0 && (OldCoreData
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
317 // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
318 // Every bit in the array indicate the status of the corresponding memory page available or not
320 OldCoreData
->PeiCodeMemoryRangeUsageBitMap
= AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber
)>>6) + 1)*sizeof(UINT64
));
324 // Shadow PEI Core. When permanent memory is avaiable, shadow
325 // PEI Core and PEIMs to get high performance.
327 OldCoreData
->ShadowedPeiCore
= (PEICORE_FUNCTION_POINTER
) (UINTN
) PeiCore
;
328 if ((HandoffInformationTable
->BootMode
== BOOT_ON_S3_RESUME
&& PcdGetBool (PcdShadowPeimOnS3Boot
))
329 || (HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
&& PcdGetBool (PcdShadowPeimOnBoot
))) {
330 OldCoreData
->ShadowedPeiCore
= ShadowPeiCore (OldCoreData
);
334 // PEI Core has now been shadowed to memory. Restart PEI Core in memory.
336 OldCoreData
->ShadowedPeiCore (SecCoreData
, PpiList
, OldCoreData
);
339 // Should never reach here.
348 // Memory is available to the PEI Core and the PEI Core has been shadowed to memory.
350 CopyMem (&NewSecCoreData
, SecCoreDataPtr
, sizeof (NewSecCoreData
));
351 SecCoreData
= &NewSecCoreData
;
353 CopyMem (&PrivateData
, OldCoreData
, sizeof (PrivateData
));
355 CpuIo
= (VOID
*)PrivateData
.ServiceTableShadow
.CpuIo
;
356 PciCfg
= (VOID
*)PrivateData
.ServiceTableShadow
.PciCfg
;
358 CopyMem (&PrivateData
.ServiceTableShadow
, &gPs
, sizeof (gPs
));
360 PrivateData
.ServiceTableShadow
.CpuIo
= CpuIo
;
361 PrivateData
.ServiceTableShadow
.PciCfg
= PciCfg
;
365 // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory
367 PrivateData
.Ps
= &PrivateData
.ServiceTableShadow
;
370 // Save PeiServicePointer so that it can be retrieved anywhere.
372 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES
**)&PrivateData
.Ps
);
375 // Initialize libraries that the PEI Core is linked against
377 ProcessLibraryConstructorList (NULL
, (CONST EFI_PEI_SERVICES
**)&PrivateData
.Ps
);
380 // Initialize PEI Core Services
382 InitializeMemoryServices (&PrivateData
, SecCoreData
, OldCoreData
);
385 // Update performance measurements
387 if (OldCoreData
== NULL
) {
388 PERF_EVENT ("SEC"); // Means the end of SEC phase.
391 // If first pass, start performance measurement.
393 PERF_CROSSMODULE_BEGIN ("PEI");
394 PERF_INMODULE_BEGIN ("PreMem");
397 PERF_INMODULE_END ("PreMem");
398 PERF_INMODULE_BEGIN ("PostMem");
402 // Complete PEI Core Service initialization
404 InitializeSecurityServices (&PrivateData
.Ps
, OldCoreData
);
405 InitializeDispatcherData (&PrivateData
, OldCoreData
, SecCoreData
);
406 InitializeImageServices (&PrivateData
, OldCoreData
);
409 // Perform PEI Core Phase specific actions
411 if (OldCoreData
== NULL
) {
413 // Report Status Code EFI_SW_PC_INIT
417 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT
)
421 // If SEC provided the PpiList, process it.
423 if (PpiList
!= NULL
) {
424 ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES
**) &PrivateData
.Ps
, PpiList
);
428 // Try to locate Temporary RAM Done Ppi.
430 Status
= PeiServicesLocatePpi (
431 &gEfiTemporaryRamDonePpiGuid
,
434 (VOID
**)&TemporaryRamDonePpi
436 if (!EFI_ERROR (Status
)) {
438 // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete.
440 TemporaryRamDonePpi
->TemporaryRamDone ();
444 // Alert any listeners that there is permanent memory available
446 PERF_INMODULE_BEGIN ("DisMem");
447 Status
= PeiServicesInstallPpi (&mMemoryDiscoveredPpi
);
450 // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
452 ProcessDispatchNotifyList (&PrivateData
);
454 PERF_INMODULE_END ("DisMem");
458 // Call PEIM dispatcher
460 PeiDispatcher (SecCoreData
, &PrivateData
);
462 if (PrivateData
.HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
) {
464 // Check if InstallPeiMemory service was called on non-S3 resume boot path.
466 ASSERT(PrivateData
.PeiMemoryInstalled
== TRUE
);
470 // Measure PEI Core execution time.
472 PERF_INMODULE_END ("PostMem");
475 // Lookup DXE IPL PPI
477 Status
= PeiServicesLocatePpi (
481 (VOID
**)&TempPtr
.DxeIpl
483 ASSERT_EFI_ERROR (Status
);
485 if (EFI_ERROR (Status
)) {
487 // Report status code to indicate DXE IPL PPI could not be found.
490 EFI_ERROR_CODE
| EFI_ERROR_MAJOR
,
491 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND
)
497 // Enter DxeIpl to load Dxe core.
499 DEBUG ((EFI_D_INFO
, "DXE IPL Entry\n"));
500 Status
= TempPtr
.DxeIpl
->Entry (
506 // Should never reach here.
508 ASSERT_EFI_ERROR (Status
);