UEFI Driver Binding Protocol Explained
The Unified Extensible Firmware Interface (UEFI) uses a modular, event-driven architecture to discover hardware and initialize devices before an operating system loads. Central to this process is the UEFI Driver Binding Protocol, a standardized mechanism that enables the firmware to dynamically evaluate system handles, determine compatibility between hardware controllers and available drivers, and bind the appropriate driver to each device. This model eliminates the need for hardcoded device initialization sequences, providing a flexible framework for managing complex, modern platform hardware.
The Role of Handles and Protocols
UEFI represents all system resources—including physical hardware,
buses, and logical software abstractions—as unique entities called
handles. Hardware controllers exist in the firmware database as handles
that publish protocols describing their capabilities, such as a
Device Path Protocol or a
PCI I/O Protocol.
Drivers are also represented as handles in the UEFI database. A
driver capable of managing hardware registers an instance of the
EFI_DRIVER_BINDING_PROTOCOL. This protocol acts as the
standardized interface through which the UEFI core interacts with the
driver to test and establish hardware control.
The Three Core Functions of Driver Binding
Every driver implementing the Driver Binding Protocol provides pointers to three fundamental functions:
Supported(): Tests whether a driver supports a given controller handle without modifying the hardware state or allocating major resources.Start(): Instructs the driver to take control of the controller handle, initialize the hardware, allocate necessary runtime or boot resources, and install new protocol interfaces (such asBlock I/OorSimple Network Protocol).Stop(): Directs the driver to stop managing the controller, release all allocated memory, uninstall published protocols, and return the hardware to a quiescent state.
The Matching Mechanism: How ConnectController Works
Hardware matching is driven by the UEFI Boot Service function
ConnectController(). When the platform firmware boots, the
system initiates a scan across all registered controller handles and
performs the following sequence to find the correct driver:
1. Querying Drivers with
Supported()
The firmware engine iterates through all registered
EFI_DRIVER_BINDING_PROTOCOL instances and passes the target
controller handle to each driver’s Supported()
function.
Inside Supported(), the driver checks the target
controller handle to see if it exposes the prerequisite protocols. For
example, a SATA driver checks if the handle provides a
PCI I/O Protocol and queries the PCI configuration space to
verify if the Vendor ID, Device ID, or Class Code matches a supported
storage controller. If the driver cannot manage the device, it returns
EFI_UNSUPPORTED. If it can, it returns
EFI_SUCCESS.
2. Driver Precedence and Prioritization
If multiple drivers return EFI_SUCCESS for a single
controller handle, UEFI resolves the conflict using a strict precedence
hierarchy:
- Platform Override Protocol: Gives platform-specific firmware policies top priority.
- Driver Family Override Protocol: Allows a vendor to supply an updated or specialized driver that supersedes a generic driver.
- Bus Specific Driver Override Protocol: Allows a parent bus driver to suggest a specific driver for a child device.
- Version Matching: If no override policies apply, UEFI selects the driver with the highest driver binding version number.
3. Binding Hardware with
Start()
Once the best matching driver is determined, UEFI invokes that
driver’s Start() function. The driver programs the
hardware, configures operational states, and installs higher-level
protocols onto the controller handle. This allows downstream components,
boot managers, and operating system loaders to communicate with the
hardware through generic, device-agnostic interfaces.
Hierarchical Matching and Bus Enumeration
The Driver Binding Protocol also handles device hierarchies, such as
PCI host controllers, USB controllers, and connected peripherals. When a
bus driver binds to a controller via its Start() function,
it enumerates child devices on that bus and creates a new handle for
each detected peripheral.
Once these child handles are registered, UEFI recursively triggers
ConnectController() on each new handle. For example, a USB
host controller driver creates child handles for attached USB flash
drives, which in turn match with a generic USB Mass Storage driver,
which finally produces a Block I/O Protocol handle for the
UEFI file system. This recursive matching continues until all hardware
controllers are bound to their respective drivers.