This commit is contained in:
zhongluofeng
2026-08-21 18:28:33 +08:00
commit 9e478f1591
76 changed files with 27707 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
# LEDE 5G 固件构建与分析记录
> 日期:2026-08-21
> 仓库:https://github.com/Atieei/ledefork 自 coolsnowwolf/lede
> 提交:`a09ade8` add 5G modem support (RM520N-GL MBIM) with luci management and CI build
> 目标:飞牛OS (fnOS) KVM 虚拟机 + PCIe 直通 RM520N-GL,编译带自写管理界面的精简稳定版 LEDE 固件
---
## 一、实测经验核心结论(固件设计依据)
以下结论来自 RM520N-GL 在 fnOS KVM + PCIe 直通环境下的实测,是整个固件方案的基石:
| 结论 | 详情 |
|---|---|
| MBIM 是唯一可行模式 | RM520N-GL 在 PCIe/MHI 下 QMI 通道不可用,驱动必须以 `mhi_mbim_enabled=1` 加载 |
| 拨号命令禁用 -i 参数 | MBIM 模式下 `quectel-CM -s <APN>` 即可,传 `-i rmnet_mhi0` 会导致异常 |
| 驱动版本 | pcie_mhi V1.3.8(源码来自 Siriling/5G-Modem-Support 的 quectel_MHI |
| 拨号工具 | quectel-CM V1.6.8QConnectManagerMBIM 路径实测通过) |
| AT 通道与拨号并存 | `/dev/mhi_DUN`sms_tool AT)与 `/dev/mhi_MBIM` 拨号可同时使用 |
| SYS_ERR 故障 | 模块失联时 VM 内 reboot 无法恢复(不切断 PCIe 供电),需阶梯式自愈或宿主机断电 |
| 数据接口 | 拨号成功后 IP 出现在 `rmnet_mhi0.1` |
---
## 二、固件包结构(package/5g-modem/
```
package/5g-modem/
├── pcie-mhi/ # 内核驱动 kmod-pcie-mhi (V1.3.8)
│ ├── Makefile # 外部内核模块编译 (kbuild, 产出 pcie_mhi.ko)
│ ├── src/ # 驱动源码 (core/controllers/devices)
│ └── files/etc/modules.d/90-pcie_mhi # 开机自动加载: pcie_mhi mhi_mbim_enabled=1
├── quectel-cm/ # 拨号工具 quectel-cm (V1.6.8)
│ ├── Makefile # musl-gcc 单命令编译 (与实测通过的编译命令一致)
│ └── src/ # QConnectManager 源码
├── sms-tool/ # AT 命令工具 (obsy/sms_tool + 中文编码修正补丁)
└── luci-app-5gmodem/ # 自写 LuCI 管理应用
├── luasrc/controller/5gmodem.lua # 菜单 + API (status/dial/at)
├── luasrc/model/cbi/5gmodem/settings.lua # 设置页 (APN/认证/PIN/守护开关)
├── luasrc/view/5gmodem/status.htm # 状态页 (轮询+控制+AT控制台)
└── root/
├── etc/config/5gmodem # UCI 默认配置
├── etc/init.d/5gmodem # procd 拨号服务 (START=95)
├── usr/bin/5gmodem-guard # SYS_ERR 自愈守护
└── usr/libexec/5gmodem-status.sh # 状态采集 (JSON 输出)
```
依赖声明:`luci-app-5gmodem``+kmod-pcie-mhi +quectel-cm +sms-tool +luci-compat`
---
## 三、LuCI 管理界面功能
菜单:网络 → 5G 拨号(状态 / 拨号设置)
**状态页(10 秒轮询)**
- 服务与驱动:quectel-CM 运行状态/PID、守护状态、pcie_mhi 加载、MBIM/DUN 通道就绪、PCI 设备地址
- 连接信息:`rmnet_mhi0.1` 的 IP、上下行流量(自动格式化 B/KB/MB/GB
- 模块信息:型号/制造商/固件/IMEI/IMSI/SIM 状态/运营商(PLMN 数字映射中文名)/网络模式/频段信道
- 信号质量:RSRP/SINR/RSRQ/RSSI,带优/中/差彩色分级标签
- 拨号控制:启动/停止/重启(POST + token,防 CSRF
- AT 控制台:自由输入 + 15 条常用命令快捷下拉(QCSQ/QNWINFO/QENG="servingcell"/QTEMP 等),输出区滚动显示
- 拨号日志:/tmp/quectel_cm.log 尾部 12 行实时展示
**设置页**
- 开机自动拨号、APN(默认 wonet)、PAP/CHAP 用户名密码(明文显示便于调试)、认证方式、PIN 码、AT 串口路径、自愈守护开关
**API(控制器)**
- `api_status`GET 状态 JSON
- `api_dial`POST start/stop/restart/reload(白名单校验)
- `api_at`:POST AT 命令,正则白名单校验(`^AT` 开头,允许字母数字空格 `+ " = % ? , . : / # * ( ) -`,禁单引号保证 shell 拼接安全),串口路径二次校验 + 存在性检查
---
## 四、SYS_ERR 自愈守护(5gmodem-guard
基于实测故障经验设计,procd 托管、每 15 秒巡检,恢复阶梯:
1. **阶段 1**`echo <bdf> > /sys/bus/pci/drivers/mhi_q/bind`(实测有效的手动唤醒法,每 30s 重试)
2. **阶段 2**PCI remove + rescan,重走 BHI 固件下载(故障 120s 后,每 60s 一次)
3. **阶段 3**rmmod pcie_mhi + 重加载 MBIM 模式(故障 300s 后,每 90s 一次)
4. **阶段 4**:日志提示需宿主机断电(故障 600s 后,每 300s 提示;VM 内无法切断 PCIe 供电属物理限制)
附加:设备在但 quectel-CM 进程死亡超过 60s 时自动 restart 拨号服务。日志写入 `/tmp/5gmodem_guard.log`(超 200 行自动截半)。
设备识别:扫描 `/sys/bus/pci/devices/*/vendor` 匹配移远 `0x17cb`/`0x1eac`
---
## 五、兼容性验证记录(关键分析)
### 5.1 LuCI 分支兼容性(openwrt-25.12
feeds.conf.default 使用 `coolsnowwolf/luci;openwrt-25.12` 分支,该分支 ucode dispatcher 为新架构。逐项读源码实证:
1. **Lua controller 支持**`modules/luci-base/ucode/dispatcher.uc``glob('/usr/lib/lua/luci/controller/*.lua')` 扫描并通过 `runtime.call('luci.dispatcher', 'process_lua_controller', file)` 桥接处理 → 旧式 controller 完全可用
2. **依赖链完整**`luci-compat` (Makefile: `LUCI_DEPENDS:=+luci-lua-runtime`) → `luci-lua-runtime` 模块存在(含 dispatcher.lua/template.lua 等),luci-base 依赖 `ucode-mod-*` 全套
3. **模板桥接**`luci-lua-runtime/luasrc/template.lua``include()` 在 Lua 视图目录找不到时回退 `L.include(name)`ucode 主题模板),因此 `<%+header%>`/`<%+footer%>` 正确渲染主题框架;bootstrap 主题提供 `ucode/template/themes/bootstrap/header.ut|footer.ut`
4. **同模式先例**:该分支有 68 个 luasrc/controller 文件、150 个 CBI 文件(docker/diskman/lucky/nfs 等应用均为旧式 Lua 写法)
5. **CBI Flag 类**`luci-compat/luasrc/cbi.lua` Flag 构造器初始化 `enabled="1"/disabled="0"`,设置页默认值逻辑正确
### 5.2 内核驱动 6.12/6.18 兼容性
- pcie_mhi 源码版本守护完善:42 处 `LINUX_VERSION_CODE` 条件编译
- 关键破坏点 `class_create` 已适配:`mhi_uci.c:954``mhi_init.c:2678` 均有 `>= 6.4.0` 单参数版本分支
- `mhi_netdev_quectel.c` 有 6.1 分界适配(netdev/dm/timer API
### 5.3 重要发现与修正:virtio 配置冗余
原计划在 `target/linux/x86/config-6.12` base 配置添加 KVM guest 支持。复查发现 **`target/linux/x86/64/config-6.12`(6.18 同)子目标配置已内建全套支持**(`HYPERVISOR_GUEST`/`KVM_GUEST`/`PARAVIRT`/`PARAVIRT_CLOCK`/`VIRTIO`/`VIRTIO_PCI`/`VIRTIO_NET`/`VIRTIO_BLK`/`VIRTIO_BALLOON`/`SCSI_VIRTIO`/`HW_RANDOM_VIRTIO`/`DRM_VIRTIO_GPU` 等全为 y,且子目标配置覆盖合并 base)。
**处置**:回退 base config 修改。fork 相对上游 diff 仅剩纯新增的 3 个目录(`.github/workflows/``configs/``package/5g-modem/`),后续同步上游零冲突。
### 5.4 内核竞争配置检查
确认内核主线 MHI 相关配置(`CONFIG_MHI_BUS` 等)未启用,与外部 pcie_mhi 驱动无符号竞争。
---
## 六、本地校验记录(提交前)
| 项目 | 方法 | 结果 |
|---|---|---|
| 4 个 shell 脚本 | Git Bash `sh -n`status.sh / guard / init.d / modules.d | 全部通过 |
| status.htm 内嵌 JS145 行) | Node `new Function()` 语法检查(LuCI 模板占位符替换后) | 通过 |
| 2 个 Lua 文件 | 自写块结构平衡检查器(剥离注释/字符串后统计 function/if/do/end 配对) | 通过 |
| 行尾检查 | 逐文件统计 CRLF | 仅 sms-tool/Makefile 为 CRLF,已规范化为 LF |
| 执行位 | `git update-index --add --chmod=+x` 三个脚本 | 索引中 100755 确认 |
| 行尾入库保障 | `package/5g-modem/.gitattributes`*.sh/*.lua/*.htm/Makefile 强制 LF | 已设置 |
---
## 七、Git 提交与推送
- 克隆采用 `--depth=1 --filter=blob:none` + sparse-checkout(仅 target/linux/x86 等),提交前将新目录加入 sparse 规则
- 提交 `a09ade8`80 个文件,45600 行插入
- 已推送 `master``origin/master`81636b7..a09ade8
- 三个可执行脚本(init.d/5gmodem、5gmodem-guard、5gmodem-status.sh)以 100755 模式入库(Linux 上 procd 直接执行必需)
---
## 八、新镜像构建与产物
### 构建方法(手动触发)
1. 打开 https://github.com/Atieei/lede/actions
2. 左侧选 **Build 5G-Modem LEDE (x86_64)**
3. **Run workflow** → 直接 Run(首编约 2-3 小时)
4. 可选输入:勾选"忽略缓存全量重编"(首次构建或缓存异常时使用)
### 工作流特性
- 运行环境 ubuntu-22.04lede 官方 CI 同款依赖安装 + jlumbroso/free-disk-space 磁盘清理
- toolchain/dl 缓存(key 含 feeds.conf.default 与种子配置哈希),重编大幅提速
- `.config``configs/x86_64-5gmodem.config` 种子 + `make defconfig` 生成,并强校验 5G 五个包必须被选中(否则立即失败)
- 编译失败自动重试 `make -j1 V=s` 并产出日志 artifact
### 产物(3 个 artifact
| Artifact | 内容 |
|---|---|
| lede-5gmodem-firmware-x86_64 | 固件镜像(BIOS+EFI 双启动 squashfs+gzip,位于 bin/targets/x86/64/ |
| lede-5gmodem-packages | 全部 .ipk(可装进现有系统调试,无需重刷固件) |
| lede-5gmodem-buildinfo | *.buildinfo / *.manifest(精确还原配置) |
### 精简配置说明(configs/x86_64-5gmodem.config
- 关闭:CPU 微码、声卡全套、物理显卡(amdgpu/i915)、物理网卡(igb/i40e/mlx5/r8125 等 17 种)、USB 网卡、f2fs/mmc/传感器/自动挂载
- 保留:e100/e1000/e1000eKVM 常见网卡)+ virtio(内核内建)+ PCIe 直通 + LuCI 中文界面 + 5G 全套包
---
## 九、部署指南
1. 下载固件 artifact,解压取 `*-x86-64-generic-squashfs-combined-efi.img.gz`fnOS KVM 用 EFI
2. `gunzip` 后作为磁盘导入 KVM 虚拟机,vCPU/内存按需,PCIe 直通 RM520N-GL
3. 首次启动后 LAN 口(默认 192.168.1.1)访问 LuCI → 网络 → 5G 拨号
4. 设置页填 APN(联通 wonet)保存即自动拨号;或状态页手动"启动拨号"
5. 多 WAN 需手动配置(固件按需求不预置策略路由)
## 十、故障排查速查
| 现象 | 排查 |
|---|---|
| 状态页全灰 | `lsmod | grep pcie_mhi``ls -l /dev/mhi_*``cat /tmp/5gmodem_guard.log` |
| 拨号无 IP | `cat /tmp/quectel_cm.log`(完整日志)、AT 控制台发 `AT+CPIN?` 查 SIM |
| 自愈不成功 | 看守护日志阶段提示;600s 仍未恢复需宿主机断电(物理限制) |
| AT 控制台无响应 | 确认 `/dev/mhi_DUN` 存在;串口路径在设置页可改 |
| ipk 调试 | artifacts 的 packages 里直接 `opkg install` 对应 ipk 到现有系统 |