@ -1,19 +1,24 @@
@@ -1,19 +1,24 @@
/*
* Copyright ( c ) 2017 , 2020 Nordic Semiconductor ASA
* Copyright ( c ) 2017 - 2025 Nordic Semiconductor ASA
* Copyright ( c ) 2017 Linaro Limited
* Copyright ( c ) 2020 Gerson Fernando Budke < nandojve @ gmail . com >
*
* SPDX - License - Identifier : Apache - 2.0
*/
# include <zephyr/types.h>
# include <assert.h>
# include <stddef.h>
# include <stdio.h>
# include <string.h>
# include <zephyr/logging/log.h>
# include <zephyr/dfu/mcuboot.h>
# include <zephyr/dfu/flash_img.h>
# include <zephyr/dfu/mcuboot.h>
# include <zephyr/storage/flash_map.h>
# include <zephyr/storage/stream_flash.h>
LOG_MODULE_REGISTER ( flash_img , CONFIG_IMG_MANAGER_LOG_LEVEL ) ;
# ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
# include <bootutil/bootutil_public.h>
# endif
@ -48,6 +53,9 @@ BUILD_ASSERT((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_WRITE_BLOCK_SIZE == 0),
@@ -48,6 +53,9 @@ BUILD_ASSERT((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_WRITE_BLOCK_SIZE == 0),
" FLASH_WRITE_BLOCK_SIZE " ) ;
# endif
# define FLASH_CHECK_ERASED_BUFFER_SIZE 16
# define ERASED_VAL_32(x) (((x) << 24) | ((x) << 16) | ((x) << 8) | (x))
static int scramble_mcuboot_trailer ( struct flash_img_context * ctx )
{
int rc = 0 ;
@ -132,10 +140,64 @@ size_t flash_img_bytes_written(struct flash_img_context *ctx)
@@ -132,10 +140,64 @@ size_t flash_img_bytes_written(struct flash_img_context *ctx)
return stream_flash_bytes_written ( & ctx - > stream ) ;
}
# if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET)
/**
* Determines if the specified area of flash is completely unwritten .
*
* @ param fa pointer to flash area to scan
*
* @ return 0 when not empty , 1 when empty , negative errno code on error .
*/
static int flash_check_erased ( const struct flash_area * fa )
{
uint32_t data [ FLASH_CHECK_ERASED_BUFFER_SIZE ] ;
off_t addr ;
off_t end ;
int bytes_to_read ;
int rc ;
int i ;
uint8_t erased_val ;
uint32_t erased_val_32 ;
assert ( fa - > fa_size % sizeof ( erased_val_32 ) = = 0 ) ;
erased_val = flash_area_erased_val ( fa ) ;
erased_val_32 = ERASED_VAL_32 ( erased_val ) ;
end = fa - > fa_size ;
for ( addr = 0 ; addr < end ; addr + = sizeof ( data ) ) {
if ( end - addr < sizeof ( data ) ) {
bytes_to_read = end - addr ;
} else {
bytes_to_read = sizeof ( data ) ;
}
rc = flash_area_read ( fa , addr , data , bytes_to_read ) ;
if ( rc < 0 ) {
LOG_ERR ( " Failed to read data from flash area: %d " , rc ) ;
return rc ;
}
for ( i = 0 ; i < bytes_to_read / sizeof ( erased_val_32 ) ; i + + ) {
if ( data [ i ] ! = erased_val_32 ) {
return 0 ;
}
}
}
return 1 ;
}
# endif
int flash_img_init_id ( struct flash_img_context * ctx , uint8_t area_id )
{
int rc ;
const struct device * flash_dev ;
# if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET)
uint32_t sector_count = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN ;
struct flash_sector sector_data ;
# endif
rc = flash_area_open ( area_id ,
( const struct flash_area * * ) & ( ctx - > flash_area ) ) ;
@ -145,9 +207,45 @@ int flash_img_init_id(struct flash_img_context *ctx, uint8_t area_id)
@@ -145,9 +207,45 @@ int flash_img_init_id(struct flash_img_context *ctx, uint8_t area_id)
flash_dev = flash_area_get_device ( ctx - > flash_area ) ;
# if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET)
/* Query size of first sector in flash for upgrade slot, so it can be erased, and begin
* upload started at the second sector
*/
rc = flash_area_sectors ( ( const struct flash_area * ) ctx - > flash_area , & sector_count ,
& sector_data ) ;
if ( rc & & rc ! = - ENOMEM ) {
flash_area_close ( ctx - > flash_area ) ;
ctx - > flash_area = NULL ;
return rc ;
} else if ( sector_count ! = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN ) {
flash_area_close ( ctx - > flash_area ) ;
ctx - > flash_area = NULL ;
return - ENOENT ;
}
if ( ! flash_check_erased ( ( const struct flash_area * ) ctx - > flash_area ) ) {
/* Flash is not empty, therefore flatten/erase the area to prevent issues when
* the firmware update process begins
*/
rc = flash_area_flatten ( ( const struct flash_area * ) ctx - > flash_area , 0 ,
sector_data . fs_size ) ;
if ( rc ) {
flash_area_close ( ctx - > flash_area ) ;
ctx - > flash_area = NULL ;
return rc ;
}
}
return stream_flash_init ( & ctx - > stream , flash_dev , ctx - > buf , CONFIG_IMG_BLOCK_BUF_SIZE ,
( ctx - > flash_area - > fa_off + sector_data . fs_size ) ,
( ctx - > flash_area - > fa_size - sector_data . fs_size ) , NULL ) ;
# else
return stream_flash_init ( & ctx - > stream , flash_dev , ctx - > buf ,
CONFIG_IMG_BLOCK_BUF_SIZE , ctx - > flash_area - > fa_off ,
ctx - > flash_area - > fa_size , NULL ) ;
# endif
}
# ifdef CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD
@ -194,7 +292,7 @@ int flash_img_check(struct flash_img_context *ctx,
@@ -194,7 +292,7 @@ int flash_img_check(struct flash_img_context *ctx,
fac . match = fic - > match ;
fac . clen = fic - > clen ;
fac . off = 0 ;
fac . off = boot_get_image_start_offset ( area_id ) ;
fac . rbuf = ctx - > buf ;
fac . rblen = sizeof ( ctx - > buf ) ;