11.1 Component Name Protocol Implementations
The implementation of the Component Name Protocols for a specific driver is typically found in the file ComponentName.c. Appendix A contains a template for a ComponentName.c file for a UEFI Driver. This file typically contains the following:
- Add global variable for the
EFI_COMPONENT_NAME_PROTOCOL
instance toComponentName.c
. - Add global variable for theEFI_COMPONENT_NAME2_PROTOCOL
instance toComponentName.c
. EFI_COMPONENT_NAME2_PROTOCOL
instance- Add static table of UEFI Driver names as Unicode strings to
ComponentName.c
. - Add static table of controller names as Unicode strings to
ComponentName.c
. - Implementation of the
GetDriverName()
service - Implementation of the
GetControllerName()
service - Install all the Component Name Protocols in the driver entry point.
- If the UEFI Driver supports the unload feature, uninstall all the Component
Name Protocols in the
Unload()
function.
The Component Name Protocols provide names in one or more languages. At a minimum, the protocols should support the English language. The Component Name Protocols advertise the languages they supports in a data field called SupportedLanguages. This data filed is a null-terminated ASCII string that contains one or more 3 character ISO 639-2 language codes with no separator character. The Component Name 2 Protocol also advertises the languages it supports in a data field called SupportedLanguages. This data filed is a null-terminated ASCII string that contains one or more RFC 4646 language codes separated by semicolons (';').
A consumer of the Component Name Protocols may parse the SupportedLanguages data field to determine if the protocol supports a language in which the consumer is interested. This data field can also be used by the implementation of the Component Name Protocols to see if names are available in the requested language.
For reference, Example 126, below, shows the protocol interface structure for
the Component Name Protocol and Example 127 shows the protocol interface
structure for the Component Name 2 Protocol. Both are composed of the two
services called GetDriverName()
and GetControllerName()
and a data field called
SupportedLanguages
Example 126-Component Name Protocol
typedef struct _EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL;
///
/// This protocol is used to retrieve user readable names of drivers
/// and controllers managed by UEFI Drivers.
///
struct _EFI_COMPONENT_NAME_PROTOCOL {
EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName;
EFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName;
///
/// A Null-terminated ASCII string that contains one or more
/// ISO 639-2 language codes. This is the list of language codes
/// that this protocol supports.
///
CHAR8 *SupportedLanguages;
};
Example 127-Component Name 2 Protocol
typedef struct _EFI_COMPONENT_NAME2_PROTOCOL
EFI_COMPONENT_NAME2_PROTOCOL;
///
/// This protocol is used to retrieve user readable names of drivers
/// and controllers managed by UEFI Drivers.
///
struct _EFI_COMPONENT_NAME2_PROTOCOL {
EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName;
EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName;
///
/// A Null-terminated ASCII string array that contains one or more
/// supported language codes. This is the list of language codes that
/// this protocol supports. The number of languages supported by a
/// driver is up to the driver writer. SupportedLanguages is
/// specified in RFC 4646 format.
///
CHAR8 *SupportedLanguages;
};
Example 128-Driver Diagnostics Protocol declaration
UEFI Drivers declare global variables for the Component Name Protocol and Component Name 2 Protocol instances that are produced. The SupportedLanguages fields are typically initialized by the UEFI Driver in the declaration for the specific set of languages the UEFI Driver supports. The following following example shows how the Component Name Protocols are typically declared in a driver and, in this case, declared to support both English and French.
#include <Uefi.h>
#include <Protocol/ComponentName2.h>
#include <Protocol/ComponentName.h>
GLOBAL_REMOVE_IF_UNREFERENCED
EFI_COMPONENT_NAME_PROTOCOL gAbcComponentName = {
(EFI_COMPONENT_NAME_GET_DRIVER_NAME) AbcGetDriverName,
(EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) AbcGetControllerName,
"engfra"
};
GLOBAL_REMOVE_IF_UNREFERENCED
EFI_COMPONENT_NAME2_PROTOCOL gAbcComponentName2 = {
AbcGetDriverName,
AbcGetControllerName,
"en;fr"
};
The implementations of the Component Name Protocols change in complexity depending on the type of UEFI Driver Model driver and the specific Component Name Protocol features implemented. A device driver is the simplest to implement. A bus driver or a hybrid driver may be more complex because it may provide names for both the bus controller and the child controllers. These implementations are discussed later in this section.
The EFI_COMPONENT_NAME_PROTOCOL
and EFI_COMPONENT_NAME2_PROTOCOL
are
installed onto the driver's image handle. It is possible for a driver to
produce more than one instance of the Component Name Protocols. All additional
instances of the Component Name Protocols must be installed onto new handles.
The Component Name Protocols can be installed directly using the UEFI Boot
Service InstallMultipleProtocolInterfaces()
. However, the EDK II library
UefiLib
provides a number of helper functions to install the Component Name
Protocols. The helper functions covered in more detail in Chapter 7 are:
EfiLibInstallDriverBinding()
EfiLibInstallAllDriverProtocols()
EfiLibInstallDriverBindingComponentName2()
EfiLibInstallAllDriverProtocols2()
If an error is generated installing any of the Component Name Protocol
instances the entire driver should fail and return an error status such as
EFI_ABORTED
. If a UEFI Driver implements the Unload()
feature, any
Component Name Protocol instances installed in the driver entry point must be
uninstalled in the Unload()
function.
The simplest implementation of the Component Name Protocols provides the name of the UEFI Driver. The next most complex implementation is that for a device driver providing both the name of the UEFI Driver and the names of the controllers under UEFI Driver management. The most complex implementation is that of a bus or a hybrid driver producing names for the UEFI Driver, names for the bus controllers it is managing, and names for the child controllers the driver has produced. All three of these implementations are discussed in the sections that follow.
The EDK II library UefiLib
provides functions to simplify the implementation
of the Component Name Protocols. These library functions provide services to register
Unicode strings in a table, lookup Unicode strings in a table, and free tables
of Unicode strings. Some UEFI Drivers have fixed names for the UEFI Driver
itself and the controllers that they manage. Other UEFI Drivers may dynamically
create names based on information retrieved from the platform or the controller
itself. The EDK II library UefiLib
functions managing tables of Unicode
strings are:
LookupUnicodeString()
LookupUnicodeString2()
AddUnicodeString()
AddUnicodeString2()
FreeUnicodeStringTable()
UEFI Drivers producing dynamic names for controllers or children register those
dynamic names in the Driver Binding Protocol Start()
function and are freed
in the Driver Binding Stop()
function. In addition, dynamic name tables
require extra fields in the driver's private context data structure pointing to
the dynamic name tables. See Chapter 8 of this guide for details on the
design of private context data structures.