env

U_BOOT_ENV_LOCATION

  • 通过该宏定义环境变量的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
* Define a callback that can be associated with variables.
* when associated through the ".callbacks" environment variable, the callback
* will be executed any time the variable is inserted, overwritten, or deleted.
*
* For SPL these are silently dropped to reduce code size, since environment
* callbacks are not supported with SPL.
*/
#ifdef CONFIG_XPL_BUILD
#define U_BOOT_ENV_CALLBACK(name, callback) \
static inline __maybe_unused void _u_boot_env_noop_##name(void) \
{ \
(void)callback; \
}
#else
#define U_BOOT_ENV_CALLBACK(name, callback) \
ll_entry_declare(struct env_clbk_tbl, name, env_clbk) = \
{#name, callback}
#endif

default_environment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
const char default_environment[] = {
#ifndef CONFIG_USE_DEFAULT_ENV_FILE
#ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
#endif
#ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT
ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
#endif
#ifdef CONFIG_USE_BOOTARGS
"bootargs=" CONFIG_BOOTARGS "\0"
#endif
#ifdef CONFIG_BOOTCOMMAND
"bootcmd=" CONFIG_BOOTCOMMAND "\0"
#endif
#if defined(CONFIG_BOOTDELAY)
"bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0"
#endif
#if !defined(CONFIG_OF_SERIAL_BAUD) && defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
"baudrate=" __stringify(CONFIG_BAUDRATE) "\0"
#endif
#ifdef CONFIG_LOADS_ECHO
"loads_echo=" __stringify(CONFIG_LOADS_ECHO) "\0"
#endif
#ifdef CONFIG_ETHPRIME
"ethprime=" CONFIG_ETHPRIME "\0"
#endif
#ifdef CONFIG_USE_IPADDR
"ipaddr=" CONFIG_IPADDR "\0"
#endif
#ifdef CONFIG_USE_SERVERIP
"serverip=" CONFIG_SERVERIP "\0"
#endif
#ifdef CONFIG_SYS_DISABLE_AUTOLOAD
"autoload=0\0"
#endif
#ifdef CONFIG_PREBOOT_DEFINED
"preboot=" CONFIG_PREBOOT "\0"
#endif
#ifdef CONFIG_USE_ROOTPATH
"rootpath=" CONFIG_ROOTPATH "\0"
#endif
#ifdef CONFIG_USE_GATEWAYIP
"gatewayip=" CONFIG_GATEWAYIP "\0"
#endif
#ifdef CONFIG_USE_NETMASK
"netmask=" CONFIG_NETMASK "\0"
#endif
#ifdef CONFIG_USE_HOSTNAME
"hostname=" CONFIG_HOSTNAME "\0"
#endif
#ifdef CONFIG_USE_BOOTFILE
"bootfile=" CONFIG_BOOTFILE "\0"
#endif
#ifdef CONFIG_SYS_LOAD_ADDR
"loadaddr=" __stringify(CONFIG_SYS_LOAD_ADDR)"\0"
#endif
#ifdef CONFIG_ENV_VARS_UBOOT_CONFIG
"arch=" CONFIG_SYS_ARCH "\0"
#ifdef CONFIG_SYS_CPU
"cpu=" CONFIG_SYS_CPU "\0"
#endif
#ifdef CONFIG_SYS_BOARD
"board=" CONFIG_SYS_BOARD "\0"
"board_name=" CONFIG_SYS_BOARD "\0"
#endif
#ifdef CONFIG_SYS_VENDOR
"vendor=" CONFIG_SYS_VENDOR "\0"
#endif
#ifdef CONFIG_SYS_SOC
"soc=" CONFIG_SYS_SOC "\0"
#endif
#ifdef CONFIG_USB_HOST
"usb_ignorelist="
#ifdef CONFIG_USB_KEYBOARD
/* Ignore Yubico devices. Currently only a single USB keyboard device is
* supported and the emulated HID keyboard Yubikeys present is useless
* as keyboard.
*/
"0x1050:*,"
#endif
"\0"
#endif
#ifdef CONFIG_ENV_IMPORT_FDT
"env_fdt_path=" CONFIG_ENV_FDT_PATH "\0"
#endif
#endif
#if defined(CONFIG_BOOTCOUNT_BOOTLIMIT) && (CONFIG_BOOTCOUNT_BOOTLIMIT > 0)
"bootlimit=" __stringify(CONFIG_BOOTCOUNT_BOOTLIMIT)"\0"
#endif
#ifdef CONFIG_MTDIDS_DEFAULT
"mtdids=" CONFIG_MTDIDS_DEFAULT "\0"
#endif
#ifdef CONFIG_MTDPARTS_DEFAULT
"mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0"
#endif
#ifdef CONFIG_EXTRA_ENV_TEXT
/* This is created in the Makefile */
CONFIG_EXTRA_ENV_TEXT
#endif
#ifdef CFG_EXTRA_ENV_SETTINGS
CFG_EXTRA_ENV_SETTINGS
#endif
#ifdef CONFIG_OF_SERIAL_BAUD
/* Padding for baudrate at the end when environment is writable */
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
#endif
"\0"
#else /* CONFIG_USE_DEFAULT_ENV_FILE */
#include "generated/defaultenv_autogenerated.h"
#endif
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
}
#endif
};

