【u-boot】u-boot网络系统剖析
本文基于u-boot源码版本:v2017.09
一、网络系统

u-boot网络系统分为四类:
(1)网络驱动: 位于drivers/net/目录下,不同平台有不同实现。
(2)网络核心框架:实现了数据包的接收分发机制;实现了网络状态机(通过net_state维护);控制网络的初始化、发送和超时重试。
(3)网络协议层:实现u-boot支持网络的协议,位于net/ 目录 。
(4)网络命令层:实现u-boot网络命令的文件,位于cmd/ 目录 。
(1-1)网络驱动
位于drivers/net/,不同平台有不同实现,每个驱动都要实现一个struct eth_ops,用于描述以太网MAC控制器的操作:
struct eth_ops {/* 准备硬件以便进行数据包的发送和接收。 */int (*start)(struct udevice *dev);/* 将传入的 “packet” 缓冲区中的字节作为一个网络数据包发送出去。 */int (*send)(struct udevice *dev, void *packet, int length);/** 检查硬件是否接收到数据包。如果接收到,则通过参数 packetp* 返回指向数据包缓冲区的指针;如果没有接收到,则返回错误码或0。* 返回0表示硬件接收FIFO为空。若返回0,网络栈不会处理空包,* 但如果定义了free_pkt(),该函数仍会被调用以释放包内存。*/int (*recv)(struct udevice *dev, int flags, uchar **packetp);/** 当网络栈处理完数据包后,驱动可借此机会管理其包缓冲区内存。* 仅当 recv 没有返回错误时才会调用此函数 —— 可选实现。*/int (*free_pkt)(struct udevice *dev, uchar *packet, int length);/* 停止硬件的包检测操作,即使当前状态为PASSIVE时也可能被调用。 */void (*stop)(struct udevice *dev);
#ifdef CONFIG_MCAST_TFTP/* 加入或离开一个多播组(用于 TFTP 等)—— 可选实现 */int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
#endif/** 将MAC地址写入硬件(在部分平台如ARM上用于传递给linux)。* 此函数期望eth_pdata::enetaddr字段已被填充。* 若返回-ENOSYS,表示该硬件不支持此功能 —— 可选实现。*/int (*write_hwaddr)(struct udevice *dev);/** 某些设备在板载 ROM 中保存有备用 MAC 地址。* 驱动应通过此函数将该地址提供给网络栈。* 函数应填写eth_pdata::enetaddr字段——可选实现。*/int (*read_rom_hwaddr)(struct udevice *dev);
};
常见驱动有:stmmac.c(Synopsys DesignWare GMAC)、fec_mxc.c(i.MX FEC)、bcm_eth.c(Broadcom)、rtl8169.c(Realtek)
例如xilinx_axi_emac.c文件中的驱动描述,首先创建静态struct eth_ops实例,并指定对应的回调:

使用U_BOOT_DRIVER()创建静态驱动实例,并关联对应的.ops操作:

(1-2)网络核心框架
net/net.c这个文件是U-Boot网络栈的核心:
- 实现了数据包的接收分发机制;
- 实现了网络状态机(通过
net_state维护); - 控制网络的初始化、发送和超时重试。
主要函数如下:
int net_init(void);
int net_loop(enum proto_t protocol); //启动网络通信
void net_receive(uchar *pkt, int len); //收包分发
void net_send_packet(uchar *pkt, int len);
net_loop()是网络通信的核心循环,会根据当前协议(如TFTP、DHCP)调度不同处理函数。
(1-3)网络协议层
网络协议层位于net/目录下,常见模块如下:
| 协议 | 源文件 | 功能 |
|---|---|---|
| ARP | arp.c | 实现MAC地址与IP地址的映射 |
| BOOTP/DHCP | bootp.c, dhcp.c | 动态获取IP地址及网络参数 |
| ICMP | ping.c | 实现ping命令 |
| TFTP | tftp.c | 通过TFTP下载镜像文件 |
| NFS | nfs.c | 通过NFS挂载加载文件 |
| DNS | dns.c | 支持主机名解析 |
(1-4)网络命令层
网路命令层位于cmd/目录,例如:
| 命令 | 源文件 | 功能 |
|---|---|---|
ping | cmd/ping.c | 测试网络连通性 |
dhcp | cmd/dhcp.c | 通过DHCP获取IP |
tftpboot | cmd/net.c | 通过TFTP下载镜像 |
nfs | cmd/nfs.c | 从NFS下载镜像 |
二、初始化
(2-1)网络系统初始化
在u-boot启动路径中,使用initr_net()初始化网络,实现如下(/common/board_r.c):
static int initr_net(void)
{puts("Net: ");eth_initialize();
#if defined(CONFIG_RESET_PHY_R)debug("Reset Ethernet PHY\n");reset