uboot的环境变量基础
环境变量的作用
(1)让我们可以不用修改uboot的源代码,而是通过修改环境变量来影响uboot运行时的一些数据和特性。譬如说通过修改bootdelay环境变量就可以更改系统开机自动启动倒数的秒数。
环境变量的优先级
(1)uboot代码当中有一个值,环境变量中也有一个值。uboot程序实际运行时规则是:如果环境变量为空则使用代码中的值;如果环境变量不为空则有限使用环境变量对应的值。
(2)譬如machid(机器码)。uboot中在x210_sd.h中定义了一个机器码2456.写死在程序当中了。如果想要修改uboot中配置的机器码,可以修改x210_sd.h中的机器码,但是修改源代码后需要重新编译烧录,很麻烦;比较简单的方法就是使用环境变量machid。set machid 098类似的,有了machid环境变量后,系统启动时会优先使用machid对应的环境变量,这就是优先级问题。
环境变量在uboot中工作方式
(1)默认环境变量,在uboot/common/env_common.c中default_environment,这东西本质是一个字符数组,大小为CFG_ENV_SIZE(16KB),里面内容就是很多个环境变量连续分布组成的,每个环境变量最末端以"\0"结束。
(2)SD卡环境变量分区,在uboot的raw分区中。SD卡其实就是给了个分区,专门用来存储而已。存储时其实把DDR中的环境变量整体的写入SD卡中分区里。所以当我们saveenv时其实整个所有的环境变量都被保存了一遍,而不是只保存更改了的。
(3)DDR中环境变量,在default_environment中,实质是字符数组。在uboot中其实是一个全局变量,链接时在数据段,重定位时default_environment就被重定位到DDR中一个内存地址处了。这个地址处这个全局字符数组就是我们uboot运行时的DDR中的环境变量了。
总结:刚烧录的系统中环境变量分区是空白的,uboot第一次运行时加载的是uboot代码中自带的一份环境变量,叫默认环境变量。我们在saveenv是DDR中的环境变量会被更新到SD卡的环境变量中。就可以被保存下来,下次开机会在环境变量relocate时会SD卡中的环境变量会被加载到DDR中去。
default_environment中的内容虽然被uboot源代码初始化为一定的值(这个值就是我们的默认环境变量),但是在uboot启动的第二阶段,env_relocate时代码会去判断SD卡中的env分区的crc是否通过。如果crc校验通过说明SD卡中有正确的环境变量存储,则relocate函数会从SD卡读取环境变量来覆盖default_environment字符数组,而每次开机可以保持上一次更改过得环境变量。
环境变量相关命令源码分析–Cmd_nvedit.c
环境变量先关命令源码解析
(1)找到printfenv命令所对应的函数。通过printfenv的help可以看出,这个命令有2种使用方法。第一种直接使用不加参数则打印所有的环境变量;第二种是printenv name 则只打印出name这个环境变量的值。
(2)分析do_printenv函数
(3)do_printenv函数首先区分argc=1还是=2的情况,若argc=1那么就循环打印所有的环境变量出来;如果argc不等于1,则后面的参数就是要打印的环境变量,给哪个就打印哪个。
(4)argc=1时用双重for循环来依次处理所有的环境变量的打印。第一重for循环就是处理各个环境变量。所以有多个环境变量则第一重就执行循环多少圈!
(5)这个函数要看懂,首先明白整个环境变量在内存中如何存储的问题
(6)关键点:第一要明白环境变量在内存中存储的方式。第二要C语言处理字符串的功底要好。
int do_printenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int i, j, k, nxt;int rcode = 0;if (argc == 1) {
/* Print all env variables */for (i=0; env_get_char(i) != '\0'; i=nxt