ESP-IDF NVS 分区生成器实战:用 CSV 定制 NVS 分区,支持加密与多页 Blob
2026/9/14 14:19:36 网站建设 项目流程

ESP-IDF NVS 分区生成器实战:用 CSV 定制 NVS 分区,支持加密与多页 Blob

【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf

本文基于 ESP-IDF 仓库中的 NVS Partition Generator 文档 展开,讲解nvs_partition_gen.py工具的完整用法:如何用 CSV 文件描述键值对并生成可烧录的 NVS 二进制分区,包括多页 Blob(multipage blob)格式版本控制、XTS-AES 加密分区的生成与解密、以及 HMAC 密钥保护方案。读完后你将能够完成 ODM/OEM 产线场景下"一份固件、多台设备各自定制参数(如序列号)"的 NVS 分区定制工作,并理解加密密钥分区与应用侧 sdkconfig 的一致性要求。

工具定位与适用场景

该工具的实际入口是 nvs_partition_gen.py,它负责根据 CSV 文件提供的键值对,生成符合 NVS 架构定义 的二进制文件。

它的典型应用场景是:为 ODM/OEM 厂商生成包含设备特定数据的二进制镜像,在设备量产时由外部设备烧录。这样厂家可以用同一份应用固件,为每台设备烧录定制化的 NVS 数据(例如每台设备唯一的序列号),而不需要为每台设备单独编译固件。

从源码结构看,nvs_partition_gen.py 本身只有一行核心逻辑——通过subprocess调用esp_idf_nvs_partition_genPython 模块执行真正的生成逻辑,即该工具以 Python 包形式随 ESP-IDF 安装环境一起分发,仓库中的脚本只是方便用户直接运行的薄封装。

前提条件

若要以加密模式使用本工具,需要安装cryptography包。文档指出,所有必需依赖均已包含在 ESP-IDF 根目录的requirements.txt中,即执行 ESP-IDF 标准的 Python 依赖安装(idf_tools.py install-python-env)后即可满足加密模式所需。

CSV 文件格式

CSV 文件每一行包含 4 个以逗号分隔的参数:

序号参数说明备注
1Key数据键名,应用之后使用该键访问数据
2Type支持filedatanamespace三种类型
3Encoding支持u8i8u16i16u32i32u64i64stringhex2binbase64binary。指定实际数据在输出二进制文件中的编码方式。stringbinary的区别在于:string数据以 NULL 字符结尾,binary数据不以 NULL 结尾目前file类型仅支持hex2binbase64stringbinary四种编码
4Value数据值namespace类型的EncodingValue两列必须留空(其取值固定、不可配置,填写也会被忽略)

两点格式硬性要求:

  • 第一行必须是不可配置的列头key,type,encoding,value
  • 空格规则:逗号前后不能有空格,每行行尾不能有空格。

示例 CSV(仓库中随工具提供的 sample_singlepage_blob.csv 即包含下列全部要素):

key,type,encoding,value <-- 列头 namespace_name,namespace,, <-- 第一条必须为 namespace 类型 key1,data,u8,1 key2,file,string,/path/to/file

仓库还另外提供了一份 sample_val.csv,演示了在storage命名空间下写入 u8/i8/u16/u32/i32 整型和多行字符串的用法;字符串若包含逗号或换行,需要用双引号包裹(可跨行)。

NVS 条目与命名空间的关联规则

命名空间(namespace)的关联遵循"区间归属"规则:当解析器在 CSV 中遇到一个 namespace 条目时,其后所有条目都归属于该命名空间,直到遇到下一个 namespace 条目为止——之后的条目转而归属于新的命名空间。

因此第一条条目必须namespace条目,否则后续的 data/file 条目将无处归属。这也是所有示例 CSV 都将namespace行放在第一位的原因。

多页 Blob 支持(格式版本 1 与 2)

默认情况下,二进制 Blob 允许跨多个页面存储,按 NVS 文档中的条目结构(structure of entry)格式写入,对应格式版本 2(Version 2,默认值)。如果目标设备运行的是旧版本固件,可以使用--version 1选项禁用多页 Blob 支持,生成版本 1格式:

版本含义
--version 1禁用多页 Blob 支持
--version 2启用多页 Blob 支持(默认)

版本 2 的完整示例命令(仓库提供 sample_multipage_blob.csv 作为输入,其包含testdata/sample_multipage_blob.bin这样的大 Blob 文件):

