123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167 |
- /*++
- Copyright (c) 2014 Minoca Corp. All Rights Reserved
- Module Name:
- drvsup.c
- Abstract:
- This module implements UEFI core driver support routines.
- Author:
- Evan Green 5-Mar-2014
- Environment:
- Firmware
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "ueficore.h"
- #include <minoca/uefi/protocol/drvbind.h>
- #include <minoca/uefi/protocol/drvplato.h>
- #include <minoca/uefi/protocol/drvfamov.h>
- #include <minoca/uefi/protocol/drvbusov.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- EFI_STATUS
- EfipCoreConnectSingleController (
- EFI_HANDLE ControllerHandle,
- EFI_HANDLE *ContextDriverImageHandles,
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- );
- VOID
- EfipCoreAddSortedDriverBindingProtocol (
- EFI_HANDLE DriverBindingHandle,
- UINTN *NumberOfSortedDriverBindingProtocols,
- EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,
- UINTN DriverBindingHandleCount,
- EFI_HANDLE *DriverBindingHandleBuffer,
- BOOLEAN IsImageHandle
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- EFI_GUID EfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
- EFI_GUID EfiPlatformDriverOverrideProtocolGuid =
- EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID;
- EFI_GUID EfiDriverFamilyOverrideProtocolGuid =
- EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID;
- EFI_GUID EfiBusSpecificDriverOverrideProtocolGuid =
- EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID;
- //
- // ------------------------------------------------------------------ Functions
- //
- EFIAPI
- EFI_STATUS
- EfiCoreConnectController (
- EFI_HANDLE ControllerHandle,
- EFI_HANDLE *DriverImageHandle,
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
- BOOLEAN Recursive
- )
- /*++
- Routine Description:
- This routine connects one or more drivers to a controller.
- Arguments:
- ControllerHandle - Supplies the handle of the controller which driver(s)
- are connecting to.
- DriverImageHandle - Supplies a pointer to an ordered list of handles that
- support the EFI_DRIVER_BINDING_PROTOCOL.
- RemainingDevicePath - Supplies an optional pointer to the device path that
- specifies a child of the controller specified by the controller handle.
- Recursive - Supplies a boolean indicating if this routine should be called
- recursively until the entire tree of controllers below the specified
- controller has been connected. If FALSE, then the tree of controllers
- is only expanded one level.
- Return Value:
- EFI_SUCCESS on success.
- EFI_INVALID_PARAMETER if the controller handle is NULL.
- EFI_NOT_FOUND if either there are no EFI_DRIVER_BINDING_PROTOCOL instances
- present in the system, or no drivers were connected to the controller
- handle.
- EFI_SECURITY_VIOLATION if the user has no permission to start UEFI device
- drivers on the device associated with the controller handle or specified
- by the remaining device path.
- --*/
- {
- EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath;
- EFI_HANDLE *ChildHandleBuffer;
- UINTN ChildHandleCount;
- PLIST_ENTRY CurrentEntry;
- PEFI_HANDLE_DATA Handle;
- UINTN Index;
- PEFI_OPEN_PROTOCOL_DATA OpenData;
- PLIST_ENTRY OpenEntry;
- PEFI_PROTOCOL_INTERFACE ProtocolInterface;
- EFI_STATUS ReturnStatus;
- EFI_STATUS Status;
- Status = EfipCoreValidateHandle(ControllerHandle);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- Handle = ControllerHandle;
- //
- // Make a copy of the device path to ensure it is aligned.
- //
- AlignedRemainingDevicePath = NULL;
- if (RemainingDevicePath != NULL) {
- AlignedRemainingDevicePath = EfiCoreDuplicateDevicePath(
- RemainingDevicePath);
- if (AlignedRemainingDevicePath == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
- //
- // Connect all drivers to the controller handle. If the connection routine
- // returns EFI_NOT_READY, then the number of driver binding protocols in
- // the handle database has increased during the call so the connect
- // operation must be restarted.
- //
- do {
- ReturnStatus = EfipCoreConnectSingleController(
- ControllerHandle,
- DriverImageHandle,
- AlignedRemainingDevicePath);
- } while (ReturnStatus == EFI_NOT_READY);
- if (AlignedRemainingDevicePath != NULL) {
- EfiCoreFreePool(AlignedRemainingDevicePath);
- }
- //
- // If recursive, then connect all drivers to all of the controller handle's
- // children.
- //
- if (Recursive != FALSE) {
- EfiCoreAcquireLock(&EfiProtocolDatabaseLock);
- //
- // Make sure the driver binding handle is valid.
- //
- Status = EfipCoreValidateHandle(ControllerHandle);
- if (EFI_ERROR(Status)) {
- EfiCoreReleaseLock(&EfiProtocolDatabaseLock);
- return Status;
- }
- //
- // Count the controller handle's children.
- //
- ChildHandleCount = 0;
- CurrentEntry = Handle->ProtocolList.Next;
- while (CurrentEntry != &(Handle->ProtocolList)) {
- ProtocolInterface = LIST_VALUE(CurrentEntry,
- EFI_PROTOCOL_INTERFACE,
- ListEntry);
- ASSERT(ProtocolInterface->Magic == EFI_PROTOCOL_INTERFACE_MAGIC);
- CurrentEntry = CurrentEntry->Next;
- OpenEntry = ProtocolInterface->OpenList.Next;
- while (OpenEntry != &(ProtocolInterface->OpenList)) {
- OpenData = LIST_VALUE(OpenEntry,
- EFI_OPEN_PROTOCOL_DATA,
- ListEntry);
- ASSERT(OpenData->Magic == EFI_OPEN_PROTOCOL_MAGIC);
- OpenEntry = OpenEntry->Next;
- if ((OpenData->Attributes &
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- ChildHandleCount += 1;
- }
- }
- }
- //
- // Allocate an array for the controller handle's children.
- //
- ChildHandleBuffer = EfiCoreAllocateBootPool(
- ChildHandleCount * sizeof(EFI_HANDLE));
- if (ChildHandleBuffer == NULL) {
- EfiCoreReleaseLock(&EfiProtocolDatabaseLock);
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Fill in the handle buffer with the controller handle's children.
- //
- ChildHandleCount = 0;
- CurrentEntry = Handle->ProtocolList.Next;
- while (CurrentEntry != &(Handle->ProtocolList)) {
- ProtocolInterface = LIST_VALUE(CurrentEntry,
- EFI_PROTOCOL_INTERFACE,
- ListEntry);
- ASSERT(ProtocolInterface->Magic == EFI_PROTOCOL_INTERFACE_MAGIC);
- CurrentEntry = CurrentEntry->Next;
- OpenEntry = ProtocolInterface->OpenList.Next;
- while (OpenEntry != &(ProtocolInterface->OpenList)) {
- OpenData = LIST_VALUE(OpenEntry,
- EFI_OPEN_PROTOCOL_DATA,
- ListEntry);
- ASSERT(OpenData->Magic == EFI_OPEN_PROTOCOL_MAGIC);
- OpenEntry = OpenEntry->Next;
- if ((OpenData->Attributes &
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- ChildHandleBuffer[ChildHandleCount] =
- OpenData->ControllerHandle;
- ChildHandleCount += 1;
- }
- }
- }
- EfiCoreReleaseLock(&EfiProtocolDatabaseLock);
- //
- // Recursively connect each child.
- //
- for (Index = 0; Index < ChildHandleCount; Index += 1) {
- EfiCoreConnectController(ChildHandleBuffer[Index],
- NULL,
- NULL,
- TRUE);
- }
- EfiCoreFreePool(ChildHandleBuffer);
- }
- return ReturnStatus;
- }
- EFIAPI
- EFI_STATUS
- EfiCoreDisconnectController (
- EFI_HANDLE ControllerHandle,
- EFI_HANDLE DriverImageHandle,
- EFI_HANDLE ChildHandle
- )
- /*++
- Routine Description:
- This routine disconnects one or more drivers to a controller.
- Arguments:
- ControllerHandle - Supplies the handle of the controller which driver(s)
- are disconnecting from.
- DriverImageHandle - Supplies an optional pointer to the driver to
- disconnect from the controller. If NULL, all drivers are disconnected.
- ChildHandle - Supplies an optional pointer to the handle of the child to
- destroy.
- Return Value:
- EFI_SUCCESS if one or more drivers were disconnected, no drivers are
- managing the handle, or a driver image handle was supplied and it is not
- controlling the given handle.
- EFI_INVALID_PARAMETER if the controller handle or driver handle is not a
- valid EFI handle, or the driver image handle doesn't support the
- EFI_DRIVER_BINDING_PROTOCOL.
- EFI_OUT_OF_RESOURCES if there are not enough resources are available to
- disconnect the controller(s).
- EFI_DEVICE_ERROR if the controller could not be disconnected because of a
- device error.
- --*/
- {
- EFI_HANDLE *ChildBuffer;
- UINTN ChildBufferCount;
- BOOLEAN ChildHandleValid;
- UINTN ChildrenToStop;
- PLIST_ENTRY CurrentEntry;
- EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
- EFI_HANDLE *DriverImageHandleBuffer;
- UINTN DriverImageHandleCount;
- BOOLEAN DriverImageHandleValid;
- BOOLEAN Duplicate;
- PEFI_HANDLE_DATA Handle;
- UINTN HandleIndex;
- UINTN Index;
- PEFI_OPEN_PROTOCOL_DATA OpenData;
- PLIST_ENTRY OpenEntry;
- PEFI_PROTOCOL_INTERFACE ProtocolInterface;
- EFI_STATUS Status;
- UINTN StopCount;
- Status = EfipCoreValidateHandle(ControllerHandle);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- //
- // Make sure the child handle is valid if supplied.
- //
- if (ChildHandle != NULL) {
- Status = EfipCoreValidateHandle(ChildHandle);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- }
- Handle = ControllerHandle;
- //
- // Get a list of drivers managing the controller handle.
- //
- DriverImageHandleBuffer = NULL;
- DriverImageHandleCount = 0;
- if (DriverImageHandle == NULL) {
- DriverImageHandleCount = 0;
- EfiCoreAcquireLock(&EfiProtocolDatabaseLock);
- CurrentEntry = Handle->ProtocolList.Next;
- while (CurrentEntry != &(Handle->ProtocolList)) {
- ProtocolInterface = LIST_VALUE(CurrentEntry,
- EFI_PROTOCOL_INTERFACE,
- ListEntry);
- ASSERT(ProtocolInterface->Magic == EFI_PROTOCOL_INTERFACE_MAGIC);
- OpenEntry = ProtocolInterface->OpenList.Next;
- while (OpenEntry != &(ProtocolInterface->OpenList)) {
- OpenData = LIST_VALUE(OpenEntry,
- EFI_OPEN_PROTOCOL_DATA,
- ListEntry);
- ASSERT(OpenData->Magic == EFI_OPEN_PROTOCOL_MAGIC);
- OpenEntry = OpenEntry->Next;
- if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
- DriverImageHandleCount += 1;
- }
- }
- CurrentEntry = CurrentEntry->Next;
- }
- EfiCoreReleaseLock(&EfiProtocolDatabaseLock);
- //
- // If there are no drivers managing this controller, then there's no
- // work to do.
- //
- if (DriverImageHandleCount == 0) {
- Status = EFI_SUCCESS;
- goto CoreDisconnectControllerEnd;
- }
- DriverImageHandleBuffer = EfiCoreAllocateBootPool(
- DriverImageHandleCount * sizeof(EFI_HANDLE));
- if (DriverImageHandleBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto CoreDisconnectControllerEnd;
- }
- DriverImageHandleCount = 0;
- EfiCoreAcquireLock(&EfiProtocolDatabaseLock);
- CurrentEntry = Handle->ProtocolList.Next;
- while (CurrentEntry != &(Handle->ProtocolList)) {
- ProtocolInterface = LIST_VALUE(CurrentEntry,
- EFI_PROTOCOL_INTERFACE,
- ListEntry);
- ASSERT(ProtocolInterface->Magic == EFI_PROTOCOL_INTERFACE_MAGIC);
- OpenEntry = ProtocolInterface->OpenList.Next;
- while (OpenEntry != &(ProtocolInterface->OpenList)) {
- OpenData = LIST_VALUE(OpenEntry,
- EFI_OPEN_PROTOCOL_DATA,
- ListEntry);
- OpenEntry = OpenEntry->Next;
- if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
- Duplicate = FALSE;
- for (Index = 0;
- Index < DriverImageHandleCount;
- Index += 1) {
- if (DriverImageHandleBuffer[Index] ==
- OpenData->AgentHandle) {
- Duplicate = TRUE;
- break;
- }
- }
- if (Duplicate == FALSE) {
- DriverImageHandleBuffer[DriverImageHandleCount] =
- OpenData->AgentHandle;
- DriverImageHandleCount += 1;
- }
- }
- }
- CurrentEntry = CurrentEntry->Next;
- }
- EfiCoreReleaseLock(&EfiProtocolDatabaseLock);
- }
- //
- // Loop through each driver that has this controller open.
- //
- StopCount = 0;
- for (HandleIndex = 0;
- HandleIndex < DriverImageHandleCount;
- HandleIndex += 1) {
- if (DriverImageHandleBuffer != NULL) {
- DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
- }
- //
- // Get the driver binding protocol of the driver managing this
- // controller.
- //
- Status = EfiCoreHandleProtocol(DriverImageHandle,
- &EfiDriverBindingProtocolGuid,
- (VOID **)&DriverBinding);
- if ((EFI_ERROR(Status)) || (DriverBinding == NULL)) {
- Status = EFI_INVALID_PARAMETER;
- goto CoreDisconnectControllerEnd;
- }
- //
- // Look at each protocol interface for a match.
- //
- DriverImageHandleValid = FALSE;
- ChildBufferCount = 0;
- EfiCoreAcquireLock(&EfiProtocolDatabaseLock);
- CurrentEntry = Handle->ProtocolList.Next;
- while (CurrentEntry != &(Handle->ProtocolList)) {
- ProtocolInterface = LIST_VALUE(CurrentEntry,
- EFI_PROTOCOL_INTERFACE,
- ListEntry);
- ASSERT(ProtocolInterface->Magic == EFI_PROTOCOL_INTERFACE_MAGIC);
- OpenEntry = ProtocolInterface->OpenList.Next;
- while (OpenEntry != &(ProtocolInterface->OpenList)) {
- OpenData = LIST_VALUE(OpenEntry,
- EFI_OPEN_PROTOCOL_DATA,
- ListEntry);
- OpenEntry = OpenEntry->Next;
- ASSERT(OpenData->Magic == EFI_OPEN_PROTOCOL_MAGIC);
- if (OpenData->AgentHandle == DriverImageHandle) {
- if ((OpenData->Attributes &
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- ChildBufferCount += 1;
- }
- if ((OpenData->Attributes &
- EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
- //
- // The driver really does have the controller open.
- //
- DriverImageHandleValid = TRUE;
- }
- }
- }
- CurrentEntry = CurrentEntry->Next;
- }
- EfiCoreReleaseLock(&EfiProtocolDatabaseLock);
- //
- // If the driver really has the controller open, stop it.
- //
- if (DriverImageHandleValid != FALSE) {
- ChildHandleValid = FALSE;
- ChildBuffer = NULL;
- if (ChildBufferCount != 0) {
- ChildBuffer = EfiCoreAllocateBootPool(
- ChildBufferCount * sizeof(EFI_HANDLE));
- if (ChildBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto CoreDisconnectControllerEnd;
- }
- ChildBufferCount = 0;
- EfiCoreAcquireLock(&EfiProtocolDatabaseLock);
- CurrentEntry = Handle->ProtocolList.Next;
- while (CurrentEntry != &(Handle->ProtocolList)) {
- ProtocolInterface = LIST_VALUE(CurrentEntry,
- EFI_PROTOCOL_INTERFACE,
- ListEntry);
- ASSERT(ProtocolInterface->Magic ==
- EFI_PROTOCOL_INTERFACE_MAGIC);
- OpenEntry = ProtocolInterface->OpenList.Next;
- while (OpenEntry != &(ProtocolInterface->OpenList)) {
- OpenData = LIST_VALUE(OpenEntry,
- EFI_OPEN_PROTOCOL_DATA,
- ListEntry);
- OpenEntry = OpenEntry->Next;
- if ((OpenData->AgentHandle == DriverImageHandle) &&
- ((OpenData->Attributes &
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
- Duplicate = FALSE;
- for (Index = 0;
- Index < ChildBufferCount;
- Index += 1) {
- if (ChildBuffer[Index] ==
- OpenData->ControllerHandle) {
- Duplicate = TRUE;
- break;
- }
- }
- if (Duplicate == FALSE) {
- ChildBuffer[ChildBufferCount] =
- OpenData->ControllerHandle;
- if (ChildHandle ==
- ChildBuffer[ChildBufferCount]) {
- ChildHandleValid = TRUE;
- }
- ChildBufferCount += 1;
- }
- }
- }
- CurrentEntry = CurrentEntry->Next;
- }
- EfiCoreReleaseLock(&EfiProtocolDatabaseLock);
- }
- if ((ChildHandle == NULL) || (ChildHandleValid != FALSE)) {
- ChildrenToStop = 0;
- Status = EFI_SUCCESS;
- if (ChildBufferCount > 0) {
- if (ChildHandle != NULL) {
- ChildrenToStop = 1;
- Status = DriverBinding->Stop(DriverBinding,
- ControllerHandle,
- ChildrenToStop,
- &ChildHandle);
- } else {
- ChildrenToStop = ChildBufferCount;
- Status = DriverBinding->Stop(DriverBinding,
- ControllerHandle,
- ChildrenToStop,
- ChildBuffer);
- }
- }
- if ((!EFI_ERROR(Status)) &&
- ((ChildHandle == NULL) ||
- (ChildBufferCount == ChildrenToStop))) {
- Status = DriverBinding->Stop(DriverBinding,
- ControllerHandle,
- 0,
- NULL);
- }
- if (!EFI_ERROR(Status)) {
- StopCount += 1;
- }
- }
- if (ChildBuffer != NULL) {
- EfiCoreFreePool(ChildBuffer);
- }
- }
- }
- if (StopCount > 0) {
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_NOT_FOUND;
- }
- CoreDisconnectControllerEnd:
- if (DriverImageHandleBuffer != NULL) {
- EfiCoreFreePool(DriverImageHandleBuffer);
- }
- return Status;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- EFI_STATUS
- EfipCoreConnectSingleController (
- EFI_HANDLE ControllerHandle,
- EFI_HANDLE *ContextDriverImageHandles,
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- /*++
- Routine Description:
- This routine connects one controller to a driver.
- Arguments:
- ControllerHandle - Supplies the handle of the controller to connect.
- ContextDriverImageHandles - Supplies a pointer to an ordered list of driver
- image handles.
- RemainingDevicePath - Supplies a pointer to the device path that specifies
- a child of the controller.
- Return Value:
- EFI status code.
- --*/
- {
- EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
- EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
- EFI_HANDLE *DriverBindingHandleBuffer;
- UINTN DriverBindingHandleCount;
- EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL *DriverFamilyOverride;
- UINT32 DriverFamilyOverrideVersion;
- BOOLEAN DriverFound;
- EFI_HANDLE DriverImageHandle;
- UINTN HighestIndex;
- UINT32 HighestVersion;
- UINTN Index;
- EFI_HANDLE *NewDriverBindingHandleBuffer;
- UINTN NewDriverBindingHandleCount;
- UINTN NumberOfSortedDriverBindingProtocols;
- BOOLEAN OneStarted;
- EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride;
- EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;
- UINTN SortIndex;
- EFI_STATUS Status;
- DriverBindingHandleCount = 0;
- DriverBindingHandleBuffer = NULL;
- NumberOfSortedDriverBindingProtocols = 0;
- SortedDriverBindingProtocols = NULL;
- //
- // Get a list of all driver binding protocol instances.
- //
- Status = EfiCoreLocateHandleBuffer(ByProtocol,
- &EfiDriverBindingProtocolGuid,
- NULL,
- &DriverBindingHandleCount,
- &DriverBindingHandleBuffer);
- if ((EFI_ERROR(Status)) || (DriverBindingHandleCount == 0)) {
- return EFI_NOT_FOUND;
- }
- //
- // Allocate a duplicate array for the sorted driver binding protocol
- // instances.
- //
- SortedDriverBindingProtocols = EfiCoreAllocateBootPool(
- DriverBindingHandleCount * sizeof(EFI_HANDLE));
- if (SortedDriverBindingProtocols == NULL) {
- EfiCoreFreePool(DriverBindingHandleBuffer);
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Add Driver Binding Protocols from Context Driver Image Handles first.
- //
- if (ContextDriverImageHandles != NULL) {
- Index = 0;
- while (ContextDriverImageHandles[Index] != NULL) {
- EfipCoreAddSortedDriverBindingProtocol(
- ContextDriverImageHandles[Index],
- &NumberOfSortedDriverBindingProtocols,
- SortedDriverBindingProtocols,
- DriverBindingHandleCount,
- DriverBindingHandleBuffer,
- FALSE);
- Index += 1;
- }
- }
- //
- // Add the Platform Driver Override Protocol drivers for the controller
- // handle next.
- //
- Status = EfiCoreLocateProtocol(&EfiPlatformDriverOverrideProtocolGuid,
- NULL,
- (VOID **)&PlatformDriverOverride);
- if ((!EFI_ERROR(Status)) && (PlatformDriverOverride != NULL)) {
- DriverImageHandle = NULL;
- do {
- Status = PlatformDriverOverride->GetDriver(PlatformDriverOverride,
- ControllerHandle,
- &DriverImageHandle);
- if (!EFI_ERROR(Status)) {
- EfipCoreAddSortedDriverBindingProtocol(
- DriverImageHandle,
- &NumberOfSortedDriverBindingProtocols,
- SortedDriverBindingProtocols,
- DriverBindingHandleCount,
- DriverBindingHandleBuffer,
- TRUE);
- }
- } while (!EFI_ERROR(Status));
- }
- //
- // Add the Driver Family Override Protocol drivers fot he controller handle.
- //
- while (TRUE) {
- HighestIndex = DriverBindingHandleCount;
- HighestVersion = 0;
- for (Index = 0; Index < DriverBindingHandleCount; Index += 1) {
- Status = EfiCoreHandleProtocol(DriverBindingHandleBuffer[Index],
- &EfiDriverFamilyOverrideProtocolGuid,
- (VOID **)&DriverFamilyOverride);
- if ((!EFI_ERROR(Status)) && (DriverFamilyOverride != NULL)) {
- DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion(
- DriverFamilyOverride);
- if ((HighestIndex == DriverBindingHandleCount) ||
- (DriverFamilyOverrideVersion > HighestVersion)) {
- HighestVersion = DriverFamilyOverrideVersion;
- HighestIndex = Index;
- }
- }
- }
- if (HighestIndex == DriverBindingHandleCount) {
- break;
- }
- EfipCoreAddSortedDriverBindingProtocol(
- DriverBindingHandleBuffer[HighestIndex],
- &NumberOfSortedDriverBindingProtocols,
- SortedDriverBindingProtocols,
- DriverBindingHandleCount,
- DriverBindingHandleBuffer,
- FALSE);
- }
- //
- // Get the Bus Specific Driver Override Protocol instance on the controller
- // handle.
- //
- Status = EfiCoreHandleProtocol(ControllerHandle,
- &EfiBusSpecificDriverOverrideProtocolGuid,
- (VOID **)&BusSpecificDriverOverride);
- if ((!EFI_ERROR(Status)) && (BusSpecificDriverOverride != NULL)) {
- DriverImageHandle = NULL;
- do {
- Status = BusSpecificDriverOverride->GetDriver(
- BusSpecificDriverOverride,
- &DriverImageHandle);
- if (!EFI_ERROR(Status)) {
- EfipCoreAddSortedDriverBindingProtocol(
- DriverImageHandle,
- &NumberOfSortedDriverBindingProtocols,
- SortedDriverBindingProtocols,
- DriverBindingHandleCount,
- DriverBindingHandleBuffer,
- TRUE);
- }
- } while (!EFI_ERROR(Status));
- }
- //
- // Finally, add all remaining Driver Binding Protocols.
- //
- SortIndex = NumberOfSortedDriverBindingProtocols;
- for (Index = 0; Index < DriverBindingHandleCount; Index += 1) {
- EfipCoreAddSortedDriverBindingProtocol(
- DriverBindingHandleBuffer[Index],
- &NumberOfSortedDriverBindingProtocols,
- SortedDriverBindingProtocols,
- DriverBindingHandleCount,
- DriverBindingHandleBuffer,
- FALSE);
- }
- EfiCoreFreePool(DriverBindingHandleBuffer);
- //
- // If the number of Driver Binding Protocols has increased since this
- // function started, return "not ready" so it will be restarted.
- //
- Status = EfiCoreLocateHandleBuffer(ByProtocol,
- &EfiDriverBindingProtocolGuid,
- NULL,
- &NewDriverBindingHandleCount,
- &NewDriverBindingHandleBuffer);
- EfiCoreFreePool(NewDriverBindingHandleBuffer);
- if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
- EfiCoreFreePool(SortedDriverBindingProtocols);
- return EFI_NOT_READY;
- }
- //
- // Sort the remaining driver binding protocols based on their version field
- // from highest to lowest.
- //
- while (SortIndex < NumberOfSortedDriverBindingProtocols) {
- HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
- HighestIndex = SortIndex;
- for (Index = SortIndex + 1;
- Index < NumberOfSortedDriverBindingProtocols;
- Index += 1) {
- if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
- HighestVersion = SortedDriverBindingProtocols[Index]->Version;
- HighestIndex = Index;
- }
- }
- if (SortIndex != HighestIndex) {
- DriverBinding = SortedDriverBindingProtocols[SortIndex];
- SortedDriverBindingProtocols[SortIndex] =
- SortedDriverBindingProtocols[HighestIndex];
- SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
- }
- SortIndex += 1;
- }
- //
- // Loop until no more drivers can be started on the controller handle.
- //
- OneStarted = FALSE;
- do {
- //
- // Loop through the sorted driver binding protocol instance in order,
- // and see if any of the driver binding protocols support the
- // controller.
- //
- DriverBinding = NULL;
- DriverFound = FALSE;
- for (Index = 0;
- Index < NumberOfSortedDriverBindingProtocols;
- Index += 1) {
- if (DriverFound != FALSE) {
- break;
- }
- if (SortedDriverBindingProtocols[Index] != NULL) {
- DriverBinding = SortedDriverBindingProtocols[Index];
- Status = DriverBinding->Supported(DriverBinding,
- ControllerHandle,
- RemainingDevicePath);
- if (!EFI_ERROR(Status)) {
- SortedDriverBindingProtocols[Index] = NULL;
- DriverFound = TRUE;
- //
- // A driver was found that claims to support the controller,
- // so start the driver on the controller.
- //
- Status = DriverBinding->Start(DriverBinding,
- ControllerHandle,
- RemainingDevicePath);
- if (!EFI_ERROR(Status)) {
- OneStarted = TRUE;
- }
- }
- }
- }
- } while (DriverFound != FALSE);
- EfiCoreFreePool(SortedDriverBindingProtocols);
- //
- // If at least one driver started, declare success.
- //
- if (OneStarted != FALSE) {
- return EFI_SUCCESS;
- }
- //
- // If no drivers started and the remaining device path is an end device
- // node, return success.
- //
- if (RemainingDevicePath != NULL) {
- if (EfiCoreIsDevicePathEnd(RemainingDevicePath) != FALSE) {
- return EFI_SUCCESS;
- }
- }
- //
- // No drivers were started on the controller.
- //
- return EFI_NOT_FOUND;
- }
- VOID
- EfipCoreAddSortedDriverBindingProtocol (
- EFI_HANDLE DriverBindingHandle,
- UINTN *NumberOfSortedDriverBindingProtocols,
- EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,
- UINTN DriverBindingHandleCount,
- EFI_HANDLE *DriverBindingHandleBuffer,
- BOOLEAN IsImageHandle
- )
- /*++
- Routine Description:
- This routine adds a driver binding protocol to a sorted driver binding
- protocol list.
- Arguments:
- DriverBindingHandle - Supplies the handle of the driver binding protcol.
- NumberOfSortedDriverBindingProtocols - Supplies a pointer containing the
- number os sorted driver binding protocols. This will be incremented by
- this function.
- SortedDriverBindingProtocols - Supplies the sorted protocol list.
- DriverBindingHandleCount - Supplies the number of handles in the driver
- binding handle buffer.
- DriverBindingHandleBuffer - Supplies the buffer of driver binding handles
- to be modified.
- IsImageHandle - Supplies a boolean indicating if the driver binding handle
- is an image handle.
- Return Value:
- None.
- --*/
- {
- EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
- UINTN Index;
- EFI_STATUS Status;
- Status = EfipCoreValidateHandle(DriverBindingHandle);
- if (EFI_ERROR(Status)) {
- ASSERT(FALSE);
- return;
- }
- //
- // If the handle is an image handle, find all the driver binding handles
- // associated with that image handle and add them to the sorted list.
- //
- if (IsImageHandle != FALSE) {
- for (Index = 0; Index < DriverBindingHandleCount; Index += 1) {
- Status = EfiCoreHandleProtocol(DriverBindingHandleBuffer[Index],
- &EfiDriverBindingProtocolGuid,
- (VOID **)&DriverBinding);
- if ((EFI_ERROR(Status)) || (DriverBinding == NULL)) {
- continue;
- }
- //
- // If the image handle associated with the driver binding matches
- // the driver binding handle, then add the driver binding to the
- // list.
- //
- if (DriverBinding->ImageHandle == DriverBindingHandle) {
- EfipCoreAddSortedDriverBindingProtocol(
- DriverBindingHandleBuffer[Index],
- NumberOfSortedDriverBindingProtocols,
- SortedDriverBindingProtocols,
- DriverBindingHandleCount,
- DriverBindingHandleBuffer,
- FALSE);
- }
- }
- return;
- }
- Status = EfiCoreHandleProtocol(DriverBindingHandle,
- &EfiDriverBindingProtocolGuid,
- (VOID **)&DriverBinding);
- if ((EFI_ERROR(Status)) || (DriverBinding == NULL)) {
- return;
- }
- //
- // See if the driver binding is already on the list.
- //
- for (Index = 0;
- Index < *NumberOfSortedDriverBindingProtocols;
- Index += 1) {
- if (Index >= DriverBindingHandleCount) {
- break;
- }
- if (DriverBinding == SortedDriverBindingProtocols[Index]) {
- return;
- }
- }
- //
- // Add the driver binding to the end of the list.
- //
- if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
- SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] =
- DriverBinding;
- }
- *NumberOfSortedDriverBindingProtocols += 1;
- //
- // Mark the corresponding handle in the driver binding handle buffer as
- // used.
- //
- for (Index = 0; Index < DriverBindingHandleCount; Index += 1) {
- if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
- DriverBindingHandleBuffer[Index] = NULL;
- }
- }
- return;
- }
|