diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 8999403c5..b124ff894 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -298,6 +298,26 @@ boot_slots_compatible(struct boot_loader_state *state) } } +#ifdef MCUBOOT_SLOT0_EXPECTED_ERASE_SIZE + if (sector_sz_pri != MCUBOOT_SLOT0_EXPECTED_ERASE_SIZE) { + BOOT_LOG_DBG("Discrepancy, slot0 expected erase size: %d, actual: %d", + MCUBOOT_SLOT0_EXPECTED_ERASE_SIZE, sector_sz_pri); + } +#endif +#ifdef MCUBOOT_SLOT1_EXPECTED_ERASE_SIZE + if (sector_sz_sec != MCUBOOT_SLOT1_EXPECTED_ERASE_SIZE) { + BOOT_LOG_DBG("Discrepancy, slot1 expected erase size: %d, actual: %d", + MCUBOOT_SLOT1_EXPECTED_ERASE_SIZE, sector_sz_sec); + } +#endif + +#if defined(MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE) || defined(MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE) + if (!swap_write_block_size_check(state)) { + BOOT_LOG_WRN("Cannot upgrade: slot write sizes are not compatible"); + return 0; + } +#endif + if (num_sectors_pri > num_sectors_sec) { if (sector_sz_pri != boot_img_sector_size(state, BOOT_PRIMARY_SLOT, i)) { BOOT_LOG_WRN("Cannot upgrade: not same sector layout"); diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 960c72250..255e74736 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -101,6 +101,19 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat #endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) */ +#if defined(MCUBOOT_SWAP_USING_MOVE) +/** + * Check if device write block sizes are as expected, function should emit an error if there is + * a problem. If true is returned, the slots are marked as compatible, otherwise the slots are + * marked as incompatible. + * + * Requires MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE be set to the write block size of image 0 primary + * slot and MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE be set to the write block size of image 0 secondary + * slot. + */ +bool swap_write_block_size_check(struct boot_loader_state *state); +#endif /* defined(MCUBOOT_SWAP_USING_MOVE) */ + /** * Returns the maximum size of an application that can be loaded to a slot. */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 7762a22c8..eb9707f1e 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -379,13 +379,43 @@ function(dt_get_parent node) set(${node} "${${node}}" PARENT_SCOPE) endfunction() -if(CONFIG_BOOT_MAX_IMG_SECTORS_AUTO) - dt_nodelabel(slot0_flash NODELABEL "slot0_partition") - dt_prop(slot0_size PATH "${slot0_flash}" PROPERTY "reg" INDEX 1) - dt_get_parent(slot0_flash) - dt_get_parent(slot0_flash) - dt_prop(erase_size_slot0 PATH "${slot0_flash}" PROPERTY "erase-block-size") +dt_nodelabel(slot0_flash NODELABEL "slot0_partition") +dt_prop(slot0_size PATH "${slot0_flash}" PROPERTY "reg" INDEX 1) +dt_get_parent(slot0_flash) +dt_get_parent(slot0_flash) +dt_prop(erase_size_slot0 PATH "${slot0_flash}" PROPERTY "erase-block-size") +dt_prop(write_size_slot0 PATH "${slot0_flash}" PROPERTY "write-block-size") + +if(CONFIG_BOOT_SWAP_USING_MOVE) + if(DEFINED erase_size_slot0) + zephyr_compile_definitions("MCUBOOT_SLOT0_EXPECTED_ERASE_SIZE=${erase_size_slot0}") + endif() + + if(DEFINED write_size_slot0) + zephyr_compile_definitions("MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE=${write_size_slot0}") + endif() +endif() + +if(NOT CONFIG_SINGLE_APPLICATION_SLOT) + dt_nodelabel(slot1_flash NODELABEL "slot1_partition") + dt_prop(slot1_size PATH "${slot1_flash}" PROPERTY "reg" INDEX 1) + dt_get_parent(slot1_flash) + dt_get_parent(slot1_flash) + dt_prop(erase_size_slot1 PATH "${slot1_flash}" PROPERTY "erase-block-size") + dt_prop(write_size_slot1 PATH "${slot1_flash}" PROPERTY "write-block-size") + + if(CONFIG_BOOT_SWAP_USING_MOVE) + if(DEFINED erase_size_slot1) + zephyr_compile_definitions("MCUBOOT_SLOT1_EXPECTED_ERASE_SIZE=${erase_size_slot1}") + endif() + if(DEFINED write_size_slot1) + zephyr_compile_definitions("MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE=${write_size_slot1}") + endif() + endif() +endif() + +if(CONFIG_BOOT_MAX_IMG_SECTORS_AUTO) if(NOT DEFINED slot0_size) message(WARNING "Unable to determine size of slot0 partition, cannot calculate minimum sector usage") elseif(NOT DEFINED erase_size_slot0) @@ -395,12 +425,6 @@ if(CONFIG_BOOT_MAX_IMG_SECTORS_AUTO) endif() if(NOT CONFIG_SINGLE_APPLICATION_SLOT) - dt_nodelabel(slot1_flash NODELABEL "slot1_partition") - dt_prop(slot1_size PATH "${slot1_flash}" PROPERTY "reg" INDEX 1) - dt_get_parent(slot1_flash) - dt_get_parent(slot1_flash) - dt_prop(erase_size_slot1 PATH "${slot1_flash}" PROPERTY "erase-block-size") - if(NOT DEFINED slot1_size) message(WARNING "Unable to determine size of slot1 partition, cannot calculate minimum sector usage") elseif(NOT DEFINED erase_size_slot1) @@ -422,6 +446,10 @@ if(CONFIG_BOOT_MAX_IMG_SECTORS_AUTO) endif() endif() +if((CONFIG_BOOT_SWAP_USING_SCRATCH OR CONFIG_BOOT_SWAP_USING_MOVE) AND (DEFINED write_size_slot0 OR DEFINED write_size_slot1)) + zephyr_library_sources(flash_check.c) +endif() + if(SYSBUILD) if(CONFIG_SINGLE_APPLICATION_SLOT OR CONFIG_BOOT_FIRMWARE_LOADER OR CONFIG_BOOT_SWAP_USING_SCRATCH OR CONFIG_BOOT_SWAP_USING_MOVE OR CONFIG_BOOT_UPGRADE_ONLY OR CONFIG_BOOT_DIRECT_XIP OR CONFIG_BOOT_RAM_LOAD) # TODO: RAM LOAD support diff --git a/boot/zephyr/flash_check.c b/boot/zephyr/flash_check.c new file mode 100644 index 000000000..e8b1b4d06 --- /dev/null +++ b/boot/zephyr/flash_check.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include <../../bootutil/src/bootutil_priv.h> +#include "bootutil/bootutil_log.h" + +#include "mcuboot_config/mcuboot_config.h" + +#if defined(MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE) || defined(MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE) +BOOT_LOG_MODULE_DECLARE(mcuboot); + +bool swap_write_block_size_check(struct boot_loader_state *state) +{ +#ifdef MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE + size_t flash_write_block_size_pri; +#endif +#ifdef MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE + size_t flash_write_block_size_sec; +#endif + +#ifdef MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE + flash_write_block_size_pri = flash_get_write_block_size( + state->imgs[0][BOOT_PRIMARY_SLOT].area->fa_dev); + + if (flash_write_block_size_pri != MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE) { + BOOT_LOG_DBG("Discrepancy, slot0 expected write block size: %d, actual: %d", + MCUBOOT_SLOT0_EXPECTED_WRITE_SIZE, flash_write_block_size_pri); + } +#endif + +#ifdef MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE + flash_write_block_size_sec = flash_get_write_block_size( + state->imgs[0][BOOT_SECONDARY_SLOT].area->fa_dev); + + if (flash_write_block_size_sec != MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE) { + BOOT_LOG_DBG("Discrepancy, slot1 expected write block size: %d, actual: %d", + MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE, flash_write_block_size_sec); + } +#endif + + return true; +} +#endif diff --git a/docs/release-notes.d/compatible-slots.md b/docs/release-notes.d/compatible-slots.md new file mode 100644 index 000000000..4cbae1818 --- /dev/null +++ b/docs/release-notes.d/compatible-slots.md @@ -0,0 +1,7 @@ +- Added optional write block size checking to ensure expected + sizes match what is available on the hardware. +- Added optional erase size checking to ensure expected sizes + match what is available on the hardware. +- Added debug logs for zephyr to output discrepencies in erase + and write block sizes in dts vs actual hardware configuration + at run-time.