u-boot与linux下网卡MAC地址的更改
前言
①假设有许多开发板,连接到了同一个路由器中,而路由器的dhcpd是根据MAC地址来分配一个固定的IP地址,那么就需要为每一个开发板设定一个不同的MAC地址从而获取不同的IP地址。
②MAC地址是需要购买的(参考点1),在产品出厂之前,都需要给板子一个MAC地址(如果有对应的设备,例如网卡,Wifi)。且这个MAC地址在出厂后,我们并不期望被更改。
下面简述了嵌入式产品中如何保证IP地址不被更改的、以及开发过程或者生产过程如何更改MAC地址。
不被更改的方法
嵌入式中对于期望不被更改的数据,一般都是存放在无法被直接擦除或者修改的存储设备中,例如nand、eMMC、EEPROM、带保护的Nor Flash、甚至是直接写在程序中。这里说的无法被直接修改是相对内存而言的,并不是无法被修改。例如nand在修改之前,一般是需要去保护、擦除。
具体的,对于嵌入式产品而言,一般都是使用u-boot来作为bootloader,u-boot将需要的一些参数放在环境变量中,例如MAC地址就是从环境变量ethaddr中获取的。因此要保证MAC地址能够不被直接修改,那么可以将u-boot中的环境变量放在一个带有保护措施的存储器中,在需要改写的时候去除保护,改写完成后再进行保护。
u-boot启动后,在板极硬件初始化的过程中,会去初始化网卡,并获取MAC地址,这有两种情况:
在初始化的过程中会去读取MAC地址相关的环境变量
也有可能是从网卡芯片中的内置EEPROM获取MAC地址(例如SMC911x,就会有一个EEPROM存储MAC地址,上电后,会将此IP地址加载到用户可以访问的寄存器中)
调用的路径如下,具体详细的关于u-boot中eth driver的说明参考u-boot中的文档doc/drivers.net.eth:
board_init()
eth_initialize()
board_eth_init() / cpu_eth_init()
driver_register()
initialize eth_device
eth_register()
从环境变量ethaddr获取MAC地址的实例
具体到瑞萨的Cortex-A15芯片而言,如果使用的是SoC自带的ether,那么在board_eth_init中会从环境变量中读取ethaddr环境变量,来获取MAC地址。代码文件sh-net.c。
int board_eth_init(bd_t *bis)
{
int ret = -ENODEV;
u32 val;
unsigned char enetaddr[6];
#ifdef CONFIG_SH_ETHER
ret = sh_eth_initialize(bis);
if (!eth_getenv_enetaddr("ethaddr", enetaddr))
return ret;
/* Set Mac address */
val = enetaddr[0] << 24 | enetaddr[1] << 16 |
enetaddr[2] << 8 | enetaddr[3];
writel(val, 0xEE7003C0);
val = enetaddr[4] << 8 | enetaddr[5];
writel(val, 0xEE7003C8);
#endif
return ret;
}
在sh_eth_initialize(瑞萨的一款Cortex-A15 SoC自带的eth)中,会去读取ethaddr环境变量:
int sh_eth_initialize(bd_t *bd)
{
int ret = 0;
struct sh_eth_dev *eth = NULL;
struct eth_device *dev = NULL;
eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev));
if (!eth) {
printf(SHETHER_NAME ": %s: malloc failed\n", __func__);
ret = -ENOMEM;
goto err;
}
dev = (struct eth_device *)malloc(sizeof(struct eth_device));
if (!dev) {
printf(SHETHER_NAME ": %s: malloc failed\n", __func__);
ret = -ENOMEM;
goto err;
}
memset(dev, 0, sizeof(struct eth_device));
memset(eth, 0, sizeof(struct sh_eth_dev));
eth->port = CONFIG_SH_ETHER_USE_PORT;
eth->port_info[eth->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR;
dev->priv = (void *)eth;
dev->iobase = 0;
dev->init = sh_eth_init;
......
sprintf(dev->name, SHETHER_NAME);
/* Register Device to EtherNet subsystem */
eth_register(dev);
bb_miiphy_buses[0].priv = eth;
miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write);
if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr))
puts("Please set MAC address\n");
return ret;
.....
}
在倒数几行中,使用eth_getenv_ethaddr函数从环境变量ethaddr中获取并设置MAC地址,如果环境变量中不存在此环境变量,那么就会要求你先设置一个。如果设置成功了,那么以后都会从这个环境变量中获取。
从网卡芯片中的EEPROM中获取MAC地址
对于SMC911x(这里使用smc911x与smsc911x,不作区分,一个是实际的名字,一个是代码中使用的名字)芯片而言,在其上电后,会从EEPROM中将MAC地址加载到用户可以访问的MAC地址寄存器中,参考下面的图Figure1:MAC Address Reg中的框图中的Description描述。如果SMC911x没有设置过MAC地址,那么出厂的默认MAC都是FF。
对于SMC911x(smc911x.c代码文件点击此处, smsc911x的datasheet下载点击此处),u-boot在启动后,smc911x的initialze中会到硬件中获取MAC地址,如果MAC地址全部为FF,那么就会从环境变量中获取,然后在smc911x_init中将此MAC值设置到芯片的MAC地址存储寄存器中,芯片会自动将这个MAC地址写入到EEPROM中,用于下一次的使用。
详细而言,网络控制器芯片SMC911X,使用两个寄存器来保存MAC地址值,这两个寄存器32Bit的,每一个寄存器保存6字节MAC地址的3Byte。需要注意的是这个寄存器是可读可写的:
Figure1:MAC Address Reg
对应的代码实现在drivers/net/smc911x.c中,设置MAC地址的函数为:
static void smc911x_handle_mac_address(struct eth_device *dev)
{
unsigned long addrh, addrl;
uchar *m = dev->enetaddr;
addrl = m[0] | (m[1] << 8) | (m[2] << 16) | (m[3] << 24);
addrh = m[4] | (m[5] << 8);
smc911x_set_mac_csr(dev, ADDRL, addrl);
smc911x_set_mac_csr(dev, ADDRH, addrh);
printf(DRIVERNAME ": MAC %pM\n", m);
}
其中第8-9行,就是设置数据书册中的提到的MAC地址高低寄存器。
不可被覆盖
如果在设置了ethaddr之后,又去设置ethaddr环境变量,那么会出现错误,提示不能重写ethaddr,这样就完成了基本的不可重写的保护:
set ethaddr 2e:09:0a:00:6e:1f
[ 28.372] ## Error: Can't overwrite "ethaddr"
[ 28.373] ## Error inserting "ethaddr" variable, errno=1
更改的方法
MAC地址可以配置的地方有以下2个:
u-boot中
Linux启动后
u-boot中更改MAC地址
共有两种方法:
destroy所有的环境变量:不需要重新编译u-boot,但是如果env写死在代码中,那么就无能为力了
在板极配置头文件(include/configs/xxx.h)中定义CONFIG_ENV_OVERWRITE 后重新编译u-boot:需要重新编译u-boot
销毁env区域来更改
对于第一种方法,因为不同的板子,存放u-boot环境变量的位置也不一样,有可能是nand flash、eMMC、SD Card也有可能是SPI Norflash,因此命令各不相同,但是显然步骤几乎都是一样的:
保存现在的所有env,以免万一哪些项需要的是无法恢复:可以使用pri来查看所有的env
擦除u-boot env区域:使用不同flash的擦除命令来完成
设置default env值:可以使用env default -a
设置MAC地址:setenv ethaddr XX:YY:...
将env存储到env layout区域::saveenv
重新编译u-boot来更改
如果是代码中直接写死了ethaddr环境变量的值,那么就只能重新编译了:
#define CONFIG_EXTRA_ENV_SETTINGS \
"baudrate=460800\0" \
"bootm_low=0x40e00000\0" \
"bootm_size=0x100000\0" \
"ethact=smc911x-2\0" \
"ethaddr=2e:09:0a:00:6e:1e\0"
如果代码中没有写死,那么可以在配置文件中添加下面一行来让ethaddr可以被更改:
#define CONFIG_ENV_OVERWRITE 1
linux下更改MAC地址
当系统启动到OS后,要更改MAC地址既可以直接使用命令来更改,也可以在sysV-init脚本中配置。
①对于命令行,可以直接使用busybox中的ifconfig来完成:
busybox ifconfig eth0 hw ether 12:34:56:78:90:af
但是这个更改无法永久性的更改,重启后就又恢复回到原值了,因为ifconfig命令中根本就不会去更改硬件寄存器,或者环境变量,ifconfig中设置hw部分的代码如下:
#if ENABLE_FEATURE_IFCONFIG_HW
} else { /* A_CAST_HOST_COPY_IN_ETHER */
/* This is the "hw" arg case. */
smalluint hw_class = index_in_substrings("ether\0"
IF_FEATURE_HWIB("infiniband\0"), *argv) + 1;
if (!hw_class || !*++argv)
bb_show_usage();
host = *argv;
if (hw_class == 1 ? in_ether(host, &sa) : in_ib(host, &sa))
bb_error_msg_and_die("invalid hw-addr %s", host);
p = (char *) &sa;
}
#endif
②对于使用更改SysV-Init或者systemd等的更改,google中可以找到许多的答案。但是这种方法也无法永久性的更改,因为同样也没有操作硬件。
参考
1. 14.2.14. Where Can I Get a Valid MAC Address from?
如果文章有格式问题,请移步:http://www.hexiongjun.com/?p=228
转载请注明出处。作者:TonyHo hexiongjun.com
————————————————
版权声明:本文为CSDN博主「TonyHo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sy373466062/article/details/49021485
u-boot与linux下网卡MAC地址的更改相关推荐
- Linux下修改MAC地址总结
偶尔会用到这个知识点,久了不用又会记不住,所以记之,方便以后查询. Linux下修改MAC地址 方法一: 1.关闭网卡设备 ifconfig eth0 down 2.修改MAC地址 ifconfig ...
- 网关屏蔽mac地址,linux下修改mac地址方法
局域网里有一台机器,同一网段内的机器,只有部分能够ping通,也无法ping通网关,现象很奇怪,尝试过修改IP,重启网络服务,都无法解决问题. 最后怀疑是不是网关将该机器mac地址给屏蔽掉了,因此修改 ...
- Linux调整网卡MAC地址(指令)
Linux调整网卡MAC地址(指令) 有的时候需要使用欺骗的方法为电脑设置新的mac,比如存在上网网卡限制,或者想要隐藏自己的真实mac地址.这里列举三种修改mac的方法,适用于Debian系的Lin ...
- linux 命令行修改mac,Linux下修改MAC地址
Linux下修改MAC地址 Author: Jaylin Zhou Date: 10/17/2009 使用ifconfig命令 标准形式: # ifconfig device_name hw ethe ...
- linux设置mac地址命令,[转载]Linux下修改MAC地址
转自http://blogold.chinaunix.net/u3/94284/showart_2430693.html Linux下修改MAC地址 方法一: 1.关闭网卡设备 ifconfig et ...
- linux服务器远程修改mac地址,linux下修改MAC地址问题解决方法
linux下修改MAC地址问题解决方法 作者:佚名 来源:网络整理 2013-4-17 在linux中,修改MAC地址 # ifdown eth0 # ifconfig eth0 hw ether 1 ...
- Linux服务器绑定mac地址,linux下绑定mac地址
我还是分两种发行版来介绍绑定mac的方法.RedHat和Debian. RedHat(这是网友的一篇文章) linux的发布版本我选择了Redhat9.0,为什么?没有为什么,就因为他安装so eas ...
- linux电脑mac地址修改不了怎么办,linux下修改MAC地址问题解决方法
在linux中,修改MAC地址 # ifdown eth0 # ifconfig eth0 hw ether 12:34:56:78:90:12 (修改的MAC地址跟原来的地址不同) # ifup e ...
- Linux 下查看mac地址
linux 最常用的查看mac地址的方式 有很多种,下面给出4种方式,其中前两种在配置ip之后,后面两种可以在操作系统未设置IP地址之前. 1.ifconfig 这是最常用的方式 2.CentOS系统 ...
- linux得到网卡mac地址,获取 linux 网卡MAC地址(包含编程方法)
网卡在计算机专业词汇里面被叫做 network interface 如果检索资料可以用这个词汇 常用的几种办法 ip link show cat /sys/class/net//address 使用 ...
最新文章
- php源码安全加密之PHP混淆算法.
- 5G时代下,边缘计算产品的未来展望
- Linux服务器-使用mysql
- Feather包实现数据框快速读写,你值得拥有
- 如何缩小码农和高手的差距
- 学习 SpringCloud 五大组件后的总结 一
- python—缺失数据的处理
- HTTP协议发展历史
- u盘启动盘 联想服务器TS250 Win Server 2016 下 安装Linux(ubuntu-18.04.1-desktop-amd64)双系统 各种问题总结(2018-11-13)
- 谷歌浏览器为什么要禁用Flash插件?深夜有感而发
- selenium 确实是好东西,使用selenium-server 加快执行速度,对速度有很大提升,同时可以拆分服务,进行集群部署。
- RSA系列第2篇:RSA 加密解密
- 安卓开发之Intent使用介绍(显式Intent和隐式Intent)
- mars3d中时间的转换
- mount qemu qcow2、img
- Linux下服务器开发的必要准备
- 离散型随机变量-Discrete Random Variables
- Python nose测试大法
- 同事喜欢、领导器重的是哪类人?
- proteus教程——使能端口控制8255