uboot的环境变量
https://www.cnblogs.com/biaohc/p/6398515.html
uboot 环境变量实现原理:
首先我们先要搞清楚uboot中环境变量的作用,uboot中环境变量的作用就是在不改变源码、不用重新编译的情况下,可以使我们通过
设置环境变量的值来改变uboot的一些设置,如bootdelay时间、机器码的值等等。
具体看一下uboot中环境变量如何实现
1、首先看一下环境变量的初始化函数:
env_init定义在commen/env_movi.c中 函数中实际执行的就是把default_environment的地址赋值给全局变量gd中的env_addr 和env_valid两个值;
1 int env_init(void) 2 { 3 #if defined(ENV_IS_EMBEDDED) 4 #else /* ENV_IS_EMBEDDED */ 5 gd->env_addr = (ulong)&default_environment[0]; 6 gd->env_valid = 1; 7 #endif /* ENV_IS_EMBEDDED */ 8 9 return (0); 10 }
来看一下default_environment数组
在来看一下env_relocate 这个函数
重点是一下两句代码
- env_ptr = (env_t *)malloc (CFG_ENV_SIZE); 这句代码作用是给uboot环境变量开辟一块16k大小的内存
- env_relocate_spec (); 这句代码的作用是把sd卡中的uboot环境变量整个分区复制到开辟的这个内存地址处;
1 void env_relocate (void) 2 { 3 4 5 #ifdef ENV_IS_EMBEDDED 6 #else 7 /* 8 * We must allocate a buffer for the environment 9 */ 10 env_ptr = (env_t *)malloc (CFG_ENV_SIZE); 11 DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr); 12 #endif 13 14 if (gd->env_valid == 0) { 15 16 } 17 else { 18 env_relocate_spec (); 19 } 20 gd->env_addr = (ulong)&(env_ptr->data); 21 22 23 }
env_relocate_spec ()函数:
通过movi_read_env函数把sd卡中的环境变量复制到内存中
主要用到的是 movi_read_env(virt_to_phys((ulong)env_ptr)); 函数
crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc
use_default()
三个函数: movi_read_env把sd卡中的uboot的环境变量分区复制到env_ptr中;
crc32 计算内存中环境变量的crc的值,如果不相等则执行
use_default函数
1 void env_relocate_spec (void) 2 { 3 #if !defined(ENV_IS_EMBEDDED) 4 uint *magic = (uint*)(PHYS_SDRAM_1); 5 6 if ((0x24564236 != magic[0]) || (0x20764316 != magic[1])) 7 movi_read_env(virt_to_phys((ulong)env_ptr)); 8 9 if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) 10 return use_default(); 11 #endif /* ! ENV_IS_EMBEDDED */ 12 }
下面看一下use_default函数的代码:
1:输出*** Warning - bad CRC or moviNAND, using default environment:
2:清0环境变量内存,把default_environment中的值复制到环境变量内存
3:计算crc,写入内存中的crc位
4:设置gd中的env_valid为1;
1 static void use_default() 2 { 3 puts ("*** Warning - bad CRC or moviNAND, using default environment\n\n"); 4 5 if (default_environment_size > CFG_ENV_SIZE){ 6 puts ("*** Error - default environment is too large\n\n"); 7 return; 8 } 9 10 memset (env_ptr, 0, sizeof(env_t)); 11 memcpy (env_ptr->data, 12 default_environment, 13 default_environment_size); 14 env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); 15 gd->env_valid = 1; 16 }
这样环境变量初始化算是完成了;
我们在回顾一下环境变量初始化都做了哪些工作:
1:在uboot还没有初始化flash设备(nand movinand 等flash)的时候,先进行环境变量初级初始化,即把gd全局变量中的 env_valid = 1; env_addr 等于全局变量default_enviroment数组的首地址
2:初始化完flash设置以后就要进行环境变量的重定位工作了,即把环境变量从flash中copy到内存中,用一个全局变量env_ptr指向这段内存;复制工作时通过movi_read_env这个函数实现的,实际就是把sd卡中
环境变量分区全部复制到env_ptr指向的这段内存中,然后在对这段内存中的环境变量进行crc校验,如果失败的话,则把default_enviroment中的环境变量复制到这里;
(这里对代码分析env_relocate函数中用malloc设置了一段内存来存放环境变量,一直没有用free来释放这段内存,这里是否存在安全隐患?)
------------------------------------------------------------------------------------------------------------
接下来我们在看一下uboot中关于环境变量的一些命令
第一个 printenv 实现函数为do_printfenv
第二个命令:setenv命令对用的函数是do_setenv 命令,实际上调用的是_do_setenv函数