Skip to content

Commit 00800d4

Browse files
yonschnashif
authored andcommitted
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 <[email protected]>
1 parent fd68fc4 commit 00800d4

File tree

4 files changed

+461
-5
lines changed

4 files changed

+461
-5
lines changed

include/zephyr/bindesc.h

Lines changed: 184 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ extern "C" {
2323
#define BINDESC_TYPE_STR 0x1
2424
#define BINDESC_TYPE_BYTES 0x2
2525
#define BINDESC_TYPE_DESCRIPTORS_END 0xf
26+
/* sizeof ignores the data as it's a flexible array */
27+
#define BINDESC_ENTRY_HEADER_SIZE (sizeof(struct bindesc_entry))
2628

2729
/**
2830
* @brief Binary Descriptor Definition
@@ -131,11 +133,18 @@ extern "C" {
131133
*/
132134
#define BINDESC_TAG(type, id) ((BINDESC_TYPE_##type & 0xf) << 12 | (id & 0x0fff))
133135

136+
/**
137+
* @brief Utility macro to get the type of a bindesc tag
138+
*
139+
* @param tag Tag to get the type of
140+
*/
141+
#define BINDESC_GET_TAG_TYPE(tag) ((tag >> 12) & 0xf)
142+
134143
/**
135144
* @endcond
136145
*/
137146

138-
#if !defined(_LINKER)
147+
#if !defined(_LINKER) || defined(__DOXYGEN__)
139148

140149
#include <zephyr/sys/byteorder.h>
141150

@@ -278,6 +287,10 @@ extern "C" {
278287
*/
279288
#define BINDESC_GET_SIZE(name) BINDESC_NAME(name).len
280289

290+
/**
291+
* @}
292+
*/
293+
281294
/*
282295
* An entry of the binary descriptor header. Each descriptor is
283296
* described by one of these entries.
@@ -301,6 +314,176 @@ BUILD_ASSERT(offsetof(struct bindesc_entry, tag) == 0, "Incorrect memory layout"
301314
BUILD_ASSERT(offsetof(struct bindesc_entry, len) == 2, "Incorrect memory layout");
302315
BUILD_ASSERT(offsetof(struct bindesc_entry, data) == 4, "Incorrect memory layout");
303316

317+
struct bindesc_handle {
318+
const uint8_t *address;
319+
enum {
320+
BINDESC_HANDLE_TYPE_RAM,
321+
BINDESC_HANDLE_TYPE_MEMORY_MAPPED_FLASH,
322+
BINDESC_HANDLE_TYPE_FLASH,
323+
} type;
324+
size_t size_limit;
325+
#if IS_ENABLED(CONFIG_BINDESC_READ_FLASH)
326+
const struct device *flash_device;
327+
uint8_t buffer[sizeof(struct bindesc_entry) +
328+
CONFIG_BINDESC_READ_FLASH_MAX_DATA_SIZE] __aligned(BINDESC_ALIGNMENT);
329+
#endif /* IS_ENABLED(CONFIG_BINDESC_READ_FLASH) */
330+
};
331+
332+
/**
333+
* @brief Reading Binary Descriptors of other images.
334+
* @defgroup bindesc_read Bindesc Read
335+
* @ingroup os_services
336+
* @{
337+
*/
338+
339+
/**
340+
* @brief Callback type to be called on descriptors found during a walk
341+
*
342+
* @param entry Current descriptor
343+
* @param user_data The user_data given to @ref bindesc_foreach
344+
*
345+
* @return Any non zero value will halt the walk
346+
*/
347+
typedef int (*bindesc_callback_t)(const struct bindesc_entry *entry, void *user_data);
348+
349+
/**
350+
* @brief Open an image's binary descriptors for reading, from a memory mapped flash
351+
*
352+
* @details
353+
* Initializes a bindesc handle for subsequent calls to bindesc API.
354+
* Memory mapped flash is any flash that can be directly accessed by the CPU,
355+
* without needing to use the flash API for copying the data to RAM.
356+
*
357+
* @param handle Bindesc handle to be given to subsequent calls
358+
* @param offset The offset from the beginning of the flash that the bindesc magic can be found at
359+
*
360+
* @retval 0 On success
361+
* @retval -ENOENT If no bindesc magic was found at the given offset
362+
*/
363+
int bindesc_open_memory_mapped_flash(struct bindesc_handle *handle, size_t offset);
364+
365+
/**
366+
* @brief Open an image's binary descriptors for reading, from RAM
367+
*
368+
* @details
369+
* Initializes a bindesc handle for subsequent calls to bindesc API.
370+
* It's assumed that the whole bindesc context was copied to RAM prior to calling
371+
* this function, either by the user or by a bootloader.
372+
*
373+
* @note The given address must be aligned to BINDESC_ALIGNMENT
374+
*
375+
* @param handle Bindesc handle to be given to subsequent calls
376+
* @param address The address that the bindesc magic can be found at
377+
* @param max_size Maximum size of the given buffer
378+
*
379+
* @retval 0 On success
380+
* @retval -ENOENT If no bindesc magic was found at the given address
381+
* @retval -EINVAL If the given address is not aligned
382+
*/
383+
int bindesc_open_ram(struct bindesc_handle *handle, const uint8_t *address, size_t max_size);
384+
385+
/**
386+
* @brief Open an image's binary descriptors for reading, from flash
387+
*
388+
* @details
389+
* Initializes a bindesc handle for subsequent calls to bindesc API.
390+
* As opposed to reading bindesc from RAM or memory mapped flash, this
391+
* backend requires reading the data from flash to an internal buffer
392+
* using the flash API
393+
*
394+
* @param handle Bindesc handle to be given to subsequent calls
395+
* @param offset The offset from the beginning of the flash that the bindesc magic can be found at
396+
* @param flash_device Flash device to read descriptors from
397+
*
398+
* @retval 0 On success
399+
* @retval -ENOENT If no bindesc magic was found at the given offset
400+
*/
401+
int bindesc_open_flash(struct bindesc_handle *handle, size_t offset,
402+
const struct device *flash_device);
403+
404+
/**
405+
* @brief Walk the binary descriptors and run a user defined callback on each of them
406+
*
407+
* @note
408+
* If the callback returns a non zero value, the walk stops.
409+
*
410+
* @param handle An initialized bindesc handle
411+
* @param callback A user defined callback to be called on each descriptor
412+
* @param user_data User defined data to be given to the callback
413+
*
414+
* @return If the walk was finished prematurely by the callback,
415+
* return the callback's retval, zero otherwise
416+
*/
417+
int bindesc_foreach(struct bindesc_handle *handle, bindesc_callback_t callback, void *user_data);
418+
419+
/**
420+
* @brief Find a specific descriptor of type string
421+
*
422+
* @warning
423+
* When using the flash backend, result will be invalidated by the next call to any bindesc API.
424+
* Use the value immediately or copy it elsewhere.
425+
*
426+
* @param handle An initialized bindesc handle
427+
* @param id ID to search for
428+
* @param result Pointer to the found string
429+
*
430+
* @retval 0 If the descriptor was found
431+
* @retval -ENOENT If the descriptor was not found
432+
*/
433+
int bindesc_find_str(struct bindesc_handle *handle, uint16_t id, const char **result);
434+
435+
/**
436+
* @brief Find a specific descriptor of type uint
437+
*
438+
* @warning
439+
* When using the flash backend, result will be invalidated by the next call to any bindesc API.
440+
* Use the value immediately or copy it elsewhere.
441+
*
442+
* @param handle An initialized bindesc handle
443+
* @param id ID to search for
444+
* @param result Pointer to the found uint
445+
*
446+
* @retval 0 If the descriptor was found
447+
* @retval -ENOENT If the descriptor was not found
448+
*/
449+
int bindesc_find_uint(struct bindesc_handle *handle, uint16_t id, const uint32_t **result);
450+
451+
/**
452+
* @brief Find a specific descriptor of type bytes
453+
*
454+
* @warning
455+
* When using the flash backend, result will be invalidated by the next call to any bindesc API.
456+
* Use the value immediately or copy it elsewhere.
457+
*
458+
* @param handle An initialized bindesc handle
459+
* @param id ID to search for
460+
* @param result Pointer to the found bytes
461+
* @param result_size Size of the found bytes
462+
*
463+
* @retval 0 If the descriptor was found
464+
* @retval -ENOENT If the descriptor was not found
465+
*/
466+
int bindesc_find_bytes(struct bindesc_handle *handle, uint16_t id, const uint8_t **result,
467+
size_t *result_size);
468+
469+
/**
470+
* @brief Get the size of an image's binary descriptors
471+
*
472+
* @details
473+
* Walks the binary descriptor structure to caluculate the total size of the structure
474+
* in bytes. This is useful, for instance, if the whole structure is to be copied to RAM.
475+
*
476+
* @param handle An initialized bindesc handle
477+
* @param result Pointer to write result to
478+
*
479+
* @return 0 On success, negative errno otherwise
480+
*/
481+
int bindesc_get_size(struct bindesc_handle *handle, size_t *result);
482+
483+
/**
484+
* @}
485+
*/
486+
304487
#if defined(CONFIG_BINDESC_KERNEL_VERSION_STRING)
305488
extern const struct bindesc_entry BINDESC_NAME(kernel_version_string);
306489
#endif /* defined(CONFIG_BINDESC_KERNEL_VERSION_STRING) */
@@ -411,10 +594,6 @@ extern const struct bindesc_entry BINDESC_NAME(cxx_compiler_version);
411594

412595
#endif /* !defined(_LINKER) */
413596

414-
/**
415-
* @}
416-
*/
417-
418597
#ifdef __cplusplus
419598
}
420599
#endif

