1) remove unused library class 2) remove unreferenced GUIDs git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2401 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			535 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			535 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| 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 <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];
 | |
|   REPORT_STATUS_CODE_LIBRARY_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) {
 | |
| 
 | |
|                 Status =  TempPtr.PeimEntry (
 | |
|                                     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));
 | |
| }
 | |
| 
 |