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