13.2.2 Bus Drivers and Hybrid Drivers
Bus drivers and hybrid drivers implementing the Driver Diagnostics Protocols
must verify that ControllerHandle and ChildHandle represent a device
currently managed by the driver. In addition, RunDiagnostics()
must verify
that the requested Language is in the set of languages supported by the UEFI
Driver. The following example shows the steps required to check these
parameters and also retrieve the private context data structure. If the checks
pass, the diagnostics are executed and results 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()
. It checks to see if the UEFI Drivers providing the RunDiagnostics()
service is currently managing ControllerHandle. If the private context structure is required, then, typically, the UEFI Boot Service
OpenProtocol()
is used to open one of the protocols on ControllerHandle
that the UEFI Driver produced 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 made to run diagnostics on the bus controller. If ChildHandle is not NULL, a request is made to run diagnostics on a child controller managed by the UEFI Driver.
Example 149-RunDiagnostics() for a Bus Driver or Hybrid Driver
#include <Uefi.h>
#include <Protocol/DriverDiagnostics2.h>
#include <Protocol/PciIo.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiLib.h>
EFI_STATUS
EFIAPI
AbcRunDiagnostics (
IN EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle, OPTIONAL
IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,
IN CHAR8 *Language,
OUT EFI_GUID **ErrorType,
OUT UINTN *BufferSize,
OUT CHAR16 **Buffer
)
{
EFI_STATUS Status;
CHAR8 *SupportedLanguages;
BOOLEAN Rfc4646Language;
BOOLEAN Found;
UINTN Index;
//
// 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;
}
}
//
// Check input parameters
//
if (Language == NULL || ErrorType == NULL ||
BufferSize == NULL || Buffer == NULL ) {
return EFI_INVALID_PARAMETER;
}
//
// Make sure Language is in the set of Supported Languages
//
SupportedLanguages = This->SupportedLanguages;
Rfc4646Language = (BOOLEAN)(This == &gAbcDriverDiagnostics2);
Found = FALSE;
while (*SupportedLanguages != 0) {
if (Rfc4646Language) {
for (Index = 0;
SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';
';
Index++);
if ((AsciiStrnCmp (SupportedLanguages, Language, Index) == 0) &&
(Language[Index] == 0)) {
Found = TRUE;
break;
}
SupportedLanguages += Index;
for (;
*SupportedLanguages != 0 && *SupportedLanguages == ';
';
SupportedLanguages++);
} else {
if (CompareMem (Language, SupportedLanguages, 3) == 0) {
Found = TRUE;
break;
}
SupportedLanguages += 3;
}
}
//
// If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
//
if (!Found) {
return EFI_UNSUPPORTED;
}
if (ChildHandle == NULL) {
//
// Perform Diagnostics Algorithm on the bus controller specified
// by ControllerHandle for the type of diagnostics requested in
// DiagnosticsType
//
// Return results in ErrorType, Buffer, and BufferSize
//
// If Diagnostics Algorithm fails, then return EFI_DEVICE_ERROR
//
} else {
//
// Perform Diagnostics Algorithm on child controller specified
// by ChildHandle for the type of diagnostics requested in
// DiagnosticsType
//
// Return results in ErrorType, Buffer, and BufferSize
//
// If Diagnostics Algorithm fails, then return EFI_DEVICE_ERROR
//
}
return EFI_SUCCESS;
}
It is recommended that bus drivers and hybrid provide diagnostics for both the bus controller and the child controllers produced by these driver types. Implementing diagnostics for only the bus controller or only the child controllers is strongly discouraged.