适用场景:Ubuntu 虚拟机运行 TFTP 服务,开发板通过网线连接电脑,U-Boot 从虚拟机下载镜像到 RAM。下载成功只证明这次传输完成;是否可以启动、应写哪个存储位置,需要另行核对镜像格式和板级布局。
1. 让开发板能够到达虚拟机
跳转到“1. 让开发板能够到达虚拟机”直连开发板时,桥接到连接开发板的那张物理网卡通常最直观。虚拟机表现为同一二层网络中的独立设备,具有独立 IP。多网卡主机应明确指定有线接口,避免自动桥接到 Wi-Fi。
| 网络方式 | 默认连通范围 | 用于此场景时的要点 |
|---|---|---|
| 桥接 | 虚拟机与物理网卡所在网络中的设备 | 无需 NAT 转发;交换机安全策略、无线桥接限制和虚拟化过滤驱动仍可能影响通信 |
| NAT | 虚拟机通常可主动访问外部,外部不能默认主动访问虚拟机服务 | 可用路由或端口转发实现入站,但 TFTP 还使用协商后的 UDP 端口,单转发 69 常不够 |
| Host-only | 主机与同一 host-only 网络中的虚拟机彼此通信 | 不会自动连到物理开发板;需额外路由/转发或另一网卡 |
因此桥接是这里的简便方案,不是实现通信的唯一方式。虚拟机也可使用两张网卡:一张 NAT 上网,一张桥接到开发板;开发板接口不要添加不需要的默认路由。
以隔离实验网段为例:
Ubuntu 虚拟机:192.168.1.100/24开发板: 192.168.1.101/24电脑有线口: 如需配置,另选不冲突的地址如果电脑现有 Wi-Fi、VPN 或其他网卡已经使用 192.168.1.0/24,换用不冲突的网段,并同步修改下面各处。直连同网段通信不需要路由器、网关或 DNS。
2. 配置 Ubuntu 的开发板接口
跳转到“2. 配置 Ubuntu 的开发板接口”先用 ip -br link、ip -br addr、ip route 确认接口名、地址和路由。已有 NetworkManager 配置的桌面系统,应继续用该管理器配置连接;不要同时让多个配置文件或管理器管理同一接口。
下面是由 Netplan / systemd-networkd 管理接口时的示例,enp0s8 必须替换为实际名称;应修改已有配置,避免新旧定义冲突。
network: version: 2 renderer: networkd ethernets: enp0s8: dhcp4: false addresses: - 192.168.1.100/24在本地控制台应用前,先检查语法,再试运行:
sudo netplan generatesudo netplan tryip -br addrip route get 192.168.1.101netplan try 默认在未确认时尝试回滚,但官方文档提示回滚存在已知限制。超时或取消后仍要检查实际地址以及磁盘上的配置,尤其不能把它当作远程修改网络的绝对保险。
3. 建立仅供下载的 TFTP 目录
跳转到“3. 建立仅供下载的 TFTP 目录”Ubuntu/Debian 的 tftpd-hpa 可用于该实验:
sudo apt updatesudo apt install tftpd-hpasudo install -d -o root -g root -m 0755 /srv/tftp# u-boot.bin 为当前目录内已经确认来源、格式的文件。sudo install -o root -g root -m 0644 u-boot.bin /srv/tftp/u-boot.binsha256sum /srv/tftp/u-boot.binstat -c '%s bytes' /srv/tftp/u-boot.bin编辑 /etc/default/tftpd-hpa,示例绑定开发板网络的地址:
TFTP_USERNAME="tftp"TFTP_DIRECTORY="/srv/tftp"TFTP_ADDRESS="192.168.1.100:69"TFTP_OPTIONS="--secure --port-range 30000:30010"--secure 把服务限制在共享目录内;没有 --create 时不会创建新上传文件。目录由 root 持有且只有 0755、文件为 0644,使服务用户无法写入已有文件。tftpd-hpa 默认要求供下载文件具有其他用户可读权限,因此这里采用 0644。无需 chmod 777,也无需把目录交给 nobody。不要在共享目录放凭据或其他私人文件。
sudo systemctl restart tftpd-hpasudo systemctl status tftpd-hpa --no-pagersudo ss -lunpsudo journalctl -u tftpd-hpa -n 50 --no-pagerTFTP 的初始请求发往 UDP 69;后续数据由服务端另外选择的传输端口发送。上例把该范围限定为 UDP 30000–30010,便于按来源地址、接口和方向制定规则。在实际防火墙中允许开发板与服务地址间这些必要的流量,或者配置能够正确跟踪 TFTP 的机制;不要为排查关闭整台电脑的防火墙。范围大小需满足并发数要求,主机和虚拟机两侧过滤也都要检查。
4. 在 U-Boot 中测试
跳转到“4. 在 U-Boot 中测试”先执行 version、help tftpboot、bdinfo 并核对板级 RAM 布局。以下操作假定 ${loadaddr} 已设为容量足够、与 U-Boot/栈/设备树等不重叠的有效 RAM 区域。不能从别的开发板照抄地址。
printenv loadaddr ipaddr serverip netmask ethact autostartsetenv ipaddr 192.168.1.101setenv serverip 192.168.1.100setenv netmask 255.255.255.0setenv autostart noping ${serverip}if tftpboot ${loadaddr} u-boot.bin; then setenv download_size ${filesize} echo Downloaded bytes hex: ${download_size}else echo TFTP download failedfiautostart=no 防止某些配置在加载后自动启动镜像;先保留在 RAM 环境即可,不必立即 saveenv。若板上有多个网口,按 ethact、PHY 链路和实际接线选择接口。ping 成功可以确认部分 IP 连通性,但 ICMP 失败不一定意味着 TFTP 必然不可用;还要看对端是否过滤 ICMP。
只有下载成功才记录 ${filesize}。U-Boot 中它通常是十六进制长度,必须与主机的十进制文件大小按相同进制比较。后续加载其他文件会改变 ${filesize},所以应立刻另存。本例没有设置 autoload,因为没有使用会触发自动加载的 DHCP/BOOTP 流程。
有 hash 命令时,在成功分支后按目标帮助执行 hash sha256 ${loadaddr} ${download_size},与主机摘要比较。摘要相同可以帮助发现传输或内存损坏;没有可信摘要来源时不能证明镜像受信任。TFTP 本身没有身份认证和加密,适合受控开发网络。
5. 按现象排查
跳转到“5. 按现象排查”| 现象 | 优先检查 |
|---|---|
| 没有链路或 ARP 一直超时 | 网线、PHY、正确的物理桥接接口、虚拟网卡是否连接、IP/掩码、重复 IP |
| 虚拟机本机可访问,开发板不行 | NAT/host-only 选错,宿主过滤驱动、入站规则、路由网段冲突 |
| 请求有响应,传输开始后超时 | 服务端传输端口、双向防火墙、NAT 跟踪;抓包确认 DATA/ACK 的端口 |
File not found | 文件实际位于 /srv/tftp 内;请求用 u-boot.bin,不加主机的绝对目录;注意大小写 |
Access violation | 文件/目录权限、服务用户和安全策略,不用开放全部写权限解决 |
| 大文件传输异常 | RAM 容量、传输端口、MTU/分片、协商块长、超时与重试;先用小文件定位 |
RFC 1350 的基本块长为 512 字节,最后一个数据块必须短于块长;文件长度恰好为块长整数倍时还需要一个零长度尾块。支持扩展的客户端/服务器可以协商更大块长,不能仅凭抓包中不是 512 字节就判定错误。
6. 下载后再决定启动或更新
跳转到“6. 下载后再决定启动或更新”不要从“TFTP 成功”直接跳到 nand erase 或猜测 nand write.jffs2 参数。目标可能使用 SD、eMMC、SPI NOR、NAND 或 ROM 特定容器;原始 u-boot.bin 也可能缺少 SPL、启动头或平台固件。
先确认文件格式、目标介质、预留区域、长度单位和恢复入口,再按 U-Boot 加载、校验与存储更新 操作。这里验证到 RAM 下载为止,真实写入后还需要读回、启动以及失败恢复验证。