EFI DRIVER BINDING PROTOCOL

From PhoenixWiki

Jump to: navigation, search

Provides the services required to determine if a driver supports a given controller. If a controller is supported, then it also provides routines to start and stop the controller.

Contents

GUID

#define EFI_DRIVER_BINDING_PROTOCOL_GUID \
  {0x18A031AB,0xB443,0x4D1A,0xA5,0xC0,0x0C,0x09,0x26,0x1E,0x9F,0x71}

Protocol Interface Structure

#include EFI_PROTOCOL_PRODUCER(DriverBinding)  

extern EFI_GUID gEfiDriverBindingProtocolGuid;
typedef struct _EFI_DRIVER_BINDING_PROTOCOL {
  EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED Supported;
  EFI_DRIVER_BINDING_PROTOCOL_START     Start;
  EFI_DRIVER_BINDING_PROTOCOL_STOP      Stop;
  UINT32                                Version;
  EFI_HANDLE                            ImageHandle;
  EFI_HANDLE                            DriverBindingHandle;
} EFI_DRIVER_BINDING_PROTOCOL;

Members

Member Description
Supported Tests to see if this driver supports a given controller. This service is called by the EFI boot service ConnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. ConnectController() must follow these calling restrictions. If any other agent wishes to call Supported() it must also follow these calling restrictions.
Start Starts a controller using this driver. This service is called by the EFI boot service ConnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. ConnectController() must follow these calling restrictions. If any other agent wishes to call Start() it must also follow these calling restrictions.
Stop Stops a controller using this driver. This service is called by the EFI boot service DisconnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. DisconnectController() must follow these calling restrictions. If any other agent wishes to call Stop() it must also follow these calling restrictions.
Version The version number of the UEFI driver that produced the EFI_DRIVER_BINDING_PROTOCOL. This field is used by the EFI boot service ConnectController() to determine the order that driver's Supported() service will be used when a controller needs to be started. EFI Driver Binding Protocol instances with higher Version values will be used before ones with lower Version values. The Version values of 0x0-0x0f and 0xfffffff0-0xffffffff are reserved for platform/OEM specific drivers. The Version values of 0x10-0xffffffef are reserved for IHV-developed drivers.
ImageHandle The image handle of the UEFI driver that produced this instance of the EFI_DRIVER_BINDING_PROTOCOL.
DriverBindingHandle The handle on which this instance of the EFI_DRIVER_BINDING_PROTOCOL is installed. In most cases, this is the same handle as ImageHandle. However, for UEFI drivers that produce more than one instance of the EFI_DRIVER_BINDING_PROTOCOL, this value may not be the same as ImageHandle.

Description

The EFI_DRIVER_BINDING_PROTOCOL provides a service to determine if a driver supports a given controller. If a controller is supported, then it also provides services to start and stop the controller. All UEFI drivers are required to be reentrant so they can manage one or more controllers. This requires that drivers not use global variables to store device context. Instead, they must allocate a separate context structure per controller that the driver is managing. Bus drivers must support starting and stopping the same bus multiple times, and they must also support starting and stopping all of their children, or just a subset of their children.

Supported()

Tests to see if this driver supports a given controller. If a child device is provided, it further tests to see if this driver supports creating a handle for the specified child device.

Prototype

typedef
EFI_STATUS
(EFIAPI *EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED) (
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
  IN EFI_HANDLE ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL);

Parameters

Parameter Description
This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
ControllerHandle The handle of the controller to test. This handle must support a protocol interface that supplies an I/O abstraction to the driver. Sometimes just the presence of this I/O abstraction is enough for the driver to determine if it supports ControllerHandle. Sometimes, the driver may use the services of the I/O abstraction to determine if this driver supports ControllerHandle.
RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. For bus drivers, if this parameter is not NULL, then the bus driver must determine if the bus controller specified by ControllerHandle and the child controller specified by RemainingDevicePath are both supported by this bus driver.

