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;
}