5.2.3 LocateDevicePath()
This service locates a device handle that supports a specific protocol and has the closest matching device path. Although a rare requirement, it is useful when a UEFI Driver needs to find an I/O abstraction for one of its parent controllers.
Normally, a UEFI Driver uses the services on the ControllerHandle that is
passed into the Supported()
and Start()
functions of the EFI driver's
EFI_DRIVER_BINDING_PROTOCOL
. However, if a UEFI Driver does require the use of services from a parent
controller, LocateDevicePath()
can be used to find the handle of a parent
controller.
For example, a PCI device driver normally uses the PCI I/O Protocol to manage a
PCI controller. Hypothetically, if a PCI device driver required the services of
the PCI Root Bridge I/O Protocol of which the PCI controller is a child, then
the gBS->LocateDevicePath()
function can be used to find the parent handle that
supports the PCI Root Bridge I/O Protocol. Then the gBS->OpenProtocol()
service can be used to retrieve the PCI Root Bridge I/O Protocol interface from
that handle.
The code fragment below shows how a UEFI Driver for a PCI Controller can retrieve the PCI Root Bridge I/O Protocol of which the PCI controller is a child.
Caution: This operation is provided only as an illustration and is not recommended because a parent bus driver typically owns the parent I/O abstractions. Directly using a parent I/O may cause unintended side effects.
Section 18.4.2, Example 175, contains another example showing the recommended method for a PCI driver to access the resources of other PCI controllers on the same PCI adapter without using the PCI Root Bridge I/O Protocol.
Example 63-Locate Device Path
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
EFI_STATUS Status;
EFI_HANDLE ControllerHandle;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_HANDLE ParentHandle;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
//
// Retrieve the Device Path Protocol instance on ControllerHandle
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDevicePathProtocolGuid,
(VOID **)&DevicePath,
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Find a parent controller that supports the
// PCI Root Bridge I/O Protocol
//
Status = gBS->LocateDevicePath (
&gEfiPciRootBridgeIoProtocolGuid,
&DevicePath,
&ParentHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the PCI Root Bridge I/O Protocol instance on ParentHandle
//
Status = gBS->OpenProtocol (
ParentHandle,
&gEfiPciRootBridgeIoProtocolGuid,
(VOID **)&PciRootBridgeIo,
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}