python nvs_partition_gen.py generate sample_multipage_blob.csv sample.bin 0x4000 --version 2

两个注意点(原文档 Caveats 部分):

  • 所需最小 NVS 分区大小为0x3000字节;
  • 将生成的二进制烧录到设备时,必须确保它与应用侧的sdkconfig配置一致(例如加密与否、格式版本等需与应用匹配)。

加密分区的生成与解密

工具支持创建加密二进制文件和解密已有加密文件,采用XTS-AES加密方案(详见 NVS 加密文档)。ESP-IDF 侧对应 Kconfig 中的NVS_ENCRYPTION选项:启用后整个 NVS 数据(页头除外)用 XTS-AES 加密,XTS 密钥要么存放在一个加密的密钥分区中(此时必须启用 Flash 加密),要么从烧入 eFuse 的 HMAC 密钥派生。工具侧的密钥生成/加密流程与应用侧这两套方案一一对应。

子命令总览

工具提供 4 个子命令,各子命令可通过python nvs_partition_gen.py {command} -h查看更详细帮助:

命令说明
generate生成 NVS 分区
generate-key生成加密密钥
encrypt生成加密的 NVS 分区
decrypt解密加密的 NVS 分区

generate:生成 NVS 分区(默认命令)

python nvs_partition_gen.py generate [-h] [--version {1,2}] [--outdir OUTDIR] input output size

位置参数

参数说明
input待解析 CSV 文件的路径
output输出 NVS 二进制文件的路径
sizeNVS 分区大小(字节,必须是 4096 的整数倍)

可选参数

参数说明
-h/--help显示帮助信息
--version {1,2}设置多页 Blob 格式版本(默认 Version 2;1 表示禁用多页 Blob 支持,2 表示启用)
--outdir OUTDIR生成文件的输出目录(默认当前目录)

运行示例:

python nvs_partition_gen.py generate sample_singlepage_blob.csv sample.bin 0x3000

generate-key:仅生成加密密钥分区

# 默认(Flash 加密)方案 python nvs_partition_gen.py generate-key [-h] [--keyfile KEYFILE] [--outdir OUTDIR]
参数说明
--keyfile KEYFILE输出密钥文件的路径
--outdir OUTDIR输出目录(默认当前目录)

最小运行命令:

python nvs_partition_gen.py generate-key

HMAC 方案专用参数(仅当目标芯片支持 HMAC 外设,即 Kconfig 中SOC_HMAC_SUPPORTED成立时可用,例如 ESP32-C3 等 RISC-V 芯片):

参数说明
--key_protect_hmac设置后使用基于 HMAC 外设的 NVS 加密密钥保护方案;否则使用默认的基于 Flash 加密的方案
--kp_hmac_keygen为 HMAC 方案生成 HMAC 密钥
--kp_hmac_keyfile KP_HMAC_KEYFILEHMAC 密钥文件输出路径
--kp_hmac_inputkey KP_HMAC_INPUTKEY包含用于派生 NVS 加密密钥的 HMAC 密钥的文件

HMAC 方案的两种典型命令:

# 同时生成 HMAC 密钥与 NVS 加密密钥 python nvs_partition_gen.py generate-key --key_protect_hmac --kp_hmac_keygen

执行后会在输出目录创建加密密钥文件<outdir>/keys/keys-<timestamp>.bin和 HMAC 密钥文件<outdir>/keys/hmac-keys-<timestamp>.bin(两个文件名均可通过参数自定义)。

# 已有 HMAC 密钥时,仅生成 NVS 加密密钥 python nvs_partition_gen.py generate-key --key_protect_hmac --kp_hmac_inputkey testdata/sample_hmac_key.bin

仓库 testdata/ 目录下提供了sample_hmac_key.binsample_encryption_keys.binsample_encryption_keys_hmac.bin等样例密钥文件,可直接用于演练上述流程。

encrypt:生成加密的 NVS 分区

python nvs_partition_gen.py encrypt [-h] [--version {1,2}] [--keygen] [--keyfile KEYFILE] [--inputkey INPUTKEY] [--outdir OUTDIR] input output size

位置参数与generate相同(inputCSV 路径、output输出 NVS 二进制路径、size分区大小且为 4096 的整数倍)。

可选参数

