1、环境变量介绍

uboot中环境变量的作用类似于全局变量,需要某个环境变量的值时调用getenv函数就可以得到。环境变量会指导程序的运行,不必修改代码重新编译,通过修改环境变量就可以改变uboot的的数据和特性。在uboot启动时bootdelay时间内按下按键就可以打断uboot的启动进入控制台,输入printenv命令就可以查看当前的环境变量,setenv可以改变环境变量的值,如果没有saveenv则修改只有本次启动有效,因为修改的是DDR里的那一份环境变量。

2、环境变量在内存中的保存形式

 bootdelay=3`\0`bootcmd=movi read kernel 30008000; movi read rootfs 30B00000 300000; bootm 30008000 30B00000`\0`.........

环境变量是类似于数组,一个接着一个加载在某段内存中,其中该段内存的起始地址保存在全局变量gd->env_addr中。每个环境变量之间以反斜杠零(\0)作为分隔符(也就是字符串的末尾符),在遍历环境变量时去找反斜杠零(\0)就可以将每个环境变量分隔开,而每个环境变量的格式也是固定的,
格式:env=value,再根据等号作为分隔符区分环境变量的名字和数值。只要拿到保存环境变量的内存起始地址,就可以解析出所有的环境变量。

3、默认环境变量和SD卡中的环境变量

环境变量在代码里有一份默认的环境变量,是用数组来实现的;在SD卡/flash等外存也存在一份,uboot会加载到内存中。首先是调用env_init函数,暂时使用默认的环境变量;后续再调用env_relocate函数将SD卡中的那一份环境变量加载到内存中,如果CRC校验通过则将gd->env_addr指向内存中从SD卡处加载的环境变量。由此可见,SD卡中的环境变量优先级高于默认的环境变量。

//初始化默认环境变量,保存在default_environment数组中
int env_init(void)
{gd->env_addr  = (ulong)&default_environment[0];gd->env_valid = 1;return (0);
}char * env_ptr;//从SD卡中重定位环境变量
void env_relocate (void)
{/** We must allocate a buffer for the environment*/env_ptr = (env_t *)malloc (CFG_ENV_SIZE); //申请CFG_ENV_SIZE大小的内存,此时已经初始化了堆管理器,所以可以用mallocDEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);if (gd->env_valid == 0) {puts ("*** Warning - bad CRC, using default environment\n\n");show_boot_progress (-60);set_default_env();}else {env_relocate_spec (); //把外存里的环境变量加载到内存,并将内存起始地址保存在env_ptr->data}gd->env_addr = (ulong)&(env_ptr->data);
}void env_relocate_spec (void)
{uint *magic = (uint*)(PHYS_SDRAM_1);if ((0x24564236 != magic[0]) || (0x20764316 != magic[1]))movi_read_env(virt_to_phys((ulong)env_ptr)); //从外存读取环境变量if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) //crc校验不通过则用默认的环境变量return use_default();
}

4、关键函数的实现思路

前提:从gd->env_addr得到环境变量在内存中的地址,并且uboot中有变量记录当前所有环境变量所占内存大小
(1)printenv思路分析:
以反斜杠零为分隔符解析处各个环境变量,然后通过控制台输出;
(2)setenv思路分析
首先通过以反斜杠零和等号为分隔符,解析处各个环境变量的名字和数值,然后去匹配是否存在要查找的环境变量,如果存在则覆盖掉原来的值;
(3)saveenv思路分析
将内存中的那份环境变量写到SD卡中特定的分区里;
(4)getenv思路分析
首先通过以反斜杠零和等号为分隔符,解析处各个环境变量的名字和数值,然后去匹配是否存在要查找的环境变量,如果存在则返回该环境变量的值;

5、可重入版本和不可重入版本的函数

可重入版本函数的名字就是在不可重入版本函数的名字后面加"_r",因为可重入版本是在不可重入版本后面出现的。不可重入函数,简单理解就是函数不能同时多个地方调用或者同时调用不安全。
(1)char *getenv (char *name);
传入环境变量的名字返回环境变量字符串所在的内存地址;如果修改返回来的环境变量字符串内容,则内存中的环境变量也会被修改,这样不安全。
(2)int getenv_r (char *name, char *buf, unsigned len);
传入环境变量的名字name,缓冲区buf,buf的长度len,返回读取到的环境变量字符串的长度。环境变量的值是保存在buf中,无论你怎么修改buf中保存的环境变量字符串也不会影响内存中的环境变量。

6、补充

在SD卡中会预留出分区来保存环境变量,在uboot的配置文件里会用宏定义来指定环境变量保存在SD卡里起始块和块数量的信息。参见博客:《uboot中环境变量的加载、写入过程详解》;

