Asus PCE-AC88 with hostapd
Intro
For several years i've been using hostapd on my home server to create a Wifi access point for all my devices, but due to a recent replacement of the server's hardware, i needed to get a new Wifi adapter as the new mainboard didn't have a PCI slot anymore.
After initially buying a TP-Link Archer T9E, which needs a closed-source driver and doesn't even support master (AP) mode, i (finally!) did a bit more research and found the Asus PCE-AC88 to be a worthy, albeit expensive, candidate.
The PCE-AC88 uses the Broadcom BCM4366 chip, which is supported by the open-source brcmfmac
driver - if you feed it the proper (still proprietary) firmware. Luckily that firmware file, called brcmfmac4366b-pcie.bin
,is readily available for Debian 9 in the firmware-brcm80211
package - so what could possibly go wrong?
Well, getting a card with a newer hardware revision (v4), which needs the firmware file brcmfmac4366c-pcie.bin
- that's what could possibly go wrong.
Fortunately i'm not the only person with issues like this, so there were other people who figured out ways how to get a firmware if there is no official source for it. So here's how i did it...
Firmware
The first step is to download the current firmware package for the Asus RT-AC88U - which is the Asus Wifi router with the same chip in it. Why? It also runs Linux, so it obviously also needs the firmware for that chip! You can pick any OS (e.g. "Others") from the dropdown menu, as long as you download the file below "Firmware". For me that was version 3.0.0.4.384.45149
, released just 2 days ago.
Preparation
Download that file to a folder, make sure you have p7zip
installed, then run the following to extract the kernel module that contains the firmware somewhere inside it:
7z x FW_RT_AC88U_300438445149.zip 7z x RT-AC88U/RT-AC88U_3.0.0.4_384_45149-g467037b.trx lib/modules/2.6.36.4brcmarm/kernel/drivers/net/dhd/dhd.ko mv lib/modules/2.6.36.4brcmarm/kernel/drivers/net/dhd/dhd.ko ./ rm -r ./RT-AC88U ./lib
This will give you the file dhd.ko
in the current directory. This is not the firmware, but, as mentioned before, only a kernel module containing the firmware.
Investigation
To figure out what the start of the firmware file looks like, we have a look at brcmfmac4366b-pcie.bin
from the firmware-brcm80211
package to get the first four hex bytes:
$ xxd /lib/firmware/brcm/brcmfmac4366b-pcie.bin | head -n1 00000000: 00f2 3eb8 04f2 b0bf 04f2 bbbf 04f2 c6bf ..>.............
Now that we know that we're looking for the bytes 00 F2 3E B8
, we can use binwalk
to look for the position of those bytes in the kernel module:
$ binwalk -R "\x00\xf2\x3e\xb8\x04\xf2" dhd.ko DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 256904 0x3EB88 \x00\xf2\x3e\xb8 256936 0x3EBA8 \x00\xf2\x3e\xb8
Let's do it once more and grab that offset to put it into an environment variable:
$ OFFSET=$(binwalk -R "\x00\xf2\x3e\xb8\x04\xf2" dhd.ko | sed '4!d' | awk '{print $1}') $ echo ${OFFSET} 256904
So now we know at what offset the firmware starts, but where does it end? This gets a bit tricky, but stay with me: Kernel modules are ELF files (which you can verify by running file dhd.ko
), so we can use readelf
to get some information about the kernel module's structure, especially the objects (ko = kernel object) inside it:
$ readelf -s dhd.ko | grep OBJECT ... 484: 00004220 4 OBJECT GLOBAL DEFAULT 35 dhd_radio_up 487: 0000442c 20 OBJECT GLOBAL DEFAULT 35 dlimagedate_4366c0 521: 00000654 4 OBJECT GLOBAL DEFAULT 35 dhd_download_fw_on_driver 526: 00004448 0x10b351 OBJECT GLOBAL DEFAULT 35 dlarray_4366c0 527: 00004210 4 OBJECT GLOBAL DEFAULT 35 dhd_console_ms 544: 00001058 4 OBJECT GLOBAL DEFAULT 45 dhd_found 545: 00004218 4 OBJECT GLOBAL DEFAULT 35 dhd_master_mode ...
We see a long list of tiny objects (the third column is the size), but one that sticks out because of its size, and the name dlarray_4366c0
also implies that we have found the object we are looking for - and its size.
So let's do that again, and also grab the size and put it into an environment variable:
$ SIZE=$(readelf -s dhd.ko | grep dlarray_4366c0 | awk '{print $3}' | xargs printf "%d\n") $ echo ${SIZE} 1094481
Extraction
We have the kernel module, we know where the firmware starts, and we know the size of it, so now we can use dd
to extract the section that we think is is the firmware from the kernel module:
$ dd if=dhd.ko skip=${OFFSET} ibs=1 count=${SIZE} of=brcmfmac4366c-pcie.bin
This is not necessary, but let's get the full details about the firmware we just extracted:
$ strings brcmfmac4366c-pcie.bin_10.10.122.47 | grep Version 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-stamon-hostpmac-murx-splitassoc-hostmemucode-dyn160-txpwr-stamon Version: 10.10.122.47 CRC: 13f8b3a1 Date: Tue 2018-08-14 10:45:51 CST FWID 01-ef91d5ac
Or in a more readable format:
Features | pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-stamon-hostpmac-murx-splitassoc-hostmemucode-dyn160-txpwr-stamon |
Version | 10.10.122.47 |
CRC | 13f8b3a1 |
Date | Tue 2018-08-14 10:45:51 CST |
FWID | 01-ef91d5ac |
Installation
The brcmfmac
module is looking for its firmware files in a specific folder, so you need to copy the extracted firmware there:
$ cp brcmfmac4366c-pcie.bin /lib/firmware/brcm/brcmfmac4366c-pcie.bin
Initialization
You probably have the brcmfmac
module still loaded, so let's unload and reload it:
$ modprobe -r brcmfmac $ modprobe brcmfmac
If everything went well, dmesg
should show you that it was able to initialize the chip with the firmware, even though it complains about brcm/brcmfmac4366c-pcie.txt
and brcm/brcmfmac4366c-pcie.clm_blob
:
[62448.893550] usbcore: registered new interface driver brcmfmac [62449.000758] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4366c-pcie for chip BCM4366/4 [62449.002127] brcmfmac 0000:42:00.0: firmware: direct-loading firmware brcm/brcmfmac4366c-pcie.bin [62449.002137] brcmfmac 0000:42:00.0: firmware: failed to load brcm/brcmfmac4366c-pcie.txt (-2) [62449.002330] brcmfmac 0000:42:00.0: Direct firmware load for brcm/brcmfmac4366c-pcie.txt failed with error -2 [62449.753733] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4366c-pcie for chip BCM4366/4 [62449.753749] brcmfmac 0000:42:00.0: firmware: failed to load brcm/brcmfmac4366c-pcie.clm_blob (-2) [62449.753926] brcmfmac 0000:42:00.0: Direct firmware load for brcm/brcmfmac4366c-pcie.clm_blob failed with error -2 [62449.753928] brcmfmac: brcmf_c_process_clm_blob: no clm_blob available (err=-2), device may have limited channels available [62449.754055] brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM4366/4 wl0: Sep 12 2016 13:26:44 version 10.10.69.6908 (r658761) FWID 01-fed440e1 [62449.767104] brcmfmac 0000:42:00.0 wlp66s0: renamed from wlan0
Verification
Run the command below, and if you get a similar output you now have a working PCE-AC88.
$ iw phy#0 info Wiphy phy0 max # scan SSIDs: 10 max scan IEs length: 2048 bytes max # sched scan SSIDs: 0 max # match sets: 0 max # scan plans: 1 max scan plan interval: -1 max scan plan iterations: 0 Retry short limit: 7 Retry long limit: 4 Coverage class: 0 (up to 0m) Device supports roaming. Supported Ciphers: * WEP40 (00-0f-ac:1) * WEP104 (00-0f-ac:5) * TKIP (00-0f-ac:2) * CCMP-128 (00-0f-ac:4) * CMAC (00-0f-ac:6) Available Antennas: TX 0 RX 0 Supported interface modes: * IBSS * managed * AP * P2P-client * P2P-GO * P2P-device Band 1: Capabilities: 0x1022 HT20/HT40 Static SM Power Save RX HT20 SGI No RX STBC Max AMSDU length: 3839 bytes DSSS/CCK HT40 Maximum RX AMPDU length 65535 bytes (exponent: 0x003) Minimum RX AMPDU time spacing: 16 usec (0x07) HT TX/RX MCS rate indexes supported: 0-31 Bitrates (non-HT): * 1.0 Mbps * 2.0 Mbps (short preamble supported) * 5.5 Mbps (short preamble supported) * 11.0 Mbps (short preamble supported) * 6.0 Mbps * 9.0 Mbps * 12.0 Mbps * 18.0 Mbps * 24.0 Mbps * 36.0 Mbps * 48.0 Mbps * 54.0 Mbps Frequencies: * 2412 MHz [1] (20.0 dBm) * 2417 MHz [2] (20.0 dBm) * 2422 MHz [3] (20.0 dBm) * 2427 MHz [4] (20.0 dBm) * 2432 MHz [5] (20.0 dBm) * 2437 MHz [6] (20.0 dBm) * 2442 MHz [7] (20.0 dBm) * 2447 MHz [8] (20.0 dBm) * 2452 MHz [9] (20.0 dBm) * 2457 MHz [10] (20.0 dBm) * 2462 MHz [11] (20.0 dBm) * 2467 MHz [12] (20.0 dBm) * 2472 MHz [13] (20.0 dBm) * 2484 MHz [14] (disabled) Band 2: Capabilities: 0x1062 HT20/HT40 Static SM Power Save RX HT20 SGI RX HT40 SGI No RX STBC Max AMSDU length: 3839 bytes DSSS/CCK HT40 Maximum RX AMPDU length 65535 bytes (exponent: 0x003) Minimum RX AMPDU time spacing: 16 usec (0x07) HT TX/RX MCS rate indexes supported: 0-31 VHT Capabilities (0x0c1b4064): Max MPDU length: 3895 Supported Channel Width: 160 MHz short GI (80 MHz) short GI (160/80+80 MHz) MU Beamformer MU Beamformee VHT RX MCS set: 1 streams: MCS 0-9 2 streams: MCS 0-9 3 streams: MCS 0-9 4 streams: MCS 0-9 5 streams: not supported 6 streams: not supported 7 streams: not supported 8 streams: not supported VHT RX highest supported: 0 Mbps VHT TX MCS set: 1 streams: MCS 0-9 2 streams: MCS 0-9 3 streams: MCS 0-9 4 streams: MCS 0-9 5 streams: not supported 6 streams: not supported 7 streams: not supported 8 streams: not supported VHT TX highest supported: 0 Mbps Bitrates (non-HT): * 6.0 Mbps * 9.0 Mbps * 12.0 Mbps * 18.0 Mbps * 24.0 Mbps * 36.0 Mbps * 48.0 Mbps * 54.0 Mbps Frequencies: * 5170 MHz [34] (disabled) * 5180 MHz [36] (20.0 dBm) * 5190 MHz [38] (disabled) * 5200 MHz [40] (20.0 dBm) * 5210 MHz [42] (disabled) * 5220 MHz [44] (20.0 dBm) * 5230 MHz [46] (disabled) * 5240 MHz [48] (20.0 dBm) * 5260 MHz [52] (disabled) * 5280 MHz [56] (disabled) * 5300 MHz [60] (disabled) * 5320 MHz [64] (disabled) * 5500 MHz [100] (disabled) * 5520 MHz [104] (disabled) * 5540 MHz [108] (disabled) * 5560 MHz [112] (disabled) * 5580 MHz [116] (disabled) * 5600 MHz [120] (disabled) * 5620 MHz [124] (disabled) * 5640 MHz [128] (disabled) * 5660 MHz [132] (disabled) * 5680 MHz [136] (disabled) * 5700 MHz [140] (disabled) * 5720 MHz [144] (disabled) * 5745 MHz [149] (disabled) * 5765 MHz [153] (disabled) * 5785 MHz [157] (disabled) * 5805 MHz [161] (disabled) * 5825 MHz [165] (disabled) Supported commands: * new_interface * set_interface * new_key * start_ap * join_ibss * set_pmksa * del_pmksa * flush_pmksa * remain_on_channel * frame * set_wiphy_netns * set_channel * start_p2p_device * connect * disconnect * crit_protocol_start * crit_protocol_stop * Unknown command (122) Supported TX frame types: * managed: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0 0xc0 0xd0 0xe0 0xf0 * P2P-client: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0 0xc0 0xd0 0xe0 0xf0 * P2P-GO: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0 0xc0 0xd0 0xe0 0xf0 * P2P-device: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0 0xc0 0xd0 0xe0 0xf0 Supported RX frame types: * managed: 0x40 0xd0 * P2P-client: 0x40 0xd0 * P2P-GO: 0x00 0x20 0x40 0xa0 0xb0 0xc0 0xd0 * P2P-device: 0x40 0xd0 WoWLAN support: * wake up on disconnect * wake up on magic packet * wake up on pattern match, up to 8 patterns of 1-128 bytes, maximum packet offset 1500 bytes software interface modes (can always be added): valid interface combinations: * #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1, total <= 3, #channels <= 1 * #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1, total <= 4, #channels <= 1 * #{ AP } <= 4, total <= 4, #channels <= 1, STA/AP BI must match Device supports scan flush.
Versions
The first line is the version reported in dmesg, the second line the strings in the firmware:
$ ls -1 brcmfmac4366c-pcie.bin* | xargs -i% strings % | grep -P '\d+\.\d+\.\d+\.\d+' 10.10.122.303 (r666429) 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-stamon-hostpmac-murx-splitassoc-hostmemucode-dyn160-txpwr-stamon Version: 10.10.122.47 CRC: 9ebbf2e1 Date: Wed 2017-07-26 14:44:35 CST FWID 01-fb27523d 10.10.122.303 (r666429) 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-stamon-hostpmac-murx-splitassoc-hostmemucode-dyn160-txpwr-stamon Version: 10.10.122.47 CRC: 13f8b3a1 Date: Tue 2018-08-14 10:45:51 CST FWID 01-ef91d5ac 10.10.69.6908 (r658761) 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-hostpmac-txpwr Version: 10.10.69.252 CRC: 9fa88ab1 Date: Mon 2016-09-12 13:28:49 CST Ucode Ver: 1073.579 FWID: 01-fed440e1 10.10.69.69017 (r730013) 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-hostpmac-txpwr-stamon Version: 10.10.69.69017 (r730013) CRC: cf0b5621 Date: Tue 2017-11-07 12:34:00 CST Ucode Ver: 1073.579 FWID: 01-e258597c 10.10.69.69027 (r766943) 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-hostpmac-txpwr-stamon Version: 10.10.69.69027 (r766943) CRC: 9055790c Date: Thu 2018-08-23 14:36:02 CST Ucode Ver: 1073.579 FWID: 01-15a952d6 10.10.69.69 (r625687) 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-hostpmac Version: 10.10.69.69 CRC: 34d30c8c Date: Tue 2016-08-23 17:31:24 PDT FWID 01-8438621f 10.10.69.74 (r629731 WLTEST) 4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfgtest-seqcmds-phydbg-phydump-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-11nprop-dbgam-dbgams-ringer-dmaindex16-bgdfs-hostpmac Version: 10.10.69.74 CRC: a6268b76 Date: Mon 2016-09-12 16:39:23 CST FWID 01-5c0166fa
hostapd
interface=wlp66s0 bridge=br0 driver=nl80211 ctrl_interface=/var/run/hostapd ctrl_interface_group=0 ##### IEEE 802.11 ssid=ThisIsMySSID country_code=DE ieee80211d=1 ieee80211h=1 hw_mode=a channel=60 auth_algs=1 wmm_enabled=1 ##### IEEE 802.11n ieee80211n=1 ht_capab=[HT40-] [SHORT-GI-40] [DSSS_CCK-40] ##### IEEE 802.11ac ieee80211ac=1 vht_capab=[VHT160] [SHORT-GI-80] [SHORT-GI-160] [BF-ANTENNA-4] [SOUNDING-DIMENSION-4] [MU-BEAMFORMER] [MU-BEAMFORMEE] vht_oper_chwidth=1 vht_oper_centr_freq_seg0_idx=66 ##### WPA/IEEE 802.11i wpa=2 wpa_passphrase=ThisIsMyPassword wpa_key_mgmt=WPA-PSK rsn_pairwise=CCMP