subsys/bindesc/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,5 @@ if(CONFIG_BINDESC_DEFINE_HOST_INFO)
6666
gen_str_definition(CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER_ID})
6767
gen_str_definition(CXX_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
6868
endif()
69+
70+
zephyr_library_sources_ifdef(CONFIG_BINDESC_READ bindesc_read.c)

subsys/bindesc/Kconfig

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,46 @@ config BINDESC_DEFINE_MAX_DATA_SIZE
3131

3232
endif # BINDESC_DEFINE
3333

34+
config BINDESC_READ
35+
bool "Binary Descriptors Read"
36+
help
37+
Enable the app to read the binary descriptors of another image
38+
39+
if BINDESC_READ
40+
41+
module = BINDESC_READ
42+
module-str = Binary Descriptor read
43+
source "subsys/logging/Kconfig.template.log_config"
44+
45+
config BINDESC_READ_RAM
46+
bool "Bindesc read from RAM"
47+
help
48+
Enable reading and parsing binary descriptors from RAM.
49+
50+
config BINDESC_READ_MEMORY_MAPPED_FLASH
51+
bool "Bindesc read from memory mapped flash"
52+
help
53+
Enable reading and parsing binary descriptors from memory mapped flash.
54+
55+
config BINDESC_READ_FLASH
56+
bool "Bindesc read from flash"
57+
help
58+
Enable reading and parsing binary descriptors from non memory mapped flash
59+
(e.g. external flash).
60+
61+
if BINDESC_READ_FLASH
62+
63+
config BINDESC_READ_FLASH_MAX_DATA_SIZE
64+
int "Bindesc read flash max data size"
65+
range 4 $(UINT16_MAX)
66+
default 128
67+
help
68+
The maximum expected size of the descriptors' data. This should be set to
69+
the value set to BINDESC_DEFINE_MAX_DATA_SIZE by the read image.
70+
Any descriptor that exceeds this size will be ignored.
71+
72+
endif # BINDESC_READ_FLASH
73+
74+
endif # BINDESC_READ
75+
3476
endif # BINDESC

0 commit comments

Comments
 (0)