Description
This function checks to see if the driver specified by This supports the device specified by ControllerHandle. Drivers will typically use the device path attached to ControllerHandle and/or the services from the bus I/O abstraction attached to ControllerHandle to determine if the driver supports ControllerHandle. This function may be called many times during platform initialization. In order to reduce boot times, the tests performed by this function must be very small, and take as little time as possible to execute. This function must not change the state of any hardware devices, and this function must be aware that the device specified by ControllerHandle may already be managed by the same driver or a different driver. This function must match its calls to AllocatePages() with FreePages(), AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). Since ControllerHandle may have been previously started by the same driver, if a protocol is already in the opened state, then it must not be closed with CloseProtocol(). This is required to guarantee the state of ControllerHandle is not modified by this function.

If any of the protocol interfaces on the device specified by ControllerHandle that are required by the driver specified by This are already open for exclusive access by a different driver or application, then EFI_ACCESS_DENIED is returned.

If any of the protocol interfaces on the device specified by ControllerHandle that are required by the driver specified by This are already opened by the same driver, then EFI_ALREADY_STARTED is returned. However, if the driver specified by This is a bus driver, then it is not an error, and the bus driver should continue with its test of ControllerHandle and RemainingDevicePath. This allows a bus driver to create one child handle on the first call to Supported() and Start(), and create additional child handles on additional calls to Supported() and Start().This also allows a bus driver to create no child handle on the first call to Supported() and Start() by specifying an End of Device Path Node RemainingDevicePath, and create additional child handles on additional calls to Supported() and Start().

If ControllerHandle is not supported by This, then EFI_UNSUPPORTED is returned.

If This is a bus driver that creates child handles with an EFI_DEVICE_PATH_PROTOCOL, then ControllerHandle must support the EFI_DEVICE_PATH_PROTOCOL. If it does not, then EFI_UNSUPPORTED is returned.

If ControllerHandle is supported by This, and This is a device driver, then EFI_SUCCESS is returned.

If ControllerHandle is supported by This, and This is a bus driver, and RemainingDevicePath is NULLor the first Device Path Node is the End of Device Path Node, then EFI_SUCCESS is returned.

If ControllerHandle is supported by This, and This is a bus driver, and RemainingDevicePath is not NULL, then RemainingDevicePath must be analyzed. If the first node of RemainingDevicePath is the End of Device Path Node or an EFI Device Path node that the bus driver recognizes and supports, then EFI_SUCCESS is returned. Otherwise, EFI_UNSUPPORTED is returned.

The Supported() function is designed to be invoked from the EFI boot service ConnectController(). As a result, much of the error checking on the parameters to Supported() has been moved into this common boot service. It is legal to call Supported() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic.

ControllerHandle must be a valid EFI_HANDLE. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned EFI_DEVICE_PATH_PROTOCOL.

Status Codes Returned

Status Code Description
EFI_SUCCESS The device specified by ControllerHandle and RemainingDevicePath is supported by the driver specified by This.
EFI_ALREADY_STARTED The device specified by ControllerHandle and RemainingDevicePath is already being managed by the driver specified by This.
EFI_ACCESS_DENIED The device specified by ControllerHandle and RemainingDevicePath is already being managed by a different driver or an application that requires exclusive access.
EFI_UNSUPPORTED The device specified by ControllerHandle and RemainingDevicePath is not supported by the driver specified by This.

Pseudo Code
Listed below are the algorithms for the Supported() function for three different types of drivers. How the Start() function of a driver is implemented can affect how the Supported() function is implemented. All of the services in the EFI_DRIVER_BINDING_PROTOCOL need to work together to make sure that all resources opened or allocated in Supported() and Start() are released in Stop().

The first algorithm is a simple device driver that does not create any additional handles. It only attaches one or more protocols to an existing handle. The second is a bus driver that always creates all of its child handles on the first call to Start(). The third is a more advanced bus driver that can either create one child handles at a time on successive calls to Start(), or it can create all of its child handles or all of the remaining child handles in a single call to Start().


Device Driver:

  1. Ignore the parameter RemainingDevicePath.
  2. Open all required protocols with OpenProtocol(). A standard driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. If this driver needs exclusive access to a protocol interface, and it requires any drivers that may be using the protocol interface to disconnect, then the driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE.
  3. If any of the calls to OpenProtocol() in (2) returned an error, then close all of the protocols opened in (2) with CloseProtocol(), and return the status code from the call to OpenProtocol() that returned an error.
  4. Use the protocol instances opened in (2) to test to see if this driver supports the controller. Sometimes, just the presence of the protocols is enough of a test. Other times, the services of the protocols opened in (2) are used to further check the identity of the controller. If any of these tests fails, then close all the protocols opened in (2) with CloseProtocol() and return EFI_UNSUPPORTED.
  5. Close all protocols opened in (2) with CloseProtocol().
  6. Return EFI_SUCCESS.


