summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Core/Pei/Dispatcher
diff options
context:
space:
mode:
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-04 07:51:48 +0000
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-04 07:51:48 +0000
commit192f6d4c29fa0dd595b8d5a36bd2078e1474aa4e (patch)
tree5f0afdc001df93627963ec0d4a94d8d2e388ffb8 /MdeModulePkg/Core/Pei/Dispatcher
parent6afbfebff49d81d833c08f94aaa2187b8a034525 (diff)
downloadedk2-192f6d4c29fa0dd595b8d5a36bd2078e1474aa4e.zip
edk2-192f6d4c29fa0dd595b8d5a36bd2078e1474aa4e.tar.gz
edk2-192f6d4c29fa0dd595b8d5a36bd2078e1474aa4e.tar.bz2
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
Diffstat (limited to 'MdeModulePkg/Core/Pei/Dispatcher')
-rw-r--r--MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c543
-rw-r--r--MdeModulePkg/Core/Pei/Dispatcher/Stack.c55
2 files changed, 598 insertions, 0 deletions
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
new file mode 100644
index 0000000..15b2360
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -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));
+}
+
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Stack.c b/MdeModulePkg/Core/Pei/Dispatcher/Stack.c
new file mode 100644
index 0000000..8895cae
--- /dev/null
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Stack.c
@@ -0,0 +1,55 @@
+/** @file
+ PeiSwitchStacks() function for PEI dispatcher.
+
+ Copyright (c) 2006, Intel Corporation<BR>
+ 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: String.c
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+/**
+ Transfers control to a function starting with a new stack.
+
+ Transfers control to the function specified by EntryPoint using the new stack
+ specified by NewStack and passing in the parameters specified by Context1 and
+ Context2. Context1 and Context2 are optional and may be NULL. The function
+ EntryPoint must never return.
+
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ @param EntryPoint A pointer to function to call with the new stack.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function.
+ @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
+ Reserved on other architectures.
+
+**/
+VOID
+EFIAPI
+PeiSwitchStacks (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack,
+ IN VOID *NewBsp
+ )
+{
+ SwitchStack (EntryPoint, Context1, Context2, NewStack);
+}