上节介绍了环境变量的基本概念和使用方法,这一节环境变量的实现。
在U-boot中环境变量相关的源码目录。U-boot支持多种非易失设备存放环境变量,为屏蔽设备之间的差异,环境变量实现中需提供统一访问接口,对变量进行读出和写回;在使用环境变量时,变量的值类型有很多,字符串类型、整型等,U-boot环境变量的实现中也提供了一组接口供上层使用。
存储结构
环境变量在非易失设备的存储结构如下:
typedef struct environment_s {
uint32_t crc; /* CRC32 over data bytes */
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
unsigned char flags; /* active/obsolete flags */
#endif
unsigned char data[ENV_SIZE]; /* Environment data */
} env_t;
环境变量以内存块的形式存放,内存块头部有CRC校验和flags标记。每个环境变量的存放方式为:"var=value\0"。每个变量用一个NULL结尾的字符串表示,依次存放。
框架结构
环境变量的实现中,分多层实现
从下往上:存储驱动层-》中间维护层-》命令访问层。存储驱动层实现统一的存储访问接口,供中间维护层;中间维护层负责维护加载到内存中的环境变量;命令访问层由U-boot几条环境变量相关的命令printenv,savenv等组成,对环境变量进行访问。在中间维护层和命令访问层之间,为不同类型变量值提供不同访问接口。
存储驱动层
存储驱动层主要功能实现统一的存储访问接口,包含:
函数名 | 描述 |
void load(void) | 加载环境变量到内存 |
void save(void) | 保存内存中的环境变量到非易失存储设备 |
相关结构体struct env_driver,定义在include/environment.h中。
从访问接口可见,存储驱动层实现功能很简单:读取变量到内存、写回变量到存储设备。
注意:有个问题,void load()于void save(void)接口都没有参数,如何获取读取或写入的地址等信息呢?