const char default_environment[] = {
"bootargs=console=ttySTM0,2000000 root=/dev/ram "
"loglevel=8\000bootcmd=bootm "
"90080000\000bootdelay=3\000baudrate=2000000\000loadaddr="
"0xc1800000\000arch=arm\000cpu=armv7m\000board=stm32h750-art-pi\000board_"
"name=stm32h750-art-pi\000vendor=st\000soc=stm32h7\000kernel_addr_r="
"0xC0008000\000fdtfile=stm32h750i-art-pi.dtb\000fdt_addr_r="
"0xC0408000\000scriptaddr=0xC0418000\000pxefile_addr_r="
"0xC0428000\000ramdisk_addr_r=0xC0438000\000mmc_boot=if mmc dev ${devnum}; "
"then devtype=mmc; run scan_dev_for_boot_part; fi\000boot_prefixes=/ "
"/boot/\000boot_scripts=boot.scr.uimg "
"boot.scr\000boot_script_dhcp=boot.scr.uimg\000boot_targets=mmc0 "
"\000boot_syslinux_conf=extlinux/extlinux.conf\000boot_extlinux=sysboot "
"${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} "
"${prefix}${boot_syslinux_conf}\000scan_dev_for_extlinux=if test -e "
"${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; "
"then echo Found ${prefix}${boot_syslinux_conf}; run boot_extlinux; echo "
"EXTLINUX FAILED: continuing...; fi\000boot_a_script=load ${devtype} "
"${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source "
"${scriptaddr}\000scan_dev_for_scripts=for script in ${boot_scripts}; do "
"if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; "
"then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo "
"SCRIPT FAILED: continuing...; fi; done\000scan_dev_for_boot=echo Scanning "
"${devtype} ${devnum}:${distro_bootpart}...; for prefix in "
"${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; "
"done;\000scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable "
"devplist; env exists devplist || setenv devplist 1; for distro_bootpart "
"in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} "
"bootfstype; then part uuid ${devtype} ${devnum}:${distro_bootpart} "
"distro_bootpart_uuid ; run scan_dev_for_boot; fi; done; setenv "
"devplist\000bootcmd_mmc0=devnum=0; run mmc_boot\000distro_bootcmd=for "
"target in ${boot_targets}; do run bootcmd_${target}; done\000\000"
};

bootargs=console=ttySTM0,2000000 root=/dev/ram loglevel=8
bootcmd=bootm 90080000
bootdelay=3
baudrate=2000000
loadaddr=0xc1800000
arch=arm
cpu=armv7m
board=stm32h750-art-pi
board_name=stm32h750-art-pi
vendor=st
soc=stm32h7
kernel_addr_r=0xC0008000
fdtfile=stm32h750i-art-pi.dtb
fdt_addr_r=0xC0408000
scriptaddr=0xC0418000
pxefile_addr_r=0xC0428000
ramdisk_addr_r=0xC0438000
mmc_boot=if mmc dev ${devnum}; then devtype=mmc; run scan_dev_for_boot_part; fi
boot_prefixes=/ /boot/
boot_scripts=boot.scr.uimg boot.scr
boot_script_dhcp=boot.scr.uimg
boot_targets=mmc0
boot_syslinux_conf=extlinux/extlinux.conf
boot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}${boot_syslinux_conf}
scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then echo Found ${prefix}${boot_syslinux_conf}; run boot_extlinux; echo EXTLINUX FAILED: continuing...; fi
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; done
scan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;
scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then part uuid ${devtype} ${devnum}:${distro_bootpart} distro_bootpart_uuid ; run scan_dev_for_boot; fi; done; setenv devplist
bootcmd_mmc0=devnum=0; run mmc_boot
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done

