]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Cleanup INF file for PEI Core
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 EFI PEI Core dispatch services\r
3 \r
90e128e2 4Copyright (c) 2006 - 2009, Intel Corporation\r
192f6d4c 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
615c6dd0 13**/\r
192f6d4c 14\r
0d516397 15#include "PeiMain.h"\r
192f6d4c 16\r
b1f6a7c6 17///\r
3d4d0c34 18/// temporary memory is filled with this initial value during SEC phase\r
b1f6a7c6 19///\r
a7715e73 20#define INIT_CAR_VALUE 0x5AA55AA5\r
21\r
797a9d67 22typedef struct {\r
23 EFI_STATUS_CODE_DATA DataHeader;\r
24 EFI_HANDLE Handle;\r
25} PEIM_FILE_HANDLE_EXTENDED_DATA;\r
26\r
b1f6a7c6 27/**\r
b0d803fe 28\r
29 Discover all Peims and optional Apriori file in one FV. There is at most one\r
30 Apriori file in one FV.\r
31\r
b0d803fe 32\r
3b428ade 33 @param Private Pointer to the private data passed in from caller\r
34 @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.\r
b0d803fe 35\r
b1f6a7c6 36**/\r
37VOID\r
38DiscoverPeimsAndOrderWithApriori (\r
39 IN PEI_CORE_INSTANCE *Private,\r
3b428ade 40 IN PEI_CORE_FV_HANDLE *CoreFileHandle\r
b1f6a7c6 41 )\r
b0d803fe 42{\r
43 EFI_STATUS Status;\r
44 EFI_PEI_FV_HANDLE FileHandle;\r
177aabe6 45 EFI_PEI_FILE_HANDLE AprioriFileHandle;\r
b0d803fe 46 EFI_GUID *Apriori;\r
47 UINTN Index;\r
48 UINTN Index2;\r
49 UINTN PeimIndex;\r
50 UINTN PeimCount;\r
51 EFI_GUID *Guid;\r
177aabe6 52 EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
53 EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
3b428ade 54 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
55 EFI_FV_FILE_INFO FileInfo;\r
56 \r
57 FvPpi = CoreFileHandle->FvPpi;\r
58 \r
b0d803fe 59 //\r
60 // Walk the FV and find all the PEIMs and the Apriori file.\r
61 //\r
62 AprioriFileHandle = NULL;\r
63 Private->CurrentFvFileHandles[0] = NULL;\r
64 Guid = NULL;\r
65 FileHandle = NULL;\r
66\r
67 //\r
68 // If the current Fv has been scanned, directly get its cachable record.\r
69 //\r
70 if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {\r
71 CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
72 return;\r
73 }\r
74\r
75 //\r
76 // Go ahead to scan this Fv, and cache FileHandles within it.\r
77 //\r
177aabe6 78 for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
3b428ade 79 Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);\r
b0d803fe 80 if (Status != EFI_SUCCESS) {\r
81 break;\r
82 }\r
58dcdada 83\r
b0d803fe 84 Private->CurrentFvFileHandles[PeimCount] = FileHandle;\r
85 }\r
97b2c9b5
LG
86 \r
87 //\r
88 // Check whether the count of Peims exceeds the max support PEIMs in a FV image\r
89 // If more Peims are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.\r
90 //\r
91 ASSERT (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv));\r
b0d803fe 92\r
3b428ade 93 //\r
94 // Get Apriori File handle\r
95 //\r
58dcdada 96 Private->AprioriCount = 0;\r
3b428ade 97 Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);\r
98 if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {\r
b0d803fe 99 //\r
100 // Read the Apriori file\r
101 //\r
3b428ade 102 Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
b0d803fe 103 if (!EFI_ERROR (Status)) {\r
104 //\r
105 // Calculate the number of PEIMs in the A Priori list\r
106 //\r
3b428ade 107 Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);\r
108 ASSERT_EFI_ERROR (Status);\r
109 Private->AprioriCount = FileInfo.BufferSize & 0x00FFFFFF;\r
595d4b4c 110 Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);\r
b0d803fe 111 Private->AprioriCount /= sizeof (EFI_GUID);\r
58dcdada 112\r
82b8c8df 113 ZeroMem (FileGuid, sizeof (FileGuid));\r
b0d803fe 114 for (Index = 0; Index < PeimCount; Index++) {\r
115 //\r
116 // Make an array of file name guids that matches the FileHandle array so we can convert\r
117 // quickly from file name to file handle\r
118 //\r
3b428ade 119 Status = FvPpi->GetFileInfo (FvPpi, Private->CurrentFvFileHandles[Index], &FileInfo);\r
120 CopyMem (&FileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));\r
b0d803fe 121 }\r
122\r
123 //\r
124 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.\r
58dcdada 125 // Add avalible PEIMs in Apriori file into TempFileHandles array at first.\r
b0d803fe 126 //\r
127 Index2 = 0;\r
128 for (Index = 0; Index2 < Private->AprioriCount; Index++) {\r
129 while (Index2 < Private->AprioriCount) {\r
130 Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);\r
131 if (Guid != NULL) {\r
132 break;\r
133 }\r
134 }\r
135 if (Guid == NULL) {\r
58dcdada 136 break;\r
b0d803fe 137 }\r
138 PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);\r
139 TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];\r
140\r
141 //\r
142 // Since we have copied the file handle we can remove it from this list.\r
143 //\r
144 Private->CurrentFvFileHandles[PeimIndex] = NULL;\r
145 }\r
146\r
147 //\r
148 // Update valid Aprioricount\r
149 //\r
150 Private->AprioriCount = Index;\r
58dcdada 151\r
b0d803fe 152 //\r
153 // Add in any PEIMs not in the Apriori file\r
154 //\r
155 for (;Index < PeimCount; Index++) {\r
156 for (Index2 = 0; Index2 < PeimCount; Index2++) {\r
157 if (Private->CurrentFvFileHandles[Index2] != NULL) {\r
158 TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];\r
159 Private->CurrentFvFileHandles[Index2] = NULL;\r
160 break;\r
161 }\r
162 }\r
163 }\r
164 //\r
165 //Index the end of array contains re-range Pei moudle.\r
166 //\r
167 TempFileHandles[Index] = NULL;\r
58dcdada 168\r
b0d803fe 169 //\r
170 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.\r
58dcdada 171 // We need to update it to start with files in the A Priori list and\r
172 // then the remaining files in PEIM order.\r
b0d803fe 173 //\r
174 CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));\r
175 }\r
176 }\r
177 //\r
178 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.\r
179 // Instead, we can retrieve the file handles within this Fv from cachable data.\r
180 //\r
181 Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;\r
182 CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
58dcdada 183\r
184}\r
185\r
b1f6a7c6 186/**\r
187 Shadow PeiCore module from flash to installed memory.\r
188 \r
d73d93c3 189 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
b1f6a7c6 190 @param PrivateInMem PeiCore's private data structure\r
191\r
82b8c8df 192 @return PeiCore function address after shadowing.\r
b1f6a7c6 193**/\r
58dcdada 194VOID*\r
195ShadowPeiCore(\r
6c7a807a 196 IN CONST EFI_PEI_SERVICES **PeiServices,\r
197 IN PEI_CORE_INSTANCE *PrivateInMem\r
58dcdada 198 )\r
199{\r
200 EFI_PEI_FILE_HANDLE PeiCoreFileHandle;\r
201 EFI_PHYSICAL_ADDRESS EntryPoint;\r
202 EFI_STATUS Status;\r
203 UINT32 AuthenticationState;\r
204\r
205 PeiCoreFileHandle = NULL;\r
206\r
207 //\r
208 // Find the PEI Core in the BFV\r
209 //\r
3b428ade 210 Status = PrivateInMem->Fv[0].FvPpi->FindFileByType (\r
211 PrivateInMem->Fv[0].FvPpi,\r
212 EFI_FV_FILETYPE_PEI_CORE,\r
213 PrivateInMem->Fv[0].FvHandle,\r
214 &PeiCoreFileHandle\r
215 );\r
58dcdada 216 ASSERT_EFI_ERROR (Status);\r
217\r
218 //\r
219 // Shadow PEI Core into memory so it will run faster\r
220 //\r
221 Status = PeiLoadImage (\r
222 PeiServices,\r
223 *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),\r
224 &EntryPoint,\r
225 &AuthenticationState\r
226 );\r
227 ASSERT_EFI_ERROR (Status);\r
228\r
82b8c8df 229 //\r
230 // Compute the PeiCore's function address after shaowed PeiCore.\r
231 // _ModuleEntryPoint is PeiCore main function entry\r
232 //\r
58dcdada 233 return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);\r
b0d803fe 234}\r
235\r
b1f6a7c6 236/**\r
192f6d4c 237 Conduct PEIM dispatch.\r
238\r
b1f6a7c6 239 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 240 environment, such as the size and location of temporary RAM, the stack location and\r
241 the BFV location.\r
b1f6a7c6 242 @param Private Pointer to the private data passed in from caller\r
192f6d4c 243\r
b1f6a7c6 244**/\r
245VOID\r
246PeiDispatcher (\r
247 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
248 IN PEI_CORE_INSTANCE *Private\r
249 )\r
192f6d4c 250{\r
b0d803fe 251 EFI_STATUS Status;\r
252 UINT32 Index1;\r
253 UINT32 Index2;\r
6c7a807a 254 CONST EFI_PEI_SERVICES **PeiServices;\r
b0d803fe 255 EFI_PEI_FILE_HANDLE PeimFileHandle;\r
256 UINTN FvCount;\r
257 UINTN PeimCount;\r
258 UINT32 AuthenticationState;\r
259 EFI_PHYSICAL_ADDRESS EntryPoint;\r
797a9d67 260 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;\r
b0d803fe 261 UINTN SaveCurrentPeimCount;\r
1053e0c5 262 UINTN SaveCurrentFvCount;\r
b0d803fe 263 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;\r
797a9d67 264 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;\r
58dcdada 265 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase;\r
266 TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;\r
267 EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable;\r
268 EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable;\r
66c69dea 269 INTN StackOffset;\r
270 INTN HeapOffset;\r
58dcdada 271 PEI_CORE_INSTANCE *PrivateInMem;\r
272 UINT64 NewPeiStackSize;\r
273 UINT64 OldPeiStackSize;\r
274 UINT64 StackGap;\r
288f9b38 275 EFI_FV_FILE_INFO FvFileInfo;\r
58dcdada 276 UINTN OldCheckingTop;\r
277 UINTN OldCheckingBottom;\r
3b428ade 278 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
b0d803fe 279\r
6c7a807a 280 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;\r
b0d803fe 281 PeimEntryPoint = NULL;\r
282 PeimFileHandle = NULL;\r
288f9b38 283 EntryPoint = 0;\r
b0d803fe 284\r
285 if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
286 //\r
287 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
288 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.\r
289 //\r
290 SaveCurrentPeimCount = Private->CurrentPeimCount;\r
1053e0c5 291 SaveCurrentFvCount = Private->CurrentPeimFvCount;\r
b0d803fe 292 SaveCurrentFileHandle = Private->CurrentFileHandle;\r
293\r
1053e0c5 294 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
177aabe6 295 for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
b0d803fe 296 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
58dcdada 297 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
b0d803fe 298 Status = PeiLoadImage (\r
6c7a807a 299 (CONST EFI_PEI_SERVICES **) &Private->PS,\r
58dcdada 300 PeimFileHandle,\r
301 &EntryPoint,\r
b0d803fe 302 &AuthenticationState\r
303 );\r
304 if (Status == EFI_SUCCESS) {\r
305 //\r
306 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
307 //\r
308 Private->Fv[Index1].PeimState[Index2]++;\r
1053e0c5 309 Private->CurrentFileHandle = PeimFileHandle;\r
58dcdada 310 Private->CurrentPeimFvCount = Index1;\r
311 Private->CurrentPeimCount = Index2;\r
b0d803fe 312 //\r
313 // Call the PEIM entry point\r
314 //\r
797a9d67 315 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
58dcdada 316\r
b0d803fe 317 PERF_START (0, "PEIM", NULL, 0);\r
797a9d67 318 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);\r
b0d803fe 319 PERF_END (0, "PEIM", NULL, 0);\r
58dcdada 320 }\r
321\r
b0d803fe 322 //\r
323 // Process the Notify list and dispatch any notifies for\r
324 // newly installed PPIs.\r
325 //\r
326 ProcessNotifyList (Private);\r
327 }\r
328 }\r
329 }\r
58dcdada 330 Private->CurrentFileHandle = SaveCurrentFileHandle;\r
331 Private->CurrentPeimFvCount = SaveCurrentFvCount;\r
332 Private->CurrentPeimCount = SaveCurrentPeimCount;\r
b0d803fe 333 }\r
192f6d4c 334\r
335 //\r
336 // This is the main dispatch loop. It will search known FVs for PEIMs and\r
337 // attempt to dispatch them. If any PEIM gets dispatched through a single\r
338 // pass of the dispatcher, it will start over from the Bfv again to see\r
339 // if any new PEIMs dependencies got satisfied. With a well ordered\r
340 // FV where PEIMs are found in the order their dependencies are also\r
341 // satisfied, this dipatcher should run only once.\r
342 //\r
b0d803fe 343 do {\r
82b8c8df 344 //\r
345 // In case that reenter PeiCore happens, the last pass record is still available. \r
346 //\r
347 if (!Private->PeimDispatcherReenter) {\r
348 Private->PeimNeedingDispatch = FALSE;\r
349 Private->PeimDispatchOnThisPass = FALSE;\r
350 } else {\r
351 Private->PeimDispatcherReenter = FALSE;\r
352 }\r
353 \r
b0d803fe 354 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
3b428ade 355 CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);\r
356 ASSERT (CoreFvHandle != NULL);\r
357 \r
2a00326e 358 //\r
3b428ade 359 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.\r
2a00326e 360 //\r
3b428ade 361 if (CoreFvHandle->FvPpi == NULL) {\r
362 continue;\r
363 }\r
364 \r
365 Private->CurrentPeimFvCount = FvCount;\r
192f6d4c 366\r
b0d803fe 367 if (Private->CurrentPeimCount == 0) {\r
368 //\r
369 // When going through each FV, at first, search Apriori file to\r
58dcdada 370 // reorder all PEIMs to ensure the PEIMs in Apriori file to get\r
b0d803fe 371 // dispatch at first.\r
372 //\r
3b428ade 373 DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);\r
b0d803fe 374 }\r
192f6d4c 375\r
376 //\r
b0d803fe 377 // Start to dispatch all modules within the current Fv.\r
192f6d4c 378 //\r
58dcdada 379 for (PeimCount = Private->CurrentPeimCount;\r
380 (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);\r
b0d803fe 381 PeimCount++) {\r
382 Private->CurrentPeimCount = PeimCount;\r
383 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
384\r
385 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {\r
386 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
82b8c8df 387 Private->PeimNeedingDispatch = TRUE;\r
b0d803fe 388 } else {\r
3b428ade 389 Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);\r
288f9b38
LG
390 ASSERT_EFI_ERROR (Status);\r
391 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
392 //\r
393 // For Fv type file, Produce new FV PPI and FV hob\r
394 //\r
3b428ade 395 Status = ProcessFvFile (&Private->Fv[FvCount], PeimFileHandle);\r
396 AuthenticationState = 0;\r
288f9b38
LG
397 } else {\r
398 //\r
399 // For PEIM driver, Load its entry point\r
400 //\r
401 Status = PeiLoadImage (\r
58dcdada 402 PeiServices,\r
403 PeimFileHandle,\r
404 &EntryPoint,\r
288f9b38
LG
405 &AuthenticationState\r
406 );\r
407 }\r
408\r
b0d803fe 409 if ((Status == EFI_SUCCESS)) {\r
192f6d4c 410 //\r
58dcdada 411 // The PEIM has its dependencies satisfied, and its entry point\r
412 // has been found, so invoke it.\r
192f6d4c 413 //\r
b0d803fe 414 PERF_START (0, "PEIM", NULL, 0);\r
192f6d4c 415\r
b0d803fe 416 ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;\r
192f6d4c 417\r
418 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
419 EFI_PROGRESS_CODE,\r
797a9d67 420 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
192f6d4c 421 (VOID *)(&ExtendedData),\r
422 sizeof (ExtendedData)\r
423 );\r
424\r
3b428ade 425 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle);\r
b0d803fe 426 if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {\r
427 //\r
428 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
429 //\r
430 Private->Fv[FvCount].PeimState[PeimCount]++;\r
58dcdada 431\r
288f9b38
LG
432 if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
433 //\r
434 // Call the PEIM entry point for PEIM driver\r
435 //\r
797a9d67 436 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
437 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
288f9b38 438 }\r
797a9d67 439\r
82b8c8df 440 Private->PeimDispatchOnThisPass = TRUE;\r
192f6d4c 441 }\r
442\r
443 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
444 EFI_PROGRESS_CODE,\r
797a9d67 445 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
192f6d4c 446 (VOID *)(&ExtendedData),\r
447 sizeof (ExtendedData)\r
448 );\r
b0d803fe 449 PERF_END (0, "PEIM", NULL, 0);\r
450\r
58dcdada 451 }\r
452\r
453 if (Private->SwitchStackSignal) {\r
a7715e73 454 //\r
3d4d0c34 455 // Before switch stack from temporary memory to permenent memory, caculate the heap and stack\r
a7715e73 456 // usage in temporary memory for debuging.\r
457 //\r
458 DEBUG_CODE_BEGIN ();\r
96317468 459 UINT32 *StackPointer;\r
a7715e73 460 \r
96317468 461 for (StackPointer = (UINT32*)SecCoreData->StackBase;\r
462 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \\r
a7715e73 463 && (*StackPointer == INIT_CAR_VALUE);\r
464 StackPointer ++);\r
465 \r
3d4d0c34 466 DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
467 DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",\r
a7715e73 468 (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
469 ));\r
3d4d0c34 470 DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",\r
a7715e73 471 ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -\r
472 (UINTN) Private->HobList.Raw)\r
473 ));\r
474 DEBUG_CODE_END ();\r
475 \r
a3a15d21 476 //\r
58dcdada 477 // Reserve the size of new stack at bottom of physical memory\r
a3a15d21 478 //\r
63b62331 479 OldPeiStackSize = (UINT64) SecCoreData->StackSize;\r
58dcdada 480 NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;\r
481 if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {\r
482 Private->StackSize = NewPeiStackSize;\r
483 } else {\r
484 Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize);\r
485 }\r
192f6d4c 486\r
58dcdada 487 //\r
488 // In theory, the size of new stack in permenent memory should large than\r
489 // size of old stack in temporary memory.\r
490 // But if new stack is smaller than the size of old stack, we also reserve\r
491 // the size of old stack at bottom of permenent memory.\r
492 //\r
90e128e2 493 DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (INT32) OldPeiStackSize, (INT32) Private->StackSize));\r
28127cc7
LG
494 ASSERT (Private->StackSize >= OldPeiStackSize);\r
495 StackGap = Private->StackSize - OldPeiStackSize;\r
d74eeda8 496\r
58dcdada 497 //\r
498 // Update HandOffHob for new installed permenent memory\r
499 //\r
500 OldHandOffTable = Private->HobList.HandoffInformationTable;\r
5c5a0601 501 OldCheckingBottom = (UINTN)(SecCoreData->TemporaryRamBase);\r
58dcdada 502 OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);\r
192f6d4c 503\r
504 //\r
58dcdada 505 // The whole temporary memory will be migrated to physical memory.\r
506 // CAUTION: The new base is computed accounding to gap of new stack.\r
192f6d4c 507 //\r
58dcdada 508 NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;\r
40f26b8f 509 \r
510 //\r
3d4d0c34 511 // Caculate stack offset and heap offset between temporary memory and new permement \r
40f26b8f 512 // memory seperately.\r
513 //\r
d74eeda8 514 StackOffset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase;\r
66c69dea 515 HeapOffset = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \\r
516 (UINTN) SecCoreData->PeiTemporaryRamBase);\r
7df7393f 517 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64)HeapOffset, (INT64)StackOffset));\r
66c69dea 518 \r
40f26b8f 519 //\r
520 // Caculate new HandOffTable and PrivateData address in permenet memory's stack\r
521 //\r
66c69dea 522 NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);\r
523 PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);\r
192f6d4c 524\r
525 //\r
58dcdada 526 // TemporaryRamSupportPpi is produced by platform's SEC\r
192f6d4c 527 //\r
58dcdada 528 Status = PeiLocatePpi (\r
529 (CONST EFI_PEI_SERVICES **) PeiServices,\r
530 &gEfiTemporaryRamSupportPpiGuid,\r
531 0,\r
532 NULL,\r
533 (VOID**)&TemporaryRamSupportPpi\r
534 );\r
535\r
81c7803c 536\r
58dcdada 537 if (!EFI_ERROR (Status)) {\r
40f26b8f 538 //\r
539 // Temporary Ram support Ppi is provided by platform, it will copy \r
540 // temporary memory to permenent memory and do stack switching.\r
541 // After invoken temporary Ram support, following code's stack is in \r
3d4d0c34 542 // memory but not in temporary memory.\r
40f26b8f 543 //\r
58dcdada 544 TemporaryRamSupportPpi->TemporaryRamMigration (\r
545 (CONST EFI_PEI_SERVICES **) PeiServices,\r
546 (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,\r
547 (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,\r
548 SecCoreData->TemporaryRamSize\r
549 );\r
550\r
551 } else {\r
b414ea4b 552 //\r
553 // In IA32/x64/Itanium architecture, we need platform provide\r
554 // TEMPORAY_RAM_MIGRATION_PPI.\r
555 //\r
556 ASSERT (FALSE);\r
58dcdada 557 }\r
558\r
559\r
560 //\r
b0d803fe 561 //\r
58dcdada 562 // Fixup the PeiCore's private data\r
b0d803fe 563 //\r
58dcdada 564 PrivateInMem->PS = &PrivateInMem->ServiceTableShadow;\r
565 PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo;\r
66c69dea 566 PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset);\r
58dcdada 567 PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);\r
568\r
6c7a807a 569 PeiServices = (CONST EFI_PEI_SERVICES **) &PrivateInMem->PS;\r
58dcdada 570\r
571 //\r
572 // Fixup for PeiService's address\r
573 //\r
574 SetPeiServicesTablePointer(PeiServices);\r
575\r
576 //\r
577 // Update HandOffHob for new installed permenent memory\r
578 //\r
579 NewHandOffTable->EfiEndOfHobList =\r
66c69dea 580 (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset);\r
58dcdada 581 NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin +\r
582 PrivateInMem->PhysicalMemoryLength;\r
583 NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin;\r
584 NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop;\r
585 NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +\r
586 sizeof (EFI_HOB_GENERIC_HEADER);\r
587\r
588 //\r
589 // We need convert the PPI desciptor's pointer\r
590 //\r
40f26b8f 591 ConvertPpiPointers (PrivateInMem, \r
58dcdada 592 OldCheckingBottom, \r
593 OldCheckingTop, \r
5c5a0601 594 HeapOffset\r
595 );\r
58dcdada 596\r
7df7393f 597 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",\r
598 PrivateInMem->StackBase,\r
58dcdada 599 PrivateInMem->StackSize));\r
600 BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);\r
601\r
602 //\r
603 // After the whole temporary memory is migrated, then we can allocate page in\r
604 // permenent memory.\r
605 //\r
606 PrivateInMem->PeiMemoryInstalled = TRUE;\r
607\r
1bd90a4c 608 //\r
82b8c8df 609 // Indicate that PeiCore reenter\r
1bd90a4c 610 //\r
82b8c8df 611 PrivateInMem->PeimDispatcherReenter = TRUE;\r
612 \r
192f6d4c 613 //\r
b0d803fe 614 // Shadow PEI Core. When permanent memory is avaiable, shadow\r
615 // PEI Core and PEIMs to get high performance.\r
192f6d4c 616 //\r
58dcdada 617 PrivateInMem->ShadowedPeiCore = ShadowPeiCore (\r
618 PeiServices,\r
619 PrivateInMem\r
620 );\r
b0d803fe 621 //\r
58dcdada 622 // Process the Notify list and dispatch any notifies for\r
623 // newly installed PPIs.\r
b0d803fe 624 //\r
58dcdada 625 ProcessNotifyList (PrivateInMem);\r
626\r
b0d803fe 627 //\r
58dcdada 628 // Entry PEI Phase 2\r
b0d803fe 629 //\r
58dcdada 630 PeiCore (SecCoreData, NULL, PrivateInMem);\r
b0d803fe 631\r
58dcdada 632 //\r
633 // Code should not come here\r
634 //\r
635 ASSERT_EFI_ERROR(FALSE);\r
192f6d4c 636 }\r
192f6d4c 637\r
58dcdada 638 //\r
639 // Process the Notify list and dispatch any notifies for\r
640 // newly installed PPIs.\r
641 //\r
642 ProcessNotifyList (Private);\r
643\r
b0d803fe 644 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \\r
645 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
646 //\r
58dcdada 647 // If memory is availble we shadow images by default for performance reasons.\r
648 // We call the entry point a 2nd time so the module knows it's shadowed.\r
b0d803fe 649 //\r
650 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
e67ca95c 651 ASSERT (PeimEntryPoint != NULL);\r
797a9d67 652 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
b0d803fe 653 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
58dcdada 654\r
b0d803fe 655 //\r
656 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
657 //\r
658 Private->Fv[FvCount].PeimState[PeimCount]++;\r
192f6d4c 659\r
192f6d4c 660 //\r
b0d803fe 661 // Process the Notify list and dispatch any notifies for\r
662 // newly installed PPIs.\r
192f6d4c 663 //\r
b0d803fe 664 ProcessNotifyList (Private);\r
192f6d4c 665 }\r
666 }\r
667 }\r
192f6d4c 668 }\r
192f6d4c 669\r
b0d803fe 670 //\r
671 // We set to NULL here to optimize the 2nd entry to this routine after\r
672 // memory is found. This reprevents rescanning of the FV. We set to\r
673 // NULL here so we start at the begining of the next FV\r
674 //\r
675 Private->CurrentFileHandle = NULL;\r
676 Private->CurrentPeimCount = 0;\r
677 //\r
678 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL\r
679 //\r
680 SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);\r
192f6d4c 681 }\r
682\r
683 //\r
58dcdada 684 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go\r
b0d803fe 685 // through all the FV.\r
192f6d4c 686 //\r
b0d803fe 687 Private->CurrentPeimFvCount = 0;\r
192f6d4c 688\r
689 //\r
58dcdada 690 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get\r
b0d803fe 691 // dispatched. So we need to make another pass\r
192f6d4c 692 //\r
58dcdada 693 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this\r
b0d803fe 694 // pass. If we did not dispatch a PEIM there is no point in trying again\r
695 // as it will fail the next time too (nothing has changed).\r
192f6d4c 696 //\r
82b8c8df 697 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);\r
192f6d4c 698\r
192f6d4c 699}\r
700\r
b1f6a7c6 701/**\r
192f6d4c 702 Initialize the Dispatcher's data members\r
703\r
b1f6a7c6 704 @param PrivateData PeiCore's private data structure\r
705 @param OldCoreData Old data from SecCore\r
192f6d4c 706 NULL if being run in non-permament memory mode.\r
b1f6a7c6 707 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 708 environment, such as the size and location of temporary RAM, the stack location and\r
709 the BFV location.\r
192f6d4c 710\r
b1f6a7c6 711 @return None.\r
192f6d4c 712\r
b1f6a7c6 713**/\r
714VOID\r
715InitializeDispatcherData (\r
716 IN PEI_CORE_INSTANCE *PrivateData,\r
717 IN PEI_CORE_INSTANCE *OldCoreData,\r
718 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
719 )\r
192f6d4c 720{\r
192f6d4c 721 if (OldCoreData == NULL) {\r
82b8c8df 722 PrivateData->PeimDispatcherReenter = FALSE;\r
b0d803fe 723 PeiInitializeFv (PrivateData, SecCoreData);\r
8e0e40ed 724 } else {\r
7ec93917 725 PeiReinitializeFv (PrivateData);\r
192f6d4c 726 }\r
727\r
728 return;\r
729}\r
730\r
b1f6a7c6 731/**\r
732 This routine parses the Dependency Expression, if available, and\r
733 decides if the module can be executed.\r
734\r
735\r
736 @param Private PeiCore's private data structure\r
737 @param FileHandle PEIM's file handle\r
738 @param PeimCount Peim count in all dispatched PEIMs.\r
192f6d4c 739\r
b1f6a7c6 740 @retval TRUE Can be dispatched\r
741 @retval FALSE Cannot be dispatched\r
742\r
743**/\r
192f6d4c 744BOOLEAN\r
745DepexSatisfied (\r
b0d803fe 746 IN PEI_CORE_INSTANCE *Private,\r
747 IN EFI_PEI_FILE_HANDLE FileHandle,\r
748 IN UINTN PeimCount\r
192f6d4c 749 )\r
192f6d4c 750{\r
288f9b38
LG
751 EFI_STATUS Status;\r
752 VOID *DepexData;\r
b0d803fe 753\r
754 if (PeimCount < Private->AprioriCount) {\r
755 //\r
756 // If its in the A priori file then we set Depex to TRUE\r
757 //\r
758 return TRUE;\r
759 }\r
58dcdada 760\r
288f9b38 761 //\r
58dcdada 762 // Depex section not in the encapsulated section.\r
288f9b38
LG
763 //\r
764 Status = PeiServicesFfsFindSectionData (\r
765 EFI_SECTION_PEI_DEPEX,\r
58dcdada 766 FileHandle,\r
288f9b38
LG
767 (VOID **)&DepexData\r
768 );\r
b0d803fe 769\r
192f6d4c 770 if (EFI_ERROR (Status)) {\r
b0d803fe 771 //\r
772 // If there is no DEPEX, assume the module can be executed\r
773 //\r
192f6d4c 774 return TRUE;\r
775 }\r
776\r
777 //\r
778 // Evaluate a given DEPEX\r
779 //\r
b0d803fe 780 return PeimDispatchReadiness (&Private->PS, DepexData);\r
192f6d4c 781}\r
782\r
14e8823a 783/**\r
784 This routine enable a PEIM to register itself to shadow when PEI Foundation\r
785 discovery permanent memory.\r
786\r
b1f6a7c6 787 @param FileHandle File handle of a PEIM.\r
58dcdada 788\r
b1f6a7c6 789 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.\r
790 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.\r
791 @retval EFI_SUCCESS Successfully to register itself.\r
14e8823a 792\r
58dcdada 793**/\r
14e8823a 794EFI_STATUS\r
795EFIAPI\r
796PeiRegisterForShadow (\r
797 IN EFI_PEI_FILE_HANDLE FileHandle\r
798 )\r
799{\r
800 PEI_CORE_INSTANCE *Private;\r
801 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
802\r
803 if (Private->CurrentFileHandle != FileHandle) {\r
804 //\r
805 // The FileHandle must be for the current PEIM\r
806 //\r
807 return EFI_NOT_FOUND;\r
808 }\r
809\r
810 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {\r
811 //\r
812 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started\r
813 //\r
814 return EFI_ALREADY_STARTED;\r
815 }\r
58dcdada 816\r
14e8823a 817 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;\r
818\r
819 return EFI_SUCCESS;\r
820}\r
821\r
3b428ade 822\r