目的:探索env的读取和保存(qspi)
一.涉及的类型定义
CONFIG_ENV_OFFSET_REDUND
ReDund:redundancy(冗余,即开启环境变量的备份).
官方解释:
config_env_offset_redundancy(可选)指定第二个存储区域,大小为CONFIG_ENV_SIZE,
用于保存环境数据的冗余副本。这提供了一个有效的备份副本,以防另一个副本损坏.
例如由于在"saveenv"操作期间电源故障。这个值也是以字节为单位,但也必须与MMC扇区边界对齐。
/*******************************************************************/
//解释:全局变量 struct hsearch_data env_htab的类型定义
typedef struct entry {
const char *key;
char *data;
int (*callback)(const char *name, const char *value, enum env_op op,
int flags);
int flags;
} ENTRY;
typedef struct _ENTRY {
int used;
ENTRY entry;
} _ENTRY;
struct hsearch_data {
struct _ENTRY *table;
unsigned int size;
unsigned int filled;
/*
* Callback function which will check whether the given change for variable
* "__item" to "newval" may be applied or not, and possibly apply such change.
* When (flag & H_FORCE) is set, it shall not print out any error message and
* shall force overwriting of write-once variables.
* Must return 0 for approval, 1 for denial.
*/
int (*change_ok)(const ENTRY *__item, const char *newval, enum env_op,
int flag);
};
struct hsearch_data env_htab = {
.change_ok = env_flags_validate,
};
/*************************************************************************/
//解释:env_t* env_out对应的类型定义
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;
二.关键函数解释
/***********************env/env.c主要函数*****************************/
//解释:.config文件中的配置决定了驱动,以下三个函数均为调用对应存储设备驱动的实现(见注2)
//在zynq开发板环境下: env/sf.c
//初始化
int env_init(void)
/**************************************************************/
//从存储设备中加载环境变量
int env_load(void);
/**************************************************************/
//解释: 把环境变量保存到存储设备中
int env_save(void);
//注1:
//解释:定义一个环境变量驱动位置存放设置的宏,每一个存储环境变量的设备driver定义时都使用该宏
/* Declare a new environment location driver */
#define U_BOOT_ENV_LOCATION(__name) \
ll_entry_declare(struct env_driver, __name, env_driver)
//注2
U_BOOT_ENV_LOCATION(sf) = {
.location = ENVL_SPI_FLASH,
ENV_NAME("SPI Flash")
.load = env_sf_load,
#ifdef CMD_SAVEENV
.save = env_save_ptr(env_sf_save),
#endif
#if defined(INITENV) && defined(CONFIG_ENV_ADDR)
.init = env_sf_init,
#endif
};
/***********************env/env.c 其他函数*****************************/
/***************************************************************/
//解释:从env_htab 中导出到env_out中,并计算env_out->crc
int env_export(env_t *env_out)
{
char *res;
ssize_t len;
res = (char *)env_out->data;
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
if (len < 0) {
pr_err("Cannot export environment: errno = %d\n", errno);
return 1;
}
env_out->crc = crc32(0, env_out->data, ENV_SIZE);
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
env_out->flags = ++env_flags; /* increase the serial */
#endif
return 0;
}
/***************************************************************/
//解释:buf强制转换为env_t类型,然后导入到 全局变量env_htab
//(check:是否对比env_t的crc)
int env_import(const char *buf, int check)
三.zynq702 .config中的关键配置
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xE0000
#
# Environment commands
#
# CONFIG_CMD_ASKENV is not set
CONFIG_CMD_EXPORTENV=y
CONFIG_CMD_IMPORTENV=y
CONFIG_CMD_EDITENV=y
# CONFIG_CMD_GREPENV is not set
CONFIG_CMD_SAVEENV=y
CONFIG_CMD_ENV_EXISTS=y
# CONFIG_CMD_ENV_CALLBACK is not set
# CONFIG_CMD_ENV_FLAGS is not set
#
# Environment
#
# CONFIG_ENV_IS_IN_EEPROM is not set
# CONFIG_ENV_IS_IN_FAT is not set
# CONFIG_ENV_IS_IN_EXT4 is not set
# CONFIG_ENV_IS_IN_FLASH is not set
# CONFIG_ENV_IS_IN_MMC is not set
# CONFIG_ENV_IS_IN_NAND is not set
# CONFIG_ENV_IS_IN_NVRAM is not set
# CONFIG_ENV_IS_IN_ONENAND is not set
# CONFIG_ENV_IS_IN_REMOTE is not set
#!!!!!!确定使用env/sf.c中的驱动(见 注1)
CONFIG_ENV_IS_IN_SPI_FLASH=y
# CONFIG_ENV_IS_IN_UBI is not set
CONFIG_ENV_SECT_SIZE=0x20000
# CONFIG_USE_DEFAULT_ENV_FILE is not set
# CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG is not set
CONFIG_NET=y
CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_NETCONSOLE is not set
注1:
static enum env_location env_locations[] = {
#ifdef CONFIG_ENV_IS_IN_EEPROM
ENVL_EEPROM,
#endif
#ifdef CONFIG_ENV_IS_IN_EXT4
ENVL_EXT4,
#endif
#ifdef CONFIG_ENV_IS_IN_FAT
ENVL_FAT,
#endif
#ifdef CONFIG_ENV_IS_IN_FLASH
ENVL_FLASH,
#endif
#ifdef CONFIG_ENV_IS_IN_MMC
ENVL_MMC,
#endif
#ifdef CONFIG_ENV_IS_IN_NAND
ENVL_NAND,
#endif
#ifdef CONFIG_ENV_IS_IN_NVRAM
ENVL_NVRAM,
#endif
#ifdef CONFIG_ENV_IS_IN_REMOTE
ENVL_REMOTE,
#endif
#ifdef CONFIG_ENV_IS_IN_SATA
ENVL_ESATA,
#endif
#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
ENVL_SPI_FLASH,
#endif
#ifdef CONFIG_ENV_IS_IN_UBI
ENVL_UBI,
#endif
#ifdef CONFIG_ENV_IS_NOWHERE
ENVL_NOWHERE,
#endif
};