env_locations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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_SPI_FLASH
ENVL_SPI_FLASH,
#endif
#ifdef CONFIG_ENV_IS_IN_UBI
ENVL_UBI,
#endif
#ifdef CONFIG_ENV_IS_NOWHERE
ENVL_NOWHERE,
#endif
};

initr_env

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static int initr_env(void)
{
/* initialize environment */
if (should_load_env()) //使用默认环境或者从其他地方加载环境
env_relocate();
else
env_set_default(NULL, 0);

env_import_fdt(); //导入fdt环境变量

if (IS_ENABLED(CONFIG_OF_CONTROL))
env_set_hex("fdtcontroladdr",
(unsigned long)map_to_sysmem(gd->fdt_blob));

#if (IS_ENABLED(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) || \
IS_ENABLED(CONFIG_SAVE_PREV_BL_FDT_ADDR))
save_prev_bl_data();
#endif

/* Initialize from environment */
image_load_addr = env_get_ulong("loadaddr", 16, image_load_addr);

return 0;
}

env.c

  • 从其他存储位置加载环境变量
  • 其他地方没有存储则执行默认的环境变量
  • 这样可以在使用在其他地方配置好环境变量,然后在u-boot中直接使用

env_init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int env_init(void)
{
struct env_driver *drv;
int ret = -ENOENT;
int prio;
// 从优先级0开始查找环境驱动,直到没有环境驱动
for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
// 如果环境驱动的init函数存在,则调用init函数
if (!drv->init || !(ret = drv->init())) // 如果初始化成功
env_set_inited(drv->location);
if (ret == -ENOENT) // 如果不需要初始化
env_set_inited(drv->location); //gd->env_has_init |= BIT(location);

debug("%s: Environment %s init done (ret=%d)\n", __func__,
drv->name, ret);

if (gd->env_valid == ENV_INVALID)
ret = -ENOENT;
}
// 如果没有找到环境驱动,则返回-ENOENT
if (!prio)
return -ENODEV;
// 找到了环境驱动,但是环境无效,则使用默认环境
if (ret == -ENOENT) {
gd->env_addr = (ulong)&default_environment[0];
gd->env_valid = ENV_VALID;

return 0;
}

return ret;
}

env_driver_lookup

  • 根据优先级和操作查找环境驱动并返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static struct env_driver *env_driver_lookup(enum env_operation op, int prio)
{
enum env_location loc = env_get_location(op, prio);
struct env_driver *drv;

if (loc == ENVL_UNKNOWN)
return NULL;

drv = _env_driver_lookup(loc);
if (!drv) {
debug("%s: No environment driver for location %d\n", __func__,
loc);
return NULL;
}

return drv;
}

arch_env_get_location

  • 根据优先级返回环境位置
1
2
3
4
5
6
7
__weak enum env_location arch_env_get_location(enum env_operation op, int prio)
{
if (prio >= ARRAY_SIZE(env_locations))
return ENVL_UNKNOWN;

return env_locations[prio];
}

_env_driver_lookup

  • 在段中查找环境驱动,匹配符合的环境位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static struct env_driver *_env_driver_lookup(enum env_location loc)
{
struct env_driver *drv;
const int n_ents = ll_entry_count(struct env_driver, env_driver);
struct env_driver *entry;

drv = ll_entry_start(struct env_driver, env_driver);
for (entry = drv; entry != drv + n_ents; entry++) {
if (loc == entry->location)
return entry;
}

/* Not found */
return NULL;
}

common.c

