环境变量加载
4 Dec 2024
Read time: 2 minute(s)
如前面所述,环境变量的处理有两个阶段:
-
环境变量初始
-
环境变量读取
如下面的调用流程, env_init() 在 board_init_f()
阶段执行,但具体的加载过程 在 board_init_r()
阶段执行。
reset // arch/riscv/cpu/start.S
|-> save_boot_params // arch/riscv/mach-artinchip/lowlevel_init.S
|-> ...
|-> board_init_f(); // common/board_f.c
|-> setup_reloc(); // common/board_f.c
|-> jump_to_copy(); // common/board_f.c
|-> relocate_code(); // arch/riscv/cpu/start.S
|-> invalidate_icache_all()
|-> flush_dcache_all()
|-> board_init_r();
| // 逐个调用 init_sequence_r 里面的函数,其中包括 initr_env
|-> initr_env(); // common/board_r.c
|-> should_load_env(void);// common/board_r.c
| // 由于没有在 DTS 中进行配置,总是返回 1
| // fdtdec_get_config_int(gd->fdt_blob, "load-environment", 1);
|-> env_relocate(); // env/common.c
|-> env_load(); // env/env.c
U-Boot 支持在多种存储介质中保存环境变量,并且提供了一个插拔式的机制,用于实现从 不同的存储介质中加载环境变量内容。
在添加新的环境变量加载器时,只需要实现对应存储介质的 load 和 save 函数,
然后通过宏 U_BOOT_ENV_LOCATION 将对应的信息添加到
.u_boot_list_2
链接段中。 比如下面的定义,将生成
.u_boot_list_2_env_driver_2_spinand
信息。U_BOOT_ENV_LOCATION(spinand) = {
.location = ENVL_SPINAND,
ENV_NAME("SPINAND")
.load = env_spinand_load,
#if defined(CMD_SAVEENV)
.save = env_save_ptr(env_spinand_save),
#endif
};
env_driver_lookup() 函数首先通过检查当前的启动设备,然后从
.u_boot_list_2
段中查找对应启动设备的 ENV
加载驱动,最后调用对应的驱动读取并导入环境变量内容。env_load(); // env/env.c
|-> env_driver_lookup(ENVOP_LOAD, prio);
| |-> loc = env_get_location(); // board/artinchip/d211/env_location.c
| | |-> bd = aic_get_boot_device(); // 获取当前的启动设备
| |
| |-> _env_driver_lookup(loc);
| |-> drv = ll_entry_start();
| // 查找指定存储介质的 env 加载驱动
|
|-> drv->load();
// 此处调用个存储介质的对应函数
env_ram_load(); // board/artinchip/d211/env_location.c
env_spinand_load(); // env/spinand.c
env_sf_load(); // env/sf.c
env_mmc_load(); // env/mmc.c
具体各种存储介质中,环境变量保存的位置可参考存储介质上的保存。