LS1043A NH03 OpenWrt 笔记

当前方案概览

  • 板级硬件:XSPEED NH03,NXP Layerscape LS1043A,ARMv8。
  • 板级 target/profile:layerscape/armv8_64b / fsl_nh03(显示名称为 XSPEED NH03)。
  • 个人构建配置:configs/jungle.config(普通版)和 configs/jungle-debug.config(调试版)。
  • 当前设备优先从 SATA SSD 启动:内核与 DTB 放在 sda1,根系统位于 sda2;SATA 读取失败时回退到 eMMC 的第一、第二分区。
  • 根系统生成 rootfs.tar.gz,解压到已经扩容的 ext4 分区,避免每次写入 ext4 镜像后重新扩容。
  • U-Boot 从第一分区读取 Imagefsl-nh03-sdk.dtb

板级代码负责 NH03 的硬件描述、网口映射、默认 LAN/WAN 端口和板载驱动;个人配置负责要安装的软件包、调试能力、主题以及每台设备的运行参数。不要把 COM12/COM14 的地址或 sing-box 等个人设置写进板级 profile。

板级支持(所有 NH03 构建共享)

target/linux/layerscape/。各文件职责如下:

内容 文件
NH03 设备树、I²C/GPIO、存储和 PHY target/linux/layerscape/files-6.12/arch/arm64/boot/dts/freescale/fsl-nh03-sdk.dts
板级默认 LAN/WAN 端口 target/linux/layerscape/base-files/etc/board.d/02_network
fsl_nh03 镜像 profile 和板载驱动包 target/linux/layerscape/image/armv8_64b.mk
Layerscape 6.12 平台内核选项 target/linux/layerscape/armv8_64b/config-6.12

以太网与 PHY 映射

NH03 的映射不是标准 LS1043A-RDB 映射:

Linux 接口 FMan MAC PHY MDIO 地址 用途
eth0 e0000 Marvell 88E1545 fd000 4 LAN/QSGMII
eth1 e2000 Marvell 88E1545 fd000 5 LAN/QSGMII
eth2 e4000 RTL8211F fc000 1 WAN/RGMII-ID
eth3 e6000 RTL8211F fc000 3 LAN/RGMII-ID
eth4 e8000 Marvell 88E1545 fd000 6 LAN/QSGMII
eth5 ea000 Marvell 88E1545 fd000 7 LAN/QSGMII

板级 profile

板级 profile 位于:

1
target/linux/layerscape/image/armv8_64b.mk

文件中只有一个 NH03 板级设备定义:define Device/fsl_nh03。它只提供 NH03 板载硬件、设备树和可更换 Wi-Fi 模块所需驱动,不包含 Jungle 的软件包选择或设备运行参数。

个人构建配置(Jungle)

个人配置种子位于 configs/,与板级支持分开维护:

配置 用途
configs/jungle.config 普通版:LuCI、ttyd、sing-box、网络诊断工具和主题包
configs/jungle-debug.config 调试版:包含普通版内容,并额外启用 perf、BPF/eBPF、BTF、FTrace、Kprobe 和 bpftool

两个种子都选择 layerscape/armv8_64b 下的 fsl_nh03 目标;选择目标是为了生成 NH03 镜像,软件包和调试选项才是个人配置的差异。

自定义主题源码目录也属于个人配置,必须保存在 Git 中:

1
2
3
4
package/luci-theme/
package/luci-theme-argon/
package/luci-theme-aurora/
package/luci-theme-proton2025/

选择主题包并不会自动保存这些未跟踪源码。

编译个人配置

1
2
3
cp configs/jungle-debug.config .config
make defconfig
make -j$(nproc)

关键产物:

1
2
3
build_dir\target-aarch64_generic_musl\linux-layerscape_armv8_64b\Image
build_dir\target-aarch64_generic_musl\linux-layerscape_armv8_64b\image-fsl-nh03-sdk.dtb
bin\targets\layerscape\armv8_64b\openwrt-*-rootfs.tar.gz

U-Boot 启动参数

把 SATA 和 eMMC 分成两个子命令,bootcmd_manual 按顺序先运行 SATA、再运行 eMMC。SATA 成功执行 booti 后不会返回;只有 SATA 加载或启动失败并返回时,才会继续尝试 eMMC:

1
2
3
4
5
setenv bootcmd_manual_emmc "mmc dev 0; if ext4load mmc 0:1 0xa0000000 Image && ext4load mmc 0:1 0xb0000000 image-fsl-nh03-sdk.dtb; then setenv bootargs console=ttyS0,115200 earlycon=uart8250,mmio,0x21c0500 root=/dev/mmcblk0p2 rw rootwait; booti 0xa0000000 - 0xb0000000; else echo eMMC boot failed; fi"
setenv bootcmd_manual_sata "if scsi scan && scsi dev 0 && ext4load scsi 0:1 0xa0000000 Image && ext4load scsi 0:1 0xb0000000 image-fsl-nh03-sdk.dtb; then setenv bootargs console=ttyS0,115200 earlycon=uart8250,mmio,0x21c0500 root=/dev/sda2 rw rootwait; booti 0xa0000000 - 0xb0000000; fi"
setenv bootcmd_manual "run bootcmd_manual_sata; run bootcmd_manual_emmc"
setenv bootcmd "run bootcmd_manual"
saveenv && reset