env_get_from_linear

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
static int env_get_from_linear(const char *env, const char *name, char *buf,
unsigned len)
{
const char *p, *end;
size_t name_len;

if (name == NULL || *name == '\0')
return -1;

name_len = strlen(name);

for (p = env; *p != '\0'; p = end + 1) {
const char *value;
unsigned res;
//识别到数组结束符
for (end = p; *end != '\0'; ++end)
if (end - env >= CONFIG_ENV_SIZE)
return -1;

if (strncmp(name, p, name_len) || p[name_len] != '=')
continue;
//找到name
value = &p[name_len + 1];

res = end - value;
//拷贝环境变量的值
memcpy(buf, value, min(len, res + 1));

if (len <= res) {
buf[len - 1] = '\0';
printf("env_buf [%u bytes] too small for value of \"%s\"\n",
len, name);
}

return res;
}

return -1;
}

env_set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int env_set(const char *varname, const char *varvalue)
{
const char * const argv[4] = { "setenv", varname, varvalue, NULL };

/* before import into hashtable */
if (!(gd->flags & GD_FLG_ENV_READY))
return 1;
//H_PROGRAMMATIC 指示导入来自 env_set()
if (varvalue == NULL || varvalue[0] == '\0')
//没有值,则少个参数传入,所以是2
//执行删除操作
return env_do_env_set(0, 2, (char * const *)argv, H_PROGRAMMATIC);
else
//有值,则多一个参数传入,所以是3
//执行设置操作
return env_do_env_set(0, 3, (char * const *)argv, H_PROGRAMMATIC);
}

env_do_env_set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
int env_do_env_set(int flag, int argc, char *const argv[], int env_flag)
{
int i, len;
char *name, *value, *s;
struct env_entry e, *ep;

debug("Initial value for argc=%d\n", argc);

#if !IS_ENABLED(CONFIG_XPL_BUILD) && IS_ENABLED(CONFIG_CMD_NVEDIT_EFI)
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
return do_env_set_efi(NULL, flag, --argc, ++argv);
#endif
//处理-或者-其他的参数
while (argc > 1 && **(argv + 1) == '-') {
char *arg = *++argv;

--argc;
while (*++arg) {
switch (*arg) {
case 'f': /* force */
env_flag |= H_FORCE;
break;
default:
return CMD_RET_USAGE;
}
}
}
//不允许使用 = 赋值
if (strchr(name, '=')) {
printf("## Error: illegal character '=' "
"in variable name \"%s\"\n", name);
return 1;
}
//删除操作
if (argc < 3 || argv[2] == NULL) {
int rc = hdelete_r(name, &env_htab, env_flag);

/* If the variable didn't exist, don't report an error */
return rc && rc != -ENOENT ? 1 : 0;
}
// 添加/替换
for (i = 2, len = 0; i < argc; ++i)
len += strlen(argv[i]) + 1;

value = malloc(len);
if (value == NULL) {
printf("## Can't malloc %d bytes\n", len);
return 1;
}
//拼接参数每个参数之间用空格隔开
for (i = 2, s = value; i < argc; ++i) {
char *v = argv[i];

while ((*s++ = *v++) != '\0')
;
*(s - 1) = ' ';
}
//如果分配的内存没有用完,则将最后一个空格替换为'\0'
if (s != value)
*--s = '\0';

e.key = name;
e.data = value;
//替换或插入现有数据
hsearch_r(e, ENV_ENTER, &ep, &env_htab, env_flag);
free(value);
if (!ep) {
printf("## Error inserting \"%s\" variable, errno=%d\n",
name, errno);
return 1;
}

return 0;
}

env_id 可以检查环境是否已更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* 每次我们设置环境变量时,此变量都会递增,
* 因此我们可以通过 env_get_id() 进行检查,以查看环境是否已更改。
* 这使得只有在环境已更改,通常由网络代码使用。
*/
static int env_id = 1;

int env_get_id(void)
{
return env_id;
}

void env_inc_id(void)
{
env_id++;
}

env_complete env变量补全

env_get 从环境变量中获取值

  • 根据当前状态,使用不同的方式获取环境变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char *env_get(const char *name)
{
if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */
struct env_entry e, *ep;

schedule();

e.key = name;
e.data = NULL;
hsearch_r(e, ENV_FIND, &ep, &env_htab, 0);

return ep ? ep->data : NULL;
}

/* restricted capabilities before import */
if (env_get_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) >= 0)
return (char *)(gd->env_buf);

return NULL;
}

env_get_from_linear

  • 识别\0结束符,匹配name,返回value
  • 一个个搜索过去

nowhere.c

  • 环墫位置为NOWHERE,无处可去的默认位置会执行这里
  • 根据env_locations的定义,这里是最低优先级的执行位置
