警告

This document is not updated for ESP32H21 yet, so some of the content may not be correct.

This warning was automatically inserted due to the source file being in the add_warnings_pages list.

# NVS 分区生成程序

[English]

## 介绍

NVS 分区生成程序 (nvs_flash/nvs_partition_generator/nvs_partition_gen.py) 根据 CSV 文件中的键值对生成二进制文件。该二进制文件与 非易失性存储库 中定义的 NVS 结构兼容。

NVS 分区生成程序适合用于生成二进制数据 (blob)，其中包括设备生产时可从外部烧录的 ODM/OEM 数据。这也使得生产制造商在使用同一个应用固件的基础上，通过自定义参数，如序列号，为每个设备生成不同配置的二进制 NVS 分区。

## 准备工作

在加密模式下使用该程序，需安装下列软件包：

  - `cryptography`

根目录下的 requirements.txt 包含必需 python 包，请预先安装。

### CSV 文件格式

CSV 文件每行需包含四个参数，以逗号隔开。具体参数描述见下表：

序号 | 参数 | 描述 | 说明
--- | --- | --- | ---
1 | Key | 主键，应用程序可通过查询此键来获取数据。 |
2 | Type | 支持 `file`、`data` 和 `namespace`。 |
3 | Encoding | 支持 `u8`、`i8`、`u16`、`i16`、`u32`、`i32`、`u64`、`i64`、`string`、`hex2bin`、`base64` 和 `binary`。决定二进制 `bin` 文件中 value 被编码成的类型。`string` 和 `binary` 编码的区别在于，`string` 数据以 NULL 字符结尾，`binary` 数据则不是。 | `file` 类型当前仅支持 `hex2bin`、`base64`、 `string` 和 `binary` 编码。
4 | Value | Data value | `namespace` 字段的 `encoding` 和 `value` 应为空。 `namespace` 的 `encoding` 和 `value` 为固定值，不可设置。这些单元格中的所有值都会被忽视。

备注

CSV 文件的第一行应始终为列标题，不可设置。

此类 CSV 文件的 Dump 示例如下:

    key,type,encoding,value     <-- 列标题
    namespace_name,namespace,,  <-- 第一个条目为 "namespace"
    key1,data,u8,1
    key2,file,string,/path/to/file

备注

请确保：

  - 逗号 ',' 前后无空格；

  - CSV 文件每行末尾无空格。

## NVS 条目和命名空间 (namespace) 的关联

如 CSV 文件中出现命名空间条目，后续条目均会被视为该命名空间的一部分，直至找到下一个命名空间条目。找到新命名空间条目后，后续所有条目都会被视为新命名空间的一部分。

备注

CSV 文件中第一个条目应始终为 `namespace`。

## 支持多页 blob

默认情况下，二进制 blob 可跨多页，格式参考 条目结构 章节。如需使用旧版格式，可在程序中禁用该功能。

## 支持加解密

NVS 分区生成程序还可使用 XTS-AES 加密生成二进制加密文件或对此类文件进行解密。更多信息详见 NVS 加密。

## 运行程序

使用方法:

    python nvs_partition_gen.py [-h] {generate,generate-key,encrypt,decrypt} ...

可选参数：

序号 | 参数 | 描述
--- | --- | ---
1 | `-h` / `--help` | 显示帮助信息并退出

命令:

> 运行 `nvs_partition_gen.py {command} -h` 查看更多帮助信息

序号 | 参数 | 描述
--- | --- | ---
1 | `generate` | 生成 NVS 分区
2 | `generate-key` | 生成加密密钥
3 | `encrypt` | 加密 NVS 分区
4 | `decrypt` | 解密 NVS 分区

### 生成 NVS 分区（默认模式）

使用方法:

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

位置参数：

参数 | 描述
--- | ---
`input` | 待解析的 CSV 文件路径
`output` | NVS 二进制文件的输出路径
`size` | NVS 分区大小（以字节为单位，且为 4096 的整数倍）

可选参数：

参数 | 描述
`-h` / `--help` | 显示帮助信息并退出
`--version {1,2}` | 设置多页 blob 版本，默认为版本 2。 版本 1：禁用多页 blob； 版本 2：启用多页 blob。
`--outdir OUTDIR` | 输出目录，用于存储创建的文件。（默认当前目录）

运行如下命令创建 NVS 分区，该程序同时会提供 CSV 示例文件:

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

### 生成加密密钥分区

使用方法:

    python nvs_partition_gen.py generate-key [-h] [--key_protect_hmac] [--kp_hmac_keygen]
                                                  [--kp_hmac_keyfile KP_HMAC_KEYFILE] [--kp_hmac_inputkey KP_HMAC_INPUTKEY]
                                                  [--keyfile KEYFILE] [--outdir OUTDIR]

可选参数:

参数 | 描述
--- | ---
`-h` / `--help` | 显示帮助信息并退出
`--keyfile KEYFILE` | 加密密钥分区文件的输出路径
`--outdir OUTDIR` | 输出目录，用于存储创建的文件（默认当前目录）

可选参数（仅适用于 HMAC 方案）:

