How UEFI Drivers Implement the UNDI Specification
This article explains how network interface card (NIC) drivers implement the UEFI Universal Network Driver Interface (UNDI) specification. It covers the architectural relationship between UNDI and the UEFI network stack, the implementation of core protocol interfaces like the Network Interface Identifier Protocol, hardware abstraction techniques, command processing workflows, and buffer management required for pre-boot network communication.
Architectural Role of UNDI in UEFI
In the UEFI networking architecture, UNDI acts as the hardware-dependent device driver layer, abstracting physical NIC hardware away from generic upper-layer networking protocols. It sits below the Simple Network Protocol (SNP) and the Managed Network Protocol (MNP).
Rather than requiring the UEFI firmware to contain dedicated drivers
for every network controller, the NIC vendor provides an Option ROM or
integrated firmware image implementing UNDI. A generic UEFI SNP driver
then consumes this UNDI interface, exposing a standardized
EFI_SIMPLE_NETWORK_PROTOCOL to upper layers such as
IPv4/IPv6, PXE, and HTTP boot services.
The Network Interface Identifier (NII) Protocol
The bridge between UEFI driver management and the UNDI runtime is the
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL (commonly
referred to as NII, supported in 31-bit and 64-bit variants like
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31).
When a NIC driver initializes, it:
- Implements standard
EFI_DRIVER_BINDING_PROTOCOLfunctions (Supported(),Start(), andStop()). - Probes the PCI bus using
EFI_PCI_IO_PROTOCOLto match supported vendor and device IDs. - Allocates and initializes the
!PXEinterface parameter block. - Installs the
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOLon the controller handle, publishing pointers to the entry point and state data.
The UNDI Entry Point and Command Execution Model
Unlike modern operating system drivers that rely on asynchronous hardware interrupts, UEFI operates in a synchronous, polling-based single-threaded execution environment. UNDI implements this model through a single entry point called the API Entry Point.
When upper layers (such as the generic SNP driver) need the NIC to perform an action, they execute the UNDI entry point with a pointer to a Command Descriptor Block (CDB). The driver processes requests via a standardized dispatch table matching predefined opcodes:
- PXE_OPCODE_START / STOP: Initializes or de-initializes the driver's software state and basic resource tracking.
- PXE_OPCODE_OPEN / CLOSE: Powers up the physical transceiver (PHY), initializes link negotiation, sets the MAC address, and programs receive filters.
- PXE_OPCODE_INITIALIZE / SHUTDOWN: Configures memory buffers, ring descriptors, and DMA mappings for hardware access.
- PXE_OPCODE_TRANSMIT: Accepts a packet buffer address, populates the hardware transmit (TX) descriptor ring, and rings the hardware doorbell/tail register.
- PXE_OPCODE_RECEIVE: Queries the hardware receive (RX) ring for newly arrived frame descriptors, copies or maps the payload into the caller-provided buffer, and advances the ring index.
- PXE_OPCODE_GET_STATUS: Clears interrupt status registers and reports link state (up/down, speed, duplex) and TX/RX completion queues.
Direct Memory Access (DMA) and Buffer Management
Because UEFI runs in flat physical memory mode with identity mapping
(or specific IOMMU configurations depending on platform security), UNDI
drivers must handle DMA transactions using the
EFI_PCI_IO_PROTOCOL.
- Mapping: Buffers passed to UNDI from external
callers are mapped using
EFI_PCI_IO_PROTOCOL.Map()with appropriate operation types (EfiPciIoOperationBusMasterRead,EfiPciIoOperationBusMasterWrite, orEfiPciIoOperationBusMasterCommonBuffer). - Ring Allocation: Descriptor rings and
hardware-shared structures are allocated via
EFI_PCI_IO_PROTOCOL.AllocateBuffer()to guarantee proper hardware-accessible memory alignment and cache attributes. - Unmapping: Once transmission is acknowledged or a
receive buffer is handled, drivers unmap the bus addresses using
EFI_PCI_IO_PROTOCOL.Unmap()to enforce memory coherence across platforms.
Polling and Event Handling
Because interrupts are generally disabled during UEFI runtime boot
phases, the driver does not register an interrupt service routine (ISR).
Instead, upper-layer protocols periodically poll UNDI via
PXE_OPCODE_GET_STATUS or through a periodic timer event
created via CreateEvent(). The driver updates descriptor
pointers, checks transmit completion rings, acknowledges status
registers, and services the receive engine entirely on demand.
OS Handoff and Cleanup
When an operating system kernel assumes control of the system, UEFI
calls ExitBootServices(). The UNDI driver registers an
exit-event handler that shuts down the NIC's DMA engines, disables
hardware interrupt generation, and resets PHY/MAC controllers to a
pristine state so the operating system's native driver can initialize
the device without encountering resource conflicts.