在 Omarchy 上修复 MacBookPro14,2 的 BCM43602 5GHz Wi-Fi
写在最前
本人非常不推荐读者跟着本篇文章手动修复这个问题。本文内容更多的是给后来的 Agent 提供真实场景的参考,如果您一定要手动修复,请先设计好自动回滚和数据备份。
(下面是正文)
本文记录一台 2017 款 13 英寸 MacBook Pro(MacBookPro14,2)在 Omarchy/Arch Linux 下修复内置 Broadcom BCM43602 5GHz Wi-Fi 的全过程。
这不是一篇“下载一个 NVRAM 文件然后重启”的速成教程。真正的问题横跨四层:板级射频校准、BCM43602 老固件、Linux brcmfmac 的监管域通知,以及接入点广播的 Country IE。只解决其中一层,可能出现 Band 2 已经出现、却仍然看不到低信道 5GHz,甚至 2.4GHz 也无法关联的情况。
最终结果如下:
| 项目 | 修复后结果 |
|---|---|
| 目标 SSID | ChinaNet-xxxx-5G(已匿名化) |
| BSSID | bc:45:29:xx:xx:f4(已匿名化) |
| 频率 | 5240 MHz,信道 48 |
| 信号 | 约 -38 至 -52 dBm |
| RX/TX | 最高约 780 / 866.6 Mbit/s |
| 公网连通 | 223.5.5.5 Ping 0% 丢包 |
| HTTPS | 直连百度返回 HTTP 200 |
| 重启验证 | 通过,自动回滚保护已解除 |
适用范围与风险
本文的已验证环境是:
| |
不要把本文的定制模块直接复制到其他内核,也不要把某台机器的 NVRAM、MAC 地址或射频参数无差别复制到其他 Broadcom 芯片。
NVRAM 不只是“国家码配置”,还包含天线链、RF 开关、LNA/PA、功率表、TSSI/PAPD 和蓝牙共存参数。错误的文件可能造成:
- Band 2 仍然消失;
- 只出现部分 5GHz 信道;
- 能扫描但不能关联;
- 2.4GHz 退化或持续收到
status_code=16; - 发射功率、信号或蓝牙共存异常。
在远程机器上实验时,必须准备独立控制通道,并设置 systemd 自动回滚。不要在只有这一条 Wi-Fi SSH 链路时直接覆盖驱动后“观察看看”。
最初的症状
机器能够稳定连接 2.4GHz,但完全搜索不到 5GHz。基础检查如下:
| |
典型结果是:
| |
iw phy 只有 Band 1,没有 Band 2。内核日志同时显示:
| |
| |
这里已经能排除一个常见误判:不是 NetworkManager 把 5GHz 隐藏了,而是固件初始化后根本没有向 cfg80211 注册 Band 2。
另一台正常工作的 macOS 设备确认,同一路由器的真正 5GHz SSID(文中匿名为 ChinaNet-xxxx-5G)工作在信道 48、5240 MHz。这个外部证据非常关键:如果只看 Linux 扫描结果,会误以为路由器根本没有 5GHz。
MAC 地址也是一条支线陷阱
这台机器最初显示的无线地址是 00:90:4c:*。这个 OUI 来自 Broadcom/Epigram,是固件缺少有效板级数据时常见的占位地址,不是可信的 Apple 永久 MAC。
由于机器已经只有 Omarchy,Internet Recovery 又在中途失败,无法回到 macOS 查看“系统信息”。最后是从 EFI 的 ROM 与 HW_ROM 两个独立变量中读取 6 字节 payload,并确认二者一致,才找回真实 Apple 地址。EFI variable 文件开头有 4 字节 attributes,不能把它们当作地址的一部分:
| |
另一个误区是从 Internet Recovery 的 preferred-networks 二进制记录里搜索 Apple OUI。记录中确实可能出现看似 MAC 的 6 字节片段,但它们处在摘要/哈希区域,不能据此认定硬件地址。
MAC 并不是本次 5GHz 信道故障的根因,但错误 MAC 会干扰 AP 过滤、NetworkManager profile 和关联实验。排障时应先把“真实硬件地址”和“固件当前暴露的地址”分开记录。
为什么常规修复无效
在 Band 2 尚未注册时,下面这些设置都只能影响“如何使用已经存在的频段”,不能凭空补出板级射频能力:
- 在 NetworkManager、wpa_supplicant 和 iwd 之间切换;
- 关闭 Wi-Fi 省电;
- 关闭扫描 MAC 随机化;
- 调整 WPA2/WPA3、PMF、RSN 或 CCMP;
- 单独执行
iw reg set CN; - 只添加
brcmfmac.feature_disable=0x82000; - 修改连接配置中的 band 或 BSSID。
feature_disable=0x82000 仍然有用,它处理的是 BCM43602 与现代 supplicant/AP 之间的另一类握手兼容问题;但它不能替代缺失的板级 NVRAM。Omarchy PR #7487 也明确把这两个问题区分开来。
三份社区 NVRAM 不是一回事
早期最大的误区,是把所有 brcmfmac43602-pcie.txt 都当成“同一份修复”。实际比对后,至少存在三类显著不同的射频数据。
| 来源 | boardtype/rev | 天线链 | country tuple | boardflags3 | 本机结果 |
|---|---|---|---|---|---|
| Omarchy PR #7671 / Bugzilla 290569 | 0x61b / 0x1421 | 3×3,7 | 00/245 | 0xC0000303 | 所有 Wi-Fi 关联失败 |
| jsoyer/nohz donor | 0x61b / 0x1421 | 3×3,7 | 00/245 | 0x00000300 | Band 2 出现,但低信道不可用,2.4GHz status 16 |
| Omarchy PR #7487 / Boot Camp | 0x073e / 0x1101 | 2×2,3 | 0/1 | 0x40000108 | 配合内核补丁后完整成功 |
PR #7671 的公开验证是在 MacBookPro14,3 的信道 149;它证明某份 BCM43602 NVRAM 可以恢复高信道 5GHz,却不能证明所有 MacBookPro14,x 都适用,更不能证明信道 48 可用。
本机对 jsoyer/nohz 三串流文件的受控实验进一步说明:
- Band 2 可以被激活,说明 5GHz RF 硬件本身大概率没有损坏。
- 149、153、157、161 可以被扫描到。
- 36、40、44、48 仍被禁用。
- 2.4GHz 关联持续收到 AP 的
status_code=16。 - 改 PMF、CCMP、MAC、
feature_disable、国家码和固件内 country tuple 均无法解决。
所以“iw phy 出现 Band 2”不能作为修复成功的标准。真正的验收必须包含目标信道扫描、WPA 关联、IP 获取和真实数据传输。
除此之外还有两次有价值的阴性实验:
- vfontanela 的约 20 行最小 MacBookPro14,2 配置仍然只有 Band 1,证明仅补几个 board 字段不够;
- animatek 的 MacBookPro14,3 二串流配置只在被动扫描中暴露高信道,仍不能满足本机信道 48 的目标。
这些结果共同指向一个结论:必须同时匹配板级 RF 参数和 BCM43602 的固件监管行为,不能只在 NVRAM 中反复试 country code。
突破点:问题不只在 NVRAM
1. 国家码矩阵实验
为了把射频校准问题与监管域问题拆开,在 NetworkManager 停止、AP 尚未参与扫描时,使用同一份完整 NVRAM,仅改变初始 country tuple,然后热加载驱动。
低信道结果如下:
| 固件初始 tuple | 36/40/44/48 |
|---|---|
CN/0 | 全部 disabled |
JP/0 | 全部可用 |
00/245 | 全部可用 |
这组结果把根因缩小到了 BCM43602 固件自己的国家表:这份 2015 年固件中的 CN/rev0 会禁用 5150–5250 MHz 的低信道。
为什么扫描 AP 后又变回 CN/0
wpa_supplicant 日志出现了:
| |
接入点广播的 Country IE 告诉 Linux 当前国家是 CN。这个信息本身完全正确,问题发生在 brcmfmac 如何把它传给老固件。
Linux 7.1.9 的 brcmf_translate_country_code() 对 BCM43602 启用 ISO 3166 fallback。当设备没有专用 country map 时,它会把收到的 CN 转换为:
| |
随后 brcmf_cfg80211_reg_notifier() 通过 firmware country iovar 把它写回 BCM43602。于是流程变成:
| |
这解释了几个此前互相矛盾的现象:
- CN 监管域在法规上允许 36–48,但网卡仍显示 disabled;
- 某些社区用户在高信道 149 成功,本机信道 48 却失败;
- 强制 JP 似乎能“修好”低信道,但它不是合规、可靠的长期方案;
- 只安装 NVRAM 或只设置
cfg80211.ieee80211_regdom=CN都不够。
最终修复设计
最终方案坚持一个原则:
Linux 主机仍按 CN 监管域限制信道和发射行为,但不再让 BCM43602 把自己的工作 NVRAM 改写为有缺陷的
CN/0表。
方案包含三部分:
- 使用 Apple Boot Camp lineage 的 2×2 BCM43602 NVRAM;
- 对 BCM43602 做窄范围
brcmfmac补丁; - 通过内核命令行让 cfg80211 的全局监管域保持 CN。
NVRAM 来源
本文使用 Omarchy PR #7487 中的 Boot Camp NVRAM。写作时该 PR 仍处于 open 状态;其 NVRAM 来自 Apple Windows/Boot Camp 驱动 lineage,属于 Broadcom 专有数据,不在 linux-firmware 的常规分发范围内。
本次验证文件的 SHA-256:
| |
下载固定提交,避免上游内容漂移:
| |
不要直接沿用文件中的示例 MAC,更不要使用本文案例中的 MAC。先检查永久地址:
| |
如果得到的是 00:90:4c:*,它很可能是 Broadcom/Epigram 占位地址,不应当作唯一硬件身份。应从本机 Apple/EFI 信息可靠取得真实地址,或者按照 PR #7487 的安装逻辑删除 macaddr= 行,让固件尝试 OTP fallback。不要猜一个地址。
内核补丁
补丁只处理 BRCM_CC_43602_CHIP_ID,不改变其他 Broadcom 芯片。
| |
两个改动缺一不可:
REGULATORY_COUNTRY_IE_IGNORE阻止 AP Country IE 再次驱动这张网卡的固件国家切换;- notifier 中的 BCM43602/CN 特判处理开机时由全局 CN 监管域触发的请求,否则即使忽略 AP Country IE,启动阶段仍可能把固件改成
CN/0。
Linux 主机侧仍使用 CN,所以这不是伪装成 JP,也不是关闭监管。
在 Omarchy 上构建匹配当前内核的模块
1. 安装构建依赖
| |
确保 headers 与正在运行的内核完全一致:
| |
2. 获取精确源码
本次运行的是 7.1.9-arch1-2,对应实验使用 gregkh 的 v7.1.9,提交:
| |
| |
对 cfg80211.c 应用上面的补丁后先运行:
| |
3. 外部模块构建的一个坑
Omarchy 当前内核启用了:
| |
Broadcom 父目录 Makefile 原本通过 subdir-ccflags 添加 -DDEBUG。直接把 brcmfmac 子目录作为外部模块构建时,这个父级 flag 不会自动继承,结果会出现 brcmf_debug_create_memdump 等符号重定义。
本次构建命令因此是:
| |
只有在当前内核确实是 CONFIG_BRCMDBG=y 时才照搬 KCFLAGS=-DDEBUG。其他内核配置应按自己的 Kbuild 条件调整。
验证模块:
| |
vermagic 必须匹配当前 uname -r。本案例结果是:
| |
先做非持久化验证
不要把第一次尝试直接写进启动路径。推荐流程:
- 停止 NetworkManager;
- 备份并临时安装 generic 与 DMI-specific NVRAM;
- 卸载
brcmfmac_wcc和brcmfmac; iw reg set CN;- 用
insmod /path/to/brcmfmac.ko feature_disable=0x82000 roamoff=1加载补丁模块; - 检查信道 36–48;
- 扫描并连接目标 AP;
- 验证公网和 HTTPS;
- 无论成功失败都恢复原模块和 NVRAM。
临时 NVRAM 文件名应同时覆盖 generic 与 DMI-specific 请求:
| |
先检查低信道:
| |
期望:
| |
再扫描目标:
| |
本次非持久化测试第一次就找到:
| |
然后从同一路由器的 2.4GHz profile 克隆凭据,只修改 SSID、band 和 BSSID。不要在日志中打印 PSK:
| |
持久化配置
1. 安装模块
不要覆盖发行版原文件,把模块放到 updates:
| |
期望选中:
| |
2. 安装 NVRAM
先对现有同名文件做带时间戳备份,然后安装已经完成 MAC 处理的文件:
| |
3. 模块参数
/etc/modprobe.d/brcmfmac.conf:
| |
4. Limine 内核参数
/etc/limine-entry-tool.d/90-brcmfmac.conf:
| |
重建 UKI:
| |
重启后确认:
| |
应包含:
| |
如何设计自动回滚
本次所有会断开 Wi-Fi 的实验都由 root systemd oneshot 服务执行,而不是依赖 SSH 进程继续存活。持久化前,状态目录保存以下内容:
- 原
updates/brcmfmac.ko是否存在及其备份; - generic 与 DMI-specific NVRAM 备份;
- Limine、modprobe、NetworkManager 配置备份;
- 是否由本次实验新建 5GHz connection;
- 一个
armed标记。
开机 validator 的成功条件应同时满足:
| |
本案例最终使用:
| |
验证失败时,rollback 应恢复备份、删除或停用 custom module、执行 depmod 与 limine-mkinitcpio,再重启回原 2.4GHz 配置。验证成功时则删除 armed,并禁用 validator 服务。
一个真实的假阴性
第一次持久化验证错误地使用了:
| |
5GHz 已经关联成功并取得 192.168.0.x/23,但网关 Ping 100% 丢包,回滚逻辑因此取消了重启。后来回到完全正常的 2.4GHz 再测,网关仍然 100% 丢包,而公共 IP 和 HTTPS 正常。
结论是:这个路由器不回应 ICMP echo。Ping 网关在这里不是链路健康检查,而是稳定的假阴性来源。
重启后的最终验证
1. 模块与命令行
| |
| |
2. 监管域
| |
全局应为 CN。phy#N 可能仍显示 country 99,这是 brcmfmac 自定义 wiphy regdom 的标识,不等于机器真的被设置到了某个“99 国家”。关键是全局 CN 与实际可用信道的交集仍由 cfg80211 执行。
3. 5GHz 链路
| |
最终记录:
| |
4. 真实网络
| |
最终结果:公网 Ping 0% 丢包,HTTPS 200,开机 validator 写入 RESULT=SUCCESS 并解除回滚保护。
哪些方法不要再重复
只改 regdom
无 NVRAM 时连 Band 2 都不存在;有 NVRAM 后,未补丁的驱动又会把 CN 写成固件的 CN/0。单独改 regdom 不能覆盖这两层问题。
强制 JP
JP/0 在实验中确实开放了低信道,但物理位置在中国,长期伪装其他监管域不是正确方案。最终修复保留了主机侧 CN。
看见 Band 2 就宣布成功
三串流 donor 已经证明 Band 2 可以出现,但 2.4GHz 会关联失败,信道 48 仍然不可用。验收必须做到实际关联和数据传输。
反复换 NetworkManager 后端
当 iw phy 没有目标频段或信道 disabled 时,问题在 supplicant 之下。换 iwd/wpa_supplicant 只会制造更多变量。
覆盖发行版原模块
把自定义模块安装到 updates,保留发行版 .ko.zst。这样回滚只需撤销 override,不必从包缓存恢复原文件。
回滚方法
如果重启后无法联网,使用有线网络、USB 网卡或本地终端进入系统,恢复安装前备份。若没有旧的同名文件,可先把 custom 文件移动到隔离目录:
| |
再恢复原 Limine/modprobe 配置,执行:
| |
如果这些路径在实验前已有文件,应恢复备份,而不是简单删除。
内核升级后的维护
这个 brcmfmac.ko 与 7.1.9-arch1-2 的 ABI/vermagic 绑定。升级内核后:
- 新内核不会自动使用旧目录中的模块;
- 不能强制加载旧
.ko; - 应获取与新内核匹配的源码,重新应用同一窄补丁并构建;
- 构建后重新检查
modinfo -F vermagic; - 再走一次非持久化验证和开机回滚流程。
在补丁被上游或发行版正式接纳前,最好把“内核升级后检查 5GHz custom module”加入维护清单,而不是建立一个盲目对所有未来内核自动编译的 DKMS 包。
结论
这次排障最重要的不是得到了一个能工作的 .ko,而是把两个互相叠加的问题拆开了:
- BCM43602 缺少板级 NVRAM,所以最初只有 2.4GHz;
- NVRAM 恢复 Band 2 后,Linux 7.1.9 的国家码 fallback 又会把 AP/主机的 CN 请求写成老固件有缺陷的
CN/rev0,重新禁用目标信道 48。
Boot Camp 2×2 NVRAM 解决板级校准,BCM43602 专用内核补丁解决 CN/0 回写,cfg80211 全局 CN 则保留合法监管。三者组合后,机器才能在真实重启后稳定连接信道 48。
如果面对另一台 Mac,最值得复用的是排障方法,而不是直接复制结果:先确认硬件与目标信道,再区分 Band 注册、固件 country table、Linux regdom 和 Wi-Fi 关联四个层次;每一步都设置可自动执行的回滚,并用真实数据面而不是单一 Ping 作为成功标准。