14.2.2 Bus Drivers and Hybrid Drivers

Bus drivers and hybrid drivers implementing the Driver Health Protocol must verify that ControllerHandle and ChildHandle represent a device that is currently under the driver's management. The Driver Health Protocol also supports returning the combined health status for all controllers a UEFI Driver manages. This request is made by passing in a ControllerHandle value of NULL.

The example below shows the steps required to check these parameters and also retrieve the private context data structure. If these checks pass, the health status is returned. In this specific example, the driver opens the PCI I/O Protocol in its Driver Binding Start() function. This is why gEfiPciIoProtocolGuid is used in the call to the EDK II Library UefiLib function EfiTestManagedDevice() that checks to see if the UEFI Drivers providing this GetHealthStatus() service is currently managing ControllerHandle. If the private context structure is required, the UEFI Boot Service OpenProtocol() is typically used to open one of the UEFI Driver produced protocols on ControllerHandle and then uses a CR() based macro to retrieve a pointer to the private context structure. If diagnostics are being run on ChildHandle, a produced protocol on ChildHandle can be opened.


Note: If ChildHandle is NULL, a request is being made to run diagnostics on the bus controller. If ChildHandle is not NULL,then a request is being made to run diagnostics on a UEFI Driver managed child controller.


Example 154-GetHealthStatus() for a Bus Driver or Hybrid Driver
#include <Uefi.h>
#include <Protocol/DriverHealth.h>
#include <Protocol/PciIo.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiLib.h>

EFI_STATUS
EFIAPI
AbcGetHealthStatus (
  IN  EFI_DRIVER_HEALTH_PROTOCOL     *This,
  IN  EFI_HANDLE                     ControllerHandle,  OPTIONAL
  IN  EFI_HANDLE                     ChildHandle,       OPTIONAL
  OUT EFI_DRIVER_HEALTH_STATUS       *HealthStatus,
  OUT EFI_DRIVER_HEALTH_HII_MESSAGE  **MessageList,     OPTIONAL
  OUT EFI_HII_HANDLE                 *FormHiiHandle     OPTIONAL
  )
{
  EFI_STATUS  Status;

  //
  // Check input parameters
  //
  if (HealthStatus == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (ControllerHandle == NULL) {
    //
    // If all controllers managed by this UEFI Driver are healthly,
    // then assign HealthStatus to EfiDriverHealthStatusHealthy.
    // Otherwise, assign HealthStatus to EfiDriverHealthStatusFailed.
    //
    return EFI_SUCCESS;
  }

  //
  // Make sure this driver is currently managing ControllerHandle
  //
  Status = EfiTestManagedDevice (
             ControllerHandle,
             gAbcDriverBinding.DriverBindingHandle,
             &gEfiPciIoProtocolGuid
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // If ChildHandle is not NULL, then make sure this driver produced ChildHandle
  //
  if (ChildHandle != NULL) {
    Status = EfiTestChildHandle (
               ControllerHandle,
               ChildHandle,
               &gEfiPciIoProtocolGuid
               );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  if (ChildHandle == NULL) {
    //
    // Retrieve health status for ControllerHandle
    //
  } else {
    //
    // Retrieve health status for ChildHandle
    //
  }

  return EFI_SUCCESS;
}

Bus drivers and hybrid drivers are recommended to provide health status for both the bus controller and the child controllers these types of drivers produce. Implementing diagnostics for only the bus controller or only the child controllers is strongly discouraged.