2 EFI PEI Core dispatch services
4 Copyright (c) 2006 - 2009, 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 VolumeHandle - Fv handle.
38 DiscoverPeimsAndOrderWithApriori (
39 IN PEI_CORE_INSTANCE
*Private
,
40 IN EFI_PEI_FV_HANDLE VolumeHandle
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
)];
56 // Walk the FV and find all the PEIMs and the Apriori file.
58 AprioriFileHandle
= NULL
;
59 Private
->CurrentFvFileHandles
[0] = NULL
;
64 // If the current Fv has been scanned, directly get its cachable record.
66 if (Private
->Fv
[Private
->CurrentPeimFvCount
].ScanFv
) {
67 CopyMem (Private
->CurrentFvFileHandles
, Private
->Fv
[Private
->CurrentPeimFvCount
].FvFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
72 // Go ahead to scan this Fv, and cache FileHandles within it.
74 for (PeimCount
= 0; PeimCount
< FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
); PeimCount
++) {
75 Status
= PeiFindFileEx (
78 PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE
,
82 if (Status
!= EFI_SUCCESS
) {
86 Private
->CurrentFvFileHandles
[PeimCount
] = FileHandle
;
90 // Check whether the count of Peims exceeds the max support PEIMs in a FV image
91 // If more Peims are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.
93 ASSERT (PeimCount
< FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
));
95 Private
->AprioriCount
= 0;
96 if (AprioriFileHandle
!= NULL
) {
98 // Read the Apriori file
100 Status
= PeiServicesFfsFindSectionData (EFI_SECTION_RAW
, AprioriFileHandle
, (VOID
**) &Apriori
);
101 if (!EFI_ERROR (Status
)) {
103 // Calculate the number of PEIMs in the A Priori list
105 Private
->AprioriCount
= *(UINT32
*)(((EFI_FFS_FILE_HEADER
*)AprioriFileHandle
)->Size
) & 0x00FFFFFF;
106 Private
->AprioriCount
-= sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_COMMON_SECTION_HEADER
);
107 Private
->AprioriCount
/= sizeof (EFI_GUID
);
109 ZeroMem (FileGuid
, sizeof (FileGuid
));
110 for (Index
= 0; Index
< PeimCount
; Index
++) {
112 // Make an array of file name guids that matches the FileHandle array so we can convert
113 // quickly from file name to file handle
115 CopyMem (&FileGuid
[Index
], &((EFI_FFS_FILE_HEADER
*)Private
->CurrentFvFileHandles
[Index
])->Name
,sizeof(EFI_GUID
));
119 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
120 // Add avalible PEIMs in Apriori file into TempFileHandles array at first.
123 for (Index
= 0; Index2
< Private
->AprioriCount
; Index
++) {
124 while (Index2
< Private
->AprioriCount
) {
125 Guid
= ScanGuid (FileGuid
, PeimCount
* sizeof (EFI_GUID
), &Apriori
[Index2
++]);
133 PeimIndex
= ((UINTN
)Guid
- (UINTN
)&FileGuid
[0])/sizeof (EFI_GUID
);
134 TempFileHandles
[Index
] = Private
->CurrentFvFileHandles
[PeimIndex
];
137 // Since we have copied the file handle we can remove it from this list.
139 Private
->CurrentFvFileHandles
[PeimIndex
] = NULL
;
143 // Update valid Aprioricount
145 Private
->AprioriCount
= Index
;
148 // Add in any PEIMs not in the Apriori file
150 for (;Index
< PeimCount
; Index
++) {
151 for (Index2
= 0; Index2
< PeimCount
; Index2
++) {
152 if (Private
->CurrentFvFileHandles
[Index2
] != NULL
) {
153 TempFileHandles
[Index
] = Private
->CurrentFvFileHandles
[Index2
];
154 Private
->CurrentFvFileHandles
[Index2
] = NULL
;
160 //Index the end of array contains re-range Pei moudle.
162 TempFileHandles
[Index
] = NULL
;
165 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
166 // We need to update it to start with files in the A Priori list and
167 // then the remaining files in PEIM order.
169 CopyMem (Private
->CurrentFvFileHandles
, TempFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
173 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
174 // Instead, we can retrieve the file handles within this Fv from cachable data.
176 Private
->Fv
[Private
->CurrentPeimFvCount
].ScanFv
= TRUE
;
177 CopyMem (Private
->Fv
[Private
->CurrentPeimFvCount
].FvFileHandles
, Private
->CurrentFvFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
182 Shadow PeiCore module from flash to installed memory.
184 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
185 @param PrivateInMem PeiCore's private data structure
187 @return PeiCore function address after shadowing.
191 IN CONST EFI_PEI_SERVICES
**PeiServices
,
192 IN PEI_CORE_INSTANCE
*PrivateInMem
195 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
196 EFI_PHYSICAL_ADDRESS EntryPoint
;
198 UINT32 AuthenticationState
;
200 PeiCoreFileHandle
= NULL
;
203 // Find the PEI Core in the BFV
205 Status
= PeiFindFileEx (
206 (EFI_PEI_FV_HANDLE
)PrivateInMem
->Fv
[0].FvHeader
,
208 EFI_FV_FILETYPE_PEI_CORE
,
212 ASSERT_EFI_ERROR (Status
);
215 // Shadow PEI Core into memory so it will run faster
217 Status
= PeiLoadImage (
219 *((EFI_PEI_FILE_HANDLE
*)&PeiCoreFileHandle
),
223 ASSERT_EFI_ERROR (Status
);
226 // Compute the PeiCore's function address after shaowed PeiCore.
227 // _ModuleEntryPoint is PeiCore main function entry
229 return (VOID
*) ((UINTN
) EntryPoint
+ (UINTN
) PeiCore
- (UINTN
) _ModuleEntryPoint
);
233 Conduct PEIM dispatch.
235 @param SecCoreData Points to a data structure containing information about the PEI core's operating
236 environment, such as the size and location of temporary RAM, the stack location and
238 @param Private Pointer to the private data passed in from caller
243 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
244 IN PEI_CORE_INSTANCE
*Private
250 CONST EFI_PEI_SERVICES
**PeiServices
;
251 EFI_PEI_FV_HANDLE VolumeHandle
;
252 EFI_PEI_FILE_HANDLE PeimFileHandle
;
255 UINT32 AuthenticationState
;
256 EFI_PHYSICAL_ADDRESS EntryPoint
;
257 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint
;
258 UINTN SaveCurrentPeimCount
;
259 UINTN SaveCurrentFvCount
;
260 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle
;
261 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData
;
262 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase
;
263 TEMPORARY_RAM_SUPPORT_PPI
*TemporaryRamSupportPpi
;
264 EFI_HOB_HANDOFF_INFO_TABLE
*OldHandOffTable
;
265 EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffTable
;
268 PEI_CORE_INSTANCE
*PrivateInMem
;
269 UINT64 NewPeiStackSize
;
270 UINT64 OldPeiStackSize
;
272 EFI_FV_FILE_INFO FvFileInfo
;
273 UINTN OldCheckingTop
;
274 UINTN OldCheckingBottom
;
277 PeiServices
= (CONST EFI_PEI_SERVICES
**) &Private
->PS
;
278 PeimEntryPoint
= NULL
;
279 PeimFileHandle
= NULL
;
282 if ((Private
->PeiMemoryInstalled
) && (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
284 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
285 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
287 SaveCurrentPeimCount
= Private
->CurrentPeimCount
;
288 SaveCurrentFvCount
= Private
->CurrentPeimFvCount
;
289 SaveCurrentFileHandle
= Private
->CurrentFileHandle
;
291 for (Index1
= 0; Index1
<= SaveCurrentFvCount
; Index1
++) {
292 for (Index2
= 0; (Index2
< FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)) && (Private
->Fv
[Index1
].FvFileHandles
[Index2
] != NULL
); Index2
++) {
293 if (Private
->Fv
[Index1
].PeimState
[Index2
] == PEIM_STATE_REGISITER_FOR_SHADOW
) {
294 PeimFileHandle
= Private
->Fv
[Index1
].FvFileHandles
[Index2
];
295 Status
= PeiLoadImage (
296 (CONST EFI_PEI_SERVICES
**) &Private
->PS
,
301 if (Status
== EFI_SUCCESS
) {
303 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
305 Private
->Fv
[Index1
].PeimState
[Index2
]++;
306 Private
->CurrentFileHandle
= PeimFileHandle
;
307 Private
->CurrentPeimFvCount
= Index1
;
308 Private
->CurrentPeimCount
= Index2
;
310 // Call the PEIM entry point
312 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
314 PERF_START (0, "PEIM", NULL
, 0);
315 PeimEntryPoint(PeimFileHandle
, (const EFI_PEI_SERVICES
**) &Private
->PS
);
316 PERF_END (0, "PEIM", NULL
, 0);
320 // Process the Notify list and dispatch any notifies for
321 // newly installed PPIs.
323 ProcessNotifyList (Private
);
327 Private
->CurrentFileHandle
= SaveCurrentFileHandle
;
328 Private
->CurrentPeimFvCount
= SaveCurrentFvCount
;
329 Private
->CurrentPeimCount
= SaveCurrentPeimCount
;
333 // This is the main dispatch loop. It will search known FVs for PEIMs and
334 // attempt to dispatch them. If any PEIM gets dispatched through a single
335 // pass of the dispatcher, it will start over from the Bfv again to see
336 // if any new PEIMs dependencies got satisfied. With a well ordered
337 // FV where PEIMs are found in the order their dependencies are also
338 // satisfied, this dipatcher should run only once.
342 // In case that reenter PeiCore happens, the last pass record is still available.
344 if (!Private
->PeimDispatcherReenter
) {
345 Private
->PeimNeedingDispatch
= FALSE
;
346 Private
->PeimDispatchOnThisPass
= FALSE
;
348 Private
->PeimDispatcherReenter
= FALSE
;
351 for (FvCount
= Private
->CurrentPeimFvCount
; FvCount
< Private
->FvCount
; FvCount
++) {
352 Private
->CurrentPeimFvCount
= FvCount
;
354 // Get this Fv Handle by PeiService FvFindNextVolume.
356 PeiFvFindNextVolume (PeiServices
, FvCount
, &VolumeHandle
);
358 if (Private
->CurrentPeimCount
== 0) {
360 // When going through each FV, at first, search Apriori file to
361 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
362 // dispatch at first.
364 DiscoverPeimsAndOrderWithApriori (Private
, VolumeHandle
);
368 // Start to dispatch all modules within the current Fv.
370 for (PeimCount
= Private
->CurrentPeimCount
;
371 (PeimCount
< FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)) && (Private
->CurrentFvFileHandles
[PeimCount
] != NULL
);
373 Private
->CurrentPeimCount
= PeimCount
;
374 PeimFileHandle
= Private
->CurrentFileHandle
= Private
->CurrentFvFileHandles
[PeimCount
];
376 if (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_NOT_DISPATCHED
) {
377 if (!DepexSatisfied (Private
, PeimFileHandle
, PeimCount
)) {
378 Private
->PeimNeedingDispatch
= TRUE
;
380 Status
= PeiFfsGetFileInfo (PeimFileHandle
, &FvFileInfo
);
381 ASSERT_EFI_ERROR (Status
);
382 if (FvFileInfo
.FileType
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
384 // For Fv type file, Produce new FV PPI and FV hob
386 Status
= ProcessFvFile (PeiServices
, VolumeHandle
, PeimFileHandle
, &AuthenticationState
);
389 // For PEIM driver, Load its entry point
391 Status
= PeiLoadImage (
399 if ((Status
== EFI_SUCCESS
)) {
401 // The PEIM has its dependencies satisfied, and its entry point
402 // has been found, so invoke it.
404 PERF_START (0, "PEIM", NULL
, 0);
406 ExtendedData
.Handle
= (EFI_HANDLE
)PeimFileHandle
;
408 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
410 FixedPcdGet32(PcdStatusCodeValuePeimDispatch
),
411 (VOID
*)(&ExtendedData
),
412 sizeof (ExtendedData
)
415 Status
= VerifyPeim (Private
, VolumeHandle
, PeimFileHandle
);
416 if (Status
!= EFI_SECURITY_VIOLATION
&& (AuthenticationState
== 0)) {
418 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
420 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
422 if (FvFileInfo
.FileType
!= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
424 // Call the PEIM entry point for PEIM driver
426 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
427 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
430 Private
->PeimDispatchOnThisPass
= TRUE
;
433 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
435 FixedPcdGet32(PcdStatusCodeValuePeimDispatch
),
436 (VOID
*)(&ExtendedData
),
437 sizeof (ExtendedData
)
439 PERF_END (0, "PEIM", NULL
, 0);
443 if (Private
->SwitchStackSignal
) {
445 // Before switch stack from temporary memory to permenent memory, caculate the heap and stack
446 // usage in temporary memory for debuging.
449 UINT32
*StackPointer
;
451 for (StackPointer
= (UINT32
*)SecCoreData
->StackBase
;
452 (StackPointer
< (UINT32
*)((UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
)) \
453 && (*StackPointer
== INIT_CAR_VALUE
);
456 DEBUG ((EFI_D_INFO
, "Total temporary memory: %d bytes.\n", (UINT32
)SecCoreData
->TemporaryRamSize
));
457 DEBUG ((EFI_D_INFO
, " temporary memory stack ever used: %d bytes.\n",
458 (SecCoreData
->StackSize
- ((UINTN
) StackPointer
- (UINTN
)SecCoreData
->StackBase
))
460 DEBUG ((EFI_D_INFO
, " temporary memory heap used: %d bytes.\n",
461 ((UINTN
) Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryBottom
-
462 (UINTN
) Private
->HobList
.Raw
)
467 // Reserve the size of new stack at bottom of physical memory
469 OldPeiStackSize
= (UINT64
) SecCoreData
->StackSize
;
470 NewPeiStackSize
= (RShiftU64 (Private
->PhysicalMemoryLength
, 1) + EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
471 if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize
) > (UINT32
) NewPeiStackSize
) {
472 Private
->StackSize
= NewPeiStackSize
;
474 Private
->StackSize
= FixedPcdGet32(PcdPeiCoreMaxPeiStackSize
);
478 // In theory, the size of new stack in permenent memory should large than
479 // size of old stack in temporary memory.
480 // But if new stack is smaller than the size of old stack, we also reserve
481 // the size of old stack at bottom of permenent memory.
483 DEBUG ((EFI_D_INFO
, "Old Stack size %d, New stack size %d\n", (INT32
) OldPeiStackSize
, (INT32
) Private
->StackSize
));
484 ASSERT (Private
->StackSize
>= OldPeiStackSize
);
485 StackGap
= Private
->StackSize
- OldPeiStackSize
;
488 // Update HandOffHob for new installed permenent memory
490 OldHandOffTable
= Private
->HobList
.HandoffInformationTable
;
491 OldCheckingBottom
= (UINTN
)(SecCoreData
->TemporaryRamBase
);
492 OldCheckingTop
= (UINTN
)(OldCheckingBottom
+ SecCoreData
->TemporaryRamSize
);
495 // The whole temporary memory will be migrated to physical memory.
496 // CAUTION: The new base is computed accounding to gap of new stack.
498 NewPermenentMemoryBase
= Private
->PhysicalMemoryBegin
+ StackGap
;
501 // Caculate stack offset and heap offset between temporary memory and new permement
502 // memory seperately.
504 StackOffset
= (UINTN
) NewPermenentMemoryBase
- (UINTN
) SecCoreData
->StackBase
;
505 HeapOffset
= (INTN
) ((UINTN
) Private
->PhysicalMemoryBegin
+ Private
->StackSize
- \
506 (UINTN
) SecCoreData
->PeiTemporaryRamBase
);
507 DEBUG ((EFI_D_INFO
, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64
)HeapOffset
, (INT64
)StackOffset
));
510 // Caculate new HandOffTable and PrivateData address in permenet memory's stack
512 NewHandOffTable
= (EFI_HOB_HANDOFF_INFO_TABLE
*)((UINTN
)OldHandOffTable
+ HeapOffset
);
513 PrivateInMem
= (PEI_CORE_INSTANCE
*)((UINTN
) (VOID
*) Private
+ StackOffset
);
516 // TemporaryRamSupportPpi is produced by platform's SEC
518 Status
= PeiLocatePpi (
519 (CONST EFI_PEI_SERVICES
**) PeiServices
,
520 &gEfiTemporaryRamSupportPpiGuid
,
523 (VOID
**)&TemporaryRamSupportPpi
527 if (!EFI_ERROR (Status
)) {
529 // Temporary Ram support Ppi is provided by platform, it will copy
530 // temporary memory to permenent memory and do stack switching.
531 // After invoken temporary Ram support, following code's stack is in
532 // memory but not in temporary memory.
534 TemporaryRamSupportPpi
->TemporaryRamMigration (
535 (CONST EFI_PEI_SERVICES
**) PeiServices
,
536 (EFI_PHYSICAL_ADDRESS
)(UINTN
) SecCoreData
->TemporaryRamBase
,
537 (EFI_PHYSICAL_ADDRESS
)(UINTN
) NewPermenentMemoryBase
,
538 SecCoreData
->TemporaryRamSize
543 // In IA32/x64/Itanium architecture, we need platform provide
544 // TEMPORAY_RAM_MIGRATION_PPI.
552 // Fixup the PeiCore's private data
554 PrivateInMem
->PS
= &PrivateInMem
->ServiceTableShadow
;
555 PrivateInMem
->CpuIo
= &PrivateInMem
->ServiceTableShadow
.CpuIo
;
556 PrivateInMem
->HobList
.Raw
= (VOID
*) ((UINTN
) PrivateInMem
->HobList
.Raw
+ HeapOffset
);
557 PrivateInMem
->StackBase
= (EFI_PHYSICAL_ADDRESS
)(((UINTN
)PrivateInMem
->PhysicalMemoryBegin
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
);
559 PeiServices
= (CONST EFI_PEI_SERVICES
**) &PrivateInMem
->PS
;
562 // Fixup for PeiService's address
564 SetPeiServicesTablePointer(PeiServices
);
567 // Update HandOffHob for new installed permenent memory
569 NewHandOffTable
->EfiEndOfHobList
=
570 (EFI_PHYSICAL_ADDRESS
)((UINTN
) NewHandOffTable
->EfiEndOfHobList
+ HeapOffset
);
571 NewHandOffTable
->EfiMemoryTop
= PrivateInMem
->PhysicalMemoryBegin
+
572 PrivateInMem
->PhysicalMemoryLength
;
573 NewHandOffTable
->EfiMemoryBottom
= PrivateInMem
->PhysicalMemoryBegin
;
574 NewHandOffTable
->EfiFreeMemoryTop
= PrivateInMem
->FreePhysicalMemoryTop
;
575 NewHandOffTable
->EfiFreeMemoryBottom
= NewHandOffTable
->EfiEndOfHobList
+
576 sizeof (EFI_HOB_GENERIC_HEADER
);
579 // We need convert the PPI desciptor's pointer
581 ConvertPpiPointers (PrivateInMem
,
587 DEBUG ((EFI_D_INFO
, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",
588 PrivateInMem
->StackBase
,
589 PrivateInMem
->StackSize
));
590 BuildStackHob (PrivateInMem
->StackBase
, PrivateInMem
->StackSize
);
593 // After the whole temporary memory is migrated, then we can allocate page in
596 PrivateInMem
->PeiMemoryInstalled
= TRUE
;
599 // Indicate that PeiCore reenter
601 PrivateInMem
->PeimDispatcherReenter
= TRUE
;
604 // Shadow PEI Core. When permanent memory is avaiable, shadow
605 // PEI Core and PEIMs to get high performance.
607 PrivateInMem
->ShadowedPeiCore
= ShadowPeiCore (
612 // Process the Notify list and dispatch any notifies for
613 // newly installed PPIs.
615 ProcessNotifyList (PrivateInMem
);
620 PeiCore (SecCoreData
, NULL
, PrivateInMem
);
623 // Code should not come here
625 ASSERT_EFI_ERROR(FALSE
);
629 // Process the Notify list and dispatch any notifies for
630 // newly installed PPIs.
632 ProcessNotifyList (Private
);
634 if ((Private
->PeiMemoryInstalled
) && (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_REGISITER_FOR_SHADOW
) && \
635 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
637 // If memory is availble we shadow images by default for performance reasons.
638 // We call the entry point a 2nd time so the module knows it's shadowed.
640 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
641 ASSERT (PeimEntryPoint
!= NULL
);
642 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
643 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
646 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
648 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
651 // Process the Notify list and dispatch any notifies for
652 // newly installed PPIs.
654 ProcessNotifyList (Private
);
661 // We set to NULL here to optimize the 2nd entry to this routine after
662 // memory is found. This reprevents rescanning of the FV. We set to
663 // NULL here so we start at the begining of the next FV
665 Private
->CurrentFileHandle
= NULL
;
666 Private
->CurrentPeimCount
= 0;
668 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
670 SetMem (Private
->CurrentFvFileHandles
, sizeof (Private
->CurrentFvFileHandles
), 0);
674 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
675 // through all the FV.
677 Private
->CurrentPeimFvCount
= 0;
680 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
681 // dispatched. So we need to make another pass
683 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
684 // pass. If we did not dispatch a PEIM there is no point in trying again
685 // as it will fail the next time too (nothing has changed).
687 } while (Private
->PeimNeedingDispatch
&& Private
->PeimDispatchOnThisPass
);
692 Initialize the Dispatcher's data members
694 @param PrivateData PeiCore's private data structure
695 @param OldCoreData Old data from SecCore
696 NULL if being run in non-permament memory mode.
697 @param SecCoreData Points to a data structure containing information about the PEI core's operating
698 environment, such as the size and location of temporary RAM, the stack location and
705 InitializeDispatcherData (
706 IN PEI_CORE_INSTANCE
*PrivateData
,
707 IN PEI_CORE_INSTANCE
*OldCoreData
,
708 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
711 if (OldCoreData
== NULL
) {
712 PrivateData
->PeimDispatcherReenter
= FALSE
;
713 PeiInitializeFv (PrivateData
, SecCoreData
);
720 This routine parses the Dependency Expression, if available, and
721 decides if the module can be executed.
724 @param Private PeiCore's private data structure
725 @param FileHandle PEIM's file handle
726 @param PeimCount Peim count in all dispatched PEIMs.
728 @retval TRUE Can be dispatched
729 @retval FALSE Cannot be dispatched
734 IN PEI_CORE_INSTANCE
*Private
,
735 IN EFI_PEI_FILE_HANDLE FileHandle
,
742 if (PeimCount
< Private
->AprioriCount
) {
744 // If its in the A priori file then we set Depex to TRUE
750 // Depex section not in the encapsulated section.
752 Status
= PeiServicesFfsFindSectionData (
753 EFI_SECTION_PEI_DEPEX
,
758 if (EFI_ERROR (Status
)) {
760 // If there is no DEPEX, assume the module can be executed
766 // Evaluate a given DEPEX
768 return PeimDispatchReadiness (&Private
->PS
, DepexData
);
772 This routine enable a PEIM to register itself to shadow when PEI Foundation
773 discovery permanent memory.
775 @param FileHandle File handle of a PEIM.
777 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
778 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
779 @retval EFI_SUCCESS Successfully to register itself.
784 PeiRegisterForShadow (
785 IN EFI_PEI_FILE_HANDLE FileHandle
788 PEI_CORE_INSTANCE
*Private
;
789 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
791 if (Private
->CurrentFileHandle
!= FileHandle
) {
793 // The FileHandle must be for the current PEIM
795 return EFI_NOT_FOUND
;
798 if (Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] >= PEIM_STATE_REGISITER_FOR_SHADOW
) {
800 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
802 return EFI_ALREADY_STARTED
;
805 Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] = PEIM_STATE_REGISITER_FOR_SHADOW
;