2 Pei Core Main Entry Point
4 Copyright (c) 2006 - 2010, 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
,
68 Shadow PeiCore module from flash to installed memory.
70 @param PrivateData PeiCore's private data structure
72 @return PeiCore function address after shadowing.
74 PEICORE_FUNCTION_POINTER
76 IN PEI_CORE_INSTANCE
*PrivateData
79 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
80 EFI_PHYSICAL_ADDRESS EntryPoint
;
82 UINT32 AuthenticationState
;
84 PeiCoreFileHandle
= NULL
;
87 // Find the PEI Core in the BFV
89 Status
= PrivateData
->Fv
[0].FvPpi
->FindFileByType (
90 PrivateData
->Fv
[0].FvPpi
,
91 EFI_FV_FILETYPE_PEI_CORE
,
92 PrivateData
->Fv
[0].FvHandle
,
95 ASSERT_EFI_ERROR (Status
);
98 // Shadow PEI Core into memory so it will run faster
100 Status
= PeiLoadImage (
101 GetPeiServicesTablePointer (),
102 *((EFI_PEI_FILE_HANDLE
*)&PeiCoreFileHandle
),
103 PEIM_STATE_REGISITER_FOR_SHADOW
,
107 ASSERT_EFI_ERROR (Status
);
110 // Compute the PeiCore's function address after shaowed PeiCore.
111 // _ModuleEntryPoint is PeiCore main function entry
113 return (PEICORE_FUNCTION_POINTER
)((UINTN
) EntryPoint
+ (UINTN
) PeiCore
- (UINTN
) _ModuleEntryPoint
);
117 This routine is invoked by main entry of PeiMain module during transition
118 from SEC to PEI. After switching stack in the PEI core, it will restart
119 with the old core data.
121 @param SecCoreData Points to a data structure containing information about the PEI core's operating
122 environment, such as the size and location of temporary RAM, the stack location and
124 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
125 An empty PPI list consists of a single descriptor with the end-tag
126 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
127 phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
128 that both the PEI Foundation and any modules can leverage the associated service
129 calls and/or code in these early PPIs
130 @param Data Pointer to old core data that is used to initialize the
132 If NULL, it is first PeiCore entering.
138 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
139 IN CONST EFI_PEI_PPI_DESCRIPTOR
*PpiList
,
143 PEI_CORE_INSTANCE PrivateData
;
145 PEI_CORE_TEMP_POINTERS TempPtr
;
147 PEI_CORE_INSTANCE
*OldCoreData
;
148 EFI_PEI_CPU_IO_PPI
*CpuIo
;
149 EFI_PEI_PCI_CFG2_PPI
*PciCfg
;
150 EFI_HOB_HANDOFF_INFO_TABLE
*HandoffInformationTable
;
153 OldCoreData
= (PEI_CORE_INSTANCE
*)Data
;
156 // Record the system tick for first entering PeiCore.
157 // This tick is duration of executing platform seccore module.
159 if (PerformanceMeasurementEnabled()) {
160 if (OldCoreData
== NULL
) {
161 Tick
= GetPerformanceCounter ();
165 if (OldCoreData
!= NULL
) {
166 if (OldCoreData
->ShadowedPeiCore
== NULL
) {
169 // Fixup the PeiCore's private data
171 OldCoreData
->Ps
= &OldCoreData
->ServiceTableShadow
;
172 OldCoreData
->CpuIo
= &OldCoreData
->ServiceTableShadow
.CpuIo
;
173 if (OldCoreData
->HeapOffsetPositive
) {
174 OldCoreData
->HobList
.Raw
= (VOID
*)(OldCoreData
->HobList
.Raw
+ OldCoreData
->HeapOffset
);
176 OldCoreData
->HobList
.Raw
= (VOID
*)(OldCoreData
->HobList
.Raw
- OldCoreData
->HeapOffset
);
180 // Fixup for PeiService's address
182 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES
**)&OldCoreData
->Ps
);
185 // Update HandOffHob for new installed permenent memory
187 HandoffInformationTable
= OldCoreData
->HobList
.HandoffInformationTable
;
188 if (OldCoreData
->HeapOffsetPositive
) {
189 HandoffInformationTable
->EfiEndOfHobList
= HandoffInformationTable
->EfiEndOfHobList
+ OldCoreData
->HeapOffset
;
191 HandoffInformationTable
->EfiEndOfHobList
= HandoffInformationTable
->EfiEndOfHobList
- OldCoreData
->HeapOffset
;
193 HandoffInformationTable
->EfiMemoryTop
= OldCoreData
->PhysicalMemoryBegin
+ OldCoreData
->PhysicalMemoryLength
;
194 HandoffInformationTable
->EfiMemoryBottom
= OldCoreData
->PhysicalMemoryBegin
;
195 HandoffInformationTable
->EfiFreeMemoryTop
= OldCoreData
->FreePhysicalMemoryTop
;
196 HandoffInformationTable
->EfiFreeMemoryBottom
= HandoffInformationTable
->EfiEndOfHobList
+ sizeof (EFI_HOB_GENERIC_HEADER
);
199 // We need convert the PPI desciptor's pointer
201 ConvertPpiPointers (OldCoreData
, (UINTN
)SecCoreData
->TemporaryRamBase
, (UINTN
)SecCoreData
->TemporaryRamBase
+ SecCoreData
->TemporaryRamSize
, OldCoreData
->HeapOffset
, OldCoreData
->HeapOffsetPositive
);
204 // After the whole temporary memory is migrated, then we can allocate page in
207 OldCoreData
->PeiMemoryInstalled
= TRUE
;
210 // Indicate that PeiCore reenter
212 OldCoreData
->PeimDispatcherReenter
= TRUE
;
214 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0 && (OldCoreData
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
216 // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
217 // Every bit in the array indicate the status of the corresponding memory page available or not
219 OldCoreData
->PeiCodeMemoryRangeUsageBitMap
= AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber
)>>6) + 1)*sizeof(UINT64
));
223 // Process the Notify list and dispatch any notifies for
224 // newly installed PPIs.
226 ProcessNotifyList (OldCoreData
);
229 // Shadow PEI Core. When permanent memory is avaiable, shadow
230 // PEI Core and PEIMs to get high performance.
232 OldCoreData
->ShadowedPeiCore
= ShadowPeiCore (OldCoreData
);
235 // PeiCore has been shadowed to memory for first entering, so
236 // just jump to PeiCore in memory here.
238 OldCoreData
->ShadowedPeiCore (SecCoreData
, PpiList
, OldCoreData
);
241 CopyMem (&PrivateData
, OldCoreData
, sizeof (PrivateData
));
243 CpuIo
= (VOID
*)PrivateData
.ServiceTableShadow
.CpuIo
;
244 PciCfg
= (VOID
*)PrivateData
.ServiceTableShadow
.PciCfg
;
246 CopyMem (&PrivateData
.ServiceTableShadow
, &gPs
, sizeof (gPs
));
248 PrivateData
.ServiceTableShadow
.CpuIo
= CpuIo
;
249 PrivateData
.ServiceTableShadow
.PciCfg
= PciCfg
;
252 // If OldCoreData is NULL, means current is first Peicore's entering.
255 ZeroMem (&PrivateData
, sizeof (PEI_CORE_INSTANCE
));
256 PrivateData
.Signature
= PEI_CORE_HANDLE_SIGNATURE
;
257 CopyMem (&PrivateData
.ServiceTableShadow
, &gPs
, sizeof (gPs
));
260 PrivateData
.Ps
= &PrivateData
.ServiceTableShadow
;
263 // Initialize libraries that the PeiCore is linked against
265 ProcessLibraryConstructorList (NULL
, (CONST EFI_PEI_SERVICES
**)&PrivateData
.Ps
);
267 InitializeMemoryServices (&PrivateData
, SecCoreData
, OldCoreData
);
269 InitializePpiServices (&PrivateData
, OldCoreData
);
272 // Save PeiServicePointer so that it can be retrieved anywhere.
274 SetPeiServicesTablePointer((CONST EFI_PEI_SERVICES
**) &PrivateData
.Ps
);
276 if (OldCoreData
!= NULL
) {
278 PERF_END (NULL
,"PreMem", NULL
, 0);
279 PERF_START (NULL
,"PostMem", NULL
, 0);
282 // Alert any listeners that there is permanent memory available
285 PERF_START (NULL
,"DisMem", NULL
, 0);
286 Status
= PeiServicesInstallPpi (&mMemoryDiscoveredPpi
);
287 PERF_END (NULL
,"DisMem", NULL
, 0);
292 // Report Status Code EFI_SW_PC_INIT
296 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT
)
299 PERF_START (NULL
, "SEC", NULL
, 1);
300 PERF_END (NULL
, "SEC", NULL
, Tick
);
302 PERF_START (NULL
,"PEI", NULL
, Tick
);
304 // If first pass, start performance measurement.
306 PERF_START (NULL
,"PreMem", NULL
, Tick
);
309 // If SEC provided any PPI services to PEI, install them.
311 if (PpiList
!= NULL
) {
312 Status
= PeiServicesInstallPpi (PpiList
);
313 ASSERT_EFI_ERROR (Status
);
317 InitializeSecurityServices (&PrivateData
.Ps
, OldCoreData
);
319 InitializeDispatcherData (&PrivateData
, OldCoreData
, SecCoreData
);
322 // Install Pei Load File PPI.
324 InitializeImageServices (&PrivateData
, OldCoreData
);
327 // Call PEIM dispatcher
329 PeiDispatcher (SecCoreData
, &PrivateData
);
332 // Check if InstallPeiMemory service was called.
334 ASSERT(PrivateData
.PeiMemoryInstalled
== TRUE
);
337 // Till now, PEI phase will be finished, get performace count
338 // for computing duration of PEI phase
340 PERF_END (NULL
, "PostMem", NULL
, 0);
342 Status
= PeiServicesLocatePpi (
346 (VOID
**)&TempPtr
.DxeIpl
348 ASSERT_EFI_ERROR (Status
);
351 // Enter DxeIpl to load Dxe core.
353 DEBUG ((EFI_D_INFO
, "DXE IPL Entry\n"));
354 Status
= TempPtr
.DxeIpl
->Entry (
360 // Should never reach here.
362 ASSERT_EFI_ERROR (Status
);