Add PeiCore module for enabling NT32Pkg, please attention this PeiCore does follows PI specification except some FV definitions.
Also the old definition of MdeModulePkg/Include/Ppi/LoadFile.h and EFI_PEI_STARTUP_DESCRIPTOR in MdePkg/Include/PiPei.h will be removed when enabling PI. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3029 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
543
MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Normal file
543
MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Normal file
@@ -0,0 +1,543 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, 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 common header file for this module.
|
||||
//
|
||||
#include "CommonHeader.h"
|
||||
|
||||
#include <PeiMain.h>
|
||||
|
||||
STATIC
|
||||
VOID *
|
||||
TransferOldDataToNewDataRange (
|
||||
IN PEI_CORE_INSTANCE *PrivateData
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
PeiDispatcher (
|
||||
IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,
|
||||
IN PEI_CORE_INSTANCE *PrivateData,
|
||||
IN PEI_CORE_DISPATCH_DATA *DispatchData
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Conduct PEIM dispatch.
|
||||
|
||||
Arguments:
|
||||
|
||||
PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR
|
||||
PrivateData - Pointer to the private data passed in from caller
|
||||
DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Successfully dispatched PEIM.
|
||||
EFI_NOT_FOUND - The dispatch failed.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PEI_CORE_TEMP_POINTERS TempPtr;
|
||||
UINTN PrivateDataInMem;
|
||||
BOOLEAN NextFvFound;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress;
|
||||
VOID *TopOfStack;
|
||||
//
|
||||
// Debug data for uninstalled Peim list
|
||||
//
|
||||
EFI_GUID DebugFoundPeimList[32];
|
||||
EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
|
||||
|
||||
//
|
||||
// save the Current FV Address so that we will not process it again if FindFv returns it later
|
||||
//
|
||||
DefaultFvAddress = DispatchData->BootFvAddress;
|
||||
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
for (;;) {
|
||||
//
|
||||
// This is the PEIM search loop. It will scan through all PEIMs it can find
|
||||
// looking for PEIMs to dispatch, and will dipatch them if they have not
|
||||
// already been dispatched and all of their dependencies are met.
|
||||
// If no more PEIMs can be found in this pass through all known FVs,
|
||||
// then it will break out of this loop.
|
||||
//
|
||||
for (;;) {
|
||||
|
||||
Status = FindNextPeim (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentFvAddress,
|
||||
&DispatchData->CurrentPeimAddress
|
||||
);
|
||||
|
||||
//
|
||||
// If we found a PEIM, check if it is dispatched. If so, go to the
|
||||
// next PEIM. If not, dispatch it if its dependencies are satisfied.
|
||||
// If its dependencies are not satisfied, go to the next PEIM.
|
||||
//
|
||||
if (Status == EFI_SUCCESS) {
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
|
||||
//
|
||||
// Fill list of found Peims for later list of those not installed
|
||||
//
|
||||
CopyMem (
|
||||
&DebugFoundPeimList[DispatchData->CurrentPeim],
|
||||
&DispatchData->CurrentPeimAddress->Name,
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
if (!Dispatched (
|
||||
DispatchData->CurrentPeim,
|
||||
DispatchData->DispatchedPeimBitMap
|
||||
)) {
|
||||
if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) {
|
||||
Status = PeiLoadImage (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentPeimAddress,
|
||||
&TempPtr.Raw
|
||||
);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
|
||||
//
|
||||
// The PEIM has its dependencies satisfied, and its entry point
|
||||
// has been found, so invoke it.
|
||||
//
|
||||
PERF_START (
|
||||
(VOID *) (UINTN) (DispatchData->CurrentPeimAddress),
|
||||
"PEIM",
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
//
|
||||
// BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE
|
||||
//
|
||||
ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress;
|
||||
|
||||
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
|
||||
EFI_PROGRESS_CODE,
|
||||
EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN,
|
||||
(VOID *)(&ExtendedData),
|
||||
sizeof (ExtendedData)
|
||||
);
|
||||
|
||||
//
|
||||
// Is this a authentic image
|
||||
//
|
||||
Status = VerifyPeim (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentPeimAddress
|
||||
);
|
||||
|
||||
if (Status != EFI_SECURITY_VIOLATION) {
|
||||
|
||||
//
|
||||
// BUGBUG: Before enable PI, we need cast EFI_FFS_FILE_HEADER* to EFI_PEI_FILE_HANDLE*
|
||||
// Because we use new MdePkg's definition, but they are binary compatible in fact.
|
||||
//
|
||||
Status = TempPtr.PeimEntry (
|
||||
(EFI_PEI_FILE_HANDLE*)DispatchData->CurrentPeimAddress,
|
||||
&PrivateData->PS
|
||||
);
|
||||
}
|
||||
|
||||
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
|
||||
EFI_PROGRESS_CODE,
|
||||
EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END,
|
||||
(VOID *)(&ExtendedData),
|
||||
sizeof (ExtendedData)
|
||||
);
|
||||
|
||||
PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 0);
|
||||
|
||||
//
|
||||
// Mark the PEIM as dispatched so we don't attempt to run it again
|
||||
//
|
||||
SetDispatched (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentPeim,
|
||||
&DispatchData->DispatchedPeimBitMap
|
||||
);
|
||||
|
||||
//
|
||||
// Process the Notify list and dispatch any notifies for
|
||||
// newly installed PPIs.
|
||||
//
|
||||
ProcessNotifyList (&PrivateData->PS);
|
||||
|
||||
//
|
||||
// If real system memory was discovered and installed by this
|
||||
// PEIM, switch the stacks to the new memory. Since we are
|
||||
// at dispatch level, only the Core's private data is preserved,
|
||||
// nobody else should have any data on the stack.
|
||||
//
|
||||
if (PrivateData->SwitchStackSignal) {
|
||||
TempPtr.PeiCore = (PEI_CORE_ENTRY_POINT)PeiCore;
|
||||
PrivateDataInMem = (UINTN) TransferOldDataToNewDataRange (PrivateData);
|
||||
ASSERT (PrivateDataInMem != 0);
|
||||
//
|
||||
// Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT
|
||||
//
|
||||
TopOfStack = (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - CPU_STACK_ALIGNMENT);
|
||||
TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
|
||||
|
||||
PeiSwitchStacks (
|
||||
(SWITCH_STACK_ENTRY_POINT)(UINTN)TempPtr.Raw,
|
||||
PeiStartupDescriptor,
|
||||
(VOID*)PrivateDataInMem,
|
||||
TopOfStack,
|
||||
(VOID*)(UINTN)PrivateData->StackBase
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DispatchData->CurrentPeim++;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// If we could not find another PEIM in the current FV, go try
|
||||
// the FindFv PPI to look in other FVs for more PEIMs. If we can
|
||||
// not locate the FindFv PPI, or if the FindFv PPI can not find
|
||||
// anymore FVs, then exit the PEIM search loop.
|
||||
//
|
||||
if (DispatchData->FindFv == NULL) {
|
||||
Status = PeiServicesLocatePpi (
|
||||
&gEfiFindFvPpiGuid,
|
||||
0,
|
||||
NULL,
|
||||
(VOID **)&DispatchData->FindFv
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
NextFvFound = FALSE;
|
||||
while (!NextFvFound) {
|
||||
Status = DispatchData->FindFv->FindFv (
|
||||
DispatchData->FindFv,
|
||||
&PrivateData->PS,
|
||||
&DispatchData->CurrentFv,
|
||||
&NextFvAddress
|
||||
);
|
||||
//
|
||||
// if there is no next fv, get out of this loop of finding FVs
|
||||
//
|
||||
if (Status != EFI_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
//
|
||||
// don't process the default Fv again. (we don't know the order in which the hobs were created)
|
||||
//
|
||||
if ((NextFvAddress != DefaultFvAddress) &&
|
||||
(NextFvAddress != DispatchData->CurrentFvAddress)) {
|
||||
|
||||
//
|
||||
// VerifyFv() is currently returns SUCCESS all the time, add code to it to
|
||||
// actually verify the given FV
|
||||
//
|
||||
Status = VerifyFv (NextFvAddress);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
NextFvFound = TRUE;
|
||||
DispatchData->CurrentFvAddress = NextFvAddress;
|
||||
DispatchData->CurrentPeimAddress = NULL;
|
||||
//
|
||||
// current PRIM number (CurrentPeim) must continue as is, don't reset it here
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// if there is no next fv, get out of this loop of dispatching PEIMs
|
||||
//
|
||||
if (!NextFvFound) {
|
||||
break;
|
||||
}
|
||||
//
|
||||
// continue in the inner for(;;) loop with a new FV;
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If all the PEIMs that we have found have been dispatched, then
|
||||
// there is nothing left to dispatch and we don't need to go search
|
||||
// through all PEIMs again.
|
||||
//
|
||||
if ((~(DispatchData->DispatchedPeimBitMap) &
|
||||
((1 << DispatchData->CurrentPeim)-1)) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if no more PEIMs that depex was satisfied
|
||||
//
|
||||
if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) {
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Case when Depex is not satisfied and has to traverse the list again
|
||||
//
|
||||
DispatchData->CurrentPeim = 0;
|
||||
DispatchData->CurrentPeimAddress = 0;
|
||||
DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap;
|
||||
|
||||
//
|
||||
// don't go back to the loop without making sure that the CurrentFvAddress is the
|
||||
// same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and
|
||||
// mess it up, always start processing the PEIMs from the default FV just like in the first time around.
|
||||
//
|
||||
DispatchData->CurrentFv = 0;
|
||||
DispatchData->CurrentFvAddress = DefaultFvAddress;
|
||||
}
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
//
|
||||
// Debug data for uninstalled Peim list
|
||||
//
|
||||
UINT32 DebugNotDispatchedBitmap;
|
||||
UINT8 DebugFoundPeimPoint;
|
||||
|
||||
DebugFoundPeimPoint = 0;
|
||||
//
|
||||
// Get bitmap of Peims that were not dispatched,
|
||||
//
|
||||
|
||||
DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1));
|
||||
//
|
||||
// Scan bitmap of Peims not installed and print GUIDS
|
||||
//
|
||||
while (DebugNotDispatchedBitmap != 0) {
|
||||
if ((DebugNotDispatchedBitmap & 1) != 0) {
|
||||
DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n",
|
||||
&DebugFoundPeimList[DebugFoundPeimPoint]
|
||||
));
|
||||
}
|
||||
DebugFoundPeimPoint++;
|
||||
DebugNotDispatchedBitmap >>= 1;
|
||||
}
|
||||
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
VOID
|
||||
InitializeDispatcherData (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN PEI_CORE_INSTANCE *OldCoreData,
|
||||
IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor
|
||||
)
|
||||
/*++
|
||||
|
||||
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.
|
||||
PeiStartupDescriptor - Information and services provided by SEC phase.
|
||||
|
||||
Returns:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
PEI_CORE_INSTANCE *PrivateData;
|
||||
|
||||
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
|
||||
|
||||
if (OldCoreData == NULL) {
|
||||
PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume;
|
||||
PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume;
|
||||
} else {
|
||||
|
||||
//
|
||||
// Current peim has been dispatched, but not count
|
||||
//
|
||||
PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
Dispatched (
|
||||
IN UINT8 CurrentPeim,
|
||||
IN UINT32 DispatchedPeimBitMap
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine checks to see if a particular PEIM has been dispatched during
|
||||
the PEI core dispatch.
|
||||
|
||||
Arguments:
|
||||
CurrentPeim - The PEIM/FV in the bit array to check.
|
||||
DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.
|
||||
|
||||
Returns:
|
||||
TRUE - PEIM already dispatched
|
||||
FALSE - Otherwise
|
||||
|
||||
--*/
|
||||
{
|
||||
return (BOOLEAN)((DispatchedPeimBitMap & (1 << CurrentPeim)) != 0);
|
||||
}
|
||||
|
||||
VOID
|
||||
SetDispatched (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN UINT8 CurrentPeim,
|
||||
OUT UINT32 *DispatchedPeimBitMap
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine sets a PEIM as having been dispatched once its entry
|
||||
point has been invoked.
|
||||
|
||||
Arguments:
|
||||
|
||||
PeiServices - The PEI core services table.
|
||||
CurrentPeim - The PEIM/FV in the bit array to check.
|
||||
DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Check if the total number of PEIMs exceed the bitmap.
|
||||
// CurrentPeim is 0-based
|
||||
//
|
||||
ASSERT (CurrentPeim < (sizeof (*DispatchedPeimBitMap) * 8));
|
||||
*DispatchedPeimBitMap |= (1 << CurrentPeim);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
DepexSatisfied (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN VOID *CurrentPeimAddress
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine parses the Dependency Expression, if available, and
|
||||
decides if the module can be executed.
|
||||
|
||||
Arguments:
|
||||
PeiServices - The PEI Service Table
|
||||
CurrentPeimAddress - Address of the PEIM Firmware File under investigation
|
||||
|
||||
Returns:
|
||||
TRUE - Can be dispatched
|
||||
FALSE - Cannot be dispatched
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
INT8 *DepexData;
|
||||
BOOLEAN Runnable;
|
||||
|
||||
Status = PeiServicesFfsFindSectionData (
|
||||
EFI_SECTION_PEI_DEPEX,
|
||||
CurrentPeimAddress,
|
||||
(VOID **)&DepexData
|
||||
);
|
||||
//
|
||||
// If there is no DEPEX, assume the module can be executed
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Evaluate a given DEPEX
|
||||
//
|
||||
Status = PeimDispatchReadiness (
|
||||
PeiServices,
|
||||
DepexData,
|
||||
&Runnable
|
||||
);
|
||||
|
||||
return Runnable;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID *
|
||||
TransferOldDataToNewDataRange (
|
||||
IN PEI_CORE_INSTANCE *PrivateData
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine transfers the contents of the pre-permanent memory
|
||||
PEI Core private data to a post-permanent memory data location.
|
||||
|
||||
Arguments:
|
||||
|
||||
PrivateData - Pointer to the current PEI Core private data pre-permanent memory
|
||||
|
||||
Returns:
|
||||
|
||||
Pointer to the PrivateData once the private data has been transferred to permanent memory
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range
|
||||
//
|
||||
return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE));
|
||||
}
|
||||
|
Reference in New Issue
Block a user