imx6ull使用Unique ID配置网卡MAC地址

前言:

貌似不管用什么ARM处理器都会遇到一个问题,那就是MAC地址唯一性,如果是使用随机的,每次reboot之后MAC地址都会变化,如果是在代码里面固定死了,如果局域网里面有两个设备的话,路由又会有问题。其实最大的问题就是量产的不方便。

以前用stm32的时候,可以使用stm32的唯一ID来配置给MAC地址使用,后来使用的zynq并没有,然后就使用的是板子上的flash的以为ID。最近在研究imx6ull,也是同样的问题,查了一下datasheet之后发现这款CPU也有唯一ID。下面是datasheet里面的介绍:

 

 

 

接下来就切入正题了:

本篇blog不做过程分析,因为之前zynq已经分析过一次了,我已经知道需要在什么地方做修改了。所以接下来只把需要做修改的地方给大家分享一下,有需要看分析过程的朋友可以参考我之前写的blog:ZYNQ通过读取SPI Flash的唯一ID来做MAC地址使用

首先依照惯例还是先介绍一下平台,这里使用的开发板是韦东山老师的100ask_imx6ull开发板,是真的便宜。然后u-boot和kernel都是百问网提供的。

然后说一下需要修改什么,主要是修改u-boot和设备树,跟kernel关系不大。

接下来先修改u-boot:

根据datasheet 《i.MX 6ULL Applications Processor Reference Manual》 2404页的寄存器介绍,可以知道只需要把这两个寄存器里面的ID读出来就行了。

然后这里会有两个ID,因为一共是64位,所以肯定采购一批IC的话,高32位因为是不会变的,所以我们需要知道哪个寄存器里面存的是低32位。因为我手里只有一张开发板,所以我麻烦了一下交流群里面的朋友把它的ID截图给我看了一下。

第一张的群里朋友的截图,第二章是我这边读出来的,所以可以确定我们应该使用OCOTP_CFG1寄存器里面保存的ID。

打开u-boot源码里面 ./cmd/fdt.c 找到函数 void set_working_fdt_addr(ulong addr) 将函数内容替换成

void set_working_fdt_addr(ulong addr)
{
	void *buf;
	/* patch by hlb start */
	#define B2L(x)	(((x & 0xff000000) >> 24) | ((x & 0xff0000) >> 8) | ((x & 0xff00) << 8) | ((x & 0xff) << 24))

	unsigned int off_dt_struct; 	 /* offset to structure */
	unsigned int off_dt_strings;		 /* offset to strings */
	unsigned int off_mem_rsvmap;		 /* offset to memory reserve map */

	unsigned int temp;
	unsigned int len;
	unsigned int name_off;
	unsigned char* str;
	unsigned char* node_name;
	int root_node = 0;
	int mac_cnt = 0;
	unsigned int ID0 = *((volatile const unsigned int*)0x21BC410);
	unsigned int ID1 = *((volatile const unsigned int*)0x21BC420);
	printf("\nID0 = 0x%08x\n", ID0);
	printf("ID1 = 0x%08x\n", ID1);
	/* patch by hlb end */
	buf = map_sysmem(addr, 0);
	working_fdt = buf;
	/* patch by hlb start*/
#if 0
	printf("addr = 0x%08x\n", addr);
	printf("buf = 0x%08x\n", buf);
#endif
	
	off_dt_struct = B2L(working_fdt->off_dt_struct);
	off_dt_strings = B2L(working_fdt->off_dt_strings);
	off_mem_rsvmap = B2L(working_fdt->off_mem_rsvmap);

#if 0
	printf("off_dt_struct = %d\n", off_dt_struct);
	printf("off_dt_strings = %d\n", off_dt_strings);
	printf("off_mem_rsvmap = %d\n", off_mem_rsvmap);
#endif
	off_dt_struct += (unsigned int)working_fdt;
	off_dt_strings += (unsigned int)working_fdt;
	off_mem_rsvmap += (unsigned int)working_fdt;

	do
	{
		temp = *((unsigned int*)off_dt_struct);
		off_dt_struct += 4;
		temp = B2L(temp);
		switch (temp)
		{
		case 1:
			if (root_node == 0)	//处理根节点
			{
				root_node = 1;
				off_dt_struct += 4;	//根节点没有名字,跳过
			}
			else
			{
				/* node name */
				node_name = (unsigned char*)off_dt_struct;
				//printf("node name: %s\n", str);

				int str_len;
				str_len = strlen((const char*)node_name) + 1;
				off_dt_struct += str_len;
				if (str_len % 4)
				{
					off_dt_struct += 4 - (str_len % 4);	//4字节对齐
				}
			}
			break;

		case 2:
			break;

		case 3:
			/* value len */
			temp = *((unsigned int*)off_dt_struct);
			len = B2L(temp);

			off_dt_struct += 4;

			/* nameoff */
			temp = *((unsigned int*)off_dt_struct);
			name_off = B2L(temp);
			str = (unsigned char*)(off_dt_strings + name_off);

			off_dt_struct += 4;
			
			if (strstr((char*)str, (const char*)"local-mac-address"))
			{
				unsigned char* pmac;
				pmac = (unsigned char*)off_dt_struct;
				
#if 1		
				printf("Finding eth%d node name is: %s\n", mac_cnt, node_name);
				printf("Old local-mac-address value len = %d\n", len);
				for (int i = 0; i < 6; i++)
				{
					printf("0x%02x ", pmac[i]);
				}
				printf("\n");
#endif			
				pmac[0] = 0x00;
				pmac[1] = 0x0a;
				pmac[2] = 0x35 + mac_cnt++;
				pmac[3] = (unsigned char)(ID1 >> 16);
				pmac[4] = (unsigned char)(ID1 >> 8);
				pmac[5] = (unsigned char)(ID1 >> 0);
				
#if 1				
				printf("Use ID1 value!\n");
				printf("local-mac-address value len = %d\n", len);
				for (int i = 0; i < 6; i++)
				{
					printf("0x%02x ", pmac[i]);
				}
				printf("\n\n");
#endif			
			}


			off_dt_struct += len;	//加上value长度偏移
			if (len % 4)
			{
				off_dt_struct += 4 - (len % 4);	//4字节对齐
			}
			break;

		case 9:
			off_dt_struct = 0;
			break;

		default:
			break;
		}

	} while (off_dt_struct);
	
	/* patch by hlb end */
	setenv_hex("fdtaddr", addr);
}

