admin 管理员组文章数量: 887021
uboot
这几天看uboot,感觉getenv函数里嵌套了很多其他函数,一直没搞清是怎么实现get的。今天终于领会了,把它记下来,供大家一起学习。
我研究的是IPaddr的环境变量如何get的,其实就是 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");该如何分析。先找到getenv_IPaddr函数:
typedef ulong IPaddr_t;
IPaddr_t getenv_IPaddr (char *var)
{return (string_to_ip(getenv(var)));
getenv_IPaddr函数使用字符串"ipaddr"做为参数,返回一个ulong型整数。再看getenv函数:
char *getenv (char *name)
{int i, nxt;WATCHDOG_RESET();for (i=0; env_get_char(i) != '\0'; i=nxt+1) {int val;for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {if (nxt >= CFG_ENV_SIZE) {return (NULL);}}if ((val=envmatch((uchar *)name, i)) < 0)continue;return ((char *)env_get_addr(val));}return (NULL);
}
getenv 是一个指针函数,返回字符型指针。为什么会返回字符型指针?后面再说。getenv 函数的参数是字符指针变量name,实参就是“ipaddr"。从这里开始出现了一大堆莫名其妙的函数env_get_char,envmatch,env_get_addr。在分析getenv 之前,还得先把这些其他的函数搞清楚。首先看env_get_char:
uchar (*env_get_char)(int) = env_get_char_init;
static uchar env_get_char_init (int index)
{uchar c;/* if crc was bad, use the default environment */if (gd->env_valid){c = env_get_char_spec(index);} else {c = default_environment[index]; //返回default_environment指定位置的字符}return (c);
}
env_get_char和env_get_char_init等效,参数为int,返回default_environment指定位置的字符。default_environment是定义了一系列缺省的环境变量值。以IP地址为例
#ifdef CONFIG_IPADDR"ipaddr=" MK_STR(CONFIG_IPADDR) "\0"
#endif
#define CONFIG_IPADDR 192.168.1.230
结果是 "ipaddr=192.168.1.230”+"\0"
再看envmatch:
static int
envmatch (uchar *s1, int i2)
{while (*s1 == env_get_char(i2++))if (*s1++ == '=')return(i2);if (*s1 == '\0' && env_get_char(i2-1) == '=')return(i2);return(-1);
}
我开始一直搞不清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)。
uchar *env_get_addr (int index)
{if (gd->env_valid) {return ( ((uchar *)(gd->env_addr + index)) );} else {return (&default_environment[index]);}
}
找到了val的值,也就是ipaddr在default_environment中所处的位置,即可以返回ipaddr字符串的地址。前面说为什么会返回字符型指针?这里给出了答案。注意:这里返回的是指针,是192.168.1.230的地址,确切地说是"1"的指针地址。
我们再返回char *getenv (char *name) 函数,其返回值也就是192.168.1.230的地址, 这个地址是string_to_ip函数的地址。
IPaddr_t string_to_ip(char *s)
{IPaddr_t addr;char *e;int i;if (s == NULL)return(0);for (addr=0, i=0; i<4; ++i) {ulong val = s ? simple_strtoul(s, &e, 10) : 0;addr <<= 8;addr |= (val & 0xFF);if (s) {s = (*e) ? e+1 : e;}}return (htonl(addr));
}
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,
本文标签: uboot
版权声明:本文标题:uboot 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1686584823h13515.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论