© 2023 DiyTronic

Запускаем Wi-Fi на Orange Pi Zero Plus 2 H3

В ходе настройки Orange Pi Zero Plus 2 H3 обнаружил, что есть конкретные проблемы с Wi-Fi. В зависимости от используемого дистрибутива Linux имеем либо негрузящайся драйвер, либо работают только первые 11 каналов Wi-Fi, а учитывая, что моих сетей там нет, это проблема, которую пришлось решать. Решение я нашёл и ниже я его вам покажу и расскажу как с этой проблемой бороться.

Итак, хотелось мне запустить эту плату именно в Armbin, но именно этот дистрибутив славился тем, что данная плата в нём Wi-Fi не поддерживала. Но мы не ищем лёгких путей и из-за какого-то там чортова драйвера менять дистрибутив для меня просто унижение. Если драйвер есть и он в принципе работает, то и в Armbian он у меня заработает. Вызов принят!

Получаем проблему

Итак, первым делом накатываем Armbian. На официальной стрaнице образа для данной платы я не нашёл, но зато нашёл где эти сборки выкладываются. В общем качаем отсюда https://fi.mirror.armbian.de/archive/orangepizeroplus2-h3/archive/. Я использовал версию bullseye. Пробовал jammy, но там ровно тоже самое.

Альтернативные драйвера

Они существуют и возможно работают.

Проблема одна — их надо качать, а сети нет. Можно конечно скачать код на другом компьютере, залить на карточку и попытаться собрать на плате, но слишком много возни и вероятно потребуется докачивать зависимости.

Анализируем ошибки

В итоге имеем условно работающий Wi-Fi из каробки с куцым списком доступных сетей и ошибки в логах при загрузке фирмвари данного драйвера.

Ошибки выглядят так

% dmesg | grep brcm
brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43430-sdio for chip BCM43430/1
brcmfmac mmc1:0001:1: Direct firmware load for brcm/brcmfmac43430-sdio.xunlong,orangepi-zero-plus2-h3.bin failed with error -2
brcmfmac mmc1:0001:1: Falling back to sysfs fallback for: brcm/brcmfmac43430-sdio.xunlong,orangepi-zero-plus2-h3.bin
brcmfmac mmc1:0001:1: Direct firmware load for brcm/brcmfmac43430-sdio.xunlong,orangepi-zero-plus2-h3.txt failed with error -2
brcmfmac mmc1:0001:1: Falling back to sysfs fallback for: brcm/brcmfmac43430-sdio.xunlong,orangepi-zero-plus2-h3.txt
brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43430-sdio for chip BCM43430/1
brcmfmac: brcmf_c_process_clm_blob: no clm_blob available (err=-2), device may have limited channels available
brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM43430/1 wl0: Mar 30 2016 11:30:56 version 7.45.77.h8.4 FWID 01-ee8a6268

Как видно оно пытается загрузить какую-то фирмварь и не может найти нужных файлов. Придётся таки разбираться, что такое firmware и как оно грузится

Linux и firmware

В общем, как выяснилось, для всяких проприетарных драйверов типа Broadcom-а у нас есть бинарные файлы (та самая firmware), которые и подгружаются родным линуксовым драйвером, чтобы всё работало как надо. Но кроме бинарника у нас есть некий конфиг, который есть ни что иное как набор переменных, которые заливаются в NVRAM драйвера.

Что не так в нашем случае

Для нашего случая всё выглядит вот так.

