OpenWRT 下以太网MAC地址的写入

近期在为朋友制定OpenWRT系统下产测解决方案时,遇到了MAC地址的写入问题。产测使用Qualcomm Atheros的ART软件,只能写入无线的MAC地址,无法写入以太网的MAC地址, 笔者花了一些时间终于研究清楚,在这里做个记录,以便后续查阅。注:本文以AR9344无线AP为例进行说明,这种方法仅适用于采用Qualcomm Atheros AR93xx/AR94xx系列芯片的AP设备。

首先,必须清楚一点,AP类设备与无线相关的校准数据都是保存在Flash的ART分区的,熟悉OpenWRT的读者肯定都知道。例如 笔者所用的OpenWRT固件版本,其Flash分区如下图。可以看到,Flash中的0x7F0000-0x80000这一段是划分给ART分区的。

ART-MTD

然后,Qualcomm Atheros官方说明文档中对于ART分区的内容有进一步的说明,如下图。可以看到MAC0也就是ETH0的MAC地址保存在0x0-0x5偏移地址中,MAC1也就是ETH1的MAC地址保存在0x6-0xB偏移地址中,无线的MAC地址分别保存在0x1000-0x4FFF与0x5000-0x8FFF偏移地址中。这里需要指出的是,如果是单Radio设备,那么只有First Radio Calibration Data,如果是双Radio设备,会同时有First/Second Radio Calibration Data。

ART-Block-Diagram

接下来,可以根据这些已有的信息尝试写入MAC地址,以下是全部过程。

1. 为主板加电,当串口中出现Hit any key to stop autoboot:字样时,敲击回车键,待测板会停留在u-boot阶段。

Stop-u-boot

2. 敲入printenv命令,不难看出Flash的地址空间映射为0x9F000000-0x9F7FFFFF,则推断出ART分区的地址为0x9F7F0000-0x9F7FFFF。由此,可以得知,ETH0的MAC地址存放于0x9F7F0000-0x9F7F0005,ETH1的MAC地址存放于0x9F7F0006-0x9F7F000B。

Printenv

3. 写入以太网MAC地址不能破坏原有校准数据,因此需要先将ART分区的内容复制到内存中,输入以下命令

cp.b 0x9f7f0000 0x80060000 10000

4. 假设欲写入的ETH0,ETH1 MAC分别为“00-03-7f-01-01-02”,“00-03-7f-01-01-03”,则修改内存中的MAC地址,依次输入以下命令

mw 0x80060000 00037f01
mw 0x80060004 01020003
mw 0x80060008 7f010103

5. 查看内存中的MAC地址是否准确,输入以下命令

md 0x80060000

串口中的打印信息应为

80060000: 00037f01 01020003 7f010103 ffffffff

即80060000存放的数据为ETH0与ETH1 MAC地址的结合。

6. 确认无误后,将Flash中的原有校准数据擦除,在串口中输入以下命令

erase 0x9f7f0000 +10000
cp.b 0x80060000 0x9f7f0000 10000

串口中的打印信息应为

Copy to Flash... write addr: 9f7f0000
done

7. 以上完整操作过程下图所示。

Operation-Process

8. 最后检验MAC地址是否已准确写入,在串口中输入以下命令

md 0x9f7f0000

串口中的打印信息应为

9f7f0000: 00037f01 01020003 7f010103 ffffffff

此时可确认ETH0及ETH1 MAC地址已准确写入。

9 thoughts on “OpenWRT 下以太网MAC地址的写入

  1. Alex,我们也在使用openWRT,测试中发现,两个ap连接的时候有时候会出现噪声和信号电平出错,重启后就有显示正常

  2. lics你好,非常感谢你的文章, 我如果想在linux环境下, 通过应用来读取mac地址和 写入mac地址应该怎样操作

    我的是tp系列, mac地址放在uboot中, 在spi flash 的 0x1fc00偏移位置

    在应用中读mac

    fd = open(“/dev/mtd0”, O_RDWR);
    lseek(fd, 0x1fc00, SEEK_SET);
    read(fd, buf, 6);
    这样可以读出 0x1fc00 处保存的数据

    但是写的话, 始终写不进去
    fd = open(“/dev/mtd0”, O_RDWR);
    lseek(fd, 0x1fc00, SEEK_SET);
    write(fd, buf, 6);
    是不是 /dev/mtdn 字符设备不能这样简单的写入, 而要块擦除后,再写入, 有没有操作方法。

    另外一个小问题一直比较困惑,
    ART数据是64K
    在您文章的图中, eth0_mac , eth1_mac 是从ART数据的头部开始算的吗?
    为啥到后面是0x8fff, 而不是64k, 是说 ART 0x8fff 之后的没有保存数据吗
    我打开几个934x系列的 art文件, 发现从 0x00 到 0x1000 之间的数据都是 0xFF

    1. 补充一下, Uboot区域和ART区域已经去掉只读属性

      write的时候,没有报错, 返回的写入个数也跟传进去的一致,就是读flash内容没有变换

    2. 这个我也不太懂,我就说一下我的思路吧,不一定对:先把mtd0信息dd到一个文件中,然后将文件中mac地址对应的位置修改掉,擦除mtd0,最后将修改过后的文件写入mtd0。

      0x8fff之后应该是用不到的。

发表评论