uboot之uboot中环境变量

一、环境变量基础

    1、环境变量的作用

        让我们可以不用修改uboot的源代码,而是通过修改环境变量来影响uboot运行时的一些数据和特性。譬如说通过

        修改bootdelay环境变量就可以更改系统开机自动启动时倒数的秒数。

    2、环境变量优先级

        (1)uboot代码当中有一个值,环境变量中也有一个值。uboot程序实际运行时规则是:如果环境变量为空则使用代

        码中的值;如果环境变量不为空则优先使用环境变量对应的值。

        (2)譬如machid(机器码)。uboot中在x210_sd.h中定义了一个机器码2456,写死在程序中的不能更改。如果要

        修改uboot中配置的机器码,可以修改x210_sd.h中的机器码,但是修改源代码后需要重新编译烧录,很麻烦;比

        较简单的方法就是使用环境变量machid。set machid 0x998类似这样,有了machid环境变量后,系统启动时会优

        先使用machid对应的环境变量,这就是优先级问题。

    3、环境变量在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中的环境变量了。

二、环境变量解析

    1、printenv

        (1)找到printenv命令所对应的函数。通过printenv的help可以看出,这个命令有2种使用方法。第一种直接使用

        不加参数则打印所有的环境变量;第二种是printenv name则只打印出name这个环境变量的值。

        (2)do_printenv函数首先区分argc=1还是不等于1的情况,若argc=1那么就循环打印所有的环境变量出来;如果

        argc不等于1,则后面的参数就是要打印的环境变量,给哪个就打印哪个。

        (3)argc=1时用双重for循环来依次处理所有的环境变量的打印。第一重for循环就是处理各个环境变量。所以有多少

        个环境变量则第一重就执行循环多少圈。

    2、setenv

        (1)命令定义和对应的函数在uboot/common/cmd_nvedit.c中,对应的函数为do_setenv。

        (2)setenv的思路就是:先去DDR中的环境变量处寻找原来有没有这个环境变量,如果原来就有则需要覆盖原来的

        环境变量,如果原来没有则在最后新增一个环境变量即可。

            第1步:遍历DDR中环境变量的数组,找到原来就有的那个环境变量对应的地址。168-174行。

            第2步:擦除原来的环境变量,259-265行

            第3步:写入新的环境变量,266-273行。

     3、saveenv

         (1)在uboot/common/cmd_nvedit.c中,对应函数为do_saveenv

         (2)从uboot实际执行saveenv命令的输出,和x210_sd.h中的配置(#define CFG_ENV_IS_IN_AUTO)可以分析

        出:我们实际使用的是env_auto.c中相关的内容。没有一种芯片叫auto的,env_auto.c中是使用宏定义的方式去

        条件编译了各种常见的flash芯片(如movinand、norflash、nand等)。然后在程序中读取INF_REG(OMpin内

        部对应的寄存器)从而知道我们的启动介质,然后调用这种启动介质对应的操作函数来操作。    

        (3)do_saveenv内部调用env_auto.c中的saveenv函数来执行实际的环境变量保存操作。

        (4)寄存器地址:E010F000+0C=E010_F00C,含义是用户自定义数据。

        (5)真正执行保存环境变量操作的是:cpu/s5pc11x/movi.c中的movi_write_env函数,这个函数肯定是写sd卡,

        将DDR中的环境变量数组(其实就是default_environment这个数组,大小16kb,刚好32个扇区)写入iNand中的

        ENV分区中。

        (6)raw_area_control是uboot中规划iNnad/SD卡的原始分区表,这个里面记录了我们对iNand的分区,env分区

        也在这里,下标是2.追到这一层就够了,再里面就是调用驱动部分的写SD卡/iNand的底层函数了。

    4、getenv

        (1)应该是不可重入的。

        (2)实现方式就是去遍历default_environment数组,挨个拿出所有的环境变量比对name,找到相等的直接返回

        这个环境变量的首地址即可。

    5、getenv_r

        (1)可重入版本。(可自行搜索补充可重入函数的概念)

        (2)getenv函数是直接返回这个找到的环境变量在DDR中环境变量处的地址,而getenv_r函数的做法是找到了DDR

        中环境变量地址后,将这个环境变量复制一份到提供的buf中,而不动原来DDR中环境变量。

        所以差别就是:getenv中返回的地址只能读不能随便乱写,而getenv_r中返回的环境变量是在自己提供的buf中,

        是可以随便改写加工的。

欢迎各位指出不足之处        

猜你喜欢

转载自blog.csdn.net/qq_41003024/article/details/80450156