boot_serial: Update cddl-gen

Update and rename submodule.
Regenerate code and copy updated files.
Update regeneration script.

Signed-off-by: Øyvind Rønningstad <oyvind.ronningstad@nordicsemi.no>
diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c
index 5501126..5fa794a 100644
--- a/boot/boot_serial/src/boot_serial.c
+++ b/boot/boot_serial/src/boot_serial.c
@@ -27,7 +27,7 @@
 #include "bootutil/bootutil_log.h"
 
 #ifdef __ZEPHYR__
-#include <sys/reboot.h>
+#include <power/reboot.h>
 #include <sys/byteorder.h>
 #include <sys/__assert.h>
 #include <drivers/flash.h>
@@ -254,13 +254,16 @@
      * }
      */
 
-    Upload_t upload;
-    if (!cbor_decode_Upload((const uint8_t *)buf, len, &upload)) {
+    struct Upload upload;
+    size_t decoded_len;
+    bool result = cbor_decode_Upload((const uint8_t *)buf, len, &upload, &decoded_len);
+
+    if (!result || (len != decoded_len)) {
         goto out_invalid_data;
     }
 
     for (int i = 0; i < upload._Upload_members_count; i++) {
-        _Member_t *member = &upload._Upload_members[i];
+        struct Member_ *member = &upload._Upload_members[i];
         switch(member->_Member_choice) {
             case _Member_image:
                 img_num = member->_Member_image;
diff --git a/boot/boot_serial/src/cbor_common.c b/boot/boot_serial/src/cbor_common.c
new file mode 100644
index 0000000..79469d5
--- /dev/null
+++ b/boot/boot_serial/src/cbor_common.c
@@ -0,0 +1,125 @@
+/*
+ * This file has been copied from the cddl-gen submodule.
+ * Commit 8f9358a0b4b0e9b0cd579f0988056ef0b60760e4
+ */
+
+/*
+ * 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
new file mode 100644
index 0000000..ce73dd6
--- /dev/null
+++ b/boot/boot_serial/src/cbor_common.h
@@ -0,0 +1,145 @@
+/*
+ * This file has been copied from the cddl-gen submodule.
+ * Commit 8f9358a0b4b0e9b0cd579f0988056ef0b60760e4
+ */
+
+/*
+ * 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
index 9d27bbb..74c4cd7 100644
--- a/boot/boot_serial/src/cbor_decode.c
+++ b/boot/boot_serial/src/cbor_decode.c
@@ -1,6 +1,6 @@
 /*
- * This file has been copied from the cddl_gen submodule.
- * Commit 9d911cf0c7c9f13b5a9fdd5ed6c1012df21e5576
+ * This file has been copied from the cddl-gen submodule.
+ * Commit 8f9358a0b4b0e9b0cd579f0988056ef0b60760e4
  */
 
 /*
@@ -14,22 +14,8 @@
 #include <stddef.h>
 #include <string.h>
 #include "cbor_decode.h"
+#include "cbor_common.h"
 
-/** 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;
 
 /** Return value length from additional value.
  */
@@ -52,122 +38,124 @@
 /** Extract the additional info, i.e. the last 5 bits of the header byte. */
 #define ADDITIONAL(header_byte) ((header_byte) & 0x1F)
 
-/** Shorthand macro to check if a result is within min/max constraints.
- */
-#define PTR_VALUE_IN_RANGE(type, p_res, p_min, p_max) \
-		(((p_min == NULL) || (*(type *)p_res >= *(type *)p_min)) \
-		&& ((p_max == NULL) || (*(type *)p_res <= *(type *)p_max)))
-
-#define FAIL() \
-do {\
-	cbor_decode_trace(); \
-	return false; \
-} while(0)
 
 #define FAIL_AND_DECR_IF(expr) \
 do {\
 	if (expr) { \
-		(p_state->p_payload)--; \
+		(state->payload)--; \
 		FAIL(); \
 	} \
 } while(0)
 
-#define VALUE_IN_HEADER 23 /**! For values below this, the value is encoded
-                                directly in the header. */
+#define FAIL_IF(expr) \
+do {\
+	if (expr) { \
+		FAIL(); \
+	} \
+} while(0)
 
-#define BOOL_TO_PRIM 20 ///! In CBOR, false/true have the values 20/21
+
+#define FAIL_RESTORE() \
+	state->payload = state->payload_bak; \
+	state->elem_count++; \
+	FAIL()
 
 /** Get a single value.
  *
- * @details @p pp_payload must point to the header byte. This function will
+ * @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 pp_payload doesn't overrun past @p p_payload_end.
- *           - That @p p_elem_count has not been exhausted.
+ *           - That @p payload doesn't overrun past @p payload_end.
+ *           - That @p elem_count has not been exhausted.
  *
- *          @p pp_payload and @p p_elem_count are updated if the function
+ *          @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_decode_state_t * p_state,
-		void * const p_result, size_t result_len)
+static bool value_extract(cbor_state_t *state,
+		void *const result, uint32_t result_len)
 {
-	cbor_decode_trace();
-	cbor_decode_assert(result_len != 0, "0-length result not supported.\n");
+	cbor_trace();
+	cbor_assert(result_len != 0, "0-length result not supported.\n");
+	cbor_assert(result != NULL, NULL);
 
-	FAIL_AND_DECR_IF(p_state->elem_count == 0);
-	FAIL_AND_DECR_IF(p_state->p_payload >= p_state->p_payload_end);
+	FAIL_IF((state->elem_count == 0) \
+		|| (state->payload >= state->payload_end));
 
-	uint8_t *p_u8_result  = (uint8_t *)p_result;
-	uint8_t additional = ADDITIONAL(*p_state->p_payload);
+	uint8_t *u8_result  = (uint8_t *)result;
+	uint8_t additional = ADDITIONAL(*state->payload);
 
-	(p_state->p_payload)++;
+	state->payload_bak = state->payload;
+	(state->payload)++;
 
-	memset(p_result, 0, result_len);
+	memset(result, 0, result_len);
 	if (additional <= VALUE_IN_HEADER) {
 #ifdef CONFIG_BIG_ENDIAN
-		p_u8_result[result_len - 1] = additional;
+		u8_result[result_len - 1] = additional;
 #else
-		p_u8_result[0] = additional;
+		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((p_state->p_payload + len)
-				> p_state->p_payload_end);
+		FAIL_AND_DECR_IF((state->payload + len)
+				> state->payload_end);
 
 #ifdef CONFIG_BIG_ENDIAN
-		memcpy(&p_u8_result[result_len - len], p_state->p_payload, len);
+		memcpy(&u8_result[result_len - len], state->payload, len);
 #else
 		for (uint32_t i = 0; i < len; i++) {
-			p_u8_result[i] = (p_state->p_payload)[len - i - 1];
+			u8_result[i] = (state->payload)[len - i - 1];
 		}
 #endif /* CONFIG_BIG_ENDIAN */
 
-		(p_state->p_payload) += len;
+		(state->payload) += len;
 	}
 
-	(p_state->elem_count)--;
+	(state->elem_count)--;
 	return true;
 }
 
 
-static bool int32_decode(cbor_decode_state_t * p_state,
-		int32_t *p_result, void *p_min_value, void *p_max_value)
+static bool int32_decode(cbor_state_t *state, int32_t *result)
 {
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
+	uint8_t major_type = MAJOR_TYPE(*state->payload);
+	uint32_t uint_result;
+	int32_t int_result;
 
-	if (!value_extract(p_state, p_result, 4)) {
+	if (!value_extract(state, &uint_result, 4)) {
 		FAIL();
 	}
-	if (*p_result < 0) {
+
+	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();
+		FAIL_RESTORE();
 	}
 
 	if (major_type == CBOR_MAJOR_TYPE_NINT) {
-		// Convert from CBOR's representation.
-		*p_result = 1 - *p_result;
+		/* Convert from CBOR's representation. */
+		int_result = -1 - uint_result;
+	} else {
+		int_result = uint_result;
 	}
-	if (!PTR_VALUE_IN_RANGE(int32_t, p_result, p_min_value, p_max_value)) {
-		FAIL();
-	}
-	cbor_decode_print("val: %d\r\n", *p_result);
+
+	cbor_print("val: %d\r\n", int_result);
+	*result = int_result;
 	return true;
 }
 
 
-bool intx32_decode(cbor_decode_state_t * p_state,
-		int32_t *p_result, void *p_min_value, void *p_max_value)
+bool intx32_decode(cbor_state_t *state, int32_t *result)
 {
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
+	uint8_t major_type = MAJOR_TYPE(*state->payload);
 
 	if (major_type != CBOR_MAJOR_TYPE_PINT
 		&& major_type != CBOR_MAJOR_TYPE_NINT) {
@@ -175,203 +163,376 @@
 		FAIL();
 	}
 
-	if (!int32_decode(p_state,
-				p_result, p_min_value,
-				p_max_value)){
+	if (!int32_decode(state, result)) {
 		FAIL();
 	}
 	return true;
 }
 
-
-static bool uint32_decode(cbor_decode_state_t * p_state,
-		void *p_result, void *p_min_value, void *p_max_value)
+bool intx32_expect(cbor_state_t *state, int32_t result)
 {
-	if (!value_extract(p_state, p_result, 4)) {
+	int32_t value;
+
+	if (!intx32_decode(state, &value)) {
 		FAIL();
 	}
 
-	if (!PTR_VALUE_IN_RANGE(uint32_t, p_result, p_min_value, p_max_value)) {
-		FAIL();
+	if (value != result) {
+		cbor_print("%d != %d\r\n", value, result);
+		FAIL_RESTORE();
 	}
-	cbor_decode_print("val: %u\r\n", *(uint32_t *)p_result);
 	return true;
 }
 
 
-bool uintx32_decode(cbor_decode_state_t * p_state,
-		uint32_t *p_result, void *p_min_value, void *p_max_value)
+static bool uint32_decode(cbor_state_t *state, uint32_t *result)
 {
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
+	if (!value_extract(state, result, 4)) {
+		FAIL();
+	}
+
+	return true;
+}
+
+
+bool uintx32_decode(cbor_state_t *state, uint32_t *result)
+{
+	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(p_state, p_result, p_min_value, p_max_value)){
+	if (!uint32_decode(state, result)) {
 		FAIL();
 	}
 	return true;
 }
 
-
-static bool size_decode(cbor_decode_state_t * p_state,
-		size_t *p_result, size_t *p_min_value, size_t *p_max_value)
+bool uintx32_expect(cbor_state_t *state, uint32_t result)
 {
-	_Static_assert((sizeof(size_t) == sizeof(uint32_t)),
-			"This code needs size_t to be 4 bytes long.");
-	return uint32_decode(p_state,
-			p_result, p_min_value, p_max_value);
+	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);
 }
 
 
-bool strx_start_decode(cbor_decode_state_t * p_state,
-		cbor_string_type_t *p_result, void *p_min_len, void *p_max_len)
+static bool strx_start_decode(cbor_state_t *state,
+		cbor_string_type_t *result, cbor_major_type_t exp_major_type)
 {
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
-	cbor_string_type_t *p_str_result = (cbor_string_type_t *)p_result;
+	uint8_t major_type = MAJOR_TYPE(*state->payload);
 
-	if (major_type != CBOR_MAJOR_TYPE_BSTR
-		&& major_type != CBOR_MAJOR_TYPE_TSTR) {
-		/* Value to be read doesn't have the right type. */
+	if (major_type != exp_major_type) {
 		FAIL();
 	}
-	if (!size_decode(p_state,
-			&p_str_result->len, (size_t *)p_min_len,
-			(size_t *)p_max_len)) {
+
+	if (!uint32_decode(state, &result->len)) {
 		FAIL();
 	}
-	p_str_result->value = p_state->p_payload;
+
+	if ((state->payload + result->len) > state->payload_end) {
+		cbor_print("error: 0x%x > 0x%x\r\n",
+		(uint32_t)(state->payload + result->len),
+		(uint32_t)state->payload_end);
+		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();
+	}
+
+	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_decode_state_t * p_state,
-		cbor_string_type_t *p_result, void *p_min_len, void *p_max_len)
+bool strx_decode(cbor_state_t *state, cbor_string_type_t *result,
+		cbor_major_type_t exp_major_type)
 {
-	if (!strx_start_decode(p_state, p_result,
-				p_min_len, p_max_len)) {
-		return false;
+	if (!strx_start_decode(state, result, exp_major_type)) {
+		FAIL();
 	}
-	(p_state->p_payload) += p_result->len;
+
+	(state->payload) += result->len;
 	return true;
 }
 
 
-bool list_start_decode(cbor_decode_state_t * p_state,
-		size_t *p_result, size_t min_num, size_t max_num)
+bool strx_expect(cbor_state_t *state, cbor_string_type_t *result,
+		cbor_major_type_t exp_major_type)
 {
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
+	cbor_string_type_t tmp_result;
 
-	*p_result = p_state->elem_count;
-
-	if (major_type != CBOR_MAJOR_TYPE_LIST
-		&& major_type != CBOR_MAJOR_TYPE_MAP) {
+	if (!strx_decode(state, &tmp_result, exp_major_type)) {
 		FAIL();
 	}
-	if (!uint32_decode(p_state,
-			p_result, &min_num, &max_num)) {
-		FAIL();
+	if ((tmp_result.len != result->len)
+			|| memcmp(result->value, tmp_result.value, tmp_result.len)) {
+		FAIL_RESTORE();
 	}
-	size_t tmp = *p_result;
-	*p_result = p_state->elem_count;
-	p_state->elem_count = major_type == CBOR_MAJOR_TYPE_MAP ? tmp * 2 : tmp;
 	return true;
 }
 
 
-bool primx_decode(cbor_decode_state_t * p_state,
-		uint8_t *p_result, void *p_min_result, void *p_max_result)
+bool bstrx_decode(cbor_state_t *state, cbor_string_type_t *result)
 {
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
-	uint32_t val;
+	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)
+{
+	uint32_t new_elem_count;
+	uint8_t major_type = MAJOR_TYPE(*state->payload);
+
+	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)
+{
+	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(p_state,
-			&val, p_min_result, p_max_result)) {
+	if (!uint32_decode(state, result)) {
 		FAIL();
 	}
-	if (p_result != NULL) {
-		*p_result = val;
+	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 boolx_decode(cbor_decode_state_t * p_state,
-		bool *p_result, void *p_min_result, void *p_max_result)
+bool nilx_expect(cbor_state_t *state, void *result)
 {
-	uint8_t min_result = *(uint8_t *)p_min_result + BOOL_TO_PRIM;
-	uint8_t max_result = *(uint8_t *)p_max_result + BOOL_TO_PRIM;
-
-	if (!primx_decode(p_state,
-			(uint8_t *)p_result, &min_result, &max_result)) {
+	if (!primx_expect(state, 22)) {
 		FAIL();
 	}
-	(*p_result) -= BOOL_TO_PRIM;
 	return true;
 }
 
 
-bool double_decode(cbor_decode_state_t * p_state,
-		double *p_result, void *p_min_result, void *p_max_result)
+bool boolx_decode(cbor_state_t *state, bool *result)
 {
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
+	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)
+{
+	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(p_state, p_result,
-			sizeof(*p_result))) {
-		FAIL();
-	}
-
-	if (!PTR_VALUE_IN_RANGE(double, p_result, p_min_result, p_max_result)) {
+	if (!value_extract(state, result,
+			sizeof(*result))) {
 		FAIL();
 	}
 	return true;
 }
 
 
-bool any_decode(cbor_decode_state_t * p_state,
-		void *p_result, void *p_min_result, void *p_max_result)
+bool double_expect(cbor_state_t *state, double *result)
 {
-	cbor_decode_assert(p_result == NULL,
+	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");
 
-	uint8_t major_type = MAJOR_TYPE(*p_state->p_payload);
+	uint8_t major_type = MAJOR_TYPE(*state->payload);
 	uint32_t value;
-	size_t num_decode;
-	void *p_null_result = NULL;
-	size_t temp_elem_count;
+	uint32_t num_decode;
+	void *null_result = NULL;
+	uint32_t temp_elem_count;
+	uint8_t const *payload_bak;
 
-	if (!value_extract(p_state, &value, sizeof(value))) {
-		/* Can happen because of p_elem_count (or p_payload_end) */
+	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:
-			(p_state->p_payload) += value;
+			(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 = p_state->elem_count;
-			p_state->elem_count = value;
-			if (!multi_decode(value, value, &num_decode, any_decode,
-					p_state,
-					&p_null_result,	NULL, NULL, 0)) {
-				p_state->elem_count = temp_elem_count;
+			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();
 			}
-			p_state->elem_count = temp_elem_count;
+			state->elem_count = temp_elem_count;
 			break;
 		default:
 			/* Do nothing */
@@ -382,36 +543,76 @@
 }
 
 
-bool multi_decode(size_t min_decode,
-		size_t max_decode,
-		size_t *p_num_decode,
-		decoder_t decoder,
-		cbor_decode_state_t * p_state,
-		void *p_result,
-		void *p_min_result,
-		void *p_max_result,
-		size_t result_len)
+bool tag_decode(cbor_state_t *state, uint32_t *result)
 {
-	for (size_t i = 0; i < max_decode; i++) {
-		uint8_t const *p_payload_bak = p_state->p_payload;
-		size_t elem_count_bak = p_state->elem_count;
+	uint8_t major_type = MAJOR_TYPE(*state->payload);
 
-		if (!decoder(p_state,
-				(uint8_t *)p_result + i*result_len,
-				p_min_result,
-				p_max_result)) {
-			*p_num_decode = i;
-			p_state->p_payload = p_payload_bak;
-			p_state->elem_count = elem_count_bak;
+	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_decode_print("Found %zu elements.\n", i);
+				cbor_print("Found %zu elements.\n", i);
 			}
 			return true;
 		}
 	}
-	cbor_decode_print("Found %zu elements.\n", max_decode);
-	*p_num_decode = max_decode;
+	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
index cd466cd..b0cfaa1 100644
--- a/boot/boot_serial/src/cbor_decode.h
+++ b/boot/boot_serial/src/cbor_decode.h
@@ -1,6 +1,6 @@
 /*
- * This file has been copied from the cddl_gen submodule.
- * Commit 9d911cf0c7c9f13b5a9fdd5ed6c1012df21e5576
+ * This file has been copied from the cddl-gen submodule.
+ * Commit 8f9358a0b4b0e9b0cd579f0988056ef0b60760e4
  */
 
 /*
@@ -9,11 +9,12 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#ifndef CDDL_CBOR_H__
-#define CDDL_CBOR_H__
+#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.
  *
@@ -21,23 +22,19 @@
  * $CDDL_GEN_BASE/scripts/cddl_gen.py
  *
  * Some details to notice about this library:
- *  - Integers are all 32 bits (uint32_t and size_t). This means that CBOR's
- *    64 bit values are not supported. This applies to integer types, as well as
- *    lengths for other types.
+ *  - 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. All functions
- *    are designed to reset pp_payload and p_elem_count to their original values
- *    if they return false.
+ *    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 decoder_t type which is compatible
+ *    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.
- *  - This library has no function for semantic tags.
- *  - This library doesn't distinguish lists from maps.
  *
  *
  * CBOR's format is described well on Wikipedia
@@ -54,7 +51,11 @@
  *
  * The available major types can be seen in @ref cbor_major_type_t.
  *
- * PINT, NINT, TAG, and PRIM elements have no payload, only Value.
+ * 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.
@@ -65,7 +66,7 @@
  *       21: "true"
  *       22: "null"
  *       23: "undefined"
- *       >256: Interpret as IEEE 754 float with given precision
+ *       >=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
@@ -74,148 +75,105 @@
  * For LIST and MAP, sub elements are regular CBOR elements with their own
  * Header, Value and Payload. LISTs and MAPs can be recursively encoded.
  *
- * 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.
- *
  * The additional info means slightly different things for different major
  * types.
  */
 
-
-/** Convenience type that allows pointing to strings directly inside the payload
- *  without the need to copy out.
- */
-typedef struct
-{
-	const uint8_t *value;
-	size_t len;
-} cbor_string_type_t;
-
-#ifdef CDDL_CBOR_VERBOSE
-#include <sys/printk.h>
-#define cbor_decode_trace() (printk("p_state->p_payload: 0x%x, "\
-	"*p_state->p_payload: 0x%x, p_state->elem_count: 0x%zx, %s:%d\n",\
-	(uint32_t)p_state->p_payload, *p_state->p_payload, p_state->elem_count,\
-	__FILE__, __LINE__))
-#define cbor_decode_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_decode_print(...) printk(__VA_ARGS__)
-#else
-#define cbor_decode_trace()
-#define cbor_decode_assert(...)
-#define cbor_decode_print(...)
-#endif
-
-typedef struct {
-	uint8_t const *p_payload;
-	uint8_t const *p_payload_end;
-	size_t elem_count;
-} cbor_decode_state_t;
-
-/** 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(decoder_t)(cbor_decode_state_t *, void *, void *, void *);
-
 /** Decode a PINT/NINT into a int32_t.
  *
- * @param[inout] pp_payload     The current place in the payload. Will be
- *                              updated if the element is correctly decoded.
- * @param[in]    p_payload_end  The end of the payload. This will be checked
- *                              against pp_payload before decoding.
- * @param[inout] p_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 decoding
- *                              decremented if the element is correctly decoded.
- * @param[out]   p_result       Where to place the decoded value.
- * @param[in]    p_min_value    The minimum acceptable value. This is checked
- *                              after decoding, and if the decoded value is
- *                              outside the range, the decoding will fail.
- *                              A NULL value here means there is no restriction.
- * @param[in]    p_max_value    The maximum acceptable value. This is checked
- *                              after decoding, and if the decoded value is
- *                              outside the range, the decoding will fail.
- *                              A NULL value here means there is no restriction.
+ * @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, the value was not within the
- *                acceptable range, or the value was larger than can fit in the
- *                result variable.
+ *                element count was exhausted, or the value was larger than can
+ *                fit in the result variable.
  */
-bool intx32_decode(cbor_decode_state_t * p_state, int32_t *p_result, void *p_min_value, void *p_max_value);
+bool intx32_decode(cbor_state_t *state, int32_t *result);
 
-/** Decode a PINT into a uint32_t.
+/** Expect a PINT/NINT with a certain value. Uses intx32_decode internally.
  *
- * @details See @ref intx32_decode for information about parameters and return
- *          values.
+ * @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 uintx32_decode(cbor_decode_state_t * p_state, uint32_t *p_result, void *p_min_value, void *p_max_value);
+bool intx32_expect(cbor_state_t *state, int32_t result);
 
-/** Decode a BSTR or TSTR, but leave pp_payload pointing at the payload.
- *
- * @details See @ref intx32_decode for information about parameters and return
- *          values. For strings, the value refers to the length of the string.
- */
-bool strx_start_decode(cbor_decode_state_t * p_state, cbor_string_type_t *p_result, void *p_min_len, void *p_max_len);
+/** 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 a BSTR or TSTR, and move pp_payload to after the payload.
+/** Decode and consume a BSTR header.
  *
- * @details See @ref intx32_decode for information about parameters and return
- *          values. For strings, the value refers to the length of the string.
+ * 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 strx_decode(cbor_decode_state_t * p_state, cbor_string_type_t *p_result, void *p_min_len, void *p_max_len);
+bool bstrx_cbor_start_decode(cbor_state_t *state, cbor_string_type_t *result);
 
-/** Decode a LIST or MAP, but leave pp_payload pointing at the payload.
+/** Finalize decoding a CBOR-encoded bstr.
  *
- * @details See @ref intx32_decode for information about parameters and return
- *          values. For lists and maps, the value refers to the number of
- *          elements.
+ * Restore element count from backup.
  */
-bool list_start_decode(cbor_decode_state_t * p_state, size_t *p_result, size_t min_num, size_t max_num);
+bool bstrx_cbor_end_decode(cbor_state_t *state);
 
-/** Decode a primitive value.
- *
- * @details See @ref intx32_decode for information about parameters and return
- *          values.
- */
-bool primx_decode(cbor_decode_state_t * p_state, uint8_t *p_result, void *p_min_result, void *p_max_result);
+/** 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 a boolean primitive value.
- *
- * @details See @ref intx32_decode for information about parameters and return
- *          values. The result is translated internally from the primitive
- *          values for true/false (20/21) to 0/1.
- */
-bool boolx_decode(cbor_decode_state_t * p_state, bool *p_result, void *p_min_result, void *p_max_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 a float
+/** Decode and consume a LIST header.
  *
- * @warning This function has not been tested, and likely doesn't work.
+ * The contents of the list can be decoded via subsequent function calls.
+ * A state backup is created to keep track of the element count.
  *
- * @details See @ref intx32_decode for information about parameters and return
- *          values.
+ * @retval true   Header decoded correctly
+ * @retval false  Header decoded incorrectly, or backup failed.
  */
-bool float_decode(cbor_decode_state_t * p_state, double *p_result, void *p_min_result, void *p_max_result);
+bool list_start_decode(cbor_state_t *state);
 
-/** Skip a single element, regardless of type and value.
+/** Decode and consume a MAP header. */
+bool map_start_decode(cbor_state_t *state);
+
+/** Finalize decoding a LIST
  *
- * @details See @ref intx32_decode for information about parameters and return
- *          values. @p p_result, @p p_min_result, and @p p_max_result must be
- *          NULL.
+ * 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 any_decode(cbor_decode_state_t * p_state, void *p_result, void *p_min_result, void *p_max_result);
+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.
  *
@@ -224,46 +182,52 @@
  *          with length 8, that could be done with:
  *
  *          @code{c}
- *              size_t elem_count = 5;
  *              uint32_t int_min = 0;
  *              uint32_t int_max = 100;
- *              size_t bstr_size = 8;
+ *              uint32_t bstr_size = 8;
  *              uint32_t ints[3];
  *              cbor_string_type_t bstrs[2];
+ *              bool res;
  *
- *              list_start_decode(pp_payload, p_payload_end, &parent_elem_count,
- *                                &elem_count, NULL, NULL);
- *              multi_decode(3, 3, &num_decode, uintx32_decode, pp_payload,
- *                           p_payload_end, ints, &int_min, &int_max, 4);
- *              multi_decode(0, 2, &num_decode, strx_decode, pp_payload,
- *                           p_payload_end, bstrs, &bstr_size, &bstr_size,
+ *              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
  *
- *          See @ref intx32_decode for information about the undocumented
- *          parameters.
- *
  * @param[in]  min_decode    The minimum acceptable number of elements.
  * @param[in]  max_decode    The maximum acceptable number of elements.
- * @param[out] p_num_decode  The actual 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.
- *                           p_result is moved @p result_len bytes for each call
- *                           to @p decoder, i.e. @p p_result refers to an array
+ *                           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] p_result      Where to place the decoded values. Must be an array
+ * @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 expected by the @p decoder.
+ *                           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(size_t min_decode, size_t max_decode, size_t *p_num_decode,
-		decoder_t decoder, cbor_decode_state_t * p_state, void *p_result, void *p_min_result, void *p_max_result,
-		size_t result_len);
+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);
 
-#endif
+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/regenerate_serial_recovery_cbor.sh b/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
index 79cb6e9..b371e0a 100755
--- a/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
+++ b/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
@@ -1,19 +1,19 @@
 #!/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 cddl-gen submodule is updated."
 	echo "Usage: $0 <copyright>"
-	echo "  e.g. $0 \"2020 Nordic Semiconductor ASA\""
+	echo "  e.g. $0 \"2021 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 cddl-gen submodule.
  * Commit %s
  */
 
-' "$2" "$(git -C ../../../ext/cddl_gen rev-parse HEAD)"; cat $1;)" > $1
+' "$2" "$(git -C ../../../ext/cddl-gen rev-parse HEAD)"; cat $1;)" > $1
 }
 
 echo "Copying cbor_decode.c|h"
@@ -22,11 +22,15 @@
 	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/include/cbor_decode.h cbor_decode.h cbor_decode.h
+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/scripts/cddl_gen.py -i serial_recovery.cddl -t Upload --oc serial_recovery_cbor.c --oh serial_recovery_cbor.h --time-header
+python3 ../../../ext/cddl-gen/scripts/cddl_gen.py -c serial_recovery.cddl code -d -t Upload --oc serial_recovery_cbor.c --oh serial_recovery_cbor.h --time-header
 
 add_copyright() {
 echo "$(printf '/*
@@ -42,3 +46,4 @@
 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"
diff --git a/boot/boot_serial/src/serial_recovery_cbor.c b/boot/boot_serial/src/serial_recovery_cbor.c
index 45634ef..4277a7d 100644
--- a/boot/boot_serial/src/serial_recovery_cbor.c
+++ b/boot/boot_serial/src/serial_recovery_cbor.c
@@ -1,16 +1,18 @@
 /*
- * This file has been generated from the cddl_gen submodule.
- * Commit 9d911cf0c7c9f13b5a9fdd5ed6c1012df21e5576
+ * This file has been generated from the cddl-gen submodule.
+ * Commit 8f9358a0b4b0e9b0cd579f0988056ef0b60760e4
  */
 
 /*
- * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2021 Nordic Semiconductor ASA
  *
  * SPDX-License-Identifier: Apache-2.0
  */
 
-/* Generated with cddl_gen.py (https://github.com/oyvindronningstad/cddl_gen)
- * at: 2020-05-13 12:19:04
+/*
+ * Generated with cddl_gen.py (https://github.com/NordicSemiconductor/cddl-gen)
+ * at: 2021-05-10 09:40:43
+ * Generated with a default_max_qty of 3
  */
 
 #include <stdint.h>
@@ -20,65 +22,73 @@
 #include "cbor_decode.h"
 #include "serial_recovery_cbor.h"
 
+#if DEFAULT_MAX_QTY != 3
+#error "The type file was generated with a different default_max_qty than this file"
+#endif
+
 
 static bool decode_Member(
-		cbor_decode_state_t *p_state, void * p_result, void * p_min_value,
-		void * p_max_value)
+		cbor_state_t *state, struct Member_ *result)
 {
-	cbor_decode_print("decode_Member\n");
-	uint8_t const * p_payload_bak;
-	size_t elem_count_bak;
-	_Member_t* p_type_result = (_Member_t*)p_result;
+	cbor_print("%s\n", __func__);
+	cbor_string_type_t tmp_str;
+	bool int_res;
 
-	bool result = (((p_payload_bak = p_state->p_payload) && ((elem_count_bak = p_state->elem_count) || 1) && ((((strx_decode(p_state, &((*p_type_result)._Member_image_key), NULL, NULL))&& !memcmp("image", (*p_type_result)._Member_image_key.value, (*p_type_result)._Member_image_key.len)
-	&& (intx32_decode(p_state, &((*p_type_result)._Member_image), NULL, NULL))) && (((*p_type_result)._Member_choice = _Member_image) || 1))
-	|| ((p_state->p_payload = p_payload_bak) && ((p_state->elem_count = elem_count_bak) || 1) && (((strx_decode(p_state, &((*p_type_result)._Member_data_key), NULL, NULL))&& !memcmp("data", (*p_type_result)._Member_data_key.value, (*p_type_result)._Member_data_key.len)
-	&& (strx_decode(p_state, &((*p_type_result)._Member_data), NULL, NULL))) && (((*p_type_result)._Member_choice = _Member_data) || 1)))
-	|| ((p_state->p_payload = p_payload_bak) && ((p_state->elem_count = elem_count_bak) || 1) && (((strx_decode(p_state, &((*p_type_result)._Member_len_key), NULL, NULL))&& !memcmp("len", (*p_type_result)._Member_len_key.value, (*p_type_result)._Member_len_key.len)
-	&& (intx32_decode(p_state, &((*p_type_result)._Member_len), NULL, NULL))) && (((*p_type_result)._Member_choice = _Member_len) || 1)))
-	|| ((p_state->p_payload = p_payload_bak) && ((p_state->elem_count = elem_count_bak) || 1) && (((strx_decode(p_state, &((*p_type_result)._Member_off_key), NULL, NULL))&& !memcmp("off", (*p_type_result)._Member_off_key.value, (*p_type_result)._Member_off_key.len)
-	&& (intx32_decode(p_state, &((*p_type_result)._Member_off), NULL, NULL))) && (((*p_type_result)._Member_choice = _Member_off) || 1)))
-	|| ((p_state->p_payload = p_payload_bak) && ((p_state->elem_count = elem_count_bak) || 1) && (((strx_decode(p_state, &((*p_type_result)._Member_sha_key), NULL, NULL))&& !memcmp("sha", (*p_type_result)._Member_sha_key.value, (*p_type_result)._Member_sha_key.len)
-	&& (strx_decode(p_state, &((*p_type_result)._Member_sha), NULL, NULL))) && (((*p_type_result)._Member_choice = _Member_sha) || 1))))));
+	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))));
 
-	if (!result)
-	{
-		cbor_decode_trace();
-	}
+	if (!tmp_result)
+		cbor_trace();
 
-	return result;
+	return tmp_result;
 }
 
 static bool decode_Upload(
-		cbor_decode_state_t *p_state, void * p_result, void * p_min_value,
-		void * p_max_value)
+		cbor_state_t *state, struct Upload *result)
 {
-	cbor_decode_print("decode_Upload\n");
-	size_t temp_elem_counts[2];
-	size_t *p_temp_elem_count = temp_elem_counts;
-	Upload_t* p_type_result = (Upload_t*)p_result;
+	cbor_print("%s\n", __func__);
+	bool int_res;
 
-	bool result = (((list_start_decode(p_state, &(*(p_temp_elem_count++)), 1, 5))
-	&& multi_decode(1, 5, &(*p_type_result)._Upload_members_count, (void*)decode_Member, p_state, &((*p_type_result)._Upload_members), NULL, NULL, sizeof(_Member_t))
-	&& ((p_state->elem_count = *(--p_temp_elem_count)) || 1)));
+	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)))));
 
-	if (!result)
-	{
-		cbor_decode_trace();
-	}
+	if (!tmp_result)
+		cbor_trace();
 
-	p_state->elem_count = temp_elem_counts[0];
-	return result;
+	return tmp_result;
 }
 
 
-bool cbor_decode_Upload(const uint8_t * p_payload, size_t payload_len, Upload_t * p_result)
-{
-	cbor_decode_state_t state = {
-		.p_payload = p_payload,
-		.p_payload_end = p_payload + payload_len,
-		.elem_count = 1
-	};
 
-	return decode_Upload(&state, p_result, NULL, NULL);
+__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,
+		struct Upload *result,
+		uint32_t *payload_len_out)
+{
+	return entry_function(payload, payload_len, (const void *)result,
+		payload_len_out, (void *)decode_Upload,
+		1, 2);
 }
diff --git a/boot/boot_serial/src/serial_recovery_cbor.h b/boot/boot_serial/src/serial_recovery_cbor.h
index aa14f5c..bccc443 100644
--- a/boot/boot_serial/src/serial_recovery_cbor.h
+++ b/boot/boot_serial/src/serial_recovery_cbor.h
@@ -1,16 +1,18 @@
 /*
- * This file has been generated from the cddl_gen submodule.
- * Commit 9d911cf0c7c9f13b5a9fdd5ed6c1012df21e5576
+ * This file has been generated from the cddl-gen submodule.
+ * Commit 8f9358a0b4b0e9b0cd579f0988056ef0b60760e4
  */
 
 /*
- * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2021 Nordic Semiconductor ASA
  *
  * SPDX-License-Identifier: Apache-2.0
  */
 
-/* Generated with cddl_gen.py (https://github.com/oyvindronningstad/cddl_gen)
- * at: 2020-05-13 12:19:04
+/*
+ * Generated with cddl_gen.py (https://github.com/NordicSemiconductor/cddl-gen)
+ * at: 2021-05-10 09:40:43
+ * Generated with a default_max_qty of 3
  */
 
 #ifndef SERIAL_RECOVERY_CBOR_H__
@@ -21,45 +23,17 @@
 #include <stddef.h>
 #include <string.h>
 #include "cbor_decode.h"
+#include "types_serial_recovery_cbor.h"
+
+#if DEFAULT_MAX_QTY != 3
+#error "The type file was generated with a different default_max_qty than this file"
+#endif
 
 
-typedef struct {
-	union {
-		struct {
-			cbor_string_type_t _Member_image_key;
-			int32_t _Member_image;
-		};
-		struct {
-			cbor_string_type_t _Member_data_key;
-			cbor_string_type_t _Member_data;
-		};
-		struct {
-			cbor_string_type_t _Member_len_key;
-			int32_t _Member_len;
-		};
-		struct {
-			cbor_string_type_t _Member_off_key;
-			int32_t _Member_off;
-		};
-		struct {
-			cbor_string_type_t _Member_sha_key;
-			cbor_string_type_t _Member_sha;
-		};
-	};
-	enum {
-		_Member_image,
-		_Member_data,
-		_Member_len,
-		_Member_off,
-		_Member_sha,
-	} _Member_choice;
-} _Member_t;
+bool cbor_decode_Upload(
+		const uint8_t *payload, uint32_t payload_len,
+		struct Upload *result,
+		uint32_t *payload_len_out);
 
-typedef struct {
-	_Member_t _Upload_members[5];
-	size_t _Upload_members_count;
-} Upload_t;
 
-bool cbor_decode_Upload(const uint8_t * p_payload, size_t payload_len, Upload_t * p_result);
-
-#endif // SERIAL_RECOVERY_CBOR_H__
+#endif /* SERIAL_RECOVERY_CBOR_H__ */
diff --git a/boot/boot_serial/src/types_serial_recovery_cbor.h b/boot/boot_serial/src/types_serial_recovery_cbor.h
new file mode 100644
index 0000000..01505eb
--- /dev/null
+++ b/boot/boot_serial/src/types_serial_recovery_cbor.h
@@ -0,0 +1,56 @@
+/*
+ * This file has been generated from the cddl-gen submodule.
+ * Commit 8f9358a0b4b0e9b0cd579f0988056ef0b60760e4
+ */
+
+/*
+ * Generated with cddl_gen.py (https://github.com/NordicSemiconductor/cddl-gen)
+ * at: 2021-05-10 09:40:43
+ * 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/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt
index 3c8b93d..29cff0a 100644
--- a/boot/zephyr/CMakeLists.txt
+++ b/boot/zephyr/CMakeLists.txt
@@ -239,6 +239,7 @@
   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_common.c)
 
   zephyr_include_directories(${BOOT_DIR}/bootutil/include)
   zephyr_include_directories(${BOOT_DIR}/boot_serial/include)