]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
bf99e4bd4c2229e24b59e345a345e98a72cef003
[mirror_edk2.git] / MdeModulePkg / Core / Pei / PeiMain / PeiMain.c
1 /** @file
2 Pei Core Main Entry Point
3
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
9
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.
12
13 **/
14
15 #include "PeiMain.h"
16
17 EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = {
18 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
19 &gEfiPeiMemoryDiscoveredPpiGuid,
20 NULL
21 };
22
23 ///
24 /// Pei service instance
25 ///
26 EFI_PEI_SERVICES gPs = {
27 {
28 PEI_SERVICES_SIGNATURE,
29 PEI_SERVICES_REVISION,
30 sizeof (EFI_PEI_SERVICES),
31 0,
32 0
33 },
34 PeiInstallPpi,
35 PeiReInstallPpi,
36 PeiLocatePpi,
37 PeiNotifyPpi,
38
39 PeiGetBootMode,
40 PeiSetBootMode,
41
42 PeiGetHobList,
43 PeiCreateHob,
44
45 PeiFfsFindNextVolume,
46 PeiFfsFindNextFile,
47 PeiFfsFindSectionData,
48
49 PeiInstallPeiMemory,
50 PeiAllocatePages,
51 PeiAllocatePool,
52 (EFI_PEI_COPY_MEM)CopyMem,
53 (EFI_PEI_SET_MEM)SetMem,
54
55 PeiReportStatusCode,
56 PeiResetSystem,
57
58 &gPeiDefaultCpuIoPpi,
59 &gPeiDefaultPciCfg2Ppi,
60
61 PeiFfsFindFileByName,
62 PeiFfsGetFileInfo,
63 PeiFfsGetVolumeInfo,
64 PeiRegisterForShadow
65 };
66
67 /**
68 Shadow PeiCore module from flash to installed memory.
69
70 @param PrivateData PeiCore's private data structure
71
72 @return PeiCore function address after shadowing.
73 **/
74 PEICORE_FUNCTION_POINTER
75 ShadowPeiCore (
76 IN PEI_CORE_INSTANCE *PrivateData
77 )
78 {
79 EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
80 EFI_PHYSICAL_ADDRESS EntryPoint;
81 EFI_STATUS Status;
82 UINT32 AuthenticationState;
83
84 PeiCoreFileHandle = NULL;
85
86 //
87 // Find the PEI Core in the BFV
88 //
89 Status = PrivateData->Fv[0].FvPpi->FindFileByType (
90 PrivateData->Fv[0].FvPpi,
91 EFI_FV_FILETYPE_PEI_CORE,
92 PrivateData->Fv[0].FvHandle,
93 &PeiCoreFileHandle
94 );
95 ASSERT_EFI_ERROR (Status);
96
97 //
98 // Shadow PEI Core into memory so it will run faster
99 //
100 Status = PeiLoadImage (
101 GetPeiServicesTablePointer (),
102 *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),
103 PEIM_STATE_REGISITER_FOR_SHADOW,
104 &EntryPoint,
105 &AuthenticationState
106 );
107 ASSERT_EFI_ERROR (Status);
108
109 //
110 // Compute the PeiCore's function address after shaowed PeiCore.
111 // _ModuleEntryPoint is PeiCore main function entry
112 //
113 return (PEICORE_FUNCTION_POINTER)((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
114 }
115
116 /**
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.
120
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
123 the BFV location.
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
131 core's data areas.
132 If NULL, it is first PeiCore entering.
133
134 **/
135 VOID
136 EFIAPI
137 PeiCore (
138 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
139 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
140 IN VOID *Data
141 )
142 {
143 PEI_CORE_INSTANCE PrivateData;
144 EFI_STATUS Status;
145 PEI_CORE_TEMP_POINTERS TempPtr;
146 UINT64 Tick;
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;
151
152 Tick = 0;
153 OldCoreData = (PEI_CORE_INSTANCE *)Data;
154
155 //
156 // Record the system tick for first entering PeiCore.
157 // This tick is duration of executing platform seccore module.
158 //
159 if (PerformanceMeasurementEnabled()) {
160 if (OldCoreData == NULL) {
161 Tick = GetPerformanceCounter ();
162 }
163 }
164
165 if (OldCoreData != NULL) {
166 if (OldCoreData->ShadowedPeiCore == NULL) {
167 //
168 //
169 // Fixup the PeiCore's private data
170 //
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);
175 } else {
176 OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset);
177 }
178
179 //
180 // Fixup for PeiService's address
181 //
182 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
183
184 //
185 // Update HandOffHob for new installed permenent memory
186 //
187 HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
188 if (OldCoreData->HeapOffsetPositive) {
189 HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
190 } else {
191 HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
192 }
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);
197
198 //
199 // We need convert the PPI desciptor's pointer
200 //
201 ConvertPpiPointers (OldCoreData, (UINTN)SecCoreData->TemporaryRamBase, (UINTN)SecCoreData->TemporaryRamBase + SecCoreData->TemporaryRamSize, OldCoreData->HeapOffset, OldCoreData->HeapOffsetPositive);
202
203 //
204 // After the whole temporary memory is migrated, then we can allocate page in
205 // permenent memory.
206 //
207 OldCoreData->PeiMemoryInstalled = TRUE;
208
209 //
210 // Indicate that PeiCore reenter
211 //
212 OldCoreData->PeimDispatcherReenter = TRUE;
213
214 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
215 //
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
218 //
219 OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));
220 }
221
222 //
223 // Process the Notify list and dispatch any notifies for
224 // newly installed PPIs.
225 //
226 ProcessNotifyList (OldCoreData);
227
228 //
229 // Shadow PEI Core. When permanent memory is avaiable, shadow
230 // PEI Core and PEIMs to get high performance.
231 //
232 OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
233
234 //
235 // PeiCore has been shadowed to memory for first entering, so
236 // just jump to PeiCore in memory here.
237 //
238 OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);
239 }
240
241 CopyMem (&PrivateData, OldCoreData, sizeof (PrivateData));
242
243 CpuIo = (VOID*)PrivateData.ServiceTableShadow.CpuIo;
244 PciCfg = (VOID*)PrivateData.ServiceTableShadow.PciCfg;
245
246 CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
247
248 PrivateData.ServiceTableShadow.CpuIo = CpuIo;
249 PrivateData.ServiceTableShadow.PciCfg = PciCfg;
250 } else {
251 //
252 // If OldCoreData is NULL, means current is first Peicore's entering.
253 //
254
255 ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
256 PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
257 CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
258 }
259
260 PrivateData.Ps = &PrivateData.ServiceTableShadow;
261
262 //
263 // Initialize libraries that the PeiCore is linked against
264 //
265 ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
266
267 InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData);
268
269 InitializePpiServices (&PrivateData, OldCoreData);
270
271 //
272 // Save PeiServicePointer so that it can be retrieved anywhere.
273 //
274 SetPeiServicesTablePointer((CONST EFI_PEI_SERVICES **) &PrivateData.Ps);
275
276 if (OldCoreData != NULL) {
277
278 PERF_END (NULL,"PreMem", NULL, 0);
279 PERF_START (NULL,"PostMem", NULL, 0);
280
281 //
282 // Alert any listeners that there is permanent memory available
283 //
284
285 PERF_START (NULL,"DisMem", NULL, 0);
286 Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
287 PERF_END (NULL,"DisMem", NULL, 0);
288
289 } else {
290
291 //
292 // Report Status Code EFI_SW_PC_INIT
293 //
294 REPORT_STATUS_CODE (
295 EFI_PROGRESS_CODE,
296 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT)
297 );
298
299 PERF_START (NULL, "SEC", NULL, 1);
300 PERF_END (NULL, "SEC", NULL, Tick);
301
302 PERF_START (NULL,"PEI", NULL, Tick);
303 //
304 // If first pass, start performance measurement.
305 //
306 PERF_START (NULL,"PreMem", NULL, Tick);
307
308 //
309 // If SEC provided any PPI services to PEI, install them.
310 //
311 if (PpiList != NULL) {
312 Status = PeiServicesInstallPpi (PpiList);
313 ASSERT_EFI_ERROR (Status);
314 }
315 }
316
317 InitializeSecurityServices (&PrivateData.Ps, OldCoreData);
318
319 InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData);
320
321 //
322 // Install Pei Load File PPI.
323 //
324 InitializeImageServices (&PrivateData, OldCoreData);
325
326 //
327 // Call PEIM dispatcher
328 //
329 PeiDispatcher (SecCoreData, &PrivateData);
330
331 //
332 // Check if InstallPeiMemory service was called.
333 //
334 ASSERT(PrivateData.PeiMemoryInstalled == TRUE);
335
336 //
337 // Till now, PEI phase will be finished, get performace count
338 // for computing duration of PEI phase
339 //
340 PERF_END (NULL, "PostMem", NULL, 0);
341
342 Status = PeiServicesLocatePpi (
343 &gEfiDxeIplPpiGuid,
344 0,
345 NULL,
346 (VOID **)&TempPtr.DxeIpl
347 );
348 ASSERT_EFI_ERROR (Status);
349
350 //
351 // Enter DxeIpl to load Dxe core.
352 //
353 DEBUG ((EFI_D_INFO, "DXE IPL Entry\n"));
354 Status = TempPtr.DxeIpl->Entry (
355 TempPtr.DxeIpl,
356 &PrivateData.Ps,
357 PrivateData.HobList
358 );
359 //
360 // Should never reach here.
361 //
362 ASSERT_EFI_ERROR (Status);
363 CpuDeadLoop();
364 }
365
366