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