1028在uboot中自动获取mac的方式

一、查看uboot中随机获取mac的位置

源码位置:ls1028/OK1028-linux-fs/packages/firmware/u-boot/net/eth-uclass.c

#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, pdata->enetaddr);
		char tmp[50] = {'\n'};
                if (dev->seq == 0){
                       sprintf(tmp, "setenv ethaddr %pM\n", pdata->enetaddr);
                }
                else{
                       sprintf(tmp, "setenv eth%daddr %pM\n", dev->seq, pdata->enetaddr);
                }
                run_command(tmp, 0);
                run_command("saveenv", 0);
#else
		printf("\nError: %s address not set.\n",
		       dev->name);
		return -EINVAL;
#endif

1.首先从第一个函数**net_random_ethaddr(pdata->enetaddr)**上看

文件路径:ls1028/OK1028-linux-fs/packages/firmware/u-boot/include/net.h

/**
 * net_random_ethaddr - Generate software assigned random Ethernet address
 * @addr: Pointer to a six-byte array containing the Ethernet address
 *
 * Generate a random Ethernet address (MAC) that is not multicast
 * and has the local assigned bit set.
 */
static inline void net_random_ethaddr(uchar *addr)
{
	int i;
	unsigned int seed = get_ticks();

	for (i = 0; i < 6; i++)
		addr[i] = rand_r(&seed);

	addr[0] &= 0xfe;	/* clear multicast bit */
	addr[0] |= 0x02;	/* set local assignment bit (IEEE802) */
}

get_ticks() 的功能,这个函数是获取以毫秒级为单位的时间。

rand_r() 的功能为传入一个指针类型的参数,会产生一个随机序列,需要注意的是,在传入参数不变的情况下,产生的随机序列也是不会发生改变的。

注:

1.组播的MAC地址是最高字节的低位为一,例 如 01-00-00-00-00-00 。所以要使用 addr[0] &= 0xfe 把组播位清除掉。

在实际使用中,组播数据是使用通过数据链路层进行MAC地址绑定然后进行转发,所以一个以太网卡在绑定了一个组播的IP地址以后,必须还要绑定一个组播的MAC地址,才能像单播那样工作。

还有就是在网上说的多播和组播是一个东西,只不过名字是不同的。

2.MAC地址最高字节(MSB)的低第二位(LSb)表示这个MAC地址表示全球唯一MAC地址,或者本地MAC地址,即U/L (Universal/Local)位,如果为0,表示是全局地址。这里设置的为1表示本地

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cy5aajRG-1665489352279)(https://bkimg.cdn.bcebos.com/pic/7af40ad162d9f2d36c26cc35a7ec8a136327cc31?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2U4MA==,g_7,xp_5,yp_5/format,f_auto)]

2.打印提示信息

printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
		       dev->name, dev->seq, pdata->enetaddr);

打印设备名字、设备号、和获取的使用net_random_ethaddr()函数获取的MAC地址。

: 一个疑问点,为什么在命令的最后有一个M,在实际的打印信息中是没有这个M

3.保存环境变量

在保存环境变量时,要先了解两个函数:sprintf()run_command

(1)sprintf()用法:

sprintf()用法和printf()类似,但是也有不同,在printf中输出的目标是显示器,而sprintf的输出目标是指针所指的缓存区域。

(2)run_command的解释:

这个命令大概就是说要把传递进来的 tmp 变量拆分一下,分别把前半段的命令拆分出来存储在 argv[0] 位,把后面设置的环境变量的参数也是拆分出来存储在 argv[1] 中,之后由 find_cmd() 函数去查找是否存在 argv[0] 存储的命令。查找到了就去执行相对应的命令。

其中的运行过程相当于在uboot命令行中执行命令的效果是一样的。

4.加入打印信息验证

U-Boot 2019.10 (Sep 30 2022 - 16:14:20 +0800)

SoC:  LS1028A Rev1.0 (0x870b0110)
Clock Configuration:
       CPU0(A72):1500 MHz  CPU1(A72):1500 MHz  
       Bus:      400  MHz  DDR:      1600 MT/s
Reset Configuration Word (RCW):
       00000000: 3c004010 00000030 00000000 00000000
       00000010: 00000000 018f0000 0030c000 00000000
       00000020: 01e031a0 00002580 00000000 00008296
       00000030: 00000000 00000050 00000000 00000000
       00000040: 00000000 00000000 00000000 00000000
       00000050: 00000000 00000000 00000000 00000000
       00000060: 00000000 00000000 100e7014 00000000
       00000070: eb580000 03000000
Model: Forlinx OK1028A-C Board
Board: LS1028A Rev1.0-RDB, Version: A, boot from XSPI NOR
SERDES1 Reference : Clock1 = 100.00MHz Clock2 = 100.00MHz
DRAM:  1.9 GiB
DDR    1.9 GiB (DDR4, 32-bit, CL=11, ECC off)
Using SERDES1 Protocol: 60248 (0xeb58)
PCIe0: pcie@3400000 disabled
PCIe1: pcie@3500000 Root Complex: no link
WDT:   Started with servicing (60s timeout)
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from SPI Flash... SF: Detected w25q128 with page size 256 Bytes, erase size 64 KiB, total 16 MiB
OK
In:    serial
Out:   serial
Err:   serial
Net:   eth0: enetc-0
Warning: enetc-2 (eth2) using random MAC address - b2:d1:c6:67:38:17
/******************************************************/
Saving Environment to SPI Flash... SF: Detected w25q128 with page size 256 Bytes, erase size 64 KiB, total 16 MiB
Erasing SPI flash...Writing to SPI flash...done
OK
, eth2: enetc-2, eth4: swp0, eth5: swp1, eth6: swp2, eth7: swp3
Hit any key to stop autoboot:  0 
=>

设置环境变量 setenv eth4addr

编辑环境变量 editenv eth5addr

保存环境变量 saveenv