一个高通 ath10k 路由 Openwrt 适配记(QCA9563+QCA9886)

宿舍设备密度太太太大2.4G的无线几乎没法用不管是学校的AP还是自己的路由都卡成屎所以没法必须搞个5G+802.11AC的路由

总方向自然是越便宜越好但是以后还是有机会用到的还是不能太差了加之本人对高通方案的路由比较偏爱锁定视线到了斐讯的K2T不过一百多的售价还是贵了最终偶然发现恩山有人卖相同方案的矿渣79包邮https://www.right.com.cn/forum/thread-1023506-1-1.html

硬件篇

收到货应该是矿渣倒闭之后滞留在工厂的货是全新的

配置:
CPU: QCA9563+128M DDR2+16M SPI Flash
2.4G: CPU自带2.4G功能+SKY85310-21独立功放
5G: QCA9886+MSC589H功放
全千兆网口

虽然功放是外置的但是似乎参数一般不过这个价钱这个配置不算亏

DC_POWER

12V1.5A DC 5.5*2.1mm电源有点分量比三无电源要靠谱很多

CASE

巨大的外壳底面贴纸标明着他的身份CSAC路由器这是层铁板增重装高端吗脚垫和标签下面有一共5颗螺丝拧下之后铁板就可以很轻松的取下来

PCB-PS

拆出来主板其实跟硕大的铁壳相比小多了买家秀里有大佬给做了个亚克力外壳

用料还可以该有的都有主要芯片还给上了散热片2.4G本来是3T3R被阉割了一路5G2T2R值得一提的是5G的天线是IPEX插头的白胶下面可以自己更换天线但是2.4G是焊接头的难道这矿渣还准备出好几个挡位的配置吗哈哈

板子上还有1Mini PCIE接口留了焊盘不过貌似没看到主板有走线不懂什么意思但是USB脚是有走线的可以引出额外的1USB2.0接口没什么卵用

左上角可以看到两颗芯片丝印着CSAC5K应该是挖矿芯片了据说没通电但是还是用自己的固件比较放心

原厂固件篇

自带的固件是qsdk功能简陋确实没什么好说的不过好奇心使我还是解包去研究了下这是伏笔

nmap扫一下发现有两个端口开了HTTP服务还有个好像是HTTPS响应的结果有些奇怪的名字

先上TTL拿到dmesg之后发现要密码才能进系统随便试了试无果

先刷Breedbreed-qca956x-uart_rx18_tx22-reset2(Auto).bin

Breed导出完整固件备份解包得到rootfs

逛了逛发现如下信息openwrt适配作准备

Caldata
2.4G: /tmp/wifi0.caldata 来自ART分区 skip=4096 count=1088
5G: /tmp/wifi1.caldata 来自ART分区 skip=20480 count=12064
Board Data FileboardData_2_0_QCA9888_5G_Y9690.bin
/lib/firmware/QCA9888/hw.2/boarddata_0.bin 来自 /usr/share/base-config/9886_calData_20171012_edit.bin
Code swap structure
bin_filename=QCA9888/hw.2/athwlan.bin swap_filename=/lib/firmware/QCA9888/hw.2/athwlan.codeswap.bin

此外虽然我们没有在原厂固件发现挖矿相关的信息但是在固件内是可以看到他们业务的相关代码的

代码位置在rootfs/usr/share都是lua写的

Code

至于有些啥感兴趣的自己研究吧

番外篇

其实也不算秘密这个圈子就这么大做矿机的自己不懂技术那找谁做呢其实做矿机的和那些捡垃圾的大神研究矿渣的大神其实就是一拨人

前脚给矿机做系统赚一波钱矿机崩了就民间大神出来适配固件迅速低价抛货清盘走人你说民间大神多厉害做出来的固件又好用那你说民间大神他能不厉害吗本身这玩意就是他做的他能不懂么

不过对于垃圾佬来说只要价钱合适我们倒是不亏的

这个机子就是这样的一个老板一个圈内玩家一个民间大神一起唱出戏机子就清掉了~

1

2

这个民间大神倒是确实是也应该对路由器感兴趣github上可以看到给Openwrt也有不少的Contribution

3

那他跟这路由还有啥关系呢

4

随手搜一下发现固件中许多代码的作者署名都是他

其实用nmap扫一下原厂固件的时候就发现了在某个端口的返回信息中也有他的署名所以这才勾起的我深入研究的欲望

适配篇

据说此板的原型是高通的AP152 Reference Broad加上ath10k的支持就好了

