Skip to content

Commit

Permalink
mgmt: mcumgr: grp: img_mgmt: Add optional max image size reduction
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
nordicjm committed Jan 29, 2024
1 parent b7ebf84 commit 3a51b22
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
32 changes: 32 additions & 0 deletions subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
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"
Expand Down
82 changes: 82 additions & 0 deletions subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

#include <mgmt/mcumgr/grp/img_mgmt/img_mgmt_priv.h>

#if defined(CONFIG_MCUMGR_GRP_IMG_TOO_LARGE_BOOTLOADER_INFO)
#include <zephyr/retention/retention.h>
#include <zephyr/retention/blinfo.h>
#endif

LOG_MODULE_DECLARE(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL);

#define SLOT0_PARTITION slot0_partition
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -626,6 +644,70 @@ 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_SINGLE_APP) && \
!defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) && \
CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE > 0

//check if direct XIP (without revert) is needed

Check failure on line 652 in subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c:652 do not use C99 // comments
#if 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)
/* 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);

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_ROM_END_OFFSET,
(fa->fa_size + CONFIG_ROM_END_OFFSET));

if (fa_current->fa_size >= (fa->fa_size + CONFIG_ROM_END_OFFSET)) {
/* Upgrade slot is of sufficient size, nothing to check */
goto skip_size_check;
}
#endif

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_ROM_END_OFFSET));
return IMG_MGMT_ERR_INVALID_IMAGE_TOO_LARGE;
}

#if 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)

Check warning on line 693 in subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c:693 line length of 298 exceeds 100 columns
skip_size_check:
#endif
#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) {
Expand Down

0 comments on commit 3a51b22

Please sign in to comment.