代码
代码位置:uboot/net/eth-uclass.c
/* Check if the device has a valid MAC address in device tree */
if (!eth_dev_get_mac_address(dev, pdata->enetaddr) ||
!is_valid_ethaddr(pdata->enetaddr)) {
source = "ROM";
/* Check if the device has a MAC address in ROM */
if (eth_get_ops(dev)->read_rom_hwaddr)
eth_get_ops(dev)->read_rom_hwaddr(dev);
}
eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
if (!is_zero_ethaddr(env_enetaddr)) {
if (!is_zero_ethaddr(pdata->enetaddr) &&
memcmp(pdata->enetaddr, env_enetaddr, ARP_HLEN)) {
printf("\nWarning: %s MAC addresses don't match:\n",
dev->name);
printf("Address in %s is\t\t%pM\n",
source, pdata->enetaddr);
printf("Address in environment is\t%pM\n",
env_enetaddr);
}
/* Override the ROM MAC address */
memcpy(pdata->enetaddr, env_enetaddr, ARP_HLEN);
} else if (is_valid_ethaddr(pdata->enetaddr)) {
eth_env_set_enetaddr_by_index("eth", dev_seq(dev),
pdata->enetaddr);
} else if (is_zero_ethaddr(pdata->enetaddr) ||
!is_valid_ethaddr(pdata->enetaddr)) {
#ifdef CONFIG_NET_RANDOM_ETHADDR
net_random_ethaddr(pdata->enetaddr);
printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
dev->name, dev_seq(dev), pdata->enetaddr);
eth_env_set_enetaddr_by_index("eth", dev_seq(dev),
pdata->enetaddr);
#else
printf("\nError: %s address not set.\n",
dev->name);
return -EINVAL;
#endif
}
解析
首先尝试从设备树中读取mac地址:
eth_dev_get_mac_address(dev, pdata->enetaddr),读取设备树命名为中"mac-address"或"local-mac-address"的数组,
如果读取失败了,或者读取成功但是经检测mac地址无效(是组播地址,或者全是0),那么就进行第二步,尝试从fec网卡驱动获取mac地址。
读取成功则进行第三步。
第二步从fec网卡驱动读取mac地址:
eth_get_ops(dev)->read_rom_hwaddr(dev),之后进行第三步。
第三步从环境变量中读取mac地址:
eth_env_get_enetaddr_by_index(“eth”, dev_seq(dev), env_enetaddr),如果从环境变量中读取到的mac地址不是0,那么这个就是最终的mac地址了,不需要进行第四步。如果从驱动读取的mac地址不为0,比较从环境变量中读取到的mac地址和从其他两个来源读取的mac地址,如果不同,打印一串警告,但是最终还是采用从环境变量中的mac地址。
如果从环境变量中读取到的mac地址为0,检查从其他两个来源读取的mac地址是否有效(非0且非组播),如果有效,采用从其他两个来源中读取的mac地址,并设置到环境变量中;如果无效,进行第四步。
第四步随机生成mac地址
随机生成mac地址需要打开编译配置项CONFIG_NET_RANDOM_ETHADDR,如果没有打开,则不会随机生成mac地址。
net_random_ethaddr(pdata->enetaddr)
使用随机数生成一个mac地址。
结论
1.mac地址的优先级:环境变量中的mac地址 > 设备树中的mac地址 > fec网卡驱动中的mac地址 > 随机生成的mac地址
环境变量中的mac地址优先级最高,优先采用这个mac地址;如果没有,采用设备树中的mac地址;如果还没由或者无效,采用fec驱动中的mac地址;如果还是没有或者无效,随机生成一个mac地址(如果没配CONFIG_NET_RANDOM_ETHADDR,那么就没有mac地址了)。
2.组播地址(第8bit为1)只有设置在环境变量才生效,设置在驱动和设备树都不生效
注:
全为0视为没有。