__FUNCTION__ is a pre-standard extension that gcc and Visual C++ among others support, while __func__ was standardized in C99. Since it's more standard, replace __FUNCTION__ with __func__ throughout MdeModulePkg. Signed-off-by: Rebecca Cran <rebecca@bsdio.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
		
			
				
	
	
		
			1485 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1485 lines
		
	
	
		
			50 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 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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_SMM_DXE,
 | 
						|
  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.
 | 
						|
  @param  Type                  Fv File Type of file 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,
 | 
						|
  IN  EFI_FV_FILETYPE                Type
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).
 | 
						|
 | 
						|
  @param  Fv                    The FIRMWARE_VOLUME protocol installed on the FV.
 | 
						|
  @param  FvHandle              The handle which FVB protocol installed on.
 | 
						|
  @param  FileName              The file name guid specified.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory or other resource.
 | 
						|
  @retval EFI_SUCCESS           Function successfully returned.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CoreProcessFvImageFile (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,
 | 
						|
  IN  EFI_HANDLE                     FvHandle,
 | 
						|
  IN  EFI_GUID                       *FileName
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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 ();
 | 
						|
 | 
						|
      DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_SUCCESS\n", DriverName));
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_NOT_FOUND\n", DriverName));
 | 
						|
 | 
						|
  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;
 | 
						|
  EFI_EVENT              DxeDispatchEvent;
 | 
						|
 | 
						|
  PERF_FUNCTION_BEGIN ();
 | 
						|
 | 
						|
  if (gDispatcherRunning) {
 | 
						|
    //
 | 
						|
    // If the dispatcher is running don't let it be restarted.
 | 
						|
    //
 | 
						|
    return EFI_ALREADY_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  gDispatcherRunning = TRUE;
 | 
						|
 | 
						|
  Status = CoreCreateEventEx (
 | 
						|
             EVT_NOTIFY_SIGNAL,
 | 
						|
             TPL_NOTIFY,
 | 
						|
             EfiEventEmptyFunction,
 | 
						|
             NULL,
 | 
						|
             &gEfiEventDxeDispatchGuid,
 | 
						|
             &DxeDispatchEvent
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  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) && !DriverEntry->IsFvImage) {
 | 
						|
        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 ();
 | 
						|
 | 
						|
      if (DriverEntry->IsFvImage) {
 | 
						|
        //
 | 
						|
        // Produce a firmware volume block protocol for FvImage so it gets dispatched from.
 | 
						|
        //
 | 
						|
        Status = CoreProcessFvImageFile (DriverEntry->Fv, DriverEntry->FvHandle, &DriverEntry->FileName);
 | 
						|
      } else {
 | 
						|
        REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
 | 
						|
          EFI_PROGRESS_CODE,
 | 
						|
          (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN),
 | 
						|
          &DriverEntry->ImageHandle,
 | 
						|
          sizeof (DriverEntry->ImageHandle)
 | 
						|
          );
 | 
						|
        ASSERT (DriverEntry->ImageHandle != NULL);
 | 
						|
 | 
						|
        Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);
 | 
						|
 | 
						|
        REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
 | 
						|
          EFI_PROGRESS_CODE,
 | 
						|
          (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END),
 | 
						|
          &DriverEntry->ImageHandle,
 | 
						|
          sizeof (DriverEntry->ImageHandle)
 | 
						|
          );
 | 
						|
      }
 | 
						|
 | 
						|
      ReturnStatus = EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Now DXE Dispatcher finished one round of dispatch, signal an event group
 | 
						|
    // so that SMM Dispatcher get chance to dispatch SMM Drivers which depend
 | 
						|
    // on UEFI protocols
 | 
						|
    //
 | 
						|
    if (!EFI_ERROR (ReturnStatus)) {
 | 
						|
      CoreSignalEvent (DxeDispatchEvent);
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 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;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (DriverEntry->Unrequested) {
 | 
						|
          DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));
 | 
						|
          DEBUG ((DEBUG_DISPATCH, "  SOR                                             = Not Requested\n"));
 | 
						|
          DEBUG ((DEBUG_DISPATCH, "  RESULT = FALSE\n"));
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (ReadyToRun);
 | 
						|
 | 
						|
  //
 | 
						|
  // Close DXE dispatch Event
 | 
						|
  //
 | 
						|
  CoreCloseEvent (DxeDispatchEvent);
 | 
						|
 | 
						|
  gDispatcherRunning = FALSE;
 | 
						|
 | 
						|
  PERF_FUNCTION_END ();
 | 
						|
 | 
						|
  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 && (DriverEntry != InsertedDriverEntry)) {
 | 
						|
      DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));
 | 
						|
      DEBUG ((DEBUG_DISPATCH, "  BEFORE FFS(%g) = ", &DriverEntry->BeforeAfterGuid));
 | 
						|
      if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
 | 
						|
        //
 | 
						|
        // Recursively process BEFORE
 | 
						|
        //
 | 
						|
        DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));
 | 
						|
        CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
 | 
						|
      } else {
 | 
						|
        DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 && (DriverEntry != InsertedDriverEntry)) {
 | 
						|
      DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));
 | 
						|
      DEBUG ((DEBUG_DISPATCH, "  AFTER FFS(%g) = ", &DriverEntry->BeforeAfterGuid));
 | 
						|
      if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
 | 
						|
        //
 | 
						|
        // Recursively process AFTER
 | 
						|
        //
 | 
						|
        DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));
 | 
						|
        CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
 | 
						|
      } else {
 | 
						|
        DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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 if new
 | 
						|
  entry is different from one in mFvHandleList by checking FvImage Guid.
 | 
						|
  Items are never removed/freed from the mFvHandleList.
 | 
						|
 | 
						|
  @param  FvHandle              The handle of a FV that has been processed
 | 
						|
 | 
						|
  @return A point to new added FvHandle entry. If FvHandle with the same FvImage guid
 | 
						|
          has been added, NULL will return.
 | 
						|
 | 
						|
**/
 | 
						|
KNOWN_HANDLE *
 | 
						|
FvIsBeingProcessed (
 | 
						|
  IN  EFI_HANDLE  FvHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_GUID                            FvNameGuid;
 | 
						|
  BOOLEAN                             FvNameGuidIsFound;
 | 
						|
  UINT32                              ExtHeaderOffset;
 | 
						|
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;
 | 
						|
  EFI_FV_BLOCK_MAP_ENTRY              *BlockMap;
 | 
						|
  UINTN                               LbaOffset;
 | 
						|
  UINTN                               Index;
 | 
						|
  EFI_LBA                             LbaIndex;
 | 
						|
  LIST_ENTRY                          *Link;
 | 
						|
  KNOWN_HANDLE                        *KnownHandle;
 | 
						|
 | 
						|
  FwVolHeader = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the FirmwareVolumeBlock protocol on that handle
 | 
						|
  //
 | 
						|
  FvNameGuidIsFound = FALSE;
 | 
						|
  Status            = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Get the full FV header based on FVB protocol.
 | 
						|
    //
 | 
						|
    ASSERT (Fvb != NULL);
 | 
						|
    Status = GetFwVolHeader (Fvb, &FwVolHeader);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      ASSERT (FwVolHeader != NULL);
 | 
						|
      if (VerifyFvHeaderChecksum (FwVolHeader) && (FwVolHeader->ExtHeaderOffset != 0)) {
 | 
						|
        ExtHeaderOffset = (UINT32)FwVolHeader->ExtHeaderOffset;
 | 
						|
        BlockMap        = FwVolHeader->BlockMap;
 | 
						|
        LbaIndex        = 0;
 | 
						|
        LbaOffset       = 0;
 | 
						|
        //
 | 
						|
        // Find LbaIndex and LbaOffset for FV extension header based on BlockMap.
 | 
						|
        //
 | 
						|
        while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
 | 
						|
          for (Index = 0; Index < BlockMap->NumBlocks && ExtHeaderOffset >= BlockMap->Length; Index++) {
 | 
						|
            ExtHeaderOffset -= BlockMap->Length;
 | 
						|
            LbaIndex++;
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // Check whether FvExtHeader is crossing the multi block range.
 | 
						|
          //
 | 
						|
          if (Index < BlockMap->NumBlocks) {
 | 
						|
            LbaOffset = ExtHeaderOffset;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          BlockMap++;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Read FvNameGuid from FV extension header.
 | 
						|
        //
 | 
						|
        Status = ReadFvbData (Fvb, &LbaIndex, &LbaOffset, sizeof (FvNameGuid), (UINT8 *)&FvNameGuid);
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          FvNameGuidIsFound = TRUE;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      CoreFreePool (FwVolHeader);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (FvNameGuidIsFound) {
 | 
						|
    //
 | 
						|
    // Check whether the FV image with the found FvNameGuid has been processed.
 | 
						|
    //
 | 
						|
    for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
 | 
						|
      KnownHandle = CR (Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
 | 
						|
      if (CompareGuid (&FvNameGuid, &KnownHandle->FvNameGuid)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, &FvNameGuid));
 | 
						|
        return NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  KnownHandle = AllocateZeroPool (sizeof (KNOWN_HANDLE));
 | 
						|
  ASSERT (KnownHandle != NULL);
 | 
						|
 | 
						|
  KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
 | 
						|
  KnownHandle->Handle    = FvHandle;
 | 
						|
  if (FvNameGuidIsFound) {
 | 
						|
    CopyGuid (&KnownHandle->FvNameGuid, &FvNameGuid);
 | 
						|
  }
 | 
						|
 | 
						|
  InsertTailList (&mFvHandleList, &KnownHandle->Link);
 | 
						|
  return KnownHandle;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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.
 | 
						|
  @param  Type                  Fv File Type of file 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,
 | 
						|
  IN  EFI_FV_FILETYPE                Type
 | 
						|
  )
 | 
						|
{
 | 
						|
  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);
 | 
						|
  if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
 | 
						|
    DriverEntry->IsFvImage = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  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  FvNameGuid            The FV image guid specified.
 | 
						|
  @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  CONST EFI_GUID  *FvNameGuid,
 | 
						|
  IN  CONST EFI_GUID  *DriverName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS  HobFv2;
 | 
						|
 | 
						|
  HobFv2.Raw = GetHobList ();
 | 
						|
 | 
						|
  while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {
 | 
						|
    //
 | 
						|
    // Compare parent FvNameGuid and FileGuid both.
 | 
						|
    //
 | 
						|
    if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName) &&
 | 
						|
        CompareGuid (FvNameGuid, &HobFv2.FirmwareVolume2->FvName))
 | 
						|
    {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    HobFv2.Raw = GET_NEXT_HOB (HobFv2);
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find USED_SIZE FV_EXT_TYPE entry in FV extension header and get the FV used size.
 | 
						|
 | 
						|
  @param[in]  FvHeader      Pointer to FV header.
 | 
						|
  @param[out] FvUsedSize    Pointer to FV used size returned,
 | 
						|
                            only valid if USED_SIZE FV_EXT_TYPE entry is found.
 | 
						|
  @param[out] EraseByte     Pointer to erase byte returned,
 | 
						|
                            only valid if USED_SIZE FV_EXT_TYPE entry is found.
 | 
						|
 | 
						|
  @retval TRUE              USED_SIZE FV_EXT_TYPE entry is found,
 | 
						|
                            FV used size and erase byte are returned.
 | 
						|
  @retval FALSE             No USED_SIZE FV_EXT_TYPE entry found.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
GetFvUsedSize (
 | 
						|
  IN EFI_FIRMWARE_VOLUME_HEADER  *FvHeader,
 | 
						|
  OUT UINT32                     *FvUsedSize,
 | 
						|
  OUT UINT8                      *EraseByte
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT16                                        ExtHeaderOffset;
 | 
						|
  EFI_FIRMWARE_VOLUME_EXT_HEADER                *ExtHeader;
 | 
						|
  EFI_FIRMWARE_VOLUME_EXT_ENTRY                 *ExtEntryList;
 | 
						|
  EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE  *ExtEntryUsedSize;
 | 
						|
 | 
						|
  ExtHeaderOffset = ReadUnaligned16 (&FvHeader->ExtHeaderOffset);
 | 
						|
  if (ExtHeaderOffset != 0) {
 | 
						|
    ExtHeader    = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + ExtHeaderOffset);
 | 
						|
    ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)(ExtHeader + 1);
 | 
						|
    while ((UINTN)ExtEntryList < ((UINTN)ExtHeader + ReadUnaligned32 (&ExtHeader->ExtHeaderSize))) {
 | 
						|
      if (ReadUnaligned16 (&ExtEntryList->ExtEntryType) == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {
 | 
						|
        //
 | 
						|
        // USED_SIZE FV_EXT_TYPE entry is found.
 | 
						|
        //
 | 
						|
        ExtEntryUsedSize = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)ExtEntryList;
 | 
						|
        *FvUsedSize      = ReadUnaligned32 (&ExtEntryUsedSize->UsedSize);
 | 
						|
        if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ERASE_POLARITY) != 0) {
 | 
						|
          *EraseByte = 0xFF;
 | 
						|
        } else {
 | 
						|
          *EraseByte = 0;
 | 
						|
        }
 | 
						|
 | 
						|
        DEBUG ((
 | 
						|
          DEBUG_INFO,
 | 
						|
          "FV at 0x%x has 0x%x used size, and erase byte is 0x%02x\n",
 | 
						|
          FvHeader,
 | 
						|
          *FvUsedSize,
 | 
						|
          *EraseByte
 | 
						|
          ));
 | 
						|
        return TRUE;
 | 
						|
      }
 | 
						|
 | 
						|
      ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)
 | 
						|
                     ((UINT8 *)ExtEntryList + ReadUnaligned16 (&ExtEntryList->ExtEntrySize));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // No USED_SIZE FV_EXT_TYPE entry found.
 | 
						|
  //
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).
 | 
						|
 | 
						|
  @param  Fv                    The FIRMWARE_VOLUME protocol installed on the FV.
 | 
						|
  @param  FvHandle              The handle which FVB protocol installed on.
 | 
						|
  @param  FileName              The file name guid specified.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory or other resource.
 | 
						|
  @retval EFI_SUCCESS           Function successfully returned.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CoreProcessFvImageFile (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,
 | 
						|
  IN  EFI_HANDLE                     FvHandle,
 | 
						|
  IN  EFI_GUID                       *FileName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_SECTION_TYPE            SectionType;
 | 
						|
  UINT32                      AuthenticationStatus;
 | 
						|
  VOID                        *Buffer;
 | 
						|
  VOID                        *AlignedBuffer;
 | 
						|
  UINTN                       BufferSize;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
 | 
						|
  UINT32                      FvAlignment;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL    *FvFileDevicePath;
 | 
						|
  UINT32                      FvUsedSize;
 | 
						|
  UINT8                       EraseByte;
 | 
						|
  UINTN                       Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // Read firmware volume section(s)
 | 
						|
  //
 | 
						|
  SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
 | 
						|
 | 
						|
  Index = 0;
 | 
						|
  do {
 | 
						|
    FvHeader      = NULL;
 | 
						|
    FvAlignment   = 0;
 | 
						|
    Buffer        = NULL;
 | 
						|
    BufferSize    = 0;
 | 
						|
    AlignedBuffer = NULL;
 | 
						|
    Status        = Fv->ReadSection (
 | 
						|
                          Fv,
 | 
						|
                          FileName,
 | 
						|
                          SectionType,
 | 
						|
                          Index,
 | 
						|
                          &Buffer,
 | 
						|
                          &BufferSize,
 | 
						|
                          &AuthenticationStatus
 | 
						|
                          );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Evaluate the authentication status of the Firmware Volume through
 | 
						|
      // Security Architectural Protocol
 | 
						|
      //
 | 
						|
      if (gSecurity != NULL) {
 | 
						|
        FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, FileName);
 | 
						|
        Status           = gSecurity->FileAuthenticationState (
 | 
						|
                                        gSecurity,
 | 
						|
                                        AuthenticationStatus,
 | 
						|
                                        FvFileDevicePath
 | 
						|
                                        );
 | 
						|
        if (FvFileDevicePath != NULL) {
 | 
						|
          FreePool (FvFileDevicePath);
 | 
						|
        }
 | 
						|
 | 
						|
        if (Status != EFI_SUCCESS) {
 | 
						|
          //
 | 
						|
          // Security check failed. The firmware volume should not be used for any purpose.
 | 
						|
          //
 | 
						|
          if (Buffer != NULL) {
 | 
						|
            FreePool (Buffer);
 | 
						|
          }
 | 
						|
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // FvImage should be at its required alignment.
 | 
						|
      //
 | 
						|
      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Buffer;
 | 
						|
      //
 | 
						|
      // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
 | 
						|
      // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
 | 
						|
      // its initial linked location and maintain its alignment.
 | 
						|
      //
 | 
						|
      if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
 | 
						|
        //
 | 
						|
        // Get FvHeader alignment
 | 
						|
        //
 | 
						|
        FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);
 | 
						|
        //
 | 
						|
        // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
 | 
						|
        //
 | 
						|
        if (FvAlignment < 8) {
 | 
						|
          FvAlignment = 8;
 | 
						|
        }
 | 
						|
 | 
						|
        DEBUG ((
 | 
						|
          DEBUG_INFO,
 | 
						|
          "%a() FV at 0x%x, FvAlignment required is 0x%x\n",
 | 
						|
          __func__,
 | 
						|
          FvHeader,
 | 
						|
          FvAlignment
 | 
						|
          ));
 | 
						|
 | 
						|
        //
 | 
						|
        // Check FvImage alignment.
 | 
						|
        //
 | 
						|
        if ((UINTN)FvHeader % FvAlignment != 0) {
 | 
						|
          //
 | 
						|
          // Allocate the aligned buffer for the FvImage.
 | 
						|
          //
 | 
						|
          AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN)FvAlignment);
 | 
						|
          if (AlignedBuffer == NULL) {
 | 
						|
            FreePool (Buffer);
 | 
						|
            Status = EFI_OUT_OF_RESOURCES;
 | 
						|
            break;
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // Move FvImage into the aligned buffer and release the original buffer.
 | 
						|
            //
 | 
						|
            if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) {
 | 
						|
              //
 | 
						|
              // Copy the used bytes and fill the rest with the erase value.
 | 
						|
              //
 | 
						|
              CopyMem (AlignedBuffer, FvHeader, (UINTN)FvUsedSize);
 | 
						|
              SetMem (
 | 
						|
                (UINT8 *)AlignedBuffer + FvUsedSize,
 | 
						|
                (UINTN)(BufferSize - FvUsedSize),
 | 
						|
                EraseByte
 | 
						|
                );
 | 
						|
            } else {
 | 
						|
              CopyMem (AlignedBuffer, Buffer, BufferSize);
 | 
						|
            }
 | 
						|
 | 
						|
            FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AlignedBuffer;
 | 
						|
            FreePool (Buffer);
 | 
						|
            Buffer = NULL;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Produce a FVB protocol for the file
 | 
						|
      //
 | 
						|
      Status = ProduceFVBProtocolOnBuffer (
 | 
						|
                 (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
 | 
						|
                 (UINT64)BufferSize,
 | 
						|
                 FvHandle,
 | 
						|
                 AuthenticationStatus,
 | 
						|
                 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));
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    } else {
 | 
						|
      Index++;
 | 
						|
    }
 | 
						|
  } while (TRUE);
 | 
						|
 | 
						|
  if (Index > 0) {
 | 
						|
    //
 | 
						|
    // At least one FvImage has been processed successfully.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    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_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;
 | 
						|
  VOID                           *DepexBuffer;
 | 
						|
  KNOWN_HANDLE                   *KnownHandle;
 | 
						|
 | 
						|
  FvHandle = NULL;
 | 
						|
 | 
						|
  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.
 | 
						|
    //
 | 
						|
    KnownHandle = FvIsBeingProcessed (FvHandle);
 | 
						|
    if (KnownHandle == NULL) {
 | 
						|
      //
 | 
						|
      // The FV with the same FV name guid has already been processed.
 | 
						|
      // So lets skip it!
 | 
						|
      //
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
 | 
						|
    if (EFI_ERROR (Status) || (Fv == NULL)) {
 | 
						|
      //
 | 
						|
      // FvHandle must have Firmware Volume2 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;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 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 (&KnownHandle->FvNameGuid, &NameGuid)) {
 | 
						|
              continue;
 | 
						|
            }
 | 
						|
 | 
						|
            //
 | 
						|
            // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has SMM depex section.
 | 
						|
            //
 | 
						|
            DepexBuffer  = NULL;
 | 
						|
            SizeOfBuffer = 0;
 | 
						|
            Status       = Fv->ReadSection (
 | 
						|
                                 Fv,
 | 
						|
                                 &NameGuid,
 | 
						|
                                 EFI_SECTION_SMM_DEPEX,
 | 
						|
                                 0,
 | 
						|
                                 &DepexBuffer,
 | 
						|
                                 &SizeOfBuffer,
 | 
						|
                                 &AuthenticationStatus
 | 
						|
                                 );
 | 
						|
            if (!EFI_ERROR (Status)) {
 | 
						|
              //
 | 
						|
              // If SMM depex section is found, this FV image is invalid to be supported.
 | 
						|
              // ASSERT FALSE to report this FV image.
 | 
						|
              //
 | 
						|
              FreePool (DepexBuffer);
 | 
						|
              ASSERT (FALSE);
 | 
						|
            }
 | 
						|
 | 
						|
            //
 | 
						|
            // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has DXE depex section.
 | 
						|
            //
 | 
						|
            DepexBuffer  = NULL;
 | 
						|
            SizeOfBuffer = 0;
 | 
						|
            Status       = Fv->ReadSection (
 | 
						|
                                 Fv,
 | 
						|
                                 &NameGuid,
 | 
						|
                                 EFI_SECTION_DXE_DEPEX,
 | 
						|
                                 0,
 | 
						|
                                 &DepexBuffer,
 | 
						|
                                 &SizeOfBuffer,
 | 
						|
                                 &AuthenticationStatus
 | 
						|
                                 );
 | 
						|
            if (EFI_ERROR (Status)) {
 | 
						|
              //
 | 
						|
              // If no depex section, produce a firmware volume block protocol for it so it gets dispatched from.
 | 
						|
              //
 | 
						|
              CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);
 | 
						|
            } else {
 | 
						|
              //
 | 
						|
              // If depex section is found, this FV image will be dispatched until its depex is evaluated to TRUE.
 | 
						|
              //
 | 
						|
              FreePool (DepexBuffer);
 | 
						|
              CoreAddToDriverList (Fv, FvHandle, &NameGuid, Type);
 | 
						|
            }
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // Transition driver from Undiscovered to Discovered state
 | 
						|
            //
 | 
						|
            CoreAddToDriverList (Fv, FvHandle, &NameGuid, Type);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } 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.
 | 
						|
    //
 | 
						|
 | 
						|
    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))
 | 
						|
        {
 | 
						|
          CoreAcquireDispatcherLock ();
 | 
						|
          DriverEntry->Dependent = FALSE;
 | 
						|
          DriverEntry->Scheduled = TRUE;
 | 
						|
          InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
 | 
						|
          CoreReleaseDispatcherLock ();
 | 
						|
          DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));
 | 
						|
          DEBUG ((DEBUG_DISPATCH, "  RESULT = TRUE (Apriori)\n"));
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 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
 | 
						|
  )
 | 
						|
{
 | 
						|
  PERF_FUNCTION_BEGIN ();
 | 
						|
 | 
						|
  mFwVolEvent = EfiCreateProtocolNotifyEvent (
 | 
						|
                  &gEfiFirmwareVolume2ProtocolGuid,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  CoreFwVolEventProtocolNotify,
 | 
						|
                  NULL,
 | 
						|
                  &mFwVolEventRegistration
 | 
						|
                  );
 | 
						|
 | 
						|
  PERF_FUNCTION_END ();
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// 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));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |