MX6ULL使用UNIQUE ID配置网卡MAC地址

标签: imx6ull

前言:

貌似不管用什么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) 将函数内容替换成


  1. void set_working_fdt_addr(ulong addr)

  2. {

  3. void *buf;

  4. /* patch by hlb start */

  5. #define B2L(x) (((x & 0xff000000) >> 24) | ((x & 0xff0000) >> 8) | ((x & 0xff00) << 8) | ((x & 0xff) << 24))

  6. unsigned int off_dt_struct; /* offset to structure */

  7. unsigned int off_dt_strings; /* offset to strings */

  8. unsigned int off_mem_rsvmap; /* offset to memory reserve map */

  9. unsigned int temp;

  10. unsigned int len;

  11. unsigned int name_off;

  12. unsigned char* str;

  13. unsigned char* node_name;

  14. int root_node = 0;

  15. int mac_cnt = 0;

  16. unsigned int ID0 = *((volatile const unsigned int*)0x21BC410);

  17. unsigned int ID1 = *((volatile const unsigned int*)0x21BC420);

  18. printf("\nID0 = 0x%08x\n", ID0);

  19. printf("ID1 = 0x%08x\n", ID1);

  20. /* patch by hlb end */

  21. buf = map_sysmem(addr, 0);

  22. working_fdt = buf;

  23. /* patch by hlb start*/

  24. #if 0

  25. printf("addr = 0x%08x\n", addr);

  26. printf("buf = 0x%08x\n", buf);

  27. #endif

  28. off_dt_struct = B2L(working_fdt->off_dt_struct);

  29. off_dt_strings = B2L(working_fdt->off_dt_strings);

  30. off_mem_rsvmap = B2L(working_fdt->off_mem_rsvmap);

  31. #if 0

  32. printf("off_dt_struct = %d\n", off_dt_struct);

  33. printf("off_dt_strings = %d\n", off_dt_strings);

  34. printf("off_mem_rsvmap = %d\n", off_mem_rsvmap);

  35. #endif

  36. off_dt_struct += (unsigned int)working_fdt;

  37. off_dt_strings += (unsigned int)working_fdt;

  38. off_mem_rsvmap += (unsigned int)working_fdt;

  39. do

  40. {

  41. temp = *((unsigned int*)off_dt_struct);

  42. off_dt_struct += 4;

  43. temp = B2L(temp);

  44. switch (temp)

  45. {

  46. case 1:

  47. if (root_node == 0) //处理根节点

  48. {

  49. root_node = 1;

  50. off_dt_struct += 4; //根节点没有名字,跳过

  51. }

  52. else

  53. {

  54. /* node name */

  55. node_name = (unsigned char*)off_dt_struct;

  56. //printf("node name: %s\n", str);

  57. int str_len;

  58. str_len = strlen((const char*)node_name) + 1;

  59. off_dt_struct += str_len;

  60. if (str_len % 4)

  61. {

  62. off_dt_struct += 4 - (str_len % 4); //4字节对齐

  63. }

  64. }

  65. break;

  66. case 2:

  67. break;

  68. case 3:

  69. /* value len */

  70. temp = *((unsigned int*)off_dt_struct);

  71. len = B2L(temp);

  72. off_dt_struct += 4;

  73. /* nameoff */

  74. temp = *((unsigned int*)off_dt_struct);

  75. name_off = B2L(temp);

  76. str = (unsigned char*)(off_dt_strings + name_off);

  77. off_dt_struct += 4;

  78. if (strstr((char*)str, (const char*)"local-mac-address"))

  79. {

  80. unsigned char* pmac;

  81. pmac = (unsigned char*)off_dt_struct;

  82. #if 1

  83. printf("Finding eth%d node name is: %s\n", mac_cnt, node_name);

  84. printf("Old local-mac-address value len = %d\n", len);

  85. for (int i = 0; i < 6; i++)

  86. {

  87. printf("0x%02x ", pmac[i]);

  88. }

  89. printf("\n");

  90. #endif

  91. pmac[0] = 0x00;

  92. pmac[1] = 0x0a;

  93. pmac[2] = 0x35 + mac_cnt++;

  94. pmac[3] = (unsigned char)(ID1 >> 16);

  95. pmac[4] = (unsigned char)(ID1 >> 8);

  96. pmac[5] = (unsigned char)(ID1 >> 0);

  97. #if 1

  98. printf("Use ID1 value!\n");

  99. printf("local-mac-address value len = %d\n", len);

  100. for (int i = 0; i < 6; i++)

  101. {

  102. printf("0x%02x ", pmac[i]);

  103. }

  104. printf("\n\n");

  105. #endif

  106. }

  107. off_dt_struct += len; //加上value长度偏移

  108. if (len % 4)

  109. {

  110. off_dt_struct += 4 - (len % 4); //4字节对齐

  111. }

  112. break;

  113. case 9:

  114. off_dt_struct = 0;

  115. break;

  116. default:

  117. break;

  118. }

  119. } while (off_dt_struct);

  120. /* patch by hlb end */

  121. setenv_hex("fdtaddr", addr);

  122. }

