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