本机只有一块 SATA SSD,AHCI 驱动也已编入内核,因此 SATA 根分区直接使用 /dev/sda2。eMMC 回退分支使用 /dev/mmcblk0p2。如果以后增加其他 SCSI/SATA 磁盘,设备枚举顺序可能变化,此时再改用 PARTUUID 更稳妥。

首次启动

新 DTB 下:

1
2
3
4
cat /etc/board.json
board_name = xspeed,nh03[sdboot]
LAN = eth3 eth0 eth1 eth4 eth5
WAN = eth2

首次启动且没有旧 /etc/config/network 时,OpenWrt 会创建 br-lan,LAN 默认地址通常为:

1
192.168.1.1/24

首次连接优先使用已经验证可 Link Up 的 eth3eth0

1
ssh root@192.168.1.1

若恢复旧网络配置,COM12 使用 192.168.2.1,COM14 使用 192.168.3.1

1
2
ssh root@192.168.2.1
ssh root@192.168.3.1

首次登录立即设置密码:

1
passwd

手工恢复基础网络

以下命令建议通过串口执行。下面按 COM14 配置为 192.168.3.1;COM12 保持 192.168.2.1。网络重启后原 SSH 会话会断开。

如果不采用板级脚本生成的默认网络配置,先显式创建 br-lan,并把五个 LAN 口加入网桥。下面第一条命令用于兼容全新系统中已有的匿名 br-lan 设备;没有该设备时也不会影响后续创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
uci -q rename network.@device[0]='br_lan'
uci set network.br_lan='device'
uci set network.br_lan.name='br-lan'
uci set network.br_lan.type='bridge'
uci -q delete network.br_lan.ports
uci add_list network.br_lan.ports='eth3'
uci add_list network.br_lan.ports='eth0'
uci add_list network.br_lan.ports='eth1'
uci add_list network.br_lan.ports='eth4'
uci add_list network.br_lan.ports='eth5'
uci set network.lan.proto='static'
uci set network.lan.device='br-lan'
uci set network.lan.ipaddr='192.168.3.1'
uci set network.lan.netmask='255.255.255.0'
uci set network.lan.ip6assign='60'
uci set network.wan.device='eth2'
uci set network.wan.proto='dhcp'
uci set network.wan6.device='eth2'
uci set network.wan6.proto='dhcpv6'
uci show network
uci commit network
/etc/init.d/network restart

关闭硬件 bypass

先确认驱动和本次启动分配的 GPIO 范围:

1
2
dmesg | grep -Ei 'gpio|pca953|pca955|pca957'
cat /sys/kernel/debug/gpio

使用 OpenWrt 自带的 gpio_switch 持久化,重启后仍自动输出低电平:

1
2
3
4
5
6
7
uci set system.bypass='gpio_switch'
uci set system.bypass.name='bypass_off'
uci set system.bypass.gpio_pin='647'
uci set system.bypass.value='0'
uci commit system
/etc/init.d/gpio_switch enable
/etc/init.d/gpio_switch restart

手工恢复防火墙

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
uci show firewall | grep "\.name="

uci -q delete firewall.wan_luci
uci set firewall.wan_luci='rule'
uci set firewall.wan_luci.name='Allow-LuCI-from-upstream'
uci set firewall.wan_luci.src='wan'
uci set firewall.wan_luci.src_ip='192.168.13.0/24'
uci set firewall.wan_luci.proto='tcp'
uci set firewall.wan_luci.dest_port='80'
uci set firewall.wan_luci.target='ACCEPT'
uci set firewall.wan_luci.family='ipv4'

uci -q delete firewall.wan_ssh
uci set firewall.wan_ssh='rule'
uci set firewall.wan_ssh.name='Allow-SSH-from-upstream'
uci set firewall.wan_ssh.src='wan'
uci set firewall.wan_ssh.src_ip='192.168.13.0/24'
uci set firewall.wan_ssh.proto='tcp'
uci set firewall.wan_ssh.dest_port='22'
uci set firewall.wan_ssh.target='ACCEPT'
uci set firewall.wan_ssh.family='ipv4'

uci -q delete firewall.wan_ttyd
uci set firewall.wan_ttyd='rule'
uci set firewall.wan_ttyd.name='Allow-ttyd-from-upstream'
uci set firewall.wan_ttyd.src='wan'
uci set firewall.wan_ttyd.src_ip='192.168.13.0/24'
uci set firewall.wan_ttyd.proto='tcp'
uci set firewall.wan_ttyd.dest_port='7681'
uci set firewall.wan_ttyd.target='ACCEPT'
uci set firewall.wan_ttyd.family='ipv4'