参数 | 描述
--- | ---
`--key_protect_hmac` | 设置后使用基于 HMAC 的 NVS 加密密钥保护方案，否则使用基于 flash 加密的默认方案
`--kp_hmac_keygen` | 为基于 HMAC 的加密方案生成 HMAC 密钥
`--kp_hmac_keyfile KP_HMAC_KEYFILE` | HMAC 密钥文件的输出路径
`--kp_hmac_inputkey KP_HMAC_INPUTKEY` | 包含 HMAC 密钥的文件，用于生成 NVS 加密密钥

运行以下命令仅生成加密密钥分区:

    python nvs_partition_gen.py generate-key

运行以下命令，为基于 HMAC 的方案生成加密密钥：

- 生成 HMAC 密钥和 NVS 加密密钥:

      python nvs_partition_gen.py generate-key --key_protect_hmac --kp_hmac_keygen

备注

上述命令生成 `<outdir>/keys/keys-<timestamp>.bin` 格式的加密密钥和 `<outdir>/keys/hmac-keys-<timestamp>.bin` 格式的 HMAC 密钥。

- 基于 HMAC 密钥生成 NVS 加密密钥:

      python nvs_partition_gen.py generate-key --key_protect_hmac --kp_hmac_inputkey testdata/sample_hmac_key.bin

备注

可将自定义文件名作为参数提供给 HMAC 密钥和加密密钥。

### 生成 NVS 加密分区

使用方法:

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

位置参数：

参数 | 描述
--- | ---
`input` | 待解析的 CSV 文件路径
`output` | NVS 二进制文件的输出路径
`size` | NVS 分区大小（以字节为单位，且为 4096 的整数倍）

可选参数：

参数 | 描述
`-h` / `--help` | 显示帮助信息并退出
`--version {1,2}` | 设置多页 blob 版本，默认为版本 2。 版本 1：禁用多页 blob； 版本 2：启用多页 blob。
`--keygen` | 生成 NVS 分区加密密钥
`--keyfile KEYFILE` | 密钥文件的输出路径
`--inputkey INPUTKEY` | 内含 NVS 分区加密密钥的文件
`--outdir OUTDIR` | 输出目录，用于存储创建的文件。（默认当前目录）

可选参数（仅适用于 HMAC 方案）:

参数 | 描述
--- | ---
`--key_protect_hmac` | 设置后使用基于 HMAC 的 NVS 加密密钥保护方案，否则使用基于 flash 加密的默认方案
`--kp_hmac_keygen` | 为基于 HMAC 的加密方案生成 HMAC 密钥
`--kp_hmac_keyfile KP_HMAC_KEYFILE` | HMAC 密钥文件的输出路径
`--kp_hmac_inputkey KP_HMAC_INPUTKEY` | 包含 HMAC 密钥的文件，用于生成 NVS 加密密钥

运行以下命令加密 NVS 分区，该程序同时会提供一个 CSV 示例文件。

- 通过 NVS 分区生成程序生成加密密钥来加密:

      python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen

  备注

  创建的加密密钥格式为 `<outdir>/keys/keys-<timestamp>.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

  备注

  上述命令生成 `<outdir>/keys/keys-<timestamp>.bin` 格式的加密密钥和 `<outdir>/keys/hmac-keys-<timestamp>.bin` 格式的 HMAC 密钥。

  - 通过 NVS 分区生成程序使用用户提供的 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

备注

可将自定义文件名作为参数提供给 HMAC 密钥和加密密钥。

- 通过 NVS 分区生成程序生成加密密钥，并将密钥存储于自定义的文件中:

      python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen --keyfile sample_keys.bin

备注

- 创建的加密密钥格式为 `<outdir>/keys/sample_keys.bin`。

- 加密密钥存储于新建文件的 `keys/` 目录下，与 NVS 密钥分区结构兼容。更多信息请参考 NVS 密钥分区。

- 将加密密钥用作二进制输入文件来进行加密:

      python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --inputkey sample_keys.bin

### 解密 NVS 分区

使用方法:

    python nvs_partition_gen.py decrypt [-h] [--outdir OUTDIR] input key output

位置参数：

参数 | 描述
--- | ---
`input` | 待解析的 NVS 加密分区文件路径
`key` | 含有解密密钥的文件路径
`output` | 已解密的二进制文件输出路径

可选参数：

参数 | 描述
--- | ---
`-h` / `--help` | 显示帮助信息并退出
`--outdir OUTDIR` | 输出目录，用于存储创建的文件（默认当前目录）

运行以下命令解密已加密的 NVS 分区:

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

可以在命令中提供版本参数，选择格式版本号：

  - 版本 1：禁用多页 blob

  - 版本 2：启用多页 blob

### 版本 1：禁用多页 blob

如需禁用多页 blob，请按照如下命令将版本参数设置为 1，以此格式运行分区生成程序。该程序同时会提供一个 CSV 示例文件:

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

### 版本 2：启用多页 blob

如需启用多页 blob，请按照如下命令将版本参数设置为 2，以此格式运行分区生成程序。该程序同时会提供一个 CSV 示例文件:

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

备注

- NVS 分区最小为 0x3000 字节。

- 将二进制文件烧录至设备时，请确保与应用的 sdkconfig 设置一致。

## 说明

- 分区生成程序不会对重复键进行检查，而将数据同时写入这两个重复键中。请注意不要使用同名的键；

- 新页面创建后，前一页的空白处不会再写入数据。CSV 文件中的字段须按次序排列以优化内存；

- 暂不支持 64 位数据类型。

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。