@ -15,6 +15,8 @@
@@ -15,6 +15,8 @@
# include <sys/__assert.h>
# include <sys/byteorder.h>
# include "bootutil/bootutil_public.h"
# include <dfu/mcuboot.h>
# include "mcuboot_priv.h"
@ -55,333 +57,6 @@ struct mcuboot_v1_raw_header {
@@ -55,333 +57,6 @@ struct mcuboot_v1_raw_header {
* End of strict defines
*/
# define BOOT_FLAG_IMAGE_OK 0
# define BOOT_FLAG_COPY_DONE 1
# define FLASH_MIN_WRITE_SIZE \
DT_PROP ( DT_CHOSEN ( zephyr_flash ) , write_block_size )
# ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
# define SWAP_TYPE_OFFS(bank_area) ((bank_area)->fa_size -\
BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3 )
# endif
# define COPY_DONE_OFFS(bank_area) ((bank_area)->fa_size -\
BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2 )
# define IMAGE_OK_OFFS(bank_area) ((bank_area)->fa_size - BOOT_MAGIC_SZ -\
BOOT_MAX_ALIGN )
# define MAGIC_OFFS(bank_area) ((bank_area)->fa_size - BOOT_MAGIC_SZ)
# if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
static const uint32_t boot_img_magic [ 4 ] = {
0xf395c277 ,
0x7fefd260 ,
0x0f505235 ,
0x8079b62c ,
} ;
# define BOOT_MAGIC_ARR_SZ ARRAY_SIZE(boot_img_magic)
# endif
struct boot_swap_table {
/** For each field, a value of 0 means "any". */
uint8_t magic_primary_slot ;
uint8_t magic_secondary_slot ;
uint8_t image_ok_primary_slot ;
uint8_t image_ok_secondary_slot ;
uint8_t copy_done_primary_slot ;
uint8_t swap_type ;
} ;
# ifdef FLASH_AREA_IMAGE_SECONDARY
/**
* This set of tables maps image trailer contents to swap operation type .
* When searching for a match , these tables must be iterated sequentially .
*
* NOTE : the table order is very important . The settings in the secondary
* slot always are priority to the primary slot and should be located
* earlier in the table .
*
* The table lists only states where there is action needs to be taken by
* the bootloader , as in starting / finishing a swap operation .
*/
static const struct boot_swap_table boot_swap_tables [ ] = {
{
/* | slot-0 | slot-1 |
* - - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - |
* magic | Any | Good |
* image - ok | Any | Unset |
* - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - +
* swap : test |
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '
*/
. magic_primary_slot = BOOT_MAGIC_ANY ,
. magic_secondary_slot = BOOT_MAGIC_GOOD ,
. image_ok_primary_slot = BOOT_FLAG_ANY ,
. image_ok_secondary_slot = BOOT_FLAG_UNSET ,
. copy_done_primary_slot = BOOT_FLAG_ANY ,
. swap_type = BOOT_SWAP_TYPE_TEST ,
} ,
{
/* | slot-0 | slot-1 |
* - - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - |
* magic | Any | Good |
* image - ok | Any | 0x01 |
* - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - +
* swap : permanent |
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '
*/
. magic_primary_slot = BOOT_MAGIC_ANY ,
. magic_secondary_slot = BOOT_MAGIC_GOOD ,
. image_ok_primary_slot = BOOT_FLAG_ANY ,
. image_ok_secondary_slot = BOOT_FLAG_SET ,
. copy_done_primary_slot = BOOT_FLAG_ANY ,
. swap_type = BOOT_SWAP_TYPE_PERM ,
} ,
{
/* | slot-0 | slot-1 |
* - - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - |
* magic | Good | Unset |
* image - ok | Unset | Any |
* - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - +
* swap : revert ( test image running ) |
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '
*/
. magic_primary_slot = BOOT_MAGIC_GOOD ,
. magic_secondary_slot = BOOT_MAGIC_UNSET ,
. image_ok_primary_slot = BOOT_FLAG_UNSET ,
. image_ok_secondary_slot = BOOT_FLAG_ANY ,
. copy_done_primary_slot = BOOT_FLAG_SET ,
. swap_type = BOOT_SWAP_TYPE_REVERT ,
} ,
} ;
# define BOOT_SWAP_TABLES_COUNT (ARRAY_SIZE(boot_swap_tables))
# endif
# if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
static int boot_magic_decode ( const uint32_t * magic )
{
if ( memcmp ( magic , boot_img_magic , BOOT_MAGIC_SZ ) = = 0 ) {
return BOOT_MAGIC_GOOD ;
}
return BOOT_MAGIC_BAD ;
}
static int boot_flag_decode ( uint8_t flag )
{
if ( flag ! = BOOT_FLAG_SET ) {
return BOOT_FLAG_BAD ;
}
return BOOT_FLAG_SET ;
}
# endif
# if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
int flash_area_read_is_empty ( const struct flash_area * fa , uint32_t off ,
void * dst , uint32_t len )
{
const uint8_t erase_val = flash_area_erased_val ( fa ) ;
uint8_t * u8dst ;
uint8_t i ;
int rc ;
rc = flash_area_read ( fa , off , dst , len ) ;
if ( rc ) {
return rc ;
}
for ( i = 0 , u8dst = ( uint8_t * ) dst ; i < len ; i + + ) {
if ( u8dst [ i ] ! = erase_val ) {
return 0 ;
}
}
return 1 ;
}
# endif
static int erased_flag_val ( uint8_t bank_id )
{
const struct flash_area * fa ;
int rc ;
rc = flash_area_open ( bank_id , & fa ) ;
if ( rc ) {
return - EINVAL ;
}
return flash_area_erased_val ( fa ) ;
}
# if !defined(CONFIG_BOOTLOADER_MCUBOOT) && !defined(CONFIG_ZTEST)
/* Provided by MCUBoot */
int boot_magic_compatible_check ( uint8_t tbl_val , uint8_t val ) ;
# else
/**
* Determines if a status source table is satisfied by the specified magic
* code .
*
* @ param tbl_val A magic field from a status source table .
* @ param val The magic value in a trailer , encoded as a
* BOOT_MAGIC_ [ . . . ] .
*
* @ return 1 if the two values are compatible ;
* 0 otherwise .
*/
int boot_magic_compatible_check ( uint8_t tbl_val , uint8_t val )
{
switch ( tbl_val ) {
case BOOT_MAGIC_ANY :
return 1 ;
case BOOT_MAGIC_NOTGOOD :
return val ! = BOOT_MAGIC_GOOD ;
default :
return tbl_val = = val ;
}
}
# endif
static int boot_flag_offs ( int flag , const struct flash_area * fa , uint32_t * offs )
{
switch ( flag ) {
case BOOT_FLAG_COPY_DONE :
* offs = COPY_DONE_OFFS ( fa ) ;
return 0 ;
case BOOT_FLAG_IMAGE_OK :
* offs = IMAGE_OK_OFFS ( fa ) ;
return 0 ;
default :
return - ENOTSUP ;
}
}
static int boot_write_trailer_byte ( const struct flash_area * fa , uint32_t off ,
uint8_t val )
{
uint8_t buf [ BOOT_MAX_ALIGN ] ;
uint8_t align ;
uint8_t erased_val ;
int rc ;
align = flash_area_align ( fa ) ;
__ASSERT_NO_MSG ( align < = BOOT_MAX_ALIGN ) ;
erased_val = flash_area_erased_val ( fa ) ;
memset ( buf , erased_val , BOOT_MAX_ALIGN ) ;
buf [ 0 ] = val ;
rc = flash_area_write ( fa , off , buf , align ) ;
if ( rc ! = 0 ) {
return - EIO ;
}
return 0 ;
}
static int boot_flag_write ( int flag , uint8_t bank_id )
{
const struct flash_area * fa ;
uint32_t offs ;
int rc ;
rc = flash_area_open ( bank_id , & fa ) ;
if ( rc ) {
return rc ;
}
rc = boot_flag_offs ( flag , fa , & offs ) ;
if ( rc ! = 0 ) {
flash_area_close ( fa ) ;
return rc ;
}
rc = boot_write_trailer_byte ( fa , offs , BOOT_FLAG_SET ) ;
flash_area_close ( fa ) ;
return rc ;
}
static int boot_flag_read ( int flag , uint8_t bank_id )
{
const struct flash_area * fa ;
uint32_t offs ;
int rc ;
uint8_t flag_val ;
rc = flash_area_open ( bank_id , & fa ) ;
if ( rc ) {
return rc ;
}
rc = boot_flag_offs ( flag , fa , & offs ) ;
if ( rc ! = 0 ) {
flash_area_close ( fa ) ;
return rc ;
}
rc = flash_area_read ( fa , offs , & flag_val , sizeof ( flag_val ) ) ;
if ( rc ! = 0 ) {
return rc ;
}
return flag_val ;
}
static int boot_image_ok_read ( uint8_t bank_id )
{
return boot_flag_read ( BOOT_FLAG_IMAGE_OK , bank_id ) ;
}
static int boot_image_ok_write ( uint8_t bank_id )
{
return boot_flag_write ( BOOT_FLAG_IMAGE_OK , bank_id ) ;
}
# ifdef FLASH_AREA_IMAGE_SECONDARY
static int boot_magic_write ( uint8_t bank_id )
{
const struct flash_area * fa ;
uint32_t offs ;
int rc ;
rc = flash_area_open ( bank_id , & fa ) ;
if ( rc ) {
return rc ;
}
offs = MAGIC_OFFS ( fa ) ;
rc = flash_area_write ( fa , offs , boot_img_magic , BOOT_MAGIC_SZ ) ;
flash_area_close ( fa ) ;
return rc ;
}
# ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
static int boot_swap_type_write ( uint8_t bank_id , uint8_t swap_type )
{
const struct flash_area * fa ;
uint32_t offs ;
int rc ;
rc = flash_area_open ( bank_id , & fa ) ;
if ( rc ) {
return rc ;
}
offs = SWAP_TYPE_OFFS ( fa ) ;
rc = boot_write_trailer_byte ( fa , offs , swap_type ) ;
flash_area_close ( fa ) ;
return rc ;
}
# endif /* CONFIG_MCUBOOT_TRAILER_SWAP_TYPE */
# endif /* FLASH_AREA_IMAGE_SECONDARY */
static int boot_read_v1_header ( uint8_t area_id ,
struct mcuboot_v1_raw_header * v1_raw )
{
@ -469,221 +144,58 @@ int boot_read_bank_header(uint8_t area_id,
@@ -469,221 +144,58 @@ int boot_read_bank_header(uint8_t area_id,
return 0 ;
}
# if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
static int boot_read_swap_state ( const struct flash_area * fa ,
struct boot_swap_state * state )
int mcuboot_swap_type ( void )
{
uint32_t magic [ BOOT_MAGIC_ARR_SZ ] ;
uint32_t off ;
int rc ;
off = MAGIC_OFFS ( fa ) ;
rc = flash_area_read_is_empty ( fa , off , magic , BOOT_MAGIC_SZ ) ;
if ( rc < 0 ) {
return - EIO ;
}
if ( rc = = 1 ) {
state - > magic = BOOT_MAGIC_UNSET ;
} else {
state - > magic = boot_magic_decode ( magic ) ;
}
# ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
off = SWAP_TYPE_OFFS ( fa ) ;
rc = flash_area_read_is_empty ( fa , off , & state - > swap_type ,
sizeof ( state - > swap_type ) ) ;
if ( rc < 0 ) {
return - EIO ;
}
if ( rc = = 1 | | state - > swap_type > BOOT_SWAP_TYPE_REVERT ) {
state - > swap_type = BOOT_SWAP_TYPE_NONE ;
}
off = COPY_DONE_OFFS ( fa ) ;
rc = flash_area_read_is_empty ( fa , off , & state - > copy_done ,
sizeof ( state - > copy_done ) ) ;
if ( rc < 0 ) {
return - EIO ;
}
if ( rc = = 1 ) {
state - > copy_done = BOOT_FLAG_UNSET ;
} else {
state - > copy_done = boot_flag_decode ( state - > copy_done ) ;
}
# ifdef FLASH_AREA_IMAGE_SECONDARY
return boot_swap_type ( ) ;
# else
# ifdef FLASH_AREA_IMAGE_SCRATCH
if ( fa - > fa_id ! = FLASH_AREA_IMAGE_SCRATCH ) {
# endif
off = COPY_DONE_OFFS ( fa ) ;
rc = flash_area_read_is_empty ( fa , off , & state - > copy_done ,
sizeof ( state - > copy_done ) ) ;
if ( rc < 0 ) {
return - EIO ;
}
if ( rc = = 1 ) {
state - > copy_done = BOOT_FLAG_UNSET ;
} else {
state - > copy_done = boot_flag_decode ( state - > copy_done ) ;
}
# ifdef FLASH_AREA_IMAGE_SCRATCH
}
# endif
return BOOT_SWAP_TYPE_NONE ;
# endif
off = IMAGE_OK_OFFS ( fa ) ;
rc = flash_area_read_is_empty ( fa , off , & state - > image_ok ,
sizeof ( state - > image_ok ) ) ;
if ( rc < 0 ) {
return - EIO ;
}
if ( rc = = 1 ) {
state - > image_ok = BOOT_FLAG_UNSET ;
} else {
state - > image_ok = boot_flag_decode ( state - > image_ok ) ;
}
return 0 ;
}
# endif
# if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
/**
* Reads the image trailer from the scratch area .
*/
int
boot_read_swap_state_by_id ( int flash_area_id , struct boot_swap_state * state )
{
const struct flash_area * fap ;
int rc ;
switch ( flash_area_id ) {
# ifdef FLASH_AREA_IMAGE_SCRATCH
case FLASH_AREA_IMAGE_SCRATCH :
# endif
case FLASH_AREA_IMAGE_PRIMARY :
# ifdef FLASH_AREA_IMAGE_SECONDARY
case FLASH_AREA_IMAGE_SECONDARY :
# endif
rc = flash_area_open ( flash_area_id , & fap ) ;
if ( rc ! = 0 ) {
return - EIO ;
}
break ;
default :
return - EINVAL ;
}
rc = boot_read_swap_state ( fap , state ) ;
flash_area_close ( fap ) ;
return rc ;
}
# endif
/* equivalent of boot_swap_type() in mcuboot bootutil_misc.c */
int mcuboot_swap_type ( void )
int boot_request_upgrade ( int permanent )
{
# ifdef FLASH_AREA_IMAGE_SECONDARY
const struct boot_swap_table * table ;
struct boot_swap_state primary_slot ;
struct boot_swap_state secondary_slot ;
int rc ;
size_t i ;
rc = boot_read_swap_state_by_id ( FLASH_AREA_IMAGE_PRIMARY ,
& primary_slot ) ;
rc = boot_set_pending ( permanent ) ;
if ( rc ) {
return rc ;
return - EFAULT ;
}
rc = boot_read_swap_state_by_id ( FLASH_AREA_IMAGE_SECONDARY ,
& secondary_slot ) ;
if ( rc ) {
return rc ;
}
for ( i = 0 ; i < BOOT_SWAP_TABLES_COUNT ; i + + ) {
table = boot_swap_tables + i ;
if ( boot_magic_compatible_check ( table - > magic_primary_slot ,
primary_slot . magic )
& &
boot_magic_compatible_check ( table - > magic_secondary_slot ,
secondary_slot . magic )
& &
( table - > image_ok_primary_slot = = BOOT_FLAG_ANY | |
table - > image_ok_primary_slot = = primary_slot . image_ok )
& &
( table - > image_ok_secondary_slot = = BOOT_FLAG_ANY | |
table - > image_ok_secondary_slot = = secondary_slot . image_ok )
& &
( table - > copy_done_primary_slot = = BOOT_FLAG_ANY | |
table - > copy_done_primary_slot = = primary_slot . copy_done ) ) {
__ASSERT_NO_MSG ( table - > swap_type = = BOOT_SWAP_TYPE_TEST | |
table - > swap_type = = BOOT_SWAP_TYPE_PERM | |
table - > swap_type = = BOOT_SWAP_TYPE_REVERT ) ;
return table - > swap_type ;
}
}
# endif
return BOOT_SWAP_TYPE_NONE ;
# endif /* FLASH_AREA_IMAGE_SECONDARY */
return 0 ;
}
int boot_request_upgrade ( int permanent )
bool boot_is_img_confirmed ( void )
{
# ifdef FLASH_AREA_IMAGE_SECONDARY
# ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
uint8_t swap_type ;
# endif
const struct flash_area * fa ;
int rc ;
uint8_t flag_val ;
rc = boot_magic_write ( FLASH_AREA_IMAGE_SECONDARY ) ;
rc = flash_area_open ( FLASH_AREA_IMAGE_PRIMARY , & fa ) ;
if ( rc ) {
goto op_end ;
return false ;
}
if ( permanent ) {
rc = boot_image_ok_write ( FLASH_AREA_IMAGE_SECONDARY ) ;
# ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
if ( rc ) {
goto op_end ;
}
swap_type = BOOT_SWAP_TYPE_PERM ;
} else {
swap_type = BOOT_SWAP_TYPE_TEST ;
rc = boot_read_image_ok ( fa , & flag_val ) ;
if ( rc ) {
return false ;
}
rc = boot_swap_type_write ( FLASH_AREA_IMAGE_SECONDARY , swap_type ) ;
# else
}
# endif
op_end :
return rc ;
# else
return 0 ;
# endif /* FLASH_AREA_IMAGE_SECONDARY */
}
bool boot_is_img_confirmed ( void )
{
return boot_image_ok_read ( FLASH_AREA_IMAGE_PRIMARY ) = = BOOT_FLAG_SET ;
return flag_val = = BOOT_FLAG_SET ;
}
int boot_write_img_confirmed ( void )
{
int rc ;
if ( boot_image_ok_read ( FLASH_AREA_IMAGE_PRIMARY ) ! =
erased_flag_val ( FLASH_AREA_IMAGE_PRIMARY ) ) {
/* Already confirmed. */
return 0 ;
rc = boot_set_confirmed ( ) ;
if ( rc ) {
return - EIO ;
}
rc = boot_image_ok_write ( FLASH_AREA_IMAGE_PRIMARY ) ;
return rc ;
return 0 ;
}
int boot_erase_img_bank ( uint8_t area_id )