警告

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 API。为此，NVS 提供了一个简化 API，仅支持只读访问 NVS 数据。

该 API 支持读取除 blob 之外的所有 NVS 数据类型。一次 API 调用可以同时读取多个 NVS 条目。可以从同一 NVS 分区的不同命名空间读取值，读取结果存储在输入/输出结构数组中，每个数据项的固定大小最多为 8 字节。

由于引导加载程序中的堆内存分配限制，读取字符串条目时，API 要求调用者提供缓冲区及其大小。

### 读取加密的 NVS 分区

如果 NVS 分区使用 NVS 加密 指南中的加密方案，该 API 还支持解密 NVS 数据。

应用程序应按照以下步骤使用 `nvs_bootloader_read()` API 读取加密 NVS 分区数据：

> 1. 根据所选的 NVS 加密方案填充 NVS 安全配置结构 `nvs_sec_cfg_t` （详情请参阅 NVS 加密）。

> 2. 使用 `nvs_bootloader_read_security_cfg()` API 从指定的安全方案中读取 NVS 安全配置。

> 3. 获取安全配置后，使用 `nvs_bootloader_secure_init()` API 初始化 NVS flash 分区。

> 4. 使用 `nvs_bootloader_read()` API 执行 NVS 读取操作。

> 5. 使用 `nvs_bootloader_secure_deinit()` API 反初始化 NVS flash 分区，并清除安全配置。

备注

在使用基于 HMAC 的方案进行上述流程时，可以直接调用 `nvs_flash_secure_init()` API 对默认和自定义 NVS 分区进行加密，而无需启用 NVS 加密相关配置选项（如 CONFIG_NVS_ENCRYPTION， CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME -> `CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC`， CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID）。

## 应用示例

代码示例请参阅 ESP-IDF 示例 storage/nvs 目录下的 storage/nvs/nvs_bootloader。

本节演示了如何在输入/输出结构中准备数据，以支持不同的数据类型、命名空间和键。此外，还包含从 NVS 读取字符串数据的示例。

示例还演示了如何检查读取操作是否成功，数据是否存在不一致，或是否在 NVS 中找不到某些值的情形。该示例能够将 API 返回的值（或错误码）打印到控制台。

## API 参考

### Header File

- components/nvs_flash/include/nvs_bootloader.h

- This header file can be included with:

  >     #include "nvs_bootloader.h"

- This header file is a part of the API provided by the `nvs_flash` component. To declare that your component depends on `nvs_flash`, add the following to your CMakeLists.txt:

  >     REQUIRES nvs_flash

  > or

  >     PRIV_REQUIRES nvs_flash

### Functions

esp_err_t nvs_bootloader_read(const char *partition_name, const size_t read_list_count, nvs_bootloader_read_list_t read_list[])

  Reads data specified from the specified NVS partition.

  This function reads data from the NVS partition specified by `partition_name`. Multiple NVS entries can be read in a single call. The list of entries to read is specified in the `read_list` array. Function indicates overall success or failure by its return value. In case it is ESP_OK or ESP_ERR_INVALID_ARG, result of validation / reading of individual entry is returned in the `result_code` member of each element of the `read_list` array.

  参数:

    - partition_name -- The name of the NVS partition to read from.

    - read_list_count -- The number of elements in the `read_list` array.

    - read_list -- An array of `nvs_bootloader_read_list_t` structures specifying the keys and buffers for reading data.

  返回:

    The return value of the function in this file can be one of the following:

    - `ESP_OK`: The function successfully checked all input parameters and executed successfully. The individual `result_code` in `read_list` indicates the result of the lookup for a particular requested key.

    - `ESP_ERR_INVALID_ARG`: The validity of all `read_list` input parameters was checked and failed for at least one of the parameters. The individual `result_code` in `read_list` provides the detailed reason. This error code is also returned when read_list is null or read_list_count is 0.

    - `ESP_ERR_NVS_INVALID_NAME`: The partition name specified is too long or is null.

    - `ESP_ERR_NVS_PART_NOT_FOUND`: The partition was not found in the partition table.

    - `ESP_ERR_NVS_CORRUPT_KEY_PART`: Encryption-related problems.

    - `ESP_ERR_NVS_WRONG_ENCRYPTION`: Encryption-related problems.

    - `ESP_ERR_INVALID_STATE`: NVS partition or pages related errors - wrong size of partition, header inconsistent / entries inconsistencies, multiple active pages, page in state INVALID.

    - `ESP_ERR_NO_MEM`: Cannot allocate memory required to perform the function.

    - Technical errors in underlying storage.

