U-boot ethaddr mac address

U-boot交互模式下,使用 setenv 设置网卡的MAC地址时,发现报一下错误:

=> setenv ethaddr D4:6D:6D:18:FD:F5
## Error: Can't overwrite "ethaddr"
## Error inserting "ethaddr" variable, errno=1

原来,U-boot中对MAC地址是写保护的,默认是不可以更改的。在u-boot的文档中,可以看到说明:

- Vendor Parameter Protection:

                U-Boot considers the values of the environment
                variables "serial#" (Board Serial Number) and
                "ethaddr" (Ethernet Address) to be parameters that
                are set once by the board vendor / manufacturer, and
                protects these variables from casual modification by
                the user. Once set, these variables are read-only,
                and write or delete attempts are rejected. You can
                change this behaviour:


                If CONFIG_ENV_OVERWRITE is #defined in your config
                file, the write protection for vendor parameters is
                completely disabled. Anybody can change or delete
                these parameters.


                Alternatively, if you #define _both_ CONFIG_ETHADDR
                _and_ CONFIG_OVERWRITE_ETHADDR_ONCE, a default
                Ethernet address is installed in the environment,
                which can be changed exactly ONCE by the user. [The
                serial# is unaffected by this, i. e. it remains
                read-only.]


                The same can be accomplished in a more flexible way
                for any variable by configuring the type of access
                to allow for those variables in the ".flags" variable
                or define CONFIG_ENV_FLAGS_LIST_STATIC.

当然,如果你想重新修改MAC地址,最简单的方法就是通过配置:CONFIG_ENV_OVERWRITE,重新编译U-boot,重启u-boot,就可以多次修改MAC地址对应的环境变量:ethaddr了。

U-boot中,使用环境变量 ethaddr ,用来存储 网卡对应 的 MAC地址,每个板子对应的MAC地址都是唯一的,这个是如何做到的呢?以RK3588平台为例,先看看ethaddr这个环境变量是如何初始化的:

/* arch/arm/mach-rochchip/board.c */
__weak int misc_init_r(void)
{
    const u32 cpuid_offset = CFG_CPUID_OFFSET;
    const u32 cpuid_length = 0x10;
    u8 cpuid[cpuid_length];
    int ret;

    ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid);
    if (ret)
        return ret;
    ret = rockchip_cpuid_set(cpuid, cpuid_length);
    if (ret)
        return ret;
    ret = rockchip_setup_macaddr();
    return ret;
}

系统上电初始化后,是通过读取芯片的SID,通过CRC校验,来生成MAC地址的,从而确保每个设备的MAC地址的唯一性。每个芯片的SID,一般都是存储在芯片内部的efuse后者EEPROM中,上电后就可以读取。