固件适配没什么太多好讲的就是改改灯的定义按钮的定义和接口的定义闪存布局什么的跟AP152也都一样基本上就是改个名字的区别了具体可以看:https://git.mr-cn.net/mr/openwrt/commit/16dda3ab84944253f800e508a289491738ec4a53

不过有一些题外话可以讲

在上面的commit可以看到我是适配在了ar71xx分支下的ar71xx这代其实很特殊ar71xx\ath79其实都是他的分支两个都可以工作71xx的支持非常多大部分经典的高通的CPU都是在这个分支下面的ath79其实跟他基本上是一个东西区别在于ath79是基于DTSLinux的设备树来定义的设备信息Linux的一种定义嵌入式设备信息的一种流行的做法ar71xx可能是因为历史悠久跨度比较长可能在最开始DTS还没有发展起来所以是Openwrt自己的一种定义方式也就是mach-xxxx.c的文件定义的

我当然希望适配最新的分支所以一开始是基于ath79做的可惜这个路由的闪存布局并不合理内核与rootfs是分开的所以内核的大小是有限制的ath79作为后续分支内核版本比较新功能更丰富但是也带来了体积更大的问题而我们CSAC路由的内核分区的大小就刚好卡在了这个边缘据查询资料得知4.14之后的内核大小有一个明显提升ATH79是不支持4.14之前的内核的而作为历史遗留ar71xx却是可以支持4.9所以只好基于ar71xx重新适配

我们路由器本身的闪存大小是足够的只是分区限制了说明还是有途径解决的或许需要修改MTD分区表或许还需要修改Bootloader也就意味着没法使用Breed所以暂时没有研究下去了毕竟现在也可以用不是

到这里固件就已经可以生成了编译出来也确实可用测了一下网卡Intel 9265ac同样的位置12M穿一堵墙这个路由的吞吐是我网件R6400三分之二性能一般但相较于价格而言我认为已经挺值了也确实给我在校生活的品质带来了显著的提升哈哈

此外这个路由自带的天线也比较拉跨至少看起来是的鉴于5G的天线接口时IPEX如果把天线更换成外置的有一定增益的效果应该还能改善2.4G的就还是别折腾了吧艹死都就那样了焊接式的天线也不建议更换天线这玩意应该还是有点讲究的瞎焊可能会影响天线效果

芯片还支持802.11kvr多搞几个可以组多AP漫游网也就是所谓的Mesh还支持MU-MIMOopenwrt把这些功能全部解锁出来了

此外虽然openwrt可以支持到高达30dbm,1000mw的输出功率但是十分不建议一个是功放芯片本身只支持到20dbm的增益发热巨大之外还可能烧功放另外一个是光发射功率都顶到整整1W这个辐射还是有一定风险的建议就开到20dbm就好了这机器的瓶颈我觉得是那拉跨的天线而不是发射功率

榨干他

不过到这里还没完我们还有改善的空间之前适配虽然能用但都是按照通用的套路去适配的与机器相关的参数也只有一个从ART分区提取的pre-cal校准参数据资料显示如果加载原厂固件的Board Data而不是公版的Board Data信号质量理论上还可以获得提升

下面的内容全网都找不到资料可能只有高通内部的人有资料本人在全网各种搜寻资料后将自己的理解分享出来仅供参考

ath10kath9k是有区别的ath9k只是单纯的网卡设备ath10k更像一个SoC其功能变得更加复杂运行时也需要更复杂的固件所以在初始化设备时需要主机提供相关的固件下载到网卡中此时下载的固件不单纯是网卡的工作代码还有我们主机的主板的一些参数总所周知同样的芯片因为搭配的运放电路IC不同效果会因主板而异甚至是同一主板不同个体之间都可能不相同所以才需要ART分区保存着的校准参数这些校准参数应该也是在这个时候一同下载到网卡的

来分析原厂固件的log