% ls -la /lib/firmware/brcm/*43430*
...
/lib/firmware/brcm/brcmfmac43430-sdio.bin   # <=== бинарник фирмвари
/lib/firmware/brcm/brcmfmac43430-sdio.txt   # <=== конфиг

Но как видно из ошибки, драйвер пытается загрузить firmware из файла с суффиксом вендора устройства, то есть /lib/firmware/brcm/brcmfmac43430-sdio.xunlong,orangepi-zero-plus2-h3.bin вместо /lib/firmware/brcm/brcmfmac43430-sdio.bin. Поэтому я решил просто создать нужные симлинки.

Забегая вперёд должен отметить, что это оказалось необязательно, а эта ошибка это скорее предупреждение. Походу драйвер таки находит фирмварь и по существующим именам. Но что сделано, то сделано и как минимум убираются сообщения об ошибках при загрузке.

После исправления имеем такую картину.

% ls -la /lib/firmware/brcm/*43430*
...
/lib/firmware/brcm/brcmfmac43430-sdio.bin   # <=== бинарник фирмвари
/lib/firmware/brcm/brcmfmac43430-sdio.txt   # <=== конфиг
/lib/firmware/brcm/brcmfmac43430-sdio.xunlong,orangepi-zero-plus2-h3.bin -> /lib/firmware/brcm/brcmfmac43430-sdio.bin
/lib/firmware/brcm/brcmfmac43430-sdio.xunlong,orangepi-zero-plus2-h3.txt -> /lib/firmware/brcm/brcmfmac43430-sdio.txt

Теперь при загрузке видим следующее

% dmesg | grep brcm
brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43430-sdio for chip BCM43430/1 # <== стало норм
brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43430-sdio for chip BCM43430/1 # <== стало норм
brcmfmac: brcmf_c_process_clm_blob: no clm_blob available (err=-2), device may have limited channels available
brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM43430/1 wl0: Mar 30 2016 11:30:56 version 7.45.77.h8.4 FWID 01-ee8a6268

Задаём код региона

Несмотря на успешную загрузку фирмвари, нас осталась ошибка как раз насчёт ограничения каналов и фирмварь ругается на какой-то clm_blob. Это как оказалось ещё один бинарник с региональными настройками для данного драйвера. И с этими самыми настройками полная чехарда. В разное время за это дело отвечали следующие подсистемы.

CRDA (central regulatory domain agent)

С этим связаны рекоммендации поправить регион в /etc/default/crda, но нифига не работает, так как эта тема устарела с версии ядра 4.15

cfg80211

Есть так же рекоммендации передать регион драйверу Linux cfg80211, но это тоже устарело и сегодня каждый драйвер должен сам уметь разбираться с такими делами.

echo "options cfg80211 ieee80211_regdom=US" > /etc/modprobe.d/cfg80211.conf

clm_blob

Это по факту кусок базы данных, типа той, что использовалась в CRDA, но специфичный для данного драйвера. Как оказалось и этот метод устарел и вся информация уже должна содержаться в недрах драйвера. К слову я таки нашёл этот бинарь от Raspberry PI и подсунул для загрузки, но работать лучше не стало.

И что таки делать?

В итоге пришлось лезть в конфиг фирмвари и уже там я обнаружил подозрительную переменную ccode=ALL, поменяв значение которой, после перезагрузки я получил полный список Wi-Fi сетей.

#AP6212_NVRAM_V1.0_20140603
# 2.4 GHz, 20 MHz BW mode

# The following parameter values are just placeholders, need to be updated.
.....
xtalfreq=26000
nocrc=1
ag0=255
aa2g=1
ccode=ALL # <===== вот тут меняем ALL на RU 
extpagain2g=0
........

Но тут есть проблема — при обновлении пакета с фирмварями этот файл будет перезаписываться.

Всё чудесатее и чудесатее

Гугля по теме обнаружил ссылки на исходники с такими комментариями

/* In some cases the EFI-var stored nvram contains "ccode=ALL" or
 * "ccode=XV" to specify "worldwide" compatible settings. ccode=ALL is
 * not understood by the firmware and some of the firmware files in
 * linux-firmware support only 2.4 GHz and not 5 GHz when ccode=XV.
 */

Так, что видимо стоит попробовать вместо RU использовать XV. Возможно даже появится диапазон 5ГГц.

Я сдаюсь

Кроме всего прочего искал способ прописать ccode в драйвер через /proc или /sys.
Декомпилировал devicetree в надежде найти там способ перезаписать значения NVRAM.

Все тщетно. Походу эти фирмвари и драйвера для Broadcom писались через жопу, на скорую руку и всё, что нам остаётся это грязно патчить через подмену значения в этом текстовом конфиге.

Итого

Как оказалось в принципе по минимуму достаточно поменять ccode=ALL на ccode=RU в конфиге фирмвари драйвера.

И видимо в автозагрузку придётся добавить скрипт для замены ccode в нужном файле.

Ссылки

Комментарии