+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- Dispatcher.c\r
-\r
-Abstract:\r
-\r
- Tiano DXE Dispatcher.\r
-\r
- Step #1 - When a FV protocol is added to the system every driver in the FV\r
- is added to the mDiscoveredList. The SOR, Before, and After Depex are \r
- pre-processed as drivers are added to the mDiscoveredList. If an Apriori \r
- file exists in the FV those drivers are addeded to the \r
- mScheduledQueue. The mFvHandleList is used to make sure a \r
- FV is only processed once.\r
-\r
- Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and\r
- start it. After mScheduledQueue is drained check the \r
- mDiscoveredList to see if any item has a Depex that is ready to \r
- be placed on the mScheduledQueue.\r
-\r
- Step #3 - Adding to the mScheduledQueue requires that you process Before \r
- and After dependencies. This is done recursively as the call to add\r
- to the mScheduledQueue checks for Before and recursively adds \r
- all Befores. It then addes the item that was passed in and then \r
- processess the After dependecies by recursively calling the routine.\r
-\r
- Dispatcher Rules:\r
- The rules for the dispatcher are in chapter 10 of the DXE CIS. Figure 10-3 \r
- is the state diagram for the DXE dispatcher\r
-\r
- Depex - Dependency Expresion.\r
- SOR - Schedule On Request - Don't schedule if this bit is set.\r
-\r
---*/\r
-\r
-#include <DxeMain.h>\r
-\r
-//\r
-// The Driver List contains one copy of every driver that has been discovered.\r
-// Items are never removed from the driver list. List of EFI_CORE_DRIVER_ENTRY\r
-//\r
-LIST_ENTRY mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList); \r
-\r
-//\r
-// Queue of drivers that are ready to dispatch. This queue is a subset of the\r
-// mDiscoveredList.list of EFI_CORE_DRIVER_ENTRY.\r
-//\r
-LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);\r
-\r
-//\r
-// List of handles who's Fv's have been parsed and added to the mFwDriverList.\r
-//\r
-LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList); // list of KNOWN_HANDLE\r
-\r
-//\r
-// Lock for mDiscoveredList, mScheduledQueue, gDispatcherRunning.\r
-//\r
-EFI_LOCK mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);\r
-\r
-\r
-//\r
-// Flag for the DXE Dispacher. TRUE if dispatcher is execuing.\r
-//\r
-BOOLEAN gDispatcherRunning = FALSE;\r
-\r
-//\r
-// Module globals to manage the FwVol registration notification event\r
-//\r
-EFI_EVENT mFwVolEvent;\r
-VOID *mFwVolEventRegistration;\r
-\r
-//\r
-// List of file types supported by dispatcher\r
-//\r
-static EFI_FV_FILETYPE mDxeFileTypes[] = { \r
- EFI_FV_FILETYPE_DRIVER, \r
- EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER, \r
- EFI_FV_FILETYPE_DXE_CORE,\r
- EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\r
-};\r
-\r
-typedef struct {\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;\r
- EFI_DEVICE_PATH_PROTOCOL End;\r
-} FV_FILEPATH_DEVICE_PATH;\r
-\r
-FV_FILEPATH_DEVICE_PATH mFvDevicePath;\r
-\r
-\r
-//\r
-// Function Prototypes\r
-//\r
-STATIC\r
-VOID\r
-CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (\r
- IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry\r
- );\r
- \r
-STATIC\r
-VOID\r
-EFIAPI\r
-CoreFwVolEventProtocolNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- );\r
-\r
-STATIC\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-CoreFvToDevicePath (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,\r
- IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
- );\r
-\r
-STATIC \r
-EFI_STATUS\r
-CoreAddToDriverList (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,\r
- IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
- );\r
-\r
-STATIC\r
-EFI_STATUS \r
-CoreProcessFvImageFile (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,\r
- IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
- );\r
-\r
-STATIC\r
-VOID\r
-CoreAcquireDispatcherLock (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Enter critical section by gaining lock on mDispatcherLock\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-\r
-{\r
- CoreAcquireLock (&mDispatcherLock);\r
-}\r
-\r
-STATIC\r
-VOID\r
-CoreReleaseDispatcherLock (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Exit critical section by releasing lock on mDispatcherLock\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- CoreReleaseLock (&mDispatcherLock);\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-CoreGetDepexSectionAndPreProccess (\r
- IN EFI_CORE_DRIVER_ENTRY *DriverEntry\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read Depex and pre-process the Depex for Before and After. If Section Extraction\r
- protocol returns an error via ReadSection defer the reading of the Depex.\r
-\r
-Arguments:\r
-\r
- DriverEntry - Driver to work on.\r
- \r
-Returns:\r
-\r
- EFI_SUCCESS - Depex read and preprossesed \r
-\r
- EFI_PROTOCOL_ERROR - The section extraction protocol returned an error and \r
- Depex reading needs to be retried.\r
-\r
- Other Error - DEPEX not found.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_SECTION_TYPE SectionType;\r
- UINT32 AuthenticationStatus;\r
- EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;\r
-\r
- \r
- Fv = DriverEntry->Fv;\r
-\r
- //\r
- // Grab Depex info, it will never be free'ed.\r
- //\r
- SectionType = EFI_SECTION_DXE_DEPEX;\r
- Status = Fv->ReadSection (\r
- DriverEntry->Fv, \r
- &DriverEntry->FileName,\r
- SectionType, \r
- 0, \r
- &DriverEntry->Depex, \r
- (UINTN *)&DriverEntry->DepexSize,\r
- &AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- if (Status == EFI_PROTOCOL_ERROR) {\r
- //\r
- // The section extraction protocol failed so set protocol error flag\r
- //\r
- DriverEntry->DepexProtocolError = TRUE;\r
- } else {\r
- //\r
- // If no Depex assume EFI 1.1 driver model\r
- //\r
- DriverEntry->Depex = NULL;\r
- DriverEntry->Dependent = TRUE;\r
- DriverEntry->DepexProtocolError = FALSE;\r
- }\r
- } else {\r
- //\r
- // Set Before, After, and Unrequested state information based on Depex\r
- // Driver will be put in Dependent or Unrequested state\r
- //\r
- CorePreProcessDepex (DriverEntry);\r
- DriverEntry->DepexProtocolError = FALSE;\r
- } \r
-\r
- return Status;\r
-}\r
-\r
-EFI_DXESERVICE\r
-EFI_STATUS\r
-EFIAPI\r
-CoreSchedule (\r
- IN EFI_HANDLE FirmwareVolumeHandle,\r
- IN EFI_GUID *DriverName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check every driver and locate a matching one. If the driver is found, the Unrequested\r
- state flag is cleared.\r
-\r
-Arguments:\r
-\r
- FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware \r
- file specified by DriverName.\r
-\r
- DriverName - The Driver name to put in the Dependent state.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared\r
-\r
- EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set.\r
-\r
---*/\r
-{\r
- LIST_ENTRY *Link;\r
- EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
-\r
- //\r
- // Check every driver\r
- //\r
- for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
- DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (DriverEntry->FvHandle == FirmwareVolumeHandle &&\r
- DriverEntry->Unrequested && \r
- CompareGuid (DriverName, &DriverEntry->FileName)) {\r
- //\r
- // Move the driver from the Unrequested to the Dependent state\r
- //\r
- CoreAcquireDispatcherLock ();\r
- DriverEntry->Unrequested = FALSE;\r
- DriverEntry->Dependent = TRUE;\r
- CoreReleaseDispatcherLock ();\r
- \r
- return EFI_SUCCESS;\r
- }\r
- }\r
- return EFI_NOT_FOUND; \r
-}\r
-\r
-\r
-EFI_DXESERVICE\r
-EFI_STATUS\r
-EFIAPI\r
-CoreTrust (\r
- IN EFI_HANDLE FirmwareVolumeHandle,\r
- IN EFI_GUID *DriverName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Convert a driver from the Untrused back to the Scheduled state\r
-\r
-Arguments:\r
-\r
- FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware \r
- file specified by DriverName.\r
-\r
- DriverName - The Driver name to put in the Scheduled state\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The file was found in the untrusted state, and it was promoted \r
- to the trusted state.\r
-\r
- EFI_NOT_FOUND - The file was not found in the untrusted state.\r
-\r
---*/\r
-{\r
- LIST_ENTRY *Link;\r
- EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
-\r
- //\r
- // Check every driver\r
- //\r
- for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
- DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (DriverEntry->FvHandle == FirmwareVolumeHandle &&\r
- DriverEntry->Untrusted && \r
- CompareGuid (DriverName, &DriverEntry->FileName)) {\r
- //\r
- // Transition driver from Untrusted to Scheduled state.\r
- //\r
- CoreAcquireDispatcherLock ();\r
- DriverEntry->Untrusted = FALSE;\r
- DriverEntry->Scheduled = TRUE;\r
- InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);\r
- CoreReleaseDispatcherLock ();\r
- \r
- return EFI_SUCCESS;\r
- }\r
- }\r
- return EFI_NOT_FOUND; \r
-}\r
-\r
-\r
-EFI_DXESERVICE\r
-EFI_STATUS\r
-EFIAPI\r
-CoreDispatcher (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This is the main Dispatcher for DXE and it exits when there are no more \r
- drivers to run. Drain the mScheduledQueue and load and start a PE\r
- image for each driver. Search the mDiscoveredList to see if any driver can \r
- be placed on the mScheduledQueue. If no drivers are placed on the\r
- mScheduledQueue exit the function. On exit it is assumed the Bds()\r
- will be called, and when the Bds() exits the Dispatcher will be called \r
- again.\r
-\r
-Arguments:\r
-\r
- NONE\r
-\r
-Returns:\r
-\r
- EFI_ALREADY_STARTED - The DXE Dispatcher is already running\r
-\r
- EFI_NOT_FOUND - No DXE Drivers were dispatched\r
-\r
- EFI_SUCCESS - One or more DXE Drivers were dispatched\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_STATUS ReturnStatus;\r
- LIST_ENTRY *Link;\r
- EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
- BOOLEAN ReadyToRun;\r
-\r
- if (gDispatcherRunning) {\r
- //\r
- // If the dispatcher is running don't let it be restarted.\r
- //\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- gDispatcherRunning = TRUE;\r
-\r
-\r
- ReturnStatus = EFI_NOT_FOUND;\r
- do {\r
- //\r
- // Drain the Scheduled Queue\r
- //\r
- while (!IsListEmpty (&mScheduledQueue)) {\r
- DriverEntry = CR (\r
- mScheduledQueue.ForwardLink,\r
- EFI_CORE_DRIVER_ENTRY,\r
- ScheduledLink,\r
- EFI_CORE_DRIVER_ENTRY_SIGNATURE\r
- );\r
-\r
- //\r
- // Load the DXE Driver image into memory. If the Driver was transitioned from\r
- // Untrused to Scheduled it would have already been loaded so we may need to\r
- // skip the LoadImage\r
- //\r
- if (DriverEntry->ImageHandle == NULL) {\r
- Status = CoreLoadImage (\r
- FALSE, \r
- gDxeCoreImageHandle, \r
- DriverEntry->FvFileDevicePath,\r
- NULL, \r
- 0, \r
- &DriverEntry->ImageHandle\r
- );\r
-\r
- //\r
- // Update the driver state to reflect that it's been loaded\r
- //\r
- if (EFI_ERROR (Status)) {\r
- CoreAcquireDispatcherLock ();\r
-\r
- if (Status == EFI_SECURITY_VIOLATION) {\r
- //\r
- // Take driver from Scheduled to Untrused state\r
- //\r
- DriverEntry->Untrusted = TRUE;\r
- } else {\r
- //\r
- // The DXE Driver could not be loaded, and do not attempt to load or start it again.\r
- // Take driver from Scheduled to Initialized. \r
- //\r
- // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned\r
- //\r
- DriverEntry->Initialized = TRUE;\r
- }\r
-\r
- DriverEntry->Scheduled = FALSE;\r
- RemoveEntryList (&DriverEntry->ScheduledLink);\r
- \r
- CoreReleaseDispatcherLock ();\r
- \r
- //\r
- // If it's an error don't try the StartImage\r
- //\r
- continue;\r
- }\r
- }\r
-\r
- CoreAcquireDispatcherLock ();\r
-\r
- DriverEntry->Scheduled = FALSE;\r
- DriverEntry->Initialized = TRUE;\r
- RemoveEntryList (&DriverEntry->ScheduledLink);\r
- \r
- CoreReleaseDispatcherLock ();\r
-\r
-\r
- CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle);\r
- Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);\r
- CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, DriverEntry->ImageHandle);\r
-\r
- ReturnStatus = EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Search DriverList for items to place on Scheduled Queue\r
- //\r
- ReadyToRun = FALSE;\r
- for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
- DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
-\r
- if (DriverEntry->DepexProtocolError){\r
- //\r
- // If Section Extraction Protocol did not let the Depex be read before retry the read\r
- //\r
- Status = CoreGetDepexSectionAndPreProccess (DriverEntry);\r
- } \r
-\r
- if (DriverEntry->Dependent) {\r
- if (CoreIsSchedulable (DriverEntry)) {\r
- CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry); \r
- ReadyToRun = TRUE;\r
- } \r
- }\r
- }\r
- } while (ReadyToRun);\r
-\r
- gDispatcherRunning = FALSE;\r
-\r
- return ReturnStatus;\r
-}\r
-\r
-STATIC\r
-VOID\r
-CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (\r
- IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Insert InsertedDriverEntry onto the mScheduledQueue. To do this you \r
- must add any driver with a before dependency on InsertedDriverEntry first.\r
- You do this by recursively calling this routine. After all the Befores are\r
- processed you can add InsertedDriverEntry to the mScheduledQueue. \r
- Then you can add any driver with an After dependency on InsertedDriverEntry \r
- by recursively calling this routine.\r
-\r
-Arguments:\r
-\r
- InsertedDriverEntry - The driver to insert on the ScheduledLink Queue\r
-\r
-Returns:\r
-\r
- NONE \r
-\r
---*/\r
-{\r
- LIST_ENTRY *Link;\r
- EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
-\r
- //\r
- // Process Before Dependency\r
- //\r
- for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
- DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (DriverEntry->Before && DriverEntry->Dependent) {\r
- if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
- //\r
- // Recursively process BEFORE\r
- //\r
- CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Convert driver from Dependent to Scheduled state\r
- //\r
- CoreAcquireDispatcherLock ();\r
-\r
- InsertedDriverEntry->Dependent = FALSE;\r
- InsertedDriverEntry->Scheduled = TRUE;\r
- InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);\r
- \r
- CoreReleaseDispatcherLock ();\r
-\r
- //\r
- // Process After Dependency\r
- //\r
- for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
- DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (DriverEntry->After && DriverEntry->Dependent) {\r
- if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
- //\r
- // Recursively process AFTER\r
- //\r
- CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
- }\r
- }\r
- }\r
-}\r
-\r
-STATIC\r
-BOOLEAN\r
-FvHasBeenProcessed (\r
- IN EFI_HANDLE FvHandle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Return TRUE if the Fv has been processed, FALSE if not.\r
-\r
-Arguments:\r
-\r
- FvHandle - The handle of a FV that's being tested\r
-\r
-Returns:\r
-\r
- TRUE - Fv protocol on FvHandle has been processed\r
-\r
- FALSE - Fv protocol on FvHandle has not yet been processed\r
-\r
---*/\r
-{\r
- LIST_ENTRY *Link;\r
- KNOWN_HANDLE *KnownHandle;\r
-\r
- for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {\r
- KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);\r
- if (KnownHandle->Handle == FvHandle) {\r
- return TRUE;\r
- }\r
- }\r
- return FALSE;\r
-}\r
-\r
-STATIC\r
-VOID\r
-FvIsBeingProcesssed (\r
- IN EFI_HANDLE FvHandle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Remember that Fv protocol on FvHandle has had it's drivers placed on the\r
- mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are\r
- never removed/freed from the mFvHandleList.\r
-\r
-Arguments:\r
-\r
- FvHandle - The handle of a FV that has been processed\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- KNOWN_HANDLE *KnownHandle;\r
-\r
- KnownHandle = CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE));\r
- ASSERT (KnownHandle != NULL);\r
-\r
- KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;\r
- KnownHandle->Handle = FvHandle;\r
- InsertTailList (&mFvHandleList, &KnownHandle->Link);\r
-}\r
-\r
-\r
-\r
-STATIC\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-CoreFvToDevicePath (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,\r
- IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Convert FvHandle and DriverName into an EFI device path\r
-\r
-Arguments:\r
-\r
- Fv - Fv protocol, needed to read Depex info out of FLASH.\r
- \r
- FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the\r
- PE image can be read out of the FV at a later time.\r
-\r
- DriverName - Name of driver to add to mDiscoveredList.\r
-\r
-Returns:\r
-\r
- Pointer to device path constructed from FvHandle and DriverName\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *FileNameDevicePath;\r
-\r
- //\r
- // Remember the device path of the FV\r
- //\r
- Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- FileNameDevicePath = NULL;\r
- } else {\r
- //\r
- // Build a device path to the file in the FV to pass into gBS->LoadImage\r
- //\r
- EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);\r
- mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;\r
- mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
- SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
-\r
- FileNameDevicePath = CoreAppendDevicePath (\r
- FvDevicePath, \r
- (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath\r
- );\r
- }\r
-\r
- return FileNameDevicePath;\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-CoreAddToDriverList (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,\r
- IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry, \r
- and initilize any state variables. Read the Depex from the FV and store it\r
- in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.\r
- The Discovered list is never free'ed and contains booleans that represent the\r
- other possible DXE driver states.\r
-\r
-Arguments:\r
-\r
- Fv - Fv protocol, needed to read Depex info out of FLASH.\r
- \r
- FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the\r
- PE image can be read out of the FV at a later time.\r
-\r
- DriverName - Name of driver to add to mDiscoveredList.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - If driver was added to the mDiscoveredList.\r
-\r
- EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName\r
- may be active in the system at any one time.\r
-\r
---*/\r
-{\r
- EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
-\r
- \r
- //\r
- // Create the Driver Entry for the list. ZeroPool initializes lots of variables to \r
- // NULL or FALSE.\r
- //\r
- DriverEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY));\r
- ASSERT (DriverEntry != NULL);\r
-\r
- DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE;\r
- CopyMem (&DriverEntry->FileName, DriverName, sizeof (EFI_GUID));\r
- DriverEntry->FvHandle = FvHandle;\r
- DriverEntry->Fv = Fv;\r
- DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName);\r
-\r
- CoreGetDepexSectionAndPreProccess (DriverEntry);\r
- \r
- CoreAcquireDispatcherLock ();\r
- \r
- InsertTailList (&mDiscoveredList, &DriverEntry->Link);\r
-\r
- CoreReleaseDispatcherLock ();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-EFI_STATUS \r
-CoreProcessFvImageFile (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,\r
- IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.\r
-\r
-Arguments:\r
-\r
- Fv - The FIRMWARE_VOLUME protocol installed on the FV.\r
- FvHandle - The handle which FVB protocol installed on.\r
- DriverName - The driver guid specified.\r
-\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - No enough memory or other resource.\r
- \r
- EFI_VOLUME_CORRUPTED - Corrupted volume.\r
- \r
- EFI_SUCCESS - Function successfully returned.\r
- \r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_SECTION_TYPE SectionType;\r
- UINT32 AuthenticationStatus;\r
- VOID *Buffer;\r
- UINTN BufferSize;\r
-\r
- //\r
- // Read the first (and only the first) firmware volume section\r
- //\r
- SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
- Buffer = NULL;\r
- BufferSize = 0;\r
- Status = Fv->ReadSection (\r
- Fv, \r
- DriverName, \r
- SectionType, \r
- 0, \r
- &Buffer, \r
- &BufferSize,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Produce a FVB protocol for the file\r
- //\r
- Status = ProduceFVBProtocolOnBuffer (\r
- (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer,\r
- (UINT64)BufferSize,\r
- FvHandle,\r
- NULL\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status) && (Buffer != NULL)) { \r
- //\r
- // ReadSection or Produce FVB failed, Free data buffer\r
- //\r
- CoreFreePool (Buffer); \r
-\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-STATIC\r
-VOID\r
-EFIAPI\r
-CoreFwVolEventProtocolNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Event notification that is fired every time a FV dispatch protocol is added. \r
- More than one protocol may have been added when this event is fired, so you\r
- must loop on CoreLocateHandle () to see how many protocols were added and\r
- do the following to each FV:\r
-\r
- If the Fv has already been processed, skip it. If the Fv has not been \r
- processed then mark it as being processed, as we are about to process it.\r
-\r
- Read the Fv and add any driver in the Fv to the mDiscoveredList.The \r
- mDiscoveredList is never free'ed and contains variables that define\r
- the other states the DXE driver transitions to.. \r
- \r
- While you are at it read the A Priori file into memory.\r
- Place drivers in the A Priori list onto the mScheduledQueue.\r
-\r
-Arguments:\r
-\r
- Event - The Event that is being processed, not used.\r
- \r
- Context - Event Context, not used.\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_STATUS GetNextFileStatus;\r
- EFI_STATUS SecurityStatus;\r
- EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;\r
- EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;\r
- EFI_HANDLE FvHandle;\r
- UINTN BufferSize;\r
- EFI_GUID NameGuid;\r
- UINTN Key;\r
- EFI_FV_FILETYPE Type;\r
- EFI_FV_FILE_ATTRIBUTES Attributes;\r
- UINTN Size;\r
- EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
- EFI_GUID *AprioriFile;\r
- UINTN AprioriEntryCount;\r
- UINTN Index;\r
- LIST_ENTRY *Link;\r
- UINT32 AuthenticationStatus;\r
- UINTN SizeOfBuffer;\r
-\r
-\r
- while (TRUE) {\r
- BufferSize = sizeof (EFI_HANDLE);\r
- Status = CoreLocateHandle (\r
- ByRegisterNotify,\r
- NULL,\r
- mFwVolEventRegistration,\r
- &BufferSize,\r
- &FvHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If no more notification events exit\r
- //\r
- return;\r
- }\r
-\r
- if (FvHasBeenProcessed (FvHandle)) {\r
- //\r
- // This Fv has already been processed so lets skip it!\r
- //\r
- continue;\r
- }\r
-\r
- Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, (VOID **)&Fv);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If no dispatch protocol then skip, but do not marked as being processed as it\r
- // may show up later.\r
- //\r
- continue;\r
- }\r
-\r
- //\r
- // Since we are about to process this Fv mark it as processed.\r
- //\r
- FvIsBeingProcesssed (FvHandle);\r
-\r
-\r
- Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Fv);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // The Handle has a FirmwareVolumeDispatch protocol and should also contiain\r
- // a FirmwareVolume protocol thus we should never get here.\r
- //\r
- ASSERT (FALSE);\r
- continue;\r
- }\r
- \r
- Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // The Firmware volume doesn't have device path, can't be dispatched.\r
- //\r
- continue;\r
- }\r
- \r
- //\r
- // Evaluate the authentication status of the Firmware Volume through \r
- // Security Architectural Protocol\r
- //\r
- if (gSecurity != NULL) {\r
- SecurityStatus = gSecurity->FileAuthenticationState (\r
- gSecurity, \r
- 0, \r
- FvDevicePath\r
- );\r
- if (SecurityStatus != EFI_SUCCESS) {\r
- //\r
- // Security check failed. The firmware volume should not be used for any purpose.\r
- //\r
- continue;\r
- }\r
- } \r
- \r
- //\r
- // Discover Drivers in FV and add them to the Discovered Driver List. \r
- // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER \r
- // EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core\r
- // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb\r
- //\r
- for (Index = 0; Index < sizeof (mDxeFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {\r
- //\r
- // Initialize the search key\r
- //\r
- Key = 0;\r
- do {\r
- Type = mDxeFileTypes[Index];\r
- GetNextFileStatus = Fv->GetNextFile (\r
- Fv, \r
- &Key,\r
- &Type, \r
- &NameGuid, \r
- &Attributes, \r
- &Size\r
- );\r
- if (!EFI_ERROR (GetNextFileStatus)) {\r
- if (Type == EFI_FV_FILETYPE_DXE_CORE) {\r
- //\r
- // If this is the DXE core fill in it's DevicePath & DeviceHandle\r
- //\r
- if (gDxeCoreLoadedImage->FilePath == NULL) {\r
- if (CompareGuid (&NameGuid, gDxeCoreFileName)) {\r
- //\r
- // Maybe One specail Fv cantains only one DXE_CORE module, so its device path must\r
- // be initialized completely.\r
- //\r
- EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);\r
- mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;\r
- mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
- SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
-\r
- gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath (\r
- (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath\r
- );\r
- gDxeCoreLoadedImage->DeviceHandle = FvHandle;\r
- }\r
- }\r
- } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
- //\r
- // Found a firmware volume image. Produce a firmware volume block\r
- // protocol for it so it gets dispatched from. This is usually a \r
- // capsule.\r
- //\r
- CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);\r
- } else {\r
- //\r
- // Transition driver from Undiscovered to Discovered state\r
- //\r
- CoreAddToDriverList (Fv, FvHandle, &NameGuid);\r
- }\r
- }\r
- } while (!EFI_ERROR (GetNextFileStatus));\r
- }\r
- \r
- //\r
- // Read the array of GUIDs from the Apriori file if it is present in the firmware volume\r
- //\r
- AprioriFile = NULL;\r
- Status = Fv->ReadSection (\r
- Fv,\r
- &gAprioriGuid,\r
- EFI_SECTION_RAW,\r
- 0,\r
- (VOID **)&AprioriFile,\r
- &SizeOfBuffer,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);\r
- } else {\r
- AprioriEntryCount = 0;\r
- }\r
-\r
- //\r
- // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes\r
- // drivers not in the current FV and these must be skipped since the a priori list\r
- // is only valid for the FV that it resided in.\r
- //\r
- CoreAcquireDispatcherLock ();\r
- \r
- for (Index = 0; Index < AprioriEntryCount; Index++) {\r
- for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
- DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&\r
- (FvHandle == DriverEntry->FvHandle)) {\r
- DriverEntry->Dependent = FALSE;\r
- DriverEntry->Scheduled = TRUE;\r
- InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);\r
- break;\r
- }\r
- }\r
- }\r
-\r
- CoreReleaseDispatcherLock ();\r
-\r
- //\r
- // Free data allocated by Fv->ReadSection () \r
- //\r
- CoreFreePool (AprioriFile); \r
- }\r
-}\r
-\r
-\r
-VOID\r
-CoreInitializeDispatcher (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Initialize the dispatcher. Initialize the notification function that runs when\r
- a FV protocol is added to the system.\r
-\r
-Arguments:\r
-\r
- NONE\r
-\r
-Returns:\r
-\r
- NONE \r
-\r
---*/\r
-{\r
- mFwVolEvent = CoreCreateProtocolNotifyEvent (\r
- &gEfiFirmwareVolumeProtocolGuid, \r
- TPL_CALLBACK,\r
- CoreFwVolEventProtocolNotify,\r
- NULL,\r
- &mFwVolEventRegistration,\r
- TRUE\r
- );\r
-}\r
-\r
-//\r
-// Function only used in debug builds\r
-//\r
-VOID\r
-CoreDisplayDiscoveredNotDispatched (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Traverse the discovered list for any drivers that were discovered but not loaded \r
- because the dependency experessions evaluated to false\r
-\r
-Arguments:\r
-\r
- NONE\r
-\r
-Returns:\r
-\r
- NONE \r
-\r
---*/\r
-{\r
- LIST_ENTRY *Link;\r
- EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
-\r
- for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {\r
- DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (DriverEntry->Dependent) {\r
- DEBUG ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));\r
- }\r
- }\r
-}\r