[   16.500296] PCI: Enabling device 0000:00:00.0 (0000 -> 0002)
[   16.506154] hif_pci_enable_bus: hif_enable_pci done *********** QCA9888 *************hif_pci_enable_bus: hif_type = 0xe, target_type = 0xchif_pci_enable_bus: hif_pci_probe_tgt_wakeup donehif_target_sync: Loop checking FW signalhif_target_sync: Got FW signal, retries = 0hif_config_ce: ce_init donehif_config_ce: X, ret = 0hif_set_hia: Ehif_set_hia_extnd: E
[   16.549333] chip_id 0xc chip_revision 0x0
[   16.553665] 
[   16.553665]  CLOCK PLL skipped
[   16.558341] hif_set_hia_extnd: setting the target pll frac ffffffff intval ffffffff
[   16.566251] hif_set_hia_extnd: no frac provided, skipping pre-configuring PLL
[   16.576652] hif_pci_bus_configure: hif_set_hia donehif_configure_irq: Ehif_pci_configure_legacy_irq: Ehif_pci_configure_legacy_irq: X, ret = 0hif_enable: X OKhif_napi_create: NAPI structures initializedhif_napi_create: NAPI id 6 created for pipe 5qca_napi_create: napi instance 32 created on pipe 4
[   16.604002] hif_napi_event: received evnt: CONF cmd; v = 1 (state=0x1)hif_napi_event: setting configuration to ON
__ol_ath_attach() Allocated scn 86080420
[   16.619839] __ol_ath_attach: dev name wifi1
[   16.624195] ol_ath_attach interface_id 1
[   16.628920] ol_target_init() BMI inited.
[   16.633118] ol_target_init() BMI Get Target Info.
[   16.637977] Chip id: 0xc, chip version: 0x1000000
[   16.642853] 
[   16.642853]  CE WAR Disabled
[   16.647498] NUM_DEV=1 FWMODE=0x2 FWSUBMODE=0x0 FWBR_BUF 0
[   16.653299] ol_target_init() configure Target .
[   16.658076] 
[   16.658076]  Target Version is 1000000
[   16.663493] 

// 这上面都是启用设备的过程

[   16.663493]  Flash Download Address  c0000 
// 开始确定下载的地址了
[   16.669337] ol_transfer_bin_file: flash data file defined
[   16.674920] ol_transfer_bin_file[3637] Get Caldata for wifi1.
[   16.680963] qdf_fs_read[59], Open File /tmp/wifi1.caldata SUCCESS!!file system magic:16914836super blocksize:4096inode 205file size:12064qc98xx_verify_checksum: flash checksum passed: 0x5bb1
// 第一次下载载入了/tmp/wifi1.caldata
// 在rootfs/lib/preinit/81_load_board发现将art分区中的校准参数保存到了/tmp/wifi1.caldata
// 所以说其实第一步加载的是art分区
[   16.698681] ol_transfer_bin_file 3698: Download Flash data len 12064

// Flash data 来自art分区

[   16.705704] Board extended Data download address: 0x0
// 这里没有log 不知道Board extended Data从哪来的
// 也可能是没有下载Board extended Data 所以没有log
[   16.734002] 
[   16.734002]  Board data initialized

// Board extended Data

[   16.739185] ol_ath_download_firmware: Download OTP, flash download ADDRESS 0xc0000
[   16.747020] 
[   16.747020]  Selecting  OTP binary for CHIP Version 0
[   16.812795] ol_transfer_bin_file 3518: downloading file 0, Download data len 9084
// 9084 这个size很少见 几乎可以肯定是来自rootfs/lib/firmware/QCA9888/hw.2/otp.bin
[   16.855272] 
[   16.855272]  First OTP send param 8000
[   17.101422] ol_ath_download_firmware :First OTP download and Execute is good address:0x4000 return param 4660
[   17.111673] ol_ath_download_firmware:##Board Id 16 , CHIP Id 0
// 又一关键信息 Board Id 16
[   17.117804] ol_ath_download_firmware: BOARDDATA DOWNLOAD TO address 0xc0000
[   17.125019] 

// OTP结束 来自rootfs/lib/firmware/QCA9888/hw.2/otp.bin

[   17.125019]  wifi1: Selecting board data file name boardData_2_0_QCA9888_5G_Y9690.bin
[   17.134651] ol_transfer_bin_file: Board Data File download to address=0xc0000 file name=QCA9888/hw.2/boardData_2_0_QCA9888_5G_Y9690.bin
[   17.147593] ol_transfer_bin_file 3518: downloading file 3, Download data len 12064
// 重新加载了boardData不是很懂原因
// 猜想大概是因为上面获得了EMI Board ID所以重新匹配

[   17.155881] Board extended Data download address: 0x0
// 这应该是没有下载

