[AI Native][OpenWrt] 给犀牛 R66S 编译 OhMyWrt:从一句话到 TF 卡直接启动
这是一次完整的 AI Native 固件构建:我只提出目标,AI 通过 SSH 调查设备支持、配置并编译 OhMyWrt、校验产物、设计无 HDMI 验收流程;我唯一做的事情,是用 balenaEtcher 把镜像写进 TF 卡,然后插卡、接网线、上电。
Tags: AI Native OpenWrt OhMyWrt FastRhino R66S ARM64 Homelab
目录
- 这次到底是谁做了什么
- 为什么 R66S 需要单独编译
- 确认目标:ARM64 不等于随便一个 ARM 固件
- 构建环境
- 准备 OhMyWrt
- 配置 R66S 与软件包
- 开始编译
- 验证构建产物
- 用 balenaEtcher 写入 TF 卡
- 没有 HDMI,怎么知道它真的启动了
- 登录后的完整验收
- 最终结果
这次到底是谁做了什么
这次不是“AI 给几条命令,我自己照着敲”的传统辅助模式。
我给出的原始目标基本只有一句:
连接到构建机,给犀牛 R66S 编译 OhMyWrt,目标是 ARM 架构。
后面的工作全部由 AI 在实际环境中完成:
graph TD
A["我提出目标:给 R66S 编译 OhMyWrt"] --> B["AI SSH 登录构建机"]
B --> C["调查源码、设备树和网络定义"]
C --> D["确认 rockchip/armv8 与 R66S profile"]
D --> E["生成配置并处理软件包依赖"]
E --> F["执行交叉编译"]
F --> G["校验 SHA256、fwtool 元数据和 gzip 数据"]
G --> H["给出 TF 卡刷写与无 HDMI 验收方案"]
H --> I["我用 balenaEtcher 写卡、插卡、上电"]
I --> J["R66S 正常启动"]
我实际做的事情只有:准备一张 TF 卡,打开 balenaEtcher,选择 AI 编译好的 SquashFS 镜像,写卡,然后把卡插进 R66S,接上网线和电源。
没有手动进入 menuconfig,没有自己排查依赖,没有手工处理编译失败,也没有接显示器或串口。写完卡,插进去,就起来了。
这才是我理解的 AI Native:AI 不是在旁边解释步骤,而是直接进入真实环境,把任务从目标推进到可以使用的产物;人只保留必须接触物理设备的最后一步。
为什么 R66S 需要单独编译
犀牛 R66S 和常见的 x86 软路由不是同一种目标:
| 项目 | x86 软路由 | 犀牛 R66S |
|---|---|---|
| CPU 架构 | x86_64 |
aarch64 |
| OpenWrt target | x86/64 |
rockchip/armv8 |
| 软件包架构 | x86_64 |
aarch64_generic |
| 启动介质 | SATA、NVMe 或虚拟磁盘 | TF 卡 |
| 本地显示 | 通常有 HDMI、DP 或 VGA | 没有 HDMI 输出 |
| 首次验收 | 屏幕或虚拟控制台 | 网口、SSH,必要时 UART |
构建目标必须精确到:
Target: rockchip
Subtarget: armv8
Device: lunzn_fastrhino-r66s
Packages: aarch64_generic
完整路径是:
x86_64 Ubuntu 构建机
↓
AArch64 交叉编译工具链
↓
rockchip/armv8
↓
lunzn,fastrhino-r66s
↓
SquashFS / Ext4 TF 卡镜像
确认目标:ARM64 不等于随便一个 ARM 固件
AI 首先在 OhMyWrt 源码中确认了 R66S 的设备定义:
CONFIG_TARGET_rockchip=y
CONFIG_TARGET_rockchip_armv8=y
CONFIG_TARGET_rockchip_armv8_DEVICE_lunzn_fastrhino-r66s=y
展开后的目标信息:
CONFIG_TARGET_BOARD="rockchip"
CONFIG_TARGET_SUBTARGET="armv8"
CONFIG_TARGET_PROFILE="DEVICE_lunzn_fastrhino-r66s"
CONFIG_TARGET_ARCH_PACKAGES="aarch64_generic"
源码还明确给出了 R66S 的网络定义:
ucidef_set_interfaces_lan_wan 'eth0' 'eth1'
即 eth0 = LAN、eth1 = WAN。源码能确认逻辑接口,但不能仅靠这行配置判断机身左口或右口哪个是 LAN;第一次上电时,如果一个物理口没有获得地址,最直接的办法就是换另一个口。
构建环境
| 项目 | 配置 |
|---|---|
| 操作系统 | Ubuntu 24.04.4 LTS |
| 主机架构 | x86_64 |
| CPU | 20 vCPU |
| 内存 | 15 GiB |
| 构建方式 | 普通用户,非 root |
| OhMyWrt 提交 | 7dc7471e025142475c96d994e291a6c411d604bf |
| 固件内核 | Linux 6.12.63 |
OpenWrt 构建阶段应该使用普通用户。只有安装系统依赖时需要 sudo,不应该用 root 运行 make。构建目录也应避免空格、非 ASCII 字符、Windows 混入的异常 PATH,以及被 root 创建并遗留的文件。
准备 OhMyWrt
git clone --filter=blob:none \
git@github.com:ohmywrt/ohmywrt-next.git
cd ohmywrt-next
git checkout 7dc7471e025142475c96d994e291a6c411d604bf
./scripts/feeds update -a
./scripts/feeds install -a
构建过程使用隔离工作目录,不污染已有的 x86 构建环境。R66S 是 aarch64_generic,x86 是 x86_64,工具链、内核模块和软件包索引都不同,不应该在同一份未清理的输出目录中来回切换目标。
配置 R66S 与软件包
设备选择对应:
Target System → Rockchip
Subtarget → ARMv8 boards
Target Profile → Lunzn FastRhino R66S
核心配置:
CONFIG_TARGET_rockchip=y
CONFIG_TARGET_rockchip_armv8=y
CONFIG_TARGET_rockchip_armv8_DEVICE_lunzn_fastrhino-r66s=y
CONFIG_TARGET_ROOTFS_EXT4FS=y
CONFIG_TARGET_ROOTFS_SQUASHFS=y
CONFIG_TARGET_IMAGES_GZIP=y
CONFIG_TARGET_KERNEL_PARTSIZE=16
CONFIG_TARGET_ROOTFS_PARTSIZE=160
LuCI、网络服务与驱动:
CONFIG_LUCI_LANG_zh_Hans=y
CONFIG_PACKAGE_luci=y
CONFIG_PACKAGE_luci-i18n-base-zh-cn=y
CONFIG_PACKAGE_kmod-r8125=y
CONFIG_PACKAGE_adguardhome=y
CONFIG_PACKAGE_ddns-go=y
CONFIG_PACKAGE_luci-app-ddns-go=y
CONFIG_PACKAGE_luci-app-ksmbd=y
CONFIG_PACKAGE_luci-app-upnp=y
CONFIG_PACKAGE_luci-app-wol=y
CONFIG_PACKAGE_luci-app-nlbwmon=y
CONFIG_PACKAGE_kmod-wireguard=y
CONFIG_PACKAGE_wireguard-tools=y
CONFIG_PACKAGE_luci-proto-wireguard=y
还包含 curl、bind-dig、ethtool-full、htop、iftop、iperf3、pciutils 和 etherwake 等现场排障工具。最关键的网卡驱动是 kmod-r8125。
本次沿用了项目现有的 iptables legacy 栈:
CONFIG_PACKAGE_firewall=y
# CONFIG_PACKAGE_firewall4 is not set
CONFIG_PACKAGE_xtables-legacy=y
CONFIG_PACKAGE_iptables-zz-legacy=y
CONFIG_PACKAGE_dnsmasq_full_ipset=y
# CONFIG_PACKAGE_dnsmasq_full_nftset is not set
这组配置需要整体保持一致,不要在保留 legacy iptables、FullCone、GeoIP、TProxy 和 miniupnpd-iptables 的同时,随手打开 firewall4 与 nftset。
make defconfig
./scripts/diffconfig.sh > config-r66s.diffconfig
开始编译
make download -j"$(nproc)"
find dl -type f -size -1024c -print
make -j"$(nproc)"
如果并行编译失败,降低并发并输出详细日志:
make -j1 V=s
本次构建成功,产物位于:
bin/targets/rockchip/armv8/
验证构建产物
生成了两种 R66S 镜像:
ohmywrt-rockchip-armv8-lunzn_fastrhino-r66s-ext4-sysupgrade.img.gz
ohmywrt-rockchip-armv8-lunzn_fastrhino-r66s-squashfs-sysupgrade.img.gz
| 镜像 | 大小 | SHA256 |
|---|---|---|
| Ext4 | 约 46 MiB | ff9606fc088956b8e01006552896611b29b85b581b532a4d540af46127c4ec48 |
| SquashFS | 约 38 MiB | 302cfd5b160cd835bdb4971e81597d25c11eee522eab457c5f66cc572c66e803 |
项目生成的 checksum 全部通过:
cd bin/targets/rockchip/armv8
sha256sum -c sha256sums
直接运行 gzip -t 可能看到 decompression OK, trailing garbage ignored。这不代表固件损坏:OpenWrt 会在 gzip 数据后追加 fwtool 元数据。正确验证方式是:
staging_dir/host/bin/fwtool \
-i /dev/null \
-T bin/targets/rockchip/armv8/ohmywrt-rockchip-armv8-lunzn_fastrhino-r66s-squashfs-sysupgrade.img.gz \
| gzip -t
镜像内可以确认:
ARM64 OpenWrt Linux-6.12.63
用 balenaEtcher 写入 TF 卡
本次实际使用的是 balenaEtcher,不是命令行 dd。
选择的镜像是:
ohmywrt-rockchip-armv8-lunzn_fastrhino-r66s-squashfs-sysupgrade.img.gz
SquashFS 使用只读 /rom 加可写 overlay,并支持 failsafe 和恢复出厂。R66S 没有 HDMI,配置出错以后本地救援手段较少,因此这套恢复语义比离线修改方便的 Ext4 更重要。
实际操作只有:
- 把 TF 卡插入电脑。
- 打开 balenaEtcher。
- 选择 SquashFS 的
.img.gz文件。 - 选择正确的 TF 卡。
- 点击 Flash。
- 等待写入和验证完成。
- 安全弹出 TF 卡。
Etcher 可以直接处理压缩镜像,不需要手动解压。唯一需要反复确认的是目标磁盘:选错设备不是“刷写失败”,而是把另一块磁盘完整覆盖。
没有 HDMI,怎么知道它真的启动了
写卡完成后,R66S 断电插卡,电脑用网线直连其中一个网口,暂时不接上级路由器,然后上电等待首次启动。
默认管理地址:
http://192.168.1.1
默认用户名是 root,密码为空:
ping 192.168.1.1
curl -I http://192.168.1.1/
ssh root@192.168.1.1
如果电脑没有自动获得地址,就换另一个物理网口,或把电脑设置为 192.168.1.2/24 后重试。
本次实际体验比预想简单:TF 卡用 Etcher 写完,插入 R66S,上电以后网络就起来了。没有接 HDMI,因为它本来就没有 HDMI;也没有接 UART,因为不需要。
第一次登录后立即设置密码:
passwd
登录后的完整验收
型号与内核:
ubus call system board
cat /proc/device-tree/model
echo
uname -a
期望看到 Lunzn FastRhino R66S、aarch64 和 Linux 6.12.63。
网口与驱动:
ip -br link
lsmod | grep r8125
dmesg | grep -Ei 'r8125|eth'
TF 卡与 overlay:
dmesg | grep -Ei 'mmc|sdhci|error|fail'
mount | grep -E ' /rom | /overlay | / '
df -h
SquashFS 固件应看到只读 /rom 与可写 /overlay。持续出现 MMC I/O error、timeout 或 CRC error,通常意味着 TF 卡、读卡器或供电存在问题。
WAN 与 DNS:
ifstatus wan
ping -c 3 1.1.1.1
nslookup openwrt.org
最后验证重启持久化:
date > /etc/r66s-boot-test
sync
reboot
重新连接后文件仍存在,就说明 TF 卡 overlay 可以正常写入并跨重启保存:
cat /etc/r66s-boot-test
rm /etc/r66s-boot-test
如果网络没有起来,排障顺序应是:确认 Etcher 验证成功、等待首次启动、检查两个网口 Link、交换网口、设置静态 IP、尝试 SquashFS failsafe,最后才使用 UART。
UART 参数为 1500000 8N1,必须使用 3.3V TTL,只连接 GND、TX 和 RX,不连接 VCC。
最终结果
Target: rockchip/armv8
Device: lunzn,fastrhino-r66s
Architecture: aarch64_generic
Kernel: Linux 6.12.63
Storage: TF card
LAN/WAN: eth0 / eth1
Driver: kmod-r8125
整个过程的角色分工非常明确:
| 环节 | 执行者 |
|---|---|
| SSH 登录构建机 | AI |
| 调查 OhMyWrt 与 R66S 支持 | AI |
| 确认 ARM64 target/profile | AI |
| 生成和检查配置 | AI |
| 执行完整编译 | AI |
| 校验 checksum 与镜像元数据 | AI |
| 设计无 HDMI 启动验收方案 | AI |
| 用 balenaEtcher 写入 TF 卡 | 我 |
| 插卡、接网线、上电 | 我 |
| 系统启动 | 一次成功 |
以前这种事情通常意味着:找教程、猜 profile、进 menuconfig、处理 feeds、盯编译日志、区分设备树、确认网卡驱动,然后再担心写卡以后没有显示器该怎么办。
这次变成了:
我:给犀牛 R66S 编译 OhMyWrt。
AI:完成,镜像和校验结果在这里,推荐写 SquashFS。
我:打开 Etcher,写入 TF 卡,插卡,上电。
R66S:启动。
AI Native 的价值不只是少敲几条命令。真正的变化是:人不再需要亲自承担每一个中间步骤,只需要给出目标、保留关键决策,并完成 AI 无法替代的物理操作。
对于这次 R66S,我实际接触到的复杂度只剩下:
选择镜像
→ 写入 TF 卡
→ 插入设备
→ 上电
剩下的目标识别、交叉编译、依赖处理、固件校验和无显示验收设计,全部由 AI 在真实环境中完成。
这才是这次构建最值得记录的部分。
版权属于:一名宅。
本文链接:https://zhaiyiming.com/archives/80.html
转载时须注明出处及本声明