From 90bdba4f2df4e085d4e4f60bb86bc80bee6be409 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 29 Jan 2024 11:16:34 +0000 Subject: [PATCH 1/4] mgmt: mcumgr: grp: os_mgmt: Add firmware uploader boot type Adds firmware uploader to the output of bootloader mode for MCUboot Signed-off-by: Jamie McCrae --- modules/Kconfig.mcuboot | 9 +++++++++ subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c | 2 ++ 2 files changed, 11 insertions(+) diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index 7f41167d3d3887..b9b842b0a36125 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -231,6 +231,15 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT to downgrade running application, but note that MCUboot may do that if application with higher version will not get confirmed. +config MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER + bool "MCUboot has been configured in firmware updater mode" + select MCUBOOT_IMGTOOL_OVERWRITE_ONLY + help + MCUboot will only boot slot0_partition for the main application but has + an entrance mechanism defined for entering the slot1_partition which is + a dedicated firmware updater application used to update the slot0_partition + application. + endchoice # MCUBOOT_BOOTLOADER_MODE config MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c index 3e524362fa3c72..7de448ac78d5a9 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c @@ -435,6 +435,8 @@ os_mgmt_mcumgr_params(struct smp_streamer *ctxt) #define BOOTLOADER_MODE MCUBOOT_MODE_DIRECT_XIP #elif IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) #define BOOTLOADER_MODE MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT +#elif IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) +#define BOOTLOADER_MODE MCUBOOT_MODE_FIRMWARE_LOADER #else #define BOOTLOADER_MODE -1 #endif From abfc9a8adf53c57c3091828c8d551e57cdb0e486 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 29 Jan 2024 11:17:24 +0000 Subject: [PATCH 2/4] dfu: Add support for MCUboot estimated update image overhead size Adds support for an overhead size which MCUboot can set when using sysbuild, this can be used to check the provided size of an application being uploaded to ensure it will fit and swap without being rejected Signed-off-by: Jamie McCrae --- subsys/dfu/Kconfig | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/subsys/dfu/Kconfig b/subsys/dfu/Kconfig index e320185dfef275..ec7d90ba14a2f6 100644 --- a/subsys/dfu/Kconfig +++ b/subsys/dfu/Kconfig @@ -31,9 +31,10 @@ config MCUBOOT_IMG_MANAGER endchoice +if MCUBOOT_IMG_MANAGER + config MCUBOOT_SHELL bool "MCUboot shell" - depends on MCUBOOT_IMG_MANAGER depends on SHELL help Enable shell module, which provides information about image slots and @@ -43,7 +44,6 @@ config MCUBOOT_SHELL config MCUBOOT_TRAILER_SWAP_TYPE bool "use trailer's swap_type field" default y - depends on MCUBOOT_IMG_MANAGER help Enables usage swap type field which is required after "Fix double swap on interrupted revert" mcuboot patch @@ -51,9 +51,16 @@ config MCUBOOT_TRAILER_SWAP_TYPE Disable this option if need to be compatible with earlier version of MCUBoot. +config MCUBOOT_UPDATE_FOOTER_SIZE + hex "Estimated update footer size" + default 0x0 + help + Estimated size of update image data, which is used to prevent loading of firmware updates + that MCUboot cannot update due to being too large. This should be set from sysbuild, only + used when MCUMGR_GRP_IMG_TOO_LARGE_SYSBUILD is enabled. + config IMG_BLOCK_BUF_SIZE int "Image writer buffer size" - depends on MCUBOOT_IMG_MANAGER default 512 help Size (in Bytes) of buffer for image writer. Must be a multiple of @@ -61,7 +68,6 @@ config IMG_BLOCK_BUF_SIZE config IMG_ERASE_PROGRESSIVELY bool "Erase flash progressively when receiving new firmware" - depends on MCUBOOT_IMG_MANAGER select STREAM_FLASH_ERASE help If enabled, flash is erased as necessary when receiving new firmware, @@ -71,7 +77,6 @@ config IMG_ERASE_PROGRESSIVELY config IMG_ENABLE_IMAGE_CHECK bool "Image check functions" - depends on MCUBOOT_IMG_MANAGER select FLASH_AREA_CHECK_INTEGRITY help If enabled, there will be available the function to check flash @@ -80,6 +85,8 @@ config IMG_ENABLE_IMAGE_CHECK Another use is to ensure that firmware upgrade routines from internet server to flash slot are performing properly. +endif # MCUBOOT_IMG_MANAGER + module = IMG_MANAGER module-str = image manager source "subsys/logging/Kconfig.template.log_config" From d997f53208bc9dcea5122a2844f62090a9fa0fcb Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 29 Jan 2024 11:19:21 +0000 Subject: [PATCH 3/4] west.yml: MCUboot synchronization from upstream Update Zephyr fork of MCUboot to revision: a4eda30f5b0cfd0cf15512be9dcd559239dbfc91 Brings following Zephyr relevant fixes: - a4eda30f zephyr: Add estimated size of update trailer to sysbuild - 205d7e5b boot_serial: Adapt to zcbor 0.8.x Signed-off-by: Jamie McCrae --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 3b9b32f5b4e58b..dff0e29705c40d 100644 --- a/west.yml +++ b/west.yml @@ -282,7 +282,7 @@ manifest: groups: - crypto - name: mcuboot - revision: f09e205b1e4a8d2bc3f50dffa7960d6ccd14df59 + revision: a4eda30f5b0cfd0cf15512be9dcd559239dbfc91 path: bootloader/mcuboot - name: mipi-sys-t path: modules/debug/mipi-sys-t From 28af6ebed99621ffef94b529dd5e9ab720caa2f4 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 18 Dec 2023 11:41:23 +0000 Subject: [PATCH 4/4] mgmt: mcumgr: grp: img_mgmt: Add optional max image size reduction Adds an optional feature that can be used to reduce the maximum allowed image upload file size whereby an image could be uploaded that would be too large to swap even if it could fit the partition Signed-off-by: Jamie McCrae --- .../mgmt/mcumgr/grp/img_mgmt/img_mgmt.h | 3 + subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig | 32 +++++++ .../mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c | 84 +++++++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h index 55c226d217ce9e..c11e423e26dd3a 100644 --- a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h @@ -162,6 +162,9 @@ enum img_mgmt_err_code_t { /** Setting test to active slot is not allowed */ IMG_MGMT_ERR_IMAGE_SETTING_TEST_TO_ACTIVE_DENIED, + + /** Current active slot for image cannot be determined */ + IMG_MGMT_ERR_ACTIVE_SLOT_NOT_KNOWN, }; /** diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig index 81fc57d92385d3..80e524ff72b37c 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig @@ -153,6 +153,38 @@ config MCUMGR_GRP_IMG_MUTEX can be used by applications to reset the image management state (useful if there are multiple ways that firmware updates can be loaded). +choice MCUMGR_GRP_IMG_TOO_LARGE_CHECK + prompt "Image size check overhead" + default MCUMGR_GRP_IMG_TOO_LARGE_DISABLED + help + MCUboot images should be limited to the maximum size that the bootloader can swap, in + order to know this size, additional information is needed from the MCUboot + configuration, otherwise an image can be uploaded that is too large for the bootloader + to swap, this selects which method to use. + + Note: setting this to a non-disabled option will prevent uploading of padded and + confirmed images, if support for that is required then this feature should be left as + disabled. + +config MCUMGR_GRP_IMG_TOO_LARGE_DISABLED + bool "Disabled" + help + Will not take MCUboot configuration into account when checking for maximum file size. + +config MCUMGR_GRP_IMG_TOO_LARGE_SYSBUILD + bool "Via Sysbuild from MCUboot configuration" + depends on ROM_END_OFFSET > 0 || MCUBOOT_UPDATE_FOOTER_SIZE > 0 + help + Will use the image overhead size calculated during Sysbuild image configuration. + +config MCUMGR_GRP_IMG_TOO_LARGE_BOOTLOADER_INFO + bool "Via retention bootloader info" + depends on RETENTION_BOOTLOADER_INFO_OUTPUT_FUNCTION + help + Will fetch the maximum image size from the bootloader info retention subsystem module. + +endchoice + module = MCUMGR_GRP_IMG module-str = mcumgr_grp_img source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c index 303f112709a1e3..a67db362366aab 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c @@ -19,6 +19,11 @@ #include +#if defined(CONFIG_MCUMGR_GRP_IMG_TOO_LARGE_BOOTLOADER_INFO) +#include +#include +#endif + LOG_MODULE_DECLARE(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL); #define SLOT0_PARTITION slot0_partition @@ -564,6 +569,18 @@ int img_mgmt_upload_inspect(const struct img_mgmt_upload_req *req, if (req->off == 0) { /* First upload chunk. */ const struct flash_area *fa; +#if defined(CONFIG_MCUMGR_GRP_IMG_TOO_LARGE_SYSBUILD) && \ + (defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_WITHOUT_SCRATCH) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT)) && \ + CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE > 0 + const struct flash_area *fa_current; + int current_img_area; +#elif defined(CONFIG_MCUMGR_GRP_IMG_TOO_LARGE_BOOTLOADER_INFO) + int max_image_size; +#endif if (req->img_data.len < sizeof(struct image_header)) { /* Image header is the first thing in the image */ @@ -576,6 +593,7 @@ int img_mgmt_upload_inspect(const struct img_mgmt_upload_req *req, IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, img_mgmt_err_str_hdr_malformed); return IMG_MGMT_ERR_INVALID_LENGTH; } + action->size = req->size; hdr = (struct image_header *)req->img_data.value; @@ -626,6 +644,72 @@ int img_mgmt_upload_inspect(const struct img_mgmt_upload_req *req, return IMG_MGMT_ERR_INVALID_IMAGE_TOO_LARGE; } +#if defined(CONFIG_MCUMGR_GRP_IMG_TOO_LARGE_SYSBUILD) && \ + (defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_WITHOUT_SCRATCH) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT)) && \ + CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE > 0 + /* Check if slot1 is larger than slot0 by the update size, if so then the size + * check can be skipped because the devicetree partitions are okay + */ + current_img_area = img_mgmt_flash_area_id(req->image); + + if (current_img_area < 0) { + /* Current slot cannot be determined */ + LOG_ERR("Failed to determine active slot for image %d: %d", req->image, + current_img_area); + return IMG_MGMT_ERR_ACTIVE_SLOT_NOT_KNOWN; + } + + rc = flash_area_open(current_img_area, &fa_current); + if (rc) { + IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, + img_mgmt_err_str_flash_open_failed); + LOG_ERR("Failed to open flash area ID %u: %d", current_img_area, rc); + flash_area_close(fa); + return IMG_MGMT_ERR_FLASH_OPEN_FAILED; + } + + flash_area_close(fa_current); + + LOG_DBG("Primary size: %d, secondary size: %d, overhead: %d, max update size: %d", + fa_current->fa_size, fa->fa_size, CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE, + (fa->fa_size + CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE)); + + if (fa_current->fa_size >= (fa->fa_size + CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE)) { + /* Upgrade slot is of sufficient size, nothing to check */ + LOG_INF("Upgrade slots already sized appropriately, " + "CONFIG_MCUMGR_GRP_IMG_TOO_LARGE_SYSBUILD is not needed"); + goto skip_size_check; + } + + if (req->size > (fa->fa_size - CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE)) { + IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, + img_mgmt_err_str_image_too_large); + flash_area_close(fa); + LOG_ERR("Upload too large for slot (with end offset): %u > %u", req->size, + (fa->fa_size - CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE)); + return IMG_MGMT_ERR_INVALID_IMAGE_TOO_LARGE; + } + +skip_size_check: +#elif defined(CONFIG_MCUMGR_GRP_IMG_TOO_LARGE_BOOTLOADER_INFO) + rc = blinfo_lookup(BLINFO_MAX_APPLICATION_SIZE, (char *)&max_image_size, + sizeof(max_image_size)); + + if (rc == sizeof(max_image_size) && max_image_size > 0 && + req->size > max_image_size) { + IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, + img_mgmt_err_str_image_too_large); + flash_area_close(fa); + LOG_ERR("Upload too large for slot (with max image size): %u > %u", + req->size, max_image_size); + return IMG_MGMT_ERR_INVALID_IMAGE_TOO_LARGE; + } +#endif + #if defined(CONFIG_MCUMGR_GRP_IMG_REJECT_DIRECT_XIP_MISMATCHED_SLOT) if (hdr->ih_flags & IMAGE_F_ROM_FIXED) { if (fa->fa_off != hdr->ih_load_addr) {