summaryrefslogtreecommitdiff
path: root/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c')
-rw-r--r--Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c689
1 files changed, 689 insertions, 0 deletions
diff --git a/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c b/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c
new file mode 100644
index 0000000..91e8821
--- /dev/null
+++ b/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c
@@ -0,0 +1,689 @@
+/*++
+
+Copyright (c) 2004 - 2009, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Dispatcher.c
+
+Abstract:
+
+ EFI PEI Core dispatch services
+
+Revision History
+
+--*/
+
+#include "Tiano.h"
+#include "PeiCore.h"
+#include "PeiLib.h"
+#include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
+
+//*** AMI PORTING BEGIN ***//
+VOID PeiCoreEntry(IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList);
+//*** AMI PORTING END *****//
+VOID
+DiscoverPeimsAndOrderWithApriori (
+ IN PEI_CORE_INSTANCE *Private,
+ IN EFI_PEI_FV_HANDLE VolumeHandle
+ )
+/*++
+
+Routine Description:
+
+ Discover all Peims and optional Apriori file in one FV. There is at most one
+ Apriori file in one FV.
+
+Arguments:
+
+ Private - Pointer to the private data passed in from caller
+ VolumeHandle - Fv handle.
+Returns:
+
+ NONE
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_FV_HANDLE FileHandle;
+ EFI_PEI_FILE_HANDLE AprioriFileHandle;
+ EFI_GUID *Apriori;
+ UINTN Index;
+ UINTN Index2;
+ UINTN PeimIndex;
+ UINTN PeimCount;
+ EFI_GUID *Guid;
+ EFI_PEI_FV_HANDLE TempFileHandles[PEI_CORE_MAX_PEIM_PER_FV];
+ EFI_GUID FileGuid[PEI_CORE_MAX_PEIM_PER_FV];
+
+ //
+ // Walk the FV and find all the PEIMs and the Apriori file.
+ //
+ AprioriFileHandle = NULL;
+ Private->CurrentFvFileHandles[0] = NULL;
+ Guid = NULL;
+ FileHandle = NULL;
+
+ //
+ // If the current Fv has been scanned, directly get its cachable record.
+ //
+ if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {
+ PeiCoreCopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));
+ return;
+ }
+
+ //
+ // Go ahead to scan this Fv, and cache FileHandles within it.
+ //
+ for (PeimCount = 0; PeimCount < PEI_CORE_MAX_PEIM_PER_FV; PeimCount++) {
+ Status = PeiFindFileEx (
+ VolumeHandle,
+ NULL,
+ PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
+ &FileHandle,
+ &AprioriFileHandle
+ );
+ if (Status != EFI_SUCCESS) {
+ break;
+ }
+
+ Private->CurrentFvFileHandles[PeimCount] = FileHandle;
+ }
+
+ Private->AprioriCount = 0;
+ if (AprioriFileHandle != NULL) {
+ //
+ // Read the Apriori file
+ //
+ Status = PeiFfsFindSectionData (&Private->PS, EFI_SECTION_RAW, AprioriFileHandle, &Apriori);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Calculate the number of PEIMs in the A Priori list
+ //
+ Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF;
+ Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER);
+ Private->AprioriCount /= sizeof (EFI_GUID);
+
+ PeiCoreSetMem (FileGuid, sizeof (FileGuid), 0);
+ for (Index = 0; Index < PeimCount; Index++) {
+ //
+ // Make an array of file name guids that matches the FileHandle array so we can convert
+ // quickly from file name to file handle
+ //
+ PeiCoreCopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID));
+ }
+
+ //
+ // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
+ // Add avalible PEIMs in Apriori file into TempFileHandles array at first.
+ //
+ Index2 = 0;
+ for (Index = 0; Index2 < Private->AprioriCount; Index++) {
+ while (Index2 < Private->AprioriCount) {
+ Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);
+ if (Guid != NULL) {
+ break;
+ }
+ }
+ if (Guid == NULL) {
+ break;
+ }
+ PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);
+ TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];
+
+ //
+ // Since we have copied the file handle we can remove it from this list.
+ //
+ Private->CurrentFvFileHandles[PeimIndex] = NULL;
+ }
+
+ //
+ // Update valid Aprioricount
+ //
+ Private->AprioriCount = Index;
+
+ //
+ // Add in any PEIMs not in the Apriori file
+ //
+ for (;Index < PeimCount; Index++) {
+ for (Index2 = 0; Index2 < PeimCount; Index2++) {
+ if (Private->CurrentFvFileHandles[Index2] != NULL) {
+ TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];
+ Private->CurrentFvFileHandles[Index2] = NULL;
+ break;
+ }
+ }
+ }
+ //
+ //Index the end of array contains re-range Pei moudle.
+ //
+ TempFileHandles[Index] = NULL;
+
+ //
+ // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
+ // We need to update it to start with files in the A Priori list and
+ // then the remaining files in PEIM order.
+ //
+ PeiCoreCopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));
+ }
+ }
+ //
+ // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
+ // Instead, we can retrieve the file handles within this Fv from cachable data.
+ //
+ Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;
+ PeiCoreCopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));
+
+}
+
+
+VOID
+PeiDispatcher (
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN PEI_CORE_INSTANCE *Private
+ )
+/*++
+
+Routine Description:
+
+ Conduct PEIM dispatch.
+
+Arguments:
+
+ SecCoreData - Information and services provided by SEC phase.
+ Private - Pointer to the private data passed in from caller
+
+Returns:
+
+ EFI_SUCCESS - Successfully dispatched PEIM.
+ EFI_NOT_FOUND - The dispatch failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Index1;
+ UINT32 Index2;
+ EFI_PEI_SERVICES **PeiServices;
+ VOID *PrivateInMem;
+ EFI_PEI_FV_HANDLE VolumeHandle;
+ EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
+ EFI_PEI_FILE_HANDLE PeimFileHandle;
+ UINTN FvCount;
+ UINTN PeimCount;
+ UINT32 AuthenticationState;
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+ EFI_PEIM_ENTRY_POINT PeimEntryPoint;
+ VOID* PeiCoreReentryPoint;
+ UINTN SaveCurrentPeimCount;
+ UINTN SaveCurrentFvCount;
+ EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
+
+ PEI_REPORT_STATUS_CODE_CODE (
+
+ EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
+
+ ExtendedData.DataHeader.HeaderSize = (UINT16)sizeof (EFI_STATUS_CODE_DATA);
+ ExtendedData.DataHeader.Size = (UINT16)(sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - ExtendedData.DataHeader.HeaderSize);
+
+ PeiCoreCopyMem (
+ &ExtendedData.DataHeader.Type,
+ &gEfiStatusCodeSpecificDataGuid,
+ sizeof (EFI_GUID)
+ );
+ )
+
+ PeiServices = &Private->PS;
+ PeimEntryPoint = NULL;
+ PeimFileHandle = NULL;
+
+ if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
+ // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
+ //
+ SaveCurrentPeimCount = Private->CurrentPeimCount;
+ SaveCurrentFvCount = Private->CurrentPeimFvCount;
+ SaveCurrentFileHandle = Private->CurrentFileHandle;
+
+ for (Index1 = 0;Index1 <= SaveCurrentFvCount; Index1++) {
+ for (Index2 = 0; (Index2 < PEI_CORE_MAX_PEIM_PER_FV) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
+ if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
+ PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
+ Status = PeiLoadImage (
+ &Private->PS,
+ PeimFileHandle,
+ &EntryPoint,
+ &AuthenticationState
+ );
+ if (Status == EFI_SUCCESS) {
+ //
+ // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
+ //
+ Private->Fv[Index1].PeimState[Index2]++;
+ Private->CurrentFileHandle = PeimFileHandle;
+ Private->CurrentPeimFvCount = Index1;
+ Private->CurrentPeimCount = Index2;
+
+ //
+ // Call the PEIM entry point
+ //
+ PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;
+
+ PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
+ PeimEntryPoint(PeimFileHandle, &Private->PS);
+ PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
+ }
+
+ //
+ // Process the Notify list and dispatch any notifies for
+ // newly installed PPIs.
+ //
+ ProcessNotifyList (&Private->PS);
+ }
+ }
+ }
+ Private->CurrentFileHandle = SaveCurrentFileHandle;
+ Private->CurrentPeimFvCount = SaveCurrentFvCount;
+ Private->CurrentPeimCount = SaveCurrentPeimCount;
+ }
+
+ //
+ // This is the main dispatch loop. It will search known FVs for PEIMs and
+ // attempt to dispatch them. If any PEIM gets dispatched through a single
+ // pass of the dispatcher, it will start over from the Bfv again to see
+ // if any new PEIMs dependencies got satisfied. With a well ordered
+ // FV where PEIMs are found in the order their dependencies are also
+ // satisfied, this dipatcher should run only once.
+ //
+ do {
+ //
+ // In case that reenter PeiCore happens, the last pass record is still available.
+ //
+ if (!Private->PeimDispatcherReenter) {
+ Private->PeimNeedingDispatch = FALSE;
+ Private->PeimDispatchOnThisPass = FALSE;
+ } else {
+ Private->PeimDispatcherReenter = FALSE;
+ }
+ for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
+ Private->CurrentPeimFvCount = FvCount;
+ VolumeHandle = Private->Fv[FvCount].FvHeader;
+
+ if (Private->CurrentPeimCount == 0) {
+ //
+ // When going through each FV, at first, search Apriori file to
+ // reorder all PEIMs to ensure the PEIMs in Apriori file to get
+ // dispatch at first.
+ //
+ DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle);
+ }
+
+ //
+ // Start to dispatch all modules within the current Fv.
+ //
+ for (PeimCount = Private->CurrentPeimCount;
+ (PeimCount < PEI_CORE_MAX_PEIM_PER_FV) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
+ PeimCount++) {
+ Private->CurrentPeimCount = PeimCount;
+ PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
+
+ if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
+ if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
+ Private->PeimNeedingDispatch = TRUE;
+ } else {
+ Status = PeiLoadImage (
+ PeiServices,
+ PeimFileHandle,
+ &EntryPoint,
+ &AuthenticationState
+ );
+ if ((Status == EFI_SUCCESS)) {
+ //
+ // The PEIM has its dependencies satisfied, and its entry point
+ // has been found, so invoke it.
+ //
+ PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
+
+ PEI_REPORT_STATUS_CODE_CODE (
+ ExtendedData.Handle = PeimFileHandle;
+ )
+
+ PEI_REPORT_STATUS_CODE_CODE (
+ PeiReportStatusCode (
+ PeiServices,
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN,
+ 0,
+ NULL,
+ (EFI_STATUS_CODE_DATA *)(&ExtendedData)
+ );
+ )
+
+ Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);
+ if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {
+ //
+ // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
+ //
+ Private->Fv[FvCount].PeimState[PeimCount]++;
+
+ //
+ // Call the PEIM entry point
+ //
+ PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;
+ PeimEntryPoint (PeimFileHandle, PeiServices);
+ Private->PeimDispatchOnThisPass = TRUE;
+ }
+
+ PEI_REPORT_STATUS_CODE_CODE (
+ PeiReportStatusCode (
+ PeiServices,
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END,
+ 0,
+ NULL,
+ (EFI_STATUS_CODE_DATA *)(&ExtendedData)
+ );
+ )
+ PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
+ }
+
+ //
+ // Process the Notify list and dispatch any notifies for
+ // newly installed PPIs.
+ //
+ ProcessNotifyList (PeiServices);
+
+ //
+ // If permanent memory was discovered and installed by this
+ // PEIM, shadow PEI Core and switch the stacks to the new memory.
+ //
+ if (Private->SwitchStackSignal) {
+
+ //
+ // Make sure we don't retry the same PEIM that added memory
+ //
+ Private->CurrentPeimCount++;
+
+ //
+ // Indicate that PeiCore reenter
+ //
+ Private->PeimDispatcherReenter = TRUE;
+ //
+ // Migrate IDT from CAR into real memory, so after stack switches to
+ // the new memory, the caller can get memory version PeiServiceTable.
+ //
+ MigrateIdtTable (PeiServices);
+ //
+ // Since we are at dispatch level, only the Core's private data
+ // is preserved, nobody else should have any data on the stack.
+ // So we need to copy PEI core instance data to memory.
+ //
+ Status = PeiAllocatePool (PeiServices, sizeof (PEI_CORE_INSTANCE), &PrivateInMem);
+ ASSERT_PEI_ERROR (PeiServices, Status);
+ PeiCoreCopyMem (PrivateInMem, Private, sizeof (PEI_CORE_INSTANCE));
+
+ //
+ // Shadow PEI Core. When permanent memory is avaiable, shadow
+ // PEI Core and PEIMs to get high performance.
+ //
+ PeiCoreFileHandle = NULL;
+ //
+ // Find the PEI Core in the BFV
+ //
+ Status = PeiFindFileEx (
+ (EFI_PEI_FV_HANDLE)Private->Fv[0].FvHeader,
+ NULL,
+ EFI_FV_FILETYPE_PEI_CORE,
+ &PeiCoreFileHandle,
+ NULL
+ );
+ ASSERT_PEI_ERROR (PeiServices, Status);
+
+ //
+ // Shadow PEI Core into memory so it will run faster
+ //
+ Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState);
+ ASSERT_PEI_ERROR (PeiServices, Status);
+
+ //
+ // The 2nd time around we need to call PeiCore passing in a non
+ // NULL value to OldCoreData. We can not call the PE COFF entry
+ // point (_EntryPoint) as it had codes a NULL into OldCoreData.
+ // We calculate the memory (shadowed) address of PeiCore by
+ // figuring out the offset from _EntryPoint to PeiCore and then
+ // adding that value to the new memory based entry point.
+ //
+ PeiCoreReentryPoint = (VOID*)(UINTN)(EntryPoint +
+//*** AMI PORTING BEGIN ***//
+// (((UINT8 *)(UINTN)PeiCore) - (UINT8 *)(UINTN)PeiMain));
+ (((UINT8 *)(UINTN)PeiCore) - (UINT8 *)(UINTN)PeiCoreEntry));
+//*** AMI PORTING END ***//
+
+
+ //
+ // Switch to memory based stack and reenter PEI Core that has been
+ // shadowed to memory.
+ //
+ SwitchCoreStacks (
+ PeiCoreReentryPoint,
+ (UINTN)SecCoreData,
+ (UINTN)NULL,
+ (UINTN)PrivateInMem,
+ (VOID*)((UINTN)Private->StackBase + (UINTN)Private->StackSize - 0x10)
+ );
+ }
+
+ if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // If memory is availble we shadow images by default for performance reasons.
+ // We call the entry point a 2nd time so the module knows it's shadowed.
+ //
+ PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
+ PeimEntryPoint (PeimFileHandle, PeiServices);
+ PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
+
+ //
+ // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
+ //
+ Private->Fv[FvCount].PeimState[PeimCount]++;
+
+ //
+ // Process the Notify list and dispatch any notifies for
+ // newly installed PPIs.
+ //
+ ProcessNotifyList (PeiServices);
+ }
+ }
+ }
+ }
+
+ //
+ // We set to NULL here to optimize the 2nd entry to this routine after
+ // memory is found. This reprevents rescanning of the FV. We set to
+ // NULL here so we start at the begining of the next FV
+ //
+ Private->CurrentFileHandle = NULL;
+ Private->CurrentPeimCount = 0;
+ //
+ // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
+ //
+ PeiCoreSetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);
+ }
+
+ //
+ // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
+ // through all the FV.
+ //
+ Private->CurrentPeimFvCount = 0;
+
+ //
+ // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
+ // dispatched. So we need to make another pass
+ //
+ // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
+ // pass. If we did not dispatch a PEIM there is no point in trying again
+ // as it will fail the next time too (nothing has changed).
+ //
+ } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
+
+//*** AMI PORTING BEGIN ***//
+ // Print out a list of the PEIMs that were not dispatched
+ PEI_DEBUG_CODE
+ (
+ {
+ UINTN i = 0;
+ UINTN j = 0;
+
+ for(i = 0; i < PEI_CORE_MAX_FV_SUPPORTED; i++)
+ {
+ for(j = 0; j < PEI_CORE_MAX_PEIM_PER_FV; j++)
+ {
+ if( Private->Fv[i].FvFileHandles[j] == NULL) continue;
+
+ if(Private->Fv[i].PeimState[j] == PEIM_STATE_NOT_DISPATCHED)
+ PEI_DEBUG((&Private->PS, -1, "WARNING -> PEIM Not Dispatched: %g\n", &((EFI_FFS_FILE_HEADER*)(Private->Fv[i].FvFileHandles[j]))->Name ));
+ }
+ }
+ }
+ )
+//*** AMI PORTING END *****//
+}
+
+
+VOID
+InitializeDispatcherData (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN PEI_CORE_INSTANCE *OldCoreData,
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
+ )
+/*++
+
+Routine Description:
+
+ Initialize the Dispatcher's data members
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ OldCoreData - Pointer to old core data (before switching stack).
+ NULL if being run in non-permament memory mode.
+ SecCoreData - Information and services provided by SEC phase.
+
+Returns:
+
+ None.
+
+--*/
+{
+ if (OldCoreData == NULL) {
+ PeiInitializeFv (PrivateData, SecCoreData);
+ }
+
+ return;
+}
+
+
+BOOLEAN
+DepexSatisfied (
+ IN PEI_CORE_INSTANCE *Private,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN UINTN PeimCount
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the Dependency Expression, if available, and
+ decides if the module can be executed.
+
+Arguments:
+
+ Private - Pointer to the private data passed in from caller.
+ FileHandle - File handle of PEIM.
+ PeimCount - The PEIM sequence in one FV.
+
+Returns:
+ TRUE - Can be dispatched
+ FALSE - Cannot be dispatched
+
+--*/
+{
+ EFI_STATUS Status;
+ INT8 *DepexData;
+
+ if (PeimCount < Private->AprioriCount) {
+ //
+ // If its in the A priori file then we set Depex to TRUE
+ //
+ return TRUE;
+ }
+
+ Status = PeiFfsFindSectionData (&Private->PS, EFI_SECTION_PEI_DEPEX, FileHandle, &DepexData);
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is no DEPEX, assume the module can be executed
+ //
+ return TRUE;
+ }
+
+ //
+ // Evaluate a given DEPEX
+ //
+ return PeimDispatchReadiness (&Private->PS, DepexData);
+}
+
+
+EFI_STATUS
+EFIAPI
+PeiRegisterForShadow (
+ IN EFI_PEI_FILE_HANDLE FileHandle
+ )
+/*++
+
+Routine Description:
+
+ This routine enable a PEIM to register itself to shadow when PEI Foundation
+ discovery permanent memory.
+
+Arguments:
+ FileHandle - File handle of a PEIM.
+
+Returns:
+ EFI_NOT_FOUND - The file handle doesn't point to PEIM itself.
+ EFI_ALREADY_STARTED - Indicate that the PEIM has been registered itself.
+ EFI_SUCCESS - Successfully to register itself.
+
+--*/
+{
+ PEI_CORE_INSTANCE *Private;
+ Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
+
+ if (Private->CurrentFileHandle != FileHandle) {
+ //
+ // The FileHandle must be for the current PEIM
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {
+ //
+ // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
+ //
+ return EFI_ALREADY_STARTED;
+ }
+
+ Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;
+
+ return EFI_SUCCESS;
+}
+
+
+