2 EFI PEI Core dispatch services
4 Copyright (c) 2006 - 2010, 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
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.
18 /// temporary memory is filled with this initial value during SEC phase
20 #define INIT_CAR_VALUE 0x5AA55AA5
23 EFI_STATUS_CODE_DATA DataHeader
;
25 } PEIM_FILE_HANDLE_EXTENDED_DATA
;
29 Discover all Peims and optional Apriori file in one FV. There is at most one
30 Apriori file in one FV.
33 @param Private Pointer to the private data passed in from caller
34 @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.
38 DiscoverPeimsAndOrderWithApriori (
39 IN PEI_CORE_INSTANCE
*Private
,
40 IN PEI_CORE_FV_HANDLE
*CoreFileHandle
44 EFI_PEI_FV_HANDLE FileHandle
;
45 EFI_PEI_FILE_HANDLE AprioriFileHandle
;
52 EFI_PEI_FV_HANDLE TempFileHandles
[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)];
53 EFI_GUID FileGuid
[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)];
54 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
55 EFI_FV_FILE_INFO FileInfo
;
57 FvPpi
= CoreFileHandle
->FvPpi
;
60 // Walk the FV and find all the PEIMs and the Apriori file.
62 AprioriFileHandle
= NULL
;
63 Private
->CurrentFvFileHandles
[0] = NULL
;
68 // If the current Fv has been scanned, directly get its cachable record.
70 if (Private
->Fv
[Private
->CurrentPeimFvCount
].ScanFv
) {
71 CopyMem (Private
->CurrentFvFileHandles
, Private
->Fv
[Private
->CurrentPeimFvCount
].FvFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
76 // Go ahead to scan this Fv, and cache FileHandles within it.
78 for (PeimCount
= 0; PeimCount
< PcdGet32 (PcdPeiCoreMaxPeimPerFv
); PeimCount
++) {
79 Status
= FvPpi
->FindFileByType (FvPpi
, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE
, CoreFileHandle
->FvHandle
, &FileHandle
);
80 if (Status
!= EFI_SUCCESS
) {
84 Private
->CurrentFvFileHandles
[PeimCount
] = FileHandle
;
88 // Check whether the count of Peims exceeds the max support PEIMs in a FV image
89 // If more Peims are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.
91 ASSERT (PeimCount
< PcdGet32 (PcdPeiCoreMaxPeimPerFv
));
94 // Get Apriori File handle
96 Private
->AprioriCount
= 0;
97 Status
= FvPpi
->FindFileByName (FvPpi
, &gPeiAprioriFileNameGuid
, &CoreFileHandle
->FvHandle
, &AprioriFileHandle
);
98 if (!EFI_ERROR(Status
) && AprioriFileHandle
!= NULL
) {
100 // Read the Apriori file
102 Status
= FvPpi
->FindSectionByType (FvPpi
, EFI_SECTION_RAW
, AprioriFileHandle
, (VOID
**) &Apriori
);
103 if (!EFI_ERROR (Status
)) {
105 // Calculate the number of PEIMs in the A Priori list
107 Status
= FvPpi
->GetFileInfo (FvPpi
, AprioriFileHandle
, &FileInfo
);
108 ASSERT_EFI_ERROR (Status
);
109 Private
->AprioriCount
= FileInfo
.BufferSize
& 0x00FFFFFF;
110 Private
->AprioriCount
-= sizeof (EFI_COMMON_SECTION_HEADER
);
111 Private
->AprioriCount
/= sizeof (EFI_GUID
);
113 ZeroMem (FileGuid
, sizeof (FileGuid
));
114 for (Index
= 0; Index
< PeimCount
; Index
++) {
116 // Make an array of file name guids that matches the FileHandle array so we can convert
117 // quickly from file name to file handle
119 Status
= FvPpi
->GetFileInfo (FvPpi
, Private
->CurrentFvFileHandles
[Index
], &FileInfo
);
120 CopyMem (&FileGuid
[Index
], &FileInfo
.FileName
, sizeof(EFI_GUID
));
124 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
125 // Add avalible PEIMs in Apriori file into TempFileHandles array at first.
128 for (Index
= 0; Index2
< Private
->AprioriCount
; Index
++) {
129 while (Index2
< Private
->AprioriCount
) {
130 Guid
= ScanGuid (FileGuid
, PeimCount
* sizeof (EFI_GUID
), &Apriori
[Index2
++]);
138 PeimIndex
= ((UINTN
)Guid
- (UINTN
)&FileGuid
[0])/sizeof (EFI_GUID
);
139 TempFileHandles
[Index
] = Private
->CurrentFvFileHandles
[PeimIndex
];
142 // Since we have copied the file handle we can remove it from this list.
144 Private
->CurrentFvFileHandles
[PeimIndex
] = NULL
;
148 // Update valid Aprioricount
150 Private
->AprioriCount
= Index
;
153 // Add in any PEIMs not in the Apriori file
155 for (;Index
< PeimCount
; Index
++) {
156 for (Index2
= 0; Index2
< PeimCount
; Index2
++) {
157 if (Private
->CurrentFvFileHandles
[Index2
] != NULL
) {
158 TempFileHandles
[Index
] = Private
->CurrentFvFileHandles
[Index2
];
159 Private
->CurrentFvFileHandles
[Index2
] = NULL
;
165 //Index the end of array contains re-range Pei moudle.
167 TempFileHandles
[Index
] = NULL
;
170 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
171 // We need to update it to start with files in the A Priori list and
172 // then the remaining files in PEIM order.
174 CopyMem (Private
->CurrentFvFileHandles
, TempFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
178 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
179 // Instead, we can retrieve the file handles within this Fv from cachable data.
181 Private
->Fv
[Private
->CurrentPeimFvCount
].ScanFv
= TRUE
;
182 CopyMem (Private
->Fv
[Private
->CurrentPeimFvCount
].FvFileHandles
, Private
->CurrentFvFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
187 Shadow PeiCore module from flash to installed memory.
189 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
190 @param PrivateInMem PeiCore's private data structure
192 @return PeiCore function address after shadowing.
196 IN CONST EFI_PEI_SERVICES
**PeiServices
,
197 IN PEI_CORE_INSTANCE
*PrivateInMem
200 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
201 EFI_PHYSICAL_ADDRESS EntryPoint
;
203 UINT32 AuthenticationState
;
205 PeiCoreFileHandle
= NULL
;
208 // Find the PEI Core in the BFV
210 Status
= PrivateInMem
->Fv
[0].FvPpi
->FindFileByType (
211 PrivateInMem
->Fv
[0].FvPpi
,
212 EFI_FV_FILETYPE_PEI_CORE
,
213 PrivateInMem
->Fv
[0].FvHandle
,
216 ASSERT_EFI_ERROR (Status
);
219 // Shadow PEI Core into memory so it will run faster
221 Status
= PeiLoadImage (
223 *((EFI_PEI_FILE_HANDLE
*)&PeiCoreFileHandle
),
224 PEIM_STATE_REGISITER_FOR_SHADOW
,
228 ASSERT_EFI_ERROR (Status
);
231 // Compute the PeiCore's function address after shaowed PeiCore.
232 // _ModuleEntryPoint is PeiCore main function entry
234 return (VOID
*) ((UINTN
) EntryPoint
+ (UINTN
) PeiCore
- (UINTN
) _ModuleEntryPoint
);
238 Conduct PEIM dispatch.
240 @param SecCoreData Points to a data structure containing information about the PEI core's operating
241 environment, such as the size and location of temporary RAM, the stack location and
243 @param Private Pointer to the private data passed in from caller
248 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
249 IN PEI_CORE_INSTANCE
*Private
255 CONST EFI_PEI_SERVICES
**PeiServices
;
256 EFI_PEI_FILE_HANDLE PeimFileHandle
;
259 UINT32 AuthenticationState
;
260 EFI_PHYSICAL_ADDRESS EntryPoint
;
261 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint
;
262 UINTN SaveCurrentPeimCount
;
263 UINTN SaveCurrentFvCount
;
264 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle
;
265 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData
;
266 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase
;
267 TEMPORARY_RAM_SUPPORT_PPI
*TemporaryRamSupportPpi
;
268 EFI_HOB_HANDOFF_INFO_TABLE
*OldHandOffTable
;
269 EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffTable
;
272 PEI_CORE_INSTANCE
*PrivateInMem
;
273 UINT64 NewPeiStackSize
;
274 UINT64 OldPeiStackSize
;
276 EFI_FV_FILE_INFO FvFileInfo
;
277 UINTN OldCheckingTop
;
278 UINTN OldCheckingBottom
;
279 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
281 PeiServices
= (CONST EFI_PEI_SERVICES
**) &Private
->PS
;
282 PeimEntryPoint
= NULL
;
283 PeimFileHandle
= NULL
;
286 if ((Private
->PeiMemoryInstalled
) && (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
288 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
289 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
291 SaveCurrentPeimCount
= Private
->CurrentPeimCount
;
292 SaveCurrentFvCount
= Private
->CurrentPeimFvCount
;
293 SaveCurrentFileHandle
= Private
->CurrentFileHandle
;
295 for (Index1
= 0; Index1
<= SaveCurrentFvCount
; Index1
++) {
296 for (Index2
= 0; (Index2
< PcdGet32 (PcdPeiCoreMaxPeimPerFv
)) && (Private
->Fv
[Index1
].FvFileHandles
[Index2
] != NULL
); Index2
++) {
297 if (Private
->Fv
[Index1
].PeimState
[Index2
] == PEIM_STATE_REGISITER_FOR_SHADOW
) {
298 PeimFileHandle
= Private
->Fv
[Index1
].FvFileHandles
[Index2
];
299 Status
= PeiLoadImage (
300 (CONST EFI_PEI_SERVICES
**) &Private
->PS
,
302 PEIM_STATE_REGISITER_FOR_SHADOW
,
306 if (Status
== EFI_SUCCESS
) {
308 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
310 Private
->Fv
[Index1
].PeimState
[Index2
]++;
311 Private
->CurrentFileHandle
= PeimFileHandle
;
312 Private
->CurrentPeimFvCount
= Index1
;
313 Private
->CurrentPeimCount
= Index2
;
315 // Call the PEIM entry point
317 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
319 PERF_START (PeimFileHandle
, "PEIM", NULL
, 0);
320 PeimEntryPoint(PeimFileHandle
, (const EFI_PEI_SERVICES
**) &Private
->PS
);
321 PERF_END (PeimFileHandle
, "PEIM", NULL
, 0);
325 // Process the Notify list and dispatch any notifies for
326 // newly installed PPIs.
328 ProcessNotifyList (Private
);
332 Private
->CurrentFileHandle
= SaveCurrentFileHandle
;
333 Private
->CurrentPeimFvCount
= SaveCurrentFvCount
;
334 Private
->CurrentPeimCount
= SaveCurrentPeimCount
;
338 // This is the main dispatch loop. It will search known FVs for PEIMs and
339 // attempt to dispatch them. If any PEIM gets dispatched through a single
340 // pass of the dispatcher, it will start over from the Bfv again to see
341 // if any new PEIMs dependencies got satisfied. With a well ordered
342 // FV where PEIMs are found in the order their dependencies are also
343 // satisfied, this dipatcher should run only once.
347 // In case that reenter PeiCore happens, the last pass record is still available.
349 if (!Private
->PeimDispatcherReenter
) {
350 Private
->PeimNeedingDispatch
= FALSE
;
351 Private
->PeimDispatchOnThisPass
= FALSE
;
353 Private
->PeimDispatcherReenter
= FALSE
;
356 for (FvCount
= Private
->CurrentPeimFvCount
; FvCount
< Private
->FvCount
; FvCount
++) {
357 CoreFvHandle
= FindNextCoreFvHandle (Private
, FvCount
);
358 ASSERT (CoreFvHandle
!= NULL
);
361 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
363 if (CoreFvHandle
->FvPpi
== NULL
) {
367 Private
->CurrentPeimFvCount
= FvCount
;
369 if (Private
->CurrentPeimCount
== 0) {
371 // When going through each FV, at first, search Apriori file to
372 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
373 // dispatch at first.
375 DiscoverPeimsAndOrderWithApriori (Private
, CoreFvHandle
);
379 // Start to dispatch all modules within the current Fv.
381 for (PeimCount
= Private
->CurrentPeimCount
;
382 (PeimCount
< PcdGet32 (PcdPeiCoreMaxPeimPerFv
)) && (Private
->CurrentFvFileHandles
[PeimCount
] != NULL
);
384 Private
->CurrentPeimCount
= PeimCount
;
385 PeimFileHandle
= Private
->CurrentFileHandle
= Private
->CurrentFvFileHandles
[PeimCount
];
387 if (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_NOT_DISPATCHED
) {
388 if (!DepexSatisfied (Private
, PeimFileHandle
, PeimCount
)) {
389 Private
->PeimNeedingDispatch
= TRUE
;
391 Status
= CoreFvHandle
->FvPpi
->GetFileInfo (CoreFvHandle
->FvPpi
, PeimFileHandle
, &FvFileInfo
);
392 ASSERT_EFI_ERROR (Status
);
393 if (FvFileInfo
.FileType
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
395 // For Fv type file, Produce new FV PPI and FV hob
397 Status
= ProcessFvFile (&Private
->Fv
[FvCount
], PeimFileHandle
);
398 AuthenticationState
= 0;
401 // For PEIM driver, Load its entry point
403 Status
= PeiLoadImage (
406 PEIM_STATE_NOT_DISPATCHED
,
412 if ((Status
== EFI_SUCCESS
)) {
414 // The PEIM has its dependencies satisfied, and its entry point
415 // has been found, so invoke it.
417 PERF_START (PeimFileHandle
, "PEIM", NULL
, 0);
419 ExtendedData
.Handle
= (EFI_HANDLE
)PeimFileHandle
;
421 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
423 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT_BEGIN
),
424 (VOID
*)(&ExtendedData
),
425 sizeof (ExtendedData
)
428 Status
= VerifyPeim (Private
, CoreFvHandle
->FvHandle
, PeimFileHandle
);
429 if (Status
!= EFI_SECURITY_VIOLATION
&& (AuthenticationState
== 0)) {
431 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
433 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
435 if (FvFileInfo
.FileType
!= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
437 // Call the PEIM entry point for PEIM driver
439 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
440 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
443 Private
->PeimDispatchOnThisPass
= TRUE
;
446 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
448 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT_BEGIN
),
449 (VOID
*)(&ExtendedData
),
450 sizeof (ExtendedData
)
452 PERF_END (PeimFileHandle
, "PEIM", NULL
, 0);
456 if (Private
->SwitchStackSignal
) {
458 // Before switch stack from temporary memory to permenent memory, caculate the heap and stack
459 // usage in temporary memory for debuging.
462 UINT32
*StackPointer
;
464 for (StackPointer
= (UINT32
*)SecCoreData
->StackBase
;
465 (StackPointer
< (UINT32
*)((UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
)) \
466 && (*StackPointer
== INIT_CAR_VALUE
);
469 DEBUG ((EFI_D_INFO
, "Total temporary memory: %d bytes.\n", (UINT32
)SecCoreData
->TemporaryRamSize
));
470 DEBUG ((EFI_D_INFO
, " temporary memory stack ever used: %d bytes.\n",
471 (SecCoreData
->StackSize
- ((UINTN
) StackPointer
- (UINTN
)SecCoreData
->StackBase
))
473 DEBUG ((EFI_D_INFO
, " temporary memory heap used: %d bytes.\n",
474 ((UINTN
) Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryBottom
-
475 (UINTN
) Private
->HobList
.Raw
)
480 // Reserve the size of new stack at bottom of physical memory
482 OldPeiStackSize
= (UINT64
) SecCoreData
->StackSize
;
483 NewPeiStackSize
= (RShiftU64 (Private
->PhysicalMemoryLength
, 1) + EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
484 if (PcdGet32(PcdPeiCoreMaxPeiStackSize
) > (UINT32
) NewPeiStackSize
) {
485 Private
->StackSize
= NewPeiStackSize
;
487 Private
->StackSize
= PcdGet32(PcdPeiCoreMaxPeiStackSize
);
491 // In theory, the size of new stack in permenent memory should large than
492 // size of old stack in temporary memory.
493 // But if new stack is smaller than the size of old stack, we also reserve
494 // the size of old stack at bottom of permenent memory.
496 DEBUG ((EFI_D_INFO
, "Old Stack size %d, New stack size %d\n", (INT32
) OldPeiStackSize
, (INT32
) Private
->StackSize
));
497 ASSERT (Private
->StackSize
>= OldPeiStackSize
);
498 StackGap
= Private
->StackSize
- OldPeiStackSize
;
501 // Update HandOffHob for new installed permenent memory
503 OldHandOffTable
= Private
->HobList
.HandoffInformationTable
;
504 OldCheckingBottom
= (UINTN
)(SecCoreData
->TemporaryRamBase
);
505 OldCheckingTop
= (UINTN
)(OldCheckingBottom
+ SecCoreData
->TemporaryRamSize
);
508 // The whole temporary memory will be migrated to physical memory.
509 // CAUTION: The new base is computed accounding to gap of new stack.
511 NewPermenentMemoryBase
= Private
->PhysicalMemoryBegin
+ StackGap
;
514 // Caculate stack offset and heap offset between temporary memory and new permement
515 // memory seperately.
517 StackOffset
= (UINTN
) NewPermenentMemoryBase
- (UINTN
) SecCoreData
->StackBase
;
518 HeapOffset
= (INTN
) ((UINTN
) Private
->PhysicalMemoryBegin
+ Private
->StackSize
- \
519 (UINTN
) SecCoreData
->PeiTemporaryRamBase
);
520 DEBUG ((EFI_D_INFO
, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64
)HeapOffset
, (INT64
)StackOffset
));
523 // Caculate new HandOffTable and PrivateData address in permenet memory's stack
525 NewHandOffTable
= (EFI_HOB_HANDOFF_INFO_TABLE
*)((UINTN
)OldHandOffTable
+ HeapOffset
);
526 PrivateInMem
= (PEI_CORE_INSTANCE
*)((UINTN
) (VOID
*) Private
+ StackOffset
);
529 // TemporaryRamSupportPpi is produced by platform's SEC
531 Status
= PeiLocatePpi (
532 (CONST EFI_PEI_SERVICES
**) PeiServices
,
533 &gEfiTemporaryRamSupportPpiGuid
,
536 (VOID
**)&TemporaryRamSupportPpi
540 if (!EFI_ERROR (Status
)) {
542 // Temporary Ram support Ppi is provided by platform, it will copy
543 // temporary memory to permenent memory and do stack switching.
544 // After invoken temporary Ram support, following code's stack is in
545 // memory but not in temporary memory.
547 TemporaryRamSupportPpi
->TemporaryRamMigration (
548 (CONST EFI_PEI_SERVICES
**) PeiServices
,
549 (EFI_PHYSICAL_ADDRESS
)(UINTN
) SecCoreData
->TemporaryRamBase
,
550 (EFI_PHYSICAL_ADDRESS
)(UINTN
) NewPermenentMemoryBase
,
551 SecCoreData
->TemporaryRamSize
556 // In IA32/x64/Itanium architecture, we need platform provide
557 // TEMPORAY_RAM_MIGRATION_PPI.
565 // Fixup the PeiCore's private data
567 PrivateInMem
->PS
= &PrivateInMem
->ServiceTableShadow
;
568 PrivateInMem
->CpuIo
= &PrivateInMem
->ServiceTableShadow
.CpuIo
;
569 PrivateInMem
->HobList
.Raw
= (VOID
*) ((UINTN
) PrivateInMem
->HobList
.Raw
+ HeapOffset
);
570 PrivateInMem
->StackBase
= (EFI_PHYSICAL_ADDRESS
)(((UINTN
)PrivateInMem
->PhysicalMemoryBegin
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
);
572 PeiServices
= (CONST EFI_PEI_SERVICES
**) &PrivateInMem
->PS
;
575 // Fixup for PeiService's address
577 SetPeiServicesTablePointer(PeiServices
);
580 // Update HandOffHob for new installed permenent memory
582 NewHandOffTable
->EfiEndOfHobList
=
583 (EFI_PHYSICAL_ADDRESS
)((UINTN
) NewHandOffTable
->EfiEndOfHobList
+ HeapOffset
);
584 NewHandOffTable
->EfiMemoryTop
= PrivateInMem
->PhysicalMemoryBegin
+
585 PrivateInMem
->PhysicalMemoryLength
;
586 NewHandOffTable
->EfiMemoryBottom
= PrivateInMem
->PhysicalMemoryBegin
;
587 NewHandOffTable
->EfiFreeMemoryTop
= PrivateInMem
->FreePhysicalMemoryTop
;
588 NewHandOffTable
->EfiFreeMemoryBottom
= NewHandOffTable
->EfiEndOfHobList
+
589 sizeof (EFI_HOB_GENERIC_HEADER
);
592 // We need convert the PPI desciptor's pointer
594 ConvertPpiPointers (PrivateInMem
,
600 DEBUG ((EFI_D_INFO
, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",
601 PrivateInMem
->StackBase
,
602 PrivateInMem
->StackSize
));
603 BuildStackHob (PrivateInMem
->StackBase
, PrivateInMem
->StackSize
);
606 // After the whole temporary memory is migrated, then we can allocate page in
609 PrivateInMem
->PeiMemoryInstalled
= TRUE
;
612 // Indicate that PeiCore reenter
614 PrivateInMem
->PeimDispatcherReenter
= TRUE
;
617 // Shadow PEI Core. When permanent memory is avaiable, shadow
618 // PEI Core and PEIMs to get high performance.
620 PrivateInMem
->ShadowedPeiCore
= ShadowPeiCore (
625 // Process the Notify list and dispatch any notifies for
626 // newly installed PPIs.
628 ProcessNotifyList (PrivateInMem
);
633 PeiCore (SecCoreData
, NULL
, PrivateInMem
);
636 // Code should not come here
638 ASSERT_EFI_ERROR(FALSE
);
642 // Process the Notify list and dispatch any notifies for
643 // newly installed PPIs.
645 ProcessNotifyList (Private
);
647 if ((Private
->PeiMemoryInstalled
) && (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_REGISITER_FOR_SHADOW
) && \
648 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
650 // If memory is availble we shadow images by default for performance reasons.
651 // We call the entry point a 2nd time so the module knows it's shadowed.
653 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
654 ASSERT (PeimEntryPoint
!= NULL
);
655 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
656 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
659 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
661 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
664 // Process the Notify list and dispatch any notifies for
665 // newly installed PPIs.
667 ProcessNotifyList (Private
);
674 // We set to NULL here to optimize the 2nd entry to this routine after
675 // memory is found. This reprevents rescanning of the FV. We set to
676 // NULL here so we start at the begining of the next FV
678 Private
->CurrentFileHandle
= NULL
;
679 Private
->CurrentPeimCount
= 0;
681 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
683 SetMem (Private
->CurrentFvFileHandles
, sizeof (Private
->CurrentFvFileHandles
), 0);
687 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
688 // through all the FV.
690 Private
->CurrentPeimFvCount
= 0;
693 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
694 // dispatched. So we need to make another pass
696 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
697 // pass. If we did not dispatch a PEIM there is no point in trying again
698 // as it will fail the next time too (nothing has changed).
700 } while (Private
->PeimNeedingDispatch
&& Private
->PeimDispatchOnThisPass
);
705 Initialize the Dispatcher's data members
707 @param PrivateData PeiCore's private data structure
708 @param OldCoreData Old data from SecCore
709 NULL if being run in non-permament memory mode.
710 @param SecCoreData Points to a data structure containing information about the PEI core's operating
711 environment, such as the size and location of temporary RAM, the stack location and
718 InitializeDispatcherData (
719 IN PEI_CORE_INSTANCE
*PrivateData
,
720 IN PEI_CORE_INSTANCE
*OldCoreData
,
721 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
724 if (OldCoreData
== NULL
) {
725 PrivateData
->PeimDispatcherReenter
= FALSE
;
726 PeiInitializeFv (PrivateData
, SecCoreData
);
728 PeiReinitializeFv (PrivateData
);
735 This routine parses the Dependency Expression, if available, and
736 decides if the module can be executed.
739 @param Private PeiCore's private data structure
740 @param FileHandle PEIM's file handle
741 @param PeimCount Peim count in all dispatched PEIMs.
743 @retval TRUE Can be dispatched
744 @retval FALSE Cannot be dispatched
749 IN PEI_CORE_INSTANCE
*Private
,
750 IN EFI_PEI_FILE_HANDLE FileHandle
,
757 if (PeimCount
< Private
->AprioriCount
) {
759 // If its in the A priori file then we set Depex to TRUE
765 // Depex section not in the encapsulated section.
767 Status
= PeiServicesFfsFindSectionData (
768 EFI_SECTION_PEI_DEPEX
,
773 if (EFI_ERROR (Status
)) {
775 // If there is no DEPEX, assume the module can be executed
781 // Evaluate a given DEPEX
783 return PeimDispatchReadiness (&Private
->PS
, DepexData
);
787 This routine enable a PEIM to register itself to shadow when PEI Foundation
788 discovery permanent memory.
790 @param FileHandle File handle of a PEIM.
792 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
793 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
794 @retval EFI_SUCCESS Successfully to register itself.
799 PeiRegisterForShadow (
800 IN EFI_PEI_FILE_HANDLE FileHandle
803 PEI_CORE_INSTANCE
*Private
;
804 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
806 if (Private
->CurrentFileHandle
!= FileHandle
) {
808 // The FileHandle must be for the current PEIM
810 return EFI_NOT_FOUND
;
813 if (Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] >= PEIM_STATE_REGISITER_FOR_SHADOW
) {
815 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
817 return EFI_ALREADY_STARTED
;
820 Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] = PEIM_STATE_REGISITER_FOR_SHADOW
;