From 2c456e6703cea90db4abe33e0d1a18f9f05d59a1 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 10 Sep 2024 14:49:16 +0100 Subject: [PATCH 1/3] boot: zephyr: Add check for unexpected flash sector size Prints a debug log message if the device has a write block size for a flash device in DTS that is not the same as what the flash driver reports at run-time, this can be used to see if there is a faulty configuration as these compile-time values are used for various calculations Signed-off-by: Jamie McCrae --- boot/bootutil/src/swap_move.c | 13 +++++++++++++ boot/zephyr/CMakeLists.txt | 34 ++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 8999403c5..1b570a4f4 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -298,6 +298,19 @@ 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 (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/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 7762a22c8..6c7ffe50b 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -379,13 +379,29 @@ 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") + +if(CONFIG_BOOT_SWAP_USING_MOVE AND DEFINED erase_size_slot0) + zephyr_compile_definitions("MCUBOOT_SLOT0_EXPECTED_ERASE_SIZE=${erase_size_slot0}") +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(CONFIG_BOOT_SWAP_USING_MOVE AND DEFINED erase_size_slot1) + zephyr_compile_definitions("MCUBOOT_SLOT1_EXPECTED_ERASE_SIZE=${erase_size_slot1}") + 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 +411,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) From b19468dab960aaccb929acab470595acdc0e350b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 24 Sep 2024 09:58:15 +0100 Subject: [PATCH 2/3] boot: bootutil: Add write block size checking Adds write block size checking functionality and includes a zephyr implementation, this will not throw an error or prevent upgrade but will emit a debug log with a discrepency message Signed-off-by: Jamie McCrae --- boot/bootutil/src/swap_move.c | 7 +++++ boot/bootutil/src/swap_priv.h | 13 +++++++++ boot/zephyr/CMakeLists.txt | 26 +++++++++++++++--- boot/zephyr/flash_check.c | 50 +++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 boot/zephyr/flash_check.c diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 1b570a4f4..b124ff894 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -311,6 +311,13 @@ boot_slots_compatible(struct boot_loader_state *state) } #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 6c7ffe50b..eb9707f1e 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -384,9 +384,16 @@ 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 AND DEFINED erase_size_slot0) - zephyr_compile_definitions("MCUBOOT_SLOT0_EXPECTED_ERASE_SIZE=${erase_size_slot0}") +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) @@ -395,9 +402,16 @@ if(NOT CONFIG_SINGLE_APPLICATION_SLOT) 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(CONFIG_BOOT_SWAP_USING_MOVE AND DEFINED erase_size_slot1) - zephyr_compile_definitions("MCUBOOT_SLOT1_EXPECTED_ERASE_SIZE=${erase_size_slot1}") + if(DEFINED write_size_slot1) + zephyr_compile_definitions("MCUBOOT_SLOT1_EXPECTED_WRITE_SIZE=${write_size_slot1}") + endif() endif() endif() @@ -432,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 From 54ec0fc7c1403c68f6404a133a25c8ff3449e717 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 24 Sep 2024 10:12:08 +0100 Subject: [PATCH 3/3] docs: release-notes: Add note on erase/write block size checking Adds notes on these new features Signed-off-by: Jamie McCrae --- docs/release-notes.d/compatible-slots.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/release-notes.d/compatible-slots.md 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.