该函数里面主要是实现了解析设备树,然后找到MAC地址的属性,将MAC地址的低三个字节替换成UID的低三个字节。保存编译一下,到这里u-boot基本上就算改完了,然后接下来还要修改设备树,因为我这版设备树里面是没有MAC地址属性的。然后设备树解析这里也不详细赘述了,有兴趣的同学自行查阅资料,或者是去买韦东山老师的设备树视频来看一下。(其实这不是软文)

打开kernel源码 ./arch/arm/boot/dts 里的 100ask_imx6ull-14x14.dts 文件,找到:fec1 和 fec2 节点,然后添加:

local-mac-address = [00 0a 35 00 00 00];

最后编译一下dtb,通过nfs文件系统把dtb文件拷贝到开发板 /boot 目录下就行了,注意一下名字不要弄错了。最后再烧写一下u-boot。开机就能看效果了!

u-boot打印:

进入系统之后 ifconfig -a:

大功告成!

最后再罗嗦两句,第一个就是我是没钱买带TF卡版本的,所以我只有EMMC,然而用 mfg_tool 烧写EMMC的时候默认是 u-boot、kernel、dtb、rootfs 一起烧写的。然后这里只需要烧写 u-boot ,咨询了一下群里的老师,老师让修改一下烧写工具目录下的 ./Profiles/Linux/OS Firmware/ 里的 ucl2.xml 就行了。接下来查了一下资料,只需要删除一部分命令就行了:

大概就是把红色框框里面的东西删掉就OK了。具体语法不详细赘述了。

我把修改好的文件贴上来:

<!--
* Copyright (C) 2012, Freescale Semiconductor, Inc. All Rights Reserved.
* The CFG element contains a list of recognized usb devices.
*  DEV elements provide a name, class, vid and pid for each device.
*
* Each LIST element contains a list of update instructions.
*  "Install" - Erase media and install firmware.
*  "Update" - Update firmware only.
*
* Each CMD element contains one update instruction of attribute type.
*  "pull" - Does UtpRead(body, file) transaction.
*  "push" - Does UtpWrite(body, file) transaction.
*  "drop" - Does UtpCommand(body) then waits for device to disconnect.
*  "boot" - Finds configured device, forces it to "body" device and downloads "file".
*  "find" - Waits for "timeout" seconds for the "body" device to connect.
*  "show" - Parse and show device info in "file".  
-->


