Commit cb07e888 authored by Jamie McCrae's avatar Jamie McCrae Committed by Dominik Ermel
Browse files

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: default avatarJamie McCrae <jamie.mccrae@nordicsemi.no>
parent db6ba462
Loading
Loading
Loading
Loading
+53 −45
Original line number Diff line number Diff line
@@ -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 @@ bs_upload(char *buf, int len)
    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 @@ bs_upload(char *buf, int len)
    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 @@ bs_upload(char *buf, int len)
     * }
     */

    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 @@ bs_upload(char *buf, int len)
         }
#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 @@ bs_rc_rsp(int rc_code)
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 {

boot/boot_serial/src/echo.cddl

deleted100644 → 0
+0 −9
Original line number Diff line number Diff line
;
; Copyright (c) 2022 Nordic Semiconductor ASA
;
; SPDX-License-Identifier: Apache-2.0
;

Echo = {
	"d" => tstr
}
+0 −7
Original line number Diff line number Diff line
@@ -22,10 +22,6 @@ copy_with_copy_notice() {
	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 @@ echo "$(printf '/*
' "$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"
+0 −15
Original line number Diff line number Diff line
;
; 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
}
+0 −106
Original line number Diff line number Diff line
/*
 * 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;
}
Loading