该函数里面主要是实现了解析设备树,然后找到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了。具体语法不详细赘述了。

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


  1. <!--

  2. * Copyright (C) 2012, Freescale Semiconductor, Inc. All Rights Reserved.

  3. * The CFG element contains a list of recognized usb devices.

  4. * DEV elements provide a name, class, vid and pid for each device.

  5. *

  6. * Each LIST element contains a list of update instructions.

  7. * "Install" - Erase media and install firmware.

  8. * "Update" - Update firmware only.

  9. *

  10. * Each CMD element contains one update instruction of attribute type.

  11. * "pull" - Does UtpRead(body, file) transaction.

  12. * "push" - Does UtpWrite(body, file) transaction.

  13. * "drop" - Does UtpCommand(body) then waits for device to disconnect.

  14. * "boot" - Finds configured device, forces it to "body" device and downloads "file".

  15. * "find" - Waits for "timeout" seconds for the "body" device to connect.

  16. * "show" - Parse and show device info in "file".

  17. -->

  18. <UCL>

  19. <CFG>

  20. <STATE name="BootStrap" dev="MX6SL" vid="15A2" pid="0063"/>

  21. <STATE name="BootStrap" dev="MX6D" vid="15A2" pid="0061"/>

  22. <STATE name="BootStrap" dev="MX6Q" vid="15A2" pid="0054"/>

  23. <STATE name="BootStrap" dev="MX6SX" vid="15A2" pid="0071"/>

  24. <STATE name="BootStrap" dev="MX6UL" vid="15A2" pid="007D"/>

  25. <STATE name="BootStrap" dev="MX7D" vid="15A2" pid="0076"/>

  26. <STATE name="BootStrap" dev="MX6ULL" vid="15A2" pid="0080"/>

  27. <STATE name="Updater" dev="MSC" vid="066F" pid="37FF"/>

  28. </CFG>

  29. <LIST name="SDCard" desc="Choose SD Card as media">

  30. <CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%6uluboot%_sd.imx" ifdev="MX6UL">Loading U-boot</CMD>

  31. <CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_sd.imx" ifdev="MX6ULL">Loading U-boot</CMD>

  32. <CMD state="BootStrap" type="load" file="firmware/zImage" address="0x12000000"

  33. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6Q MX6D">Loading Kernel.</CMD>

  34. <CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"

  35. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>

  36. <CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul-%6uldtb%%ldo%.dtb" address="0x83000000"

  37. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL">Loading device tree.</CMD>

  38. <CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6ulldtb%%ldo%.dtb" address="0x83000000"

  39. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>

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

  41. <!-- create partition -->

  42. <CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>

  43. <CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>

  44. <CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>

  45. <!-- burn uboot -->

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

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

  48. <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>

  49. <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>

  50. <CMD state="Updater" type="push" body="$ while [ ! -e /dev/mmcblk%mmc%p1 ]; do sleep 1; echo \"waiting...\"; done ">Waiting for the partition ready</CMD>

  51. <CMD state="Updater" type="push" body="$ mkfs.vfat /dev/mmcblk%mmc%p1">Formatting rootfs partition</CMD>

  52. <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p1"/>

  53. <CMD state="Updater" type="push" body="$ mount -t vfat /dev/mmcblk%mmc%p1 /mnt/mmcblk%mmc%p1"/>

  54. <!-- burn zImage -->

  55. <CMD state="Updater" type="push" body="send" file="files/zImage">Sending kernel</CMD>

  56. <CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/zImage">write kernel image to sd card</CMD>

  57. <!-- burn dtb -->

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

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

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

  61. <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>

  62. <!-- burn m4 demo bins-->

  63. <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p1">Unmounting vfat partition</CMD>

  64. <!-- burn rootfs -->

  65. <CMD state="Updater" type="push" body="$ mkfs.ext3 -F -j /dev/mmcblk%mmc%p2">Formatting rootfs partition</CMD>

  66. <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2"/>

  67. <CMD state="Updater" type="push" body="$ mount -t ext3 /dev/mmcblk%mmc%p2 /mnt/mmcblk%mmc%p2"/>

  68. <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>

  69. <CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>

  70. <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p2">Unmounting rootfs partition</CMD>

  71. <CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>

  72. </LIST>

  73. <LIST name="eMMC" desc="Choose eMMC as media">

  74. <CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_ddr%ddrsize%_emmc.imx" ifdev="MX6ULL">Loading U-boot</CMD>

  75. <CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"

  76. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>

  77. <CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"

  78. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>

  79. <CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" address="0x83000000"

  80. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>

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

  82. <!-- create partition -->

  83. <CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>

  84. <CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>

  85. <CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>

  86. <!-- burn uboot -->

  87. <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>

  88. <!-- access boot partition -->

  89. <CMD state="Updater" type="push" body="$ echo 0 > /sys/block/mmcblk%mmc%boot0/force_ro">access boot partition 1</CMD>

  90. <CMD state="Updater" type="push" body="send" file="files/u-boot-dtb.imx" ifdev="MX6ULL">Sending u-boot.bin</CMD>

  91. <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>

  92. <CMD state="Updater" type="push" body="$ echo 1 > /sys/block/mmcblk%mmc%boot0/force_ro"> re-enable read-only access </CMD>

  93. <CMD state="Updater" type="push" body="$ mmc bootpart enable 1 1 /dev/mmcblk%mmc%">enable boot partion 1 to boot</CMD>

  94. </LIST>

  95. </UCL>

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

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

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

imx6ull使用Unique ID配置网卡MAC地址 - 灰信网(软件开发博客聚合)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