<UCL>
  <CFG>
    <STATE name="BootStrap" dev="MX6SL" vid="15A2" pid="0063"/>
    <STATE name="BootStrap" dev="MX6D" vid="15A2" pid="0061"/>
    <STATE name="BootStrap" dev="MX6Q" vid="15A2" pid="0054"/>
    <STATE name="BootStrap" dev="MX6SX" vid="15A2" pid="0071"/>
    <STATE name="BootStrap" dev="MX6UL" vid="15A2" pid="007D"/>
    <STATE name="BootStrap" dev="MX7D" vid="15A2" pid="0076"/>
    <STATE name="BootStrap" dev="MX6ULL" vid="15A2" pid="0080"/>
    <STATE name="Updater"   dev="MSC" vid="066F" pid="37FF"/>
  </CFG>

  

  <LIST name="SDCard" desc="Choose SD Card as media">
	<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%6uluboot%_sd.imx" ifdev="MX6UL">Loading U-boot</CMD>
	<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_sd.imx" ifdev="MX6ULL">Loading U-boot</CMD>
		
	<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x12000000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6Q MX6D">Loading Kernel.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>

	<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul-%6uldtb%%ldo%.dtb" address="0x83000000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL">Loading device tree.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6ulldtb%%ldo%.dtb" address="0x83000000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>


	<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>


	<!-- create partition -->
	<CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>
	<CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>
	<CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>

	<!-- burn uboot -->
	<CMD state="Updater" type="push" body="send" file="files/u-boot-imx6ul%6uluboot%_sd.imx" ifdev="MX6UL">Sending u-boot.bin</CMD>
	<CMD state="Updater" type="push" body="send" file="files/u-boot-imx6ul%lite%%6uluboot%_sd.imx" ifdev="MX6ULL">Sending u-boot.bin</CMD>

	<CMD state="Updater" type="push" body="$ dd if=/dev/zero of=/dev/mmcblk%mmc% bs=1k seek=768 conv=fsync count=8">clear u-boot arg</CMD>
	<CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mmcblk%mmc% bs=1k seek=1 conv=fsync">write u-boot.bin to sd card</CMD>

	<CMD state="Updater" type="push" body="$ while [ ! -e /dev/mmcblk%mmc%p1 ]; do sleep 1; echo \"waiting...\"; done ">Waiting for the partition ready</CMD>
	<CMD state="Updater" type="push" body="$ mkfs.vfat /dev/mmcblk%mmc%p1">Formatting rootfs partition</CMD>
	<CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p1"/>
	<CMD state="Updater" type="push" body="$ mount -t vfat /dev/mmcblk%mmc%p1 /mnt/mmcblk%mmc%p1"/>

	<!-- burn zImage -->
	<CMD state="Updater" type="push" body="send" file="files/zImage">Sending kernel</CMD>
	<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/zImage">write kernel image to sd card</CMD>

	<!-- burn dtb -->
	<CMD state="Updater" type="push" body="send" file="files/zImage-imx6ul-%6uldtb%%ldo%.dtb" ifdev="MX6UL">Sending Device Tree file</CMD>
	<CMD state="Updater" type="push" body="send" file="files/zImage-imx6ul%lite%-%6ulldtb%%ldo%.dtb" ifdev="MX6ULL">Sending Device Tree file</CMD>

	<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/imx6ul-%6uldtb%.dtb" ifdev="MX6UL">write device tree to sd card</CMD>
	<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/imx6ul%lite%-%6uldtb%.dtb" ifdev="MX6ULL">write device tree to sd card</CMD>

	<!-- burn m4 demo bins-->
	<CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p1">Unmounting vfat partition</CMD>

	<!-- burn rootfs -->
	<CMD state="Updater" type="push" body="$ mkfs.ext3 -F -j /dev/mmcblk%mmc%p2">Formatting rootfs partition</CMD>
	<CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2"/>
	<CMD state="Updater" type="push" body="$ mount -t ext3 /dev/mmcblk%mmc%p2 /mnt/mmcblk%mmc%p2"/>
	
	<CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/rootfs_nogpu.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting rootfs</CMD>
	<CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>
	<CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p2">Unmounting rootfs partition</CMD>
	<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
  </LIST>
  
  <LIST name="eMMC" desc="Choose eMMC as media">
  
	<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_ddr%ddrsize%_emmc.imx" ifdev="MX6ULL">Loading U-boot</CMD>
		
	<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>

	<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>


	<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" address="0x83000000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>

	<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>


	<!-- create partition -->
	<CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>
	<CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>
	<CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>

	<!-- burn uboot -->
	<CMD state="Updater" type="push" body="$ dd if=/dev/zero of=/dev/mmcblk%mmc% bs=1k seek=768 conv=fsync count=8">clear u-boot arg</CMD>
	<!-- access boot partition -->
	<CMD state="Updater" type="push" body="$ echo 0 > /sys/block/mmcblk%mmc%boot0/force_ro">access boot partition 1</CMD>
	
	
	<CMD state="Updater" type="push" body="send" file="files/u-boot-dtb.imx" ifdev="MX6ULL">Sending u-boot.bin</CMD>
	
	<CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mmcblk%mmc%boot0 bs=512 seek=2">write U-Boot to sd card</CMD>
	<CMD state="Updater" type="push" body="$ echo 1 > /sys/block/mmcblk%mmc%boot0/force_ro"> re-enable read-only access </CMD>
	<CMD state="Updater" type="push" body="$ mmc bootpart enable 1 1 /dev/mmcblk%mmc%">enable boot partion 1 to boot</CMD>
  </LIST>
</UCL>

注意!注意!注意!我这里是使用的EMMC哈!

然后说第二点,通过上面的修改,两个网卡的MAC地址都应该是搞定了的。然而这里面还有一种情况,就是 u-boot 的环境变量里面设置了 ethaddr 变量,这种情况下u-boot会去解析设备树之后把我们修改好的值替换成这个变量的值。当然这里也是可以解决的,解决方法就在上文中提到的另外一篇blog里面写得很详细的,因为我实在是不想打字了,抱歉了。

最后依照惯例还是应该要说一下,本人毕竟水平有限。有什么问题就联系我吧!

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值