uboot环境变量实现分析
来源:互联网 发布:rt809f编程器怎么安装 编辑:程序博客网 时间:2024/05/17 02:29
转自:http://blog.csdn.net/skyflying2012/article/details/39005705#comments
原创作者分析的很到位,非常感谢!
u-boot的环境变量用来存储一些经常使用的参数变量,uboot希望将环境变量存储在静态存储器中(如nand nor eeprom mmc)。
其中有一些也是大家经常使用,有一些是使用人员自己定义的,更改这些名字会出现错误,下面的表中我们列出了一些常用的环境变量:
bootdelay 执行自动启动的等候秒数
baudrate 串口控制台的波特率
netmask 以太网接口的掩码
ethaddr 以太网卡的网卡物理地址
bootfile 缺省的下载文件
bootargs 传递给内核的启动参数
bootcmd 自动启动时执行的命令
serverip 服务器端的ip地址
ipaddr 本地ip 地址
stdin 标准输入设备
stdout 标准输出设备
stderr 标准出错设备
上面这些是uboot默认存在的环境变量,uboot本身会使用这些环境变量来进行配置。我们可以自己定义一些环境变量来供我们自己uboot驱动来使用。
Uboot环境变量的设计逻辑是在启动过程中将env从静态存储器中读出放到RAM中,之后在uboot下对env的操作(如printenv editenv setenv)都是对RAM中env的操作,只有在执行saveenv时才会将RAM中的env重新写入静态存储器中。
这种设计逻辑可以加快对env的读写速度。
基于这种设计逻辑,2014.4版本uboot实现了saveenv这个保存env到静态存储器的命令,而没有实现读取env到RAM的命令。
那我们就来看一下uboot中env的数据结构 初始化 操作如何实现的。
一 env数据结构
在include/environment.h中定义了env_t,如下:
CONFIG_ENV_SIZE是我们需要在配置文件中配置的环境变量的总长度。
这里我们使用的nand作为静态存储器,nand的一个block是128K,因此选用一个block来存储env,CONFIG_ENV_SIZE为128K。
Env_t结构体头4个bytes是对data的crc校验码,没有定义CONFIG_SYS_REDUNDAND_ENVIRONMENT,所以后面紧跟data数组,数组大小是ENV_SIZE.
ENV_SIZE是CONFIG_ENV_SIZE减掉ENV_HEADER_SIZE,也就是4bytes,
所以env_t这个结构体就包含了整个我们规定的长度为CONFIG_ENV_SIZE的存储区域。
头4bytes是crc校验码,后面剩余的空间全部用来存储环境变量。
需要说明的一点,crc校验码是uboot中在saveenv时计算出来,然后写入nand,所以在第一次启动uboot时crc校验会出错,
因为uboot从nand上读入的一个block数据是随机的,没有意义的,执行saveenv后重启uboot,crc校验就正确了。
data 字段保存实际的环境变量。u-boot 的 env 按 name=value”\0”的方式存储,在所有env 的最后以”\0\0”表示整个 env 的结束。
新的name=value 对总是被添加到 env 数据块的末尾,当删除一个 name=value 对时,后面的环境变量将前移,对一个已经存在的环境变量的修改实际上先删除再插入。
u-boot 把env_t 的数据指针还保存在了另外一个地方,这就
是 gd_t 结构(不同平台有不同的 gd_t 结构 ),这里以ARM 为例仅列出和 env 相关的部分
二 env的初始化
uboot中env的整个架构可以分为3层:
(1) 命令层,如saveenv,setenv editenv这些命令的实现,还有如启动时调用的env_relocate函数。
(2) 中间封装层,利用不同静态存储器特性封装出命令层需要使用的一些通用函数,如env_init,env_relocate_spec,saveenv这些函数。实现文件在common/env_xxx.c
(3) 驱动层,实现不同静态存储器的读写擦等操作,这些是uboot下不同子系统都必须的。
按照执行流顺序,首先分析一下uboot启动的env初始化过程。
首先在board_init_f中调用init_sequence的env_init,这个函数是不同存储器实现的函数,nand中的实现如下:
从注释就基本可以看出这个函数的作用,因为env_init要早于静态存储器的初始化,所以无法进行env的读写,这里将gd中的env相关变量进行配置,
默认设置env为valid。方便后面env_relocate函数进行真正的env从nand到ram的relocate。
继续执行,在board_init_r中,如下:
这是在所有存储器初始化完成后执行的。
首先调用should_load_env,如下:
从注释可以看出,CONFIG_OF_CONTROL没有定义,鉴于考虑安全性问题,如果我们想要推迟env的load,可以定义CONFIG_DELAY_ENVIRONMENT,这里返回0,就调用set_default_env使用默认的env,默认env是在配置文件中CONFIG_EXTRA_ENV_SETTINGS设置的。
我们可以在之后的某个地方在调用env_relocate来load env。这里我们选择在这里直接load env。所以没有定义CONFIG_DELAY_ENVIRONMENT,返回1。调用env_relocate。
在common/env_common.c中:
Gd->env_valid在之前的env_init中设置为1,所以这里调用env_relocate_spec,
这个函数也是不同存储器的中间封装层提供的函数,对于nand在common/env_nand.c中,如下:
首先定义一个长度为CONFIG_ENV_SIZE的buf,然后调用readenv,
CONFIG_ENV_OFFSET是在配置文件中定义的env在nand中偏移位置。我们这里定义的是在4M的位置。
Readenv也在env_nand.c中,如下:
Readenv函数利用nand_info[0]对nand进行读操作,读出指定位置,指定长度的数据到buf中。Nand_info[0]是一个全局变量,来表征第一个nand device,这里在nand_init时会初始化这个变量。Nand_init必须在env_relocate之前。
回到env_relocate_spec中,buf读回后调用env_import,如下:
首先将buf强制转换为env_t类型,然后对data进行crc校验,跟buf中原有的crc对比,不一致则使用默认env。
最后调用himport_r,该函数将给出的data按照‘\0’分割填入env_htab的哈希表中。
之后对于env的操作,如printenv setenv editenv,都是对该哈希表的操作。
Env_relocate执行完成,env的初始化就完成了。
三 env的操作实现
Uboot对env的操作命令实现在common/cmd_nvedit.c中。
对于setenv printenv editenv这3个命令,看其实现代码,都是对relocate到RAM中的env_htab的操作,这里就不再详细分析了,重点来看一下savenv实现。
在do_env_save调用saveenv,这个函数是不同存储器实现的封装层函数。对于nand,在common/env_nand.c中,如下:
定义env_t类型的变量env_new,准备来存储env。
利用函数hexport_r对env_htab操作,读取env内容到env_new->data,
校验data,获取校验码env_new->crc。
最后调用erase_and_write_env将env_new先擦后写入由location定义的偏移量和长度的nand区域中。
这样就完成了env写入nand的操作。在savenv readenv函数以及printenv setenv的实现函数中涉及到的函数himport_r hexport_r hdelete_r hmatch_r都是对env_htab哈希表的一些基本操作函数。
这些函数都封装在uboot的lib/hashtable.c中,这里就不仔细分析这些函数了。
- uboot环境变量实现分析
- uboot环境变量实现分析
- uboot环境变量实现分析
- uboot环境变量实现分析
- uboot环境变量实现分析
- uboot环境变量实现分析
- uboot环境变量实现分析
- uboot 源码分析(2)uboot 环境变量实现简析
- 【驱动】uboot环境变量分析
- uboot 环境变量实现简析
- uboot 环境变量实现简析
- uboot 环境变量实现简析
- uboot-命令实现分析
- uboot命令分析+实现
- uboot笔记:uboot命令分析+实现
- uboot环境变量的实现和读取设置
- uboot环境变量的实现和读取设置
- uboot 环境变量
- Centos IP、DNS设置
- django创建project报错 ImportError: No module named dajango.core.management
- Eclipse左侧的工程目录不见了
- php中读取文件内容的几种方法
- css是什么?css是和js一样的作用于最终html页面的技术
- uboot环境变量实现分析
- 4月问题pop-up合集
- 怎么在大批量数据中找出某一行数据
- Android AOP之字节码插桩
- 【Java学习笔记】05.数组、方法和方法重载
- ACM-二叉树
- 第八届蓝桥杯分巧克力
- 注解方式过滤器(Filter)不能过滤Servlet的问题
- Jsoup解析HTML