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