A reverse-engineered nexmon firmware-patch
port targeting the Broadcom BCM4389c1 Wi-Fi 6E combo chip as shipped in the
Google Pixel 6 (oriole), firmware 20.101.90 (r1098710, FWID 01-3f632e0d).
The goal is monitor mode and frame injection on the phone's internal radio — no
external USB adapter. As far as we can tell this is the first public nexmon work against a
4389-class chip.
Status: monitor mode and frame injection both WORK on the internal radio. The patched firmware builds, loads, decompresses its microcode, boots reliably, and does sustained raw 802.11 monitor capture (radiotap, STA unharmed). A runtime monitor↔wifi switch works with no reboot per switch (a one-instruction driver patch). Frame injection is over-the-air and OTA-verified: crafted 802.11 frames radiate from the internal radio, confirmed by an independent listener. The earlier blocker — injection "walls in the fw's internal scb handling from the ioctl context" — was bypassed by hooking after the scb-container trap site and sourcing a live scb snapshot from the firmware's own TX drain (post-trap snapshot / snap-scb). Sustained rate is ~7 frames/s; higher-rate burst TX is the one open item. See docs/STATUS.md, docs/RE-writeup.md.
The
s2mpuwall — resolved. The earlier blocker (the dongle DMAs its first D2H completion to a host address the Pixel 6 Tensors2mpurefuses, trapping the chip) is a hot-swap artifact: re-downloading firmware to an already-running chip (rmmod+insmod, or a bind-mount + reload) fragments the DMA pool so the dongle's index buffers land outside thes2mpugrant window. Loading the firmware at a clean boot (persist it, then reboot) gives a clean DMA pool and the chip comes up fine. So: load via reboot, not a hot swap —fw-swap.sh reloadis the trap door. For a research device you own.
- A complete
definitions.mkfor the 4389c1 — every address nexmon needs (RAM/ROM layout, the three D11 microcode blobs and their pointer-pool slots, four template-RAM regions, the TCAM/flashpatch config table, reclaim-3 boundary, version pointers), recovered by disassembly and cross-checked against the stock image. - A microcode-download path for a write-only UCM. On this chip the ucode memory
is not directly addressable; it is written through the D11
objaddr/objdatabackplane window. nexmon's stock decompressor assumes byte-addressable UCM, so this port ships an override that streams the decompressed ucode throughobjdata(patches/common/ucode_compression_code.c). A subtle bug lived here: a 32-bit register store to a packed struct field compiled to fourstrbinstructions, which the backplane rejects — fixed by forcing a single word store. That fix cleared the chip's download stall. - The RE tooling (
tools/fw_re/) — capstone + radare2 helpers to re-derive all of the above for a different firmware build, so the port can be rebased. - An honest map of the RE journey — how both the
s2mpuDMA wall (a fixed-offset wrong-DMA-address bug) and the frame-injection scb-context wall were each diagnosed and resolved, documented with evidence indocs/.
firmwares/bcm4389c1/20_101_90_r1098710/ nexmon firmware defs (definitions.mk, structs.h, Makefile)
patches/bcm4389c1/20_101_90_r1098710/ the nexmon patch (patch.c, version, linker, Makefile)
patches/common/ucode_compression_code.c override: decompress ucode into the write-only UCM
tools/fw_re/ RE tooling: rebase the address map for another build
scripts/ on-device helpers (firmware swap, monitor gate, channel tune)
oot/mon_flip/ out-of-tree kernel module: flip the driver's monitor gate
docs/ RE writeup, current status, build notes
This repository contains no Broadcom firmware. fw_bcmdhd.bin is proprietary and
is not redistributable. To build, extract fw_bcmdhd.bin (and, for RE, generate a
.map) from your own device's /vendor/firmware/ and drop it at the repo root.
The address map here is specific to firmware 20.101.90 r1098710; a different build
needs a rebase (tools/fw_re/). See BUILD.md.
This is a set of chip/firmware definitions, patches, and overrides intended to sit on
top of an upstream nexmon checkout — not a fork of it. The nexmon-derived files under
patches/ and firmwares/ carry nexmon's GPL-3.0-or-later headers; the out-of-tree
kernel module oot/mon_flip/ is GPL-2.0 by kernel convention. Per-file SPDX
identifiers are authoritative — see LICENSE. Credit to the SEEMOO Lab nexmon
project, on whose framework and conventions this is built.
Research use on a device you own. Monitor-mode capture is receive-only; frame injection (TX) is now
functional — the patch.c injection path radiates crafted 802.11 frames over the air, and it fires
only on an explicit spc_tx command (it transmits nothing on its own). Keep injection to benign,
directed frames on a network you own — no attack traffic (no deauth/jam/flood) — and respect your local
regulations on transmitting and on the 6 GHz band. Firmware loads and reverts via a /vendor write +
reboot — a plain reboot restores stock. Do not hot-reload with rmmod/insmod (fw-swap.sh reload):
it traps the dongle (the s2mpu wall).