Bus Driver that creates all of its child handles on the first call to Start():

  1. Check the contents of the first Device Path Node of RemainingDevicePath to make sure it is the End of Device Path Node or a legal Device Path Node for this bus driver’s children. If it is not, then return EFI_UNSUPPORTED.
  2. Open all required protocols with OpenProtocol(). A standard driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. If this driver needs exclusive access to a protocol interface, and it requires any drivers that may be using the protocol interface to disconnect, then the driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE.
  3. If any of the calls to OpenProtocol() in (2) returned an error, then close all of the protocols opened in (2) with CloseProtocol(), and return the status code from the call to OpenProtocol() that returned an error.
  4. Use the protocol instances opened in (2) to test to see if this driver supports the controller. Sometimes, just the presence of the protocols is enough of a test. Other times, the services of the protocols opened in (2) are used to further check the identity of the controller. If any of these tests fails, then close all the protocols opened in (2) with CloseProtocol() and return EFI_UNSUPPORTED.
  5. Close all protocols opened in (2) with CloseProtocol().
  6. Return EFI_SUCCESS.


Bus Driver that is able to create all or one of its child handles on each call to Start():

  1. Check the contents of the first Device Path Node of RemainingDevicePath to make sure it is the End of Device Path Node or a legal Device Path Node for this bus driver’s children. If it is not, then return EFI_UNSUPPORTED.
  2. Open all required protocols with OpenProtocol(). A standard driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. If this driver needs exclusive access to a protocol interface, and it requires any drivers that may be using the protocol interface to disconnect, then the driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE.
  3. If any of the calls to OpenProtocol() in (2) failed with an error other than EFI_ALREADY_STARTED, then close all of the protocols opened in (2) that did not return EFI_ALREADY_STARTED with CloseProtocol(), and return the status code from the OpenProtocol() call that returned an error.
  4. Use the protocol instances opened in (2) to test to see if this driver supports the controller. Sometimes, just the presence of the protocols is enough of a test. Other times, the services of the protocols opened in (2) are used to further check the identity of the controller. If any of these tests fails, then close all the protocols opened in (2) that did not return EFI_ALREADY_STARTED with CloseProtocol() and return EFI_UNSUPPORTED.
  5. Close all protocols opened in (2) that did not return EFI_ALREADY_STARTED with CloseProtocol().
  6. Return EFI_SUCCESS.

Start()

Starts a device controller or a bus controller. The Start() and Stop() services of the EFI_DRIVER_BINDING_PROTOCOL mirror each other.

Prototype

typedef
EFI_STATUS
(EFIAPI *EFI_DRIVER_BINDING_PROTOCOL_START) (
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
  IN EFI_HANDLE ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL);

Parameters

Parameter Description
This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
ControllerHandle The handle of the controller to start. This handle must support a protocol interface that supplies an I/O abstraction to the driver.
RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. For a bus driver, if this parameter is NULL, then handles for all the children of Controller are created by this driver. If this parameter is not NULL and the first Device Path Node is not the End of Device Path Node, then only the handle for the child device specified by the first Device Path Node of RemainingDevicePath is created by this driver. If the first Device Path Node of RemainingDevicePath is the End of Device Path Node, no child handle is created by this driver.

Description
This function starts the device specified by Controller with the driver specified by This. Whatever resources are allocated in Start() must be freed in Stop(). For example, every AllocatePool(), AllocatePages(), OpenProtocol(), and InstallProtocolInterface() in Start() must be matched with a FreePool(), FreePages(), CloseProtocol(), and UninstallProtocolInterface() in Stop().

If Controller is started, then EFI_SUCCESS is returned. If Controller cannot be started due to a device error, then EFI_DEVICE_ERROR is returned. If there are not enough resources to start the device or bus specified by Controller, then EFI_OUT_OF_RESOURCES is returned.