uci -q delete firewall.k3s_api
uci set firewall.k3s_api=rule
uci set firewall.k3s_api.name='Allow-K3s-API-from-upstream'
uci set firewall.k3s_api.src='wan'
uci set firewall.k3s_api.src_ip='192.168.13.160'
# uci set firewall.k3s_api.dest='lan' 尽量不要把 lan 暴露给外面 !!!
uci set firewall.k3s_api.proto='tcp'
uci set firewall.k3s_api.dest_port='6443'
uci set firewall.k3s_api.target='ACCEPT'
uci set firewall.k3s_api.family='ipv4'

uci commit firewall
/etc/init.d/firewall restart

手工恢复 ttyd

1
2
3
4
5
6
uci set ttyd.@ttyd[0].command='/bin/login'
uci set ttyd.@ttyd[0].listen='0.0.0.0'
uci commit ttyd
/etc/init.d/ttyd enable
/etc/init.d/ttyd restart
netstat -lntp | grep ':7681 '

进阶操作

手工恢复 sing-box

先手工创建并检查: 参考hexo_posts代理与 TUN 模式配置.md

1
/etc/sing-box/config.json

不要把包含订阅、密码或密钥的配置提交到公开仓库。然后启用服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
uci set sing-box.main.enabled='1'
uci set sing-box.main.user='root'
uci commit sing-box
/etc/init.d/sing-box enable
/etc/init.d/sing-box restart
/etc/init.d/sing-box status

uci set network.singbox_tun=interface
uci set network.singbox_tun.device='tun0'
uci set network.singbox_tun.proto='unmanaged'
uci commit network
uci -q del_list firewall.@zone[0].network='singbox_tun'
uci add_list firewall.@zone[0].network='singbox_tun'
uci commit firewall
/etc/init.d/network reload
/etc/init.d/firewall restart

确认 sing-box 已经监听 127.0.0.1:5353 后,再把 dnsmasq DNS 转发过去:

1
2
3
4
5
6
7
8
9
10
netstat -lnup | grep ':5353'

uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#5353'
uci set dhcp.@dnsmasq[0].noresolv='1'
uci -q del_list dhcp.@dnsmasq[0].rebind_domain='fzcsxl.com'
uci add_list dhcp.@dnsmasq[0].rebind_domain='fzcsxl.com'
uci commit dhcp
/etc/init.d/dnsmasq restart
# sysctl -w net.ipv4.conf.all.rp_filter=0

恢复后检查

检查:

1
2
3
4
5
6
7
8
9
ubus call system board
ip addr show
ip route
ubus call network.interface dump
ubus call network.interface.wan status
dmesg | grep -E 'fsl_dpaa_mac|PHY|Link is'
uci show firewall | grep -E "name='wan'|input|output|forward|masq"
ip rule
ip route show table all

DTB 调试

反编译仅用于检查生成结果:

1
dtc -I dtb -O dts -o /tmp/fsl-nh03-sdk.generated.dts fsl-nh03-sdk.dtb

正式修改始终编辑源码树中的 fsl-nh03-sdk.dts。不要再直接反编译、修改并覆盖唯一的 DTB。

Wi-Fi AP 配置

当前设备的 radio0 是 2.4 GHz 无线网卡,默认 AP 配置已绑定到 lan,但 wireless.default_radio0.disabled='1',因此不会创建无线接口或广播 SSID。

encryption='psk2' 表示仅使用 WPA2-Personal。更推荐使用 sae-mixed(WPA2/WPA3-Personal 混合模式):支持 WPA3 的设备使用 SAE,旧设备仍可使用 WPA2-PSK。

设备已有 radio0、2.4 GHz、信道、AP 模式以及 lan 绑定,无需重复配置。 只需设置 SSID、加密方式、密码并解除禁用。密码建议使用至少 12 位随机字符:

1
2
3
4
5
6
7
uci set wireless.default_radio0.ssid='替换为SSID'
uci set wireless.default_radio0.encryption='sae-mixed'
uci set wireless.default_radio0.key='替换为至少8位的密码'
uci set wireless.default_radio0.disabled='0'

uci commit wireless
wifi reload

检查无线接口、SSID 和客户端关联状态:

1
2
3
ubus call network.wireless status
iwinfo
wifi status

正常情况下,radio0 应显示 up: trueinterfaces 不再为空,并能看到 AP 接口和配置的 SSID。 无线客户端会接入 lan。COM14 由 LAN DHCP 分配 192.168.3.0/24 网段地址;COM12 仍使用 192.168.2.0/24

如果 wifi reload 报 SAE/WPA3 不受支持,说明固件中的 wpad/hostapd 版本未包含 SAE 支持。 可以先回退到仅 WPA2-Personal:

1
2
3
uci set wireless.default_radio0.encryption='psk2'
uci commit wireless
wifi reload

不要使用 encryption='none',否则会建立无密码热点。

主题替换

outline 的登录界面好看,直接改

1
2
3
4
5
6
7
echo "{% include('themes/outline/sysauth', {
media: '/luci-static/outline',
theme: 'outline'
}) %}" > /usr/share/ucode/luci/template/themes/proton2025/sysauth.ut

rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
/etc/init.d/uhttpd restart