esp_err_t nvs_bootloader_secure_init(const nvs_sec_cfg_t *sec_cfg)

  Initialize internal NVS security context, thus, enabling the NVS bootloader read API to decrypt encrypted NVS partitions.

  备注

  Once `nvs_bootloader_secure_init()` is performed, `nvs_bootloader_read()` can correctly read only those NVS partitions that are encrypted using the given `nvs_sec_cfg_t` security config, until `nvs_bootloader_secure_deinit()` clears the internal NVS security context.

  参数:

    sec_cfg -- NVS security key that would be used for decrypting the NVS partition

  返回:

    ESP_OK if security initialization is successful

void nvs_bootloader_secure_deinit(void)

  Clear the internal NVS security context.

esp_err_t nvs_bootloader_read_security_cfg(nvs_sec_scheme_t *scheme_cfg, nvs_sec_cfg_t *cfg)

  Reads NVS bootloader security configuration set by the specified security scheme.

  参数:

    - scheme_cfg -- [in] Security scheme specific configuration

    - cfg -- [out] Security configuration (encryption keys)

  返回:

    - ESP_OK, if cfg was read successfully;

    - ESP_ERR_INVALID_ARG, if scheme_cfg or cfg is NULL;

    - ESP_FAIL, if the key reading process fails

### Unions

union nvs_bootloader_value_placeholder_t
  #include <nvs_bootloader.h>

  Union of value placeholders for all nvs_type_t supported by bootloader code.

  Public Members

  uint8_t u8_val

    Placeholder for unsigned 8 bit integer variable

  int8_t i8_val

    Placeholder for signed 8 bit integer variable

  uint16_t u16_val

    Placeholder for unsigned 16 bit integer variable

  int16_t i16_val

    Placeholder for signed 16 bit integer variable

  uint32_t u32_val

    Placeholder for unsigned 32 bit integer variable

  int32_t i32_val

    Placeholder for signed 32 bit integer variable

  uint64_t u64_val

    Placeholder for unsigned 64 bit integer variable

  int64_t i64_val

    Placeholder for signed 64 bit integer variable

  nvs_bootloader_str_value_placeholder_t str_val

    Placeholder for string buffer information

### Structures

struct nvs_bootloader_str_value_placeholder_t

  Placeholders for buffer pointer and length of string type.

  Public Members

  char *buff_ptr

    Pointer to the buffer where string and terminating zero character will be read

  size_t buff_len

    Buffer length in bytes

struct nvs_bootloader_read_list_t

  Structure representing one NVS bootloader entry.

  This structure serves as read operation input parameters and result value and status placeholder. Before calling the `nvs_bootloader_read` function, populate the namespace_name, key_name and value_type members. If string value has to be read, provide also buffer and its length in the `value.str_val` member.

  The result_code member will be populated by the function with the result of the read operation. There are 2 possible situations and interpretations of the result_code: If the return value of the `nvs_bootloader_read` was ESP_OK, the result_code will be one of the following:

  - `ESP_OK`: Entry found, value member contains the data. This is the only case when the value member is populated.

  - `ESP_ERR_NVS_TYPE_MISMATCH`: Entry was found, but requested datatype doesn't match datatype found in NVS

  - `ESP_ERR_NVS_NOT_FOUND`: Data was not found.

  - `ESP_ERR_INVALID_SIZE`: the value found for string is longer than the space provided in placeholder (str_val.buff_len) If the return value of the function was ESP_ERR_INVALID_ARG, the result_code will be one of the following:

  - `ESP_ERR_NVS_NOT_FOUND`: Check of this parameters was successful.

  - `ESP_ERR_NVS_INVALID_NAME`: namespace_name is NULL or too long

  - `ESP_ERR_NVS_KEY_TOO_LONG`: key_name NULL or too long

  - `ESP_ERR_INVALID_SIZE`: the size of the buffer provided for NVS_TYPE_STR in placeholder (str_val.buff_len) is zero or exceeds maximum value NVS_CONST_STR_LEN_MAX_SIZE

  - `ESP_ERR_INVALID_ARG`: Invalid datatype requested

  Public Members

  const char *namespace_name

    Namespace of the entry

  const char *key_name

    Key of the entry

  nvs_type_t value_type

    Expected datatype to be read, can be any of NVS_TYPE_U*, NVS_TYPE_I* or NVS_TYPE_STR

  esp_err_t result_code

    Result code of this entry. Explanation is in general description of the struct nvs_bootloader_read_list_t

  nvs_bootloader_value_placeholder_t value

    Placeholder for value read

  uint8_t namespace_index

    Index of the namespace (internal variable, do not use)

此文档对您有帮助吗？

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

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