If the driver specified by This is a device driver, then RemainingDevicePath is ignored.

If the driver specified by This is a bus driver, and RemainingDevicePath is NULL, then all of the children of Controller are discovered and enumerated, and a device handle is created for each child.

If the driver specified by This is a bus driver, and RemainingDevicePath is not NULL and begins with the End of Device Path node, then the driver must not enumerate any of the children of Controller nor create any child device handle. Only the controller initialization should be performed. If the driver implements EFI_DRIVER_DIAGNOSTICS_PROTOCOL, EFI_COMPONENT_NAME2_PROTOCOL, EFI_SERVICE_BINDING_PROTOCOL, EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL, or EFI_DRIVER_HEALTH_PROTOCOL, the driver still should install the implemented protocols. If the driver supports EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL, the driver still should retrieve and process the configuration information.

If the driver specified by This is a bus driver that is capable of creating one child handle at a time and RemainingDevicePath is not NULL and does not begin with the End of Device Path node, then an attempt is made to create the device handle for the child device specified by RemainingDevicePath. Depending on the bus type, all of the child devices may need to be discovered and enumerated, but at most only the device handle for the one child specified by RemainingDevicePath shall be created.

The Start() function is designed to be invoked from the EFI boot service ConnectController(). As a result, much of the error checking on the parameters to Start() has been moved into this common boot service. It is legal to call Start() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic.

  • ControllerHandle must be a valid EFI_HANDLE.
  • If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned EFI_DEVICE_PATH_PROTOCOL.
  • Prior to calling Start(), the Supported() function for the driver specified by This must have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.

Status Codes Returned

Status Code Description
EFI_SUCCESS The device was started.
EFI_DEVICE_ERROR The device could not be started due to a device error.
EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.

Pseudo Code
Listed below are the algorithms for the Start() function for three different types of drivers. How the Start() function of a driver is implemented can affect how the Supported() function is implemented. All of the services in the EFI_DRIVER_BINDING_PROTOCOL need to work together to make sure that all resources opened or allocated in Supported() and Start() are released in Stop().

The first algorithm is a simple device driver that does not create any additional handles. It only attaches one or more protocols to an existing handle. The second is a simple bus driver that always creates all of its child handles on the first call to Start(). It does not attach any additional protocols to the handle for the bus controller. The third is a more advanced bus driver that can either create one child handles at a time on successive calls to Start(), or it can create all of its child handles or all of the remaining child handles in a single call to Start(). Once again, it does not attach any additional protocols to the handle for the bus controller.

Device Driver:

  1. Ignore the parameter RemainingDevicePath with the exception that if the first Device Path Node is the End of Device Path Node, skip steps 5-8.
  2. Open all required protocols with OpenProtocol(). A standard driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. If this driver needs exclusive access to a protocol interface, and it requires any drivers that may be using the protocol interface to disconnect, then the driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE. It must use the same Attribute value that was used in Supported().
  3. If any of the calls to OpenProtocol() in (2) returned an error, then close all of the protocols opened in (2) with CloseProtocol(), and return the status code from the call to OpenProtocol() that returned an error.
  4. Initialize the device specified by ControllerHandle. If an error occurs, close all of the protocols opened in (2) with CloseProtocol(), and return EFI_DEVICE_ERROR.
  5. Allocate and initialize all of the data structures that this driver requires to manage the device specified by ControllerHandle. This would include space for public protocols and space for any additional private data structures that are related to ControllerHandle. If an error occurs allocating the resources, then close all of the protocols opened in (2) with CloseProtocol(), and return EFI_OUT_OF_RESOURCES.
  6. Install all the new protocol interfaces onto ControllerHandle using InstallMultipleProtocolInterfaces(). If an error occurs, close all of the protocols opened in (1) with CloseProtocol(), and return the error from InstallMultipleProtocolInterfaces().
  7. Return EFI_SUCCESS.

