uboot env ethaddr 是如何生成的

uboot env ethaddr 是如何生成的?

思考

默认环境变量中并不会指定 ethaddr , 然而板子起来后会自己生成ethaddr 变量,并且各个板子的ethaddr 是唯一的。并且即使清除env分区,重新启动后ethaddr 也不会变。是如何做到的?

  • ethaddr 变量是何时设置的?
  • 是如何做各个板子唯一的?
  • 为何清除env 分区,重新启动也不会变?
  • ethaddr 可以手动设置吗?

ethaddr 变量是何时设置的?

在uboot/doc/README.enetaddr 中有说明:

-------
 Usage
-------

If the hardware design mandates that the MAC address is stored in some special
place (like EEPROM etc...), then the board specific init code (such as the
board-specific misc_init_r() function) is responsible for locating the MAC
address(es) and initializing the respective environment variable(s) from it.
Note that this shall be done if, and only if, the environment does not already
contain these environment variables, i.e. existing variable definitions must
not be overwritten.

大意是必须在 misc_init_r 函数中对 ethaddr 进行设置。

以sun8i-h3 为例,跟踪一下代码:

misc_init_r   //u-boot-2017.11.git\board\sunxi\board.c
-> setup_environment(gd->fdt_blob);
static void setup_environment(const void *fdt)
{
	char serial_string[17] = { 0 };
	unsigned int sid[4];
	uint8_t mac_addr[6];
	char ethaddr[16];
	int i, ret;

	ret = sunxi_get_sid(sid);     // sid 是 h3 芯片的唯一id,每块芯片不一样
	if (ret == 0 && sid[0] != 0) {
		/*
		 * The single words 1 - 3 of the SID have quite a few bits
		 * which are the same on many models, so we take a crc32
		 * of all 3 words, to get a more unique value.
		 *
		 * Note we only do this on newer SoCs as we cannot change
		 * the algorithm on older SoCs since those have been using
		 * fixed mac-addresses based on only using word 3 for a
		 * long time and changing a fixed mac-address with an
		 * u-boot update is not good.
		 */
#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
		sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
#endif

		/* Ensure the NIC specific bytes of the mac are not all 0 */
		if ((sid[3] & 0xffffff) == 0)
			sid[3] |= 0x800000;

		for (i = 0; i < 4; i++) {
			sprintf(ethaddr, "ethernet%d", i);
			if (!fdt_get_alias(fdt, ethaddr))
				continue;

			if (i == 0)
				strcpy(ethaddr, "ethaddr");
			else
				sprintf(ethaddr, "eth%daddr", i);

			if (env_get(ethaddr))
				continue;

			/* Non OUI / registered MAC address */
			mac_addr[0] = (i << 4) | 0x02;
			mac_addr[1] = (sid[0] >>  0) & 0xff;
			mac_addr[2] = (sid[3] >> 24) & 0xff;
			mac_addr[3] = (sid[3] >> 16) & 0xff;
			mac_addr[4] = (sid[3] >>  8) & 0xff;
			mac_addr[5] = (sid[3] >>  0) & 0xff;

			eth_env_set_enetaddr(ethaddr, mac_addr);
		}		
	}
}

sid 对应于手册上的 Seurity ID:

至此,可以解答前三个问题:

  • ethaddr 变量是何时设置的?

    答:misc_init_r -> setup_environment 中设置

  • 是如何做各个板子唯一的?

    答:因为是通过读取芯片sid , 来生成mac 地址。

  • 为何清除env 分区,重新启动也不会变?

    答:因为sid 存在芯片内部,只要芯片没换就不会变。

ethaddr 可以手动设置吗?

默认不能。

=> setenv ethaddr d0:00:00:00:00:01
## Error: Can't overwrite "ethaddr"
## Error inserting "ethaddr" variable, errno=1
=> 

可见 uboot 中对 ethaddr 做了写权限限制。

开启 CONFIG_CMD_ENV_FLAGS=y , 可通过 env flags 查看一些变量的权限。

=> env flags
Available variable type flags (position 0):
        Flag    Variable Type Name
        ----    ------------------
        s   -   string
        d   -   decimal
        x   -   hexadecimal
        b   -   boolean
        i   -   IP address
        m   -   MAC address

Available variable access flags (position 1):
        Flag    Variable Access Name
        ----    --------------------
        a   -   any
        r   -   read-only
        o   -   write-once
        c   -   change-default

Static flags:
        Variable Name        Variable Type        Variable Access     
        -------------        -------------        ---------------     
        eth\d?addr           MAC address          write-once          
        ipaddr               IP address           any                 
        gatewayip            IP address           any                 
        netmask              IP address           any                 
        serverip             IP address           any                 
        nvlan                decimal              any                 
        vlan                 decimal              any                 
        dnsip                IP address           any                 
        serial#              string               write-once          

Active flags:
        Variable Name        Variable Type        Variable Access     
        -------------        -------------        ---------------     
        serial#              string               write-once          
        ethaddr              MAC address          write-once          
        serverip             IP address           any                 
        ipaddr               IP address           any                 

在uboot/README 中有如下说明:

- 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_ an ethaddr in the
                default env _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.

可见uboot 专门对 serial# ethaddr 等变量做了保护措施,默认不可修改,如需修改,需要打开 CONFIG_ENV_OVERWRITE=y 配置选项。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值