在引导程序中使用 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_ENCRYPTIONCONFIG_NVS_SEC_KEY_PROTECTION_SCHEME -> CONFIG_NVS_SEC_KEY_PROTECT_USING_HMACCONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID)。

应用示例

代码示例请参阅 ESP-IDF 示例 storage 目录下的 storage/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)


此文档对您有帮助吗?