From 64d84977c2c7b647adef440a33a73b371a362003 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 12 Aug 2024 09:05:23 +0100 Subject: [PATCH] [nrf fromtree] mgmt: mcumgr: grp: img_mgmt: Add optional image slot state callback Adds an optional callback which can be used to append custom fields to the image slot state command response Signed-off-by: Jamie McCrae (cherry picked from commit 031f9f2943333e561ec4abd04b141402909e1d9d) --- .../mcumgr/grp/img_mgmt/img_mgmt_callbacks.h | 18 +++++ include/zephyr/mgmt/mcumgr/mgmt/callbacks.h | 3 + subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig | 16 +++++ .../mcumgr/grp/img_mgmt/src/img_mgmt_state.c | 65 ++++++++++++------- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h index a9e05b5d3d1..ac6f01cc244 100644 --- a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h +++ b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h @@ -8,6 +8,10 @@ #ifndef H_MCUMGR_IMG_MGMT_CALLBACKS_ #define H_MCUMGR_IMG_MGMT_CALLBACKS_ +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -37,6 +41,20 @@ struct img_mgmt_upload_check { struct img_mgmt_upload_req *req; }; +/** + * Structure provided in the #MGMT_EVT_OP_IMG_MGMT_IMAGE_SLOT_STATE notification callback: This + * callback function is used to allow applications or modules append custom fields to the image + * slot state response. + */ +struct img_mgmt_state_slot_encode { + bool *ok; + zcbor_state_t *zse; + const uint32_t slot; + const char *version; + const uint8_t *hash; + const int flags; +}; + /** * @} */ diff --git a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h index 7678a70fdf9..80479555578 100644 --- a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h +++ b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h @@ -180,6 +180,9 @@ enum img_mgmt_group_events { /** Callback when an image write command has finished writing to flash. */ MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 5), + /** Callback when an image slot's state is encoded for a response. */ + MGMT_EVT_OP_IMG_MGMT_IMAGE_SLOT_STATE = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 6), + /** Used to enable all img_mgmt_group events. */ MGMT_EVT_OP_IMG_MGMT_ALL = MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_IMG), }; diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig index 20582a230d7..5e6da1e0ba7 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig @@ -185,6 +185,22 @@ config MCUMGR_GRP_IMG_TOO_LARGE_BOOTLOADER_INFO endchoice +config MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_HOOK + bool "Image slot state hook" + depends on MCUMGR_MGMT_NOTIFICATION_HOOKS + help + Allows applications to add additional fields to responses for the image slot state + command. + +config MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_STATES + int + prompt "Predicted maximum number of entries per group" if MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_HOOK + default 15 + help + This is used for defining CBOR map holding group data. + The value does not affect memory allocation, it is used by zcbor + to figure out how to encode map depending on its predicted size. + config MCUMGR_GRP_IMG_QSPI_XIP_SPLIT_IMAGE bool "QSPI XIP Split image mode" depends on MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c index edfe26e452f..29553f83c73 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c @@ -28,16 +28,11 @@ #include #endif -LOG_MODULE_DECLARE(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL); +#ifdef CONFIG_MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_HOOK +#include +#endif -/* The value here sets how many "characteristics" that describe image is - * encoded into a map per each image (like bootable flags, and so on). - * This value is only used for zcbor to predict map size and map encoding - * and does not affect memory allocation. - * In case when more "characteristics" are added to image map then - * zcbor_map_end_encode may fail it this value does not get updated. - */ -#define MAX_IMG_CHARACTERISTICS 15 +LOG_MODULE_DECLARE(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL); #ifndef CONFIG_MCUMGR_GRP_IMG_FRUGAL_LIST #define ZCBOR_ENCODE_FLAG(zse, label, value) \ @@ -415,8 +410,9 @@ img_mgmt_state_confirm(void) } /* Return zcbor encoding result */ -static bool img_mgmt_state_encode_slot(zcbor_state_t *zse, uint32_t slot, int state_flags) +static bool img_mgmt_state_encode_slot(struct smp_streamer *ctxt, uint32_t slot, int state_flags) { + zcbor_state_t *zse = ctxt->writer->zs; uint32_t flags; char vers_str[IMG_MGMT_VER_MAX_STR_LEN]; uint8_t hash[IMAGE_HASH_LEN]; /* SHA256 hash */ @@ -425,17 +421,30 @@ static bool img_mgmt_state_encode_slot(zcbor_state_t *zse, uint32_t slot, int st bool ok; int rc = img_mgmt_read_info(slot, &ver, hash, &flags); +#if defined(CONFIG_MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_HOOK) + int32_t err_rc; + uint16_t err_group; + struct img_mgmt_state_slot_encode slot_encode_data = { + .ok = &ok, + .zse = zse, + .slot = slot, + .version = vers_str, + .hash = hash, + .flags = flags, + }; +#endif + if (rc != 0) { /* zcbor encoding did not fail */ return true; } - ok = zcbor_map_start_encode(zse, MAX_IMG_CHARACTERISTICS) && + ok = zcbor_map_start_encode(zse, CONFIG_MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_STATES) && (CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER == 1 || - (zcbor_tstr_put_lit(zse, "image") && - zcbor_uint32_put(zse, slot >> 1))) && - zcbor_tstr_put_lit(zse, "slot") && - zcbor_uint32_put(zse, slot % 2) && + (zcbor_tstr_put_lit(zse, "image") && + zcbor_uint32_put(zse, slot >> 1))) && + zcbor_tstr_put_lit(zse, "slot") && + zcbor_uint32_put(zse, slot % 2) && zcbor_tstr_put_lit(zse, "version"); if (ok) { @@ -447,15 +456,27 @@ static bool img_mgmt_state_encode_slot(zcbor_state_t *zse, uint32_t slot, int st } } - ok = ok && zcbor_tstr_put_lit(zse, "hash") && + ok = ok && zcbor_tstr_put_lit(zse, "hash") && zcbor_bstr_encode(zse, &zhash) && ZCBOR_ENCODE_FLAG(zse, "bootable", !(flags & IMAGE_F_NON_BOOTABLE)) && ZCBOR_ENCODE_FLAG(zse, "pending", state_flags & REPORT_SLOT_PENDING) && ZCBOR_ENCODE_FLAG(zse, "confirmed", state_flags & REPORT_SLOT_CONFIRMED) && ZCBOR_ENCODE_FLAG(zse, "active", state_flags & REPORT_SLOT_ACTIVE) && - ZCBOR_ENCODE_FLAG(zse, "permanent", state_flags & REPORT_SLOT_PERMANENT) && - zcbor_map_end_encode(zse, MAX_IMG_CHARACTERISTICS); + ZCBOR_ENCODE_FLAG(zse, "permanent", state_flags & REPORT_SLOT_PERMANENT); + + if (!ok) { + goto failed; + } + +#if defined(CONFIG_MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_HOOK) + /* Send notification to application to optionally append more fields */ + (void)mgmt_callback_notify(MGMT_EVT_OP_IMG_MGMT_IMAGE_SLOT_STATE, &slot_encode_data, + sizeof(slot_encode_data), &err_rc, &err_group); +#endif + + ok &= zcbor_map_end_encode(zse, CONFIG_MCUMGR_GRP_IMG_IMAGE_SLOT_STATE_STATES); +failed: return ok; } @@ -499,11 +520,11 @@ img_mgmt_state_read(struct smp_streamer *ctxt) /* Need to report slots in proper order */ if (slot_a < slot_o) { - ok = img_mgmt_state_encode_slot(zse, slot_a, flags_a) && - img_mgmt_state_encode_slot(zse, slot_o, flags_o); + ok = img_mgmt_state_encode_slot(ctxt, slot_a, flags_a) && + img_mgmt_state_encode_slot(ctxt, slot_o, flags_o); } else { - ok = img_mgmt_state_encode_slot(zse, slot_o, flags_o) && - img_mgmt_state_encode_slot(zse, slot_a, flags_a); + ok = img_mgmt_state_encode_slot(ctxt, slot_o, flags_o) && + img_mgmt_state_encode_slot(ctxt, slot_a, flags_a); } }