2015年(6)
分类: LINUX
2015-03-11 16:02:53
首先定义外部环境变量在什么介质上,通过在开发板定义CONFIG_ENV_IS_IN_***选项来指定外部环境变量存储在什么介质,其中***代表外部环境变量的存储介质,例如nand、、mmc等。如果不使用外部环境变量,即定义CONFIG_ENV_IS_NO_WHERE。
内部的环境变量是default_environment[]存储在uboot的镜像里,定义在/common/env_common.c文件里。外部的环境变量可以存储在任何一种介质上,可以和uboot本身的镜像在同一存储介质上,也可以在其他介质上。另外,内部环境变量直接存储,而外部环境变量的前4字节存储的是crc校验码,代码如下。
typedef struct environment_s {
uint32_t crc; /* CRC32 over data bytes */
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
unsigned char flags; /* active/obsolete flags */
#endif
unsigned char data[ENV_SIZE]; /* Environment data */
} env_t;
初始化过程涉及两个函数分别是:函数在board.c的board_init_f和board_init_r函数里调用
l /common/env_***.c文件里的env_init函数,如果没有定义CONFIG_ENV_IS_NO_WHERE,那么对应的/common/env_***.c文件会被编译。否则对应的/common/env_nowhere.c文件会被编译。
l /top_dir/common/env_common.c文件里的env_relocate函数。
1. env_init函数会进行外部环境变量的检测,具体过程是从存储介质上读取数据到指定内存区域,通过env_ptr指针来访问,计算env_ptr->data的crc和env_ptr->crc比较如果相等说明检测到有效的外部环境变量设置gd->env_valid =1,gd->env_addr指向env_ptr->data。否则gd->env_valid =0,gd->env_add=0.
2.第二个初始化函数代码如下,进行环境变量的解析
void env_relocate (void)
{
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
extern void env_reloc(void);
env_reloc();
#endif
if (gd->env_valid == 0) {
#if defined(CONFIG_ENV_IS_NOWHERE) /* Environment not changable */
set_default_env(NULL);
#else
show_boot_progress (-60);
set_default_env("!bad CRC");
#endif
} else {
env_relocate_spec ();
}
}
分为两种情况:
2.1如果gd->env_valid == 0即没有检测到有效的外部环境变量,该情况又分为两种情况,启用了CONFIG_ENV_IS_NO_WHERE选项,和crc校验错误。然后会调用set_default_env函数,其中set_default_env函数的形参给出详细的错误信息。
2.2 如果 gd->env_valid != 0即检测到有效的外部环境变量,然后调用env_relocate_spec ()函数进行重新装载外部环境变量到内存。该函数的具体实现和外部环境变量存储在哪种存储介质有关,因此函数的实现在/common/env_***.c的文件里。
最后set_default_env()和env_relocate_spec ()中的env_import()两个函数都调用了himport_r(struct hsearch_data *htab, const char *env, size_t size, const char sep, int flag)函数,该函数把环境变量放到哈希表,其中第二个参数是环境变量在内存的地址。
如果配置了CONFIG_ENV_IS_NO_WHERE选项,就会一直使用内部的环境变量default_environment[]。