Skip to content

Wi-Fi PXE boot and Wi-Fi imaging: feasibility, and what it would actually take #157

Description

@darksidemilk

This is a tracker and research write-up, not a bug report — the same shape as the shim work in FOGProject/fogproject#995. Nothing has been built or booted.

Full analysis, with citations, is recorded as an ADR on the branch:
docs/adr/0015-wifi-pxe-boot-and-wifi-imaging.md

Why this exists

"Can FOG image over Wi-Fi, out of the box?" gets asked regularly — laptops with no Ethernet port, no wired drop at the bench, and the specific case of registering a large batch of Wi-Fi-only machines. The answer given each time is an ad-hoc "not supported, use a USB-Ethernet dongle", occasionally with a one-off debug kernel built by hand to find out which firmware a card wanted.

None of that reasoning lived in either repo. Before this, grep -rinE 'wifi|wlan|wireless|80211|ssid' over fos returned exactly one hit — an incidental string inside the out-of-tree r8168 driver — and over fogproject, two Font Awesome fa-wifi icons.

The recurring answer is also incomplete. Part of the request is genuinely achievable and part genuinely is not, and "not supported" flattens the difference.

The question splits in two, and the halves have opposite answers

Part A — Wi-Fi network boot: not FOG's to fix

Upstream iPXE's entire 802.11 driver set is ath5k, ath9k, rtl8180, rtl8185, prism2_plx, prism2_pci — pre-2011 parts. On the AX211 request (ipxe/ipxe#959) the maintainers were explicit about why that won't change: drivers are "written from scratch in C based on hardware reference manuals", sometimes under NDA, and "most wifi nics do require binary blobs, so that makes them unlikely to get any support." Their own recommendation is a USB NIC.

FOG's build has it off regardless:

  • IWMGMT_CMD — the only way to script an association — is commented out in both fog-ipxe/src/config/general.h:141 and src-efi/config/general.h:106.
  • CRYPTO_80211_WPA/WPA2 are #defined (general.h:368-370) but inert without the 802.11 core beneath them.
  • The build output confirms it rather than implying it: the linked-object baselines in fog-ipxe/tools/linked-objects/*.txt contain zero net80211/sec80211/ath*/rtl*wifi objects. The eap.o, eap_md5.o and eapol.o that are linked are wired 802.1X — an easy misread. tools/check-linked-objects.sh fails CI on any change to that set.

The one wireless first stage that works is the platform firmware's own, and FOG already supports it by doing nothing. Where firmware implements UEFI Wi-Fi — Lenovo's UEFI WI-FI Network Boot (WMI name WiFiNetworkBoot, default off, documented as requiring Secure Boot enabled), Dell's HTTPS Boot (documented for wired and wireless), some HP — it brings the radio up and presents an ordinary UEFI SNP. FOG's existing snponly.efi/snp.efi ride that unmodified.

So Part A's FOG-side work is a documented, verified recipe — plus the two fallbacks that work today: USB-stick boot via create-usb-image.sh, and a USB-Ethernet adapter for the boot only.

Part B — Wi-Fi imaging in FOS: feasible

Nothing exists today, in any arch. Kernel: # CONFIG_WIRELESS is not set, # CONFIG_RFKILL is not set, # CONFIG_WLAN is not set (configs/kernelx64.config:1044,1045,2070). Because CONFIG_WIRELESS=n, Kconfig elides the whole subtree, so CFG80211/MAC80211 don't appear in the files at all — easy to misread as "not yet reviewed" rather than "off". Userspace: WPA_SUPPLICANT, IW, WIRELESS_REGDB, WIRELESS_TOOLS, RFKILL and LIBNL all is not set.