[   17.184361] ol_ath_download_firmware: Using 0x1234 for the remainder of init
[   17.191666] 
[   17.191666]  Selecting  OTP binary for CHIP Version 0
[   17.198614] ol_transfer_bin_file 3518: downloading file 0, Download data len 9084
// 又一次OTP?
[   17.241076] 
[   17.241076]  [Flash] : Ignore Module param
[   17.246836] 
[   17.246836]  Second otp download Param 10000 
// 确实是second otp
[   17.503711] ol_ath_download_firmware : Second OTP download and Execute is good, param=0x0 
[   17.512254] 
[   17.512254]  Mission mode: Firmware CHIP Version 0
[   17.660982] ol_swap_seg_alloc: Successfully allocated memory for SWAP size=262144 
[   17.673891] Swap: bytes_left to copy: fw:16; dma_page:27561
[   17.679651] Swap: wrong length read:0
[   17.683460] ol_swap_wlan_memory_expansion: Swap total_bytes copied: 234583 Target address 41a508 
[   17.692775] scn=86080420  target_write_addr=41a508 seg_info=86138010 
[   17.699425] ol_transfer_swap_struct:Code swap structure successfully downloaded for bin type =2 
[   17.708514] bin_filename=QCA9888/hw.2/athwlan.bin swap_filename=/lib/firmware/QCA9888/hw.2/athwlan.codeswap.bin 
// 下载USB firmware
// codeswap不知道是干嘛的
[   17.719098] ol_transfer_bin_file: Downloading firmware file: QCA9888/hw.2/athwlan.bin
[   18.077288] ol_transfer_bin_file 3518: downloading file 1, Download data len 372784
// 根据这个大小应该可以确定是 rootfs/lib/firmware/QCA9888/hw.2/athwlan.bin

[   19.516913] ol_target_init() Download FW done. 
// 下载过程完毕

根据这次启动过程可以看到用到了四种关键的bin文件1.broaddata 2.OTP 3.athwlan.bin 4.athwlan.codeswap.bin

其中broaddata用到了QCA9888/hw.2/boardData_2_0_QCA9888_5G_Y9690.binART中提取的/tmp/wifi1.caldata此外在前文提到过的/lib/preinit/81_load_board中还可以发现涉及到了9886_calData_20171012_edit.bin这一文件也就是/lib/firmware/QCA9888/hw.2/boarddata_0.bin的来源虽然在log中没有发现被使用但从命名来看我觉得也是有价值的具体情况到底是用哪个目前我也还没有弄清楚

OTP文件一定是/lib/firmware/QCA9888/hw.2/otp.bin

athwlan.bin文件一定是/lib/firmware/QCA9888/hw.2/athwlan.bin

ps此机器的802.11ac芯片是QCA988698869888都是使用9888的驱动其余芯片为988X

上面的启动过程是qsdkOpenwrt中并没有这么多的文件只有board-2.bin,board.bin,firmware-5.bin其中board.bin还是一个空文件文件实际上是一串ASCII文本../../cal-pci-0000:01:00.0.bin那么这些固件是怎么加载的呢

上面的启动过程是qsdkOpenwrt中并没有这么多的文件只有board-2.bin,board.bin,firmware-5.bin其中board.bin应该是一个符号链接链接到cal文件那么这些固件是怎么加载的呢

实际上是OTP与固件athwlan.bin封装成的firmware-X.bin其中X代表固件的API版本这个X应该与无线芯片型号有关在这里我的QCA98865

[1]此外broaddata有很多版本openwrt将许多路由使用的broaddata都收集到了一起都封装到了board-2.bin文件中根据主板的EMI Board ID调用

所以说我们现在的目的就是加载正确的broaddata但是到底哪个是正确的又如何让Openwrt选择我们希望的broaddata进行加载呢?我目前暂无头绪

psath10kfirmware现在有第三方公司在维护优化版本-ct版本在编译固件时可选用CT版本的驱动普通版本的驱动搭配普通固件或者ct版本的固件使用htt-mgt版本的固件搭配ct驱动使用

ath10k驱动笔记

HTT-MGT版本作用[2]

The HTT-MGT variants transport management frames over the normal HTT tx path, just like data frames.
This saves limitted WMI buffers which can become depleted if lots of management frames become stuck in TX queues due to peer that went away.
In addition, at least for the wave-1 firmware, htt-mgt is required in order for 802.11r (fast roaming) authentication to function properly.

CT固件-驱动对应关系[2]

The htt-mgt firmware requires the use of the ath10k-ct driver. Normal non-htt-mgt ath10k-ct firmware should work
with stock drivers.

ath10k启动流程[3]

I recall qca4019 have the following flow: pre-cal -> otp get chip id -> get proper board file -> populate via otp (see commit 3d9195ea19e48).

所以说看来我之前的猜测是正确的

openwrt中的校准文件

pre-cal是来自ARTcal暂时不知道是来自哪里cal似乎不重要可以缺失

参考资料:

  1. https://github.com/erstrom/linux-ath/wiki/Firmware

  2. https://patchwork.ozlabs.org/project/lede/patch/1521585595-23155-4-git-send-email-greearb@candelatech.com/

  3. https://lists.infradead.org/pipermail/ath10k/2016-November/008766.html

  4. https://lists.infradead.org/pipermail/ath10k/2017-January/009025.html

ps: 邮件列表真是个好地方大多数资料都是来自这里