转载:http://blog.chinaunix.net/uid-25885064-id-3303132.html
在使用U-boot时,有个问题就是MAC地址的设置,如果MAC地址相同的两块开发板在同一局域网中,会互相影响。由
于设备量产需要每台机器的MAC地址都不一样,所以我们给u-boot使用随即生成MAC地址,我们这里的随机生成的变量只保存到RAM空间中,其实也可
以保存到flash或MMC中,但是如果存储设备为nand的话,每次启动都会擦写一些nand
,众所周知,nand的擦写次数是有限的,写到nand中,每次还得读出到RAM,SDRAM或DDRII中,我们用的就是DDRII,还不如,一次直接
写到RAM中,供系统使用呢。我使用的是CPU 为 IMX515,CotexA8核,内存DDRII
2Gb,使用U-boot,支持,SD,Nand启动。
一、 在Imx515中找一个随机源也不容易,它不像x86一样有个硬件计数器可以作为随机源。这里我们使用了imx515的timer,经过测试也可以得到很好的随机数。
Timer部分的代码在ccpu/arm_cortexa8/mx51/timer.c中, ret
= get_timer(0).
二、得到随机数
上面得到的随机数值差别非常小,但是经过下面的计算,就可以得到看起来很随机的数。在common/main.c中实现以下函数:
- static
unsigned char random(void) - {
- unsigned
long long rand =
get_timer(0) *
100000; - unsigned
char a; - //
See "Numerical Recipes in
C", second edition,
p. 284 - rand
= rand *
1664525L +
1013904223L; - a
= rand >> 24;
//不是最低8位 - //为了得到
‘0~9,
a ~ f,
A ~ F’ 的值 - if (a
< ‘A‘) - a
= a %
10 + 48; - else if
(a <
‘F‘) - a
= a %
6 + 65; - else if
(a <
‘a‘
||
a > ‘f‘) - a
= a %
6 + 97; - return
a; - }
三、设置随机MAC地址:
在common/main.c中实现以下函数:
- void
autoset_mac_addr(void) - {
- #define
XMK_STR(x)
#x - #define
MK_STR(x)
XMK_STR(x) - char
cmd_buf[128]; - int i =
0; - char
*p_val; - p_val
= getenv ("ethaddr"); - //如果mac地址为缺省值,则随机生成mac地址(后两位)
- if(strcmp(p_val,
MK_STR(CONFIG_ETHADDR)) == 0 ) - {
- char
new_ethaddr[20],
new_ip[20]; - int rand_val =
0; - memset(new_ethaddr,
0, sizeof(new_ethaddr)); - memset(new_ip,
0, sizeof(new_ip)); - strcpy(new_ethaddr,
MK_STR(CONFIG_ETHADDR)); - new_ethaddr[12]
= 0; - //随机生成mac地址后两位
- sprintf(new_ethaddr,
"%s%02x:%02x", new_ethaddr,
random(), random()); - printf("new_ethaddr
= %s\n",
new_ethaddr); - setenv("ethaddr", new_ethaddr);
- setenv("fec_addr", new_ethaddr);
- while(1)
- {
- //随机生成IP地址(根据server地址生成,只更改最后一位)
- strcpy(new_ip,
MK_STR(CONFIG_SERVERIP)); - p_val
= strrchr(new_ip, ‘.‘); - *(p_val
+ 1)
= 0; - rand_val
= random(); - //最后位不能为0和255
- if(
(rand_val != 0)
&&
(rand_val != 0xFF)
) - {
- sprintf(new_ip,
"%s%d",
new_ip, rand_val); - }
- //不能和SERVERIP冲突
- if(strcmp(p_val,
MK_STR(CONFIG_SERVERIP)) != 0) - {
- break;
- }
- }
- printf("new_ip = %s\n", new_ip);
- setenv("ipaddr", new_ip);}//saveenv();保存环境变量到非失设备中,如:SD,Nnad中
- }
四、应用
上面的函数实现以后, 在系统第一次加载的时候,会重新生成一个随机的MAC地址,根据serverip地址设置ipaddr.我们使用的
lan8710,要设置ethaddr,fec_addr。如果要想将随机生成的MAC地址,IP地址存储到nand或MMC中,则在
setenv("ipaddr", new_ip) 下一行,添加 saveenv()函数调用。