bindesc: Add support for reading binary descriptors
This commit adds support for reading and parsing binary descriptors. It can be used for reading the descriptors of another image, or for iterating over one's own descriptors. Signed-off-by: Yonatan Schachter <yonatan.schachter@gmail.com>
This commit is contained in:
parent
fd68fc486c
commit
00800d4818
4 changed files with 461 additions and 5 deletions
|
|
@ -23,6 +23,8 @@ extern "C" {
|
||||||
#define BINDESC_TYPE_STR 0x1
|
#define BINDESC_TYPE_STR 0x1
|
||||||
#define BINDESC_TYPE_BYTES 0x2
|
#define BINDESC_TYPE_BYTES 0x2
|
||||||
#define BINDESC_TYPE_DESCRIPTORS_END 0xf
|
#define BINDESC_TYPE_DESCRIPTORS_END 0xf
|
||||||
|
/* sizeof ignores the data as it's a flexible array */
|
||||||
|
#define BINDESC_ENTRY_HEADER_SIZE (sizeof(struct bindesc_entry))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Binary Descriptor Definition
|
* @brief Binary Descriptor Definition
|
||||||
|
|
@ -131,11 +133,18 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define BINDESC_TAG(type, id) ((BINDESC_TYPE_##type & 0xf) << 12 | (id & 0x0fff))
|
#define BINDESC_TAG(type, id) ((BINDESC_TYPE_##type & 0xf) << 12 | (id & 0x0fff))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Utility macro to get the type of a bindesc tag
|
||||||
|
*
|
||||||
|
* @param tag Tag to get the type of
|
||||||
|
*/
|
||||||
|
#define BINDESC_GET_TAG_TYPE(tag) ((tag >> 12) & 0xf)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @endcond
|
* @endcond
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(_LINKER)
|
#if !defined(_LINKER) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
#include <zephyr/sys/byteorder.h>
|
#include <zephyr/sys/byteorder.h>
|
||||||
|
|
||||||
|
|
@ -278,6 +287,10 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define BINDESC_GET_SIZE(name) BINDESC_NAME(name).len
|
#define BINDESC_GET_SIZE(name) BINDESC_NAME(name).len
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An entry of the binary descriptor header. Each descriptor is
|
* An entry of the binary descriptor header. Each descriptor is
|
||||||
* described by one of these entries.
|
* described by one of these entries.
|
||||||
|
|
@ -301,6 +314,176 @@ BUILD_ASSERT(offsetof(struct bindesc_entry, tag) == 0, "Incorrect memory layout"
|
||||||
BUILD_ASSERT(offsetof(struct bindesc_entry, len) == 2, "Incorrect memory layout");
|
BUILD_ASSERT(offsetof(struct bindesc_entry, len) == 2, "Incorrect memory layout");
|
||||||
BUILD_ASSERT(offsetof(struct bindesc_entry, data) == 4, "Incorrect memory layout");
|
BUILD_ASSERT(offsetof(struct bindesc_entry, data) == 4, "Incorrect memory layout");
|
||||||
|
|
||||||
|
struct bindesc_handle {
|
||||||
|
const uint8_t *address;
|
||||||
|
enum {
|
||||||
|
BINDESC_HANDLE_TYPE_RAM,
|
||||||
|
BINDESC_HANDLE_TYPE_MEMORY_MAPPED_FLASH,
|
||||||
|
BINDESC_HANDLE_TYPE_FLASH,
|
||||||
|
} type;
|
||||||
|
size_t size_limit;
|
||||||
|
#if IS_ENABLED(CONFIG_BINDESC_READ_FLASH)
|
||||||
|
const struct device *flash_device;
|
||||||
|
uint8_t buffer[sizeof(struct bindesc_entry) +
|
||||||
|
CONFIG_BINDESC_READ_FLASH_MAX_DATA_SIZE] __aligned(BINDESC_ALIGNMENT);
|
||||||
|
#endif /* IS_ENABLED(CONFIG_BINDESC_READ_FLASH) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reading Binary Descriptors of other images.
|
||||||
|
* @defgroup bindesc_read Bindesc Read
|
||||||
|
* @ingroup os_services
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback type to be called on descriptors found during a walk
|
||||||
|
*
|
||||||
|
* @param entry Current descriptor
|
||||||
|
* @param user_data The user_data given to @ref bindesc_foreach
|
||||||
|
*
|
||||||
|
* @return Any non zero value will halt the walk
|
||||||
|
*/
|
||||||
|
typedef int (*bindesc_callback_t)(const struct bindesc_entry *entry, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open an image's binary descriptors for reading, from a memory mapped flash
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* Initializes a bindesc handle for subsequent calls to bindesc API.
|
||||||
|
* Memory mapped flash is any flash that can be directly accessed by the CPU,
|
||||||
|
* without needing to use the flash API for copying the data to RAM.
|
||||||
|
*
|
||||||
|
* @param handle Bindesc handle to be given to subsequent calls
|
||||||
|
* @param offset The offset from the beginning of the flash that the bindesc magic can be found at
|
||||||
|
*
|
||||||
|
* @retval 0 On success
|
||||||
|
* @retval -ENOENT If no bindesc magic was found at the given offset
|
||||||
|
*/
|
||||||
|
int bindesc_open_memory_mapped_flash(struct bindesc_handle *handle, size_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open an image's binary descriptors for reading, from RAM
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* Initializes a bindesc handle for subsequent calls to bindesc API.
|
||||||
|
* It's assumed that the whole bindesc context was copied to RAM prior to calling
|
||||||
|
* this function, either by the user or by a bootloader.
|
||||||
|
*
|
||||||
|
* @note The given address must be aligned to BINDESC_ALIGNMENT
|
||||||
|
*
|
||||||
|
* @param handle Bindesc handle to be given to subsequent calls
|
||||||
|
* @param address The address that the bindesc magic can be found at
|
||||||
|
* @param max_size Maximum size of the given buffer
|
||||||
|
*
|
||||||
|
* @retval 0 On success
|
||||||
|
* @retval -ENOENT If no bindesc magic was found at the given address
|
||||||
|
* @retval -EINVAL If the given address is not aligned
|
||||||
|
*/
|
||||||
|
int bindesc_open_ram(struct bindesc_handle *handle, const uint8_t *address, size_t max_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open an image's binary descriptors for reading, from flash
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* Initializes a bindesc handle for subsequent calls to bindesc API.
|
||||||
|
* As opposed to reading bindesc from RAM or memory mapped flash, this
|
||||||
|
* backend requires reading the data from flash to an internal buffer
|
||||||
|
* using the flash API
|
||||||
|
*
|
||||||
|
* @param handle Bindesc handle to be given to subsequent calls
|
||||||
|
* @param offset The offset from the beginning of the flash that the bindesc magic can be found at
|
||||||
|
* @param flash_device Flash device to read descriptors from
|
||||||
|
*
|
||||||
|
* @retval 0 On success
|
||||||
|
* @retval -ENOENT If no bindesc magic was found at the given offset
|
||||||
|
*/
|
||||||
|
int bindesc_open_flash(struct bindesc_handle *handle, size_t offset,
|
||||||
|
const struct device *flash_device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Walk the binary descriptors and run a user defined callback on each of them
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* If the callback returns a non zero value, the walk stops.
|
||||||
|
*
|
||||||
|
* @param handle An initialized bindesc handle
|
||||||
|
* @param callback A user defined callback to be called on each descriptor
|
||||||
|
* @param user_data User defined data to be given to the callback
|
||||||
|
*
|
||||||
|
* @return If the walk was finished prematurely by the callback,
|
||||||
|
* return the callback's retval, zero otherwise
|
||||||
|
*/
|
||||||
|
int bindesc_foreach(struct bindesc_handle *handle, bindesc_callback_t callback, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find a specific descriptor of type string
|
||||||
|
*
|
||||||
|
* @warning
|
||||||
|
* When using the flash backend, result will be invalidated by the next call to any bindesc API.
|
||||||
|
* Use the value immediately or copy it elsewhere.
|
||||||
|
*
|
||||||
|
* @param handle An initialized bindesc handle
|
||||||
|
* @param id ID to search for
|
||||||
|
* @param result Pointer to the found string
|
||||||
|
*
|
||||||
|
* @retval 0 If the descriptor was found
|
||||||
|
* @retval -ENOENT If the descriptor was not found
|
||||||
|
*/
|
||||||
|
int bindesc_find_str(struct bindesc_handle *handle, uint16_t id, const char **result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find a specific descriptor of type uint
|
||||||
|
*
|
||||||
|
* @warning
|
||||||
|
* When using the flash backend, result will be invalidated by the next call to any bindesc API.
|
||||||
|
* Use the value immediately or copy it elsewhere.
|
||||||
|
*
|
||||||
|
* @param handle An initialized bindesc handle
|
||||||
|
* @param id ID to search for
|
||||||
|
* @param result Pointer to the found uint
|
||||||
|
*
|
||||||
|
* @retval 0 If the descriptor was found
|
||||||
|
* @retval -ENOENT If the descriptor was not found
|
||||||
|
*/
|
||||||
|
int bindesc_find_uint(struct bindesc_handle *handle, uint16_t id, const uint32_t **result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find a specific descriptor of type bytes
|
||||||
|
*
|
||||||
|
* @warning
|
||||||
|
* When using the flash backend, result will be invalidated by the next call to any bindesc API.
|
||||||
|
* Use the value immediately or copy it elsewhere.
|
||||||
|
*
|
||||||
|
* @param handle An initialized bindesc handle
|
||||||
|
* @param id ID to search for
|
||||||
|
* @param result Pointer to the found bytes
|
||||||
|
* @param result_size Size of the found bytes
|
||||||
|
*
|
||||||
|
* @retval 0 If the descriptor was found
|
||||||
|
* @retval -ENOENT If the descriptor was not found
|
||||||
|
*/
|
||||||
|
int bindesc_find_bytes(struct bindesc_handle *handle, uint16_t id, const uint8_t **result,
|
||||||
|
size_t *result_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the size of an image's binary descriptors
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* Walks the binary descriptor structure to caluculate the total size of the structure
|
||||||
|
* in bytes. This is useful, for instance, if the whole structure is to be copied to RAM.
|
||||||
|
*
|
||||||
|
* @param handle An initialized bindesc handle
|
||||||
|
* @param result Pointer to write result to
|
||||||
|
*
|
||||||
|
* @return 0 On success, negative errno otherwise
|
||||||
|
*/
|
||||||
|
int bindesc_get_size(struct bindesc_handle *handle, size_t *result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
#if defined(CONFIG_BINDESC_KERNEL_VERSION_STRING)
|
#if defined(CONFIG_BINDESC_KERNEL_VERSION_STRING)
|
||||||
extern const struct bindesc_entry BINDESC_NAME(kernel_version_string);
|
extern const struct bindesc_entry BINDESC_NAME(kernel_version_string);
|
||||||
#endif /* defined(CONFIG_BINDESC_KERNEL_VERSION_STRING) */
|
#endif /* defined(CONFIG_BINDESC_KERNEL_VERSION_STRING) */
|
||||||
|
|
@ -411,10 +594,6 @@ extern const struct bindesc_entry BINDESC_NAME(cxx_compiler_version);
|
||||||
|
|
||||||
#endif /* !defined(_LINKER) */
|
#endif /* !defined(_LINKER) */
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -66,3 +66,5 @@ if(CONFIG_BINDESC_DEFINE_HOST_INFO)
|
||||||
gen_str_definition(CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER_ID})
|
gen_str_definition(CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER_ID})
|
||||||
gen_str_definition(CXX_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
|
gen_str_definition(CXX_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_BINDESC_READ bindesc_read.c)
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,46 @@ config BINDESC_DEFINE_MAX_DATA_SIZE
|
||||||
|
|
||||||
endif # BINDESC_DEFINE
|
endif # BINDESC_DEFINE
|
||||||
|
|
||||||
|
config BINDESC_READ
|
||||||
|
bool "Binary Descriptors Read"
|
||||||
|
help
|
||||||
|
Enable the app to read the binary descriptors of another image
|
||||||
|
|
||||||
|
if BINDESC_READ
|
||||||
|
|
||||||
|
module = BINDESC_READ
|
||||||
|
module-str = Binary Descriptor read
|
||||||
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
|
||||||
|
config BINDESC_READ_RAM
|
||||||
|
bool "Bindesc read from RAM"
|
||||||
|
help
|
||||||
|
Enable reading and parsing binary descriptors from RAM.
|
||||||
|
|
||||||
|
config BINDESC_READ_MEMORY_MAPPED_FLASH
|
||||||
|
bool "Bindesc read from memory mapped flash"
|
||||||
|
help
|
||||||
|
Enable reading and parsing binary descriptors from memory mapped flash.
|
||||||
|
|
||||||
|
config BINDESC_READ_FLASH
|
||||||
|
bool "Bindesc read from flash"
|
||||||
|
help
|
||||||
|
Enable reading and parsing binary descriptors from non memory mapped flash
|
||||||
|
(e.g. external flash).
|
||||||
|
|
||||||
|
if BINDESC_READ_FLASH
|
||||||
|
|
||||||
|
config BINDESC_READ_FLASH_MAX_DATA_SIZE
|
||||||
|
int "Bindesc read flash max data size"
|
||||||
|
range 4 $(UINT16_MAX)
|
||||||
|
default 128
|
||||||
|
help
|
||||||
|
The maximum expected size of the descriptors' data. This should be set to
|
||||||
|
the value set to BINDESC_DEFINE_MAX_DATA_SIZE by the read image.
|
||||||
|
Any descriptor that exceeds this size will be ignored.
|
||||||
|
|
||||||
|
endif # BINDESC_READ_FLASH
|
||||||
|
|
||||||
|
endif # BINDESC_READ
|
||||||
|
|
||||||
endif # BINDESC
|
endif # BINDESC
|
||||||
|
|
|
||||||
233
subsys/bindesc/bindesc_read.c
Normal file
233
subsys/bindesc/bindesc_read.c
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Yonatan Schachter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/bindesc.h>
|
||||||
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/drivers/flash.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(bindesc_read, CONFIG_BINDESC_READ_LOG_LEVEL);
|
||||||
|
|
||||||
|
struct find_user_data {
|
||||||
|
const void *result;
|
||||||
|
size_t size;
|
||||||
|
uint16_t tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback used by the bindesc_find_* functions.
|
||||||
|
*/
|
||||||
|
static int find_callback(const struct bindesc_entry *entry, void *user_data)
|
||||||
|
{
|
||||||
|
struct find_user_data *data = (struct find_user_data *)user_data;
|
||||||
|
|
||||||
|
if (data->tag == entry->tag) {
|
||||||
|
data->result = (const void *)&(entry->data);
|
||||||
|
data->size = entry->len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback used by the bindesc_get_size function.
|
||||||
|
*/
|
||||||
|
static int get_size_callback(const struct bindesc_entry *entry, void *user_data)
|
||||||
|
{
|
||||||
|
size_t *result = (size_t *)user_data;
|
||||||
|
|
||||||
|
*result += WB_UP(BINDESC_ENTRY_HEADER_SIZE + entry->len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This helper function is used to abstract the different methods of reading
|
||||||
|
* data from the binary descriptors.
|
||||||
|
* For RAM and memory mapped flash, the implementation is very simple, as both
|
||||||
|
* are memory mapped and can simply return a pointer to the data.
|
||||||
|
* Flash is more complex because it needs to read the data from flash, and do
|
||||||
|
* error checking.
|
||||||
|
*/
|
||||||
|
static inline int get_entry(struct bindesc_handle *handle, const uint8_t *address,
|
||||||
|
const struct bindesc_entry **entry)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
int flash_retval;
|
||||||
|
|
||||||
|
/* Check if reading from flash is enabled, if not, this if/else will be optimized out */
|
||||||
|
if (IS_ENABLED(CONFIG_BINDESC_READ_FLASH) && handle->type == BINDESC_HANDLE_TYPE_FLASH) {
|
||||||
|
flash_retval = flash_read(handle->flash_device, (size_t)address,
|
||||||
|
handle->buffer, BINDESC_ENTRY_HEADER_SIZE);
|
||||||
|
if (flash_retval) {
|
||||||
|
LOG_ERR("Flash read error: %d", flash_retval);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure buffer is large enough for the data */
|
||||||
|
if (((const struct bindesc_entry *)handle->buffer)->len + BINDESC_ENTRY_HEADER_SIZE
|
||||||
|
> sizeof(handle->buffer)) {
|
||||||
|
LOG_WRN("Descriptor too large to copy, skipping");
|
||||||
|
retval = -ENOMEM;
|
||||||
|
} else {
|
||||||
|
flash_retval = flash_read(handle->flash_device,
|
||||||
|
(size_t)address + BINDESC_ENTRY_HEADER_SIZE,
|
||||||
|
handle->buffer + BINDESC_ENTRY_HEADER_SIZE,
|
||||||
|
((const struct bindesc_entry *)handle->buffer)->len);
|
||||||
|
if (flash_retval) {
|
||||||
|
LOG_ERR("Flash read error: %d", flash_retval);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*entry = (const struct bindesc_entry *)handle->buffer;
|
||||||
|
} else {
|
||||||
|
*entry = (const struct bindesc_entry *)address;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_BINDESC_READ_MEMORY_MAPPED_FLASH)
|
||||||
|
int bindesc_open_memory_mapped_flash(struct bindesc_handle *handle, size_t offset)
|
||||||
|
{
|
||||||
|
uint8_t *address = (uint8_t *)CONFIG_FLASH_BASE_ADDRESS + offset;
|
||||||
|
|
||||||
|
if (*(uint64_t *)address != BINDESC_MAGIC) {
|
||||||
|
LOG_ERR("Magic not found in given address");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->address = address;
|
||||||
|
handle->type = BINDESC_HANDLE_TYPE_MEMORY_MAPPED_FLASH;
|
||||||
|
handle->size_limit = UINT16_MAX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* IS_ENABLED(CONFIG_BINDESC_READ_RAM) */
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_BINDESC_READ_RAM)
|
||||||
|
int bindesc_open_ram(struct bindesc_handle *handle, const uint8_t *address, size_t max_size)
|
||||||
|
{
|
||||||
|
if (!IS_ALIGNED(address, BINDESC_ALIGNMENT)) {
|
||||||
|
LOG_ERR("Given address is not aligned");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*(uint64_t *)address != BINDESC_MAGIC) {
|
||||||
|
LOG_ERR("Magic not found in given address");
|
||||||
|
return -ENONET;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->address = address;
|
||||||
|
handle->type = BINDESC_HANDLE_TYPE_RAM;
|
||||||
|
handle->size_limit = max_size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* IS_ENABLED(CONFIG_BINDESC_READ_RAM) */
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_BINDESC_READ_FLASH)
|
||||||
|
int bindesc_open_flash(struct bindesc_handle *handle, size_t offset,
|
||||||
|
const struct device *flash_device)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = flash_read(flash_device, offset, handle->buffer, sizeof(BINDESC_MAGIC));
|
||||||
|
if (retval) {
|
||||||
|
LOG_ERR("Flash read error: %d", retval);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*(uint64_t *)handle->buffer != BINDESC_MAGIC) {
|
||||||
|
LOG_ERR("Magic not found in given address");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->address = (uint8_t *)offset;
|
||||||
|
handle->type = BINDESC_HANDLE_TYPE_FLASH;
|
||||||
|
handle->flash_device = flash_device;
|
||||||
|
handle->size_limit = UINT16_MAX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* IS_ENABLED(CONFIG_BINDESC_READ_FLASH) */
|
||||||
|
|
||||||
|
int bindesc_foreach(struct bindesc_handle *handle, bindesc_callback_t callback, void *user_data)
|
||||||
|
{
|
||||||
|
const struct bindesc_entry *entry;
|
||||||
|
const uint8_t *address = handle->address;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
address += sizeof(BINDESC_MAGIC);
|
||||||
|
|
||||||
|
do {
|
||||||
|
retval = get_entry(handle, address, &entry);
|
||||||
|
if (retval == -EIO) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
address += WB_UP(BINDESC_ENTRY_HEADER_SIZE + entry->len);
|
||||||
|
if (retval) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = callback(entry, user_data);
|
||||||
|
if (retval) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
} while ((entry->tag != BINDESC_TAG_DESCRIPTORS_END) &&
|
||||||
|
((address - handle->address) <= handle->size_limit));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bindesc_find_str(struct bindesc_handle *handle, uint16_t id, const char **result)
|
||||||
|
{
|
||||||
|
struct find_user_data data = {
|
||||||
|
.tag = BINDESC_TAG(STR, id),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!bindesc_foreach(handle, find_callback, &data)) {
|
||||||
|
LOG_WRN("The requested descriptor was not found");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
*result = (char *)data.result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bindesc_find_uint(struct bindesc_handle *handle, uint16_t id, const uint32_t **result)
|
||||||
|
{
|
||||||
|
struct find_user_data data = {
|
||||||
|
.tag = BINDESC_TAG(UINT, id),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!bindesc_foreach(handle, find_callback, &data)) {
|
||||||
|
LOG_WRN("The requested descriptor was not found");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
*result = (const uint32_t *)data.result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bindesc_find_bytes(struct bindesc_handle *handle, uint16_t id, const uint8_t **result,
|
||||||
|
size_t *result_size)
|
||||||
|
{
|
||||||
|
struct find_user_data data = {
|
||||||
|
.tag = BINDESC_TAG(BYTES, id),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!bindesc_foreach(handle, find_callback, &data)) {
|
||||||
|
LOG_WRN("The requested descriptor was not found");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
*result = (const uint8_t *)data.result;
|
||||||
|
*result_size = data.size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bindesc_get_size(struct bindesc_handle *handle, size_t *result)
|
||||||
|
{
|
||||||
|
*result = sizeof(BINDESC_MAGIC);
|
||||||
|
|
||||||
|
return bindesc_foreach(handle, get_size_callback, result);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue