这一篇我们来讲一下uboot中环境变量的使用。
按照代码的流程依次来讲,首先执行的跟环境变量相关的函数是env_init
---board.c
int env_init(void)
{
gd->env_addr = (ulong)&default_environment[0];
gd->env_valid = 1;
return (0);
}
可以看到环境变量一开始是硬编码到版本中的。
uchar default_environment[] = {
#ifdef CONFIG_BOOTARGS
"bootargs=" CONFIG_BOOTARGS "\0"
#endif
#ifdef CONFIG_BOOTCOMMAND
"bootcmd=" CONFIG_BOOTCOMMAND "\0"
#endif
.
.
.
};
从default_environment可以看出,每个环境变量是字符数组的中的一段,每个环境变量以“\0”分割。这样后面获取环境变量时,实际上就是从字符数组中取出对应部分。比如:
static int init_baudrate (void)
{
char tmp[64]; /* long enough for environment variables */
int i = getenv_r ("baudrate", tmp, sizeof (tmp));
......
}
接着,在NAND FLASH初始化以后,我们会将存储在FLASH中的环境变量,复制到Memory中:
--env_common.c
void env_relocate (void)
{
env_ptr = (env_t *)malloc (CFG_ENV_SIZE);/*分配*/
/*
* After relocation to RAM, we can always use the "memory" functions
*/
env_get_char = env_get_char_memory;
env_relocate_spec ();
gd->env_addr = (ulong)&(env_ptr->data);
}
至此我们获取环境变量的途径就变成了从内存中读取。总得来看,获取环境变量分为两个阶段。
第一阶段:从字符数组default_environment中获取
第二阶段:NAND初始化后,复制相关内容到内存中,可从内存中获取
那么在uboot的代码中是如何将这两种方式统一实现的呢?
请看下面,在定义default_environment时,对env_get_char函数指针进行了初始化。
env_common.c
uchar (*env_get_char)(int) = env_get_char_init;
NAND FLASH初始化后,在env_relocate中重新对env_get_char进行了赋值
env_common.c
env_get_char = env_get_char_memory;
可以看出在FLASH中的环境变量被复制到内存之前,我们利用env_get_char_init
直接从全局数组default_environment获取,环境变量重定位以后,利用env_get_char_memory实现获取。
简而言之,通过改变函数指针的指向做到了区分,因此我们能联想到以下内容
- 保存到FLASH中的环境变量,只有NAND可用时,才能获取成功
- setenv,saveenv设置保存环境变量,是保存FLASH中的
这一篇内容讲到这里结束。至此,uboot的相关内容差不多也该完结了,以后根据具体情况可能会有补充。然后呢,我会花至少一年的时间做一系列关于内核的文章,敬请期待吧!!
最后提前祝大家2018年新年快乐,工作顺利。