uboot中变量env(收集)
Env在u-boot中通常有两种存在方式,在永久性存储介质中(flash、NVRAM等),在SDRAM中。可配置不适用env的永久存储方式,但不常用。U-boot在启动时会将存储在永久性存储介质中的env重新定位到RAM中,这样可以快速访问,同时可以通过saveenv将RAM保存到永久性存储介质中。
相关结构体
env_t定义于include/environment.h中
typedef struct environment_s {
uint32_t crc; /* CRC32 over data bytes */
#ifdef CFG_REDUNDAND_ENVIRONMENT
unsigned char flags; /* active/obsolete flags */
#endif
unsigned char data[ENV_SIZE];
} env_t;
结构说明:
crc是u-boot在保存env的时候加上去的校验头,在第一次启动时一般crc校验会出错,这很正常,因为此时Flash中的数据无效。
data字段保存实际的环境变量。U-boot的env采用name=value”\0”的方式存储,在所有env的最后以“\0\0”表示整个env的结束。新的name=value对总是被添加到env数据块的末尾,当删除一个name=value对时,后面的环境变量将前移,对一个已经存在的环境变量的修改实际上先删除再插入。
env会从flash等存储设备重定位到RAM中,在env的不同实现版本(env_xxx.c)中定义了env_ptr,它指向env在RAM中的位置。u-boot在重定位env后对环境变量的操作都是针对env_ptr。
env_embedded.c-----env和uboot存储于同一块区。
env_nand.c------------env存储在nandflash中。
env_dataflash.c --env存储在dataflash中。
env_eeprom.c --env存储在eeprom中。
env_flash.c --env存储在norflash中。
env_ptr指向环境参数区,系统启动时默认的环境参数default_environment[],定义于common/env_common.c中
uchar default_environment[] = {
61 #ifdef CONFIG_BOOTARGS
62 "bootargs=" CONFIG_BOOTARGS "\0"
63 #endif
64 #ifdef CONFIG_BOOTCOMMAND
65 "bootcmd=" CONFIG_BOOTCOMMAND "\0"
66 #endif
......
127 #if defined(CONFIG_PCI_BOOTDELAY) &&
(CONFIG_PCI_BOOTDELAY > 0)
128 "pcidelay=" MK_STR(CONFIG_PCI_BOOTDELAY) "\0"
129 #endif
130 #ifdef CONFIG_EXTRA_ENV_SETTINGS
131 CONFIG_EXTRA_ENV_SETTINGS
132 #endif
133 "\0"
134 };
参数解释如下:
bootfile 定义缺省的下载文件
bootargs 定义传递给Linux内核的命令行参数
bootcmd 定义自动启动时执行的几条命令
serverip 定义tftp服务器端的IP地址
env_t中除了数据之外还包含校验头,u-boot把env_t的数据指针又保存在另外一个地方,这就是gd_t数据结构(不同平台有不同的gd_t),这里以ARM为例仅列出env相关的部分。
typedef struct
global_data
{
……
unsigned long
env_off;
unsigned long
env_addr;
unsigned long
env_valid; /* checksum of environment valid */
……
} gd_t;
<include/asm-arm/global_data.h>
gd_t.env_addr即指向env_ptr->data。
相关文件
common/env_common.c
供u-boot调用的通用函数接口,它们隐藏了env的不同实现方式,比如dataflash、eeprom、flash等。
common/env_dataflash.c
env存储在dataflash中的实现
common/cmd_nvedit.c
实现u-boot对环境变量的操作命令
environment.c
环境变量以及一些宏定义
env如果存储在flash中还需要flash的支持。
环境变量操作流程
Env初始化
Start_armboot:lib_arm/board.c
*env_init:env_xxx.c(xxx
= nand|flash|eeprom……)
env_relocate:env_common.c
*env_relocate_spec:env_xxx.c
ENV_IS_EMBEDDED:env是否存在于u-boot
TEXT段中。
CFG_ENV_SIZE:env块的大小。
CFG_ENV_IS_IN_NAND:env块是否存在Nand
Flash中。
CFG_ENV_OFFSET:env块在Flash中偏移地址。
env_init
实现env的第一次初始化,对于nand
env(非embedded方式):
env_nand.c:env_int
gd->env_addr =
(ulong)&default_environment[0];
gd-env_valid = 1;
env_relocate
env_common.c:env_relocate
DEBUGE(“%s[%d] offset
= 0x%lx\n”, __FUNCTION__, __LINE__, gd->reloc_off);
env_ptr = (env_t
*)malloc(CFG_ENV_SIZE);
DEBUGE(“%s[%d]
malloced ENV at %p\n”, __FUNCTION__, __LINE__, env_ptr);
env_relocate_spec();
gd->env_addr =
(ulong)&(env_ptr->data);
env_relocate_spec
size_t total;
ret =
readenv(CFG_ENV_OFFSET, (u_char *) env_ptr);
//
nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char
*)env_ptr);
if(ret || total!=
CFG_ENV_SIZE)
return use_default();
if(crc32(0,
env_ptr->data, ENV_SIZE) != env_ptr->crc)
return use_default();
env_relocate_spec的意图就是调用nand_read将环境变量从CFG_ENV_OFFSET处读出,环境变量的大小为CFG_ENV_SIZE(注意CFG_ENV_OFFSET和CFG_ENV_SIZE要和nandflash的块/页边界对齐。读出数据后再调用crc32对env_ptr->data进行校验并与保存在env_ptr->crc的校验码对比,确认数据是否出错。从这里可以看出在系统第一次启动时,Nand
Flash里面没有存储任何环境变量,crc校验肯定出错,当我们保存环境变量后,接下来在启动板子u-boot就不会再报crc32出错了。
saveenv
env_nand.c:saveenv
其调用nand_erase和nand_write进行nand
flash的erase、write。nand_write和nand_erase是nand驱动建构。
env在内存中位置不定。env在内存中的空间是由malloc分配的(env_common.c中的env_relocate()),因此其在内存中的位置是一直变化的。每次系统启动时,env在内存中位置可能都不一样。
环境变量优化
由于u-boot代码通常达到100KB左右,且必须从地址0处开始,按照这样的分配方式(Nandflash结构),我们必须为env分配一块64KB的sector,而实际使用到的可能只是其中几百个字节!u-boot还会为env在RAM中保持一块同样大小的空间,这就造成ROM和RAM空间不必要的浪费。
为了尽可能减少资源浪费,同时保证系统的健壮性,我们可以把env放置在flash中容量最小的sector里。这样,env嵌入(embed)到u-boot的代码段。在common/environment.h中会比较env和monitor的范围,如果确定env位于monitor内,则定义ENV_IS_EMBEDDED。
uboot中变量env(收集)的更多相关文章
- Linux系统——访问U-BOOT环境变量
Linux系统下访问U-BOOT环境变量 移植过U-BOOT的人,都知道:在U-BOOT中存有ENV.但U-BOOT在引导内核启动之后,U-BOOT的生命周期就结束了.那么启动LINUX内核之后,U- ...
- u-boot中环境变量的实现
转载:http://blog.chinaunix.net/uid-28236237-id-3867041.html U-boot中通过环境参数保存一些配置,这些配置可以通过修改环境参数.保存环境参数. ...
- 在linux系统中通过fw_printenv查看和设置u-boot中的环境变量
uboot下可以通过命令访问(printenv)和修改环境变量(setenv),但是如果需要在Linux系统下访问这些数据该怎么办呢?其实uboot早就帮我们想好了. 1.编译fw_printenv ...
- 在uboot中加入cmd_run命令,运行环境变量
在学习uboot的过程中会经常烧录程序,每次都要敲一些下载指令.这样是不是很麻烦,有什么办法能快速的烧写呢.很简单,将需要敲击的指令编译到uboot中,以环境变量的形式存在.但是环境变量很好加,如何运 ...
- U-Boot中的filesize环境变量
U-Boot中的环境命令可以使用$(filesize)来确定刚下载(传输)得到的文件大小. 因为使用类似tftp命令传输文件后,会自动更新filesize环境变量.如:setenv updateroo ...
- u-boot中filesize环境变量【转载】
转载地址:https://blog.csdn.net/fzs333/article/details/48518559 U-Boot中的环境命令可以使用$(filesize)来确定刚下载(传输)得到的文 ...
- vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令
目录 1,前言 2,.env文件的作用 3,配置.env文件 4,配置启动命令 5,获取.env中的全局变量 5,实际用处 1,前言 分享一下vue项目中利用.env文件存储全局环境变量,以及利于项目 ...
- uboot环境变量实现分析
u-boot的环境变量用来存储一些经常使用的参数变量,uboot希望将环境变量存储在静态存储器中(如nand nor eeprom mmc). 其中有一些也是大家经常使用,有一些是使用人员自己定义的, ...
- 在Linux里读取UBOOT环境变量
转载:http://falloutmx.blog.163.com/blog/static/39236020201211145010154/ 可以通过mtd方式读取,也可以用ioremap方式.不过这些 ...
随机推荐
- 面试题 Comparable、Comparator 比较
Comparable 用作默认的比较方式 Comparator 用作自定义的比较方式,当默认的比较方式不适用时或者没有提供默认的比较方式,使用Comparator就非常有用. 像Arrays和Coll ...
- 更改 pandas dataframe 中两列的位置
更改 pandas dataframe 中两列的位置: 把其中的某列移到第一列的位置. 原来的 df 是: df = pd.read_csv('I:/Papers/consumer/codeandpa ...
- 【LeetCode】18. 4Sum (2 solutions)
4Sum Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d ...
- eclipse 垃圾回收器,内存释放
http://zhangrong-0825-163-com.iteye.com/blog/7334071.如何在eclipse里修改web工程的访问路径,步骤如下: 点击web工程——>选择pr ...
- RHEL7虚拟机添加新网卡后,网卡无法启动
RHEL7虚拟机添加新网卡后,网卡无法启动 1.在开启网络时,有错误提示: # systemctl restart network.service Job for network.service fa ...
- Linux中断 - ARM中断处理过程
一.前言 本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件动作.具体整个处理过程分成三个步骤来描述: 1.第二章描述了中断处理的准备过程 2.第三章描述了当发生中的时候 ...
- Python rindex() 方法
描述 Python rindex() 方法返回子字符串最后一次出现在字符串中的索引位置,该方法与rfind() 方法一样,只不过如果子字符串不在字符串中会报一个异常. 语法 rindex() 方法语法 ...
- java 随机日期
java 在某个范围日期内获取一个日期,再以这个日期作为开始日期,获取到随机n天后的日期 /** * 在beginDate和endDate之间获取一个随机日期作为开始日期 * @param begin ...
- Java:多线程,线程池,用Executors静态工厂生成常用线程池
一: newSingleThreadExecutor 创建一个单线程的线程池,以无界队列方式运行.这个线程池只有一个线程在工作(如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它.)此线程池 ...
- 【转】用SQL实现树的查询
树形结构是一类重要的非线性结构,在关系型数据库中如何对具有树形结构的表进行查询,从而得到所需的数据是一个常见的问题.本文笔者以 SQL Server 2000 为例,就一些常用的查询给出了相应的算法与 ...