Commit a7d34caa authored by Øyvind Rønningstad's avatar Øyvind Rønningstad Committed by David Brown
Browse files

boot_serial: Upgrade from cddl-gen 0.1.0 to zcbor 0.4.0



cddl-gen has been renamed to zcbor.
Update regenerate_serial_recovery_cbor.sh and regenerate/recopy all
files.

Remove the submodule in ext/ since it is no longer necessary when
the zcbor package is installed (only needed for regeneration, not
for building).
Signed-off-by: default avatarØyvind Rønningstad <oyvind.ronningstad@nordicsemi.no>
parent 35f61d30
......@@ -19,9 +19,6 @@
[submodule "boot/cypress/libs/cy-mbedtls-acceleration"]
path = boot/cypress/libs/cy-mbedtls-acceleration
url = https://github.com/cypresssemiconductorco/cy-mbedtls-acceleration.git
[submodule "ext/cddl-gen"]
path = ext/cddl-gen
url = https://github.com/NordicSemiconductor/cddl-gen.git
[submodule "boot/espressif/hal/esp-idf"]
path = boot/espressif/hal/esp-idf
url = https://github.com/espressif/esp-idf.git
......
......@@ -11,7 +11,6 @@ samples/*
scripts/*
sim/*
testplan/*
ext/cddl_gen/*
ext/fiat/*
ext/mbedtls/*
ext/mbedtls-asn1/*
......
......@@ -25,7 +25,7 @@
#include "sysflash/sysflash.h"
#include "bootutil/bootutil_log.h"
#include "cbor_encode.h"
#include "zcbor_encode.h"
#ifdef __ZEPHYR__
#include <sys/reboot.h>
......@@ -99,17 +99,12 @@ static char bs_obuf[BOOT_SERIAL_OUT_MAX];
static void boot_serial_output(void);
static cbor_state_backups_t dummy_backups;
static cbor_state_t cbor_state = {
.backups = &dummy_backups
};
static zcbor_state_t cbor_state[2];
void reset_cbor_state(void)
{
cbor_state.payload_mut = (uint8_t *)bs_obuf;
cbor_state.payload_end = (const uint8_t *)bs_obuf
+ sizeof(bs_obuf);
cbor_state.elem_count = 0;
zcbor_new_encode_state(cbor_state, 2, (uint8_t *)bs_obuf,
(size_t)bs_obuf + sizeof(bs_obuf), 0);
}
/**
......@@ -126,7 +121,7 @@ void reset_cbor_state(void)
*/
extern int bs_peruser_system_specific(const struct nmgr_hdr *hdr,
const char *buffer,
int len, cbor_state_t *cs);
int len, zcbor_state_t *cs);
/*
* Convert version into string without use of snprintf().
......@@ -157,6 +152,9 @@ u32toa(char *tgt, uint32_t val)
return dst - tgt;
}
#define zcbor_tstr_put_lit_cast(state, string) \
zcbor_tstr_encode_ptr(state, (uint8_t *)string, sizeof(string) - 1)
/*
* dst has to be able to fit "255.255.65535.4294967295" (25 characters).
*/
......@@ -186,9 +184,9 @@ bs_list(char *buf, int len)
const struct flash_area *fap;
uint8_t image_index;
map_start_encode(&cbor_state, 1);
tstrx_put(&cbor_state, "images");
list_start_encode(&cbor_state, 5);
zcbor_map_start_encode(cbor_state, 1);
zcbor_tstr_put_lit_cast(cbor_state, "images");
zcbor_list_start_encode(cbor_state, 5);
image_index = 0;
IMAGES_ITER(image_index) {
for (slot = 0; slot < 2; slot++) {
......@@ -235,24 +233,24 @@ bs_list(char *buf, int len)
continue;
}
map_start_encode(&cbor_state, 20);
zcbor_map_start_encode(cbor_state, 20);
#if (BOOT_IMAGE_NUMBER > 1)
tstrx_put(&cbor_state, "image");
uintx32_put(&cbor_state, image_index);
zcbor_tstr_put_lit_cast(cbor_state, "image");
zcbor_uint32_put(cbor_state, image_index);
#endif
tstrx_put(&cbor_state, "slot");
uintx32_put(&cbor_state, slot);
tstrx_put(&cbor_state, "version");
zcbor_tstr_put_lit_cast(cbor_state, "slot");
zcbor_uint32_put(cbor_state, slot);
zcbor_tstr_put_lit_cast(cbor_state, "version");
bs_list_img_ver((char *)tmpbuf, sizeof(tmpbuf), &hdr.ih_ver);
tstrx_put_term(&cbor_state, (char *)tmpbuf);
map_end_encode(&cbor_state, 20);
zcbor_tstr_encode_ptr(cbor_state, tmpbuf, strlen((char *)tmpbuf));
zcbor_map_end_encode(cbor_state, 20);
}
}
list_end_encode(&cbor_state, 5);
map_end_encode(&cbor_state, 1);
zcbor_list_end_encode(cbor_state, 5);
zcbor_map_end_encode(cbor_state, 1);
boot_serial_output();
}
......@@ -289,15 +287,15 @@ bs_upload(char *buf, int len)
*/
struct Upload upload;
uint32_t decoded_len;
bool result = cbor_decode_Upload((const uint8_t *)buf, len, &upload, &decoded_len);
size_t decoded_len;
uint_fast8_t result = cbor_decode_Upload((const uint8_t *)buf, len, &upload, &decoded_len);
if (!result || (len != decoded_len)) {
if ((result != ZCBOR_SUCCESS) || (len != decoded_len)) {
goto out_invalid_data;
}
for (int i = 0; i < upload._Upload_members_count; i++) {
struct Member_ *member = &upload._Upload_members[i];
struct Member_ *member = &upload._Upload_members[i]._Upload_members;
switch(member->_Member_choice) {
case _Member_image:
img_num = member->_Member_image;
......@@ -458,14 +456,14 @@ bs_upload(char *buf, int len)
out:
BOOT_LOG_INF("RX: 0x%x", rc);
map_start_encode(&cbor_state, 10);
tstrx_put(&cbor_state, "rc");
uintx32_put(&cbor_state, rc);
zcbor_map_start_encode(cbor_state, 10);
zcbor_tstr_put_lit_cast(cbor_state, "rc");
zcbor_uint32_put(cbor_state, rc);
if (rc == 0) {
tstrx_put(&cbor_state, "off");
uintx32_put(&cbor_state, curr_off);
zcbor_tstr_put_lit_cast(cbor_state, "off");
zcbor_uint32_put(cbor_state, curr_off);
}
map_end_encode(&cbor_state, 10);
zcbor_map_end_encode(cbor_state, 10);
boot_serial_output();
flash_area_close(fap);
......@@ -484,10 +482,10 @@ out:
static void
bs_rc_rsp(int rc_code)
{
map_start_encode(&cbor_state, 10);
tstrx_put(&cbor_state, "rc");
uintx32_put(&cbor_state, rc_code);
map_end_encode(&cbor_state, 10);
zcbor_map_start_encode(cbor_state, 10);
zcbor_tstr_put_lit_cast(cbor_state, "rc");
zcbor_uint32_put(cbor_state, rc_code);
zcbor_map_end_encode(cbor_state, 10);
boot_serial_output();
}
......@@ -605,7 +603,7 @@ boot_serial_input(char *buf, int len)
break;
}
} else if (MCUBOOT_PERUSER_MGMT_GROUP_ENABLED == 1) {
if (bs_peruser_system_specific(hdr, buf, len, &cbor_state) == 0) {
if (bs_peruser_system_specific(hdr, buf, len, cbor_state) == 0) {
boot_serial_output();
}
} else {
......@@ -628,7 +626,7 @@ boot_serial_output(void)
char encoded_buf[BASE64_ENCODE_SIZE(sizeof(buf))];
data = bs_obuf;
len = (uint32_t)cbor_state.payload_mut - (uint32_t)bs_obuf;
len = (uint32_t)cbor_state->payload_mut - (uint32_t)bs_obuf;
bs_hdr->nh_op++;
bs_hdr->nh_flags = 0;
......
/*
* This file has been copied from the cddl-gen submodule.
* Commit 9f77837f9950da1633d22abf6181a830521a6688
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "cbor_common.h"
_Static_assert((sizeof(size_t) == sizeof(void *)),
"This code needs size_t to be the same length as pointers.");
bool new_backup(cbor_state_t *state, uint32_t new_elem_count)
{
if ((state->backups->current_backup + 1)
>= state->backups->num_backups) {
FAIL();
}
uint32_t i = ++(state->backups->current_backup);
memcpy(&state->backups->backup_list[i], state,
sizeof(cbor_state_t));
state->elem_count = new_elem_count;
return true;
}
bool restore_backup(cbor_state_t *state, uint32_t flags,
uint32_t max_elem_count)
{
const uint8_t *payload = state->payload;
const uint32_t elem_count = state->elem_count;
if (state->backups->current_backup == 0) {
FAIL();
}
if (flags & FLAG_RESTORE) {
uint32_t i = state->backups->current_backup;
memcpy(state, &state->backups->backup_list[i],
sizeof(cbor_state_t));
}
if (flags & FLAG_DISCARD) {
state->backups->current_backup--;
}
if (elem_count > max_elem_count) {
cbor_print("elem_count: %d (expected max %d)\r\n",
elem_count, max_elem_count);
FAIL();
}
if (flags & FLAG_TRANSFER_PAYLOAD) {
state->payload = payload;
}
return true;
}
bool union_start_code(cbor_state_t *state)
{
if (!new_backup(state, state->elem_count)) {
FAIL();
}
return true;
}
bool union_elem_code(cbor_state_t *state)
{
if (!restore_backup(state, FLAG_RESTORE, state->elem_count)) {
FAIL();
}
return true;
}
bool union_end_code(cbor_state_t *state)
{
if (!restore_backup(state, FLAG_DISCARD, state->elem_count)) {
FAIL();
}
return true;
}
bool entry_function(const uint8_t *payload, uint32_t payload_len,
const void *struct_ptr, uint32_t *payload_len_out,
cbor_encoder_t func, uint32_t elem_count, uint32_t num_backups)
{
cbor_state_t state = {
.payload = payload,
.payload_end = payload + payload_len,
.elem_count = elem_count,
};
cbor_state_t state_backups[num_backups + 1];
cbor_state_backups_t backups = {
.backup_list = state_backups,
.current_backup = 0,
.num_backups = num_backups + 1,
};
state.backups = &backups;
bool result = func(&state, struct_ptr);
if (result && (payload_len_out != NULL)) {
*payload_len_out = MIN(payload_len,
(size_t)state.payload - (size_t)payload);
}
return result;
}
/*
* This file has been copied from the cddl-gen submodule.
* Commit 9f77837f9950da1633d22abf6181a830521a6688
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef CBOR_COMMON_H__
#define CBOR_COMMON_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/** Convenience type that allows pointing to strings directly inside the payload
* without the need to copy out.
*/
typedef struct
{
const uint8_t *value;
uint32_t len;
} cbor_string_type_t;
#ifdef CDDL_CBOR_VERBOSE
#include <sys/printk.h>
#define cbor_trace() (printk("bytes left: %d, byte: 0x%x, elem_count: 0x%zx, %s:%d\n",\
(uint32_t)state->payload_end - (uint32_t)state->payload, *state->payload, state->elem_count,\
__FILE__, __LINE__))
#define cbor_assert(expr, ...) \
do { \
if (!(expr)) { \
printk("ASSERTION \n \"" #expr \
"\"\nfailed at %s:%d with message:\n ", \
__FILE__, __LINE__); \
printk(__VA_ARGS__);\
return false; \
} \
} while(0)
#define cbor_print(...) printk(__VA_ARGS__)
#else
#define cbor_trace() ((void)state)
#define cbor_assert(...)
#define cbor_print(...)
#endif
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
struct cbor_state_backups_s;
typedef struct cbor_state_backups_s cbor_state_backups_t;
typedef struct{
union {
uint8_t *payload_mut;
uint8_t const *payload; /**< The current place in the payload. Will be
updated when an element is correctly
processed. */
};
uint8_t const *payload_bak; /**< Temporary backup of payload. */
uint32_t elem_count; /**< The current element is part of a LIST or a MAP,
and this keeps count of how many elements are
expected. This will be checked before processing
and decremented if the element is correctly
processed. */
uint8_t const *payload_end; /**< The end of the payload. This will be
checked against payload before
processing each element. */
cbor_state_backups_t *backups;
} cbor_state_t;
struct cbor_state_backups_s{
cbor_state_t *backup_list;
uint32_t current_backup;
uint32_t num_backups;
};
/** Function pointer type used with multi_decode.
*
* This type is compatible with all decoding functions here and in the generated
* code, except for multi_decode.
*/
typedef bool(cbor_encoder_t)(cbor_state_t *, const void *);
typedef bool(cbor_decoder_t)(cbor_state_t *, void *);
/** Enumeration representing the major types available in CBOR.
*
* The major type is represented in the 3 first bits of the header byte.
*/
typedef enum
{
CBOR_MAJOR_TYPE_PINT = 0, ///! Positive Integer
CBOR_MAJOR_TYPE_NINT = 1, ///! Negative Integer
CBOR_MAJOR_TYPE_BSTR = 2, ///! Byte String
CBOR_MAJOR_TYPE_TSTR = 3, ///! Text String
CBOR_MAJOR_TYPE_LIST = 4, ///! List
CBOR_MAJOR_TYPE_MAP = 5, ///! Map
CBOR_MAJOR_TYPE_TAG = 6, ///! Semantic Tag
CBOR_MAJOR_TYPE_PRIM = 7, ///! Primitive Type
} cbor_major_type_t;
/** Shorthand macro to check if a result is within min/max constraints.
*/
#define PTR_VALUE_IN_RANGE(type, res, min, max) \
(((min == NULL) || (*(type *)res >= *(type *)min)) \
&& ((max == NULL) || (*(type *)res <= *(type *)max)))
#define FAIL() \
do {\
cbor_trace(); \
return false; \
} while(0)
#define VALUE_IN_HEADER 23 /**! For values below this, the value is encoded
directly in the header. */
#define BOOL_TO_PRIM 20 ///! In CBOR, false/true have the values 20/21
#define FLAG_RESTORE 1UL
#define FLAG_DISCARD 2UL
#define FLAG_TRANSFER_PAYLOAD 4UL
bool new_backup(cbor_state_t *state, uint32_t new_elem_count);
bool restore_backup(cbor_state_t *state, uint32_t flags,
uint32_t max_elem_count);
bool union_start_code(cbor_state_t *state);
bool union_elem_code(cbor_state_t *state);
bool union_end_code(cbor_state_t *state);
bool entry_function(const uint8_t *payload, uint32_t payload_len,
const void *struct_ptr, uint32_t *payload_len_out,
cbor_encoder_t func, uint32_t elem_count, uint32_t num_backups);
#endif /* CBOR_COMMON_H__ */
/*
* This file has been copied from the cddl-gen submodule.
* Commit 9f77837f9950da1633d22abf6181a830521a6688
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "cbor_decode.h"
#include "cbor_common.h"
/** Return value length from additional value.
*/
static uint32_t additional_len(uint8_t additional)
{
if (24 <= additional && additional <= 27) {
/* 24 => 1
* 25 => 2
* 26 => 4
* 27 => 8
*/
return 1 << (additional - 24);
}
return 0;
}
/** Extract the major type, i.e. the first 3 bits of the header byte. */
#define MAJOR_TYPE(header_byte) (((header_byte) >> 5) & 0x7)
/** Extract the additional info, i.e. the last 5 bits of the header byte. */
#define ADDITIONAL(header_byte) ((header_byte) & 0x1F)
#define FAIL_AND_DECR_IF(expr) \
do {\
if (expr) { \
(state->payload)--; \
FAIL(); \
} \
} while(0)
#define FAIL_IF(expr) \
do {\
if (expr) { \
FAIL(); \
} \
} while(0)
#define FAIL_RESTORE() \
state->payload = state->payload_bak; \
state->elem_count++; \
FAIL()
/** Get a single value.
*
* @details @p ppayload must point to the header byte. This function will
* retrieve the value (either from within the additional info, or from
* the subsequent bytes) and return it in the result. The result can
* have arbitrary length.
*
* The function will also validate
* - Min/max constraints on the value.
* - That @p payload doesn't overrun past @p payload_end.
* - That @p elem_count has not been exhausted.
*
* @p ppayload and @p elem_count are updated if the function
* succeeds. If not, they are left unchanged.
*
* CBOR values are always big-endian, so this function converts from
* big to little-endian if necessary (@ref CONFIG_BIG_ENDIAN).
*/
static bool value_extract(cbor_state_t *state,
void *const result, uint32_t result_len)
{
cbor_trace();
cbor_assert(result_len != 0, "0-length result not supported.\n");
cbor_assert(result != NULL, NULL);
FAIL_IF((state->elem_count == 0) \
|| (state->payload >= state->payload_end));
uint8_t *u8_result = (uint8_t *)result;
uint8_t additional = ADDITIONAL(*state->payload);
state->payload_bak = state->payload;
(state->payload)++;
memset(result, 0, result_len);
if (additional <= VALUE_IN_HEADER) {
#ifdef CONFIG_BIG_ENDIAN
u8_result[result_len - 1] = additional;
#else
u8_result[0] = additional;
#endif /* CONFIG_BIG_ENDIAN */
} else {
uint32_t len = additional_len(additional);
FAIL_AND_DECR_IF(len > result_len);
FAIL_AND_DECR_IF((state->payload + len)
> state->payload_end);
#ifdef CONFIG_BIG_ENDIAN
memcpy(&u8_result[result_len - len], state->payload, len);
#else
for (uint32_t i = 0; i < len; i++) {
u8_result[i] = (state->payload)[len - i - 1];
}
#endif /* CONFIG_BIG_ENDIAN */
(state->payload) += len;
}
(state->elem_count)--;
return true;
}
static bool int32_decode(cbor_state_t *state, int32_t *result)
{
FAIL_IF(state->payload >= state->payload_end);
uint8_t major_type = MAJOR_TYPE(*state->payload);
uint32_t uint_result;
int32_t int_result;
if (!value_extract(state, &uint_result, 4)) {
FAIL();
}
cbor_print("uintval: %u\r\n", uint_result);
if (uint_result >= (1 << (8*sizeof(uint_result)-1))) {
/* Value is too large to fit in a signed integer. */
FAIL_RESTORE();
}
if (major_type == CBOR_MAJOR_TYPE_NINT) {
/* Convert from CBOR's representation. */
int_result = -1 - uint_result;
} else {
int_result = uint_result;
}
cbor_print("val: %d\r\n", int_result);
*result = int_result;
return true;
}
bool intx32_decode(cbor_state_t *state, int32_t *result)