Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boot: zephyr: Add check for unexpected flash sector size #2059

Merged
merged 3 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions boot/bootutil/src/swap_move.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
13 changes: 13 additions & 0 deletions boot/bootutil/src/swap_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
52 changes: 40 additions & 12 deletions boot/zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand Down
50 changes: 50 additions & 0 deletions boot/zephyr/flash_check.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/kernel.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/flash.h>

#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
7 changes: 7 additions & 0 deletions docs/release-notes.d/compatible-slots.md
Original file line number Diff line number Diff line change
@@ -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.
Loading