FreeBSD - MacBook and Broadcom BCM4321

As part of reviving my MacBook 4,1 (or early 2008 / A1181) on which I decided to install FreeBSD, I encountered some difficulties with the wifi adapter.

bwn_pci0@pci0:2:0:0:    class=0x028000 rev=0x03 hdr=0x00 vendor=0x14e4 device=0x4328 subvendor=0x106b subdevice=0x0088
    vendor     = 'Broadcom Inc. and subsidiaries'
    device     = 'BCM4321 802.11a/b/g/n'
    class      = network

Here are the steps I had to go through to get it working.

First a custom kernel has to be build with the BWN_GPL_PHY option that allows to build some GPL-licensed portions of the driver code base.

Because this MacBook is rather old I decided to use a more powerful machine to build the kernel (being careful to use the same FreeBSD version).

This is happening on the remote machine The following can be written in /usr/src/sys/amd64/conf/MACBOOK

include GENERIC
ident MACBOOK

options BWN_GPL_PHY

Then we build our new custom kernel and install it locally.

doas make buildkernel KERNCONF=MACBOOK
mkdir  /home/user/macbook
# We don't want to installation of the MACBOOK kernel to mess with our local machine kernel, so let us install it somewhere else.
env DESTDIR=/home/user/macbook doas make installkernel KERNCONF=MACBOOK # I have keepenv in my doas configuration

One needs to build the port called net/bwn-firmware-kmod, that I built with poudriere and then installed.

# I first created a default port tree and a jail for the target FreeBSD version (the one on the MacBook)
poudriere bulk -p default -j 13RC5amd64 net/bwn-firmware-kmod
# That results in a file /usr/local/poudriere/data/packages/13RC5amd64-default/All/bwn-firmware-kmod-0.1.2.txz for me

Now on the MacBook, we have to bring back the built kernel and the firmware package.

rsync -avz remote-machine:/home/user/macbook/boot/kernel/ kernel/
# rename the official kernel to GENERIC
doas mv /boot/kernel /boot/GENERIC
# mv the new kernel as the default location
doas mv ~/kernel /boot/ && doas chown -R root:wheel /boot/kernel

scp remote-machine:/usr/local/poudriere/data/packages/13RC5amd64-default/All/bwn-firmware-kmod-0.1.2.txz .
doas pkg install bwn-firmware-kmod-0.1.2.txz
# Now we have the files
#/boot/modules/bwn_v4_lp_ucode.ko
#/boot/modules/bwn_v4_n_ucode.ko
#/boot/modules/bwn_v4_ucode.ko

Some configuration is required in loader.conf and in rc.conf

### in loader.conf
bwn_v4_ucode_load="YES"

### in rc.conf
wlans_bwn0="wlan0"

For the record my full network config is

wlans_bwn0="wlan0"
ipv6_privacy="YES"
ifconfig_wlan0="WPA DHCP"
ifconfig_wlan0_ipv6="inet6 accept_rtadv"
rtsold_enable="YES"
create_args_wlan0="country FR regdomain ETSI"

# and in /etc/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant
eapol_version=2
ap_scan=1
fast_reauth=1

network={
        ssid="my_ssid" # Doesn't work with 5GHz version of it
        scan_ssid=0
        psk="my_passphrase"
        priority=5
}
network={
        priority=0
        key_mgmt=NONE
}

The only minor drawback when doing this is when one has to upgrade using freebsd-update. I’m solving this by building the kernel for this machine on the remote computer with the jail being up-to-date and re-installing that new kernel after applying the first freebsd-update install sequence, before the first reboot.