]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / Pei / PeiMain / PeiMain.c
1 /** @file
2 Pei Core Main Entry Point
3
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "PeiMain.h"
10
11 EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = {
12 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
13 &gEfiPeiMemoryDiscoveredPpiGuid,
14 NULL
15 };
16
17 ///
18 /// Pei service instance
19 ///
20 EFI_PEI_SERVICES gPs = {
21 {
22 PEI_SERVICES_SIGNATURE,
23 PEI_SERVICES_REVISION,
24 sizeof (EFI_PEI_SERVICES),
25 0,
26 0
27 },
28 PeiInstallPpi,
29 PeiReInstallPpi,
30 PeiLocatePpi,
31 PeiNotifyPpi,
32
33 PeiGetBootMode,
34 PeiSetBootMode,
35
36 PeiGetHobList,
37 PeiCreateHob,
38
39 PeiFfsFindNextVolume,
40 PeiFfsFindNextFile,
41 PeiFfsFindSectionData,
42
43 PeiInstallPeiMemory,
44 PeiAllocatePages,
45 PeiAllocatePool,
46 (EFI_PEI_COPY_MEM)CopyMem,
47 (EFI_PEI_SET_MEM)SetMem,
48
49 PeiReportStatusCode,
50 PeiResetSystem,
51
52 &gPeiDefaultCpuIoPpi,
53 &gPeiDefaultPciCfg2Ppi,
54
55 PeiFfsFindFileByName,
56 PeiFfsGetFileInfo,
57 PeiFfsGetVolumeInfo,
58 PeiRegisterForShadow,
59 PeiFfsFindSectionData3,
60 PeiFfsGetFileInfo2,
61 PeiResetSystem2,
62 PeiFreePages,
63 };
64
65 /**
66 Shadow PeiCore module from flash to installed memory.
67
68 @param PrivateData PeiCore's private data structure
69
70 @return PeiCore function address after shadowing.
71 **/
72 PEICORE_FUNCTION_POINTER
73 ShadowPeiCore (
74 IN PEI_CORE_INSTANCE *PrivateData
75 )
76 {
77 EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
78 EFI_PHYSICAL_ADDRESS EntryPoint;
79 EFI_STATUS Status;
80 UINT32 AuthenticationState;
81 UINTN Index;
82 EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
83 UINTN PeiCoreFvIndex;
84
85 PeiCoreFileHandle = NULL;
86 //
87 // Default PeiCore is in BFV
88 //
89 PeiCoreFvIndex = 0;
90 //
91 // Find the PEI Core either from EFI_PEI_CORE_FV_LOCATION_PPI indicated FV or BFV
92 //
93 Status = PeiServicesLocatePpi (
94 &gEfiPeiCoreFvLocationPpiGuid,
95 0,
96 NULL,
97 (VOID **) &PeiCoreFvLocationPpi
98 );
99 if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {
100 //
101 // If PeiCoreFvLocation present, the PEI Core should be found from indicated FV
102 //
103 for (Index = 0; Index < PrivateData->FvCount; Index ++) {
104 if (PrivateData->Fv[Index].FvHandle == PeiCoreFvLocationPpi->PeiCoreFvLocation) {
105 PeiCoreFvIndex = Index;
106 break;
107 }
108 }
109 ASSERT (Index < PrivateData->FvCount);
110 }
111 //
112 // Find PEI Core from the given FV index
113 //
114 Status = PrivateData->Fv[PeiCoreFvIndex].FvPpi->FindFileByType (
115 PrivateData->Fv[PeiCoreFvIndex].FvPpi,
116 EFI_FV_FILETYPE_PEI_CORE,
117 PrivateData->Fv[PeiCoreFvIndex].FvHandle,
118 &PeiCoreFileHandle
119 );
120 ASSERT_EFI_ERROR (Status);
121
122 //
123 // Shadow PEI Core into memory so it will run faster
124 //
125 Status = PeiLoadImage (
126 GetPeiServicesTablePointer (),
127 *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),
128 PEIM_STATE_REGISTER_FOR_SHADOW,
129 &EntryPoint,
130 &AuthenticationState
131 );
132 ASSERT_EFI_ERROR (Status);
133
134 //
135 // Compute the PeiCore's function address after shaowed PeiCore.
136 // _ModuleEntryPoint is PeiCore main function entry
137 //
138 return (PEICORE_FUNCTION_POINTER)((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
139 }
140
141 /**
142 This routine is invoked by main entry of PeiMain module during transition
143 from SEC to PEI. After switching stack in the PEI core, it will restart
144 with the old core data.
145
146 @param SecCoreDataPtr Points to a data structure containing information about the PEI core's operating
147 environment, such as the size and location of temporary RAM, the stack location and
148 the BFV location.
149 @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
150 An empty PPI list consists of a single descriptor with the end-tag
151 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
152 phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
153 that both the PEI Foundation and any modules can leverage the associated service
154 calls and/or code in these early PPIs
155 @param Data Pointer to old core data that is used to initialize the
156 core's data areas.
157 If NULL, it is first PeiCore entering.
158
159 **/
160 VOID
161 EFIAPI
162 PeiCore (
163 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreDataPtr,
164 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
165 IN VOID *Data
166 )
167 {
168 PEI_CORE_INSTANCE PrivateData;
169 EFI_SEC_PEI_HAND_OFF *SecCoreData;
170 EFI_SEC_PEI_HAND_OFF NewSecCoreData;
171 EFI_STATUS Status;
172 PEI_CORE_TEMP_POINTERS TempPtr;
173 PEI_CORE_INSTANCE *OldCoreData;
174 EFI_PEI_CPU_IO_PPI *CpuIo;
175 EFI_PEI_PCI_CFG2_PPI *PciCfg;
176 EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable;
177 EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi;
178 UINTN Index;
179
180 //
181 // Retrieve context passed into PEI Core
182 //
183 OldCoreData = (PEI_CORE_INSTANCE *) Data;
184 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) SecCoreDataPtr;
185
186 //
187 // Perform PEI Core phase specific actions.
188 //
189 if (OldCoreData == NULL) {
190 //
191 // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available.
192 //
193 ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
194 PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
195 CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
196 } else {
197 //
198 // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet.
199 //
200 if (OldCoreData->ShadowedPeiCore == NULL) {
201 //
202 // Fixup the PeiCore's private data
203 //
204 OldCoreData->Ps = &OldCoreData->ServiceTableShadow;
205 OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo;
206 if (OldCoreData->HeapOffsetPositive) {
207 OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset);
208 if (OldCoreData->UnknownFvInfo != NULL) {
209 OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset);
210 }
211 if (OldCoreData->CurrentFvFileHandles != NULL) {
212 OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset);
213 }
214 if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
215 OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiList.PpiPtrs + OldCoreData->HeapOffset);
216 }
217 if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
218 OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
219 }
220 if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
221 OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
222 }
223 OldCoreData->Fv = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv + OldCoreData->HeapOffset);
224 for (Index = 0; Index < OldCoreData->FvCount; Index ++) {
225 if (OldCoreData->Fv[Index].PeimState != NULL) {
226 OldCoreData->Fv[Index].PeimState = (UINT8 *) OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset;
227 }
228 if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
229 OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset);
230 }
231 }
232 OldCoreData->TempFileGuid = (EFI_GUID *) ((UINT8 *) OldCoreData->TempFileGuid + OldCoreData->HeapOffset);
233 OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->TempFileHandles + OldCoreData->HeapOffset);
234 } else {
235 OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset);
236 if (OldCoreData->UnknownFvInfo != NULL) {
237 OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo - OldCoreData->HeapOffset);
238 }
239 if (OldCoreData->CurrentFvFileHandles != NULL) {
240 OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset);
241 }
242 if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
243 OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiList.PpiPtrs - OldCoreData->HeapOffset);
244 }
245 if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
246 OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs - OldCoreData->HeapOffset);
247 }
248 if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
249 OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs - OldCoreData->HeapOffset);
250 }
251 OldCoreData->Fv = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv - OldCoreData->HeapOffset);
252 for (Index = 0; Index < OldCoreData->FvCount; Index ++) {
253 if (OldCoreData->Fv[Index].PeimState != NULL) {
254 OldCoreData->Fv[Index].PeimState = (UINT8 *) OldCoreData->Fv[Index].PeimState - OldCoreData->HeapOffset;
255 }
256 if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
257 OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset);
258 }
259 }
260 OldCoreData->TempFileGuid = (EFI_GUID *) ((UINT8 *) OldCoreData->TempFileGuid - OldCoreData->HeapOffset);
261 OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->TempFileHandles - OldCoreData->HeapOffset);
262 }
263
264 //
265 // Fixup for PeiService's address
266 //
267 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
268
269 //
270 // Initialize libraries that the PEI Core is linked against
271 //
272 ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
273
274 //
275 // Update HandOffHob for new installed permanent memory
276 //
277 HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
278 if (OldCoreData->HeapOffsetPositive) {
279 HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
280 } else {
281 HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
282 }
283 HandoffInformationTable->EfiMemoryTop = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength;
284 HandoffInformationTable->EfiMemoryBottom = OldCoreData->PhysicalMemoryBegin;
285 HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop;
286 HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);
287
288 //
289 // We need convert MemoryBaseAddress in memory allocation HOBs
290 //
291 ConvertMemoryAllocationHobs (OldCoreData);
292
293 //
294 // We need convert the PPI descriptor's pointer
295 //
296 ConvertPpiPointers (SecCoreData, OldCoreData);
297
298 //
299 // After the whole temporary memory is migrated, then we can allocate page in
300 // permanent memory.
301 //
302 OldCoreData->PeiMemoryInstalled = TRUE;
303
304 //
305 // Indicate that PeiCore reenter
306 //
307 OldCoreData->PeimDispatcherReenter = TRUE;
308
309 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
310 //
311 // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
312 // Every bit in the array indicate the status of the corresponding memory page available or not
313 //
314 OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));
315 }
316
317 //
318 // Shadow PEI Core. When permanent memory is avaiable, shadow
319 // PEI Core and PEIMs to get high performance.
320 //
321 OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore;
322 if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot))
323 || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {
324 OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
325 }
326
327 //
328 // PEI Core has now been shadowed to memory. Restart PEI Core in memory.
329 //
330 OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);
331
332 //
333 // Should never reach here.
334 //
335 ASSERT (FALSE);
336 CpuDeadLoop();
337
338 UNREACHABLE ();
339 }
340
341 //
342 // Memory is available to the PEI Core and the PEI Core has been shadowed to memory.
343 //
344 CopyMem (&NewSecCoreData, SecCoreDataPtr, sizeof (NewSecCoreData));
345 SecCoreData = &NewSecCoreData;
346
347 CopyMem (&PrivateData, OldCoreData, sizeof (PrivateData));
348
349 CpuIo = (VOID*)PrivateData.ServiceTableShadow.CpuIo;
350 PciCfg = (VOID*)PrivateData.ServiceTableShadow.PciCfg;
351
352 CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
353
354 PrivateData.ServiceTableShadow.CpuIo = CpuIo;
355 PrivateData.ServiceTableShadow.PciCfg = PciCfg;
356 }
357
358 //
359 // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory
360 //
361 PrivateData.Ps = &PrivateData.ServiceTableShadow;
362
363 //
364 // Save PeiServicePointer so that it can be retrieved anywhere.
365 //
366 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
367
368 //
369 // Initialize libraries that the PEI Core is linked against
370 //
371 ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
372
373 //
374 // Initialize PEI Core Services
375 //
376 InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData);
377
378 //
379 // Update performance measurements
380 //
381 if (OldCoreData == NULL) {
382 PERF_EVENT ("SEC"); // Means the end of SEC phase.
383
384 //
385 // If first pass, start performance measurement.
386 //
387 PERF_CROSSMODULE_BEGIN ("PEI");
388 PERF_INMODULE_BEGIN ("PreMem");
389
390 } else {
391 PERF_INMODULE_END ("PreMem");
392 PERF_INMODULE_BEGIN ("PostMem");
393 }
394
395 //
396 // Complete PEI Core Service initialization
397 //
398 InitializeSecurityServices (&PrivateData.Ps, OldCoreData);
399 InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData);
400 InitializeImageServices (&PrivateData, OldCoreData);
401
402 //
403 // Perform PEI Core Phase specific actions
404 //
405 if (OldCoreData == NULL) {
406 //
407 // Report Status Code EFI_SW_PC_INIT
408 //
409 REPORT_STATUS_CODE (
410 EFI_PROGRESS_CODE,
411 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT)
412 );
413
414 //
415 // If SEC provided the PpiList, process it.
416 //
417 if (PpiList != NULL) {
418 ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **) &PrivateData.Ps, PpiList);
419 }
420 } else {
421 //
422 // Try to locate Temporary RAM Done Ppi.
423 //
424 Status = PeiServicesLocatePpi (
425 &gEfiTemporaryRamDonePpiGuid,
426 0,
427 NULL,
428 (VOID**)&TemporaryRamDonePpi
429 );
430 if (!EFI_ERROR (Status)) {
431 //
432 // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete.
433 //
434 TemporaryRamDonePpi->TemporaryRamDone ();
435 }
436
437 //
438 // Alert any listeners that there is permanent memory available
439 //
440 PERF_INMODULE_BEGIN ("DisMem");
441 Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
442
443 //
444 // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
445 //
446 ProcessDispatchNotifyList (&PrivateData);
447
448 PERF_INMODULE_END ("DisMem");
449 }
450
451 //
452 // Call PEIM dispatcher
453 //
454 PeiDispatcher (SecCoreData, &PrivateData);
455
456 if (PrivateData.HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) {
457 //
458 // Check if InstallPeiMemory service was called on non-S3 resume boot path.
459 //
460 ASSERT(PrivateData.PeiMemoryInstalled == TRUE);
461 }
462
463 //
464 // Measure PEI Core execution time.
465 //
466 PERF_INMODULE_END ("PostMem");
467
468 //
469 // Lookup DXE IPL PPI
470 //
471 Status = PeiServicesLocatePpi (
472 &gEfiDxeIplPpiGuid,
473 0,
474 NULL,
475 (VOID **)&TempPtr.DxeIpl
476 );
477 ASSERT_EFI_ERROR (Status);
478
479 if (EFI_ERROR (Status)) {
480 //
481 // Report status code to indicate DXE IPL PPI could not be found.
482 //
483 REPORT_STATUS_CODE (
484 EFI_ERROR_CODE | EFI_ERROR_MAJOR,
485 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND)
486 );
487 CpuDeadLoop ();
488 }
489
490 //
491 // Enter DxeIpl to load Dxe core.
492 //
493 DEBUG ((EFI_D_INFO, "DXE IPL Entry\n"));
494 Status = TempPtr.DxeIpl->Entry (
495 TempPtr.DxeIpl,
496 &PrivateData.Ps,
497 PrivateData.HobList
498 );
499 //
500 // Should never reach here.
501 //
502 ASSERT_EFI_ERROR (Status);
503 CpuDeadLoop();
504
505 UNREACHABLE ();
506 }