boot_serial: Replace cbor auto-generated code with zcbor functions
Replaces the auto-generated decoding/encoding files with inline code
for encoding/decoding cbor data structures, this adds the benefit of
allowing the elements to be in any order and reduces code size. To
accommodate this, zcbor_bulk has been imported from Zephyr.
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c
index c6c58bf..5f83ed2 100644
--- a/boot/boot_serial/src/boot_serial.c
+++ b/boot/boot_serial/src/boot_serial.c
@@ -36,16 +36,13 @@
#include <zephyr/sys/crc.h>
#include <zephyr/sys/base64.h>
#include <hal/hal_flash.h>
-#include <zcbor_encode.h>
#elif __ESPRESSIF__
-#include "zcbor_encode.h"
#include <bootloader_utility.h>
#include <esp_rom_sys.h>
#include <esp_crc.h>
#include <endian.h>
#include <mbedtls/base64.h>
#else
-#include "zcbor_encode.h"
#include <bsp/bsp.h>
#include <hal/hal_system.h>
#include <hal/hal_flash.h>
@@ -55,6 +52,10 @@
#include <base64/base64.h>
#endif /* __ZEPHYR__ */
+#include <zcbor_decode.h>
+#include <zcbor_encode.h>
+#include "zcbor_bulk.h"
+
#include <flash_map_backend/flash_map_backend.h>
#include <os/os.h>
#include <os/os_malloc.h>
@@ -74,12 +75,14 @@
#include "single_loader.h"
#endif
-#include "serial_recovery_cbor.h"
-#include "serial_recovery_echo.h"
#include "bootutil/boot_hooks.h"
BOOT_LOG_MODULE_DECLARE(mcuboot);
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE ZCBOR_ARRAY_SIZE
+#endif
+
#ifndef MCUBOOT_SERIAL_MAX_RECEIVE_SIZE
#define MCUBOOT_SERIAL_MAX_RECEIVE_SIZE 512
#endif
@@ -383,10 +386,13 @@
size_t img_chunk_off = SIZE_MAX; /* Offset of image chunk within image */
uint8_t rem_bytes; /* Reminder bytes after aligning chunk write to
* to flash alignment */
- int img_num;
+ uint32_t img_num;
size_t img_size_tmp = SIZE_MAX; /* Temp variable for image size */
const struct flash_area *fap = NULL;
int rc;
+ struct zcbor_string img_chunk_data;
+ size_t decoded = 0;
+ bool ok;
#ifdef MCUBOOT_ERASE_PROGRESSIVELY
static off_t not_yet_erased = 0; /* Offset of next byte to erase; writes to flash
* are done in consecutive manner and erases are done
@@ -398,7 +404,25 @@
static struct flash_sector status_sector;
#endif
- img_num = 0;
+ zcbor_state_t zsd[4];
+ zcbor_new_state(zsd, sizeof(zsd) / sizeof(zcbor_state_t), (uint8_t *)buf, len, 1);
+
+ struct zcbor_map_decode_key_val image_upload_decode[] = {
+ ZCBOR_MAP_DECODE_KEY_DECODER("image", zcbor_uint32_decode, &img_num),
+ ZCBOR_MAP_DECODE_KEY_DECODER("data", zcbor_bstr_decode, &img_chunk_data),
+ ZCBOR_MAP_DECODE_KEY_DECODER("len", zcbor_size_decode, &img_size_tmp),
+ ZCBOR_MAP_DECODE_KEY_DECODER("off", zcbor_size_decode, &img_chunk_off),
+ };
+
+ ok = zcbor_map_decode_bulk(zsd, image_upload_decode, ARRAY_SIZE(image_upload_decode),
+ &decoded) == 0;
+
+ if (!ok) {
+ goto out_invalid_data;
+ }
+
+ img_chunk = img_chunk_data.value;
+ img_chunk_len = img_chunk_data.len;
/*
* Expected data format.
@@ -410,37 +434,6 @@
* }
*/
- struct Upload upload;
- size_t decoded_len;
- uint_fast8_t result = cbor_decode_Upload((const uint8_t *)buf, len, &upload, &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]._Upload_members;
- switch(member->_Member_choice) {
- case _Member_image:
- img_num = member->_Member_image;
- break;
- case _Member_data:
- img_chunk = member->_Member_data.value;
- img_chunk_len = member->_Member_data.len;
- break;
- case _Member_len:
- img_size_tmp = member->_Member_len;
- break;
- case _Member_off:
- img_chunk_off = member->_Member_off;
- break;
- case _Member_sha:
- default:
- /* Nothing to do. */
- break;
- }
- }
-
if (img_chunk_off == SIZE_MAX || img_chunk == NULL) {
/*
* Offset must be set in every block.
@@ -478,7 +471,6 @@
}
#endif
-
#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
/* We are using swap state at end of flash area to store validation
* result. Make sure the user cannot write it from an image to skip validation.
@@ -656,22 +648,38 @@
static void
bs_echo(char *buf, int len)
{
- struct Echo echo = { 0 };
- size_t decoded_len;
+ struct zcbor_string value = { 0 };
+ struct zcbor_string key;
+ bool ok;
uint32_t rc = MGMT_ERR_EINVAL;
- uint_fast8_t result = cbor_decode_Echo((const uint8_t *)buf, len, &echo, &decoded_len);
- if ((result != ZCBOR_SUCCESS) || (len != decoded_len)) {
+ zcbor_state_t zsd[4];
+ zcbor_new_state(zsd, sizeof(zsd) / sizeof(zcbor_state_t), (uint8_t *)buf, len, 1);
+
+ if (!zcbor_map_start_decode(zsd)) {
goto out;
}
- if (echo._Echo_d.value == NULL) {
+ do {
+ ok = zcbor_tstr_decode(zsd, &key);
+
+ if (ok) {
+ if (key.len == 1 && *key.value == 'd') {
+ ok = zcbor_tstr_decode(zsd, &value);
+ break;
+ }
+
+ ok = zcbor_any_skip(zsd, NULL);
+ }
+ } while (ok);
+
+ if (!ok || !zcbor_map_end_decode(zsd)) {
goto out;
}
zcbor_map_start_encode(cbor_state, 10);
zcbor_tstr_put_term(cbor_state, "r");
- if (zcbor_tstr_encode(cbor_state, &echo._Echo_d) && zcbor_map_end_encode(cbor_state, 10)) {
+ if (zcbor_tstr_encode(cbor_state, &value) && zcbor_map_end_encode(cbor_state, 10)) {
boot_serial_output();
return;
} else {
diff --git a/boot/boot_serial/src/echo.cddl b/boot/boot_serial/src/echo.cddl
deleted file mode 100644
index 42ce0ba..0000000
--- a/boot/boot_serial/src/echo.cddl
+++ /dev/null
@@ -1,9 +0,0 @@
-;
-; Copyright (c) 2022 Nordic Semiconductor ASA
-;
-; SPDX-License-Identifier: Apache-2.0
-;
-
-Echo = {
- "d" => tstr
-}
diff --git a/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh b/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
index b56c270..33fa630 100755
--- a/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
+++ b/boot/boot_serial/src/regenerate_serial_recovery_cbor.sh
@@ -22,10 +22,6 @@
add_copy_notice $2 "copied"
}
-
-echo "Generating serial_recovery_cbor.c|h"
-zcbor code -c serial_recovery.cddl -d -t Upload --oc serial_recovery_cbor.c --oh serial_recovery_cbor.h --time-header --copy-sources
-
add_copyright() {
echo "$(printf '/*
* Copyright (c) %s
@@ -36,9 +32,6 @@
' "$2"; cat $1;)" > $1
}
-add_copyright serial_recovery_cbor.c "$1"
-add_copyright serial_recovery_cbor.h "$1"
-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"
diff --git a/boot/boot_serial/src/serial_recovery.cddl b/boot/boot_serial/src/serial_recovery.cddl
deleted file mode 100644
index d45db08..0000000
--- a/boot/boot_serial/src/serial_recovery.cddl
+++ /dev/null
@@ -1,15 +0,0 @@
-;
-; Copyright (c) 2020 Nordic Semiconductor ASA
-;
-; SPDX-License-Identifier: Apache-2.0
-;
-
-Member = ("image" => int) /
- ("data" => bstr) /
- ("len" => int) /
- ("off" => int) /
- ("sha" => bstr)
-
-Upload = {
- 1**5members: Member
-}
diff --git a/boot/boot_serial/src/serial_recovery_cbor.c b/boot/boot_serial/src/serial_recovery_cbor.c
deleted file mode 100644
index b54fac4..0000000
--- a/boot/boot_serial/src/serial_recovery_cbor.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2023 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/*
- * Generated using zcbor version 0.7.0
- * https://github.com/NordicSemiconductor/zcbor
- * at: 2023-04-14 11:34:28
- * Generated with a --default-max-qty of 3
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include <zcbor_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(zcbor_state_t *state, struct Member_ *result);
-static bool decode_repeated_Upload_members(zcbor_state_t *state, struct Upload_members *result);
-static bool decode_Upload(zcbor_state_t *state, struct Upload *result);
-
-
-static bool decode_Member(
- zcbor_state_t *state, struct Member_ *result)
-{
- zcbor_print("%s\r\n", __func__);
- struct zcbor_string tmp_str;
- bool 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), true))
- || (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), true)))
- || (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), true)))
- || (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), true)))
- || (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), true)))), zcbor_union_end_code(state), int_res))));
-
- if (!tmp_result)
- 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(
- zcbor_state_t *state, struct Upload *result)
-{
- zcbor_print("%s\r\n", __func__);
-
- 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)
- zcbor_trace();
-
- return tmp_result;
-}
-
-
-
-int cbor_decode_Upload(
- const uint8_t *payload, size_t payload_len,
- struct Upload *result,
- size_t *payload_len_out)
-{
- 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 err = zcbor_pop_error(states);
-
- zcbor_print("Return error: %d\r\n", err);
- return (err == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : err;
- }
- return ZCBOR_SUCCESS;
-}
diff --git a/boot/boot_serial/src/serial_recovery_cbor.h b/boot/boot_serial/src/serial_recovery_cbor.h
deleted file mode 100644
index 6bec4e7..0000000
--- a/boot/boot_serial/src/serial_recovery_cbor.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2023 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/*
- * Generated using zcbor version 0.7.0
- * https://github.com/NordicSemiconductor/zcbor
- * at: 2023-04-14 11:34:28
- * Generated with a --default-max-qty of 3
- */
-
-#ifndef SERIAL_RECOVERY_CBOR_H__
-#define SERIAL_RECOVERY_CBOR_H__
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include <zcbor_decode.h>
-
-#include "serial_recovery_cbor_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if DEFAULT_MAX_QTY != 3
-#error "The type file was generated with a different default_max_qty than this file"
-#endif
-
-
-int cbor_decode_Upload(
- const uint8_t *payload, size_t payload_len,
- struct Upload *result,
- size_t *payload_len_out);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#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
deleted file mode 100644
index 57b1095..0000000
--- a/boot/boot_serial/src/serial_recovery_cbor_types.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2023 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/*
- * Generated using zcbor version 0.7.0
- * https://github.com/NordicSemiconductor/zcbor
- * at: 2023-04-14 11:34:28
- * 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>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** 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];
- size_t _Upload_members_count;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* SERIAL_RECOVERY_CBOR_TYPES_H__ */
diff --git a/boot/boot_serial/src/serial_recovery_echo.c b/boot/boot_serial/src/serial_recovery_echo.c
deleted file mode 100644
index 8b10a01..0000000
--- a/boot/boot_serial/src/serial_recovery_echo.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Generated using zcbor version 0.4.99
- * https://github.com/NordicSemiconductor/zcbor
- * Generated with a --default-max-qty of 3
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include <zcbor_decode.h>
-
-#include "serial_recovery_echo.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_Echo(zcbor_state_t *state, struct Echo *result);
-
-static bool decode_Echo(
- zcbor_state_t *state, struct Echo *result)
-{
- zcbor_print("%s\r\n", __func__);
- struct zcbor_string tmp_str;
-
- bool tmp_result = (((zcbor_map_start_decode(state) && (((((zcbor_tstr_expect(state, ((tmp_str.value = (uint8_t *)"d", tmp_str.len = sizeof("d") - 1, &tmp_str)))))
- && (zcbor_tstr_decode(state, (&(*result)._Echo_d))))) || (zcbor_list_map_end_force_decode(state), false)) && zcbor_map_end_decode(state))));
-
- if (!tmp_result)
- zcbor_trace();
-
- return tmp_result;
-}
-
-
-
-int cbor_decode_Echo(
- const uint8_t *payload, size_t payload_len,
- struct Echo *result,
- size_t *payload_len_out)
-{
- zcbor_state_t states[3];
-
- zcbor_new_state(states, sizeof(states) / sizeof(zcbor_state_t), payload, payload_len, 1);
-
- bool ret = decode_Echo(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 err = zcbor_pop_error(states);
-
- zcbor_print("Return error: %d\r\n", err);
- return (err == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : err;
- }
- return ZCBOR_SUCCESS;
-}
diff --git a/boot/boot_serial/src/serial_recovery_echo.h b/boot/boot_serial/src/serial_recovery_echo.h
deleted file mode 100644
index 9a5d691..0000000
--- a/boot/boot_serial/src/serial_recovery_echo.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Generated using zcbor version 0.4.99
- * https://github.com/NordicSemiconductor/zcbor
- * Generated with a --default-max-qty of 3
- */
-
-#ifndef SERIAL_RECOVERY_ECHO_H__
-#define SERIAL_RECOVERY_ECHO_H__
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include <zcbor_decode.h>
-
-#include "serial_recovery_echo_types.h"
-
-#if DEFAULT_MAX_QTY != 3
-#error "The type file was generated with a different default_max_qty than this file"
-#endif
-
-
-int cbor_decode_Echo(
- const uint8_t *payload, size_t payload_len,
- struct Echo *result,
- size_t *payload_len_out);
-
-
-#endif /* SERIAL_RECOVERY_ECHO_H__ */
diff --git a/boot/boot_serial/src/serial_recovery_echo_types.h b/boot/boot_serial/src/serial_recovery_echo_types.h
deleted file mode 100644
index 0473fea..0000000
--- a/boot/boot_serial/src/serial_recovery_echo_types.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Generated using zcbor version 0.4.99
- * https://github.com/NordicSemiconductor/zcbor
- * Generated with a --default-max-qty of 3
- */
-
-#ifndef SERIAL_RECOVERY_ECHO_TYPES_H__
-#define SERIAL_RECOVERY_ECHO_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 Echo {
- struct zcbor_string _Echo_d;
-};
-
-
-#endif /* SERIAL_RECOVERY_ECHO_TYPES_H__ */
diff --git a/boot/boot_serial/src/zcbor_bulk.c b/boot/boot_serial/src/zcbor_bulk.c
new file mode 100644
index 0000000..35ae0bd
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_bulk.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include "zcbor_bulk.h"
+
+int zcbor_map_decode_bulk(zcbor_state_t *zsd, struct zcbor_map_decode_key_val *map,
+ size_t map_size, size_t *matched)
+{
+ bool ok;
+ struct zcbor_map_decode_key_val *dptr = map;
+
+ if (!zcbor_map_start_decode(zsd)) {
+ return -EBADMSG;
+ }
+
+ *matched = 0;
+ ok = true;
+
+ do {
+ struct zcbor_string key;
+ bool found = false;
+ size_t map_count = 0;
+
+ ok = zcbor_tstr_decode(zsd, &key);
+
+ while (ok && map_count < map_size) {
+ if (dptr >= (map + map_size)) {
+ dptr = map;
+ }
+
+ if (key.len == dptr->key.len &&
+ memcmp(key.value, dptr->key.value, key.len) == 0) {
+
+ if (dptr->found) {
+ return -EADDRINUSE;
+ }
+ if (!dptr->decoder(zsd, dptr->value_ptr)) {
+ /* Failure to decode value matched to key
+ * means that either decoder has been
+ * incorrectly assigned or SMP payload
+ * is broken anyway.
+ */
+ return -ENOMSG;
+ }
+
+ dptr->found = true;
+ found = true;
+ ++dptr;
+ ++(*matched);
+ break;
+ }
+
+ ++dptr;
+ ++map_count;
+ }
+
+ if (!found && ok) {
+ ok = zcbor_any_skip(zsd, NULL);
+ }
+ } while (ok);
+
+ return zcbor_map_end_decode(zsd) ? 0 : -EBADMSG;
+}
diff --git a/boot/boot_serial/src/zcbor_bulk.h b/boot/boot_serial/src/zcbor_bulk.h
new file mode 100644
index 0000000..3b7c42f
--- /dev/null
+++ b/boot/boot_serial/src/zcbor_bulk.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2022 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef H_ZCBOR_BULK_PRIV_
+#define H_ZCBOR_BULK_PRIV_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __ZEPHYR__
+#include <zcbor_common.h>
+#include <zcbor_decode.h>
+#else
+#include "zcbor_common.h"
+#include "zcbor_decode.h"
+#endif
+
+/** @cond INTERNAL_HIDDEN */
+
+struct zcbor_map_decode_key_val {
+ struct zcbor_string key; /* Map key string */
+ zcbor_decoder_t *decoder; /* Key corresponding decoder */
+ void *value_ptr;
+ bool found;
+};
+
+/** @brief Define single key-decoder mapping
+ *
+ * The macro creates a single zcbor_map_decode_key_val type object.
+ *
+ * @param k key is "" enclosed string representing key;
+ * @param dec decoder function; this should be zcbor_decoder_t
+ * type function from zcbor or a user provided implementation
+ * compatible with the type.
+ * @param vp non-NULL pointer for result of decoding; should correspond
+ * to type served by decoder function for the mapping.
+ */
+#define ZCBOR_MAP_DECODE_KEY_DECODER(k, dec, vp) \
+ { \
+ { \
+ .value = (uint8_t *)k, \
+ .len = sizeof(k) - 1, \
+ }, \
+ .decoder = (zcbor_decoder_t *)dec, \
+ .value_ptr = vp, \
+ }
+
+/** @brief Define single key-value decode mapping
+ *
+ * ZCBOR_MAP_DECODE_KEY_DECODER should be used instead of this macro as,
+ * this macro does not allow keys with whitespaces embeeded, which CBOR
+ * does allow.
+ *
+ * The macro creates a single zcbor_map_decode_key_val type object.
+ *
+ * @param k key; the @p k will be stringified so should be given
+ * without "";
+ * @param dec decoder function; this should be zcbor_decoder_t
+ * type function from zcbor or a user provided implementation
+ * compatible with the type.
+ * @param vp non-NULL pointer for result of decoding; should correspond
+ * to type served by decoder function for the mapping.
+ */
+#define ZCBOR_MAP_DECODE_KEY_VAL(k, dec, vp) \
+ ZCBOR_MAP_DECODE_KEY_DECODER(STRINGIFY(k), dec, vp)
+
+/** @brief Decodes single level map according to a provided key-decode map.
+ *
+ * The function takes @p map of key to decoder array defined as:
+ *
+ * struct zcbor_map_decode_key_val map[] = {
+ * ZCBOR_MAP_DECODE_KEY_DECODER("key0", decode_fun0, val_ptr0),
+ * ZCBOR_MAP_DECODE_KEY_DECODER("key1", decode_fun1, val_ptr1),
+ * ...
+ * };
+ *
+ * where "key?" is string representing key; the decode_fun? is
+ * zcbor_decoder_t compatible function, either from zcbor or defined by
+ * user; val_ptr? are pointers to variables where decoder function for
+ * a given key will place a decoded value - they have to agree in type
+ * with decoder function.
+ *
+ * Failure to decode any of values will cause the function to return
+ * negative error, and leave the map open: map is broken anyway or key-decoder
+ * mapping is broken, and we can not really decode the map.
+ *
+ * Note that the function opens map by itself and will fail if map
+ * is already opened.
+ *
+ * @param zsd zcbor decoder state;
+ * @param map key-decoder mapping list;
+ * @param map_size size of maps, both maps have to have the same size;
+ * @param matched pointer to the counter of matched keys, zeroed upon
+ * successful map entry and incremented only for successful
+ * decoded fields.
+ * @return 0 when the whole map has been parsed, there have been
+ * no decoding errors, and map has been closed successfully;
+ * -ENOMSG when given decoder function failed to decode
+ * value;
+ * -EADDRINUSE when key appears twice within map, map is then
+ * parsed up to they key that has appeared twice;
+ * -EBADMSG when failed to close map.
+ */
+int zcbor_map_decode_bulk(zcbor_state_t *zsd, struct zcbor_map_decode_key_val *map,
+ size_t map_size, size_t *matched);
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_ZCBOR_BULK_PRIV_ */
diff --git a/boot/espressif/CMakeLists.txt b/boot/espressif/CMakeLists.txt
index 90dd749..2172869 100644
--- a/boot/espressif/CMakeLists.txt
+++ b/boot/espressif/CMakeLists.txt
@@ -221,7 +221,7 @@
list(APPEND bootutil_srcs
${BOOT_SERIAL_DIR}/src/boot_serial.c
- ${BOOT_SERIAL_DIR}/src/serial_recovery_cbor.c
+ ${BOOT_SERIAL_DIR}/src/zcbor_bulk.c
${ZCBOR_DIR}/src/zcbor_decode.c
${ZCBOR_DIR}/src/zcbor_encode.c
${ZCBOR_DIR}/src/zcbor_common.c
diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt
index 998464b..d9d474e 100644
--- a/boot/zephyr/CMakeLists.txt
+++ b/boot/zephyr/CMakeLists.txt
@@ -238,9 +238,7 @@
if(CONFIG_MCUBOOT_SERIAL)
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_ifdef(CONFIG_BOOT_MGMT_ECHO ${BOOT_DIR}/boot_serial/src/serial_recovery_echo.c)
+ zephyr_sources(${BOOT_DIR}/boot_serial/src/zcbor_bulk.c)
zephyr_include_directories(${BOOT_DIR}/bootutil/include)
zephyr_include_directories(${BOOT_DIR}/boot_serial/include)