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