X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=EdkModulePkg%2FCore%2FDxe%2FDispatcher%2FDispatcher.c;fp=EdkModulePkg%2FCore%2FDxe%2FDispatcher%2FDispatcher.c;h=0000000000000000000000000000000000000000;hb=808def96aa4589fba9c2d0ea55837754a3b7a4f7;hp=9792a16485c2a05a2a51884bf2e1302002c415a0;hpb=9216450d1143056a50a5f916984a2d7faf590488;p=mirror_edk2.git diff --git a/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c b/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c deleted file mode 100644 index 9792a16485..0000000000 --- a/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c +++ /dev/null @@ -1,1170 +0,0 @@ -/*++ - -Copyright (c) 2006, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - Dispatcher.c - -Abstract: - - Tiano 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. - ---*/ - -#include - -// -// 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 -// -static 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 -// -STATIC -VOID -CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter ( - IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry - ); - -STATIC -VOID -EFIAPI -CoreFwVolEventProtocolNotify ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -STATIC -EFI_DEVICE_PATH_PROTOCOL * -CoreFvToDevicePath ( - IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, - IN EFI_HANDLE FvHandle, - IN EFI_GUID *DriverName - ); - -STATIC -EFI_STATUS -CoreAddToDriverList ( - IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, - IN EFI_HANDLE FvHandle, - IN EFI_GUID *DriverName - ); - -STATIC -EFI_STATUS -CoreProcessFvImageFile ( - IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, - IN EFI_HANDLE FvHandle, - IN EFI_GUID *DriverName - ); - -STATIC -VOID -CoreAcquireDispatcherLock ( - VOID - ) -/*++ - -Routine Description: - - Enter critical section by gaining lock on mDispatcherLock - -Arguments: - - None - -Returns: - - None - ---*/ - -{ - CoreAcquireLock (&mDispatcherLock); -} - -STATIC -VOID -CoreReleaseDispatcherLock ( - VOID - ) -/*++ - -Routine Description: - - Exit critical section by releasing lock on mDispatcherLock - -Arguments: - - None - -Returns: - - None - ---*/ -{ - CoreReleaseLock (&mDispatcherLock); -} - -STATIC -EFI_STATUS -CoreGetDepexSectionAndPreProccess ( - IN EFI_CORE_DRIVER_ENTRY *DriverEntry - ) -/*++ - -Routine Description: - - 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. - -Arguments: - - DriverEntry - Driver to work on. - -Returns: - - EFI_SUCCESS - Depex read and preprossesed - - EFI_PROTOCOL_ERROR - The section extraction protocol returned an error and - Depex reading needs to be retried. - - Other Error - DEPEX not found. - ---*/ -{ - EFI_STATUS Status; - EFI_SECTION_TYPE SectionType; - UINT32 AuthenticationStatus; - EFI_FIRMWARE_VOLUME_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 EFI 1.1 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; -} - -EFI_DXESERVICE -EFI_STATUS -EFIAPI -CoreSchedule ( - IN EFI_HANDLE FirmwareVolumeHandle, - IN EFI_GUID *DriverName - ) -/*++ - -Routine Description: - - Check every driver and locate a matching one. If the driver is found, the Unrequested - state flag is cleared. - -Arguments: - - FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware - file specified by DriverName. - - DriverName - The Driver name to put in the Dependent state. - -Returns: - - EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared - - EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set. - ---*/ -{ - 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; -} - - -EFI_DXESERVICE -EFI_STATUS -EFIAPI -CoreTrust ( - IN EFI_HANDLE FirmwareVolumeHandle, - IN EFI_GUID *DriverName - ) -/*++ - -Routine Description: - - Convert a driver from the Untrused back to the Scheduled state - -Arguments: - - FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware - file specified by DriverName. - - DriverName - The Driver name to put in the Scheduled state - -Returns: - - EFI_SUCCESS - The file was found in the untrusted state, and it was promoted - to the trusted state. - - EFI_NOT_FOUND - The file was not found in the untrusted state. - ---*/ -{ - 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; -} - - -EFI_DXESERVICE -EFI_STATUS -EFIAPI -CoreDispatcher ( - VOID - ) -/*++ - -Routine Description: - - 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. - -Arguments: - - NONE - -Returns: - - EFI_ALREADY_STARTED - The DXE Dispatcher is already running - - EFI_NOT_FOUND - No DXE Drivers were dispatched - - EFI_SUCCESS - One or more DXE Drivers were dispatched - ---*/ -{ - 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) { - 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 (); - - - CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle); - Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL); - CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, 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; -} - -STATIC -VOID -CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter ( - IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry - ) -/*++ - -Routine Description: - - 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. - -Arguments: - - InsertedDriverEntry - The driver to insert on the ScheduledLink Queue - -Returns: - - NONE - ---*/ -{ - 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); - } - } - } -} - -STATIC -BOOLEAN -FvHasBeenProcessed ( - IN EFI_HANDLE FvHandle - ) -/*++ - -Routine Description: - - Return TRUE if the Fv has been processed, FALSE if not. - -Arguments: - - FvHandle - The handle of a FV that's being tested - -Returns: - - TRUE - Fv protocol on FvHandle has been processed - - FALSE - Fv protocol on FvHandle has not yet been processed - ---*/ -{ - 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; -} - -STATIC -VOID -FvIsBeingProcesssed ( - IN EFI_HANDLE FvHandle - ) -/*++ - -Routine Description: - - 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. - -Arguments: - - FvHandle - The handle of a FV that has been processed - -Returns: - - None - ---*/ -{ - KNOWN_HANDLE *KnownHandle; - - KnownHandle = CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE)); - ASSERT (KnownHandle != NULL); - - KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE; - KnownHandle->Handle = FvHandle; - InsertTailList (&mFvHandleList, &KnownHandle->Link); -} - - - -STATIC -EFI_DEVICE_PATH_PROTOCOL * -CoreFvToDevicePath ( - IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, - IN EFI_HANDLE FvHandle, - IN EFI_GUID *DriverName - ) -/*++ - -Routine Description: - - Convert FvHandle and DriverName into an EFI device path - -Arguments: - - Fv - Fv protocol, needed to read Depex info out of FLASH. - - 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. - - DriverName - Name of driver to add to mDiscoveredList. - -Returns: - - Pointer to device path constructed from FvHandle and 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); - mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH; - mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; - SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL)); - - FileNameDevicePath = CoreAppendDevicePath ( - FvDevicePath, - (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath - ); - } - - return FileNameDevicePath; -} - - - -EFI_STATUS -CoreAddToDriverList ( - IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, - IN EFI_HANDLE FvHandle, - IN EFI_GUID *DriverName - ) -/*++ - -Routine Description: - - 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. - -Arguments: - - Fv - Fv protocol, needed to read Depex info out of FLASH. - - 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. - - DriverName - Name of driver to add to mDiscoveredList. - -Returns: - - EFI_SUCCESS - If driver was added to the mDiscoveredList. - - EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName - may be active in the system at any one time. - ---*/ -{ - EFI_CORE_DRIVER_ENTRY *DriverEntry; - - - // - // Create the Driver Entry for the list. ZeroPool initializes lots of variables to - // NULL or FALSE. - // - DriverEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY)); - ASSERT (DriverEntry != NULL); - - DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE; - CopyMem (&DriverEntry->FileName, DriverName, sizeof (EFI_GUID)); - DriverEntry->FvHandle = FvHandle; - DriverEntry->Fv = Fv; - DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName); - - CoreGetDepexSectionAndPreProccess (DriverEntry); - - CoreAcquireDispatcherLock (); - - InsertTailList (&mDiscoveredList, &DriverEntry->Link); - - CoreReleaseDispatcherLock (); - - return EFI_SUCCESS; -} - - - -EFI_STATUS -CoreProcessFvImageFile ( - IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, - IN EFI_HANDLE FvHandle, - IN EFI_GUID *DriverName - ) -/*++ - -Routine Description: - - Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle. - -Arguments: - - Fv - The FIRMWARE_VOLUME protocol installed on the FV. - FvHandle - The handle which FVB protocol installed on. - DriverName - The driver guid specified. - -Returns: - - EFI_OUT_OF_RESOURCES - No enough memory or other resource. - - EFI_VOLUME_CORRUPTED - Corrupted volume. - - EFI_SUCCESS - Function successfully returned. - - ---*/ -{ - EFI_STATUS Status; - EFI_SECTION_TYPE SectionType; - UINT32 AuthenticationStatus; - VOID *Buffer; - UINTN BufferSize; - - // - // Read the first (and only the first) firmware volume section - // - SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; - Buffer = NULL; - BufferSize = 0; - Status = Fv->ReadSection ( - Fv, - DriverName, - SectionType, - 0, - &Buffer, - &BufferSize, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - // - // Produce a FVB protocol for the file - // - Status = ProduceFVBProtocolOnBuffer ( - (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, - (UINT64)BufferSize, - FvHandle, - NULL - ); - } - - if (EFI_ERROR (Status) && (Buffer != NULL)) { - // - // ReadSection or Produce FVB failed, Free data buffer - // - CoreFreePool (Buffer); - - } - - return Status; -} - -STATIC -VOID -EFIAPI -CoreFwVolEventProtocolNotify ( - IN EFI_EVENT Event, - IN VOID *Context - ) -/*++ - -Routine Description: - - 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. - -Arguments: - - Event - The Event that is being processed, not used. - - Context - Event Context, not used. - -Returns: - - None - ---*/ -{ - EFI_STATUS Status; - EFI_STATUS GetNextFileStatus; - EFI_STATUS SecurityStatus; - EFI_FIRMWARE_VOLUME_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; - } - - Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, (VOID **)&Fv); - if (EFI_ERROR (Status)) { - // - // If no dispatch protocol then skip, but do not marked as being processed as it - // may show up later. - // - continue; - } - - // - // Since we are about to process this Fv mark it as processed. - // - FvIsBeingProcesssed (FvHandle); - - - Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeProtocolGuid, (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); - mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH; - mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; - SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL)); - - gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath ( - (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath - ); - gDxeCoreLoadedImage->DeviceHandle = FvHandle; - } - } - } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { - // - // 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); - } -} - - -VOID -CoreInitializeDispatcher ( - VOID - ) -/*++ - -Routine Description: - - Initialize the dispatcher. Initialize the notification function that runs when - a FV protocol is added to the system. - -Arguments: - - NONE - -Returns: - - NONE - ---*/ -{ - mFwVolEvent = CoreCreateProtocolNotifyEvent ( - &gEfiFirmwareVolumeProtocolGuid, - TPL_CALLBACK, - CoreFwVolEventProtocolNotify, - NULL, - &mFwVolEventRegistration, - TRUE - ); -} - -// -// Function only used in debug builds -// -VOID -CoreDisplayDiscoveredNotDispatched ( - VOID - ) -/*++ - -Routine Description: - - Traverse the discovered list for any drivers that were discovered but not loaded - because the dependency experessions evaluated to false - -Arguments: - - NONE - -Returns: - - NONE - ---*/ -{ - 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 ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName)); - } - } -}