]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
MdeModulePkg: Apply uncrustify changes
[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
110 ASSERT (Index < PrivateData->FvCount);
111 }
112
113 //
114 // Find PEI Core from the given FV index
115 //
116 Status = PrivateData->Fv[PeiCoreFvIndex].FvPpi->FindFileByType (
117 PrivateData->Fv[PeiCoreFvIndex].FvPpi,
118 EFI_FV_FILETYPE_PEI_CORE,
119 PrivateData->Fv[PeiCoreFvIndex].FvHandle,
120 &PeiCoreFileHandle
121 );
122 ASSERT_EFI_ERROR (Status);
123
124 //
125 // Shadow PEI Core into memory so it will run faster
126 //
127 Status = PeiLoadImage (
128 GetPeiServicesTablePointer (),
129 *((EFI_PEI_FILE_HANDLE *)&PeiCoreFileHandle),
130 PEIM_STATE_REGISTER_FOR_SHADOW,
131 &EntryPoint,
132 &AuthenticationState
133 );
134 ASSERT_EFI_ERROR (Status);
135
136 //
137 // Compute the PeiCore's function address after shadowed PeiCore.
138 // _ModuleEntryPoint is PeiCore main function entry
139 //
140 return (PEICORE_FUNCTION_POINTER)((UINTN)EntryPoint + (UINTN)PeiCore - (UINTN)_ModuleEntryPoint);
141 }
142
143 /**
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.
147
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
150 the BFV location.
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
158 core's data areas.
159 If NULL, it is first PeiCore entering.
160
161 **/
162 VOID
163 EFIAPI
164 PeiCore (
165 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreDataPtr,
166 IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
167 IN VOID *Data
168 )
169 {
170 PEI_CORE_INSTANCE PrivateData;
171 EFI_SEC_PEI_HAND_OFF *SecCoreData;
172 EFI_SEC_PEI_HAND_OFF NewSecCoreData;
173 EFI_STATUS Status;
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;
180 UINTN Index;
181
182 //
183 // Retrieve context passed into PEI Core
184 //
185 OldCoreData = (PEI_CORE_INSTANCE *)Data;
186 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)SecCoreDataPtr;
187
188 //
189 // Perform PEI Core phase specific actions.
190 //
191 if (OldCoreData == NULL) {
192 //
193 // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available.
194 //
195 ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
196 PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
197 CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
198 } else {
199 //
200 // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet.
201 //
202 if (OldCoreData->ShadowedPeiCore == NULL) {
203 //
204 // Fixup the PeiCore's private data
205 //
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);
212 }
213
214 if (OldCoreData->CurrentFvFileHandles != NULL) {
215 OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset);
216 }
217
218 if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
219 OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs + OldCoreData->HeapOffset);
220 }
221
222 if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
223 OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
224 }
225
226 if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
227 OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
228 }
229
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;
234 }
235
236 if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
237 OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset);
238 }
239 }
240
241 OldCoreData->TempFileGuid = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid + OldCoreData->HeapOffset);
242 OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles + OldCoreData->HeapOffset);
243 } else {
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);
247 }
248
249 if (OldCoreData->CurrentFvFileHandles != NULL) {
250 OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset);
251 }
252
253 if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
254 OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs - OldCoreData->HeapOffset);
255 }
256
257 if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
258 OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs - OldCoreData->HeapOffset);
259 }
260
261 if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
262 OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs - OldCoreData->HeapOffset);
263 }
264
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;
269 }
270
271 if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
272 OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset);
273 }
274 }
275
276 OldCoreData->TempFileGuid = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid - OldCoreData->HeapOffset);
277 OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset);
278 }
279
280 //
281 // Fixup for PeiService's address
282 //
283 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
284
285 //
286 // Initialize libraries that the PEI Core is linked against
287 //
288 ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
289
290 //
291 // Update HandOffHob for new installed permanent memory
292 //
293 HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
294 if (OldCoreData->HeapOffsetPositive) {
295 HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
296 } else {
297 HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
298 }
299
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);
304
305 //
306 // We need convert MemoryBaseAddress in memory allocation HOBs
307 //
308 ConvertMemoryAllocationHobs (OldCoreData);
309
310 //
311 // We need convert the PPI descriptor's pointer
312 //
313 ConvertPpiPointers (SecCoreData, OldCoreData);
314
315 //
316 // After the whole temporary memory is migrated, then we can allocate page in
317 // permanent memory.
318 //
319 OldCoreData->PeiMemoryInstalled = TRUE;
320
321 //
322 // Indicate that PeiCore reenter
323 //
324 OldCoreData->PeimDispatcherReenter = TRUE;
325
326 if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
327 //
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
330 //
331 OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof (UINT64));
332 }
333
334 //
335 // Shadow PEI Core. When permanent memory is available, shadow
336 // PEI Core and PEIMs to get high performance.
337 //
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)))
342 {
343 OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
344 }
345
346 //
347 // PEI Core has now been shadowed to memory. Restart PEI Core in memory.
348 //
349 OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);
350
351 //
352 // Should never reach here.
353 //
354 ASSERT (FALSE);
355 CpuDeadLoop ();
356
357 UNREACHABLE ();
358 }
359
360 //
361 // Memory is available to the PEI Core and the PEI Core has been shadowed to memory.
362 //
363 CopyMem (&NewSecCoreData, SecCoreDataPtr, sizeof (NewSecCoreData));
364 SecCoreData = &NewSecCoreData;
365
366 CopyMem (&PrivateData, OldCoreData, sizeof (PrivateData));
367
368 CpuIo = (VOID *)PrivateData.ServiceTableShadow.CpuIo;
369 PciCfg = (VOID *)PrivateData.ServiceTableShadow.PciCfg;
370
371 CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
372
373 PrivateData.ServiceTableShadow.CpuIo = CpuIo;
374 PrivateData.ServiceTableShadow.PciCfg = PciCfg;
375 }
376
377 //
378 // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory
379 //
380 PrivateData.Ps = &PrivateData.ServiceTableShadow;
381
382 //
383 // Save PeiServicePointer so that it can be retrieved anywhere.
384 //
385 SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
386
387 //
388 // Initialize libraries that the PEI Core is linked against
389 //
390 ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
391
392 //
393 // Initialize PEI Core Services
394 //
395 InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData);
396
397 //
398 // Update performance measurements
399 //
400 if (OldCoreData == NULL) {
401 PERF_EVENT ("SEC"); // Means the end of SEC phase.
402
403 //
404 // If first pass, start performance measurement.
405 //
406 PERF_CROSSMODULE_BEGIN ("PEI");
407 PERF_INMODULE_BEGIN ("PreMem");
408 } else {
409 PERF_INMODULE_END ("PreMem");
410 PERF_INMODULE_BEGIN ("PostMem");
411 }
412
413 //
414 // Complete PEI Core Service initialization
415 //
416 InitializeSecurityServices (&PrivateData.Ps, OldCoreData);
417 InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData);
418 InitializeImageServices (&PrivateData, OldCoreData);
419
420 //
421 // Perform PEI Core Phase specific actions
422 //
423 if (OldCoreData == NULL) {
424 //
425 // Report Status Code EFI_SW_PC_INIT
426 //
427 REPORT_STATUS_CODE (
428 EFI_PROGRESS_CODE,
429 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT)
430 );
431
432 //
433 // If SEC provided the PpiList, process it.
434 //
435 if (PpiList != NULL) {
436 ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps, PpiList);
437 }
438 } else {
439 if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
440 //
441 // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all
442 // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot
443 //
444 DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM evacuation:\n"));
445 DumpPpiList (&PrivateData);
446
447 //
448 // Migrate installed content from Temporary RAM to Permanent RAM
449 //
450 EvacuateTempRam (&PrivateData, SecCoreData);
451
452 DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n"));
453 DumpPpiList (&PrivateData);
454 }
455
456 //
457 // Try to locate Temporary RAM Done Ppi.
458 //
459 Status = PeiServicesLocatePpi (
460 &gEfiTemporaryRamDonePpiGuid,
461 0,
462 NULL,
463 (VOID **)&TemporaryRamDonePpi
464 );
465 if (!EFI_ERROR (Status)) {
466 //
467 // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete.
468 //
469 TemporaryRamDonePpi->TemporaryRamDone ();
470 }
471
472 //
473 // Alert any listeners that there is permanent memory available
474 //
475 PERF_INMODULE_BEGIN ("DisMem");
476 Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
477
478 //
479 // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
480 //
481 ProcessDispatchNotifyList (&PrivateData);
482
483 PERF_INMODULE_END ("DisMem");
484 }
485
486 //
487 // Call PEIM dispatcher
488 //
489 PeiDispatcher (SecCoreData, &PrivateData);
490
491 if (PrivateData.HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) {
492 //
493 // Check if InstallPeiMemory service was called on non-S3 resume boot path.
494 //
495 ASSERT (PrivateData.PeiMemoryInstalled == TRUE);
496 }
497
498 //
499 // Measure PEI Core execution time.
500 //
501 PERF_INMODULE_END ("PostMem");
502
503 //
504 // Lookup DXE IPL PPI
505 //
506 Status = PeiServicesLocatePpi (
507 &gEfiDxeIplPpiGuid,
508 0,
509 NULL,
510 (VOID **)&TempPtr.DxeIpl
511 );
512 ASSERT_EFI_ERROR (Status);
513
514 if (EFI_ERROR (Status)) {
515 //
516 // Report status code to indicate DXE IPL PPI could not be found.
517 //
518 REPORT_STATUS_CODE (
519 EFI_ERROR_CODE | EFI_ERROR_MAJOR,
520 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND)
521 );
522 CpuDeadLoop ();
523 }
524
525 //
526 // Enter DxeIpl to load Dxe core.
527 //
528 DEBUG ((DEBUG_INFO, "DXE IPL Entry\n"));
529 Status = TempPtr.DxeIpl->Entry (
530 TempPtr.DxeIpl,
531 &PrivateData.Ps,
532 PrivateData.HobList
533 );
534 //
535 // Should never reach here.
536 //
537 ASSERT_EFI_ERROR (Status);
538 CpuDeadLoop ();
539
540 UNREACHABLE ();
541 }