Currently our code has not such usage model, so Mike recommended us to retire this guid git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7593 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1164 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1164 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  DXE Dispatcher.
 | 
						|
 | 
						|
  Step #1 - When a FV protocol is added to the system every driver in the FV
 | 
						|
            is added to the mDiscoveredList. The SOR, Before, and After Depex are
 | 
						|
            pre-processed as drivers are added to the mDiscoveredList. If an Apriori
 | 
						|
            file exists in the FV those drivers are addeded to the
 | 
						|
            mScheduledQueue. The mFvHandleList is used to make sure a
 | 
						|
            FV is only processed once.
 | 
						|
 | 
						|
  Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and
 | 
						|
            start it. After mScheduledQueue is drained check the
 | 
						|
            mDiscoveredList to see if any item has a Depex that is ready to
 | 
						|
            be placed on the mScheduledQueue.
 | 
						|
 | 
						|
  Step #3 - Adding to the mScheduledQueue requires that you process Before
 | 
						|
            and After dependencies. This is done recursively as the call to add
 | 
						|
            to the mScheduledQueue checks for Before and recursively adds
 | 
						|
            all Befores. It then addes the item that was passed in and then
 | 
						|
            processess the After dependecies by recursively calling the routine.
 | 
						|
 | 
						|
  Dispatcher Rules:
 | 
						|
  The rules for the dispatcher are in chapter 10 of the DXE CIS. Figure 10-3
 | 
						|
  is the state diagram for the DXE dispatcher
 | 
						|
 | 
						|
  Depex - Dependency Expresion.
 | 
						|
  SOR   - Schedule On Request - Don't schedule if this bit is set.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2008, 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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "DxeMain.h"
 | 
						|
 | 
						|
//
 | 
						|
// The Driver List contains one copy of every driver that has been discovered.
 | 
						|
// Items are never removed from the driver list. List of EFI_CORE_DRIVER_ENTRY
 | 
						|
//
 | 
						|
LIST_ENTRY  mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList);
 | 
						|
 | 
						|
//
 | 
						|
// Queue of drivers that are ready to dispatch. This queue is a subset of the
 | 
						|
// mDiscoveredList.list of EFI_CORE_DRIVER_ENTRY.
 | 
						|
//
 | 
						|
LIST_ENTRY  mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
 | 
						|
 | 
						|
//
 | 
						|
// List of handles who's Fv's have been parsed and added to the mFwDriverList.
 | 
						|
//
 | 
						|
LIST_ENTRY  mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList);           // list of KNOWN_HANDLE
 | 
						|
 | 
						|
//
 | 
						|
// Lock for mDiscoveredList, mScheduledQueue, gDispatcherRunning.
 | 
						|
//
 | 
						|
EFI_LOCK  mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// Flag for the DXE Dispacher.  TRUE if dispatcher is execuing.
 | 
						|
//
 | 
						|
BOOLEAN  gDispatcherRunning = FALSE;
 | 
						|
 | 
						|
//
 | 
						|
// Module globals to manage the FwVol registration notification event
 | 
						|
//
 | 
						|
EFI_EVENT       mFwVolEvent;
 | 
						|
VOID            *mFwVolEventRegistration;
 | 
						|
 | 
						|
//
 | 
						|
// List of file types supported by dispatcher
 | 
						|
//
 | 
						|
EFI_FV_FILETYPE mDxeFileTypes[] = {
 | 
						|
  EFI_FV_FILETYPE_DRIVER,
 | 
						|
  EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,
 | 
						|
  EFI_FV_FILETYPE_DXE_CORE,
 | 
						|
  EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
 | 
						|
};
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   File;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL            End;
 | 
						|
} FV_FILEPATH_DEVICE_PATH;
 | 
						|
 | 
						|
FV_FILEPATH_DEVICE_PATH mFvDevicePath;
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// Function Prototypes
 | 
						|
//
 | 
						|
