WSL2 + TFTP + 网络启动:那些年我们一起踩过的防火墙坑¶
为什么要写这一章¶
如果你在做嵌入式开发,网络启动几乎是绕不开的技能。烧录 SD 卡太慢?网络启动。调试内核频繁更新?网络启动。没有 SD 卡槽?还是网络启动。
但网络启动的环境搭建,尤其是用 WSL2 做开发环境,真不是一件轻松的事。我当初踩过的坑,说出来都是泪:WSL2 和开发板网络不通、TFTP 一直超时、Windows 防火墙默默丢包、目录权限不够导致 Abort……
这些坑看似简单,但每个都可能让你折腾半天。而且网上教程大多只给命令,不解释背后的原理,你照着敲能成功,但下次出问题了还是不知道怎么排查。
所以这一章,我们完整地走一遍 WSL2 + TFTP + 网络启动的搭建过程。每一步都有原理解释,每个坑都有排查方法。读完之后,你不仅能成功搭建环境,更重要的是——下次出问题时,你知道怎么排查。
网络拓扑分析:第一步搞清楚物理连接¶
在开始配置之前,我们先搞清楚网络是怎么连的。这听起来简单,但很多人第一步就搞错。
Windows 网卡情况¶
打开 Windows 的 PowerShell,运行 ipconfig:
输出类似:
以太网适配器 网桥:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::xxxx:xxxx:xxxx:xxxx%17
IPv4 地址 . . . . . . . . . . . . : 192.168.60.1
子网掩码 . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . :
以太网适配器 以太网 2:
媒体状态 . . . . . . . . . . . . : 媒体已断开
这里有两条关键信息:
- 网桥:IP 是
192.168.60.1,这是开发板实际连接的网卡 - 以太网 2:媒体状态是"已断开",说明没插网线
踩坑提醒:很多人以为开发板接在"以太网 2"上,但实际上"以太网 2"可能是开发板的 USB 网口(用于 ADB 或其他用途),真正的以太网连接是通过"网桥"。搞错这一点,后面怎么 ping 都不通。
开发板网络配置¶
在 U-Boot 命令行中,先 ping 一下网关:
如果看到 is alive,说明物理链路是通的。如果超时,检查:
- 网线是否插好
- 开发板和 Windows 是否在同一网段
- Windows 防火墙是否允许 ping(ICMP)
WSL2 网络模式:NAT vs Mirrored¶
WSL2 有两种网络模式:NAT(默认)和 Mirrored。理解它们的区别是关键。
NAT 模式的问题¶
WSL2 默认是 NAT 模式,它的网络结构是这样的:
在 NAT 模式下,WSL2 处于一个独立的虚拟网段(通常是 172.x.x.x),和开发板的 192.168.60.0/24 网段完全隔离。这就导致:
- 开发板无法直接访问 WSL2
- WSL2 的 TFTP 服务对开发板不可见
- 每次重启 WSL2,IP 可能会变化
Mirrored 模式的优势¶
Mirrored 模式让 WSL2 直接镜像 Windows 的所有网卡:
在 Mirrored 模式下,WSL2 可以直接访问 Windows 的每一块网卡,包括 192.168.60.1 这个网桥。
切换到 Mirrored 模式¶
在 Windows 用户目录下创建或编辑 .wslconfig 文件:
文件位置:C:\Users\<你的用户名>\.wslconfig
内容:
保存后,重启 WSL:
验证网络模式¶
重启 WSL 后,在 WSL 中运行:
你应该能看到类似这样的网卡:
11: eth9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.60.1/24 brd 192.168.60.255 scope global noprefixroute eth9
valid_lft forever preferred_lft forever
关键点是 inet 192.168.60.1/24,这说明 WSL2 现在能看到开发板所在的网段了。
经验:
.wslconfig是全局配置,会影响到机器上所有 WSL2 发行版。但对于普通开发使用,这通常没有副作用,上网也不受影响。
TFTP 服务搭建¶
现在网络通了,我们来搭建 TFTP 服务。
安装 tftpd-hpa¶
配置 TFTP¶
编辑配置文件:
修改为:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/charliechen/tftp"
TFTP_ADDRESS="192.168.60.1:69"
TFTP_OPTIONS="--secure"
配置说明:
TFTP_USERNAME:运行 TFTP 服务的用户TFTP_DIRECTORY:TFTP 根目录,存放可传输的文件TFTP_ADDRESS:监听地址,必须绑定到 192.168.60.1(开发板能访问的地址)TFTP_OPTIONS:--secure:安全模式,限制访问范围在 TFTP_DIRECTORY 内- 可选:
--create:允许上传文件(如果需要)
准备 TFTP 目录¶
踩坑提醒:只改目录权限不够!tftp 用户还需要能进入你的 home 目录:
否则 TFTP 会报 "Permission denied" 错误。
创建测试文件¶
踩坑提醒:文件本身也要有读权限!很多人改了目录权限忘记改文件权限,导致 TFTP 传输 Abort。
启动 TFTP 服务¶
验证 TFTP 服务¶
首先确认服务在监听正确的端口:
输出应该包含:
关键是 192.168.60.1:69,说明服务绑定到了正确的网卡。
然后在 WSL 内部测试一下:
# 安装 tftp 客户端(如果没安装)
sudo apt install tftp-hpa
# 测试
echo "get test.txt" | tftp 192.168.60.1
cat test.txt
如果能看到 "Hello from TFTP!",说明 TFTP 服务本身没问题。
Windows 防火墙配置(最隐蔽的坑!)¶
好,TFTP 服务在 WSL 里测试通过了。现在在开发板 U-Boot 里测试:
=> tftp 0x80800000 test.txt
Using ethernet@20b4000 device
TFTP from server 192.168.60.1; our IP address is 192.168.60.200
Filename 'test.txt'.
Load address: 0x80800000
Loading: T T T T T T T T T T
Retry count exceeded; starting again
看到了吗?T T T T 表示超时重试。但我们的服务明明在运行,为什么就是传不了?
答案:Windows 防火墙默默地丢掉了 UDP 69 端口的入站包。
这就是最隐蔽的坑——服务配置正确、端口监听正常、权限也没问题,但就是传不了。因为 WSL2 的网络实际上是走 Windows 的网络栈,Windows 防火墙会拦截入站流量。
添加防火墙规则¶
以管理员身份打开 PowerShell,运行:
New-NetFirewallRule -DisplayName "WSL TFTP" `
-Direction Inbound `
-Protocol UDP `
-LocalPort 69 `
-Action Allow
参数说明:
-DisplayName:规则名称,方便识别-Direction Inbound:入站规则(允许外部访问内部)-Protocol UDP:TFTP 使用 UDP 协议-LocalPort 69:TFTP 端口-Action Allow:允许通过
验证防火墙规则¶
或者查看防火墙日志(如果启用了日志):
再次测试¶
现在回到 U-Boot,再试一次:
=> tftp 0x80800000 test.txt
Using ethernet@20b4000 device
TFTP from server 192.168.60.1; our IP address is 192.168.60.200
Filename 'test.txt'.
Load address: 0x80800000
Loading: #
1.5 KiB/s
Bytes transferred = 6 (6 hex)
成功了!# 表示传输进行中,最后显示传输的字节数。
U-Boot 网络配置¶
现在 TFTP 通了,我们来完整配置 U-Boot 的网络参数。
配置网络参数¶
在 U-Boot 命令行中:
setenv ipaddr 192.168.60.200
setenv netmask 255.255.255.0
setenv gatewayip 192.168.60.1
setenv serverip 192.168.60.1
saveenv
参数说明:
ipaddr:开发板的 IP 地址netmask:子网掩码gatewayip:网关地址(通常和 serverip 相同)serverip:TFTP 服务器地址(即 WSL/Windows 的 IP)
踩坑提醒:
serverip是很多人踩的坑。我之前有一次serverip被设成了192.168.60.129(不知道哪里来的旧配置),导致 TFTP 一直连到错误的 IP。每次修改后务必确认:
如果值不对,重新
setenv然后saveenv。
验证网络连接¶
如果 ping 不通,检查: 1. 网线是否连接 2. IP 地址是否在同一网段 3. Windows 防火墙是否允许 ICMP(ping)
TFTP 下载内核实战¶
测试文件成功后,我们来下载真正的内核和设备树。
准备文件¶
把编译好的内核和设备树复制到 TFTP 目录:
# 假设你的编译输出在 ~/linux-imx-build
cp ~/linux-imx-build/arch/arm/boot/zImage ~/tftp/
cp ~/linux-imx-build/arch/arm/boot/dts/imx6ull-14x14-evk.dtb ~/tftp/
确保文件权限正确:
下载并启动¶
在 U-Boot 中:
# 下载内核
tftp 0x80800000 zImage
# 下载设备树
tftp 0x83000000 imx6ull-14x14-evk.dtb
# 启动
bootz 0x80800000 - 0x83000000
地址说明:
0x80800000:内核加载地址(i.MX6ULL DDR 起始地址 + 偏移)0x83000000:设备树加载地址(需要在内核加载地址之后,且不冲突)-:表示没有 initramfs
启动自动化¶
每次手动敲命令太累,可以把它写成启动脚本:
setenv bootcmd 'tftp 0x80800000 zImage; tftp 0x83000000 imx6ull-14x14-evk.dtb; bootz 0x80800000 - 0x83000000'
setenv bootdelay 3
saveenv
这样 U-Boot 启动时会自动执行 bootcmd,3 秒内按任意键可以中断。
踩坑排查汇总表¶
我们总结一下这一章遇到的所有坑和解决方法:
| 坑 | 现象 | 根本原因 | 解决方法 |
|---|---|---|---|
| WSL2 NAT 隔离 | WSL 和开发板 ping 不通 | WSL2 在独立网段 | 切换 mirrored 模式 |
| Windows 防火墙 | TFTP 全程 T T T 超时 |
UDP 69 入站被拦截 | 添加防火墙规则 |
| home 目录权限 | TFTP * Abort |
tftp 用户无法进入 home | chmod o+x /home/用户名 |
| 文件权限不足 | TFTP * Abort |
文件不可读 | chmod 777 ~/tftp/* |
| serverip 旧值 | 连接错误的 IP | 环境变量残留 | setenv serverip 重新配置 |
| 绑定地址错误 | WSL 内测试通,外部不通 | TFTP 绑定到 127.0.0.1 | TFTP_ADDRESS="192.168.60.1:69" |
| 网线插错口 | 物理层不通 | 混淆网桥和以太网 2 | 检查 ipconfig,确认网桥 |
| WSL 重启失效 | 配置丢失 | .wslconfig 没生效 | wsl --shutdown 完全重启 |
TFTP 传输失败的各种表现¶
TFTP 传输失败有几种典型表现,每种对应不同的问题:
现象一:全程 T T T¶
原因:服务器完全没收到请求,或者响应被丢包。
排查: 1. Windows 防火墙(最常见) 2. TFTP 服务是否启动 3. IP 地址是否正确 4. 网络物理连接
现象二:* 后 Abort¶
原因:服务器收到请求并响应,但传输中断。
排查: 1. 文件权限(最常见) 2. 目录权限 3. 磁盘空间
现象三:传输很慢或频繁重传¶
原因:网络质量问题。
排查:
1. 换一根网线
2. 检查网络拥塞
3. 减小 MTU(U-Boot 中 setenv mtu 600)
进阶:NFS 根文件系统¶
网络启动的下一步通常是 NFS 根文件系统,这样开发板可以直接从网络挂载根文件系统,开发时修改文件不需要重新烧录。
NFS 服务端搭建¶
在 WSL 中:
编辑 /etc/exports:
创建根文件系统目录:
启动服务:
U-Boot NFS 配置¶
setenv nfsroot 192.168.60.1:/home/charliechen/nfsroot
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs rw nfsroot=${nfsroot},v3,tcp ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}::eth0:off'
saveenv
内核配置¶
确保内核支持 NFS:
写在最后¶
这一章我们完整地走了一遍 WSL2 + TFTP + 网络启动的搭建过程。从网络拓扑分析、WSL2 镜像模式配置、TFTP 服务搭建,到最隐蔽的 Windows 防火墙坑,每个环节都有详细的解释和排查方法。
网络启动是嵌入式开发中非常实用的技能。它让你能够快速迭代内核和设备树,不需要每次都烧录 SD 卡。当你习惯了 tftp → bootz 的工作流,再回到烧录 SD 卡简直是折磨。
下一章,我们将进入驱动开发的实战环节。你会看到如何从零开始编写一个字符设备驱动,如何实现 open、read、write、ioctl 等操作,如何通过设备树传递硬件信息。那是从"会用内核"到"会写驱动"的关键一步。
准备好了吗?让我们继续。