uboot中环境变量的实现相关推荐

  1. uboot中环境变量的加载、写入过程详解

    1.uboot启动中环境变量的加载 1.1.uboot加载环境变量流程分析 (1)首先使用默认的环境变量default_environment[]: (2)然后加载SD卡中env分区的环境变量,校验读 ...

  2. uboot中环境变量 sf

    这个命令是 uboot实现了 对flash 的读写初始化功能,挂载在spi总线下: 执行sf probe 就是对spi总线和 flash的初始化: 命令声明: u_BOOT_CMD大家都知道就是定义u ...

  3. uboot默认环境变量修改

    uboot的默认环境变量决定了系统是通过何种方式启动的,对于定制化的嵌入式系统,uboot的定制化修改也是必要的. uboot有两种修改方式: 1.直接修改源码或者修改uboot配置 2.在uboot ...

  4. 从bootm 命令讲起/U-boot的环境变量: bootcmd 和bootargs

    从bootm 命令讲起 1 找到linux的内核入口 Bootm命令通过读取uImage的头部0×40字节的信息,将uImage定位到正确的地址,同时找到linux的内核入口地址. 这个地方就涉及到u ...

  5. uboot的环境变量

    注:本文是学习朱老师课程整理的笔记,基于uboot-1.3.4和s5pc11x分析. 环境变量的作用 可以不用修改uboot的源代码,而是通过修改环境变量来影响uboot运行时的一些数据和特性.譬如说 ...

  6. uboot之环境变量

    一.环境变量基础知识 1.环境变量的作用 环境变量的最大作用就是在我们不需要改变源代码的情况下,改变程序的执行情况.比如我们的bootdelay时间,通过修改对应的环境变量的值,就可以改变uboot开 ...

  7. java se环境变量设置_JavaSE中环境变量的配置

    在说Java中环境变量配置之前,还是先说说JDK和JRE吧. JRE(Java Runtime Environment),即Java的运行环境.主要包括JVM(Java Virtual Machine ...

  8. setlocal启动批处理文件中环境变量的本地化

    setlocal启动批处理文件中环境变量的本地化 在执行 SETLOCAL 之后所做的环境改动只限于批处理文件.要还原原先的设置,必须执行 ENDLOCAL. 学习了:https://baike.ba ...

  9. bashrc文件中环境变量配置错误,导致linux命令无法正常使用的解决方案

    分析原因 bashrc文件中环境变量配置错误,导致linux无法正常使用. 其实解决问题的方法很简单:把你在bashrc文件中写错的东西注释掉或者改写正确即可. 可是此时图形界面登陆不了,vim用不了 ...

最新文章

  1. SQL Server 索引结构及其使用(二)
  2. UVA - 10859 Placing Lampposts 放置街灯
  3. emacs c语言 自动补全,Emacs 与 C/C++ 代码自动补全
  4. nssl1319-埃雷萨拉斯寻宝【SPFA,建图】
  5. 语法推导树之短语,直接短语,句柄
  6. lucene 增量 全量 更新索引_搜索引擎:该如何设计你的倒排索引?
  7. ElasticSearch遇到问题
  8. 【转载】深入分析 ThreadLocal 内存泄漏问题
  9. Java基础,双色球系统实现,完整版本,没有BUG,完整代码版
  10. 中原工学院计算机组成原理试卷,中原工学院计算机组成原理试卷.doc
  11. 计算机专业复试有英语口语吗,计算机考研复试英语口语技巧
  12. 彐一夕儿本铺_2019-10-16汉字宫目录
  13. python 空数组_Python笔记
  14. 构建MRCP服务器,使得FreeSWITCH基于mod_unimrcp与科大讯飞进行tts和asr通信
  15. 游戏运营的十二大组成
  16. Robomaster视觉组成长之路
  17. Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:2.17:check (checkstyle-vali
  18. K-means算法及文本聚类实践
  19. 【前端面试题】原型和原型链-js
  20. 2022年湖南省证券从业资格(证券投资基金)练习题及答案

热门文章

  1. 程序计数器、指令寄存器的区别
  2. 数据库之oracle学习(一)
  3. python对三维数组切片
  4. oracle wip 拆解工单 操作_ORACLE成本管理中WIP处理对成本计算的影响
  5. linux操作系统的文件名最大长度为,linux下文件数、目录数、文件名长度的各种限制...
  6. Flink SQL客户端
  7. java比较器参数只传进去一个_post请求springMVC后台,只传一个参数,后台用一个字符串接受,参数名对应,但入参却为null,求讲解和解决,谢谢...
  8. 【Linux】在命令行中查看Linux内核版本的几种方法
  9. Python pygame(GUI编程)模块最完整教程(5)
  10. Java实现mds降维_ISOMAP和MDS降维