Bus Driver that creates all of its child handles on the first call to Start():

  1. Ignore the parameter RemainingDevicePath.
  2. Open all required protocols with OpenProtocol(). A standard driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. If this driver needs exclusive access to a protocol interface, and it requires any drivers that may be using the protocol interface to disconnect, then the driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE. It must use the same Attribute value that was used in Supported().
  3. If any of the calls to OpenProtocol() in (2) returned an error, then close all of the protocols opened in (2) with CloseProtocol(), and return the status code from the call to OpenProtocol() that returned an error.
  4. Initialize the device specified by ControllerHandle. If an error occurs, close all of the protocols opened in (2) with CloseProtocol(), and return EFI_DEVICE_ERROR.
  5. Discover all the child devices of the bus controller specified by ControllerHandle.
  6. If the bus requires it, allocate resources to all the child devices of the bus controller specified by ControllerHandle.
  7. FOR each child C of ControllerHandle:
    1. Allocate and initialize all of the data structures that this driver requires to manage the child device C. This would include space for public protocols and space for any additional private data structures that are related to the child device C. If an error occurs allocating the resources, then close all of the protocols opened in (2) with CloseProtocol(), and return EFI_OUT_OF_RESOURCES.
    2. If the bus driver creates device paths for the child devices, then create a device path for the child C based upon the device path attached to ControllerHandle.
    3. Initialize the child device C. If an error occurs, close all of the protocols opened in (2) with CloseProtocol(), and return EFI_DEVICE_ERROR.
    4. Create a new handle for C, and install the protocol interfaces for child device C using InstallMultipleProtocolInterfaces(). This may include the EFI_DEVICE_PATH_PROTOCOL.
    5. Call OpenProtocol() on behalf of the child C with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  8. END FOR
  9. If the bus driver also produces protocols on ControllerHandle, then install all the new protocol interfaces onto ControllerHandle using InstallMultipleProtocolInterfaces(). If an error occurs, close all of the protocols opened in (2) with CloseProtocol(), and return the error from InstallMultipleProtocolInterfaces().
  10. Return EFI_SUCCESS.

Bus Driver that is able to create all or one of its child handles on each call to Start():

  1. Open all required protocols with OpenProtocol(). A standard driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. If this driver needs exclusive access to a protocol interface, and it requires any drivers that may be using the protocol interface to disconnect, then the driver should use an Attribute of EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE. It must use the same Attribute value that was used in Supported().
  2. If any of the calls to OpenProtocol() in (1) returned an error, then close all of the protocols opened in (1) with CloseProtocol(), and return the status code from the call to OpenProtocol() that returned an error.
  3. Initialize the device specified by ControllerHandle. If an error occurs, close all of the protocols opened in (1) with CloseProtocol(), and return EFI_DEVICE_ERROR.
  4. IF RemainingDevicePath is not NULL, THEN
    1. C is the child device specified by RemainingDevicePath. If the first Device Path Node is the End of Device Path Node, proceed to step 6.
    2. Allocate and initialize all of the data structures that this driver requires to manage the child device C. This would include space for public protocols and space for any additional private data structures that are related to the child device C. If an error occurs allocating the resources, then close all of the protocols opened in (1) with CloseProtocol(), and return EFI_OUT_OF_RESOURCES.
    3. If the bus driver creates device paths for the child devices, then create a device path for the child C based upon the device path attached to ControllerHandle.
    4. Initialize the child device C.
    5. Create a new handle for C, and install the protocol interfaces for child device C using InstallMultipleProtocolInterfaces(). This may include the EFI_DEVICE_PATH_PROTOCOL.
    6. Call OpenProtocol() on behalf of the child C with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  5. ELSE
    1. Discover all the child devices of the bus controller specified by ControllerHandle.
    2. If the bus requires it, allocate resources to all the child devices of the bus controller specified by ControllerHandle.
    3. FOR each child C of ControllerHandle
      1. Allocate and initialize all of the data structures that this driver requires to manage the child device C. This would include space for public protocols and space for any additional private data structures that are related to the child device C. If an error occurs allocating the resources, then close all of the protocols opened in (1) with CloseProtocol(), and return EFI_OUT_OF_RESOURCES.
      2. If the bus driver creates device paths for the child devices, then create a device path for the child C based upon the device path attached to ControllerHandle.
      3. Initialize the child device C.
      4. Create a new handle for C, and install the protocol interfaces for child device C using InstallMultipleProtocolInterfaces(). This may include the EFI_DEVICE_PATH_PROTOCOL.
      5. Call OpenProtocol() on behalf of the child C with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    4. END FOR
  6. END IF
  7. If the bus driver also produces protocols on ControllerHandle, then install all the new protocol interfaces onto ControllerHandle using InstallMultipleProtocolInterfaces(). If an error occurs, close all of the protocols opened in (2) with CloseProtocol(), and return the error from InstallMultipleProtocolInterfaces().
  8. Return EFI_SUCCESS.