Four things decide the design:

  1. CONFIG_MODULES=n (kernelx64.config:781) — every supported chipset is =y in the single bzImage. No modprobe escape hatch.

  2. The firmware mechanism is open, and the obvious route may not work. FOS ships firmware inside the kernel today (CONFIG_EXTRA_FIRMWARE, kernelx64.config:1155-1169), and build.sh:378-390 already clones the whole linux-firmware tree onto the build host. But FOS boots a classic initrd on a ramdisk block device, not an initramfs (root=/dev/ram0 rw ramdisk_size=275000). An initramfs is unpacked by a rootfs_initcall and so is visible to a built-in driver probing at device_initcall; a ramdisk root mounted afterward is not. The ordinary Buildroot route — BR2_PACKAGE_LINUX_FIRMWARE_* populating /lib/firmwarecannot be assumed to work here and must be settled by a real build before anyone designs around it.

  3. Three size ceilings, all threatened by firmware blobs: BR2_TARGET_ROOTFS_EXT2_SIZE="256M" (hard build failure past it), the cross-repo ramdisk_size=275000 (charged to every client's RAM), and the 128 MB FAT image in create-usb-image.sh:27-28. Broad linux-firmware coverage is hundreds of MB and isn't an option by either route.

  4. One loop makes a wlan NIC useless even if the rest were solved. etc/init.d/S40network:39-44 waits up to 35 s on /sys/class/net/$iface/carrier and continues past the interface if it never reads 1 — an unassociated wlan interface never will. Enumeration just above is fine (wlan0 does present as link/ether). The curl "${web}"/index.php success test at :48-54 must be kept, not replaced by an association check; the comment there already argues why, and it's more true over the air.

Credentials are a network-model choice, not a code one

On WPA2/3-PSK, Wi-Fi credentials are needed before the first network round-trip, which puts them in exactly the class ADR 0011 carved out for web= — the extended-checkin redesign can't carry them, for the identical reason.

An open (or OWE) imaging SSID with a MAC ACL largely dissolves that, and is the recommended v1: the only thing FOS needs before its first round-trip is the SSID name, which is deployment-wide, not secret, and fine as a global setting on the kernel command line. No per-host encrypted column, no dependency on ADR 0011's unresolved spike.

Four things about that model, so they aren't rediscovered:

  • Don't hide the SSID. It's revealed by the client's own probe requests and by any association, and it forces active probing — worse on 5 GHz DFS channels where passive scanning is mandated.
  • A MAC ACL is weak auth, but not newly weak here. FOG's boot chain is already MAC-identified and unauthenticated (getHostByMacAddresses() matches any non-pending MAC; sysuuid resolution is deliberately commented out). This doesn't lower the bar below wired PXE — provided it's a segregated imaging SSID/VLAN, not the corporate network.
  • Open air is genuinely worse than open wire, and it's the one place this is less safe than the wired path it mirrors: cleartext PXE on a switch needs physical access; over the air anyone in range captures whole disk images. OWE / WPA3-Enhanced Open is the fix that keeps the zero-credential property, at the cost of keeping wpa_supplicant (+libnl) in the init rather than bare iw.
  • A MAC ACL inverts badly for first touch. The ACL needs the wireless MAC before the machine can reach FOG, but registration is how FOG learns MACs. So it fits re-imaging known hosts well and first-time registration poorly — which is the case that generates these requests. Needs a pre-populated ACL or a time-boxed open registration window.

The expedient PSK channel (wifissid=/wifipsk= via hostKernelArgs) works today with zero server change and is fine for prototyping, but isn't shippable: the PSK travels in the boot.php response (plaintext unless httpproto is https), sits world-readable in /proc/cmdline, and is eval'd unquoted at S40network:17 / funcs.sh:12 — so a passphrase with shell metacharacters is a command injection.

Two things that need no work

  • Host identity. getHostByMacAddresses() resolves a host from any of its non-pending MACs, and the hostMAC association table already carries N MACs per host with hmPrimary/hmIgnoreImaging. Registering the wireless MAC as an additional MAC is the whole answer — no schema change.
  • setmacto= is already wired end to end.

Multicast is a non-starter

udpcast's rendezvous (--min-receivers, --max-wait, --rexmit-hello-interval) assumes a reliable-ish L2. 802.11 multicast is unacknowledged, sent at the basic rate, and commonly filtered or unicast-converted by APs. It should be refused on a wireless interface, per the ADR-0003 fail-loud principle and the ADR-0007 precedent for LVM images. Unicast NFS is the only viable transport, and even that is tuned for a switch (nolock,proto=tcp,rsize=32768,wsize=32768,intr,noatime, no vers=/timeo=/retrans=/soft).

Phased plan

  • Phase 0 — write it down. ADR 0015 + this issue. Follow-up: FOGProject/fog-docs docs/kb/reference/hardware.md currently says only "Wireless is not used for imaging"; it should name the firmware-boot path and the two fallbacks, and link the ADR.
  • Phase 1 — spike, explicitly unsupported. One chipset family on an experimental branch; Intel iwlwifi/iwlmvm is the highest-value pick since AX2xx is what ships in the machines generating these requests. Kernel symbols + driver =y, firmware via CONFIG_EXTRA_FIRMWARE. Buildroot: WPA_SUPPLICANT (_NL80211, _CLI, _PASSPHRASE, _WPA3), LIBNL, IW, WIRELESS_REGDB, RFKILL. S40network: a wireless branch ahead of the carrier gate — detect /sys/class/net/$iface/phy80211, rfkill-unblock, write a supplicant config, wpa_supplicant -B -Dnl80211, poll wpa_cli status for COMPLETED, then fall through to the existing udhcpc + curl probe unchanged. K40network gains wpa_cli terminate. Deliverables are measurements: does it associate, does it image, what throughput, and what did init.xz/bzImage actually grow by.
  • Phase 2 — decide whether PSK is in scope at all. Only sites unwilling to stand up a separate open/OWE SSID need it, and only that path is blocked on ADR 0011. A v1 can ship without it. If it's in scope, it rides whatever ADR 0011 settles on — don't build a second bootstrap channel.
  • Phase 3 — productionize. Widen the chipset matrix against measured size cost. Add tests/checks/wireless-config.sh modelled on pcie-aspm-config.sh/secureboot-config.sh including the -b post-oldconfig mode — ADR 0010's trap applies directly, since these symbols have real dependency chains and make oldconfig silently drops unmet ones. Refuse multicast on wireless. Tune NFS mount options. Server side: a global SSID setting is a one-line INSERT IGNORE INTO globalSettings migration with no PHP change; per-host columns only if Phase 2 puts PSK in scope. Per fogproject's own guidance that's a new feature, so it goes to working-1.6 first and ports to dev-branch as a separate PR.

Explicitly out of scope

WPA2/3-Enterprise (802.1X with per-machine certs). Wireless network boot inside FOG's own stack, per Part A.

And: supported is not the same as advised. The shared-medium objection made on the forums is correct — Wi-Fi imaging will be slower than wired and can degrade the wireless network for everyone else. Any documentation of this has to keep saying so.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions