以下内容源于朱有鹏嵌入式课程的学习,如有侵权,请告知删除。

参考资料:http://www.cnblogs.com/biaohc/p/6398515.html。

一、uboot的环境变量基础

1、环境变量的作用

  • 在不改变源码、不用重新编译的情况下,可以通过设置环境变量的值来改变uboot的一些设置,如bootdelay时间、机器码的值等等。

2、环境变量的优先级

(1)uboot代码当中有一个值,SD卡中环境变量分区也有一个值。

  • uboot程序实际运行时规则是:如果环境变量分区为空则使用uboot代码中的值;如果环境变量分区不为空则优先使用环境变量分区对应的值。

(2)譬如machid(机器码)。

  • uboot中在x210_sd.h中定义了一个机器码2456,写死在程序中的不能更改(如果要修改,则要重新编译烧录);
  • SD卡的环境变量分区中也有machid;
  • 由于SD卡的环境变量分区中也有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中的环境变量。

(4)总结

  • SD卡的环境变量分区一开始是空白的,uboot第一次运行时加载的是uboot代码中的那份环境变量,叫默认环境变量。
  • 在saveenv时,DDR中的环境变量会被更新到SD卡的环境变量分区中。下次开机在环境变量relocate时,会将SD卡中的环境变量加载到DDR中去。
  • default_environment中的内容虽然被uboot源代码初始化为一定的值,但是在env_relocate时,代码会把环境变量从SD卡中拷贝到内存中,然后去判断SD卡中的env分区的crc是否通过,如果不通过则使用default_environment字符数组,通过了使用SD卡内的环境变量。

4、环境变量的初始化

(1)没有初始化flash设备前,进行环境变量初级初始化

  • 函数env_init定义在commen/env_movi.c中;
  • 把gd全局变量中的 env_valid = 1; env_addr = 全局变量default_enviroment数组的首地址。

(2)初始化flash设备之后

  • 初始化flash后,进行环境变量的重定位工作,即把环境变量从flash中copy到内存中,用一个全局变量env_ptr指向这段内存;
  • 复制是通过movi_read_env这个函数实现的,实际就是把sd卡中环境变量分区全部复制到env_ptr指向的这段内存中;
  • 然后在对这段内存中的环境变量进行crc校验,如果失败的话,则把default_enviroment中的环境变量复制到这里。
  • env_ptr = (env_t *)malloc (CFG_ENV_SIZE); 这句代码作用是给uboot环境变量开辟一块16k大小的内存;
  • env_relocate_spec ();这句代码的作用是把sd卡中的uboot环境变量整个分区复制到开辟的这个内存地址处;
  • 见博客http://blog.csdn.net/oqqhutu12345678/article/details/69365347的(四2)。

代码跟踪:env_relocate_spec ()函数:



  • 输出*** Warning - bad CRC or moviNAND, using default environment:;
  • 清0环境变量内存,把default_environment中的值复制到环境变量内存;
  • 计算crc,写入内存中的crc位;
  • 设置gd中的env_valid为1;

二、环境变量相关命令源码解析(举例)

1、printenv,实现函数为do_printfenv

  • do_printenv函数首先区分是否argc=1,若argc=1则循环打印所有的环境变量出来,否则后面的参数就是要打印的环境变量,给哪个就打印哪个。
  • argc=1时,用双重for循环来依次处理所有的环境变量的打印。第一重for循环就是处理各个环境变量,所以有多少个环境变量则第一重就执行循环多少圈。
  • 要明白整个环境变量在内存中如何存储的问题。

2、setenv命令,实际调用的是_do_setenv函数

