]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Rebuilt per the Hess's bug fixes
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
... / ...
CommitLineData
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
24#include <PeiMain.h>\r
25\r
26typedef struct {\r
27 EFI_STATUS_CODE_DATA DataHeader;\r
28 EFI_HANDLE Handle;\r
29} PEIM_FILE_HANDLE_EXTENDED_DATA;\r
30\r
31STATIC\r
32VOID\r
33InvokePeiCore (\r
34 VOID *Context1,\r
35 VOID *Context2\r
36 );\r
37\r
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
62 EFI_PEI_FILE_HANDLE AprioriFileHandle;\r
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
69 EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
70 EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
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
91 for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
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
111 Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
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
193PeiDispatcher (\r
194 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
195 IN PEI_CORE_INSTANCE *Private\r
196 )\r
197\r
198/*++\r
199\r
200Routine Description:\r
201\r
202 Conduct PEIM dispatch.\r
203\r
204Arguments:\r
205\r
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
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
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
231 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;\r
232 BOOLEAN PeimNeedingDispatch;\r
233 BOOLEAN PeimDispatchOnThisPass;\r
234 UINTN SaveCurrentPeimCount;\r
235 UINTN SaveCurrentFvCount;\r
236 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;\r
237 VOID *TopOfStack;\r
238 PEI_CORE_PARAMETERS PeiCoreParameters;\r
239 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;\r
240 EFI_FV_FILE_INFO FvFileInfo;\r
241\r
242\r
243 PeiServices = &Private->PS;\r
244 PeimEntryPoint = NULL;\r
245 PeimFileHandle = NULL;\r
246 EntryPoint = 0;\r
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
254 SaveCurrentFvCount = Private->CurrentPeimFvCount;\r
255 SaveCurrentFileHandle = Private->CurrentFileHandle;\r
256\r
257 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
258 for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
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
272 Private->CurrentFileHandle = PeimFileHandle;\r
273 Private->CurrentPeimFvCount = Index1; \r
274 Private->CurrentPeimCount = Index2; \r
275 //\r
276 // Call the PEIM entry point\r
277 //\r
278 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
279 \r
280 PERF_START (0, "PEIM", NULL, 0);\r
281 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);\r
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
293 Private->CurrentFileHandle = SaveCurrentFileHandle; \r
294 Private->CurrentPeimFvCount = SaveCurrentFvCount; \r
295 Private->CurrentPeimCount = SaveCurrentPeimCount; \r
296 }\r
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
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
313\r
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
322\r
323 //\r
324 // Start to dispatch all modules within the current Fv.\r
325 //\r
326 for (PeimCount = Private->CurrentPeimCount; \r
327 (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL); \r
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
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
355 if ((Status == EFI_SUCCESS)) {\r
356 //\r
357 // The PEIM has its dependencies satisfied, and is processed.\r
358 //\r
359 PERF_START (0, "PEIM", NULL, 0);\r
360\r
361 ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;\r
362\r
363 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
364 EFI_PROGRESS_CODE,\r
365 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
366 (VOID *)(&ExtendedData),\r
367 sizeof (ExtendedData)\r
368 );\r
369\r
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
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
381 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
382 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
383 }\r
384\r
385 PeimDispatchOnThisPass = TRUE;\r
386 }\r
387\r
388 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
389 EFI_PROGRESS_CODE,\r
390 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
391 (VOID *)(&ExtendedData),\r
392 sizeof (ExtendedData)\r
393 );\r
394 PERF_END (0, "PEIM", NULL, 0);\r
395\r
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
402 }\r
403\r
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
415\r
416 //\r
417 // Make sure we don't retry the same PEIM that added memory\r
418 //\r
419 Private->CurrentPeimCount++;\r
420\r
421 //\r
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
424 //\r
425 MigrateIdtTable (PeiServices);\r
426\r
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
434\r
435 //\r
436 // Shadow PEI Core. When permanent memory is avaiable, shadow\r
437 // PEI Core and PEIMs to get high performance.\r
438 //\r
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
475 (VOID*) ((UINTN) EntryPoint + ((UINTN) PeiCore - (UINTN) _ModuleEntryPoint)),\r
476 (VOID*) &PeiCoreParameters, \r
477 TopOfStack,\r
478 (VOID*)(UINTN)Private->StackBase\r
479 );\r
480 }\r
481\r
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
489 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
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
496\r
497 //\r
498 // Process the Notify list and dispatch any notifies for\r
499 // newly installed PPIs.\r
500 //\r
501 ProcessNotifyList (Private);\r
502 }\r
503 }\r
504 }\r
505 }\r
506\r
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
518 }\r
519\r
520 //\r
521 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go \r
522 // through all the FV.\r
523 //\r
524 Private->CurrentPeimFvCount = 0;\r
525\r
526 //\r
527 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get \r
528 // dispatched. So we need to make another pass\r
529 //\r
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
533 //\r
534 } while (PeimNeedingDispatch && PeimDispatchOnThisPass);\r
535\r
536}\r
537\r
538VOID\r
539InitializeDispatcherData (\r
540 IN PEI_CORE_INSTANCE *PrivateData,\r
541 IN PEI_CORE_INSTANCE *OldCoreData,\r
542 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
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
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
558\r
559Returns:\r
560\r
561 None.\r
562\r
563--*/\r
564{\r
565 if (OldCoreData == NULL) {\r
566 PeiInitializeFv (PrivateData, SecCoreData);\r
567 }\r
568\r
569 return;\r
570}\r
571\r
572\r
573BOOLEAN\r
574DepexSatisfied (\r
575 IN PEI_CORE_INSTANCE *Private,\r
576 IN EFI_PEI_FILE_HANDLE FileHandle,\r
577 IN UINTN PeimCount\r
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
596 EFI_STATUS Status;\r
597 VOID *DepexData;\r
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
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
614\r
615 if (EFI_ERROR (Status)) {\r
616 //\r
617 // If there is no DEPEX, assume the module can be executed\r
618 //\r
619 return TRUE;\r
620 }\r
621\r
622 //\r
623 // Evaluate a given DEPEX\r
624 //\r
625 return PeimDispatchReadiness (&Private->PS, DepexData);\r
626}\r
627\r
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
667\r
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
704 ASSERT (FALSE);\r
705 CpuDeadLoop ();\r
706}\r
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