1
2
3
4
5
6
U_BOOT_ENV_LOCATION(nowhere) = {
.location = ENVL_NOWHERE,
.init = env_nowhere_init, //gd->env_valid = ENV_INVALID;
.load = env_nowhere_load,
ENV_NAME("nowhere")
};

callback.c 执行环境变量修改时的回调函数

  • 立刻刷新内部值等处理

U_BOOT_ENV_CALLBACK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define U_BOOT_ENV_CALLBACK(name, callback) \
ll_entry_declare(struct env_clbk_tbl, name, env_clbk) = \
{#name, callback}

//在段中查找回调函数
static struct env_clbk_tbl *find_env_callback(const char *name)
{
struct env_clbk_tbl *clbkp;
int i;
int num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);

if (name == NULL)
return NULL;

/* look up the callback in the linker-list */
for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
i < num_callbacks;
i++, clbkp++) {
if (strcmp(name, clbkp->name) == 0)
return clbkp;
}

return NULL;
}

env_callback_init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
static int first_call = 1;
static const char *callback_list;

/*
* Look for a possible callback for a newly added variable
* This is called specifically when the variable did not exist in the hash
* previously, so the blanket update did not find this variable.
*/
void env_callback_init(struct env_entry *var_entry)
{
const char *var_name = var_entry->key;
char callback_name[256] = "";
struct env_clbk_tbl *clbkp;
int ret = 1;

if (first_call) {
//从环境变量".callback"中获取回调函数列表
callback_list = env_get(ENV_CALLBACK_VAR);
first_call = 0;
}

var_entry->callback = NULL;

/*在 “.callbacks” 变量中查找对此变量的引用 */
if (callback_list != NULL)
ret = env_attr_lookup(callback_list, var_name, callback_name);

/* 仅当在那里找不到时,才查看静态列表 */
if (ret)
ret = env_attr_lookup(ENV_CALLBACK_LIST_STATIC, var_name,
callback_name);

/* 如果找到关联,则设置回调指针 */
if (!ret && strlen(callback_name)) {
clbkp = find_env_callback(callback_name);
if (clbkp != NULL)
var_entry->callback = clbkp->callback;
}
}

attr.c

  • 属性值是直接在env的key上的,例如”key:[attr1,attr2,attr3] = value”

env_attr_walk

  • 传入一个值和其属性的列表,遍历并执行回调函数,传入值和属性
1
2
const char *attr_list = "var1:attr1,var2:attr2,var3:attr3";
env_attr_walk(attr_list, print_attr, NULL);

CONFIG_REGEX 正则表达式支持

env_attr_lookup

  • 从属性列表中根据名称返回其属性

flags.c

  • 环境变量的标志位
  • 直接存储为单独的变量
  1. 调用
    env_flags_validate: 在创建、覆盖或删除环境变量时调用此函数。 当设置了(标志和H_FORCE)时,不要打印出任何错误消息并强制覆盖一次性写入变量。

  2. 设置:on_flags:环境变量flag变化时,通过callback函数调用;

    • 遍历所有的环境变量执行clear_flags函数清除标志位
    • ENV_FLAGS_LIST_STATIC中的识别attr,调用set_flags函数设置标志位
    • value中的识别attr,调用set_flags函数设置标志位
  3. 识别:env_parse_flags_to_bin将字符串转换为标志位

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    enum env_flags_vartype {
    env_flags_vartype_string,
    env_flags_vartype_decimal,
    env_flags_vartype_hex,
    env_flags_vartype_bool,
    #ifdef CONFIG_NET
    env_flags_vartype_ipaddr,
    env_flags_vartype_macaddr,
    #endif
    env_flags_vartype_end
    };

    enum env_flags_varaccess {
    env_flags_varaccess_any, //任意
    env_flags_varaccess_readonly, //只读
    env_flags_varaccess_writeonce, //只写一次
    env_flags_varaccess_changedefault, //改变默认值
    #ifdef CONFIG_ENV_WRITEABLE_LIST
    env_flags_varaccess_writeable, //可写
    #endif
    env_flags_varaccess_end //结束
    };
  4. 新建:env_flags_init: 在新建环境变量时调用此函数。如果环境变量具有标志,则调用env_parse_flags_to_bin函数将标志转换为二进制值。