3.4. 环境变量

本章描述 U-Boot 中关于环境变量的关键内容,以及 ZX 平台中对环境变量的使用方式。 关于 U-Boot 环境变量的更多内容,可以参考官方文档:

U-Boot 环境变量是保存在非易失性存储(NVM)上的文本数据块,系统启动时会被拷贝到内存中使用。 环境变量中保存了系统的相关配置信息,使用过程中相关的配置可以被读写。 环境变量的数据存储格式简单,内容通过 CRC32 进行保护:

include/env_internal.h

typedef struct environment_s {
    uint32_t        crc;            /* CRC32 over data bytes        */
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
    unsigned char   flags;          /* active/obsolete flags ENVF_REDUND_ */
#endif
    unsigned char   data[ENV_SIZE]; /* Environment data             */
} env_t;

其中 data 存放的是一系列以 NULL 结束的环境变量字符串。

3.4.1. 初始环境变量设置

初始的环境变量设置有两种方式:

  • 源文件文件中设置默认的环境变量内容

    这种方式是通过具体平台的配置头文件,定义各个环境变量的初始化设置宏,然后在编译的时候展开到全局变量 default_environment 中。具体可以参考:

    • include/env_default.h

    • env/common.c

    • include/configs/qemu-riscv.h

    这种方式的好处是,烧录固件时不需要烧录环境变量内容,留空即可。启动过程中,U-Boot 检查设备上的环境变量不合法, 则会使用 default_environment 中的内容,并且会将 default_environment 中的内容主动写入到存储设备上, 后续的启动都从存储设备上读取环境变量。

  • 独立的环境变量文件

    这种方式将初始的环境变量内容,以文本的形式保存为单独的文件,编译镜像的过程中,使用 mkenvimage 对该文件进行编译,生成可烧录的环境变量二进制文件。

    在做固件烧录时,需要将该二进制文件烧录到预设的分区。

ZX 平台的初始环境变量通过独立的环境变量文件进行配置,源码中的默认环境变量 default_environment 值为空。 环境变量文件路径为:

  • env.txt

3.4.2. 存储介质上的保存

在使用过程中,保存在存储设备上的环境变量内容可能会被修改,因此选择存储位置时需要考虑存储介质的特点。 比如 MTD 设备上要注意保存在独立的擦除块上,以免在修改时影响其他数据的完整性。

常见的保存方式有下面两种:

  • 与 U-Boot 一起保存

    在使用 MMC 存储时,有些方案会将 ENV 保存在 U-Boot 的分区,并且放在 U-Boot 分区的尾部。 通过在 DTS 中指定分区名字即可访问到。

  • 单独分区保存

    多数方案使用单独的分区保存。

在 ZX 平台上,不同存储介质上 ENV 的默认保存设置如下文所述。

3.4.2.1. MMC

MMC 的 ENV 存储位置可以通过下面几个方式进行设置:

  • Kconfig 配置指定 Offset 和 大小

    • CONFIG_ENV_OFFSET

    • CONFIG_ENV_OFFSET_REDUND

    • CONFIG_ENV_SIZE

    • CONFIG_ENV_IS_IN_MMC

  • DTS 中配置 offset,Kconfig 配置大小

    • “u-boot,mmc-env-offset”

    • “u-boot,mmc-env-offset-redundant”

  • DTS 中配置分区名字,Kconfig 配置大小

    • “u-boot,mmc-env-partition”

目前默认的配置使用最后一种方式,通过 DTS 中的 config 节点配置:

config {
    u-boot,mmc-env-partition = "env";
};

u-boot,mmc-env-partition = “env” 表示环境变量使用独立分区的方式,保存在mmc设备的”env”分区上。

通过 Kconfig 设置 CONFIG_ENV_SIZE 大小为16KB。

保存 ENV 数据的区域为该分区的前 CONFIG_ENV_SIZE 大小。相关的源码在文件: board/zx/m4/mmc_env.c

3.4.2.2. SPI NAND

U-Boot 项目的源码本身没有支持 SPI NAND 启动,环境变量也没有支持从 SPI NAND 读取, ZX 平台增加了 SPI NAND 的支持。

ENV 存储位置的配置通过 Kconfig 进行,需要配置的选项有下面几个:

  • CONFIG_ENV_OFFSET

  • CONFIG_ENV_SIZE

  • CONFIG_ENV_RANGE

相应的源码在 env/spinand.c

3.4.2.3. SPI NOR

U-Boot 原本已经支持从 SPI NOR 启动和加载 ENV 内容。ENV 的存储位置通过 Kconfig 进行, 需要配置的选项有下面几个:

  • CONFIG_ENV_SPI_BUS

  • CONFIG_ENV_SPI_CS

  • CONFIG_ENV_SPI_MAX_HZ

  • CONFIG_ENV_SPI_MODE

  • CONFIG_ENV_OFFSET

  • CONFIG_ENV_OFFSET_REDUND

  • CONFIG_ENV_SECT_SIZE

  • CONFIG_ENV_SIZE

  • CONFIG_ENV_IS_IN_SPI_FLASH

相应的源码在 env/sf.c

3.4.2.4. RAM

ZX 平台上增加了从 DRAM 指定地址加载环境变量的功能,主要用于 USB 升级的场景。 在 USB 升级的过程中,主机端会先发送一个 env.bin 到设备指定内存地址,然后再启动 u-boot 进行升级。

相关的配置通过 Kconfig 进行,需要配置的选项有:

  • CONFIG_ENV_RAM_ADDR

相应的源码在 board/zx/m4/env_location.c