Stop()

Stops a device controller or a bus controller. The Start() and Stop() services of the EFI_DRIVER_BINDING_PROTOCOL mirror each other.

Prototype

typedef
EFI_STATUS
(EFIAPI *EFI_DRIVER_BINDING_PROTOCOL_STOP) (
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
  IN EFI_HANDLE ControllerHandle,
  IN UINTN NumberOfChildren,
  IN EFI_HANDLE *ChildHandleBuffer OPTIONAL);

Parameters

Parameter Description
This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
ControllerHandle A handle to the device being stopped. The handle must support a bus specific I/O protocol for the driver to use to stop the device.
NumberOfChildren The number of child device handles in ChildHandleBuffer.
ChildHandleBuffer An array of child handles to be freed. May be NULL if NumberOfChildren is 0.

Description
This function performs different operations depending on the parameter NumberOfChildren. If NumberOfChildren is not zero, then the driver specified by This is a bus driver, and it is being requested to free one or more of its child handles specified by NumberOfChildren and ChildHandleBuffer. If all of the child handles are freed, then EFI_SUCCESS is returned. If NumberOfChildren is zero, then the driver specified by This is either a device driver or a bus driver, and it is being requested to stop the controller specified by ControllerHandle. If ControllerHandle is stopped, then EFI_SUCCESS is returned.

In either case, this function is required to undo what was performed in Start(). Whatever resources are allocated in Start() must be freed in Stop(). For example, every AllocatePool(), AllocatePages(), OpenProtocol(), and InstallProtocolInterface() in Start() must be matched with a FreePool(), FreePages(), CloseProtocol(), and UninstallProtocolInterface() in Stop().

If ControllerHandle cannot be stopped, then EFI_DEVICE_ERROR is returned. If, for some reason, there are not enough resources to stop ControllerHandle, then EFI_OUT_OF_RESOURCES is returned.

The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). As a result, much of the error checking on the parameters to Stop() has been moved into this common boot service. It is legal to call Stop() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic.

  • ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this same driver’s Start() function.
  • The first NumberOfChildren handles of ChildHandleBuffer must all be a valid EFI_HANDLE. In addition, all of these handles must have been created in this driver’s Start() function, and the Start() function must have called OpenProtocol() on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.

Status Codes Returned

Status Code Description
EFI_SUCCESS The device was stopped.
EFI_DEVICE_ERROR The device could not be stopped due to a device error.

Pseudo Code

Device Driver:

  1. Uninstall all the protocols that were installed onto ControllerHandle in Start().
  2. Close all the protocols that were opened on behalf of ControllerHandle in Start().
  3. Free all the structures that were allocated on behalf of ControllerHandle in Start().
  4. Return EFI_SUCCESS.

Bus Driver that creates all of its child handles on the first call to Start():
Bus Driver that is able to create all or one of its child handles on each call to Start():

  1. IF NumberOfChildren is zero THEN:
    1. Uninstall all the protocols that were installed onto ControllerHandle in Start().
    2. Close all the protocols that were opened on behalf of ControllerHandle in Start().
    3. Free all the structures that were allocated on behalf of ControllerHandle in Start().
  2. ELSE
    1. FOR each child C in ChildHandleBuffer
      1. Uninstall all the protocols that were installed onto C in Start().
      2. Close all the protocols that were opened on behalf of C in Start().
      3. Free all the structures that were allocated on behalf of C in Start().
    2. END FOR
  3. END IF
  4. Return EFI_SUCCESS.


Copyright (C) 2008-2009 Phoenix Technologies Ltd. All Rights Reserved. Portions copyright (C) 2008 UEFI Forum, Inc. Used with permission.

Personal tools