6.1.6 Device driver protocol management
Device drivers consume one or more I/O-related protocols and use the services
of those protocols to produce one or more I/O-related protocols. The
Supported()
and Start()
functions of the Driver Binding Protocol are
responsible for opening the I/Orelated protocols being consumed using the EFI
Boot Service OpenProtocol()
. The Stop()
function is responsible for closing
the consumed I/O-related protocols using CloseProtocol()
.
A protocol can be opened in several different modes, but the most common is
EFI_OPEN_PROTOCOL_BY_DRIVER
. When a protocol is opened by
EFI_OPEN_PROTOCOL_BY_DRIVER
, a test is made to see if that protocol is
already being consumed by any other drivers. The open operation succeeds only
if the protocol is not being consumed by any other drivers.
Caution: Using the OpenProtocol()
service with
EFIOPEN_PROTOCOL_BY_DRIVER is how resource conflicts are avoided in the
UEFI driver model. However, it requires that every driver present in the system
follow the driver interoperability rules for all resource conflicts to be
avoided._
The following figure shows the image handle for a device driver as
LoadImage()
and StartImage()
are called. In addition, it shows the states
of three different controller handles as the Driver Binding Protocol services
Supported()
, Start()
, and Stop()
are called. Controller Handle 1
and
Controller Handle 3
pass the Supported()
test, so the Start()
function
can be called. In this case, the Supported()
service tests to see if the
controller handle supports Protocol A. Start()
is then called for Controller Handle 1
and Controller Handle 3
. In the Start()
function, Protocol A
is opened EFI_OPEN_PROTOCOL_BY_DRIVER
, and Protocol B
is installed onto the same controller handle. The implementation of Protocol B
uses the services of Protocol A
to produce the services of Protocol B
.
All drivers that follow the UEFI driver model must support the Stop()
service. The Stop()
service must put the handles back into their previous
state, before Start()
was called, so the Stop()
service uninstalls
Protocol B
and closes Protocol A
.
Figure 12-Device driver protocol management
The figure below shows a more complex device driver that requires Protocol A
and Protocol B
to produce Protocol C
. Notice that the controller handles that do not support either Protocol A
or Protocol B
do not pass the Supported()
test. In addition, controller handles that only support Protocol A
or only Protocol B
also do not pass the Supported()
test. Finally, note that Controller Handle 6
already has Protocol A
opened by EFI_OPEN_PROTOCOL_BY_DRIVER
, so this device driver requiring both Protocol A
and Protocol B
also does not pass the Supported()
test.
This example highlights some of the flexibility of the UEFI driver model.
Because the Supported()
and Start()
services are functions, a driver writer
can implement simple or complex algorithms to test driver support for a
specific controller handle.
Figure 13-Complex device driver protocol management
TIP: The best way to design the algorithm for the opening protocols is to write a Boolean expression for the protocols that a device driver consumes. Then, expand this Boolean expression into the sum of products form. Each product in the expanded expression requires its own Driver Binding Protocol.
This scenario is another way that a device driver may be required to produce
multiple instances of the Driver Binding Protocol. The Supported()
service
for each Driver Binding Protocol attempts to open each protocol in a product
term. If any of those open operations fail, then Supported()
fails. If all
the opens succeed, then the Supported()
test passes. The Start()
function
should open each protocol in the product term, and the Stop()
function should
close each protocol in the product term.
For example, the two examples above would have the following Boolean expressions:
(
Protocol A
)(
Protocol A
ANDProtocol B
)
These two expressions have only one product term, so only one EFI_DRIVER_BINDING_PROTOCOL
is required. A more complex expression would be
as follows:
- (
Protocol A
AND (Protocol B
ORProtocol C
))
If this Boolean expression is expanded into a sum of product form, it would yield the following:
- ((
Protocol A
ANDProtocol C
) OR (Protocol B
ANDProtocol C
))
This expression would require a driver with two instances of the EFI_DRIVER_BINDING_PROTOCOL
. One would test for Protocol A
and Protocol C
, and the other would test for Protocol B
and Protocol C