Protocols
The extensible nature of EFI is built, to a large degree, around protocols. EFI drivers are sometimes confused with EFI protocols. Although they are closely related, they are distinctly different. An EFI driver is an executable EFI image that installs a variety of protocols of various handles to accomplish its job.
An EFI protocol is a block of function pointers and data structures or APIs that have been defined by a specification. At a minimum, the specification must define a GUID. This number is the protocol's real name; boot services like LocateProtocol uses this number to find his protocol in the handle database. The protocol often includes a set of procedures and/or data structures, called the protocol interface structure. The following code sequence is an example of a protocol definition from section 9.6 of the EFI 1.10 Specification. Notice how it defines two function definitions and one data field.
Sample GUID
#define EFI_COMPONENT_NAME_PROTOCOL_GUID \ {0x107a772c,0xd5e1,0x11d4,0x9a,0x46,0x0,0x90, 0x27,0x3f,0xc1,0x4d}
Protocol Interface Structure
typedef struct _EFI_COMPONENT_NAME_PROTOCOL { EFI_COMPONENT_NAME_GET_DRIVER_NAME <b><i>GetDriverName;</b></i> EFI_COMPONENT_NAME_GET_CONTROLLER_NAME <b><i>GetControllerName;</b></i> CHAR8 <b><i>*SupportedLanguages;</i></b> } EFI_COMPONENT_NAME_PROTOCOL;
Figure 3 shows a single handle and protocol from the handle database that is produced by an EFI driver. The protocol is composed of a GUID and a protocol interface structure. Many times, the EFI driver that produces a protocol interface maintains additional private data fields. The protocol interface structure itself simply contains pointers to the protocol function. The protocol functions are actually contained within the EFI driver. An EFI driver might produce one protocol or many protocols depending on the driver's complexity.
Not all protocols are defined in the EFI 1.10 Specification. The EFI Developer Kit (EDK) includes many protocols that are not part of the EFI 1.10 Specification. These protocols provide the wider range of functionality that might be needed in any particular implementation, but they are not defined in the EFI 1.10 Specification because they do not present an external interface that is required to support booting an OS or writing an EFI driver. The creation of new protocols is how EFI-based systems can be extended over time as new devices, buses, and technologies are introduced. For example, some protocols that are in the EDK but not in the EFI 1.10 Specification are:
- Varstore. Interface to abstract storage of EFI persistent binary objects.
- ConIn. Service to provide a character console input.
- ConOut. Service to provide a character console output.
- StdErr. Service to provide a character console output for error messaging.
- PrimaryConIn. Console input with primary view.
- VgaMiniPort. Service that provides Video Graphics Array output.
- UsbAtapi. Service to abstract block access on USB bus.
The EFI Application Toolkit also contains a number of EFI protocols that may be found on some platforms, such as,:
- PPP Deamon. Point-to-Point Protocol driver.
- Ramdisk. File system instance on a Random Access Memory buffer.
- TCP/IP. Transmission Control Protocol/Internet Protocol.
The OS loader and drivers should not depend on these types of protocols because they are not guaranteed to be present in every EFI-compliant system. OS loaders and drivers should depend only on protocols that are defined in the EFI 1.10 Specification and protocols that are required by platform design guides such as Design Implementation Guide for 64-bit Server.
The extensible nature of EFI allows the developers of each platform to design and add special protocols. Using these protocols, they can expand the capabilities of EFI and provide access to proprietary devices and interfaces in congruity with the rest of the EFI architecture.
Because a protocol is "named" by a GUID, no other protocols should have that same identification number. Care must be taken when creating a new protocol to define a new GUID for it. EFI fundamentally assumes that a specific GUID exposes a specific protocol interface. Cutting and pasting an existing GUID or hand-modifying an existing GUID creates the opportunity for a duplicate GUID to be introduced. A system containing a duplicate GUID inadvertently could find the new protocol and think that it is another protocol, crashing the system as a result. For these types of bugs, finding the root cause is also very difficult. The GUID allows for naming APIs without having to worry about namespace collision. In systems such as PC/AT BIOS, services were added as an enumeration. For example, the venerable Int15h interface would pass the service type in AX. Since no central repository or specification managed the evolution of Int15h services, several vendors defined similar service numbers, thus making interoperability with operating systems and pre-OS applications difficult. Through the judicious use of GUIDs to name APIs and an association to develop the specification, EFI balances the need for API evolution with interoperability.