Bringing WiFi to UEFI with a Raspberry Pi Pico W
UEFI has no WiFi unless your vendor ships a driver. So I offloaded the radio to a $6 microcontroller and bridged it into the standard EDK II WiFi2 protocol.
Firmware does not have WiFi. That sounds obvious until you actually need a network connection before an operating system exists. UEFI can do wired networking through the standard network stack, but wireless normally requires a vendor-specific WiFi driver matched to specific hardware. If your board does not ship one, you do not have WiFi, and there is no app store to fix that.
I needed network access at the firmware level, before boot. Rather than chase a vendor driver I would never get, I took a different route: offload the radio to a cheap, widely available microcontroller and teach the firmware to speak to it. The result is PicoWifiDxe, a UEFI DXE driver that turns a Raspberry Pi Pico W into a WiFi adapter for any firmware that lacks one.
The shape of it
UEFI App ──WiFi2 protocol──► PicoWifiDxe ──USB CDC-ACM──► Pico W ──► WiFi
The host firmware never sees a WiFi frame or an IP packet. The radio, the association, the whole wireless side lives on the Pico W. The driver's job is to find that microcontroller on the USB bus, talk to it over a simple serial protocol, and then present the result to the rest of the firmware as if it were a normal WiFi adapter.
Finding the device
On load, the driver enumerates every handle that supports
EFI_USB_IO_PROTOCOL and looks for the Pico by its USB vendor and product ID:
#define PICO_VID 0x2E8A // Raspberry Pi
#define PICO_PID 0x000A // Pico W (CDC)Once matched, there are two bits of USB housekeeping. First, configure the CDC
line coding (the same SET_LINE_CODING control transfer a normal serial port
uses, here at 115200 baud). Second, walk the endpoint descriptors to find the
bulk IN and OUT endpoints, which is where the actual data flows:
// bulk endpoint: transfer type 0x02; IN if the high bit of the address is set
if ((EpDesc.Attributes & 0x03) == 0x02) {
if (EpDesc.EndpointAddress & 0x80) { /* bulk IN */ }
else { /* bulk OUT */ }
}This is the part where the EDK II mental model pays off: you are not opening "a serial port," you are locating a USB I/O protocol on a handle and driving it directly.
Talking to it
The protocol between the driver and the Pico is deliberately boring: ASCII lines over the bulk pipe, terminated by newlines and sentinels. Two commands cover the whole job.
| Command sent | Expected response |
|---|---|
SCAN\n | SSID:<name>,RSSI:<dbm>,CH:<n> lines, then END |
CONNECT:<ssid>,<psk>\n | a line containing OK on success |
On the driver side that is a small SendLine / RecvLine pair over the bulk
endpoints, with a timeout so a missing or wedged Pico fails cleanly instead of
hanging the boot. Keeping the wire format trivial means the microcontroller
firmware stays trivial too, which matters when you are debugging two sides of a
link at once.
Speaking the standard language
The driver could have exposed a bespoke "ask the Pico" API. It does not. Instead
it implements the standard EFI_WIRELESS_MAC_CONNECTION_II protocol (WiFi2) on
top of that serial transport and publishes it on a handle. Scan results from the
Pico are parsed out of those SSID:…,RSSI:…,CH:… lines, and the raw RSSI is
mapped to the 0 to 100 signal-quality value the protocol expects. The pre-shared
key is kept in a UEFI variable and supplied at connect time.
The payoff is that any UEFI application that already knows how to use the WiFi2 protocol can use this with no changes at all. It does not know or care that the radio is a microcontroller on the end of a USB cable. That is the whole point of publishing a protocol on a handle: you implement the standard interface, and everything built against that interface just works.
Why bother
Three reasons this turned out to be worth building:
- It is hardware you can actually get. A Pico W is a few dollars and on every electronics shelf. No vendor relationship, no NDA, no waiting.
- It is reproducible. Anyone can flash the microcontroller, drop the driver into a package, and have WiFi in firmware on hardware that never shipped with it. Useful for pre-boot provisioning and for lab and test setups.
- It is a clean lesson. Building this is the most direct way I know to understand how UEFI USB access and protocol publishing actually fit together, because you touch both ends: raw bulk transfers at the bottom, a standard protocol at the top.
A six-dollar microcontroller and a boring line protocol, bridged into a standard firmware interface, is not glamorous. But it turns "this board has no WiFi" into "this board has WiFi now," which is exactly the kind of problem firmware work is full of.