int _do_setenv (int flag, int argc, char *argv[])
{int   i, len, oldval;int   console = -1;uchar *env, *nxt = NULL;char *name;bd_t *bd = gd->bd;uchar *env_data = env_get_addr(0);if (!env_data)    /* need copy in RAM */return 1;name = argv[1];if (strchr(name, '=')) {printf ("## Error: illegal character '=' in variable name \"%s\"\n", name);return 1;}/** search if variable with this name already exists*/oldval = -1;for (env=env_data; *env; env=nxt+1) {for (nxt=env; *nxt; ++nxt);if ((oldval = envmatch((uchar *)name, env-env_data)) >= 0)break;}/** Delete any existing definition*/if (oldval >= 0) {/* Check for console redirection */if (strcmp(name,"stdin") == 0) {console = stdin;} else if (strcmp(name,"stdout") == 0) {console = stdout;} else if (strcmp(name,"stderr") == 0) {console = stderr;}if (console != -1) {if (argc < 3) {        /* Cannot delete it! */printf("Can't delete \"%s\"\n", name);return 1;}/* Try assigning specified device */if (console_assign (console, argv[2]) < 0)return 1;#ifdef CONFIG_SERIAL_MULTIif (serial_assign (argv[2]) < 0)return 1;
#endif}/** Switch to new baudrate if new baudrate is supported*/if (strcmp(argv[1],"baudrate") == 0) {int baudrate = simple_strtoul(argv[2], NULL, 10);int i;for (i=0; i<N_BAUDRATES; ++i) {if (baudrate == baudrate_table[i])break;}if (i == N_BAUDRATES) {printf ("## Baudrate %d bps not supported\n",baudrate);return 1;}printf ("## Switch baudrate to %d bps and press ENTER ...\n",baudrate);udelay(50000);gd->baudrate = baudrate;serial_setbrg ();udelay(50000);for (;;) {if (getc() == '\r')break;}}if (*++nxt == '\0') {if (env > env_data) {env--;} else {*env = '\0';}} else {for (;;) {*env = *nxt++;if ((*env == '\0') && (*nxt == '\0'))break;++env;}}*++env = '\0';}#ifdef CONFIG_NET_MULTIif (strncmp(name, "eth", 3) == 0) {char *end;int   num = simple_strtoul(name+3, &end, 10);if (strcmp(end, "addr") == 0) {eth_set_enetaddr(num, argv[2]);}}
#endif/* Delete only ? */if ((argc < 3) || argv[2] == NULL) {env_crc_update ();return 0;}/** Append new definition at the end*/for (env=env_data; *env || *(env+1); ++env);if (env > env_data)++env;/** Overflow when:* "name" + "=" + "val" +"\0\0"  > ENV_SIZE - (env-env_data)*/len = strlen(name) + 2;/* add '=' for first arg, ' ' for all others */for (i=2; i<argc; ++i) {len += strlen(argv[i]) + 1;}if (len > (&env_data[ENV_SIZE]-env)) {printf ("## Error: environment overflow, \"%s\" deleted\n", name);return 1;}while ((*env = *name++) != '\0')env++;for (i=2; i<argc; ++i) {char *val = argv[i];*env = (i==2) ? '=' : ' ';while ((*++env = *val++) != '\0');}/* end is marked with double '\0' */*++env = '\0';/* Update CRC */env_crc_update ();/** Some variables should be updated when the corresponding* entry in the enviornment is changed*/if (strcmp(argv[1],"ethaddr") == 0) {char *s = argv[2];    /* always use only one arg */char *e;for (i=0; i<6; ++i) {bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0;if (s) s = (*e) ? e+1 : e;}
#ifdef CONFIG_NET_MULTIeth_set_enetaddr(0, argv[2]);
#endifreturn 0;}if (strcmp(argv[1],"ipaddr") == 0) {char *s = argv[2];    /* always use only one arg */char *e;unsigned long addr;bd->bi_ip_addr = 0;for (addr=0, i=0; i<4; ++i) {ulong val = s ? simple_strtoul(s, &e, 10) : 0;addr <<= 8;addr  |= (val & 0xFF);if (s) s = (*e) ? e+1 : e;}bd->bi_ip_addr = htonl(addr);return 0;}if (strcmp(argv[1],"loadaddr") == 0) {load_addr = simple_strtoul(argv[2], NULL, 16);return 0;}
#if defined(CONFIG_CMD_NET)if (strcmp(argv[1],"bootfile") == 0) {copy_filename (BootFile, argv[2], sizeof(BootFile));return 0;}
#endif#ifdef CONFIG_AMIGAONEG3SEif (strcmp(argv[1], "vga_fg_color") == 0 ||strcmp(argv[1], "vga_bg_color") == 0 ) {extern void video_set_color(unsigned char attr);extern unsigned char video_get_attr(void);video_set_color(video_get_attr());return 0;}
#endif    /* CONFIG_AMIGAONEG3SE */return 0;
}

uboot源码——环境变量相关推荐

  1. 嵌入式之uboot源码分析-启动第二阶段学习笔记(下篇)

    接上部分---->嵌入式之uboot源码分析-启动第二阶段学习笔记(上篇) 注:如下内容来自朱老师物联网大讲堂uboot课件 3.2.14 CFG_NO_FLASH (1)虽然NandFlash ...

  2. uboot源码下载以及编译

    环境:ubuntu 20.04 uboot源码下载以及编译 1 uboot源码下载: 1.1 进入uboot官网 1.2 下载源码 2 编译uboot 2.1 配置 2.2 编译 2.2.1 确认编译 ...

  3. 在linux系统中通过fw_printenv查看和设置u-boot中的环境变量

    uboot下可以通过命令访问(printenv)和修改环境变量(setenv),但是如果需要在Linux系统下访问这些数据该怎么办呢?其实uboot早就帮我们想好了.  1.编译fw_printenv ...

  4. X210之uboot源码分析

    uboot源码分析 Makefile分析1 自己参考源码. Makefile分析2 ifdef O ifeq ("$(origin O)", "command line& ...

  5. U-Boot源码目录分析(VScode工程创建及文件夹过滤)

    参考:U-Boot工程目录介绍 作者:一只青木呀 发布时间: 2020-10-21 14:47:30 网址:https://blog.csdn.net/weixin_45309916/article/ ...

  6. linux uboot 源码分析,UBoot源码分析1.pdf

    UBoot源码分析1 • UBoot源码解析(一) 主要内容 • 分析UBoot是如何引导Linux内核 • UBoot源码的一阶段解析 BootLoader概念 • Boot Loader 就是在操 ...

  7. idea构建spring源码环境

    前言 最近抽空在摸索spring源码,就想在idea中把spring源码环境给跑起来,以便于自己进行断点调试和学习,但在自己构建的时候才发现使用idea构建spring源码的环境的确不是一件简单简单的 ...

  8. u-boot源码配置原理分析

    作者:杨老师,华清远见嵌入式学院讲师. u-boot的源代码默认是不针对任何目标平台的,当我们要移植u-boot到一个特定的目标平台时,需要生成针对目标平台的配置文件.u-boot目前已经支持的芯片可 ...

  9. Kafka源码环境搭建

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

最新文章

  1. 常见Jvm面试题总结及答案整理 120道(持续更新)
  2. 计算机基础-计算机硬件
  3. linux下的daemon进程
  4. 缺少动态连接库.so--cannot open shared object file: No such file or directory
  5. Android 开源项目android-open-project工具库解析之(一) 依赖注入,图片缓存,网络相关,数据库orm工具包,Android公共库...
  6. mysql查询大于0的标记_MySQL如何查询回答数大于0的问题并分页
  7. Mongoose 中使用 populate 实现关联查询
  8. React之回调ref中回调执行次数的问题
  9. knn机器学习算法_K-最近邻居(KNN)算法| 机器学习
  10. 五种C语言非数值计算的常用经典排序算法
  11. 替换Android中VM 加载动态库方式
  12. 独立成分分析(Indenpendent Components Analysis)斯坦福公开课讲义
  13. journalctl命令使用
  14. C/C++游戏项目详细教程:《黄金矿工》
  15. h5/5+APP消息推送神器:Goeasy.js
  16. 分享一个网站地图生成工具
  17. 车桥耦合非线性振动运动方程求解
  18. HTB靶场系列 Windows靶机 Granny靶机
  19. 涨停板打开是不是下跌信号?
  20. 游戏开发基础(10)

热门文章

  1. 2018.12.18运算符,分支结构(循环),异常处理,函数
  2. springboot和quartz整合实现动态定时任务(持久化单节点)
  3. jsp通过include指令引入html乱码的解决方法
  4. 机器视觉系统需要考虑的十个问题
  5. 20151210小问题2
  6. 分布式版本控制系统入门
  7. Sublime Text3中文环境设置
  8. java接口调试思想
  9. 一份从 0 到 1 的 Java 项目实践清单
  10. [MySQL 5.6优化] --order by limit x,x 优化