boot_serial: Upgrade from cddl-gen 0.1.0 to zcbor 0.4.0
cddl-gen has been renamed to zcbor.
Update regenerate_serial_recovery_cbor.sh and regenerate/recopy all
files.
Remove the submodule in ext/ since it is no longer necessary when
the zcbor package is installed (only needed for regeneration, not
for building).
Signed-off-by: Øyvind Rønningstad <oyvind.ronningstad@nordicsemi.no>
diff --git a/.gitmodules b/.gitmodules
index dcd3a70..bf510c9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -19,9 +19,6 @@
[submodule "boot/cypress/libs/cy-mbedtls-acceleration"]
path = boot/cypress/libs/cy-mbedtls-acceleration
url = https://github.com/cypresssemiconductorco/cy-mbedtls-acceleration.git
-[submodule "ext/cddl-gen"]
- path = ext/cddl-gen
- url = https://github.com/NordicSemiconductor/cddl-gen.git
[submodule "boot/espressif/hal/esp-idf"]
path = boot/espressif/hal/esp-idf
url = https://github.com/espressif/esp-idf.git
diff --git a/.mbedignore b/.mbedignore
index 06a173e..5dd4ea2 100644
--- a/.mbedignore
+++ b/.mbedignore
@@ -11,7 +11,6 @@
scripts/*
sim/*
testplan/*
-ext/cddl_gen/*
ext/fiat/*
ext/mbedtls/*
ext/mbedtls-asn1/*
diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c
index a11284f..4a4a63d 100644
--- a/boot/boot_serial/src/boot_serial.c
+++ b/boot/boot_serial/src/boot_serial.c
@@ -25,7 +25,7 @@
#include "sysflash/sysflash.h"
#include "bootutil/bootutil_log.h"
-#include "cbor_encode.h"
+#include "zcbor_encode.h"
#ifdef __ZEPHYR__
#include <sys/reboot.h>
@@ -99,17 +99,12 @@
static void boot_serial_output(void);
-static cbor_state_backups_t dummy_backups;
-static cbor_state_t cbor_state = {
- .backups = &dummy_backups
-};
+static zcbor_state_t cbor_state[2];
void reset_cbor_state(void)
{
- cbor_state.payload_mut = (uint8_t *)bs_obuf;
- cbor_state.payload_end = (const uint8_t *)bs_obuf
- + sizeof(bs_obuf);
- cbor_state.elem_count = 0;
+ zcbor_new_encode_state(cbor_state, 2, (uint8_t *)bs_obuf,
+ (size_t)bs_obuf + sizeof(bs_obuf), 0);
}
/**
@@ -126,7 +121,7 @@
*/
extern int bs_peruser_system_specific(const struct nmgr_hdr *hdr,
const char *buffer,
- int len, cbor_state_t *cs);
+ int len, zcbor_state_t *cs);
/*
* Convert version into string without use of snprintf().
@@ -157,6 +152,9 @@
return dst - tgt;
}
+#define zcbor_tstr_put_lit_cast(state, string) \
+ zcbor_tstr_encode_ptr(state, (uint8_t *)string, sizeof(string) - 1)
+
/*
* dst has to be able to fit "255.255.65535.4294967295" (25 characters).
*/
@@ -186,9 +184,9 @@
const struct flash_area *fap;
uint8_t image_index;
- map_start_encode(&cbor_state, 1);
- tstrx_put(&cbor_state, "images");
- list_start_encode(&cbor_state, 5);
+ zcbor_map_start_encode(cbor_state, 1);
+ zcbor_tstr_put_lit_cast(cbor_state, "images");
+ zcbor_list_start_encode(cbor_state, 5);
image_index = 0;
IMAGES_ITER(image_index) {
for (slot = 0; slot < 2; slot++) {
@@ -235,24 +233,24 @@
continue;
}
- map_start_encode(&cbor_state, 20);
+ zcbor_map_start_encode(cbor_state, 20);
#if (BOOT_IMAGE_NUMBER > 1)
- tstrx_put(&cbor_state, "image");
- uintx32_put(&cbor_state, image_index);
+ zcbor_tstr_put_lit_cast(cbor_state, "image");
+ zcbor_uint32_put(cbor_state, image_index);
#endif
- tstrx_put(&cbor_state, "slot");
- uintx32_put(&cbor_state, slot);
- tstrx_put(&cbor_state, "version");
+ zcbor_tstr_put_lit_cast(cbor_state, "slot");
+ zcbor_uint32_put(cbor_state, slot);
+ zcbor_tstr_put_lit_cast(cbor_state, "version");
bs_list_img_ver((char *)tmpbuf, sizeof(tmpbuf), &hdr.ih_ver);
- tstrx_put_term(&cbor_state, (char *)tmpbuf);
- map_end_encode(&cbor_state, 20);
+ zcbor_tstr_encode_ptr(cbor_state, tmpbuf, strlen((char *)tmpbuf));
+ zcbor_map_end_encode(cbor_state, 20);
}
}
- list_end_encode(&cbor_state, 5);
- map_end_encode(&cbor_state, 1);
+ zcbor_list_end_encode(cbor_state, 5);
+ zcbor_map_end_encode(cbor_state, 1);
boot_serial_output();
}
@@ -289,15 +287,15 @@
*/
struct Upload upload;
- uint32_t decoded_len;
- bool result = cbor_decode_Upload((const uint8_t *)buf, len, &upload, &decoded_len);
+ size_t decoded_len;
+ uint_fast8_t result = cbor_decode_Upload((const uint8_t *)buf, len, &upload, &decoded_len);
- if (!result || (len != decoded_len)) {
+ if ((result != ZCBOR_SUCCESS) || (len != decoded_len)) {
goto out_invalid_data;
}
for (int i = 0; i < upload._Upload_members_count; i++) {
- struct Member_ *member = &upload._Upload_members[i];
+ struct Member_ *member = &upload._Upload_members[i]._Upload_members;
switch(member->_Member_choice) {
case _Member_image:
img_num = member->_Member_image;
@@ -458,14 +456,14 @@
out:
BOOT_LOG_INF("RX: 0x%x", rc);
- map_start_encode(&cbor_state, 10);
- tstrx_put(&cbor_state, "rc");
- uintx32_put(&cbor_state, rc);
+ zcbor_map_start_encode(cbor_state, 10);
+ zcbor_tstr_put_lit_cast(cbor_state, "rc");
+ zcbor_uint32_put(cbor_state, rc);
if (rc == 0) {
- tstrx_put(&cbor_state, "off");
- uintx32_put(&cbor_state, curr_off);
+ zcbor_tstr_put_lit_cast(cbor_state, "off");
+ zcbor_uint32_put(cbor_state, curr_off);
}
- map_end_encode(&cbor_state, 10);
+ zcbor_map_end_encode(cbor_state, 10);
boot_serial_output();
flash_area_close(fap);
@@ -484,10 +482,10 @@
static void
bs_rc_rsp(int rc_code)
{
- map_start_encode(&cbor_state, 10);
- tstrx_put(&cbor_state, "rc");
- uintx32_put(&cbor_state, rc_code);
- map_end_encode(&cbor_state, 10);
+ zcbor_map_start_encode(cbor_state, 10);
+ zcbor_tstr_put_lit_cast(cbor_state, "rc");
+ zcbor_uint32_put(cbor_state, rc_code);
+ zcbor_map_end_encode(cbor_state, 10);
boot_serial_output();
}
@@ -605,7 +603,7 @@
break;
}
} else if (MCUBOOT_PERUSER_MGMT_GROUP_ENABLED == 1) {
- if (bs_peruser_system_specific(hdr, buf, len, &cbor_state) == 0) {
+ if (bs_peruser_system_specific(hdr, buf, len, cbor_state) == 0) {
boot_serial_output();
}
} else {
@@ -628,7 +626,7 @@
char encoded_buf[BASE64_ENCODE_SIZE(sizeof(buf))];
data = bs_obuf;
- len = (uint32_t)cbor_state.payload_mut - (uint32_t)bs_obuf;
+ len = (uint32_t)cbor_state->payload_mut - (uint32_t)bs_obuf;
bs_hdr->nh_op++;
bs_hdr->nh_flags = 0;
diff --git a/boot/boot_serial/src/cbor_common.c b/boot/boot_serial/src/cbor_common.c
deleted file mode 100644
index 8a4cd9c..0000000
--- a/boot/boot_serial/src/cbor_common.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file has been copied from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2020 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stddef.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <string.h>
-#include "cbor_common.h"
-
-_Static_assert((sizeof(size_t) == sizeof(void *)),
- "This code needs size_t to be the same length as pointers.");
-
-bool new_backup(cbor_state_t *state, uint32_t new_elem_count)
-{
- if ((state->backups->current_backup + 1)
- >= state->backups->num_backups) {
- FAIL();
- }
-
- uint32_t i = ++(state->backups->current_backup);
- memcpy(&state->backups->backup_list[i], state,
- sizeof(cbor_state_t));
-
- state->elem_count = new_elem_count;
-
- return true;
-}
-
-
-bool restore_backup(cbor_state_t *state, uint32_t flags,
- uint32_t max_elem_count)
-{
- const uint8_t *payload = state->payload;
- const uint32_t elem_count = state->elem_count;
-
- if (state->backups->current_backup == 0) {
- FAIL();
- }
-
- if (flags & FLAG_RESTORE) {
- uint32_t i = state->backups->current_backup;
-
- memcpy(state, &state->backups->backup_list[i],
- sizeof(cbor_state_t));
- }
-
- if (flags & FLAG_DISCARD) {
- state->backups->current_backup--;
- }
-
- if (elem_count > max_elem_count) {
- cbor_print("elem_count: %d (expected max %d)\r\n",
- elem_count, max_elem_count);
- FAIL();
- }
-
- if (flags & FLAG_TRANSFER_PAYLOAD) {
- state->payload = payload;
- }
-
- return true;
-}
-
-
-bool union_start_code(cbor_state_t *state)
-{
- if (!new_backup(state, state->elem_count)) {
- FAIL();
- }
- return true;
-}
-
-
-bool union_elem_code(cbor_state_t *state)
-{
- if (!restore_backup(state, FLAG_RESTORE, state->elem_count)) {
- FAIL();
- }
- return true;
-}
-
-bool union_end_code(cbor_state_t *state)
-{
- if (!restore_backup(state, FLAG_DISCARD, state->elem_count)) {
- FAIL();
- }
- return true;
-}
-
-bool entry_function(const uint8_t *payload, uint32_t payload_len,
- const void *struct_ptr, uint32_t *payload_len_out,
- cbor_encoder_t func, uint32_t elem_count, uint32_t num_backups)
-{
- cbor_state_t state = {
- .payload = payload,
- .payload_end = payload + payload_len,
- .elem_count = elem_count,
- };
-
- cbor_state_t state_backups[num_backups + 1];
-
- cbor_state_backups_t backups = {
- .backup_list = state_backups,
- .current_backup = 0,
- .num_backups = num_backups + 1,
- };
-
- state.backups = &backups;
-
- bool result = func(&state, struct_ptr);
-
- if (result && (payload_len_out != NULL)) {
- *payload_len_out = MIN(payload_len,
- (size_t)state.payload - (size_t)payload);
- }
- return result;
-}
diff --git a/boot/boot_serial/src/cbor_common.h b/boot/boot_serial/src/cbor_common.h
deleted file mode 100644
index e652908..0000000
--- a/boot/boot_serial/src/cbor_common.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file has been copied from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2020 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#ifndef CBOR_COMMON_H__
-#define CBOR_COMMON_H__
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-
-
-/** Convenience type that allows pointing to strings directly inside the payload
- * without the need to copy out.
- */
-typedef struct
-{
- const uint8_t *value;
- uint32_t len;
-} cbor_string_type_t;
-
-#ifdef CDDL_CBOR_VERBOSE
-#include <sys/printk.h>
-#define cbor_trace() (printk("bytes left: %d, byte: 0x%x, elem_count: 0x%zx, %s:%d\n",\
- (uint32_t)state->payload_end - (uint32_t)state->payload, *state->payload, state->elem_count,\
- __FILE__, __LINE__))
-#define cbor_assert(expr, ...) \
-do { \
- if (!(expr)) { \
- printk("ASSERTION \n \"" #expr \
- "\"\nfailed at %s:%d with message:\n ", \
- __FILE__, __LINE__); \
- printk(__VA_ARGS__);\
- return false; \
- } \
-} while(0)
-#define cbor_print(...) printk(__VA_ARGS__)
-#else
-#define cbor_trace() ((void)state)
-#define cbor_assert(...)
-#define cbor_print(...)
-#endif
-
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-
-
-struct cbor_state_backups_s;
-
-typedef struct cbor_state_backups_s cbor_state_backups_t;
-
-typedef struct{
-union {
- uint8_t *payload_mut;
- uint8_t const *payload; /**< The current place in the payload. Will be
- updated when an element is correctly
- processed. */
-};
- uint8_t const *payload_bak; /**< Temporary backup of payload. */
- uint32_t elem_count; /**< The current element is part of a LIST or a MAP,
- and this keeps count of how many elements are
- expected. This will be checked before processing
- and decremented if the element is correctly
- processed. */
- uint8_t const *payload_end; /**< The end of the payload. This will be
- checked against payload before
- processing each element. */
- cbor_state_backups_t *backups;
-} cbor_state_t;
-
-struct cbor_state_backups_s{
- cbor_state_t *backup_list;
- uint32_t current_backup;
- uint32_t num_backups;
-};
-
-/** Function pointer type used with multi_decode.
- *
- * This type is compatible with all decoding functions here and in the generated
- * code, except for multi_decode.
- */
-typedef bool(cbor_encoder_t)(cbor_state_t *, const void *);
-typedef bool(cbor_decoder_t)(cbor_state_t *, void *);
-
-/** Enumeration representing the major types available in CBOR.
- *
- * The major type is represented in the 3 first bits of the header byte.
- */
-typedef enum
-{
- CBOR_MAJOR_TYPE_PINT = 0, ///! Positive Integer
- CBOR_MAJOR_TYPE_NINT = 1, ///! Negative Integer
- CBOR_MAJOR_TYPE_BSTR = 2, ///! Byte String
- CBOR_MAJOR_TYPE_TSTR = 3, ///! Text String
- CBOR_MAJOR_TYPE_LIST = 4, ///! List
- CBOR_MAJOR_TYPE_MAP = 5, ///! Map
- CBOR_MAJOR_TYPE_TAG = 6, ///! Semantic Tag
- CBOR_MAJOR_TYPE_PRIM = 7, ///! Primitive Type
-} cbor_major_type_t;
-
-/** Shorthand macro to check if a result is within min/max constraints.
- */
-#define PTR_VALUE_IN_RANGE(type, res, min, max) \
- (((min == NULL) || (*(type *)res >= *(type *)min)) \
- && ((max == NULL) || (*(type *)res <= *(type *)max)))
-
-#define FAIL() \
-do {\
- cbor_trace(); \
- return false; \
-} while(0)
-
-
-#define VALUE_IN_HEADER 23 /**! For values below this, the value is encoded
- directly in the header. */
-
-#define BOOL_TO_PRIM 20 ///! In CBOR, false/true have the values 20/21
-
-#define FLAG_RESTORE 1UL
-#define FLAG_DISCARD 2UL
-#define FLAG_TRANSFER_PAYLOAD 4UL
-
-bool new_backup(cbor_state_t *state, uint32_t new_elem_count);
-
-bool restore_backup(cbor_state_t *state, uint32_t flags,
- uint32_t max_elem_count);
-
-bool union_start_code(cbor_state_t *state);
-
-bool union_elem_code(cbor_state_t *state);
-
-bool union_end_code(cbor_state_t *state);
-
-bool entry_function(const uint8_t *payload, uint32_t payload_len,
- const void *struct_ptr, uint32_t *payload_len_out,
- cbor_encoder_t func, uint32_t elem_count, uint32_t num_backups);
-
-#endif /* CBOR_COMMON_H__ */
diff --git a/boot/boot_serial/src/cbor_decode.c b/boot/boot_serial/src/cbor_decode.c
deleted file mode 100644
index 9707729..0000000
--- a/boot/boot_serial/src/cbor_decode.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * This file has been copied from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2020 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include "cbor_decode.h"
-#include "cbor_common.h"
-
-
-/** Return value length from additional value.
- */
-static uint32_t additional_len(uint8_t additional)
-{
- if (24 <= additional && additional <= 27) {
- /* 24 => 1
- * 25 => 2
- * 26 => 4
- * 27 => 8
- */
- return 1 << (additional - 24);
- }
- return 0;
-}
-
-/** Extract the major type, i.e. the first 3 bits of the header byte. */
-#define MAJOR_TYPE(header_byte) (((header_byte) >> 5) & 0x7)
-
-/** Extract the additional info, i.e. the last 5 bits of the header byte. */
-#define ADDITIONAL(header_byte) ((header_byte) & 0x1F)
-
-
-#define FAIL_AND_DECR_IF(expr) \
-do {\
- if (expr) { \
- (state->payload)--; \
- FAIL(); \
- } \
-} while(0)
-
-#define FAIL_IF(expr) \
-do {\
- if (expr) { \
- FAIL(); \
- } \
-} while(0)
-
-
-#define FAIL_RESTORE() \
- state->payload = state->payload_bak; \
- state->elem_count++; \
- FAIL()
-
-/** Get a single value.
- *
- * @details @p ppayload must point to the header byte. This function will
- * retrieve the value (either from within the additional info, or from
- * the subsequent bytes) and return it in the result. The result can
- * have arbitrary length.
- *
- * The function will also validate
- * - Min/max constraints on the value.
- * - That @p payload doesn't overrun past @p payload_end.
- * - That @p elem_count has not been exhausted.
- *
- * @p ppayload and @p elem_count are updated if the function
- * succeeds. If not, they are left unchanged.
- *
- * CBOR values are always big-endian, so this function converts from
- * big to little-endian if necessary (@ref CONFIG_BIG_ENDIAN).
- */
-static bool value_extract(cbor_state_t *state,
- void *const result, uint32_t result_len)
-{
- cbor_trace();
- cbor_assert(result_len != 0, "0-length result not supported.\n");
- cbor_assert(result != NULL, NULL);
-
- FAIL_IF((state->elem_count == 0) \
- || (state->payload >= state->payload_end));
-
- uint8_t *u8_result = (uint8_t *)result;
- uint8_t additional = ADDITIONAL(*state->payload);
-
- state->payload_bak = state->payload;
- (state->payload)++;
-
- memset(result, 0, result_len);
- if (additional <= VALUE_IN_HEADER) {
-#ifdef CONFIG_BIG_ENDIAN
- u8_result[result_len - 1] = additional;
-#else
- u8_result[0] = additional;
-#endif /* CONFIG_BIG_ENDIAN */
- } else {
- uint32_t len = additional_len(additional);
-
- FAIL_AND_DECR_IF(len > result_len);
- FAIL_AND_DECR_IF((state->payload + len)
- > state->payload_end);
-
-#ifdef CONFIG_BIG_ENDIAN
- memcpy(&u8_result[result_len - len], state->payload, len);
-#else
- for (uint32_t i = 0; i < len; i++) {
- u8_result[i] = (state->payload)[len - i - 1];
- }
-#endif /* CONFIG_BIG_ENDIAN */
-
- (state->payload) += len;
- }
-
- (state->elem_count)--;
- return true;
-}
-
-
-static bool int32_decode(cbor_state_t *state, int32_t *result)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
- uint32_t uint_result;
- int32_t int_result;
-
- if (!value_extract(state, &uint_result, 4)) {
- FAIL();
- }
-
- cbor_print("uintval: %u\r\n", uint_result);
- if (uint_result >= (1 << (8*sizeof(uint_result)-1))) {
- /* Value is too large to fit in a signed integer. */
- FAIL_RESTORE();
- }
-
- if (major_type == CBOR_MAJOR_TYPE_NINT) {
- /* Convert from CBOR's representation. */
- int_result = -1 - uint_result;
- } else {
- int_result = uint_result;
- }
-
- cbor_print("val: %d\r\n", int_result);
- *result = int_result;
- return true;
-}
-
-
-bool intx32_decode(cbor_state_t *state, int32_t *result)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
-
- if (major_type != CBOR_MAJOR_TYPE_PINT
- && major_type != CBOR_MAJOR_TYPE_NINT) {
- /* Value to be read doesn't have the right type. */
- FAIL();
- }
-
- if (!int32_decode(state, result)) {
- FAIL();
- }
- return true;
-}
-
-bool intx32_expect(cbor_state_t *state, int32_t result)
-{
- int32_t value;
-
- if (!intx32_decode(state, &value)) {
- FAIL();
- }
-
- if (value != result) {
- cbor_print("%d != %d\r\n", value, result);
- FAIL_RESTORE();
- }
- return true;
-}
-
-
-static bool uint32_decode(cbor_state_t *state, uint32_t *result)
-{
- if (!value_extract(state, result, 4)) {
- FAIL();
- }
-
- return true;
-}
-
-
-bool uintx32_decode(cbor_state_t *state, uint32_t *result)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
-
- if (major_type != CBOR_MAJOR_TYPE_PINT) {
- /* Value to be read doesn't have the right type. */
- FAIL();
- }
- if (!uint32_decode(state, result)) {
- FAIL();
- }
- return true;
-}
-
-bool uintx32_expect(cbor_state_t *state, uint32_t result)
-{
- uint32_t value;
-
- if (!uintx32_decode(state, &value)) {
- FAIL();
- }
- if (value != result) {
- cbor_print("%u != %u\r\n", value, result);
- FAIL_RESTORE();
- }
- return true;
-}
-
-bool uintx32_expect_union(cbor_state_t *state, uint32_t result)
-{
- union_elem_code(state);
- return uintx32_expect(state, result);
-}
-
-
-static bool strx_start_decode(cbor_state_t *state,
- cbor_string_type_t *result, cbor_major_type_t exp_major_type)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
-
- if (major_type != exp_major_type) {
- FAIL();
- }
-
- if (!uint32_decode(state, &result->len)) {
- FAIL();
- }
-
- if (result->len > (state->payload_end - state->payload)) {
- cbor_print("error: 0x%x > 0x%x\r\n",
- (uint32_t)result->len,
- (uint32_t)(state->payload_end - state->payload));
- FAIL_RESTORE();
- }
-
- result->value = state->payload;
- return true;
-}
-
-bool bstrx_cbor_start_decode(cbor_state_t *state, cbor_string_type_t *result)
-{
- if(!strx_start_decode(state, result, CBOR_MAJOR_TYPE_BSTR)) {
- FAIL();
- }
-
- if (!new_backup(state, 0xFFFFFFFF)) {
- FAIL_RESTORE();
- }
-
- /* Overflow is checked in strx_start_decode() */
- state->payload_end = result->value + result->len;
- return true;
-}
-
-bool bstrx_cbor_end_decode(cbor_state_t *state)
-{
- if (state->payload != state->payload_end) {
- FAIL();
- }
- if (!restore_backup(state,
- FLAG_RESTORE | FLAG_DISCARD | FLAG_TRANSFER_PAYLOAD,
- 0xFFFFFFFF)) {
- FAIL();
- }
-
- return true;
-}
-
-
-bool strx_decode(cbor_state_t *state, cbor_string_type_t *result,
- cbor_major_type_t exp_major_type)
-{
- if (!strx_start_decode(state, result, exp_major_type)) {
- FAIL();
- }
-
- /* Overflow is checked in strx_start_decode() */
- (state->payload) += result->len;
- return true;
-}
-
-
-bool strx_expect(cbor_state_t *state, cbor_string_type_t *result,
- cbor_major_type_t exp_major_type)
-{
- cbor_string_type_t tmp_result;
-
- if (!strx_decode(state, &tmp_result, exp_major_type)) {
- FAIL();
- }
- if ((tmp_result.len != result->len)
- || memcmp(result->value, tmp_result.value, tmp_result.len)) {
- FAIL_RESTORE();
- }
- return true;
-}
-
-
-bool bstrx_decode(cbor_state_t *state, cbor_string_type_t *result)
-{
- return strx_decode(state, result, CBOR_MAJOR_TYPE_BSTR);
-}
-
-
-bool bstrx_expect(cbor_state_t *state, cbor_string_type_t *result)
-{
- return strx_expect(state, result, CBOR_MAJOR_TYPE_BSTR);
-}
-
-
-bool tstrx_decode(cbor_state_t *state, cbor_string_type_t *result)
-{
- return strx_decode(state, result, CBOR_MAJOR_TYPE_TSTR);
-}
-
-
-bool tstrx_expect(cbor_state_t *state, cbor_string_type_t *result)
-{
- return strx_expect(state, result, CBOR_MAJOR_TYPE_TSTR);
-}
-
-
-static bool list_map_start_decode(cbor_state_t *state,
- cbor_major_type_t exp_major_type)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
- uint32_t new_elem_count;
-
- if (major_type != exp_major_type) {
- FAIL();
- }
-
- if (!uint32_decode(state, &new_elem_count)) {
- FAIL();
- }
-
- if (!new_backup(state, new_elem_count)) {
- FAIL_RESTORE();
- }
-
- return true;
-}
-
-
-bool list_start_decode(cbor_state_t *state)
-{
- return list_map_start_decode(state, CBOR_MAJOR_TYPE_LIST);
-}
-
-
-bool map_start_decode(cbor_state_t *state)
-{
- bool ret = list_map_start_decode(state, CBOR_MAJOR_TYPE_MAP);
-
- if (ret) {
- state->elem_count *= 2;
- }
- return ret;
-}
-
-
-bool list_map_end_decode(cbor_state_t *state)
-{
- if (!restore_backup(state,
- FLAG_RESTORE | FLAG_DISCARD | FLAG_TRANSFER_PAYLOAD,
- 0)) {
- FAIL();
- }
-
- return true;
-}
-
-
-bool list_end_decode(cbor_state_t *state)
-{
- return list_map_end_decode(state);
-}
-
-
-bool map_end_decode(cbor_state_t *state)
-{
- return list_map_end_decode(state);
-}
-
-
-static bool primx_decode(cbor_state_t *state, uint32_t *result)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
-
- if (major_type != CBOR_MAJOR_TYPE_PRIM) {
- /* Value to be read doesn't have the right type. */
- FAIL();
- }
- if (!uint32_decode(state, result)) {
- FAIL();
- }
- if (*result > 0xFF) {
- FAIL_RESTORE();
- }
- return true;
-}
-
-static bool primx_expect(cbor_state_t *state, uint32_t result)
-{
- uint32_t value;
-
- if (!primx_decode(state, &value)) {
- FAIL();
- }
- if (value != result) {
- FAIL_RESTORE();
- }
- return true;
-}
-
-
-bool nilx_expect(cbor_state_t *state, void *result)
-{
- if (!primx_expect(state, 22)) {
- FAIL();
- }
- return true;
-}
-
-
-bool boolx_decode(cbor_state_t *state, bool *result)
-{
- uint32_t tmp_result;
-
- if (!primx_decode(state, &tmp_result)) {
- FAIL();
- }
- (*result) = tmp_result - BOOL_TO_PRIM;
-
- cbor_print("boolval: %u\r\n", *result);
- return true;
-}
-
-
-bool boolx_expect(cbor_state_t *state, bool result)
-{
- bool value;
-
- if (!boolx_decode(state, &value)) {
- FAIL();
- }
- if (value != result) {
- FAIL_RESTORE();
- }
- return true;
-}
-
-
-bool double_decode(cbor_state_t *state, double *result)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
-
- if (major_type != CBOR_MAJOR_TYPE_PRIM) {
- /* Value to be read doesn't have the right type. */
- FAIL();
- }
- if (!value_extract(state, result,
- sizeof(*result))) {
- FAIL();
- }
- return true;
-}
-
-
-bool double_expect(cbor_state_t *state, double *result)
-{
- double value;
-
- if (!double_decode(state, &value)) {
- FAIL();
- }
- if (value != *result) {
- FAIL_RESTORE();
- }
- return true;
-}
-
-
-bool any_decode(cbor_state_t *state, void *result)
-{
- cbor_assert(result == NULL,
- "'any' type cannot be returned, only skipped.\n");
-
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
- uint32_t value;
- uint32_t num_decode;
- void *null_result = NULL;
- uint32_t temp_elem_count;
- uint8_t const *payload_bak;
-
- if (!value_extract(state, &value, sizeof(value))) {
- /* Can happen because of elem_count (or payload_end) */
- FAIL();
- }
-
- switch (major_type) {
- case CBOR_MAJOR_TYPE_BSTR:
- case CBOR_MAJOR_TYPE_TSTR:
- (state->payload) += value;
- break;
- case CBOR_MAJOR_TYPE_MAP:
- value *= 2; /* Because all members have a key. */
- /* Fallthrough */
- case CBOR_MAJOR_TYPE_LIST:
- temp_elem_count = state->elem_count;
- payload_bak = state->payload;
- state->elem_count = value;
- if (!multi_decode(value, value, &num_decode,
- (void *)any_decode, state,
- &null_result, 0)) {
- state->elem_count = temp_elem_count;
- state->payload = payload_bak;
- FAIL();
- }
- state->elem_count = temp_elem_count;
- break;
- default:
- /* Do nothing */
- break;
- }
-
- return true;
-}
-
-
-bool tag_decode(cbor_state_t *state, uint32_t *result)
-{
- FAIL_IF(state->payload >= state->payload_end);
- uint8_t major_type = MAJOR_TYPE(*state->payload);
-
- if (major_type != CBOR_MAJOR_TYPE_TAG) {
- /* Value to be read doesn't have the right type. */
- FAIL();
- }
- if (!uint32_decode(state, result)) {
- FAIL();
- }
- state->elem_count++;
- return true;
-}
-
-
-bool tag_expect(cbor_state_t *state, uint32_t result)
-{
- uint32_t tag_val;
-
- if (!tag_decode(state, &tag_val)) {
- FAIL();
- }
- if (tag_val != result) {
- FAIL_RESTORE();
- }
- return true;
-}
-
-
-bool multi_decode(uint32_t min_decode,
- uint32_t max_decode,
- uint32_t *num_decode,
- cbor_decoder_t decoder,
- cbor_state_t *state,
- void *result,
- uint32_t result_len)
-{
- for (uint32_t i = 0; i < max_decode; i++) {
- uint8_t const *payload_bak = state->payload;
- uint32_t elem_count_bak = state->elem_count;
-
- if (!decoder(state,
- (uint8_t *)result + i*result_len)) {
- *num_decode = i;
- state->payload = payload_bak;
- state->elem_count = elem_count_bak;
- if (i < min_decode) {
- FAIL();
- } else {
- cbor_print("Found %zu elements.\n", i);
- }
- return true;
- }
- }
- cbor_print("Found %zu elements.\n", max_decode);
- *num_decode = max_decode;
- return true;
-}
-
-
-bool present_decode(uint32_t *present,
- cbor_decoder_t decoder,
- cbor_state_t *state,
- void *result)
-{
- uint32_t num_decode;
- bool retval = multi_decode(0, 1, &num_decode, decoder, state, result, 0);
- if (retval) {
- *present = num_decode;
- }
- return retval;
-}
diff --git a/boot/boot_serial/src/cbor_decode.h b/boot/boot_serial/src/cbor_decode.h
deleted file mode 100644
index 5bdc800..0000000
--- a/boot/boot_serial/src/cbor_decode.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * This file has been copied from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2020 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#ifndef CBOR_DECODE_H__
-#define CBOR_DECODE_H__
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include "cbor_common.h"
-
-/** The cbor_decode library provides functions for decoding CBOR data elements.
- *
- * This library is primarily meant to be called from code generated by
- * $CDDL_GEN_BASE/cddl_gen/cddl_gen.py script, or its equivalent cddl_gen
- * command line executable.
- *
- * Some details to notice about this library:
- * - Integers are all 32 bits (uint32_t). This means that CBOR's 64 bit values
- * are not supported, even when the code is running on a 64 bit architecture.
- * This applies to integer types, as well as lengths for other types.
- * - Strings are kept in the container type cbor_string_type_t, which is a
- * pointer and a length.
- * - When a function returns false, it only means that decoding that particular
- * value failed. If a value is allowed to take multiple different values,
- * another decoding function can be called if the first fails.
- * - There is some type casting going on under the hood to make the code
- * generator friendly. See especially the processor_t type which is compatible
- * with all functions except multi_decode, but the compiler doesn't "know"
- * this because they are defined with different pointer types. It also means
- * any usage of multi_decode must be made with care for function types.
- *
- *
- * CBOR's format is described well on Wikipedia
- * - https://en.wikipedia.org/wiki/CBOR
- * but here's a synopsis:
- *
- * Encoded CBOR data elements look like this.
- *
- * | Header | Value | Payload |
- * | 1 byte | 0, 1, 2, 4, or 8 bytes | 0 - 2^64-1 bytes/elements |
- * | 3 bits | 5 bits |
- * | Major | Additional|
- * | Type | info |
- *
- * The available major types can be seen in @ref cbor_major_type_t.
- *
- * For all types, Values 0-23 are encoded directly in the "Additional info",
- * meaning that the "Value" field is 0 bytes long. If "Additional info" is 24,
- * 25, 26, or 27, the "Value" field is 1, 2, 4, or 8 bytes long, respectively.
- *
- * Major types PINT, NINT, TAG, and PRIM elements have no payload, only Value.
- * PINT: Interpret the Value as a positive integer.
- * NINT: Interpret the Value as a positive integer, then multiply by -1 and
- * subtract 1.
- * TAG: The Value says something about the next non-tag element.
- * See https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
- * PRIM: Different Values mean different things:
- * 20: "false"
- * 21: "true"
- * 22: "null"
- * 23: "undefined"
- * >=0x10000: Interpret as IEEE 754 float with given precision
- *
- * For BSTR, TSTR, LIST, and MAP, the Value describes the length of the payload.
- * For BSTR and TSTR, the length is in bytes, for LIST, the length is in number
- * of elements, and for MAP, the length is in number of key/value element pairs.
- *
- * For LIST and MAP, sub elements are regular CBOR elements with their own
- * Header, Value and Payload. LISTs and MAPs can be recursively encoded.
- *
- * The additional info means slightly different things for different major
- * types.
- */
-
-/** Decode a PINT/NINT into a int32_t.
- *
- * @param[inout] state The current state of the decoding.
- * @param[out] result Where to place the decoded value.
- *
- * @retval true If the value was decoded correctly.
- * @retval false If the value has the wrong type, the payload overflowed, the
- * element count was exhausted, or the value was larger than can
- * fit in the result variable.
- */
-bool intx32_decode(cbor_state_t *state, int32_t *result);
-
-/** Expect a PINT/NINT with a certain value. Uses intx32_decode internally.
- *
- * @param[inout] state The current state of the decoding.
- * @param[in] result The expected value
- *
- * @retval true If the result was decoded correctly and has the expected value.
- * @retval false If intx32_decode failed or the result doesn't have the
- * expected value.
- */
-bool intx32_expect(cbor_state_t *state, int32_t result);
-
-/** Decode a PINT. */
-bool uintx32_decode(cbor_state_t *state, uint32_t *result);
-bool uintx32_expect(cbor_state_t *state, uint32_t result);
-bool uintx32_expect_union(cbor_state_t *state, uint32_t result);
-
-/** Decode and consume a BSTR header.
- *
- * The rest of the string can be decoded as CBOR.
- * A state backup is created to keep track of the element count.
- *
- * @retval true Header decoded correctly
- * @retval false Header decoded incorrectly, or backup failed.
- */
-bool bstrx_cbor_start_decode(cbor_state_t *state, cbor_string_type_t *result);
-
-/** Finalize decoding a CBOR-encoded bstr.
- *
- * Restore element count from backup.
- */
-bool bstrx_cbor_end_decode(cbor_state_t *state);
-
-/** Decode and consume a BSTR */
-bool bstrx_decode(cbor_state_t *state, cbor_string_type_t *result);
-bool bstrx_expect(cbor_state_t *state, cbor_string_type_t *result);
-
-/** Decode and consume a TSTR */
-bool tstrx_decode(cbor_state_t *state, cbor_string_type_t *result);
-bool tstrx_expect(cbor_state_t *state, cbor_string_type_t *result);
-
-/** Decode and consume a LIST header.
- *
- * The contents of the list can be decoded via subsequent function calls.
- * A state backup is created to keep track of the element count.
- *
- * @retval true Header decoded correctly
- * @retval false Header decoded incorrectly, or backup failed.
- */
-bool list_start_decode(cbor_state_t *state);
-
-/** Decode and consume a MAP header. */
-bool map_start_decode(cbor_state_t *state);
-
-/** Finalize decoding a LIST
- *
- * Check that the list had the correct number of elements, and restore previous
- * element count from backup.
- *
- * @retval true Everything ok.
- * @retval false Element count not correct.
- */
-bool list_end_decode(cbor_state_t *state);
-
-/** Finalize decoding a MAP */
-bool map_end_decode(cbor_state_t *state);
-
-/** Decode a "nil" primitive value. */
-bool nilx_expect(cbor_state_t *state, void *result);
-
-/** Decode a boolean primitive value. */
-bool boolx_decode(cbor_state_t *state, bool *result);
-bool boolx_expect(cbor_state_t *state, bool result);
-
-/** Decode a float */
-bool float_decode(cbor_state_t *state, double *result);
-bool float_expect(cbor_state_t *state, double *result);
-
-/** Skip a single element, regardless of type and value. */
-bool any_decode(cbor_state_t *state, void *result);
-
-/** Decode a tag. */
-bool tag_decode(cbor_state_t *state, uint32_t *result);
-bool tag_expect(cbor_state_t *state, uint32_t result);
-
-/** Decode 0 or more elements with the same type and constraints.
- *
- * @details This must not necessarily decode all elements in a list. E.g. if
- * the list contains 3 INTS between 0 and 100 followed by 0 to 2 BSTRs
- * with length 8, that could be done with:
- *
- * @code{c}
- * uint32_t int_min = 0;
- * uint32_t int_max = 100;
- * uint32_t bstr_size = 8;
- * uint32_t ints[3];
- * cbor_string_type_t bstrs[2];
- * bool res;
- *
- * res = list_start_encode(state, 3, 5);
- * // check res
- * res = multi_encode(3, 3, &num_encode, uintx32_encode, state,
- * ints, &int_min, &int_max, 4);
- * // check res
- * res = multi_encode(0, 2, &num_encode, strx_encode, state,
- * bstrs, &bstr_size, &bstr_size,
- * sizeof(cbor_string_type_t));
- * // check res
- * res = list_end_encode(state, 3, 5);
- * // check res
- * @endcode
- *
- * @param[in] min_decode The minimum acceptable number of elements.
- * @param[in] max_decode The maximum acceptable number of elements.
- * @param[out] num_decode The actual number of elements.
- * @param[in] decoder The decoder function to call under the hood. This
- * function will be called with the provided arguments
- * repeatedly until the function fails (returns false)
- * or until it has been called @p max_decode times.
- * result is moved @p result_len bytes for each call
- * to @p decoder, i.e. @p result refers to an array
- * of result variables.
- * @param[out] result Where to place the decoded values. Must be an array
- * of length at least @p max_decode.
- * @param[in] result_len The length of the result variables. Must be the
- * length matching the elements of @p result.
- *
- * @retval true If at least @p min_decode variables were correctly decoded.
- * @retval false If @p decoder failed before having decoded @p min_decode
- * values.
- */
-bool multi_decode(uint32_t min_decode, uint32_t max_decode, uint32_t *num_decode,
- cbor_decoder_t decoder, cbor_state_t *state, void *result,
- uint32_t result_len);
-
-bool present_decode(uint32_t *present,
- cbor_decoder_t decoder,
- cbor_state_t *state,
- void *result);
-
-#endif /* CBOR_DECODE_H__ */
diff --git a/boot/boot_serial/src/cbor_encode.c b/boot/boot_serial/src/cbor_encode.c
deleted file mode 100644
index d12dc94..0000000
--- a/boot/boot_serial/src/cbor_encode.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * This file has been copied from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2020 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include "cbor_encode.h"
-#include "cbor_common.h"
-
-_Static_assert((sizeof(size_t) == sizeof(void *)),
- "This code needs size_t to be the same length as pointers.");
-
-uint8_t get_additional(uint32_t len, uint8_t value0)
-{
- switch(len) {
- case 0: return value0;
- case 1: return 24;
- case 2: return 25;
- case 3: return 25;
- case 4: return 26;
- case 5: return 26;
- case 6: return 26;
- case 7: return 26;
- case 8: return 27;
- }
-
- cbor_assert(false, NULL);
- return 0;
-}
-
-static bool encode_header_byte(cbor_state_t *state,
- cbor_major_type_t major_type, uint8_t additional)
-{
- if ((state->payload + 1) > state->payload_end) {
- FAIL();
- }
-
- cbor_assert(additional < 32, NULL);
-
- *(state->payload_mut++) = (major_type << 5) | (additional & 0x1F);
- return true;
-}
-
-/** Encode a single value.
- */
-static bool value_encode_len(cbor_state_t *state, cbor_major_type_t major_type,
- const void *const input, uint32_t result_len)
-{
- uint8_t *u8_result = (uint8_t *)input;
-
- if ((state->payload + 1 + result_len) > state->payload_end) {
- FAIL();
- }
-
- if (!encode_header_byte(state, major_type,
- get_additional(result_len, u8_result[0]))) {
- FAIL();
- }
- state->payload_mut--;
- cbor_trace();
- state->payload_mut++;
-
-#ifdef CONFIG_BIG_ENDIAN
- memcpy(state->payload_mut, u8_result, result_len);
- state->payload_mut += result_len;
-#else
- for (; result_len > 0; result_len--) {
- *(state->payload_mut++) = u8_result[result_len - 1];
- }
-#endif
-
- state->elem_count++;
- return true;
-}
-
-
-static uint32_t get_result_len(const void *const input, uint32_t max_result_len)
-{
- uint8_t *u8_result = (uint8_t *)input;
- size_t i;
-
- for (i = 0; i < max_result_len; i++) {
-#ifdef CONFIG_BIG_ENDIAN
- size_t idx = i;
-#else
- size_t idx = max_result_len - 1 - i;
-#endif
- if (u8_result[idx] != 0) {
- break;
- }
- }
- max_result_len -= i;
-
- /* According to specification result length can be encoded on 1, 2, 4
- * or 8 bytes.
- */
- cbor_assert(max_result_len <= 8, "Up to 8 bytes can be used to encode length.\n");
- size_t encode_byte_cnt = 1;
-
- for (size_t i = 0; i <= 3; i++) {
- if (max_result_len <= encode_byte_cnt) {
- max_result_len = encode_byte_cnt;
- break;
- }
-
- encode_byte_cnt *= 2;
- }
-
- if ((max_result_len == 1) && (u8_result[0] <= VALUE_IN_HEADER)) {
- max_result_len = 0;
- }
-
- return max_result_len;
-}
-
-
-static bool value_encode(cbor_state_t *state, cbor_major_type_t major_type,
- const void *const input, uint32_t max_result_len)
-{
- cbor_assert(max_result_len != 0, "0-length result not supported.\n");
- return value_encode_len(state, major_type, input,
- get_result_len(input, max_result_len));
-}
-
-
-bool intx32_put(cbor_state_t *state, int32_t input)
-{
- cbor_major_type_t major_type;
-
- if (input < 0) {
- major_type = CBOR_MAJOR_TYPE_NINT;
- /* Convert from CBOR's representation. */
- input = -1 - input;
- } else {
- major_type = CBOR_MAJOR_TYPE_PINT;
- input = input;
- }
-
- if (!value_encode(state, major_type, &input, 4)) {
- FAIL();
- }
-
- return true;
-}
-
-bool intx32_encode(cbor_state_t *state, const int32_t *input)
-{
- return intx32_put(state, *input);
-}
-
-
-static bool uint32_encode(cbor_state_t *state, const uint32_t *input,
- cbor_major_type_t major_type)
-{
- if (!value_encode(state, major_type, input, 4)) {
- FAIL();
- }
- return true;
-}
-
-
-bool uintx32_encode(cbor_state_t *state, const uint32_t *input)
-{
- if (!uint32_encode(state, input, CBOR_MAJOR_TYPE_PINT)) {
- FAIL();
- }
- return true;
-}
-
-
-bool uintx32_put(cbor_state_t *state, uint32_t input)
-{
- if (!uint32_encode(state, &input, CBOR_MAJOR_TYPE_PINT)) {
- FAIL();
- }
- return true;
-}
-
-
-static bool strx_start_encode(cbor_state_t *state,
- const cbor_string_type_t *input, cbor_major_type_t major_type)
-{
- if (input->value && ((get_result_len(&input->len, sizeof(input->len))
- + 1 + input->len + (size_t)state->payload)
- > (size_t)state->payload_end)) {
- FAIL();
- }
- if (!uint32_encode(state, &input->len, major_type)) {
- FAIL();
- }
-
- return true;
-}
-
-
-static bool primx_encode(cbor_state_t *state, uint32_t input)
-{
- if (!uint32_encode(state, &input, CBOR_MAJOR_TYPE_PRIM)) {
- FAIL();
- }
- return true;
-}
-
-
-static uint32_t remaining_str_len(cbor_state_t *state)
-{
- uint32_t max_len = (size_t)state->payload_end - (size_t)state->payload;
- uint32_t result_len = get_result_len(&max_len, sizeof(uint32_t));
- return max_len - result_len - 1;
-}
-
-
-bool bstrx_cbor_start_encode(cbor_state_t *state, const cbor_string_type_t *result)
-{
- if (!new_backup(state, 0)) {
- FAIL();
- }
-
- uint32_t max_len = remaining_str_len(state);
-
- /* Encode a dummy header */
- if (!uint32_encode(state, &max_len,
- CBOR_MAJOR_TYPE_BSTR)) {
- FAIL();
- }
- return true;
-}
-
-
-bool bstrx_cbor_end_encode(cbor_state_t *state)
-{
- const uint8_t *payload = state->payload;
-
- if (!restore_backup(state, FLAG_RESTORE | FLAG_DISCARD, 0xFFFFFFFF)) {
- FAIL();
- }
- cbor_string_type_t value;
-
- value.value = state->payload_end - remaining_str_len(state);
- value.len = (size_t)payload - (size_t)value.value;
-
- /* Reencode header of list now that we know the number of elements. */
- if (!bstrx_encode(state, &value)) {
- FAIL();
- }
- return true;
-}
-
-
-static bool strx_encode(cbor_state_t *state,
- const cbor_string_type_t *input, cbor_major_type_t major_type)
-{
- if (!strx_start_encode(state, input, major_type)) {
- FAIL();
- }
- if (input->len > (state->payload_end - state->payload)) {
- FAIL();
- }
- if (state->payload_mut != input->value) {
- memmove(state->payload_mut, input->value, input->len);
- }
- state->payload += input->len;
- return true;
-}
-
-
-bool bstrx_encode(cbor_state_t *state, const cbor_string_type_t *input)
-{
- return strx_encode(state, input, CBOR_MAJOR_TYPE_BSTR);
-}
-
-
-bool tstrx_encode(cbor_state_t *state, const cbor_string_type_t *input)
-{
- return strx_encode(state, input, CBOR_MAJOR_TYPE_TSTR);
-}
-
-
-static bool list_map_start_encode(cbor_state_t *state, uint32_t max_num,
- cbor_major_type_t major_type)
-{
-#ifdef CDDL_CBOR_CANONICAL
- if (!new_backup(state, 0)) {
- FAIL();
- }
-
- /* Encode dummy header with max number of elements. */
- if (!uint32_encode(state, &max_num, major_type)) {
- FAIL();
- }
- state->elem_count--; /* Because of dummy header. */
-#else
- if (!encode_header_byte(state, major_type, 31)) {
- FAIL();
- }
-#endif
- return true;
-}
-
-
-bool list_start_encode(cbor_state_t *state, uint32_t max_num)
-{
- return list_map_start_encode(state, max_num, CBOR_MAJOR_TYPE_LIST);
-}
-
-
-bool map_start_encode(cbor_state_t *state, uint32_t max_num)
-{
- return list_map_start_encode(state, max_num, CBOR_MAJOR_TYPE_MAP);
-}
-
-
-bool list_map_end_encode(cbor_state_t *state, uint32_t max_num,
- cbor_major_type_t major_type)
-{
-#ifdef CDDL_CBOR_CANONICAL
- uint32_t list_count = ((major_type == CBOR_MAJOR_TYPE_LIST) ?
- state->elem_count
- : (state->elem_count / 2));
-
- const uint8_t *payload = state->payload;
- uint32_t max_header_len = get_result_len(&max_num, 4);
- uint32_t header_len = get_result_len(&list_count, 4);
-
- if (!restore_backup(state, FLAG_RESTORE | FLAG_DISCARD, 0xFFFFFFFF)) {
- FAIL();
- }
-
- cbor_print("list_count: %d\r\n", list_count);
-
- /* Reencode header of list now that we know the number of elements. */
- if (!(uint32_encode(state, &list_count, major_type))) {
- FAIL();
- }
-
- if (max_header_len != header_len) {
- const uint8_t *start = state->payload + max_header_len - header_len;
- uint32_t body_size = payload - start;
- memmove(state->payload_mut,
- state->payload + max_header_len - header_len,
- body_size);
- /* Reset payload pointer to end of list */
- state->payload += body_size;
- } else {
- /* Reset payload pointer to end of list */
- state->payload = payload;
- }
-#else
- if (!encode_header_byte(state, CBOR_MAJOR_TYPE_PRIM, 31)) {
- FAIL();
- }
-#endif
- return true;
-}
-
-
-bool list_end_encode(cbor_state_t *state, uint32_t max_num)
-{
- return list_map_end_encode(state, max_num, CBOR_MAJOR_TYPE_LIST);
-}
-
-
-bool map_end_encode(cbor_state_t *state, uint32_t max_num)
-{
- return list_map_end_encode(state, max_num, CBOR_MAJOR_TYPE_MAP);
-}
-
-
-bool nilx_put(cbor_state_t *state, const void *input)
-{
- (void)input;
- return primx_encode(state, 22);
-}
-
-
-bool boolx_encode(cbor_state_t *state, const bool *input)
-{
- if (!primx_encode(state, *input + BOOL_TO_PRIM)) {
- FAIL();
- }
- return true;
-}
-
-
-bool boolx_put(cbor_state_t *state, bool input)
-{
- if (!primx_encode(state, input + BOOL_TO_PRIM)) {
- FAIL();
- }
- return true;
-}
-
-
-bool double_encode(cbor_state_t *state, double *input)
-{
- if (!value_encode(state, CBOR_MAJOR_TYPE_PRIM, input,
- sizeof(*input))) {
- FAIL();
- }
-
- return true;
-}
-
-
-bool double_put(cbor_state_t *state, double input)
-{
- return double_encode(state, &input);
-}
-
-
-bool any_encode(cbor_state_t *state, void *input)
-{
- return nilx_put(state, input);
-}
-
-
-bool tag_encode(cbor_state_t *state, uint32_t tag)
-{
- if (!value_encode(state, CBOR_MAJOR_TYPE_TAG, &tag, sizeof(tag))) {
- FAIL();
- }
- state->elem_count--;
-
- return true;
-}
-
-
-bool multi_encode(uint32_t min_encode,
- uint32_t max_encode,
- const uint32_t *num_encode,
- cbor_encoder_t encoder,
- cbor_state_t *state,
- const void *input,
- uint32_t result_len)
-{
- if (!PTR_VALUE_IN_RANGE(uint32_t, num_encode, NULL, &max_encode)) {
- FAIL();
- }
- for (uint32_t i = 0; i < *num_encode; i++) {
- if (!encoder(state, (const uint8_t *)input + i*result_len)) {
- FAIL();
- }
- }
- cbor_print("Found %zu elements.\n", *num_encode);
- return true;
-}
-
-
-bool present_encode(const uint32_t *present,
- cbor_encoder_t encoder,
- cbor_state_t *state,
- const void *input)
-{
- uint32_t num_encode = *present;
- bool retval = multi_encode(0, 1, &num_encode, encoder, state, input, 0);
- return retval;
-}
diff --git a/boot/boot_serial/src/cbor_encode.h b/boot/boot_serial/src/cbor_encode.h
deleted file mode 100644
index 4c53d45..0000000
--- a/boot/boot_serial/src/cbor_encode.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * This file has been copied from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2020 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#ifndef CBOR_ENCODE_H__
-#define CBOR_ENCODE_H__
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include "cbor_common.h"
-
-
-/** Encode a PINT/NINT into a int32_t.
- *
- * @param[inout] state The current state of the decoding.
- * @param[out] result Where to place the encoded value.
- *
- * @retval true Everything is ok.
- * @retval false If the payload is exhausted.
- */
-bool intx32_encode(cbor_state_t *state, const int32_t *input);
-bool intx32_put(cbor_state_t *state, int32_t result);
-
-/** Encode a PINT into a uint32_t. */
-bool uintx32_encode(cbor_state_t *state, const uint32_t *result);
-bool uintx32_put(cbor_state_t *state, uint32_t result);
-
-/** Encode a BSTR header.
- *
- * The rest of the string can be encoded as CBOR.
- * A state backup is created to keep track of the element count.
- *
- * @retval true Header encoded correctly
- * @retval false Header encoded incorrectly, or backup failed.
- */
-bool bstrx_cbor_start_encode(cbor_state_t *state, const cbor_string_type_t *result);
-
-/** Finalize encoding a CBOR-encoded BSTR.
- *
- * Restore element count from backup.
- */
-bool bstrx_cbor_end_encode(cbor_state_t *state);
-
-/** Encode a BSTR, */
-bool bstrx_encode(cbor_state_t *state, const cbor_string_type_t *result);
-
-/** Encode a TSTR. */
-bool tstrx_encode(cbor_state_t *state, const cbor_string_type_t *result);
-
-#define tstrx_put(state, string) \
- tstrx_encode(state, &(cbor_string_type_t){.value = (const uint8_t *)string, .len = (sizeof(string) - 1)})
-
-#define tstrx_put_term(state, string) \
- tstrx_encode(state, &(cbor_string_type_t){.value = (const uint8_t *)string, .len = strlen((const char *)string)})
-
-/** Encode a LIST header.
- *
- * The contents of the list can be decoded via subsequent function calls.
- * A state backup is created to keep track of the element count.
- */
-bool list_start_encode(cbor_state_t *state, uint32_t max_num);
-
-/** Encode a MAP header. */
-bool map_start_encode(cbor_state_t *state, uint32_t max_num);
-
-/** Encode end of a LIST. Do some checks and deallocate backup. */
-bool list_end_encode(cbor_state_t *state, uint32_t max_num);
-
-/** Encode end of a MAP. Do some checks and deallocate backup. */
-bool map_end_encode(cbor_state_t *state, uint32_t max_num);
-
-/** Encode a "nil" primitive value. result should be NULL. */
-bool nilx_put(cbor_state_t *state, const void *result);
-
-/** Encode a boolean primitive value. */
-bool boolx_encode(cbor_state_t *state, const bool *result);
-bool boolx_put(cbor_state_t *state, bool result);
-
-/** Encode a float */
-bool float_encode(cbor_state_t *state, double *result);
-bool float_put(cbor_state_t *state, double result);
-
-/** Dummy encode "any": Encode a "nil". input should be NULL. */
-bool any_encode(cbor_state_t *state, void *input);
-
-/** Encode a tag. */
-bool tag_encode(cbor_state_t *state, uint32_t tag);
-
-/** Encode 0 or more elements with the same type and constraints.
- *
- * @details This must not necessarily encode all elements in a list. E.g. if
- * the list contains 3 INTS between 0 and 100 followed by 0 to 2 BSTRs
- * with length 8, that could be done with:
- *
- * @code{c}
- * uint32_t int_min = 0;
- * uint32_t int_max = 100;
- * uint32_t bstr_size = 8;
- * uint32_t ints[3];
- * cbor_string_type_t bstrs[2] = <initialize here>;
- * bool res;
- *
- * res = list_start_encode(state, 5);
- * // check res
- * res = multi_encode(3, 3, &num_encode, uintx32_encode, state,
- * ints, 4);
- * // check res
- * res = multi_encode(0, 2, &num_encode, strx_encode, state,
- * bstrs, sizeof(cbor_string_type_t));
- * // check res
- * res = list_end_encode(state, 5);
- * // check res
- * @endcode
- *
- * @param[in] min_encode The minimum acceptable number of elements.
- * @param[in] max_encode The maximum acceptable number of elements.
- * @param[in] num_encode The actual number of elements.
- * @param[in] encoder The encoder function to call under the hood. This
- * function will be called with the provided arguments
- * repeatedly until the function fails (returns false)
- * or until it has been called @p max_encode times.
- * result is moved @p result_len bytes for each call
- * to @p encoder, i.e. @p result refers to an array
- * of result variables.
- * @param[in] input Source of the encoded values. Must be an array
- * of length at least @p max_encode.
- * @param[in] result_len The length of the result variables. Must be the
- * length of the elements in result.
- *
- * @retval true If at least @p min_encode variables were correctly encoded.
- * @retval false If @p encoder failed before having encoded @p min_encode
- * values.
- */
-bool multi_encode(uint32_t min_encode, uint32_t max_encode, const uint32_t *num_encode,
- cbor_encoder_t encoder, cbor_state_t *state, const void *input,
- uint32_t result_len);
-
-bool present_encode(const uint32_t *present,
- cbor_encoder_t encoder,
- cbor_state_t *state,
- const void *input);
-
-#endif /* CBOR_ENCODE_H__ */
diff --git a/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh b/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
index 08d1220..1f2137a 100755
--- a/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
+++ b/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
@@ -1,36 +1,30 @@
#!/bin/bash
if [ "$1" == "--help" ] || [ "$1" == "" ]; then
- echo "Regenerate serial_recovery_cbor.c|h if the cddl-gen submodule is updated."
+ echo "Regenerate serial_recovery_cbor.c|h if the zcbor submodule is updated."
echo "Usage: $0 <copyright>"
- echo " e.g. $0 \"2021 Nordic Semiconductor ASA\""
+ echo " e.g. $0 \"2022 Nordic Semiconductor ASA\""
exit -1
fi
add_copy_notice() {
echo "$(printf '/*
- * This file has been %s from the cddl-gen submodule.
+ * This file has been %s from the zcbor library.
* Commit %s
*/
-' "$2" "$(git -C ../../../ext/cddl-gen rev-parse HEAD)"; cat $1;)" > $1
+' "$2" "$(zcbor --version)"; cat $1;)" > $1
}
-echo "Copying cbor_decode.c|h"
+echo "Copying zcbor_decode.c|h"
copy_with_copy_notice() {
cp $1 $2
add_copy_notice $2 "copied"
}
-copy_with_copy_notice ../../../ext/cddl-gen/src/cbor_decode.c cbor_decode.c
-copy_with_copy_notice ../../../ext/cddl-gen/src/cbor_encode.c cbor_encode.c
-copy_with_copy_notice ../../../ext/cddl-gen/src/cbor_common.c cbor_common.c
-copy_with_copy_notice ../../../ext/cddl-gen/include/cbor_decode.h cbor_decode.h
-copy_with_copy_notice ../../../ext/cddl-gen/include/cbor_encode.h cbor_encode.h
-copy_with_copy_notice ../../../ext/cddl-gen/include/cbor_common.h cbor_common.h
echo "Generating serial_recovery_cbor.c|h"
-python3 ../../../ext/cddl-gen/cddl_gen/cddl_gen.py -c serial_recovery.cddl code -d -t Upload --oc serial_recovery_cbor.c --oh serial_recovery_cbor.h --time-header
+zcbor -c serial_recovery.cddl code -d -t Upload --oc serial_recovery_cbor.c --oh serial_recovery_cbor.h --time-header --copy-sources
add_copyright() {
echo "$(printf '/*
@@ -44,6 +38,10 @@
add_copyright serial_recovery_cbor.c "$1"
add_copyright serial_recovery_cbor.h "$1"
-add_copy_notice serial_recovery_cbor.c "generated"
-add_copy_notice serial_recovery_cbor.h "generated"
-add_copy_notice types_serial_recovery_cbor.h "generated"
+add_copyright serial_recovery_cbor_types.h "$1"
+add_copy_notice zcbor_decode.c "copied"
+add_copy_notice zcbor_encode.c "copied"
+add_copy_notice zcbor_common.c "copied"
+add_copy_notice zcbor_decode.h "copied"
+add_copy_notice zcbor_encode.h "copied"
+add_copy_notice zcbor_common.h "copied"
diff --git a/boot/boot_serial/src/serial_recovery_cbor.c b/boot/boot_serial/src/serial_recovery_cbor.c
index 2561b70..b00e48c 100644
--- a/boot/boot_serial/src/serial_recovery_cbor.c
+++ b/boot/boot_serial/src/serial_recovery_cbor.c
@@ -1,25 +1,21 @@
/*
- * This file has been generated from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2021 Nordic Semiconductor ASA
+ * Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
- * Generated with cddl_gen.py (https://github.com/NordicSemiconductor/cddl-gen)
- * at: 2021-08-02 17:09:42
- * Generated with a default_max_qty of 3
+ * Generated using zcbor version 0.4.0
+ * https://github.com/NordicSemiconductor/zcbor
+ * at: 2022-03-31 12:37:11
+ * Generated with a --default-max-qty of 3
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
-#include "cbor_decode.h"
+#include "zcbor_decode.h"
#include "serial_recovery_cbor.h"
#if DEFAULT_MAX_QTY != 3
@@ -28,67 +24,76 @@
static bool decode_Member(
- cbor_state_t *state, struct Member_ *result)
+ zcbor_state_t *state, struct Member_ *result)
{
- cbor_print("%s\n", __func__);
- cbor_string_type_t tmp_str;
+ zcbor_print("%s\r\n", __func__);
+ struct zcbor_string tmp_str;
bool int_res;
- bool tmp_result = (((union_start_code(state) && (int_res = (((((tstrx_expect(state, ((tmp_str.value = (const uint8_t *)"image",
- tmp_str.len = sizeof("image") - 1, &tmp_str)))))
- && (intx32_decode(state, (&(*result)._Member_image)))) && (((*result)._Member_choice = _Member_image) || 1))
- || (union_elem_code(state) && ((((tstrx_expect(state, ((tmp_str.value = (const uint8_t *)"data",
- tmp_str.len = sizeof("data") - 1, &tmp_str)))))
- && (bstrx_decode(state, (&(*result)._Member_data)))) && (((*result)._Member_choice = _Member_data) || 1)))
- || (union_elem_code(state) && ((((tstrx_expect(state, ((tmp_str.value = (const uint8_t *)"len",
- tmp_str.len = sizeof("len") - 1, &tmp_str)))))
- && (intx32_decode(state, (&(*result)._Member_len)))) && (((*result)._Member_choice = _Member_len) || 1)))
- || (union_elem_code(state) && ((((tstrx_expect(state, ((tmp_str.value = (const uint8_t *)"off",
- tmp_str.len = sizeof("off") - 1, &tmp_str)))))
- && (intx32_decode(state, (&(*result)._Member_off)))) && (((*result)._Member_choice = _Member_off) || 1)))
- || (union_elem_code(state) && ((((tstrx_expect(state, ((tmp_str.value = (const uint8_t *)"sha",
- tmp_str.len = sizeof("sha") - 1, &tmp_str)))))
- && (bstrx_decode(state, (&(*result)._Member_sha)))) && (((*result)._Member_choice = _Member_sha) || 1)))), union_end_code(state), int_res))));
+ bool tmp_result = (((zcbor_union_start_code(state) && (int_res = (((((zcbor_tstr_expect(state, ((tmp_str.value = (uint8_t *)"image", tmp_str.len = sizeof("image") - 1, &tmp_str)))))
+ && (zcbor_int32_decode(state, (&(*result)._Member_image)))) && (((*result)._Member_choice = _Member_image) || 1))
+ || (zcbor_union_elem_code(state) && ((((zcbor_tstr_expect(state, ((tmp_str.value = (uint8_t *)"data", tmp_str.len = sizeof("data") - 1, &tmp_str)))))
+ && (zcbor_bstr_decode(state, (&(*result)._Member_data)))) && (((*result)._Member_choice = _Member_data) || 1)))
+ || (zcbor_union_elem_code(state) && ((((zcbor_tstr_expect(state, ((tmp_str.value = (uint8_t *)"len", tmp_str.len = sizeof("len") - 1, &tmp_str)))))
+ && (zcbor_int32_decode(state, (&(*result)._Member_len)))) && (((*result)._Member_choice = _Member_len) || 1)))
+ || (zcbor_union_elem_code(state) && ((((zcbor_tstr_expect(state, ((tmp_str.value = (uint8_t *)"off", tmp_str.len = sizeof("off") - 1, &tmp_str)))))
+ && (zcbor_int32_decode(state, (&(*result)._Member_off)))) && (((*result)._Member_choice = _Member_off) || 1)))
+ || (zcbor_union_elem_code(state) && ((((zcbor_tstr_expect(state, ((tmp_str.value = (uint8_t *)"sha", tmp_str.len = sizeof("sha") - 1, &tmp_str)))))
+ && (zcbor_bstr_decode(state, (&(*result)._Member_sha)))) && (((*result)._Member_choice = _Member_sha) || 1)))), zcbor_union_end_code(state), int_res))));
if (!tmp_result)
- cbor_trace();
+ zcbor_trace();
+
+ return tmp_result;
+}
+
+static bool decode_repeated_Upload_members(
+ zcbor_state_t *state, struct Upload_members *result)
+{
+ zcbor_print("%s\r\n", __func__);
+
+ bool tmp_result = (((decode_Member(state, (&(*result)._Upload_members)))));
+
+ if (!tmp_result)
+ zcbor_trace();
return tmp_result;
}
static bool decode_Upload(
- cbor_state_t *state, struct Upload *result)
+ zcbor_state_t *state, struct Upload *result)
{
- cbor_print("%s\n", __func__);
- bool int_res;
+ zcbor_print("%s\r\n", __func__);
- bool tmp_result = (((map_start_decode(state) && (int_res = (multi_decode(1, 5, &(*result)._Upload_members_count, (void *)decode_Member, state, (&(*result)._Upload_members), sizeof(struct Member_))), ((map_end_decode(state)) && int_res)))));
+ bool tmp_result = (((zcbor_map_start_decode(state) && ((zcbor_multi_decode(1, 5, &(*result)._Upload_members_count, (zcbor_decoder_t *)decode_repeated_Upload_members, state, (&(*result)._Upload_members), sizeof(struct Upload_members))) || (zcbor_list_map_end_force_decode(state), false)) && zcbor_map_end_decode(state))));
if (!tmp_result)
- cbor_trace();
+ zcbor_trace();
return tmp_result;
}
-__attribute__((unused)) static bool type_test_decode_Upload(
- struct Upload *result)
-{
- /* This function should not be called, it is present only to test that
- * the types of the function and struct match, since this information
- * is lost with the casts in the entry function.
- */
- return decode_Upload(NULL, result);
-}
-
-
-bool cbor_decode_Upload(
- const uint8_t *payload, uint32_t payload_len,
+int cbor_decode_Upload(
+ const uint8_t *payload, size_t payload_len,
struct Upload *result,
- uint32_t *payload_len_out)
+ size_t *payload_len_out)
{
- return entry_function(payload, payload_len, (const void *)result,
- payload_len_out, (void *)decode_Upload,
- 1, 2);
+ zcbor_state_t states[4];
+
+ zcbor_new_state(states, sizeof(states) / sizeof(zcbor_state_t), payload, payload_len, 1);
+
+ bool ret = decode_Upload(states, result);
+
+ if (ret && (payload_len_out != NULL)) {
+ *payload_len_out = MIN(payload_len,
+ (size_t)states[0].payload - (size_t)payload);
+ }
+
+ if (!ret) {
+ int ret = zcbor_pop_error(states);
+ return (ret == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : ret;
+ }
+ return ZCBOR_SUCCESS;
}
diff --git a/boot/boot_serial/src/serial_recovery_cbor.h b/boot/boot_serial/src/serial_recovery_cbor.h
index f167d9b..cdf5335 100644
--- a/boot/boot_serial/src/serial_recovery_cbor.h
+++ b/boot/boot_serial/src/serial_recovery_cbor.h
@@ -1,18 +1,14 @@
/*
- * This file has been generated from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Copyright (c) 2021 Nordic Semiconductor ASA
+ * Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
- * Generated with cddl_gen.py (https://github.com/NordicSemiconductor/cddl-gen)
- * at: 2021-08-02 17:09:42
- * Generated with a default_max_qty of 3
+ * Generated using zcbor version 0.4.0
+ * https://github.com/NordicSemiconductor/zcbor
+ * at: 2022-03-31 12:37:11
+ * Generated with a --default-max-qty of 3
*/
#ifndef SERIAL_RECOVERY_CBOR_H__
@@ -22,18 +18,18 @@
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
-#include "cbor_decode.h"
-#include "types_serial_recovery_cbor.h"
+#include "zcbor_decode.h"
+#include "serial_recovery_cbor_types.h"
#if DEFAULT_MAX_QTY != 3
#error "The type file was generated with a different default_max_qty than this file"
#endif
-bool cbor_decode_Upload(
- const uint8_t *payload, uint32_t payload_len,
+int cbor_decode_Upload(
+ const uint8_t *payload, size_t payload_len,
struct Upload *result,
- uint32_t *payload_len_out);
+ size_t *payload_len_out);
#endif /* SERIAL_RECOVERY_CBOR_H__ */
diff --git a/boot/boot_serial/src/serial_recovery_cbor_types.h b/boot/boot_serial/src/serial_recovery_cbor_types.h
new file mode 100644
index 0000000..d890568
--- /dev/null
+++ b/boot/boot_serial/src/serial_recovery_cbor_types.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Generated using zcbor version 0.4.0
+ * https://github.com/NordicSemiconductor/zcbor
+ * at: 2022-03-31 12:37:11
+ * Generated with a --default-max-qty of 3
+ */
+
+#ifndef SERIAL_RECOVERY_CBOR_TYPES_H__
+#define SERIAL_RECOVERY_CBOR_TYPES_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include "zcbor_decode.h"
+
+/** Which value for --default-max-qty this file was created with.
+ *
+ * The define is used in the other generated file to do a build-time
+ * compatibility check.
+ *
+ * See `zcbor --help` for more information about --default-max-qty
+ */
+#define DEFAULT_MAX_QTY 3
+
+struct Member_ {
+ union {
+ struct {
+ int32_t _Member_image;
+ };
+ struct {
+ struct zcbor_string _Member_data;
+ };
+ struct {
+ int32_t _Member_len;
+ };
+ struct {
+ int32_t _Member_off;
+ };
+ struct {
+ struct zcbor_string _Member_sha;
+ };
+ };
+ enum {
+ _Member_image,
+ _Member_data,
+ _Member_len,
+ _Member_off,
+ _Member_sha,
+ } _Member_choice;
+};
+
+struct Upload_members {
+ struct Member_ _Upload_members;
+};
+
+struct Upload {
+ struct Upload_members _Upload_members[5];
+ uint_fast32_t _Upload_members_count;
+};
+
+
+#endif /* SERIAL_RECOVERY_CBOR_TYPES_H__ */
diff --git a/boot/boot_serial/src/types_serial_recovery_cbor.h b/boot/boot_serial/src/types_serial_recovery_cbor.h
deleted file mode 100644
index 8856017..0000000
--- a/boot/boot_serial/src/types_serial_recovery_cbor.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file has been generated from the cddl-gen submodule.
- * Commit 9f77837f9950da1633d22abf6181a830521a6688
- */
-
-/*
- * Generated with cddl_gen.py (https://github.com/NordicSemiconductor/cddl-gen)
- * at: 2021-08-02 17:09:42
- * Generated with a default_max_qty of 3
- */
-
-#ifndef TYPES_SERIAL_RECOVERY_CBOR_H__
-#define TYPES_SERIAL_RECOVERY_CBOR_H__
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include "cbor_decode.h"
-
-#define DEFAULT_MAX_QTY 3
-
-struct Member_ {
- union {
- struct {
- int32_t _Member_image;
- };
- struct {
- cbor_string_type_t _Member_data;
- };
- struct {
- int32_t _Member_len;
- };
- struct {
- int32_t _Member_off;
- };
- struct {
- cbor_string_type_t _Member_sha;
- };
- };
- enum {
- _Member_image,
- _Member_data,
- _Member_len,
- _Member_off,
- _Member_sha,
- } _Member_choice;
-};
-
-struct Upload {
- struct Member_ _Upload_members[5];
- uint32_t _Upload_members_count;
-};
-
-
-#endif /* TYPES_SERIAL_RECOVERY_CBOR_H__ */
diff --git a/boot/boot_serial/src/zcbor_common.c b/boot/boot_serial/src/zcbor_common.c
new file mode 100644
index 0000000..71962d6
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_common.c
@@ -0,0 +1,229 @@
+/*
+ * This file has been copied from the zcbor library.
+ * Commit zcbor 0.4.0
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "zcbor_common.h"
+
+_Static_assert((sizeof(size_t) == sizeof(void *)),
+ "This code needs size_t to be the same length as pointers.");
+
+_Static_assert((sizeof(zcbor_state_t) >= sizeof(struct zcbor_state_constant)),
+ "This code needs zcbor_state_t to be at least as large as zcbor_backups_t.");
+
+bool zcbor_new_backup(zcbor_state_t *state, uint_fast32_t new_elem_count)
+{
+ ZCBOR_CHECK_ERROR();
+
+ if ((state->constant_state->current_backup)
+ >= state->constant_state->num_backups) {
+ ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_MEM);
+ }
+
+ state->payload_moved = false;
+
+ (state->constant_state->current_backup)++;
+
+ /* use the backup at current_backup - 1, since otherwise, the 0th
+ * backup would be unused. */
+ uint_fast32_t i = (state->constant_state->current_backup) - 1;
+
+ memcpy(&state->constant_state->backup_list[i], state,
+ sizeof(zcbor_state_t));
+
+ state->elem_count = new_elem_count;
+
+ return true;
+}
+
+
+bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags,
+ uint_fast32_t max_elem_count)
+{
+ const uint8_t *payload = state->payload;
+ const uint_fast32_t elem_count = state->elem_count;
+
+ ZCBOR_CHECK_ERROR();
+
+ if (state->constant_state->current_backup == 0) {
+ zcbor_print("No backups available.\r\n");
+ ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_ACTIVE);
+ }
+
+ if (flags & ZCBOR_FLAG_RESTORE) {
+ /* use the backup at current_backup - 1, since otherwise, the
+ * 0th backup would be unused. */
+ uint_fast32_t i = state->constant_state->current_backup - 1;
+
+ if (!(flags & ZCBOR_FLAG_TRANSFER_PAYLOAD)) {
+ if (state->constant_state->backup_list[i].payload_moved) {
+ zcbor_print("Payload pointer out of date.\r\n");
+ ZCBOR_FAIL();
+ }
+ }
+ memcpy(state, &state->constant_state->backup_list[i],
+ sizeof(zcbor_state_t));
+ }
+
+ if (flags & ZCBOR_FLAG_CONSUME) {
+ state->constant_state->current_backup--;
+ }
+
+ if (elem_count > max_elem_count) {
+ zcbor_print("elem_count: %" PRIuFAST32 " (expected max %" PRIuFAST32 ")\r\n",
+ elem_count, max_elem_count);
+ ZCBOR_ERR(ZCBOR_ERR_HIGH_ELEM_COUNT);
+ }
+
+ if (flags & ZCBOR_FLAG_TRANSFER_PAYLOAD) {
+ state->payload = payload;
+ }
+
+ return true;
+}
+
+static void update_backups(zcbor_state_t *state, uint8_t const *new_payload_end)
+{
+ if (state->constant_state) {
+ for (int i = 0; i < state->constant_state->current_backup; i++) {
+ state->constant_state->backup_list[i].payload_end = new_payload_end;
+ state->constant_state->backup_list[i].payload_moved = true;
+ }
+ }
+}
+
+
+bool zcbor_union_start_code(zcbor_state_t *state)
+{
+ if (!zcbor_new_backup(state, state->elem_count)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_union_elem_code(zcbor_state_t *state)
+{
+ if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE, state->elem_count)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+bool zcbor_union_end_code(zcbor_state_t *state)
+{
+ if (!zcbor_process_backup(state, ZCBOR_FLAG_CONSUME, state->elem_count)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+bool zcbor_new_state(zcbor_state_t *state_array, uint_fast32_t n_states,
+ const uint8_t *payload, size_t payload_len, uint_fast32_t elem_count)
+{
+ state_array[0].payload = payload;
+ state_array[0].payload_end = payload + payload_len;
+ state_array[0].elem_count = elem_count;
+ state_array[0].indefinite_length_array = false;
+ state_array[0].payload_moved = false;
+ state_array[0].constant_state = NULL;
+
+ if(n_states < 2) {
+ return false;
+ }
+
+ /* Use the last state as a struct zcbor_state_constant object. */
+ state_array[0].constant_state = (struct zcbor_state_constant *)&state_array[n_states - 1];
+ state_array[0].constant_state->backup_list = NULL;
+ state_array[0].constant_state->num_backups = n_states - 2;
+ state_array[0].constant_state->current_backup = 0;
+ state_array[0].constant_state->error = ZCBOR_SUCCESS;
+#ifdef ZCBOR_STOP_ON_ERROR
+ state_array[0].constant_state->stop_on_error = false;
+#endif
+ if (n_states > 2) {
+ state_array[0].constant_state->backup_list = &state_array[1];
+ }
+ return true;
+}
+
+void zcbor_update_state(zcbor_state_t *state,
+ const uint8_t *payload, size_t payload_len)
+{
+ state->payload = payload;
+ state->payload_end = payload + payload_len;
+
+ update_backups(state, state->payload_end);
+}
+
+
+bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
+ uint_fast32_t num_fragments)
+{
+ size_t total_len = 0;
+
+ if (fragments == NULL) {
+ return false;
+ }
+
+ for (uint_fast32_t i = 0; i < num_fragments; i++) {
+ if (fragments[i].offset != total_len) {
+ return false;
+ }
+ if (fragments[i].fragment.value == NULL) {
+ return false;
+ }
+ if (fragments[i].total_len != fragments[0].total_len) {
+ return false;
+ }
+ total_len += fragments[i].fragment.len;
+ if (total_len > fragments[0].total_len) {
+ return false;
+ }
+ }
+
+ if (num_fragments && total_len != fragments[0].total_len) {
+ return false;
+ }
+
+ if (num_fragments && (fragments[0].total_len == ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH)) {
+ for (uint_fast32_t i = 0; i < num_fragments; i++) {
+ fragments[i].total_len = total_len;
+ }
+ }
+
+ return true;
+}
+
+bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
+ uint_fast32_t num_fragments, uint8_t *result, size_t *result_len)
+{
+ size_t total_len = 0;
+
+ if (!fragments) {
+ return false;
+ }
+
+ for (uint_fast32_t i = 0; i < num_fragments; i++) {
+ if ((total_len > *result_len)
+ || (fragments[i].fragment.len > (*result_len - total_len))) {
+ return false;
+ }
+ memcpy(&result[total_len],
+ fragments[i].fragment.value, fragments[i].fragment.len);
+ total_len += fragments[i].fragment.len;
+ }
+
+ *result_len = total_len;
+ return true;
+}
diff --git a/boot/boot_serial/src/zcbor_common.h b/boot/boot_serial/src/zcbor_common.h
new file mode 100644
index 0000000..eae2ffa
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_common.h
@@ -0,0 +1,371 @@
+/*
+ * This file has been copied from the zcbor library.
+ * Commit zcbor 0.4.0
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZCBOR_COMMON_H__
+#define ZCBOR_COMMON_H__
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+
+/** Convenience type that allows pointing to strings directly inside the payload
+ * without the need to copy out.
+ */
+struct zcbor_string {
+ const uint8_t *value;
+ size_t len;
+};
+
+
+/** Type representing a string fragment.
+ *
+ * Don't modify any member variables, or subsequent calls may fail.
+**/
+struct zcbor_string_fragment {
+ struct zcbor_string fragment; ///! Location and length of the fragment.
+ size_t offset; ///! The offset in the full string at which this fragment belongs.
+ size_t total_len; ///! The total length of the string this fragment is a part of.
+};
+
+
+/** Size to use in struct zcbor_string_fragment when the real size is unknown. */
+#define ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH SIZE_MAX
+
+#ifdef ZCBOR_VERBOSE
+#include <sys/printk.h>
+#define zcbor_trace() (printk("bytes left: %zu, byte: 0x%x, elem_count: 0x%" PRIxFAST32 ", %s:%d\n",\
+ (size_t)state->payload_end - (size_t)state->payload, *state->payload, \
+ state->elem_count, __FILE__, __LINE__))
+
+#define zcbor_print_assert(expr, ...) \
+do { \
+ printk("ASSERTION \n \"" #expr \
+ "\"\nfailed at %s:%d with message:\n ", \
+ __FILE__, __LINE__); \
+ printk(__VA_ARGS__);\
+} while(0)
+#define zcbor_print(...) printk(__VA_ARGS__)
+#else
+#define zcbor_trace() ((void)state)
+#define zcbor_print_assert(...)
+#define zcbor_print(...)
+#endif
+
+#ifdef ZCBOR_ASSERTS
+#define zcbor_assert(expr, ...) \
+do { \
+ if (!(expr)) { \
+ zcbor_print_assert(expr, __VA_ARGS__); \
+ ZCBOR_FAIL(); \
+ } \
+} while(0)
+#else
+#define zcbor_assert(expr, ...)
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+
+struct zcbor_state_constant;
+
+typedef struct {
+union {
+ uint8_t *payload_mut;
+ uint8_t const *payload; /**< The current place in the payload. Will be
+ updated when an element is correctly
+ processed. */
+};
+ uint8_t const *payload_bak; /**< Temporary backup of payload. */
+ uint_fast32_t elem_count; /**< The current element is part of a LIST or a MAP,
+ and this keeps count of how many elements are
+ expected. This will be checked before processing
+ and decremented if the element is correctly
+ processed. */
+ uint8_t const *payload_end; /**< The end of the payload. This will be
+ checked against payload before
+ processing each element. */
+ bool indefinite_length_array; /**< Is set to true if the decoder is currently
+ decoding the contents of an indefinite-
+ length array. */
+ bool payload_moved; /**< Is set to true while the state is stored as a backup
+ if @ref zcbor_update_state is called, since that function
+ updates the payload_end of all backed-up states. */
+ struct zcbor_state_constant *constant_state; /**< The part of the state that is
+ not backed up and duplicated. */
+} zcbor_state_t;
+
+struct zcbor_state_constant {
+ zcbor_state_t *backup_list;
+ uint_fast32_t current_backup;
+ uint_fast32_t num_backups;
+ int error;
+#ifdef ZCBOR_STOP_ON_ERROR
+ bool stop_on_error;
+#endif
+};
+
+/** Function pointer type used with zcbor_multi_decode.
+ *
+ * This type is compatible with all decoding functions here and in the generated
+ * code, except for zcbor_multi_decode.
+ */
+typedef bool(zcbor_encoder_t)(zcbor_state_t *, const void *);
+typedef bool(zcbor_decoder_t)(zcbor_state_t *, void *);
+
+/** Enumeration representing the major types available in CBOR.
+ *
+ * The major type is represented in the 3 first bits of the header byte.
+ */
+typedef enum
+{
+ ZCBOR_MAJOR_TYPE_PINT = 0, ///! Positive Integer
+ ZCBOR_MAJOR_TYPE_NINT = 1, ///! Negative Integer
+ ZCBOR_MAJOR_TYPE_BSTR = 2, ///! Byte String
+ ZCBOR_MAJOR_TYPE_TSTR = 3, ///! Text String
+ ZCBOR_MAJOR_TYPE_LIST = 4, ///! List
+ ZCBOR_MAJOR_TYPE_MAP = 5, ///! Map
+ ZCBOR_MAJOR_TYPE_TAG = 6, ///! Semantic Tag
+ ZCBOR_MAJOR_TYPE_PRIM = 7, ///! Primitive Type
+} zcbor_major_type_t;
+
+
+/** Convenience macro for failing out of a decoding/encoding function.
+*/
+#define ZCBOR_FAIL() \
+do {\
+ zcbor_trace(); \
+ return false; \
+} while(0)
+
+#define ZCBOR_ERR(err) \
+do { \
+ zcbor_error(state, err); \
+ ZCBOR_FAIL(); \
+} while(0)
+
+#define ZCBOR_ERR_IF(expr, err) \
+do {\
+ if (expr) { \
+ ZCBOR_ERR(err); \
+ } \
+} while(0)
+
+#define ZCBOR_CHECK_PAYLOAD() \
+ ZCBOR_ERR_IF(state->payload >= state->payload_end, ZCBOR_ERR_NO_PAYLOAD)
+
+#ifdef ZCBOR_STOP_ON_ERROR
+#define ZCBOR_CHECK_ERROR() \
+do { \
+ if (!zcbor_check_error(state)) { \
+ ZCBOR_FAIL(); \
+ } \
+} while(0)
+#else
+#define ZCBOR_CHECK_ERROR()
+#endif
+
+#define ZCBOR_VALUE_IN_HEADER 23 ///! Values below this are encoded directly in the header.
+#define ZCBOR_VALUE_IS_1_BYTE 24 ///! The next 1 byte contains the value.
+#define ZCBOR_VALUE_IS_2_BYTES 25 ///! The next 2 bytes contain the value.
+#define ZCBOR_VALUE_IS_4_BYTES 26 ///! The next 4 bytes contain the value.
+#define ZCBOR_VALUE_IS_8_BYTES 27 ///! The next 8 bytes contain the value.
+#define ZCBOR_VALUE_IS_INDEFINITE_LENGTH 31 ///! The list or map has indefinite length, and will instead be terminated by a 0xFF token.
+
+#define ZCBOR_BOOL_TO_PRIM ((uint8_t)20) ///! In CBOR, false/true have the values 20/21
+
+#define ZCBOR_FLAG_RESTORE 1UL ///! Restore from the backup. Overwrite the current state with the state from the backup.
+#define ZCBOR_FLAG_CONSUME 2UL ///! Consume the backup. Remove the backup from the stack of backups.
+#define ZCBOR_FLAG_TRANSFER_PAYLOAD 4UL ///! Keep the pre-restore payload after restoring.
+
+#define ZCBOR_SUCCESS 0
+#define ZCBOR_ERR_NO_BACKUP_MEM 1
+#define ZCBOR_ERR_NO_BACKUP_ACTIVE 2
+#define ZCBOR_ERR_LOW_ELEM_COUNT 3
+#define ZCBOR_ERR_HIGH_ELEM_COUNT 4
+#define ZCBOR_ERR_INT_SIZE 5
+#define ZCBOR_ERR_FLOAT_SIZE 6
+#define ZCBOR_ERR_ADDITIONAL_INVAL 7 ///! > 27
+#define ZCBOR_ERR_NO_PAYLOAD 8
+#define ZCBOR_ERR_PAYLOAD_NOT_CONSUMED 9
+#define ZCBOR_ERR_WRONG_TYPE 10
+#define ZCBOR_ERR_WRONG_VALUE 11
+#define ZCBOR_ERR_WRONG_RANGE 12
+#define ZCBOR_ERR_ITERATIONS 13
+#define ZCBOR_ERR_ASSERTION 14
+#define ZCBOR_ERR_UNKNOWN 31
+
+/** The largest possible elem_count. */
+#ifdef UINT_FAST32_MAX
+#define ZCBOR_MAX_ELEM_COUNT UINT_FAST32_MAX
+#else
+#define ZCBOR_MAX_ELEM_COUNT ((uint_fast32_t)(-1L))
+#endif
+
+/** Initial value for elem_count for when it just needs to be large. */
+#define ZCBOR_LARGE_ELEM_COUNT (ZCBOR_MAX_ELEM_COUNT - 16)
+
+
+/** Values defined by RFC8949 via www.iana.org/assignments/cbor-tags/cbor-tags.xhtml */
+enum zcbor_rfc8949_tag {
+ ZCBOR_TAG_TIME_TSTR = 0, ///! text string Standard date/time string
+ ZCBOR_TAG_TIME_NUM = 1, ///! integer or float Epoch-based date/time
+ ZCBOR_TAG_UBIGNUM_BSTR = 2, ///! byte string Unsigned bignum
+ ZCBOR_TAG_BIGNUM_BSTR = 3, ///! byte string Negative bignum
+ ZCBOR_TAG_DECFRAC_ARR = 4, ///! array Decimal fraction
+ ZCBOR_TAG_BIGFLOAT_ARR = 5, ///! array Bigfloat
+ ZCBOR_TAG_2BASE64URL = 21, ///! (any) Expected conversion to base64url encoding
+ ZCBOR_TAG_2BASE64 = 22, ///! (any) Expected conversion to base64 encoding
+ ZCBOR_TAG_2BASE16 = 23, ///! (any) Expected conversion to base16 encoding
+ ZCBOR_TAG_BSTR = 24, ///! byte string Encoded CBOR data item
+ ZCBOR_TAG_URI_TSTR = 32, ///! text string URI
+ ZCBOR_TAG_BASE64URL_TSTR = 33, ///! text string base64url
+ ZCBOR_TAG_BASE64_TSTR = 34, ///! text string base64
+ ZCBOR_TAG_MIME_TSTR = 36, ///! text string MIME message
+ ZCBOR_TAG_CBOR = 55799, ///! (any) Self-described CBOR
+};
+
+
+/** Take a backup of the current state. Overwrite the current elem_count. */
+bool zcbor_new_backup(zcbor_state_t *state, uint_fast32_t new_elem_count);
+
+/** Consult the most recent backup. In doing so, check whether elem_count is
+ * less than or equal to max_elem_count.
+ * Also, take action based on the flags (See ZCBOR_FLAG_*).
+ */
+bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags, uint_fast32_t max_elem_count);
+
+/** Convenience function for starting encoding/decoding of a union.
+ *
+ * That is, for attempting to encode, or especially decode, multiple options.
+ * Makes a new backup.
+ */
+bool zcbor_union_start_code(zcbor_state_t *state);
+
+/** Convenience function before encoding/decoding one element of a union.
+ *
+ * Call this before attempting each option.
+ * Restores the backup, without consuming it.
+ */
+bool zcbor_union_elem_code(zcbor_state_t *state);
+
+/** Convenience function before encoding/decoding one element of a union.
+ *
+ * Consumes the backup without restoring it.
+ */
+bool zcbor_union_end_code(zcbor_state_t *state);
+
+/** Initialize a state with backups.
+ * One of the states in the array is used as a struct zcbor_state_constant object.
+ * This means that you get a state with (n_states - 2) backups.
+ * The constant state is mandatory so n_states must be at least 2.
+ * payload, payload_len, and elem_count are used to initialize the first state.
+ * in the array, which is the state that can be passed to cbor functions.
+ *
+ * @retval false if n_states < 2
+ * @retval true otherwise
+ */
+bool zcbor_new_state(zcbor_state_t *state_array, uint_fast32_t n_states,
+ const uint8_t *payload, size_t payload_len, uint_fast32_t elem_count);
+
+#ifdef ZCBOR_STOP_ON_ERROR
+/** Check stored error and fail if present, but only if stop_on_error is true. */
+static inline bool zcbor_check_error(const zcbor_state_t *state)
+{
+ return !(state->constant_state->stop_on_error && state->constant_state->error);
+}
+#endif
+
+/** Return the current error state, replacing it with SUCCESS. */
+static inline int zcbor_pop_error(zcbor_state_t *state)
+{
+ int err = state->constant_state->error;
+
+ state->constant_state->error = ZCBOR_SUCCESS;
+ return err;
+}
+
+/** Write the provided error to the error state. */
+static inline void zcbor_error(zcbor_state_t *state, int err)
+{
+#ifdef ZCBOR_STOP_ON_ERROR
+ if (zcbor_check_error(state))
+#endif
+ {
+ state->constant_state->error = err;
+ }
+}
+
+/** Whether the current payload is exhausted. */
+static inline bool zcbor_payload_at_end(const zcbor_state_t *state)
+{
+ return (state->payload == state->payload_end);
+}
+
+/** Update the current payload pointer (and payload_end).
+ *
+ * For use when the payload is divided into multiple chunks.
+ *
+ * This function also updates all backups to the new payload_end.
+ * This sets a flag so that if a backup is processed with the flag
+ * @ref ZCBOR_FLAG_RESTORE, but without the flag
+ * @ref ZCBOR_FLAG_TRANSFER_PAYLOAD since this would cause an invalid state.
+ *
+ * @param[inout] state The current state, will be updated with
+ * the new payload pointer.
+ * @param[in] payload The new payload chunk.
+ * @param[in] payload_len The length of the new payload chunk.
+ */
+void zcbor_update_state(zcbor_state_t *state,
+ const uint8_t *payload, size_t payload_len);
+
+/** Check that the provided fragments are complete and in the right order.
+ *
+ * If the total length is not known, the total_len can have the value
+ * @ref ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH. If so, all fragments will be
+ * updated with the actual total length.
+ *
+ * @param[in] fragments An array of string fragments. Cannot be NULL.
+ * @param[in] num_fragments The number of fragments in @p fragments.
+ *
+ * @retval true If the fragments are in the right order, and there are no
+ * fragments missing.
+ * @retval false If not all fragments have the same total_len, or gaps are
+ * found, or if any fragment value is NULL.
+ */
+bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
+ uint_fast32_t num_fragments);
+
+/** Assemble the fragments into a single string.
+ *
+ * The fragments are copied in the order they appear, without regard for
+ * offset or total_len. To ensure that the fragments are correct, first
+ * validate with @ref zcbor_validate_string_fragments.
+ *
+ * @param[in] fragments An array of string fragments. Cannot be NULL.
+ * @param[in] num_fragments The number of fragments in @p fragments.
+ * @param[out] result The buffer to place the assembled string into.
+ * @param[inout] result_len In: The length of the @p result.
+ * Out: The length of the assembled string.
+ *
+ * @retval true On success.
+ * @retval false If the assembled string would be larger than the buffer.
+ * The buffer might still be written to.
+ */
+bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
+ uint_fast32_t num_fragments, uint8_t *result, size_t *result_len);
+
+#endif /* ZCBOR_COMMON_H__ */
diff --git a/boot/boot_serial/src/zcbor_debug.h b/boot/boot_serial/src/zcbor_debug.h
new file mode 100644
index 0000000..f34ad7f
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_debug.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZCBOR_DEBUG_H__
+#define ZCBOR_DEBUG_H__
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "zcbor_common.h"
+
+__attribute__((used))
+static void zcbor_print_compare_lines(const uint8_t *str1, const uint8_t *str2, uint32_t size)
+{
+ for (uint32_t j = 0; j < size; j++) {
+ printk ("%x ", str1[j]);
+ }
+ printk("\r\n");
+ for (uint32_t j = 0; j < size; j++) {
+ printk ("%x ", str2[j]);
+ }
+ printk("\r\n");
+ for (uint32_t j = 0; j < size; j++) {
+ printk ("%x ", str1[j] != str2[j]);
+ }
+ printk("\r\n");
+ printk("\r\n");
+}
+
+__attribute__((used))
+static void zcbor_print_compare_strings(const uint8_t *str1, const uint8_t *str2, uint32_t size)
+{
+ for (uint32_t i = 0; i <= size / 16; i++) {
+ printk("line %d (char %d)\r\n", i, i*16);
+ zcbor_print_compare_lines(&str1[i*16], &str2[i*16],
+ MIN(16, (size - i*16)));
+ }
+ printk("\r\n");
+}
+
+__attribute__((used))
+static void zcbor_print_compare_strings_diff(const uint8_t *str1, const uint8_t *str2, uint32_t size)
+{
+ bool printed = false;
+ for (uint32_t i = 0; i <= size / 16; i++) {
+ if (memcmp(&str1[i*16], &str2[i*16], MIN(16, (size - i*16)) != 0)) {
+ printk("line %d (char %d)\r\n", i, i*16);
+ zcbor_print_compare_lines(&str1[i*16], &str2[i*16],
+ MIN(16, (size - i*16)));
+ printed = true;
+ }
+ }
+ if (printed) {
+ printk("\r\n");
+ }
+}
+
+#endif /* ZCBOR_DEBUG_H__ */
diff --git a/boot/boot_serial/src/zcbor_decode.c b/boot/boot_serial/src/zcbor_decode.c
new file mode 100644
index 0000000..a525c20
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_decode.c
@@ -0,0 +1,919 @@
+/*
+ * This file has been copied from the zcbor library.
+ * Commit zcbor 0.4.0
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include "zcbor_decode.h"
+#include "zcbor_common.h"
+
+
+/** Return value length from additional value.
+ */
+static uint_fast32_t additional_len(uint8_t additional)
+{
+ if (ZCBOR_VALUE_IS_1_BYTE <= additional && additional <= ZCBOR_VALUE_IS_8_BYTES) {
+ /* 24 => 1
+ * 25 => 2
+ * 26 => 4
+ * 27 => 8
+ */
+ return 1U << (additional - ZCBOR_VALUE_IS_1_BYTE);
+ }
+ return 0;
+}
+
+/** Extract the major type, i.e. the first 3 bits of the header byte. */
+#define MAJOR_TYPE(header_byte) (((header_byte) >> 5) & 0x7)
+
+/** Extract the additional info, i.e. the last 5 bits of the header byte. */
+#define ADDITIONAL(header_byte) ((header_byte) & 0x1F)
+
+
+#define FAIL_AND_DECR_IF(expr, err) \
+do {\
+ if (expr) { \
+ (state->payload)--; \
+ ZCBOR_ERR(err); \
+ } \
+} while(0)
+
+static bool initial_checks(zcbor_state_t *state)
+{
+ ZCBOR_CHECK_ERROR();
+ ZCBOR_CHECK_PAYLOAD();
+ return true;
+}
+
+static bool type_check(zcbor_state_t *state, zcbor_major_type_t exp_major_type)
+{
+ if (!initial_checks(state)) {
+ ZCBOR_FAIL();
+ }
+ zcbor_major_type_t major_type = MAJOR_TYPE(*state->payload);
+
+ if (major_type != exp_major_type) {
+ ZCBOR_ERR(ZCBOR_ERR_WRONG_TYPE);
+ }
+ return true;
+}
+
+#define INITIAL_CHECKS() \
+do {\
+ if (!initial_checks(state)) { \
+ ZCBOR_FAIL(); \
+ } \
+} while(0)
+
+#define INITIAL_CHECKS_WITH_TYPE(exp_major_type) \
+do {\
+ if (!type_check(state, exp_major_type)) { \
+ ZCBOR_FAIL(); \
+ } \
+} while(0)
+
+#define ERR_RESTORE(err) \
+do { \
+ state->payload = state->payload_bak; \
+ state->elem_count++; \
+ ZCBOR_ERR(err); \
+} while(0)
+
+#define FAIL_RESTORE() \
+do { \
+ state->payload = state->payload_bak; \
+ state->elem_count++; \
+ ZCBOR_FAIL(); \
+} while(0)
+
+/** Get a single value.
+ *
+ * @details @p ppayload must point to the header byte. This function will
+ * retrieve the value (either from within the additional info, or from
+ * the subsequent bytes) and return it in the result. The result can
+ * have arbitrary length.
+ *
+ * The function will also validate
+ * - Min/max constraints on the value.
+ * - That @p payload doesn't overrun past @p payload_end.
+ * - That @p elem_count has not been exhausted.
+ *
+ * @p ppayload and @p elem_count are updated if the function
+ * succeeds. If not, they are left unchanged.
+ *
+ * CBOR values are always big-endian, so this function converts from
+ * big to little-endian if necessary (@ref CONFIG_BIG_ENDIAN).
+ */
+static bool value_extract(zcbor_state_t *state,
+ void *const result, uint_fast32_t result_len)
+{
+ zcbor_trace();
+ zcbor_assert(result_len != 0, "0-length result not supported.\r\n");
+ zcbor_assert(result != NULL, NULL);
+
+ INITIAL_CHECKS();
+ ZCBOR_ERR_IF((state->elem_count == 0), ZCBOR_ERR_LOW_ELEM_COUNT);
+
+ uint8_t *u8_result = (uint8_t *)result;
+ uint8_t additional = ADDITIONAL(*state->payload);
+
+ state->payload_bak = state->payload;
+ (state->payload)++;
+
+ memset(result, 0, result_len);
+ if (additional <= ZCBOR_VALUE_IN_HEADER) {
+#ifdef CONFIG_BIG_ENDIAN
+ u8_result[result_len - 1] = additional;
+#else
+ u8_result[0] = additional;
+#endif /* CONFIG_BIG_ENDIAN */
+ } else {
+ uint_fast32_t len = additional_len(additional);
+
+ FAIL_AND_DECR_IF(len > result_len, ZCBOR_ERR_INT_SIZE);
+ FAIL_AND_DECR_IF(len == 0, ZCBOR_ERR_ADDITIONAL_INVAL); // additional_len() did not recognize the additional value.
+ FAIL_AND_DECR_IF((state->payload + len) > state->payload_end,
+ ZCBOR_ERR_NO_PAYLOAD);
+
+#ifdef CONFIG_BIG_ENDIAN
+ memcpy(&u8_result[result_len - len], state->payload, len);
+#else
+ for (uint_fast32_t i = 0; i < len; i++) {
+ u8_result[i] = (state->payload)[len - i - 1];
+ }
+#endif /* CONFIG_BIG_ENDIAN */
+
+ (state->payload) += len;
+ }
+
+ (state->elem_count)--;
+ return true;
+}
+
+
+bool zcbor_int32_decode(zcbor_state_t *state, int32_t *result)
+{
+ int64_t result64;
+
+ if (zcbor_int64_decode(state, &result64)) {
+ if (result64 > INT32_MAX) {
+ ERR_RESTORE(ZCBOR_ERR_INT_SIZE);
+ }
+ *result = (int32_t)result64;
+ return true;
+ } else {
+ ZCBOR_FAIL();
+ }
+}
+
+
+bool zcbor_int64_decode(zcbor_state_t *state, int64_t *result)
+{
+ INITIAL_CHECKS();
+ uint8_t major_type = MAJOR_TYPE(*state->payload);
+ uint64_t uint_result;
+ int64_t int_result;
+
+ if (major_type != ZCBOR_MAJOR_TYPE_PINT
+ && major_type != ZCBOR_MAJOR_TYPE_NINT) {
+ /* Value to be read doesn't have the right type. */
+ ZCBOR_ERR(ZCBOR_ERR_WRONG_TYPE);
+ }
+
+ if (!value_extract(state, &uint_result, sizeof(uint_result))) {
+ ZCBOR_FAIL();
+ }
+
+ zcbor_print("uintval: %" PRIu64 "\r\n", uint_result);
+
+ int_result = (int64_t)uint_result;
+
+ if (int_result < 0) {
+ /* Value is too large to fit in a signed integer. */
+ ERR_RESTORE(ZCBOR_ERR_INT_SIZE);
+ }
+
+ if (major_type == ZCBOR_MAJOR_TYPE_NINT) {
+ /* Convert from CBOR's representation. */
+ *result = -1 - int_result;
+ } else {
+ *result = int_result;
+ }
+
+ zcbor_print("val: %" PRIi64 "\r\n", *result);
+ return true;
+}
+
+
+bool zcbor_uint32_decode(zcbor_state_t *state, uint32_t *result)
+{
+ INITIAL_CHECKS_WITH_TYPE(ZCBOR_MAJOR_TYPE_PINT);
+
+ if (!value_extract(state, result, sizeof(*result))) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_uint32_expect_union(zcbor_state_t *state, uint32_t result)
+{
+ zcbor_union_elem_code(state);
+ return zcbor_uint32_expect(state, result);
+}
+
+
+bool zcbor_uint64_expect_union(zcbor_state_t *state, uint64_t result)
+{
+ zcbor_union_elem_code(state);
+ return zcbor_uint64_expect(state, result);
+}
+
+
+bool zcbor_int32_expect(zcbor_state_t *state, int32_t result)
+{
+ return zcbor_int64_expect(state, result);
+}
+
+
+bool zcbor_int64_expect(zcbor_state_t *state, int64_t result)
+{
+ int64_t value;
+
+ if (!zcbor_int64_decode(state, &value)) {
+ ZCBOR_FAIL();
+ }
+
+ if (value != result) {
+ zcbor_print("%" PRIi64 " != %" PRIi64 "\r\n", value, result);
+ ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE);
+ }
+ return true;
+}
+
+
+bool zcbor_uint64_decode(zcbor_state_t *state, uint64_t *result)
+{
+ INITIAL_CHECKS_WITH_TYPE(ZCBOR_MAJOR_TYPE_PINT);
+
+ if (!value_extract(state, result, sizeof(*result))) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_uint32_expect(zcbor_state_t *state, uint32_t result)
+{
+ return zcbor_uint64_expect(state, result);
+}
+
+
+bool zcbor_uint64_expect(zcbor_state_t *state, uint64_t result)
+{
+ uint64_t value;
+
+ if (!zcbor_uint64_decode(state, &value)) {
+ ZCBOR_FAIL();
+ }
+ if (value != result) {
+ zcbor_print("%" PRIu64 " != %" PRIu64 "\r\n", value, result);
+ ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE);
+ }
+ return true;
+}
+
+
+static bool str_start_decode(zcbor_state_t *state,
+ struct zcbor_string *result, zcbor_major_type_t exp_major_type)
+{
+ INITIAL_CHECKS_WITH_TYPE(exp_major_type);
+
+ if (!value_extract(state, &result->len, sizeof(result->len))) {
+ ZCBOR_FAIL();
+ }
+
+ result->value = state->payload;
+ return true;
+}
+
+
+static bool str_overflow_check(zcbor_state_t *state, struct zcbor_string *result)
+{
+ if (result->len > (state->payload_end - state->payload)) {
+ zcbor_print("error: 0x%zu > 0x%zu\r\n",
+ result->len,
+ (state->payload_end - state->payload));
+ ERR_RESTORE(ZCBOR_ERR_NO_PAYLOAD);
+ }
+ return true;
+}
+
+
+bool zcbor_bstr_start_decode(zcbor_state_t *state, struct zcbor_string *result)
+{
+ if (result == NULL) {
+ struct zcbor_string dummy;
+ result = &dummy;
+ }
+
+ if(!str_start_decode(state, result, ZCBOR_MAJOR_TYPE_BSTR)) {
+ ZCBOR_FAIL();
+ }
+
+ if (!str_overflow_check(state, result)) {
+ ZCBOR_FAIL();
+ }
+
+ if (!zcbor_new_backup(state, ZCBOR_MAX_ELEM_COUNT)) {
+ FAIL_RESTORE();
+ }
+
+ state->payload_end = result->value + result->len;
+ return true;
+}
+
+
+bool zcbor_bstr_end_decode(zcbor_state_t *state)
+{
+ ZCBOR_ERR_IF(state->payload != state->payload_end, ZCBOR_ERR_PAYLOAD_NOT_CONSUMED);
+
+ if (!zcbor_process_backup(state,
+ ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME | ZCBOR_FLAG_TRANSFER_PAYLOAD,
+ ZCBOR_MAX_ELEM_COUNT)) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+static void partition_fragment(const zcbor_state_t *state,
+ struct zcbor_string_fragment *result)
+{
+ result->fragment.len = MIN(result->fragment.len,
+ (size_t)state->payload_end - (size_t)state->payload);
+}
+
+
+static bool start_decode_fragment(zcbor_state_t *state,
+ struct zcbor_string_fragment *result,
+ zcbor_major_type_t exp_major_type)
+{
+ if(!str_start_decode(state, &result->fragment, exp_major_type)) {
+ ZCBOR_FAIL();
+ }
+
+ result->offset = 0;
+ result->total_len = result->fragment.len;
+ partition_fragment(state, result);
+ state->payload_end = state->payload + result->fragment.len;
+
+ return true;
+}
+
+bool zcbor_bstr_start_decode_fragment(zcbor_state_t *state,
+ struct zcbor_string_fragment *result)
+{
+ if (!start_decode_fragment(state, result, ZCBOR_MAJOR_TYPE_BSTR)) {
+ ZCBOR_FAIL();
+ }
+ if (!zcbor_new_backup(state, ZCBOR_MAX_ELEM_COUNT)) {
+ FAIL_RESTORE();
+ }
+ return true;
+}
+
+
+void zcbor_next_fragment(zcbor_state_t *state,
+ struct zcbor_string_fragment *prev_fragment,
+ struct zcbor_string_fragment *result)
+{
+ memcpy(result, prev_fragment, sizeof(*result));
+ result->fragment.value = state->payload_mut;
+ result->offset += prev_fragment->fragment.len;
+ result->fragment.len = result->total_len - result->offset;
+
+ partition_fragment(state, result);
+ zcbor_print("New fragment length %zu\r\n", result->fragment.len);
+
+ state->payload += result->fragment.len;
+}
+
+
+void zcbor_bstr_next_fragment(zcbor_state_t *state,
+ struct zcbor_string_fragment *prev_fragment,
+ struct zcbor_string_fragment *result)
+{
+ memcpy(result, prev_fragment, sizeof(*result));
+ result->fragment.value = state->payload_mut;
+ result->offset += prev_fragment->fragment.len;
+ result->fragment.len = result->total_len - result->offset;
+
+ partition_fragment(state, result);
+ zcbor_print("fragment length %zu\r\n", result->fragment.len);
+ state->payload_end = state->payload + result->fragment.len;
+}
+
+
+bool zcbor_is_last_fragment(const struct zcbor_string_fragment *fragment)
+{
+ return (fragment->total_len == (fragment->offset + fragment->fragment.len));
+}
+
+
+static bool str_decode(zcbor_state_t *state, struct zcbor_string *result,
+ zcbor_major_type_t exp_major_type)
+{
+ if (!str_start_decode(state, result, exp_major_type)) {
+ ZCBOR_FAIL();
+ }
+
+ if (!str_overflow_check(state, result)) {
+ ZCBOR_FAIL();
+ }
+
+ state->payload += result->len;
+ return true;
+}
+
+
+static bool str_decode_fragment(zcbor_state_t *state, struct zcbor_string_fragment *result,
+ zcbor_major_type_t exp_major_type)
+{
+ if (!start_decode_fragment(state, result, exp_major_type)) {
+ ZCBOR_FAIL();
+ }
+
+ (state->payload) += result->fragment.len;
+ return true;
+}
+
+
+static bool str_expect(zcbor_state_t *state, struct zcbor_string *result,
+ zcbor_major_type_t exp_major_type)
+{
+ struct zcbor_string tmp_result;
+
+ if (!str_decode(state, &tmp_result, exp_major_type)) {
+ ZCBOR_FAIL();
+ }
+ if ((tmp_result.len != result->len)
+ || memcmp(result->value, tmp_result.value, tmp_result.len)) {
+ ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE);
+ }
+ return true;
+}
+
+
+bool zcbor_bstr_decode(zcbor_state_t *state, struct zcbor_string *result)
+{
+ return str_decode(state, result, ZCBOR_MAJOR_TYPE_BSTR);
+}
+
+
+bool zcbor_bstr_decode_fragment(zcbor_state_t *state, struct zcbor_string_fragment *result)
+{
+ return str_decode_fragment(state, result, ZCBOR_MAJOR_TYPE_BSTR);
+}
+
+
+bool zcbor_bstr_expect(zcbor_state_t *state, struct zcbor_string *result)
+{
+ return str_expect(state, result, ZCBOR_MAJOR_TYPE_BSTR);
+}
+
+
+bool zcbor_tstr_decode(zcbor_state_t *state, struct zcbor_string *result)
+{
+ return str_decode(state, result, ZCBOR_MAJOR_TYPE_TSTR);
+}
+
+
+bool zcbor_tstr_decode_fragment(zcbor_state_t *state, struct zcbor_string_fragment *result)
+{
+ return str_decode_fragment(state, result, ZCBOR_MAJOR_TYPE_TSTR);
+}
+
+
+bool zcbor_tstr_expect(zcbor_state_t *state, struct zcbor_string *result)
+{
+ return str_expect(state, result, ZCBOR_MAJOR_TYPE_TSTR);
+}
+
+
+static bool list_map_start_decode(zcbor_state_t *state,
+ zcbor_major_type_t exp_major_type)
+{
+ uint_fast32_t new_elem_count;
+ bool indefinite_length_array = false;
+
+ INITIAL_CHECKS_WITH_TYPE(exp_major_type);
+
+ if (ADDITIONAL(*state->payload) == ZCBOR_VALUE_IS_INDEFINITE_LENGTH) {
+ /* Indefinite length array. */
+ new_elem_count = ZCBOR_LARGE_ELEM_COUNT;
+ ZCBOR_ERR_IF(state->elem_count == 0, ZCBOR_ERR_LOW_ELEM_COUNT);
+ indefinite_length_array = true;
+ state->payload++;
+ state->elem_count--;
+ } else {
+ if (!value_extract(state, &new_elem_count, sizeof(new_elem_count))) {
+ ZCBOR_FAIL();
+ }
+ }
+
+ if (!zcbor_new_backup(state, new_elem_count)) {
+ FAIL_RESTORE();
+ }
+
+ state->indefinite_length_array = indefinite_length_array;
+
+ return true;
+}
+
+
+bool zcbor_list_start_decode(zcbor_state_t *state)
+{
+ return list_map_start_decode(state, ZCBOR_MAJOR_TYPE_LIST);
+}
+
+
+bool zcbor_map_start_decode(zcbor_state_t *state)
+{
+ bool ret = list_map_start_decode(state, ZCBOR_MAJOR_TYPE_MAP);
+
+ if (ret && !state->indefinite_length_array) {
+ if (state->elem_count >= (ZCBOR_MAX_ELEM_COUNT / 2)) {
+ /* The new elem_count is too large. */
+ ERR_RESTORE(ZCBOR_ERR_INT_SIZE);
+ }
+ state->elem_count *= 2;
+ }
+ return ret;
+}
+
+
+static bool array_end_expect(zcbor_state_t *state)
+{
+ INITIAL_CHECKS();
+ ZCBOR_ERR_IF(*state->payload != 0xFF, ZCBOR_ERR_WRONG_TYPE);
+
+ state->payload++;
+ return true;
+}
+
+
+static bool list_map_end_decode(zcbor_state_t *state)
+{
+ uint_fast32_t max_elem_count = 0;
+
+ if (state->indefinite_length_array) {
+ if (!array_end_expect(state)) {
+ ZCBOR_FAIL();
+ }
+ max_elem_count = ZCBOR_MAX_ELEM_COUNT;
+ state->indefinite_length_array = false;
+ }
+ if (!zcbor_process_backup(state,
+ ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME | ZCBOR_FLAG_TRANSFER_PAYLOAD,
+ max_elem_count)) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_list_end_decode(zcbor_state_t *state)
+{
+ return list_map_end_decode(state);
+}
+
+
+bool zcbor_map_end_decode(zcbor_state_t *state)
+{
+ return list_map_end_decode(state);
+}
+
+
+bool zcbor_list_map_end_force_decode(zcbor_state_t *state)
+{
+ if (!zcbor_process_backup(state,
+ ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME | ZCBOR_FLAG_TRANSFER_PAYLOAD,
+ ZCBOR_MAX_ELEM_COUNT)) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+static bool primx_expect(zcbor_state_t *state, uint8_t result)
+{
+ uint32_t value;
+
+ INITIAL_CHECKS_WITH_TYPE(ZCBOR_MAJOR_TYPE_PRIM);
+
+ if (!value_extract(state, &value, sizeof(value))) {
+ ZCBOR_FAIL();
+ }
+
+ if (value != result) {
+ ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE);
+ }
+ return true;
+}
+
+
+bool zcbor_nil_expect(zcbor_state_t *state, void *unused)
+{
+ if (!primx_expect(state, 22)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_undefined_expect(zcbor_state_t *state, void *unused)
+{
+ if (!primx_expect(state, 23)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_bool_decode(zcbor_state_t *state, bool *result)
+{
+ if (zcbor_bool_expect(state, false)) {
+ *result = false;
+ } else if (zcbor_bool_expect(state, true)) {
+ *result = true;
+ } else {
+ ZCBOR_FAIL();
+ }
+
+ zcbor_print("boolval: %u\r\n", *result);
+ return true;
+}
+
+
+bool zcbor_bool_expect(zcbor_state_t *state, bool result)
+{
+ if (!primx_expect(state, (uint8_t)(!!result) + ZCBOR_BOOL_TO_PRIM)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_float32_decode(zcbor_state_t *state, float *result)
+{
+ INITIAL_CHECKS_WITH_TYPE(ZCBOR_MAJOR_TYPE_PRIM);
+ ZCBOR_ERR_IF(ADDITIONAL(*state->payload) != ZCBOR_VALUE_IS_4_BYTES, ZCBOR_ERR_FLOAT_SIZE);
+
+ if (!value_extract(state, result, sizeof(*result))) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_float32_expect(zcbor_state_t *state, float result)
+{
+ float value;
+
+ if (!zcbor_float32_decode(state, &value)) {
+ ZCBOR_FAIL();
+ }
+ if (value != result) {
+ ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE);
+ }
+ return true;
+}
+
+
+bool zcbor_float64_decode(zcbor_state_t *state, double *result)
+{
+ INITIAL_CHECKS_WITH_TYPE(ZCBOR_MAJOR_TYPE_PRIM);
+ ZCBOR_ERR_IF(ADDITIONAL(*state->payload) != ZCBOR_VALUE_IS_8_BYTES, ZCBOR_ERR_FLOAT_SIZE);
+
+ if (!value_extract(state, result, sizeof(*result))) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_float64_expect(zcbor_state_t *state, double result)
+{
+ double value;
+
+ if (!zcbor_float64_decode(state, &value)) {
+ ZCBOR_FAIL();
+ }
+ if (value != result) {
+ ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE);
+ }
+ return true;
+}
+
+
+bool zcbor_float_decode(zcbor_state_t *state, double *result)
+{
+ float float_result;
+
+ if (zcbor_float32_decode(state, &float_result)) {
+ *result = (double)float_result;
+ } else if (!zcbor_float64_decode(state, result)) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_float_expect(zcbor_state_t *state, double result)
+{
+ if (zcbor_float32_expect(state, (float)result)) {
+ /* Do nothing */
+ } else if (!zcbor_float64_expect(state, result)) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_any_skip(zcbor_state_t *state, void *result)
+{
+ zcbor_assert(result == NULL,
+ "'any' type cannot be returned, only skipped.\r\n");
+
+ INITIAL_CHECKS();
+ uint8_t major_type = MAJOR_TYPE(*state->payload);
+ uint8_t additional = ADDITIONAL(*state->payload);
+ uint_fast32_t value;
+ uint_fast32_t num_decode;
+ uint_fast32_t temp_elem_count;
+ uint_fast32_t elem_count_bak = state->elem_count;
+ uint8_t const *payload_bak = state->payload;
+ uint64_t tag_dummy;
+
+ payload_bak = state->payload;
+
+ if (!zcbor_multi_decode(0, ZCBOR_LARGE_ELEM_COUNT, &num_decode,
+ (zcbor_decoder_t *)zcbor_tag_decode, state,
+ (void *)&tag_dummy, 0)) {
+ state->elem_count = elem_count_bak;
+ state->payload = payload_bak;
+ ZCBOR_FAIL();
+ }
+
+ if ((major_type == ZCBOR_MAJOR_TYPE_MAP) || (major_type == ZCBOR_MAJOR_TYPE_LIST)) {
+ if (additional == ZCBOR_VALUE_IS_INDEFINITE_LENGTH) {
+ ZCBOR_ERR_IF(state->elem_count == 0, ZCBOR_ERR_LOW_ELEM_COUNT);
+ state->payload++;
+ state->elem_count--;
+ temp_elem_count = state->elem_count;
+ payload_bak = state->payload;
+ state->elem_count = ZCBOR_LARGE_ELEM_COUNT;
+ if (!zcbor_multi_decode(0, ZCBOR_LARGE_ELEM_COUNT, &num_decode,
+ (zcbor_decoder_t *)zcbor_any_skip, state,
+ NULL, 0)
+ || (state->payload >= state->payload_end)
+ || !(*(state->payload++) == 0xFF)) {
+ state->elem_count = elem_count_bak;
+ state->payload = payload_bak;
+ ZCBOR_FAIL();
+ }
+ state->elem_count = temp_elem_count;
+ return true;
+ }
+ }
+
+ if (!value_extract(state, &value, sizeof(value))) {
+ /* Can happen because of elem_count (or payload_end) */
+ ZCBOR_FAIL();
+ }
+
+ switch (major_type) {
+ case ZCBOR_MAJOR_TYPE_BSTR:
+ case ZCBOR_MAJOR_TYPE_TSTR:
+ /* 'value' is the length of the BSTR or TSTR */
+ if (value > (state->payload_end - state->payload)) {
+ ZCBOR_ERR(ZCBOR_ERR_NO_PAYLOAD);
+ }
+ (state->payload) += value;
+ break;
+ case ZCBOR_MAJOR_TYPE_MAP:
+ value *= 2; /* Because all members have a key. */
+ /* Fallthrough */
+ case ZCBOR_MAJOR_TYPE_LIST:
+ temp_elem_count = state->elem_count;
+ state->elem_count = value;
+ if (!zcbor_multi_decode(value, value, &num_decode,
+ (zcbor_decoder_t *)zcbor_any_skip, state,
+ NULL, 0)) {
+ state->elem_count = elem_count_bak;
+ state->payload = payload_bak;
+ ZCBOR_FAIL();
+ }
+ state->elem_count = temp_elem_count;
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ return true;
+}
+
+
+bool zcbor_tag_decode(zcbor_state_t *state, uint32_t *result)
+{
+ INITIAL_CHECKS_WITH_TYPE(ZCBOR_MAJOR_TYPE_TAG);
+
+ if (!value_extract(state, result, sizeof(*result))) {
+ ZCBOR_FAIL();
+ }
+ state->elem_count++;
+ return true;
+}
+
+
+bool zcbor_tag_expect(zcbor_state_t *state, uint32_t result)
+{
+ uint32_t tag_val;
+
+ if (!zcbor_tag_decode(state, &tag_val)) {
+ ZCBOR_FAIL();
+ }
+ if (tag_val != result) {
+ ERR_RESTORE(ZCBOR_ERR_WRONG_VALUE);
+ }
+ return true;
+}
+
+
+bool zcbor_multi_decode(uint_fast32_t min_decode,
+ uint_fast32_t max_decode,
+ uint_fast32_t *num_decode,
+ zcbor_decoder_t decoder,
+ zcbor_state_t *state,
+ void *result,
+ uint_fast32_t result_len)
+{
+ ZCBOR_CHECK_ERROR();
+ for (uint_fast32_t i = 0; i < max_decode; i++) {
+ uint8_t const *payload_bak = state->payload;
+ uint_fast32_t elem_count_bak = state->elem_count;
+
+ if (!decoder(state,
+ (uint8_t *)result + i*result_len)) {
+ *num_decode = i;
+ state->payload = payload_bak;
+ state->elem_count = elem_count_bak;
+ ZCBOR_ERR_IF(i < min_decode, ZCBOR_ERR_ITERATIONS);
+ zcbor_print("Found %" PRIuFAST32 " elements.\r\n", i);
+ return true;
+ }
+ }
+ zcbor_print("Found %" PRIuFAST32 " elements.\r\n", max_decode);
+ *num_decode = max_decode;
+ return true;
+}
+
+
+bool zcbor_present_decode(uint_fast32_t *present,
+ zcbor_decoder_t decoder,
+ zcbor_state_t *state,
+ void *result)
+{
+ uint_fast32_t num_decode;
+ bool retval = zcbor_multi_decode(0, 1, &num_decode, decoder, state, result, 0);
+
+ zcbor_assert(retval, "zcbor_multi_decode should not fail with these parameters.\r\n");
+
+ *present = num_decode;
+ return retval;
+}
+
+
+bool zcbor_new_decode_state(zcbor_state_t *state_array, uint_fast32_t n_states,
+ const uint8_t *payload, size_t payload_len, uint_fast32_t elem_count)
+{
+ return zcbor_new_state(state_array, n_states, payload, payload_len, elem_count);
+}
diff --git a/boot/boot_serial/src/zcbor_decode.h b/boot/boot_serial/src/zcbor_decode.h
new file mode 100644
index 0000000..33a51fe
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_decode.h
@@ -0,0 +1,336 @@
+/*
+ * This file has been copied from the zcbor library.
+ * Commit zcbor 0.4.0
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZCBOR_DECODE_H__
+#define ZCBOR_DECODE_H__
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "zcbor_common.h"
+
+/** The zcbor_decode library provides functions for decoding CBOR data elements.
+ *
+ * See The README for an introduction to CBOR, including the meaning of pint,
+ * nint, bstr etc.
+ */
+
+
+/** The following applies to all single-value decode functions that don't have docs.
+ *
+ * @param[inout] state The current state of the decoding.
+ * @param[out] result Where to place the decoded value.
+ *
+ * @retval true If the value was decoded correctly.
+ * @retval false If the value has the wrong type, the payload overflowed, the
+ * element count was exhausted, or the value was larger than can
+ * fit in the result variable.
+ */
+
+/** Decode and consume a pint/nint. */
+bool zcbor_int32_decode(zcbor_state_t *state, int32_t *result);
+bool zcbor_int64_decode(zcbor_state_t *state, int64_t *result);
+bool zcbor_uint32_decode(zcbor_state_t *state, uint32_t *result);
+bool zcbor_uint64_decode(zcbor_state_t *state, uint64_t *result);
+
+/** The following applies to all _expect() functions that don't have docs.
+ *
+ * @param[inout] state The current state of the decoding.
+ * @param[in] result The expected value.
+ *
+ * @retval true If the result was decoded correctly and has the expected value.
+ * @retval false If the decoding failed or the result doesn't have the
+ * expected value.
+ */
+/** Consume and expect a pint/nint with a certain value. */
+bool zcbor_int32_expect(zcbor_state_t *state, int32_t result);
+bool zcbor_int64_expect(zcbor_state_t *state, int64_t result);
+bool zcbor_uint32_expect(zcbor_state_t *state, uint32_t result);
+bool zcbor_uint64_expect(zcbor_state_t *state, uint64_t result);
+
+/** Consume and expect a pint with a certain value, within a union.
+ *
+ * Calls @ref zcbor_union_elem_code then @ref zcbor_uint32_expect.
+ */
+bool zcbor_uint32_expect_union(zcbor_state_t *state, uint32_t result);
+bool zcbor_uint64_expect_union(zcbor_state_t *state, uint64_t result);
+
+/** Decode and consume a bstr/tstr */
+bool zcbor_bstr_decode(zcbor_state_t *state, struct zcbor_string *result);
+bool zcbor_bstr_expect(zcbor_state_t *state, struct zcbor_string *result);
+bool zcbor_tstr_decode(zcbor_state_t *state, struct zcbor_string *result);
+bool zcbor_tstr_expect(zcbor_state_t *state, struct zcbor_string *result);
+
+/** Consume and expect a bstr/tstr with the value of the provided string literal.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to expect. A pointer to the string.
+ * @param[in] len The length of the string pointed to by @p string.
+ */
+static inline bool zcbor_bstr_expect_ptr(zcbor_state_t *state, uint8_t *ptr, size_t len)
+{
+ return zcbor_bstr_expect(state, &(struct zcbor_string){.value = ptr, .len = len});
+}
+static inline bool zcbor_tstr_expect_ptr(zcbor_state_t *state, uint8_t *ptr, size_t len)
+{
+ return zcbor_tstr_expect(state, &(struct zcbor_string){.value = ptr, .len = len});
+}
+
+
+/** Consume and expect a bstr/tstr with the value of the provided string literal.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to expect. A string literal, e.g. "Foo", so
+ * that sizeof(string) - 1 is the length of the string.
+ */
+#define zcbor_bstr_expect_lit(state, string) \
+ zcbor_bstr_expect_ptr(state, string, sizeof(string) - 1)
+#define zcbor_tstr_expect_lit(state, string) \
+ zcbor_tstr_expect_ptr(state, string, sizeof(string) - 1)
+
+/** Consume and expect a bstr/tstr with the value of the provided null-terminated string.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to expect. Must be a null-terminated string,
+ * so that strlen can be used.
+ */
+#define zcbor_bstr_expect_term(state, string) \
+ zcbor_bstr_expect_ptr(state, string, strlen(string))
+#define zcbor_tstr_expect_term(state, string) \
+ zcbor_tstr_expect_ptr(state, string, strlen(string))
+
+/** Consume and expect a bstr/tstr with the value of the provided char array literal.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to expect. An array literal, e.g. {'F', 'o', 'o'},
+ * so that sizeof(string) is the length of the string.
+ */
+#define zcbor_bstr_expect_arr(state, string) \
+ zcbor_bstr_expect_ptr(state, string, (sizeof(string)))
+#define zcbor_tstr_expect_arr(state, string) \
+ zcbor_tstr_expect_ptr(state, string, (sizeof(string)))
+
+/** Decode and consume a tag. */
+bool zcbor_tag_decode(zcbor_state_t *state, uint32_t *result);
+bool zcbor_tag_expect(zcbor_state_t *state, uint32_t result);
+
+/** Decode and consume a boolean primitive value. */
+bool zcbor_bool_decode(zcbor_state_t *state, bool *result);
+bool zcbor_bool_expect(zcbor_state_t *state, bool result);
+
+/** Decode and consume a float */
+bool zcbor_float32_decode(zcbor_state_t *state, float *result);
+bool zcbor_float32_expect(zcbor_state_t *state, float result);
+bool zcbor_float64_decode(zcbor_state_t *state, double *result);
+bool zcbor_float64_expect(zcbor_state_t *state, double result);
+bool zcbor_float_decode(zcbor_state_t *state, double *result);
+bool zcbor_float_expect(zcbor_state_t *state, double result);
+
+/** Consume and expect a "nil"/"undefined" primitive value.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] unused Unused parameter to maintain signature parity with
+ * @ref zcbor_decoder_t.
+ */
+bool zcbor_nil_expect(zcbor_state_t *state, void *unused);
+bool zcbor_undefined_expect(zcbor_state_t *state, void *unused);
+
+/** Skip a single element, regardless of type and value.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] unused Unused parameter to maintain signature parity with
+ * @ref zcbor_decoder_t.
+ */
+bool zcbor_any_skip(zcbor_state_t *state, void *unused);
+
+/** Decode and consume a bstr header.
+ *
+ * The rest of the string can be decoded as CBOR.
+ * A state backup is created to keep track of the element count.
+ * Call @ref zcbor_bstr_end_decode when done decoding the contents of the bstr.
+ *
+ * @retval true Header decoded correctly
+ * @retval false Header decoded incorrectly, or backup failed.
+ */
+bool zcbor_bstr_start_decode(zcbor_state_t *state, struct zcbor_string *result);
+
+/** Finalize decoding a CBOR-encoded bstr.
+ *
+ * Restore element count from backup.
+ */
+bool zcbor_bstr_end_decode(zcbor_state_t *state);
+
+/** Start decoding a bstr/tstr, even if the payload contains only part of it.
+ *
+ * This must be followed by a call to @ref zcbor_update_state, which can be
+ * followed by a call to @ref zcbor_next_fragment. Do not call this function
+ * again on subsequent fragments of the same string.
+ *
+ * This consumes the remaining payload as long as it belongs to the string.
+ */
+bool zcbor_bstr_decode_fragment(zcbor_state_t *state, struct zcbor_string_fragment *result);
+bool zcbor_tstr_decode_fragment(zcbor_state_t *state, struct zcbor_string_fragment *result);
+
+/** Extract the next fragment of a string.
+ *
+ * Use this function to extract all but the first fragment.
+ */
+void zcbor_next_fragment(zcbor_state_t *state,
+ struct zcbor_string_fragment *prev_fragment,
+ struct zcbor_string_fragment *result);
+
+/** Decode and consume a bstr header, assuming the payload does not contain the whole bstr.
+ *
+ * The rest of the string can be decoded as CBOR.
+ * A state backup is created to keep track of the element count.
+ * Call @ref zcbor_update_state followed by @ref zcbor_bstr_next_fragment when
+ * the current payload has been exhausted.
+ * Call @ref zcbor_bstr_end_decode when done decoding the contents of the bstr.
+ */
+bool zcbor_bstr_start_decode_fragment(zcbor_state_t *state,
+ struct zcbor_string_fragment *result);
+
+/** Start decoding the next fragment of a string.
+ *
+ * Use this function to extract all but the first fragment of a CBOR-encoded
+ * bstr.
+ */
+void zcbor_bstr_next_fragment(zcbor_state_t *state,
+ struct zcbor_string_fragment *prev_fragment,
+ struct zcbor_string_fragment *result);
+
+/** Can be used on any fragment to tell if it is the final fragment of the string. */
+bool zcbor_is_last_fragment(const struct zcbor_string_fragment *fragment);
+
+/** Decode and consume a list/map header.
+ *
+ * The contents of the list can be decoded via subsequent function calls.
+ * A state backup is created to keep track of the element count.
+ * Call @ref zcbor_list_end_decode / @ref zcbor_map_end_decode when done
+ * decoding the contents of the list/map
+ *
+ * @retval true Header decoded correctly
+ * @retval false Header decoded incorrectly, or backup failed.
+ */
+bool zcbor_list_start_decode(zcbor_state_t *state);
+bool zcbor_map_start_decode(zcbor_state_t *state);
+
+/** Finalize decoding a list/map
+ *
+ * Check that the list/map had the correct number of elements, and restore the
+ * previous element count from the backup.
+ *
+ * Use @ref zcbor_list_map_end_force_decode to forcibly consume the backup if
+ * something has gone wrong.
+ *
+ * @retval true Everything ok.
+ * @retval false Element count not correct.
+ */
+bool zcbor_list_end_decode(zcbor_state_t *state);
+bool zcbor_map_end_decode(zcbor_state_t *state);
+bool zcbor_list_map_end_force_decode(zcbor_state_t *state);
+
+/** Decode 0 or more elements with the same type and constraints.
+ *
+ * The decoded values will appear consecutively in the @p result array.
+ *
+ * The following is an example of decoding a list containing 3 INTS followed by
+ * 0 to 2 bstrs:
+ *
+ * @code{c}
+ * uint32_t ints[3];
+ * struct zcbor_string bstrs[2];
+ * uint32_t num_decode;
+ * bool res;
+ *
+ * res = zcbor_list_start_decode(state);
+ * res = res && zcbor_multi_decode(3, 3, &num_decode, zcbor_uint32_decode,
+ * state, ints, sizeof(ints[0]));
+ * res = res && zcbor_multi_decode(0, 2, &num_decode, zcbor_bstr_decode,
+ * state, bstrs, sizeof(bstrs[0]));
+ * res = res && zcbor_list_end_decode(state);
+ * // check res
+ * @endcode
+ *
+ * The @ref zcbor_decoder_t type is designed to be compatible with all single-
+ * value decoder functions in this library, e.g. @ref zcbor_uint32_decode,
+ * @ref zcbor_tstr_expect, @ref zcbor_nil_expect, etc. For _expect() functions,
+ * @p result will be used as a value instead of an array/pointer, so
+ * @p result_len will determine how much the value changes for each call.
+ * To decode the same value multiple times, use a @p result_len of 0.
+ * This function can also be used with custom decoder functions, such as those
+ * generated by the zcbor.py script, which for example decodes larger chunks of
+ * the data at once.
+ *
+ * @param[in] min_decode The minimum acceptable number of elements.
+ * @param[in] max_decode The maximum acceptable number of elements.
+ * @param[out] num_decode The actual number of elements decoded.
+ * @param[in] decoder The decoder function to call under the hood. This
+ * function will be called with the provided arguments
+ * repeatedly until the function fails (returns false)
+ * or until it has been called @p max_decode times.
+ * The result pointer is moved @p result_len bytes for
+ * each call to @p decoder, i.e. @p result refers to
+ * an array of result variables.
+ * @param[out] result Where to place the decoded values. Must be an array
+ * of at least @p max_decode elements.
+ * @param[in] result_len The length of each result variable. Must be the
+ * length of the individual elements of @p result.
+ *
+ * @retval true If at least @p min_decode variables were correctly decoded.
+ * @retval false If @p decoder failed before having decoded @p min_decode
+ * values.
+ */
+bool zcbor_multi_decode(uint_fast32_t min_decode, uint_fast32_t max_decode, uint_fast32_t *num_decode,
+ zcbor_decoder_t decoder, zcbor_state_t *state, void *result,
+ uint_fast32_t result_len);
+
+/** Attempt to decode a value that might not be present in the data.
+ *
+ * Works like @ref zcbor_multi_decode, with @p present as num_decode.
+ * Will return true, even if the data is not present.
+ *
+ * @param[out] present Whether or not the data was present and successfully decoded.
+ * @param[in] decoder The decoder to attempt.
+ * @param[out] result The result, if present.
+ *
+ * @return Should always return true.
+ */
+bool zcbor_present_decode(uint_fast32_t *present,
+ zcbor_decoder_t decoder,
+ zcbor_state_t *state,
+ void *result);
+
+/** See @ref zcbor_new_state() */
+bool zcbor_new_decode_state(zcbor_state_t *state_array, uint_fast32_t n_states,
+ const uint8_t *payload, size_t payload_len, uint_fast32_t elem_count);
+
+/** Convenience macro for declaring and initializing a state with backups.
+ *
+ * This gives you a state variable named @p name. The variable functions like
+ * a pointer.
+ *
+ * The return value from @ref zcbor_new_encode_state can be safely ignored
+ * because the only error condition is n_states < 2, and this macro adds 2 to
+ * num_backups to get n_states, so it can never be < 2.
+ *
+ * @param[in] name The name of the new state variable.
+ * @param[in] num_backups The number of backup slots to keep in the state.
+ * @param[in] payload The payload to work on.
+ * @param[in] payload_size The size (in bytes) of @p payload.
+ * @param[in] elem_count The starting elem_count (typically 1).
+ */
+#define ZCBOR_STATE_D(name, num_backups, payload, payload_size, elem_count) \
+zcbor_state_t name[((num_backups) + 2)]; \
+do { \
+ (void)zcbor_new_decode_state(name, ARRAY_SIZE(name), payload, payload_size, elem_count); \
+} while(0)
+
+#endif /* ZCBOR_DECODE_H__ */
diff --git a/boot/boot_serial/src/zcbor_encode.c b/boot/boot_serial/src/zcbor_encode.c
new file mode 100644
index 0000000..2a4d5e3
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_encode.c
@@ -0,0 +1,587 @@
+/*
+ * This file has been copied from the zcbor library.
+ * Commit zcbor 0.4.0
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include "zcbor_encode.h"
+#include "zcbor_common.h"
+
+_Static_assert((sizeof(size_t) == sizeof(void *)),
+ "This code needs size_t to be the same length as pointers.");
+
+
+static uint8_t log2ceil(uint_fast32_t val)
+{
+ switch(val) {
+ case 1: return 0;
+ case 2: return 1;
+ case 3: return 2;
+ case 4: return 2;
+ case 5: return 3;
+ case 6: return 3;
+ case 7: return 3;
+ case 8: return 3;
+ }
+
+ zcbor_print("Should not come here.\r\n");
+ return 0;
+}
+
+static uint8_t get_additional(uint_fast32_t len, uint8_t value0)
+{
+ return len == 0 ? value0 : (uint8_t)(24 + log2ceil(len));
+}
+
+static bool encode_header_byte(zcbor_state_t *state,
+ zcbor_major_type_t major_type, uint8_t additional)
+{
+ ZCBOR_CHECK_ERROR();
+ ZCBOR_CHECK_PAYLOAD();
+
+ zcbor_assert(additional < 32, NULL);
+
+ *(state->payload_mut++) = (uint8_t)((major_type << 5) | (additional & 0x1F));
+ return true;
+}
+
+
+static uint_fast32_t get_encoded_len(const void *const result, uint_fast32_t result_len);
+
+
+/** Encode a single value.
+ */
+static bool value_encode_len(zcbor_state_t *state, zcbor_major_type_t major_type,
+ const void *const result, uint_fast32_t result_len)
+{
+ uint8_t *u8_result = (uint8_t *)result;
+ uint_fast32_t encoded_len = get_encoded_len(result, result_len);
+
+ if ((state->payload + 1 + encoded_len) > state->payload_end) {
+ ZCBOR_ERR(ZCBOR_ERR_NO_PAYLOAD);
+ }
+
+ if (!encode_header_byte(state, major_type,
+ get_additional(encoded_len, u8_result[0]))) {
+ ZCBOR_FAIL();
+ }
+ state->payload_mut--;
+ zcbor_trace();
+ state->payload_mut++;
+
+#ifdef CONFIG_BIG_ENDIAN
+ memcpy(state->payload_mut, u8_result, encoded_len);
+ state->payload_mut += encoded_len;
+#else
+ for (; encoded_len > 0; encoded_len--) {
+ *(state->payload_mut++) = u8_result[encoded_len - 1];
+ }
+#endif /* CONFIG_BIG_ENDIAN */
+
+ state->elem_count++;
+ return true;
+}
+
+
+static uint_fast32_t get_result_len(const void *const input, uint_fast32_t max_result_len)
+{
+ uint8_t *u8_result = (uint8_t *)input;
+ uint_fast32_t len = max_result_len;
+
+ for (; len > 0; len--) {
+#ifdef CONFIG_BIG_ENDIAN
+ if (u8_result[max_result_len - len] != 0) {
+#else
+ if (u8_result[len - 1] != 0) {
+#endif /* CONFIG_BIG_ENDIAN */
+ break;
+ }
+ }
+
+ /* Round up to nearest power of 2. */
+ return len <= 2 ? len : (uint8_t)(1 << log2ceil(len));
+}
+
+
+static const void *get_result(const void *const input, uint_fast32_t max_result_len,
+ uint_fast32_t result_len)
+{
+#ifdef CONFIG_BIG_ENDIAN
+ return &((uint8_t *)input)[max_result_len - result_len];
+#else
+ return input;
+#endif
+}
+
+
+static uint_fast32_t get_encoded_len(const void *const result, uint_fast32_t result_len)
+{
+ const uint8_t *u8_result = (const uint8_t *)result;
+
+ if ((result_len == 1) && (u8_result[0] <= ZCBOR_VALUE_IN_HEADER)) {
+ return 0;
+ }
+ return result_len;
+}
+
+
+static bool value_encode(zcbor_state_t *state, zcbor_major_type_t major_type,
+ const void *const input, uint_fast32_t max_result_len)
+{
+ zcbor_assert(max_result_len != 0, "0-length result not supported.\r\n");
+
+ uint_fast32_t result_len = get_result_len(input, max_result_len);
+ const void *const result = get_result(input, max_result_len, result_len);
+
+ return value_encode_len(state, major_type, result, result_len);
+}
+
+
+bool zcbor_int32_put(zcbor_state_t *state, int32_t input)
+{
+ return zcbor_int64_put(state, input);
+}
+
+
+bool zcbor_int64_put(zcbor_state_t *state, int64_t input)
+{
+ zcbor_major_type_t major_type;
+
+ if (input < 0) {
+ major_type = ZCBOR_MAJOR_TYPE_NINT;
+ /* Convert from CBOR's representation. */
+ input = -1 - input;
+ } else {
+ major_type = ZCBOR_MAJOR_TYPE_PINT;
+ input = input;
+ }
+
+ if (!value_encode(state, major_type, &input, 8)) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_int32_encode(zcbor_state_t *state, const int32_t *input)
+{
+ return zcbor_int32_put(state, *input);
+}
+
+
+static bool uint32_encode(zcbor_state_t *state, const uint32_t *input,
+ zcbor_major_type_t major_type)
+{
+ if (!value_encode(state, major_type, input, 4)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_uint32_encode(zcbor_state_t *state, const uint32_t *input)
+{
+ if (!uint32_encode(state, input, ZCBOR_MAJOR_TYPE_PINT)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_int64_encode(zcbor_state_t *state, const int64_t *input)
+{
+ return zcbor_int64_put(state, *input);
+}
+
+
+static bool uint64_encode(zcbor_state_t *state, const uint64_t *input,
+ zcbor_major_type_t major_type)
+{
+ if (!value_encode(state, major_type, input, 8)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_uint64_encode(zcbor_state_t *state, const uint64_t *input)
+{
+ if (!uint64_encode(state, input, ZCBOR_MAJOR_TYPE_PINT)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_uint32_put(zcbor_state_t *state, uint32_t input)
+{
+ return zcbor_uint64_put(state, input);
+}
+
+
+bool zcbor_uint64_put(zcbor_state_t *state, uint64_t input)
+{
+ if (!uint64_encode(state, &input, ZCBOR_MAJOR_TYPE_PINT)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+static bool str_start_encode(zcbor_state_t *state,
+ const struct zcbor_string *input, zcbor_major_type_t major_type)
+{
+ if (input->value && ((get_result_len(&input->len, sizeof(input->len))
+ + 1 + input->len + (size_t)state->payload)
+ > (size_t)state->payload_end)) {
+ ZCBOR_ERR(ZCBOR_ERR_NO_PAYLOAD);
+ }
+ if (!value_encode(state, major_type, &input->len, sizeof(input->len))) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+static bool primitive_put(zcbor_state_t *state, uint32_t input)
+{
+ if (!uint32_encode(state, &input, ZCBOR_MAJOR_TYPE_PRIM)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+static size_t remaining_str_len(zcbor_state_t *state)
+{
+ size_t max_len = (size_t)state->payload_end - (size_t)state->payload;
+ size_t result_len = get_result_len(&max_len, sizeof(max_len));
+
+ return max_len - result_len - 1;
+}
+
+
+bool zcbor_bstr_start_encode(zcbor_state_t *state)
+{
+ if (!zcbor_new_backup(state, 0)) {
+ ZCBOR_FAIL();
+ }
+
+ uint64_t max_len = remaining_str_len(state);
+
+ /* Encode a dummy header */
+ if (!uint64_encode(state, &max_len,
+ ZCBOR_MAJOR_TYPE_BSTR)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_bstr_end_encode(zcbor_state_t *state, struct zcbor_string *result)
+{
+ const uint8_t *payload = state->payload;
+ struct zcbor_string dummy_value;
+
+ if (result == NULL) {
+ /* Use a dummy value for the sake of the length calculation below.
+ * Will not be returned.
+ */
+ result = &dummy_value;
+ }
+
+ if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME, 0xFFFFFFFF)) {
+ ZCBOR_FAIL();
+ }
+
+ result->value = state->payload_end - remaining_str_len(state);
+ result->len = (size_t)payload - (size_t)result->value;
+
+ /* Reencode header of list now that we know the number of elements. */
+ if (!zcbor_bstr_encode(state, result)) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+static bool str_encode(zcbor_state_t *state,
+ const struct zcbor_string *input, zcbor_major_type_t major_type)
+{
+ if (input->len > (state->payload_end - state->payload)) {
+ ZCBOR_ERR(ZCBOR_ERR_NO_PAYLOAD);
+ }
+ if (!str_start_encode(state, input, major_type)) {
+ ZCBOR_FAIL();
+ }
+ if (state->payload_mut != input->value) {
+ /* Use memmove since string might be encoded into the same space
+ * because of bstrx_cbor_start_encode/bstrx_cbor_end_encode. */
+ memmove(state->payload_mut, input->value, input->len);
+ }
+ state->payload += input->len;
+ return true;
+}
+
+
+bool zcbor_bstr_encode(zcbor_state_t *state, const struct zcbor_string *input)
+{
+ return str_encode(state, input, ZCBOR_MAJOR_TYPE_BSTR);
+}
+
+
+bool zcbor_tstr_encode(zcbor_state_t *state, const struct zcbor_string *input)
+{
+ return str_encode(state, input, ZCBOR_MAJOR_TYPE_TSTR);
+}
+
+
+static bool list_map_start_encode(zcbor_state_t *state, uint_fast32_t max_num,
+ zcbor_major_type_t major_type)
+{
+#ifdef ZCBOR_CANONICAL
+ if (!zcbor_new_backup(state, 0)) {
+ ZCBOR_FAIL();
+ }
+
+ /* Encode dummy header with max number of elements. */
+ if (!value_encode(state, major_type, &max_num, sizeof(max_num))) {
+ ZCBOR_FAIL();
+ }
+ state->elem_count--; /* Because of dummy header. */
+#else
+ if (!encode_header_byte(state, major_type, ZCBOR_VALUE_IS_INDEFINITE_LENGTH)) {
+ ZCBOR_FAIL();
+ }
+#endif
+ return true;
+}
+
+
+bool zcbor_list_start_encode(zcbor_state_t *state, uint_fast32_t max_num)
+{
+ return list_map_start_encode(state, max_num, ZCBOR_MAJOR_TYPE_LIST);
+}
+
+
+bool zcbor_map_start_encode(zcbor_state_t *state, uint_fast32_t max_num)
+{
+ return list_map_start_encode(state, max_num, ZCBOR_MAJOR_TYPE_MAP);
+}
+
+
+#ifdef ZCBOR_CANONICAL
+static uint_fast32_t get_encoded_len2(const void *const input, uint_fast32_t max_result_len)
+{
+ uint_fast32_t result_len = get_result_len(input, max_result_len);
+ const void *const result = get_result(input, max_result_len, result_len);
+
+ return get_encoded_len(result, result_len);
+}
+#endif
+
+
+static bool list_map_end_encode(zcbor_state_t *state, uint_fast32_t max_num,
+ zcbor_major_type_t major_type)
+{
+#ifdef ZCBOR_CANONICAL
+ uint_fast32_t list_count = ((major_type == ZCBOR_MAJOR_TYPE_LIST) ?
+ state->elem_count
+ : (state->elem_count / 2));
+
+ const uint8_t *payload = state->payload;
+
+ uint_fast32_t max_header_len = get_encoded_len2(&max_num, 4);
+ uint_fast32_t header_len = get_encoded_len2(&list_count, 4);
+
+ if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME, 0xFFFFFFFF)) {
+ ZCBOR_FAIL();
+ }
+
+ zcbor_print("list_count: %" PRIuFAST32 "\r\n", list_count);
+
+ /* Reencode header of list now that we know the number of elements. */
+ if (!(value_encode(state, major_type, &list_count, sizeof(list_count)))) {
+ ZCBOR_FAIL();
+ }
+
+ if (max_header_len != header_len) {
+ const uint8_t *start = state->payload + max_header_len - header_len;
+ size_t body_size = (size_t)payload - (size_t)start;
+ memmove(state->payload_mut,
+ state->payload + max_header_len - header_len,
+ body_size);
+ /* Reset payload pointer to end of list */
+ state->payload += body_size;
+ } else {
+ /* Reset payload pointer to end of list */
+ state->payload = payload;
+ }
+#else
+ if (!encode_header_byte(state, ZCBOR_MAJOR_TYPE_PRIM, ZCBOR_VALUE_IS_INDEFINITE_LENGTH)) {
+ ZCBOR_FAIL();
+ }
+#endif
+ return true;
+}
+
+
+bool zcbor_list_end_encode(zcbor_state_t *state, uint_fast32_t max_num)
+{
+ return list_map_end_encode(state, max_num, ZCBOR_MAJOR_TYPE_LIST);
+}
+
+
+bool zcbor_map_end_encode(zcbor_state_t *state, uint_fast32_t max_num)
+{
+ return list_map_end_encode(state, max_num, ZCBOR_MAJOR_TYPE_MAP);
+}
+
+
+bool zcbor_list_map_end_force_encode(zcbor_state_t *state)
+{
+#ifdef ZCBOR_CANONICAL
+ if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME,
+ ZCBOR_MAX_ELEM_COUNT)) {
+ ZCBOR_FAIL();
+ }
+#endif
+ return true;
+}
+
+
+bool zcbor_nil_put(zcbor_state_t *state, const void *unused)
+{
+ (void)unused;
+ return primitive_put(state, 22);
+}
+
+
+bool zcbor_undefined_put(zcbor_state_t *state, const void *unused)
+{
+ (void)unused;
+ return primitive_put(state, 23);
+}
+
+
+bool zcbor_bool_encode(zcbor_state_t *state, const bool *input)
+{
+ if (!primitive_put(state, (uint32_t)(*input + ZCBOR_BOOL_TO_PRIM))) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_bool_put(zcbor_state_t *state, bool input)
+{
+ if (!primitive_put(state, (uint32_t)(input + ZCBOR_BOOL_TO_PRIM))) {
+ ZCBOR_FAIL();
+ }
+ return true;
+}
+
+
+bool zcbor_float64_encode(zcbor_state_t *state, const double *input)
+{
+ if (!value_encode(state, ZCBOR_MAJOR_TYPE_PRIM, input,
+ sizeof(*input))) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_float64_put(zcbor_state_t *state, double input)
+{
+ return zcbor_float64_encode(state, &input);
+}
+
+
+bool zcbor_float32_encode(zcbor_state_t *state, const float *input)
+{
+ if (!value_encode(state, ZCBOR_MAJOR_TYPE_PRIM, input,
+ sizeof(*input))) {
+ ZCBOR_FAIL();
+ }
+
+ return true;
+}
+
+
+bool zcbor_float32_put(zcbor_state_t *state, float input)
+{
+ return zcbor_float32_encode(state, &input);
+}
+
+
+bool zcbor_tag_encode(zcbor_state_t *state, uint32_t tag)
+{
+ if (!value_encode(state, ZCBOR_MAJOR_TYPE_TAG, &tag, sizeof(tag))) {
+ ZCBOR_FAIL();
+ }
+ state->elem_count--;
+
+ return true;
+}
+
+
+bool zcbor_multi_encode_minmax(uint_fast32_t min_encode,
+ uint_fast32_t max_encode,
+ const uint_fast32_t *num_encode,
+ zcbor_encoder_t encoder,
+ zcbor_state_t *state,
+ const void *input,
+ uint_fast32_t result_len)
+{
+
+ if ((*num_encode >= min_encode) && (*num_encode <= max_encode)) {
+ return zcbor_multi_encode(*num_encode, encoder, state, input, result_len);
+ } else {
+ ZCBOR_ERR(ZCBOR_ERR_ITERATIONS);
+ }
+}
+
+bool zcbor_multi_encode(uint_fast32_t num_encode,
+ zcbor_encoder_t encoder,
+ zcbor_state_t *state,
+ const void *input,
+ uint_fast32_t result_len)
+{
+ ZCBOR_CHECK_ERROR();
+ for (uint_fast32_t i = 0; i < num_encode; i++) {
+ if (!encoder(state, (const uint8_t *)input + i*result_len)) {
+ ZCBOR_FAIL();
+ }
+ }
+ zcbor_print("Encoded %" PRIuFAST32 " elements.\n", num_encode);
+ return true;
+}
+
+
+bool zcbor_present_encode(const uint_fast32_t *present,
+ zcbor_encoder_t encoder,
+ zcbor_state_t *state,
+ const void *input)
+{
+ return zcbor_multi_encode(!!*present, encoder, state, input, 0);
+}
+
+
+bool zcbor_new_encode_state(zcbor_state_t *state_array, uint_fast32_t n_states,
+ uint8_t *payload, size_t payload_len, uint_fast32_t elem_count)
+{
+ return zcbor_new_state(state_array, n_states, payload, payload_len, elem_count);
+}
diff --git a/boot/boot_serial/src/zcbor_encode.h b/boot/boot_serial/src/zcbor_encode.h
new file mode 100644
index 0000000..e129021
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_encode.h
@@ -0,0 +1,280 @@
+/*
+ * This file has been copied from the zcbor library.
+ * Commit zcbor 0.4.0
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZCBOR_ENCODE_H__
+#define ZCBOR_ENCODE_H__
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "zcbor_common.h"
+
+/** The zcbor_encode library provides functions for encoding CBOR data elements.
+ *
+ * See The README for an introduction to CBOR, including the meaning of pint,
+ * nint, bstr etc.
+ */
+
+
+/** The following param and retval docs apply to all single value encoding functions
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] input The value to encode.
+ *
+ * @retval true Everything is ok.
+ * @retval false If the payload is exhausted. Or an unexpected error happened.
+ */
+
+/** Encode a pint/nint. */
+bool zcbor_int32_put(zcbor_state_t *state, int32_t input);
+bool zcbor_int64_put(zcbor_state_t *state, int64_t input);
+bool zcbor_uint32_put(zcbor_state_t *state, uint32_t result);
+bool zcbor_uint64_put(zcbor_state_t *state, uint64_t input);
+
+/** Encode a pint/nint from a pointer.
+ *
+ * Can be used for bulk encoding with @ref zcbor_multi_encode.
+ */
+bool zcbor_int32_encode(zcbor_state_t *state, const int32_t *input);
+bool zcbor_int64_encode(zcbor_state_t *state, const int64_t *input);
+bool zcbor_uint32_encode(zcbor_state_t *state, const uint32_t *result);
+bool zcbor_uint64_encode(zcbor_state_t *state, const uint64_t *input);
+
+/** Encode a bstr. */
+bool zcbor_bstr_encode(zcbor_state_t *state, const struct zcbor_string *input);
+/** Encode a tstr. */
+bool zcbor_tstr_encode(zcbor_state_t *state, const struct zcbor_string *input);
+
+/** Encode a pointer to a string as a bstr/tstr.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to encode. A pointer to the string
+ * @param[in] len The length of the string pointed to by @p string.
+ */
+static inline bool zcbor_bstr_encode_ptr(zcbor_state_t *state, uint8_t *ptr, size_t len)
+{
+ return zcbor_bstr_encode(state, &(struct zcbor_string){.value = ptr, .len = len});
+}
+static inline bool zcbor_tstr_encode_ptr(zcbor_state_t *state, uint8_t *ptr, size_t len)
+{
+ return zcbor_tstr_encode(state, &(struct zcbor_string){.value = ptr, .len = len});
+}
+
+/** Encode a string literal as a bstr/tstr.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to encode. A string literal, e.g. "Foo", so
+ * that sizeof(string) - 1 is the length of the string.
+ */
+#define zcbor_bstr_put_lit(state, string) \
+ zcbor_bstr_encode_ptr(state, string, sizeof(string) - 1)
+#define zcbor_tstr_put_lit(state, string) \
+ zcbor_tstr_encode_ptr(state, string, sizeof(string) - 1)
+
+/** Encode null-terminated string as a bstr/tstr.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to encode. Must be a null-terminated string,
+ * so that strlen can be used.
+ */
+#define zcbor_bstr_put_term(state, string) \
+ zcbor_bstr_encode_ptr(state, string, strlen(string))
+#define zcbor_tstr_put_term(state, string) \
+ zcbor_tstr_encode_ptr(state, string, strlen(string))
+
+/** Encode a char array literal as a bstr/tstr.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] string The value to encode. An array literal, e.g. {'F', 'o', 'o'},
+ * so that sizeof(string) is the length of the string.
+ */
+#define zcbor_bstr_put_arr(state, string) \
+ zcbor_bstr_encode_ptr(state, string, sizeof(string))
+#define zcbor_tstr_put_arr(state, string) \
+ zcbor_tstr_encode_ptr(state, string, sizeof(string))
+
+/** Encode a tag. Must be called before encoding the value being tagged. */
+bool zcbor_tag_encode(zcbor_state_t *state, uint32_t input);
+
+/** Encode a boolean primitive value. */
+bool zcbor_bool_put(zcbor_state_t *state, bool input);
+bool zcbor_bool_encode(zcbor_state_t *state, const bool *input);
+
+/** Encode a float */
+bool zcbor_float32_put(zcbor_state_t *state, float input);
+bool zcbor_float32_encode(zcbor_state_t *state, const float *input);
+bool zcbor_float64_put(zcbor_state_t *state, double input);
+bool zcbor_float64_encode(zcbor_state_t *state, const double *input);
+
+/** Encode a "nil"/"undefined" primitive value. @p unused should be NULL.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] unused Unused parameter to maintain signature parity with
+ * @ref zcbor_encoder_t.
+ */
+bool zcbor_nil_put(zcbor_state_t *state, const void *unused);
+bool zcbor_undefined_put(zcbor_state_t *state, const void *unused);
+
+/** Encode a bstr header.
+ *
+ * The rest of the string can be encoded as CBOR.
+ * A state backup is created to keep track of the element count.
+ * Call @ref zcbor_bstr_end_encode when done encoding the contents of the bstr.
+ *
+ * @param[inout] state The current state of the encoding.
+ *
+ * @retval true Header encoded correctly
+ * @retval false Header encoded incorrectly, or backup failed.
+ */
+bool zcbor_bstr_start_encode(zcbor_state_t *state);
+
+/** Finalize encoding a CBOR-encoded bstr.
+ *
+ * Restore element count from backup.
+ */
+bool zcbor_bstr_end_encode(zcbor_state_t *state, struct zcbor_string *result);
+
+/** Encode a list/map header.
+ *
+ * The contents of the list/map can be encoded via subsequent function calls.
+ * If ZCBOR_CANONICAL is defined, a state backup is created to keep track of the
+ * element count.
+ * When all members have been encoded, call @ref zcbor_list_end_encode /
+ * @ref zcbor_map_end_encode to close the list/map.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] max_num The maximum number of members in the list/map.
+ * This serves as a size hint for the header. Must be
+ * equal to the max_num provided to the corresponding
+ * @ref zcbor_list_end_encode / @ref zcbor_map_end_encode
+ * call.
+ * Only used when ZCBOR_CANONICAL is defined.
+ */
+bool zcbor_list_start_encode(zcbor_state_t *state, uint_fast32_t max_num);
+bool zcbor_map_start_encode(zcbor_state_t *state, uint_fast32_t max_num);
+
+/** Encode the end of a list/map. Do some checks and deallocate backup.
+ *
+ * - Default: Adds a list terminator (0xFF) to mark the
+ * end of the list/map.
+ * - If ZCBOR_CANONICAL is defined: Instead encodes the number of members in
+ * the list/map header. If the header ends up a different size than expected,
+ * the list/map contents are moved using memmove().
+ *
+ * Use @ref zcbor_list_map_end_force_encode to forcibly consume the backup if
+ * something has gone wrong.
+ *
+ * @param[inout] state The current state of the encoding.
+ * @param[in] max_num The maximum number of members in the list/map. Must be
+ * equal to the max_num provided to the corresponding
+ * @ref zcbor_list_start_encode call.
+ * Only used when ZCBOR_CANONICAL is defined.
+ */
+bool zcbor_list_end_encode(zcbor_state_t *state, uint_fast32_t max_num);
+bool zcbor_map_end_encode(zcbor_state_t *state, uint_fast32_t max_num);
+bool zcbor_list_map_end_force_encode(zcbor_state_t *state);
+
+/** Encode 0 or more elements with the same type and constraints.
+ *
+ * The encoded values are taken from the @p input array.
+ *
+ * The following is an example of encoding a list containing 3 INTS followed by
+ * 0 to 2 bstrs:
+ *
+ * @code{c}
+ * uint32_t ints[3] = <initialize>;
+ * struct zcbor_string bstrs[2] = <initialize>;
+ * bool res;
+ *
+ * res = zcbor_list_start_encode(state, 5);
+ * res = res && zcbor_multi_encode(3, zcbor_uint32_encode, state,
+ * ints, sizeof(uint32_t));
+ * res = res && zcbor_multi_encode(2, zcbor_bstr_encode, state,
+ * bstrs, sizeof(struct zcbor_string));
+ * res = res && zcbor_list_end_encode(state, 5);
+ * // check res
+ * @endcode
+ *
+ * The @ref zcbor_encoder_t type is designed to be compatible with all single-
+ * value encoder functions in this library, e.g. @ref zcbor_uint32_encode,
+ * @ref zcbor_tstr_put, @ref zcbor_nil_put, etc. For _put() functions,
+ * @p input will be used as a value instead of an array/pointer, so
+ * @p input_len will determine how much the value changes for each call.
+ * To encode the same value multiple times, use a @p input_len of 0.
+ * This function can also be used with custom decoder functions, such as those
+ * generated by the zcbor.py script, which for example encodes larger chunks of
+ * the data at once.
+ *
+ * @param[in] num_encode The actual number of elements.
+ * @param[in] encoder The encoder function to call under the hood. This
+ * function will be called with the provided arguments
+ * repeatedly until the function fails (returns false)
+ * or until it has been called @p max_encode times.
+ * The input pointer is moved @p input_len bytes for
+ * each call to @p encoder, i.e. @p input refers to an
+ * array of input variables.
+ * @param[in] input Source of the encoded values. Must be an array of
+ * at least @p max_encode elements.
+ * @param[in] input_len The length of the input variables. Must be the
+ * length of the individual elements in input.
+ *
+ * @retval true If at least @p min_encode variables were correctly encoded.
+ * @retval false If @p encoder failed before having encoded @p min_encode
+ * values.
+ */
+bool zcbor_multi_encode(uint_fast32_t num_encode,
+ zcbor_encoder_t encoder,
+ zcbor_state_t *state,
+ const void *input,
+ uint_fast32_t result_len);
+
+/** Works like @ref zcbor_multi_encode
+ *
+ * But first checks that @p num_encode is between @p min_encode and @p max_encode.
+ */
+bool zcbor_multi_encode_minmax(uint_fast32_t min_encode, uint_fast32_t max_encode, const uint_fast32_t *num_encode,
+ zcbor_encoder_t encoder, zcbor_state_t *state, const void *input,
+ uint_fast32_t input_len);
+
+/** Runs @p encoder on @p state and @p input if @p present is true.
+ *
+ * Calls @ref zcbor_multi_encode under the hood.
+ */
+bool zcbor_present_encode(const uint_fast32_t *present,
+ zcbor_encoder_t encoder,
+ zcbor_state_t *state,
+ const void *input);
+
+/** See @ref zcbor_new_state() */
+bool zcbor_new_encode_state(zcbor_state_t *state_array, uint_fast32_t n_states,
+ uint8_t *payload, size_t payload_len, uint_fast32_t elem_count);
+
+/** Convenience macro for declaring and initializing a state with backups.
+ *
+ * This gives you a state variable named @p name. The variable functions like
+ * a pointer.
+ *
+ * The return value from @ref zcbor_new_encode_state can be safely ignored
+ * because the only error condition is n_states < 2, and this macro adds 2 to
+ * num_backups to get n_states, so it can never be < 2.
+ *
+ * @param[in] name The name of the new state variable.
+ * @param[in] num_backups The number of backup slots to keep in the state.
+ * @param[in] payload The payload to work on.
+ * @param[in] payload_size The size (in bytes) of @p payload.
+ * @param[in] elem_count The starting elem_count (typically 1).
+ */
+#define ZCBOR_STATE_E(name, num_backups, payload, payload_size, elem_count) \
+zcbor_state_t name[((num_backups) + 2)]; \
+do { \
+ (void)zcbor_new_encode_state(name, ARRAY_SIZE(name), payload, payload_size, elem_count); \
+} while(0)
+
+#endif /* ZCBOR_ENCODE_H__ */
diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt
index 026ce2b..db9067a 100644
--- a/boot/zephyr/CMakeLists.txt
+++ b/boot/zephyr/CMakeLists.txt
@@ -252,9 +252,9 @@
zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c)
zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c)
zephyr_sources(${BOOT_DIR}/boot_serial/src/serial_recovery_cbor.c)
- zephyr_sources(${BOOT_DIR}/boot_serial/src/cbor_decode.c)
- zephyr_sources(${BOOT_DIR}/boot_serial/src/cbor_encode.c)
- zephyr_sources(${BOOT_DIR}/boot_serial/src/cbor_common.c)
+ zephyr_sources(${BOOT_DIR}/boot_serial/src/zcbor_decode.c)
+ zephyr_sources(${BOOT_DIR}/boot_serial/src/zcbor_encode.c)
+ zephyr_sources(${BOOT_DIR}/boot_serial/src/zcbor_common.c)
zephyr_include_directories(${BOOT_DIR}/bootutil/include)
zephyr_include_directories(${BOOT_DIR}/boot_serial/include)
diff --git a/ext/cddl-gen b/ext/cddl-gen
deleted file mode 160000
index 9f77837..0000000
--- a/ext/cddl-gen
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 9f77837f9950da1633d22abf6181a830521a6688