RK3288以太网的mac地址调试笔记【学习笔记】【原创】

平台信息:
内核:linux3.1.0
系统:android/android6.0
平台:RK3288

作者:庄泽彬(欢迎转载,请注明作者)

邮箱:2760715357@qq.com

说明:提供以太网mac地址烧录以及读写的方式

一、功能演示以及说明:

1.1在安卓的文件系统生成如下的设备节点:/sys/kernel/pax_ethernet/mac用于烧录以及读取以太网的mac地址。使用adb命令进行以太网mac地址的烧写以及读写。本质上在使用echo "aa:aa:aa:aa:aa:aa" > /sys/kernel/pax_ethernet/mac这个命令的时候会调用kernel的底层驱动往我们存放的mac地址的分区写入以太网的mac地址。我们的需求是在烧录了以太网的mac地址之后,设备就一直使用我们烧录的mac给网卡设备,不在使用随机数生成mac地址。实现的思路大致如下:在使用adb命令往/sys/kernel/pax_ethernet/mac这个设备节点写入合法的mac地址之后,在重启之后uboot启动的时候会从这烧录mac地址的分区读取烧录mac地址,如果烧录的mac地址合法,就会通过cmdline的机制传递给kernel,kernel的以太网往驱动会解析uboot发送的cmdline,将传递的字符串解析之后,如果合法在赋值给网卡,我在kernel的驱动还做了判断,如果uboot传递的mac地址出错或者读取有异常,kernel会在一次从分区中获取mac地址。好吧,讲了这么多,我们还是看代码是如何实现的吧。

RK3288以太网的mac地址调试笔记【学习笔记】【原创】

二、uboot读取以太网的mac地址以及传递mac地址给kernel的相关代码片段如下:

2.1这部分代码是我封装的用于读取分区中以太网mac地址的读和写的接口

 1 int sp_get_mac(char *value, int len){
 2 
 3     unsigned blocks,offset_blocks;
 4     const disk_partition_t* ptn = get_disk_partition("sp");
 5 
 6     /* strcpy(value,"0123456789"); */
 7     /* return 0; */
 8 
 9     offset_blocks = DIV_ROUND_UP(SP_MAC_OFFSET, RK_BLK_SIZE);
10     /* blocks = DIV_ROUND_UP(len, RK_BLK_SIZE); */
11 
12     if (ptn) {
13         return rkloader_CopyFlash2Memory(value,ptn->start+offset_blocks,1);
14     }
15 
16     return -1;
17 }
18 
19 int sp_set_mac(char *value, int len){
20 
21     unsigned blocks,offset_blocks;
22     const disk_partition_t* ptn = get_disk_partition("sp");
23 
24     offset_blocks = DIV_ROUND_UP(SP_MAC_OFFSET, RK_BLK_SIZE);
25     blocks = DIV_ROUND_UP(len, RK_BLK_SIZE);
26 
27     if (ptn) {
28         StorageEraseBlock(ptn->start+offset_blocks, blocks, 1);
29         return rkloader_CopyMemory2Flash(value,ptn->start+offset_blocks,blocks);
30     }
31 
32     return -1;
33 }

2.2uboot传递给kernel的相关代码片段:

 1     //读取sp分区的mac地址
 2     memset(tbuf,0,sizeof(tbuf));
 3     ret = sp_get_mac(tbuf,64);
 4     if(ret!=0){
 5         tbuf[0]=0;
 6     }else{
 7         if((tbuf[0]==0xff)&&(tbuf[1]==0xff)&&(tbuf[2]==0xff)&&
 8             (tbuf[3]==0xff)&&(tbuf[4]==0xff)&&(tbuf[5]==0xff)){
 9             tbuf[0]=0;
10         }else if((tbuf[0]==0x00)&&(tbuf[1]==0x00)&&(tbuf[2]==0x00)&&
11                     (tbuf[3]==0x00)&&(tbuf[4]==0x00)&&(tbuf[5]==0x00)){
12             tbuf[0]=0;
13         }else{
14             unsigned char tmp[32];
15             memset(tmp,0,32);
16 
17             sprintf(tmp,"%02x:%02x:%02x:%02x:%02x:%02x",tbuf[0],tbuf[1],tbuf[2],tbuf[3],tbuf[4],tbuf[5]);
18             printf("[%s:%d]mac:%s
",__func__,__LINE__,tmp);
19             snprintf(command_line, len,
20                     "%s eth_mac=%s", command_line, tmp);
21         }
22     }
23     tbuf[63]=0;

2.3实验结果如下,具体的代码大家就自己看吧。uboot阶段以及成果读取并且通过cmdline发送mac的地址.

RK3288以太网的mac地址调试笔记【学习笔记】【原创】

 

三、kernel的以太网驱动解析cmdline并赋值给以太网的网卡设备。

3.1kernel解析cmdline的相关代码片段如下:查看下面的图片kernel已经成果的获取uboot传递的mac地址

u_char mac_addr_str[18] = {0};
u_char mac_addr[7] = {0};
static int __init get_mac_addr(char *str)                                                                                                                   
{                                                                                                                                                           
    strncpy(mac_addr_str,str,17);                                                                                                                           
    printk(KERN_ERR"[%s:%d] mac_addr_str = %s",__func__,__LINE__,mac_addr_str);                                                                             
    return 0;                                                                                                                                               
}                                                                                                                                                           
                                                                                                                                                            
//解析cmdline
__setup("eth_mac=",get_mac_addr);                                                                                                                           
                                                                                                                                                            
module_init(stmmac_init);                                                                                                                                   
module_exit(stmmac_exit);       

RK3288以太网的mac地址调试笔记【学习笔记】【原创】

3.2kernel层将传递的mac地址赋值给设备.

u_char char2num(u_char ch)
{   
    switch(ch){
        case 'a':
        case 'A':
            return 10;
            break;
        case 'b':
        case 'B':
            return 11;
            break;
        case 'c':
        case 'C':
            return 12;
            break;
        case 'd':
        case 'D':
            return 13;
            break;
        case 'e':
        case 'E':
            return 14;
            break;
        case 'f':
        case 'F':
            return 15;
            break;
        default:
            return 0;
    }
}
void str2byte(u_char *str, u_char *byte)
{
    int i=0, j=0;
    u_char num, n;
    u_char temp[20] = {0};

    for(i=0; i<17; i++){
        if(str[i] == ':'){
            continue;
        }else{
            temp[j] = str[i];
            j++;
        }
    }
    temp[j]='