uboot----getenv_IPaddr代码解析

转载地址: http://blog.csdn.net/cocoalary/article/details/46583697

这几天看uboot,感觉getenv函数里嵌套了很多其他函数,一直没搞清是怎么实现get的。今天终于领会了,把它记下来,供大家一起学习。

                我研究的是IPaddr的环境变量如何get的,其实就是 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");该如何分析。先找到getenv_IPaddr函数:

[html]  view plain  copy
  1. typedef ulong  IPaddr_t;  
[html]  view plain  copy
  1. IPaddr_t getenv_IPaddr (char *var)  
  2. {  
  3.     return (string_to_ip(getenv(var)));  

                getenv_IPaddr函数使用字符串"ipaddr"做为参数,返回一个ulong型整数。再看getenv函数:

[html]  view plain  copy
  1. char *getenv (char *name)  
  2. {  
  3.     int i, nxt;  
  4.   
  5.     WATCHDOG_RESET();  
  6.   
  7.     for (i=0; env_get_char(i) != '\0'; i=nxt+1) {  
  8.         int val;  
  9.   
  10.         for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {  
  11.             if (nxt >= CFG_ENV_SIZE) {  
  12.                 return (NULL);  
  13.             }  
  14.         }  
  15.         if ((val=envmatch((uchar *)name, i)) < 0)  
  16.             continue;  
  17.         return ((char *)env_get_addr(val));  
  18.     }  
  19.   
  20.     return (NULL);  
  21. }  

          getenv 是一个指针函数,返回字符型指针。为什么会返回字符型指针?后面再说。getenv 函数的参数是字符指针变量name,实参就是“ipaddr"。从这里开始出现了一大堆莫名其妙的函数env_get_char,envmatch,env_get_addr。在分析getenv 之前,还得先把这些其他的函数搞清楚。首先看env_get_char:

[html]  view plain  copy
  1. uchar (*env_get_char)(int) = env_get_char_init;  
[html]  view plain  copy
  1. static uchar env_get_char_init (int index)  
  2. {  
  3.     uchar c;  
  4.   
  5.     /* if crc was bad, use the default environment */  
  6.     if (gd->env_valid)  
  7.     {  
  8.         c = env_get_char_spec(index);  
  9.     } else {  
  10.         c = default_environment[index]; //返回default_environment指定位置的字符  
  11.     }  
  12.   
  13.     return (c);  
  14. }  

        env_get_char和env_get_char_init等效,参数为int,返回default_environment指定位置的字符。default_environment是定义了一系列缺省的环境变量值。以IP地址为例

[html]  view plain  copy
  1. #ifdef  CONFIG_IPADDR  
  2.     "ipaddr="   MK_STR(CONFIG_IPADDR)       "\0"  
  3. #endif  
[html]  view plain  copy
  1. #define CONFIG_IPADDR           192.168.1.230  

结果是  "ipaddr=192.168.1.230”+"\0"

再看envmatch:

[html]  view plain  copy
  1. static int  
  2. envmatch (uchar *s1, int i2)  
  3. {  
  4.   
  5.     while (*s1 == env_get_char(i2++))  
  6.         if (*s1++ == '=')  
  7.             return(i2);  
  8.     if (*s1 == '\0' && env_get_char(i2-1) == '=')  
  9.         return(i2);  
  10.     return(-1);  
  11. }  

           我开始一直搞不清envmatch 是如何比较的。现在搞清楚了,它是在比较“ipaddr"和"ipaddr=192.168.1.230”。while (*s1 == env_get_char(i2++)) 就是从default_environment字符串的指定位置开始比较,指定位置由env_get_char返回值所定,比较不一致时函数返回-1。当比较到default_environment字符串的IPaddr时,开始有相同的字符出现了,这时while值为1,依次比较i,p,a,d,d,r字符,因为每比较一次,S1(“ipaddr")和i2的值都加1,即指向下一个字符。当比较完"r"后,指针指向了下一个字符即"=", "="之后的字符串正是我们需要的,所以return(i2),i2是赋给val的,下一步就是env_get_addr(val)。

[html]  view plain  copy
  1. uchar *env_get_addr (int index)  
  2. {  
  3.     if (gd->env_valid) {  
  4.         return ( ((uchar *)(gd->env_addr + index)) );  
  5.     } else {  
  6.         return (&default_environment[index]);  
  7.     }  
  8. }  

             找到了val的值,也就是ipaddr在default_environment中所处的位置,即可以返回ipaddr字符串的地址。前面说为什么会返回字符型指针?这里给出了答案。注意:这里返回的是指针,是192.168.1.230的地址,确切地说是"1"的指针地址。

             我们再返回char *getenv (char *name) 函数,其返回值也就192.168.1.230的地址, 这个地址是string_to_ip函数的地址。

[html]  view plain  copy
  1. IPaddr_t string_to_ip(char *s)  
  2. {  
  3.     IPaddr_t addr;  
  4.     char *e;  
  5.     int i;  
  6.   
  7.     if (s == NULL)  
  8.         return(0);  
  9.   
  10.     for (addr=0i=0; i<4; ++i) {  
  11.         ulong val = s ? simple_strtoul(s, &e, 10) : 0;  
  12.         addr <<= 8;  
  13.         addr |= (val & 0xFF);  
  14.         if (s) {  
  15.             s = (*e) ? e+1 : e;  
  16.         }  
  17.     }  
  18.   
  19.     return (htonl(addr));  
  20. }  

        string_to_ip函数将字符串192.168.1.230转化成整数,关键的地方是for (addr=0, i=0; i<4; ++i),这里可以看出进行了四次转化,分别是四个段。但是函数simple_strtoul是如何区分"."而分成四个段? 这是靠simple_strtoul中的while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) ? toupper(*cp) : *cp)-'A'+10) < base)实现的,因为当while遇到"."时,判定条件即为0,就不再判定而往下走了。四个段都操作完成,就出现了addr = (((((192 << 8) | 168) << 8) | 1) << 8 ) | 230,

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值