Files
esp-idf/components/nvs_flash/private_include/nvs_bootloader_private.h

187 lines
8.6 KiB
C

/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "nvs_constants.h" // NVS_CONST_ENTRY_SIZE and all size related constants shared with cpp implementation of NVS
#include "nvs_bootloader.h" // nvs_bootloader_read_list_t and function prototypes
#include "esp_partition.h" // esp_partition_t
#include "nvs_flash.h" // nvs_sec_cfg_t
#include "nvs_bootloader_xts_aes.h" // nvs_bootloader_xts_aes_context
#ifdef __cplusplus
extern "C" {
#endif
// evaluates to true for NVS types fitting single NVS entry. At the moment all NVS_TYPE_U* or NVS_TYPE_I* */
#define NVS_BOOTLOADER_TYPE_FITS_SINGLE_ENTRY(data_type) \
( (data_type == NVS_TYPE_U8) \
||(data_type == NVS_TYPE_I8) \
||(data_type == NVS_TYPE_U16) \
||(data_type == NVS_TYPE_I16) \
||(data_type == NVS_TYPE_U32) \
||(data_type == NVS_TYPE_I32) \
||(data_type == NVS_TYPE_U64) \
||(data_type == NVS_TYPE_I64) \
)
// evaluates to true for NVS types supported by the nvs bootloader code*/
#define NVS_BOOTLOADER_IS_SUPPORTED_TYPE(data_type) \
( (data_type == NVS_TYPE_STR) || NVS_BOOTLOADER_TYPE_FITS_SINGLE_ENTRY(data_type) \
)
// returns length of supported data field in bytes
#define NVS_BOOTLOADER_GET_TYPE_LEN(data_type) \
( (data_type == NVS_TYPE_U8) ? 1 \
:(data_type == NVS_TYPE_I8) ? 1 \
:(data_type == NVS_TYPE_U16) ? 2 \
:(data_type == NVS_TYPE_I16) ? 2 \
:(data_type == NVS_TYPE_U32) ? 4 \
:(data_type == NVS_TYPE_I32) ? 4 \
:(data_type == NVS_TYPE_U64) ? 8 \
:(data_type == NVS_TYPE_I64) ? 8 \
:0 \
)
esp_err_t nvs_bootloader_check_parameters(const char* partition_name,
const size_t read_list_count,
nvs_bootloader_read_list_t read_list[]);
// NVS page header structure
typedef struct {
uint32_t page_state; // page state
uint32_t sequence_number; // sequence number of this page
uint8_t nvs_format_version; // nvs format version
uint8_t reserved[19]; // unused, must be 0xff
uint32_t crc32; // crc32 of everything except page_state
} nvs_bootloader_page_header_t;
// NVS page entry state array structure
// Each entry state is represented by two bits
// There are 126 entries in a page
// The last 4 bits are reserved
typedef struct {
uint8_t entry_states[NVS_CONST_ENTRY_SIZE];
} nvs_bootloader_page_entry_states_t;
// Macro to extract the state of an entry from the entry state structure
#define NVS_BOOTLOADER_GET_ENTRY_STATE(page_entry_states, entry_index) \
((page_entry_states->entry_states[(entry_index) / 4] >> (((entry_index) % 4) * 2)) & 0x03)
typedef struct {
uint8_t data[8];
} nvs_bootloader_entry_data_primitive_type_t;
typedef struct {
uint16_t size;
uint16_t reserved;
uint32_t crc32;
} nvs_bootloader_entry_data_var_len_type_t;
typedef union {
nvs_bootloader_entry_data_primitive_type_t primitive_type;
nvs_bootloader_entry_data_var_len_type_t var_len_type;
} nvs_bootloader_entry_data_t;
// NVS single entry item definition
typedef struct {
uint8_t namespace_index; // namespace index
uint8_t data_type; // data type
uint8_t span; // span
uint8_t chunk_index; // chunk index
uint32_t crc32; // crc32 of the entry
char key[NVS_KEY_NAME_MAX_SIZE]; // key
nvs_bootloader_entry_data_t data; // data, interpreted based on data_type
} nvs_bootloader_single_entry_t;
#define MAX_KEY_LENGTH = (NVS_KEY_NAME_MAX_SIZE - 1);
// read a single entry item from a page
// only reads entries marked as written
// skips items spanning multiple entries
// entry_index is the index of the first entry to read
// item is the output parameter
// entry_index is updated to the index of the next entry
// returns ESP_ERR_NOT_FOUND if no more entries are found
// returns ESP_OK if an entry is found
// returns other error codes if an error occurs
esp_err_t nvs_bootloader_read_next_single_entry_item(const esp_partition_t *partition, const size_t page_index, const nvs_bootloader_page_entry_states_t *entry_states, uint8_t *entry_index, nvs_bootloader_single_entry_t *item);
// read a block of data from the entries from a page
// the block is read starting from the offset specified as entry_index of entry
// the length of the block is specified in bytes in parameter block_len
// the block is read into the buffer pointed to by block
// before accessing the entries, the entry states are checked and the entries are read only if they are marked as written
// if any of the entries that needs to be read is not in the state written, the function returns ESP_ERR_INVALID_STATE
// if the block is not fully read after reaching end of the page, the function returns ESP_ERR_INVALID_STATE
// if the block is fully read, the function returns ESP_OK
esp_err_t nvs_bootloader_read_entries_block(const esp_partition_t *partition, const size_t page_index, const nvs_bootloader_page_entry_states_t *entry_states, const size_t entry_index, const size_t block_len, uint8_t *block);
// visitor function parameters for reading the page header
typedef struct {
size_t no_active_pages;
size_t no_freeing_pages;
} nvs_bootloader_page_visitor_param_get_page_states_t;
// visitor function parameters for reading the namespaces from pages and the key - value pairs from pages
typedef struct {
const bool skip_active_page;
const size_t read_list_count;
nvs_bootloader_read_list_t *read_list;
} nvs_bootloader_page_visitor_param_read_entries_t;
// visitor function parameter union type declaration
typedef union {
nvs_bootloader_page_visitor_param_get_page_states_t *get_page_states;
nvs_bootloader_page_visitor_param_read_entries_t *read_entries;
} nvs_bootloader_page_visitor_param_t;
// visitor function type declaration
typedef esp_err_t (*nvs_bootloader_page_visitor_t)(nvs_bootloader_page_visitor_param_t *visitor_param,
const esp_partition_t *partition,
const size_t page_index,
const nvs_bootloader_page_header_t *page_header);
// visit all pages in the partition
esp_err_t nvs_bootloader_visit_pages(const esp_partition_t *partition,
nvs_bootloader_page_visitor_t visitor,
nvs_bootloader_page_visitor_param_t *visitor_param);
// read page header
esp_err_t nvs_bootloader_read_page_header(const esp_partition_t *partition,
const size_t page_index,
const nvs_bootloader_page_header_t *page_header);
// read entry states from a page
esp_err_t nvs_bootloader_read_page_entry_states(const esp_partition_t *partition,
const size_t page_index,
nvs_bootloader_page_entry_states_t *entry_states);
// populates the page header for a given page
esp_err_t nvs_bootloader_page_visitor_get_page_states(nvs_bootloader_page_visitor_param_t *visitor_param,
const esp_partition_t *partition,
const size_t page_index,
const nvs_bootloader_page_header_t *page_header);
// populates the namespace indexes found on a page
esp_err_t nvs_bootloader_page_visitor_get_namespaces(nvs_bootloader_page_visitor_param_t *visitor_param,
const esp_partition_t *partition,
const size_t page_index,
const nvs_bootloader_page_header_t *page_header);
// populates the key value pairs found on a page
esp_err_t nvs_bootloader_page_visitor_get_key_value_pairs(nvs_bootloader_page_visitor_param_t *visitor_param,
const esp_partition_t *partition,
const size_t page_index,
const nvs_bootloader_page_header_t *page_header);
// check if the item header is consistent - crc32 matches, namespace index is valid, data type is valid and other fields are consistent
bool nvs_bootloader_check_item_header_consistency(const nvs_bootloader_single_entry_t *item,
const uint8_t entry_index);
#ifdef __cplusplus
}
#endif