参数说明
--version {1,2}多页 Blob 格式版本(默认 2)
--keygen由工具自动生成 NVS 分区加密密钥
--keyfile KEYFILE输出密钥文件的路径
--inputkey INPUTKEY包含 NVS 分区加密密钥的输入文件
--outdir OUTDIR输出目录(默认当前目录)

HMAC 方案支持的额外参数与generate-key相同(--key_protect_hmac--kp_hmac_keygen--kp_hmac_keyfile--kp_hmac_inputkey)。

按"密钥来源"分为四种典型用法:

# 1. 让工具自动生成密钥 python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen # 生成 <outdir>/keys/keys-<timestamp>.bin # 2. 自定义密钥文件名 python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen --keyfile sample_keys.bin # 生成 <outdir>/keys/sample_keys.bin # 3. 使用已有的密钥文件加密 python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --inputkey sample_keys.bin

HMAC 方案的两种变体:

# 工具同时生成 NVS 加密密钥与 HMAC 密钥 python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen --key_protect_hmac --kp_hmac_keygen # 生成 keys/keys-<timestamp>.bin 与 keys/hmac-keys-<timestamp>.bin # 用户自行提供 HMAC 密钥 python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen --key_protect_hmac --kp_hmac_inputkey testdata/sample_hmac_key.bin

关键兼容性说明:--keyfile生成并保存在keys/目录下的密钥文件,与 NVS 密钥分区(key partition)结构兼容。结合 NVS 加密文档:应用侧要求分区表中存在一个类型data、子类型nvs_keys、标记为encrypted、大小至少 4 KB 的密钥分区,菜单配置(idf.py menuconfig的 Partition Table 选项)中也提供了两份带该密钥分区的现成分区表。也就是说,工具生成的密钥文件可以直接烧录为密钥分区,与应用侧NVS_ENCRYPTION机制无缝对接。

decrypt:解密加密的 NVS 分区

python nvs_partition_gen.py decrypt [-h] [--outdir OUTDIR] input key output
参数说明
input待解密的加密 NVS 分区文件路径
key包含解密密钥的文件路径
output输出解密后的二进制文件路径
--outdir OUTDIR输出目录(默认当前目录)

运行示例:

python nvs_partition_gen.py decrypt sample_encr.bin sample_keys.bin sample_decr.bin

解密时同样可以指定格式版本号:版本 1 对应禁用多页 Blob 支持,版本 2 对应启用多页 Blob 支持。

多页 Blob 两档格式的运行示例

版本 1(禁用多页 Blob)

python nvs_partition_gen.py generate sample_singlepage_blob.csv sample.bin 0x3000 --version 1

版本 2(启用多页 Blob)

python nvs_partition_gen.py generate sample_multipage_blob.csv sample.bin 0x4000 --version 2

两个示例分别对应仓库中提供的 sample_singlepage_blob.csv 和 sample_multipage_blob.csv,区别仅在最后引用的 Blob 文件:单页版引用testdata/sample_singlepage_blob.bin(单页内可容纳的 Blob),多页版引用testdata/sample_multipage_blob.bin(跨页的大 Blob),分区大小也相应从0x3000提升到0x4000

使用限制(Caveats)

原文档明确列出以下限制,生产使用前务必注意:

  • 不检查重复键:工具不会检测重复的 key,两个同名键的数据都会被写入。键的唯一性需要使用者自己保证;
  • 新页不回填旧页剩余空间:一旦开始写新页,之前页面剩余的空间就不会再被利用。CSV 中的条目顺序应当有意识地安排以优化存储空间(例如把大的 Blob 排在合适位置,避免"小条目碎页"浪费);
  • 64 位数据类型尚不支持:CSV 中可写u64/i64编码值,但工具实际尚未支持 64 位数据写入,应避开这两类编码。

配套工具与交叉参考

  • 生成完成后,可以用同目录下的 nvs 分区解析工具 检查分区内容,其文档 描述了nvs_tool.py的用法;
  • NVS 运行时行为、API 与分区结构见 nvs_flash 参考文档;
  • 密钥分区结构、XTS-AES 与 HMAC 方案的完整说明见 NVS 加密文档;
  • 端到端的加密 NVS 测试用例可参考 nvs_flash 测试应用,其中包含由该工具生成的partition_encrypted.binpartition_encrypted_hmac.bin等真实产物及其sdkconfig.ci.*配置,可用于验证"工具生成的密钥分区 + 应用侧NVS_ENCRYPTION配置"的组合在不同芯片上是否工作正常。

【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询