/**
 | 
						|
  Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
 | 
						|
  must add any driver with a before dependency on InsertedDriverEntry first.
 | 
						|
  You do this by recursively calling this routine. After all the Befores are
 | 
						|
  processed you can add InsertedDriverEntry to the mScheduledQueue.
 | 
						|
  Then you can add any driver with an After dependency on InsertedDriverEntry
 | 
						|
  by recursively calling this routine.
 | 
						|
 | 
						|
  @param  InsertedDriverEntry   The driver to insert on the ScheduledLink Queue
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
 | 
						|
  IN  EFI_CORE_DRIVER_ENTRY   *InsertedDriverEntry
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Event notification that is fired every time a FV dispatch protocol is added.
 | 
						|
  More than one protocol may have been added when this event is fired, so you
 | 
						|
  must loop on CoreLocateHandle () to see how many protocols were added and
 | 
						|
  do the following to each FV:
 | 
						|
  If the Fv has already been processed, skip it. If the Fv has not been
 | 
						|
  processed then mark it as being processed, as we are about to process it.
 | 
						|
  Read the Fv and add any driver in the Fv to the mDiscoveredList.The
 | 
						|
  mDiscoveredList is never free'ed and contains variables that define
 | 
						|
  the other states the DXE driver transitions to..
 | 
						|
  While you are at it read the A Priori file into memory.
 | 
						|
  Place drivers in the A Priori list onto the mScheduledQueue.
 | 
						|
 | 
						|
  @param  Event                 The Event that is being processed, not used.
 | 
						|
  @param  Context               Event Context, not used.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
CoreFwVolEventProtocolNotify (
 | 
						|
  IN  EFI_EVENT       Event,
 | 
						|
  IN  VOID            *Context
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Convert FvHandle and DriverName into an EFI device path
 | 
						|
 | 
						|
  @param  Fv                    Fv protocol, needed to read Depex info out of
 | 
						|
                                FLASH.
 | 
						|
  @param  FvHandle              Handle for Fv, needed in the
 | 
						|
                                EFI_CORE_DRIVER_ENTRY so that the PE image can be
 | 
						|
                                read out of the FV at a later time.
 | 
						|
  @param  DriverName            Name of driver to add to mDiscoveredList.
 | 
						|
 | 
						|
  @return Pointer to device path constructed from FvHandle and DriverName
 | 
						|
 | 
						|
**/
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
CoreFvToDevicePath (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
 | 
						|
  IN  EFI_HANDLE                      FvHandle,
 | 
						|
  IN  EFI_GUID                        *DriverName
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,
 | 
						|
  and initilize any state variables. Read the Depex from the FV and store it
 | 
						|
  in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.
 | 
						|
  The Discovered list is never free'ed and contains booleans that represent the
 | 
						|
  other possible DXE driver states.
 | 
						|
 | 
						|
  @param  Fv                    Fv protocol, needed to read Depex info out of
 | 
						|
                                FLASH.
 | 
						|
  @param  FvHandle              Handle for Fv, needed in the
 | 
						|
                                EFI_CORE_DRIVER_ENTRY so that the PE image can be
 | 
						|
                                read out of the FV at a later time.
 | 
						|
  @param  DriverName            Name of driver to add to mDiscoveredList.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           If driver was added to the mDiscoveredList.
 | 
						|
  @retval EFI_ALREADY_STARTED   The driver has already been started. Only one
 | 
						|
                                DriverName may be active in the system at any one
 | 
						|
                                time.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CoreAddToDriverList (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
 | 
						|
  IN  EFI_HANDLE                      FvHandle,
 | 
						|
  IN  EFI_GUID                        *DriverName
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.
 | 
						|
 | 
						|
  @param  Fv                    The FIRMWARE_VOLUME protocol installed on the FV.
 | 
						|
  @param  FvHandle              The handle which FVB protocol installed on.
 | 
						|
  @param  DriverName            The driver guid specified.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory or other resource.
 | 
						|
  @retval EFI_VOLUME_CORRUPTED  Corrupted volume.
 | 
						|
  @retval EFI_SUCCESS           Function successfully returned.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CoreProcessFvImageFile (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
 | 
						|
  IN  EFI_HANDLE                      FvHandle,
 | 
						|
  IN  EFI_GUID                        *DriverName
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Enter critical section by gaining lock on mDispatcherLock.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CoreAcquireDispatcherLock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  CoreAcquireLock (&mDispatcherLock);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Exit critical section by releasing lock on mDispatcherLock.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CoreReleaseDispatcherLock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  CoreReleaseLock (&mDispatcherLock);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Read Depex and pre-process the Depex for Before and After. If Section Extraction
 | 
						|
  protocol returns an error via ReadSection defer the reading of the Depex.
 | 
						|
 | 
						|
  @param  DriverEntry           Driver to work on.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Depex read and preprossesed
 | 
						|
  @retval EFI_PROTOCOL_ERROR    The section extraction protocol returned an error
 | 
						|
                                and  Depex reading needs to be retried.
 | 
						|
  @retval Error                 DEPEX not found.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CoreGetDepexSectionAndPreProccess (
 | 
						|
  IN  EFI_CORE_DRIVER_ENTRY   *DriverEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_SECTION_TYPE              SectionType;
 | 
						|
  UINT32                        AuthenticationStatus;
 | 
						|
  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
 | 
						|
 | 
						|
 | 
						|
  Fv = DriverEntry->Fv;
 | 
						|
 | 
						|
  //
 | 
						|
  // Grab Depex info, it will never be free'ed.
 | 
						|
  //
 | 
						|
  SectionType         = EFI_SECTION_DXE_DEPEX;
 | 
						|
  Status = Fv->ReadSection (
 | 
						|
                DriverEntry->Fv,
 | 
						|
                &DriverEntry->FileName,
 | 
						|
                SectionType,
 | 
						|
                0,
 | 
						|
                &DriverEntry->Depex,
 | 
						|
                (UINTN *)&DriverEntry->DepexSize,
 | 
						|
                &AuthenticationStatus
 | 
						|
                );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (Status == EFI_PROTOCOL_ERROR) {
 | 
						|
      //
 | 
						|
      // The section extraction protocol failed so set protocol error flag
 | 
						|
      //
 | 
						|
      DriverEntry->DepexProtocolError = TRUE;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // If no Depex assume UEFI 2.0 driver model
 | 
						|
      //
 | 
						|
      DriverEntry->Depex = NULL;
 | 
						|
      DriverEntry->Dependent = TRUE;
 | 
						|
      DriverEntry->DepexProtocolError = FALSE;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Set Before, After, and Unrequested state information based on Depex
 | 
						|
    // Driver will be put in Dependent or Unrequested state
 | 
						|
    //
 | 
						|
    CorePreProcessDepex (DriverEntry);
 | 
						|
    DriverEntry->DepexProtocolError = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Check every driver and locate a matching one. If the driver is found, the Unrequested
 | 
						|
  state flag is cleared.
 | 
						|
 | 
						|
  @param  FirmwareVolumeHandle  The handle of the Firmware Volume that contains
 | 
						|
                                the firmware  file specified by DriverName.
 | 
						|
  @param  DriverName            The Driver name to put in the Dependent state.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The DriverName was found and it's SOR bit was
 | 
						|
                                cleared
 | 
						|
  @retval EFI_NOT_FOUND         The DriverName does not exist or it's SOR bit was
 | 
						|
                                not set.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreSchedule (
 | 
						|
  IN  EFI_HANDLE  FirmwareVolumeHandle,
 | 
						|
  IN  EFI_GUID    *DriverName
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY            *Link;
 | 
						|
  EFI_CORE_DRIVER_ENTRY *DriverEntry;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check every driver
 | 
						|
  //
 | 
						|
  for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
 | 
						|
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
 | 
						|
    if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
 | 
						|
        DriverEntry->Unrequested &&
 | 
						|
        CompareGuid (DriverName, &DriverEntry->FileName)) {
 | 
						|
      //
 | 
						|
      // Move the driver from the Unrequested to the Dependent state
 | 
						|
      //
 | 
						|
      CoreAcquireDispatcherLock ();
 | 
						|
      DriverEntry->Unrequested  = FALSE;
 | 
						|
      DriverEntry->Dependent    = TRUE;
 | 
						|
      CoreReleaseDispatcherLock ();
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Convert a driver from the Untrused back to the Scheduled state.
 | 
						|
 | 
						|
  @param  FirmwareVolumeHandle  The handle of the Firmware Volume that contains
 | 
						|
                                the firmware  file specified by DriverName.
 | 
						|
  @param  DriverName            The Driver name to put in the Scheduled state
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The file was found in the untrusted state, and it
 | 
						|
                                was promoted  to the trusted state.
 | 
						|
  @retval EFI_NOT_FOUND         The file was not found in the untrusted state.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreTrust (
 | 
						|
  IN  EFI_HANDLE  FirmwareVolumeHandle,
 | 
						|
  IN  EFI_GUID    *DriverName
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY            *Link;
 | 
						|
  EFI_CORE_DRIVER_ENTRY *DriverEntry;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check every driver
 | 
						|
  //
 | 
						|
  for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
 | 
						|
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
 | 
						|
    if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
 | 
						|
        DriverEntry->Untrusted &&
 | 
						|
        CompareGuid (DriverName, &DriverEntry->FileName)) {
 | 
						|
      //
 | 
						|
      // Transition driver from Untrusted to Scheduled state.
 | 
						|
      //
 | 
						|
      CoreAcquireDispatcherLock ();
 | 
						|
      DriverEntry->Untrusted = FALSE;
 | 
						|
      DriverEntry->Scheduled = TRUE;
 | 
						|
      InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
 | 
						|
      CoreReleaseDispatcherLock ();
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This is the main Dispatcher for DXE and it exits when there are no more
 | 
						|
  drivers to run. Drain the mScheduledQueue and load and start a PE
 | 
						|
  image for each driver. Search the mDiscoveredList to see if any driver can
 | 
						|
  be placed on the mScheduledQueue. If no drivers are placed on the
 | 
						|
  mScheduledQueue exit the function. On exit it is assumed the Bds()
 | 
						|
  will be called, and when the Bds() exits the Dispatcher will be called
 | 
						|
  again.
 | 
						|
 | 
						|
  @retval EFI_ALREADY_STARTED   The DXE Dispatcher is already running
 | 
						|
  @retval EFI_NOT_FOUND         No DXE Drivers were dispatched
 | 
						|
  @retval EFI_SUCCESS           One or more DXE Drivers were dispatched
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreDispatcher (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_STATUS                      ReturnStatus;
 | 
						|
  LIST_ENTRY                      *Link;
 | 
						|
  EFI_CORE_DRIVER_ENTRY           *DriverEntry;
 | 
						|
  BOOLEAN                         ReadyToRun;
 | 
						|
 | 
						|
  if (gDispatcherRunning) {
 | 
						|
    //
 | 
						|
    // If the dispatcher is running don't let it be restarted.
 | 
						|
    //
 | 
						|
    return EFI_ALREADY_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  gDispatcherRunning = TRUE;
 | 
						|
 | 
						|
 | 
						|
  ReturnStatus = EFI_NOT_FOUND;
 | 
						|
  do {
 | 
						|
    //
 | 
						|
    // Drain the Scheduled Queue
 | 
						|
    //
 | 
						|
    while (!IsListEmpty (&mScheduledQueue)) {
 | 
						|
      DriverEntry = CR (
 | 
						|
                      mScheduledQueue.ForwardLink,
 | 
						|
                      EFI_CORE_DRIVER_ENTRY,
 | 
						|
                      ScheduledLink,
 | 
						|
                      EFI_CORE_DRIVER_ENTRY_SIGNATURE
 | 
						|
                      );
 | 
						|
 | 
						|
      //
 | 
						|
      // Load the DXE Driver image into memory. If the Driver was transitioned from
 | 
						|
      // Untrused to Scheduled it would have already been loaded so we may need to
 | 
						|
      // skip the LoadImage
 | 
						|
      //
 | 
						|
      if (DriverEntry->ImageHandle == NULL) {
 | 
						|
        DEBUG ((DEBUG_INFO, "Loading driver %g\n", &DriverEntry->FileName));
 | 
						|
        Status = CoreLoadImage (
 | 
						|
                        FALSE,
 | 
						|
                        gDxeCoreImageHandle,
 | 
						|
                        DriverEntry->FvFileDevicePath,
 | 
						|
                        NULL,
 | 
						|
                        0,
 | 
						|
                        &DriverEntry->ImageHandle
 | 
						|
                        );
 | 
						|
 | 
						|
        //
 | 
						|
        // Update the driver state to reflect that it's been loaded
 | 
						|
        //
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          CoreAcquireDispatcherLock ();
 | 
						|
 | 
						|
          if (Status == EFI_SECURITY_VIOLATION) {
 | 
						|
            //
 | 
						|
            // Take driver from Scheduled to Untrused state
 | 
						|
            //
 | 
						|
            DriverEntry->Untrusted = TRUE;
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // The DXE Driver could not be loaded, and do not attempt to load or start it again.
 | 
						|
            // Take driver from Scheduled to Initialized.
 | 
						|
            //
 | 
						|
            // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
 | 
						|
            //
 | 
						|
            DriverEntry->Initialized  = TRUE;
 | 
						|
          }
 | 
						|
 | 
						|
          DriverEntry->Scheduled = FALSE;
 | 
						|
          RemoveEntryList (&DriverEntry->ScheduledLink);
 | 
						|
 | 
						|
          CoreReleaseDispatcherLock ();
 | 
						|
 | 
						|
          //
 | 
						|
          // If it's an error don't try the StartImage
 | 
						|
          //
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      CoreAcquireDispatcherLock ();
 | 
						|
 | 
						|
      DriverEntry->Scheduled    = FALSE;
 | 
						|
      DriverEntry->Initialized  = TRUE;
 | 
						|
      RemoveEntryList (&DriverEntry->ScheduledLink);
 | 
						|
 | 
						|
      CoreReleaseDispatcherLock ();
 | 
						|
 | 
						|
 
 | 
						|
      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
 | 
						|
        EFI_PROGRESS_CODE,
 | 
						|
        FixedPcdGet32(PcdStatusCodeValueDxeDriverBegin),
 | 
						|
        &DriverEntry->ImageHandle,
 | 
						|
        sizeof (DriverEntry->ImageHandle)
 | 
						|
        );
 | 
						|
 | 
						|
      Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);
 | 
						|
 | 
						|
      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
 | 
						|
        EFI_PROGRESS_CODE,
 | 
						|
        FixedPcdGet32(PcdStatusCodeValueDxeDriverEnd),
 | 
						|
        &DriverEntry->ImageHandle,
 | 
						|
        sizeof (DriverEntry->ImageHandle)
 | 
						|
        );
 | 
						|
 | 
						|
      ReturnStatus = EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Search DriverList for items to place on Scheduled Queue
 | 
						|
    //
 | 
						|
    ReadyToRun = FALSE;
 | 
						|
    for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
 | 
						|
      DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
 | 
						|
 | 
						|
      if (DriverEntry->DepexProtocolError){
 | 
						|
        //
 | 
						|
        // If Section Extraction Protocol did not let the Depex be read before retry the read
 | 
						|
        //
 | 
						|
        Status = CoreGetDepexSectionAndPreProccess (DriverEntry);
 | 
						|
      }
 | 
						|
 | 
						|
      if (DriverEntry->Dependent) {
 | 
						|
        if (CoreIsSchedulable (DriverEntry)) {
 | 
						|
          CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
 | 
						|
          ReadyToRun = TRUE;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (ReadyToRun);
 | 
						|
 | 
						|
  gDispatcherRunning = FALSE;
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
 | 
						|
  must add any driver with a before dependency on InsertedDriverEntry first.
 | 
						|
  You do this by recursively calling this routine. After all the Befores are
 | 
						|
  processed you can add InsertedDriverEntry to the mScheduledQueue.
 | 
						|
  Then you can add any driver with an After dependency on InsertedDriverEntry
 | 
						|
  by recursively calling this routine.
 | 
						|
 | 
						|
  @param  InsertedDriverEntry   The driver to insert on the ScheduledLink Queue
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
 | 
						|
  IN  EFI_CORE_DRIVER_ENTRY   *InsertedDriverEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY            *Link;
 | 
						|
  EFI_CORE_DRIVER_ENTRY *DriverEntry;
 | 
						|
 | 
						|
  //
 | 
						|
  // Process Before Dependency
 | 
						|
  //
 | 
						|
  for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
 | 
						|
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
 | 
						|
    if (DriverEntry->Before && DriverEntry->Dependent) {
 | 
						|
      if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
 | 
						|
        //
 | 
						|
        // Recursively process BEFORE
 | 
						|
        //
 | 
						|
        CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert driver from Dependent to Scheduled state
 | 
						|
  //
 | 
						|
  CoreAcquireDispatcherLock ();
 | 
						|
 | 
						|
  InsertedDriverEntry->Dependent = FALSE;
 | 
						|
  InsertedDriverEntry->Scheduled = TRUE;
 | 
						|
  InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);
 | 
						|
 | 
						|
  CoreReleaseDispatcherLock ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Process After Dependency
 | 
						|
  //
 | 
						|
  for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
 | 
						|
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
 | 
						|
    if (DriverEntry->After && DriverEntry->Dependent) {
 | 
						|
      if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
 | 
						|
        //
 | 
						|
        // Recursively process AFTER
 | 
						|
        //
 | 
						|
        CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Return TRUE if the Fv has been processed, FALSE if not.
 | 
						|
 | 
						|
  @param  FvHandle              The handle of a FV that's being tested
 | 
						|
 | 
						|
  @retval TRUE                  Fv protocol on FvHandle has been processed
 | 
						|
  @retval FALSE                 Fv protocol on FvHandle has not yet been processed
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
FvHasBeenProcessed (
 | 
						|
  IN  EFI_HANDLE      FvHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY      *Link;
 | 
						|
  KNOWN_HANDLE    *KnownHandle;
 | 
						|
 | 
						|
  for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
 | 
						|
    KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
 | 
						|
    if (KnownHandle->Handle == FvHandle) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Remember that Fv protocol on FvHandle has had it's drivers placed on the
 | 
						|
  mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are
 | 
						|
  never removed/freed from the mFvHandleList.
 | 
						|
 | 
						|
  @param  FvHandle              The handle of a FV that has been processed
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FvIsBeingProcesssed (
 | 
						|
  IN  EFI_HANDLE    FvHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  KNOWN_HANDLE  *KnownHandle;
 | 
						|
 | 
						|
  KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));
 | 
						|
  ASSERT (KnownHandle != NULL);
 | 
						|
 | 
						|
  KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
 | 
						|
  KnownHandle->Handle = FvHandle;
 | 
						|
  InsertTailList (&mFvHandleList, &KnownHandle->Link);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Convert FvHandle and DriverName into an EFI device path
 | 
						|
 | 
						|
  @param  Fv                    Fv protocol, needed to read Depex info out of
 | 
						|
                                FLASH.
 | 
						|
  @param  FvHandle              Handle for Fv, needed in the
 | 
						|
                                EFI_CORE_DRIVER_ENTRY so that the PE image can be
 | 
						|
                                read out of the FV at a later time.
 | 
						|
  @param  DriverName            Name of driver to add to mDiscoveredList.
 | 
						|
 | 
						|
  @return Pointer to device path constructed from FvHandle and DriverName
 | 
						|
 | 
						|
**/
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
CoreFvToDevicePath (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
 | 
						|
  IN  EFI_HANDLE                      FvHandle,
 | 
						|
  IN  EFI_GUID                        *DriverName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL            *FvDevicePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL            *FileNameDevicePath;
 | 
						|
 | 
						|
  //
 | 
						|
  // Remember the device path of the FV
 | 
						|
  //
 | 
						|
  Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FileNameDevicePath = NULL;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Build a device path to the file in the FV to pass into gBS->LoadImage
 | 
						|
    //
 | 
						|
    EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
 | 
						|
    SetDevicePathEndNode (&mFvDevicePath.End);
 | 
						|
 | 
						|
    FileNameDevicePath = AppendDevicePath (
 | 
						|
                            FvDevicePath,
 | 
						|
                            (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
 | 
						|
                            );
 | 
						|
  }
 | 
						|
 | 
						|
  return FileNameDevicePath;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,
 | 
						|
  and initilize any state variables. Read the Depex from the FV and store it
 | 
						|
  in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.
 | 
						|
  The Discovered list is never free'ed and contains booleans that represent the
 | 
						|
  other possible DXE driver states.
 | 
						|
 | 
						|
  @param  Fv                    Fv protocol, needed to read Depex info out of
 | 
						|
                                FLASH.
 | 
						|
  @param  FvHandle              Handle for Fv, needed in the
 | 
						|
                                EFI_CORE_DRIVER_ENTRY so that the PE image can be
 | 
						|
                                read out of the FV at a later time.
 | 
						|
  @param  DriverName            Name of driver to add to mDiscoveredList.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           If driver was added to the mDiscoveredList.
 | 
						|
  @retval EFI_ALREADY_STARTED   The driver has already been started. Only one
 | 
						|
                                DriverName may be active in the system at any one
 | 
						|
                                time.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CoreAddToDriverList (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
 | 
						|
  IN  EFI_HANDLE                      FvHandle,
 | 
						|
  IN  EFI_GUID                        *DriverName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_CORE_DRIVER_ENTRY               *DriverEntry;
 | 
						|
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the Driver Entry for the list. ZeroPool initializes lots of variables to
 | 
						|
  // NULL or FALSE.
 | 
						|
  //
 | 
						|
  DriverEntry = AllocateZeroPool (sizeof (EFI_CORE_DRIVER_ENTRY));
 | 
						|
  ASSERT (DriverEntry != NULL);
 | 
						|
 | 
						|
  DriverEntry->Signature        = EFI_CORE_DRIVER_ENTRY_SIGNATURE;
 | 
						|
  CopyGuid (&DriverEntry->FileName, DriverName);
 | 
						|
  DriverEntry->FvHandle         = FvHandle;
 | 
						|
  DriverEntry->Fv               = Fv;
 | 
						|
  DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName);
 | 
						|
 | 
						|
  CoreGetDepexSectionAndPreProccess (DriverEntry);
 | 
						|
 | 
						|
  CoreAcquireDispatcherLock ();
 | 
						|
 | 
						|
  InsertTailList (&mDiscoveredList, &DriverEntry->Link);
 | 
						|
 | 
						|
  CoreReleaseDispatcherLock ();
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is
 | 
						|
  described by a EFI_HOB_FIRMWARE_VOLUME2 Hob.
 | 
						|
 | 
						|
  @param  FvHandle              The handle which FVB protocol installed on.
 | 
						|
  @param  DriverName            The driver guid specified.
 | 
						|
 | 
						|
  @retval TRUE                  This file is found in a EFI_HOB_FIRMWARE_VOLUME2
 | 
						|
                                Hob.
 | 
						|
  @retval FALSE                 Not found.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
FvFoundInHobFv2 (
 | 
						|
  IN  EFI_HANDLE                      FvHandle,
 | 
						|
  IN  CONST EFI_GUID                  *DriverName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS                HobFv2;
 | 
						|
 | 
						|
  HobFv2.Raw = GetHobList ();
 | 
						|
 | 
						|
  while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {
 | 
						|
    if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName)) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
    HobFv2.Raw = GET_NEXT_HOB (HobFv2);
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.
 | 
						|
 | 
						|
  @param  Fv                    The FIRMWARE_VOLUME protocol installed on the FV.
 | 
						|
  @param  FvHandle              The handle which FVB protocol installed on.
 | 
						|
  @param  DriverName            The driver guid specified.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory or other resource.
 | 
						|
  @retval EFI_VOLUME_CORRUPTED  Corrupted volume.
 | 
						|
  @retval EFI_SUCCESS           Function successfully returned.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CoreProcessFvImageFile (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
 | 
						|
  IN  EFI_HANDLE                      FvHandle,
 | 
						|
  IN  EFI_GUID                        *DriverName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_SECTION_TYPE                    SectionType;
 | 
						|
  UINT32                              AuthenticationStatus;
 | 
						|
  VOID                                *Buffer;
 | 
						|
  VOID                                *AlignedBuffer;
 | 
						|
  UINTN                               BufferSize;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER          *FvHeader;
 | 
						|
  UINT32                              FvAlignment;
 | 
						|
 | 
						|
  //
 | 
						|
  // Read the first (and only the first) firmware volume section
 | 
						|
  //
 | 
						|
  SectionType   = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
 | 
						|
  FvHeader      = NULL;
 | 
						|
  FvAlignment   = 0;
 | 
						|
  Buffer        = NULL;
 | 
						|
  BufferSize    = 0;
 | 
						|
  AlignedBuffer = NULL;
 | 
						|
  Status = Fv->ReadSection (
 | 
						|
                 Fv,
 | 
						|
                 DriverName,
 | 
						|
                 SectionType,
 | 
						|
                 0,
 | 
						|
                 &Buffer,
 | 
						|
                 &BufferSize,
 | 
						|
                 &AuthenticationStatus
 | 
						|
                 );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // FvImage should be at its required alignment.
 | 
						|
    //
 | 
						|
    FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;
 | 
						|
    FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
 | 
						|
    //
 | 
						|
    // FvAlignment must be more than 8 bytes required by FvHeader structure.
 | 
						|
    //
 | 
						|
    if (FvAlignment < 8) {
 | 
						|
      FvAlignment = 8;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Allocate the aligned buffer for the FvImage.
 | 
						|
    //
 | 
						|
    AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);
 | 
						|
    if (AlignedBuffer == NULL) {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Move FvImage into the aligned buffer and release the original buffer.
 | 
						|
      //
 | 
						|
      CopyMem (AlignedBuffer, Buffer, BufferSize);
 | 
						|
      CoreFreePool (Buffer);
 | 
						|
      Buffer = NULL;
 | 
						|
      //
 | 
						|
      // Produce a FVB protocol for the file
 | 
						|
      //
 | 
						|
      Status = ProduceFVBProtocolOnBuffer (
 | 
						|
                (EFI_PHYSICAL_ADDRESS) (UINTN) AlignedBuffer,
 | 
						|
                (UINT64)BufferSize,
 | 
						|
                FvHandle,
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // ReadSection or Produce FVB failed, Free data buffer
 | 
						|
    //
 | 
						|
    if (Buffer != NULL) {
 | 
						|
      FreePool (Buffer);
 | 
						|
    }
 | 
						|
 | 
						|
    if (AlignedBuffer != NULL) {
 | 
						|
      FreeAlignedPages (AlignedBuffer, EFI_SIZE_TO_PAGES (BufferSize));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Event notification that is fired every time a FV dispatch protocol is added.
 | 
						|
  More than one protocol may have been added when this event is fired, so you
 | 
						|
  must loop on CoreLocateHandle () to see how many protocols were added and
 | 
						|
  do the following to each FV:
 | 
						|
  If the Fv has already been processed, skip it. If the Fv has not been
 | 
						|
  processed then mark it as being processed, as we are about to process it.
 | 
						|
  Read the Fv and add any driver in the Fv to the mDiscoveredList.The
 | 
						|
  mDiscoveredList is never free'ed and contains variables that define
 | 
						|
  the other states the DXE driver transitions to..
 | 
						|
  While you are at it read the A Priori file into memory.
 | 
						|
  Place drivers in the A Priori list onto the mScheduledQueue.
 | 
						|
 | 
						|
  @param  Event                 The Event that is being processed, not used.
 | 
						|
  @param  Context               Event Context, not used.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
CoreFwVolEventProtocolNotify (
 | 
						|
  IN  EFI_EVENT       Event,
 | 
						|
  IN  VOID            *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_STATUS                    GetNextFileStatus;
 | 
						|
  EFI_STATUS                    SecurityStatus;
 | 
						|
  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *FvDevicePath;
 | 
						|
  EFI_HANDLE                    FvHandle;
 | 
						|
  UINTN                         BufferSize;
 | 
						|
  EFI_GUID                      NameGuid;
 | 
						|
  UINTN                         Key;
 | 
						|
  EFI_FV_FILETYPE               Type;
 | 
						|
  EFI_FV_FILE_ATTRIBUTES        Attributes;
 | 
						|
  UINTN                         Size;
 | 
						|
  EFI_CORE_DRIVER_ENTRY         *DriverEntry;
 | 
						|
  EFI_GUID                      *AprioriFile;
 | 
						|
  UINTN                         AprioriEntryCount;
 | 
						|
  UINTN                         Index;
 | 
						|
  LIST_ENTRY                    *Link;
 | 
						|
  UINT32                        AuthenticationStatus;
 | 
						|
  UINTN                         SizeOfBuffer;
 | 
						|
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    BufferSize = sizeof (EFI_HANDLE);
 | 
						|
    Status = CoreLocateHandle (
 | 
						|
               ByRegisterNotify,
 | 
						|
               NULL,
 | 
						|
               mFwVolEventRegistration,
 | 
						|
               &BufferSize,
 | 
						|
               &FvHandle
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // If no more notification events exit
 | 
						|
      //
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (FvHasBeenProcessed (FvHandle)) {
 | 
						|
      //
 | 
						|
      // This Fv has already been processed so lets skip it!
 | 
						|
      //
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Since we are about to process this Fv mark it as processed.
 | 
						|
    //
 | 
						|
    FvIsBeingProcesssed (FvHandle);
 | 
						|
 | 
						|
    Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // The Handle has a FirmwareVolumeDispatch protocol and should also contiain
 | 
						|
      // a FirmwareVolume protocol thus we should never get here.
 | 
						|
      //
 | 
						|
      ASSERT (FALSE);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // The Firmware volume doesn't have device path, can't be dispatched.
 | 
						|
      //
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Evaluate the authentication status of the Firmware Volume through
 | 
						|
    // Security Architectural Protocol
 | 
						|
    //
 | 
						|
    if (gSecurity != NULL) {
 | 
						|
      SecurityStatus = gSecurity->FileAuthenticationState (
 | 
						|
                                    gSecurity,
 | 
						|
                                    0,
 | 
						|
                                    FvDevicePath
 | 
						|
                                    );
 | 
						|
      if (SecurityStatus != EFI_SUCCESS) {
 | 
						|
        //
 | 
						|
        // Security check failed. The firmware volume should not be used for any purpose.
 | 
						|
        //
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Discover Drivers in FV and add them to the Discovered Driver List.
 | 
						|
    // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
 | 
						|
    //  EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core
 | 
						|
    //  EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb
 | 
						|
    //
 | 
						|
    for (Index = 0; Index < sizeof (mDxeFileTypes) / sizeof (EFI_FV_FILETYPE); Index++) {
 | 
						|
      //
 | 
						|
      // Initialize the search key
 | 
						|
      //
 | 
						|
      Key = 0;
 | 
						|
      do {
 | 
						|
        Type = mDxeFileTypes[Index];
 | 
						|
        GetNextFileStatus = Fv->GetNextFile (
 | 
						|
                                  Fv,
 | 
						|
                                  &Key,
 | 
						|
                                  &Type,
 | 
						|
                                  &NameGuid,
 | 
						|
                                  &Attributes,
 | 
						|
                                  &Size
 | 
						|
                                  );
 | 
						|
        if (!EFI_ERROR (GetNextFileStatus)) {
 | 
						|
          if (Type == EFI_FV_FILETYPE_DXE_CORE) {
 | 
						|
            //
 | 
						|
            // If this is the DXE core fill in it's DevicePath & DeviceHandle
 | 
						|
            //
 | 
						|
            if (gDxeCoreLoadedImage->FilePath == NULL) {
 | 
						|
              if (CompareGuid (&NameGuid, gDxeCoreFileName)) {
 | 
						|
                //
 | 
						|
                // Maybe One specail Fv cantains only one DXE_CORE module, so its device path must
 | 
						|
                // be initialized completely.
 | 
						|
                //
 | 
						|
                EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);
 | 
						|
                SetDevicePathEndNode (&mFvDevicePath.End);
 | 
						|
 | 
						|
                gDxeCoreLoadedImage->FilePath = DuplicateDevicePath (
 | 
						|
                                                  (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
 | 
						|
                                                  );
 | 
						|
                gDxeCoreLoadedImage->DeviceHandle = FvHandle;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
 | 
						|
            //
 | 
						|
            // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
 | 
						|
            // been extracted.
 | 
						|
            //
 | 
						|
            if (FvFoundInHobFv2 (FvHandle, &NameGuid)) {
 | 
						|
              continue;
 | 
						|
            }
 | 
						|
            //
 | 
						|
            // Found a firmware volume image. Produce a firmware volume block
 | 
						|
            // protocol for it so it gets dispatched from. This is usually a
 | 
						|
            // capsule.
 | 
						|
            //
 | 
						|
            CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // Transition driver from Undiscovered to Discovered state
 | 
						|
            //
 | 
						|
            CoreAddToDriverList (Fv, FvHandle, &NameGuid);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } while (!EFI_ERROR (GetNextFileStatus));
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
 | 
						|
    //
 | 
						|
    AprioriFile = NULL;
 | 
						|
    Status = Fv->ReadSection (
 | 
						|
                  Fv,
 | 
						|
                  &gAprioriGuid,
 | 
						|
                  EFI_SECTION_RAW,
 | 
						|
                  0,
 | 
						|
                  (VOID **)&AprioriFile,
 | 
						|
                  &SizeOfBuffer,
 | 
						|
                  &AuthenticationStatus
 | 
						|
                  );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
 | 
						|
    } else {
 | 
						|
      AprioriEntryCount = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
 | 
						|
    // drivers not in the current FV and these must be skipped since the a priori list
 | 
						|
    // is only valid for the FV that it resided in.
 | 
						|
    //
 | 
						|
    CoreAcquireDispatcherLock ();
 | 
						|
 | 
						|
    for (Index = 0; Index < AprioriEntryCount; Index++) {
 | 
						|
      for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
 | 
						|
        DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
 | 
						|
        if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&
 | 
						|
            (FvHandle == DriverEntry->FvHandle)) {
 | 
						|
          DriverEntry->Dependent = FALSE;
 | 
						|
          DriverEntry->Scheduled = TRUE;
 | 
						|
          InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CoreReleaseDispatcherLock ();
 | 
						|
 | 
						|
    //
 | 
						|
    // Free data allocated by Fv->ReadSection ()
 | 
						|
    //
 | 
						|
    CoreFreePool (AprioriFile);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize the dispatcher. Initialize the notification function that runs when
 | 
						|
  an FV2 protocol is added to the system.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CoreInitializeDispatcher (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mFwVolEvent = EfiCreateProtocolNotifyEvent (
 | 
						|
                  &gEfiFirmwareVolume2ProtocolGuid,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  CoreFwVolEventProtocolNotify,
 | 
						|
                  NULL,
 | 
						|
                  &mFwVolEventRegistration
 | 
						|
                  );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Function only used in debug builds
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Traverse the discovered list for any drivers that were discovered but not loaded
 | 
						|
  because the dependency experessions evaluated to false.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CoreDisplayDiscoveredNotDispatched (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                    *Link;
 | 
						|
  EFI_CORE_DRIVER_ENTRY         *DriverEntry;
 | 
						|
 | 
						|
  for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
 | 
						|
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
 | 
						|
    if (DriverEntry->Dependent) {
 | 
						|
      DEBUG ((DEBUG_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |