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