@@ -84,6 +84,28 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr);
8484#include "bootutil/key_revocation.h"
8585#endif
8686
87+ #ifdef CONFIG_PARTITION_MANAGER_ENABLED
88+ #define THREE_CAT (a , b , c ) (a##b##c)
89+ #ifndef CONFIG_NCS_IS_VARIANT_IMAGE
90+ /* Running from slot 0 */
91+ #define NCS_VARIANT_SLOT_ID 0
92+ #else /* CONFIG_NCS_IS_VARIANT_IMAGE */
93+ /* Running from slot 1 */
94+ #define NCS_VARIANT_SLOT_ID 1
95+ #endif /* CONFIG_NCS_IS_VARIANT_IMAGE */
96+
97+ #define SLOT_MIN_ADDR THREE_CAT(PM_S, NCS_VARIANT_SLOT_ID, _ADDRESS)
98+ #define SLOT_MAX_ADDR (SLOT_MIN_ADDR + THREE_CAT(PM_S, NCS_VARIANT_SLOT_ID, _SIZE)
99+
100+ #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER == -1
101+ #define CHECK_MCUBOOT_IMAGE 0
102+ #else
103+ #define CHECK_MCUBOOT_IMAGE 1
104+ #endif
105+
106+ #undef THREE_CAT
107+ #endif /* CONFIG_PARTITION_MANAGER_ENABLED */
108+
87109BOOT_LOG_MODULE_DECLARE (mcuboot );
88110
89111static struct boot_loader_state boot_data ;
@@ -1150,12 +1172,15 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
11501172 goto out ;
11511173 }
11521174
1153- #if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES ) && defined(MCUBOOT_VERIFY_IMG_ADDRESS )
1175+ #if MCUBOOT_IMAGE_NUMBER > 1 && \
1176+ (!defined(MCUBOOT_ENC_IMAGES ) || defined(CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS )) && \
1177+ defined(MCUBOOT_VERIFY_IMG_ADDRESS )
11541178 /* Verify that the image in the secondary slot has a reset address
11551179 * located in the primary slot. This is done to avoid users incorrectly
11561180 * overwriting an application written to the incorrect slot.
11571181 * This feature is only supported by ARM platforms.
11581182 */
1183+
11591184#if MCUBOOT_IMAGE_NUMBER >= 3
11601185 /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is
11611186 * designated for XIP, where it is the second part of image stored in slots of image
@@ -1167,58 +1192,72 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
11671192 }
11681193#endif
11691194 if (fap == BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY )) {
1170- const struct flash_area * pri_fa = BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY );
11711195 struct image_header * secondary_hdr = boot_img_hdr (state , slot );
1172- uint32_t reset_value = 0 ;
1173- uint32_t reset_addr = secondary_hdr -> ih_hdr_size + sizeof (reset_value );
1174- uint32_t min_addr , max_addr ;
1196+ uint32_t internal_img_addr = 0 ; /* either the reset handler addres or the image beginning addres */
1197+ uint32_t min_addr ;
1198+ uint32_t max_addr ;
1199+ uint32_t offset = secondary_hdr -> ih_hdr_size + sizeof (internal_img_addr );
11751200 bool check_addresses = false;
11761201
1177- if (flash_area_read (fap , reset_addr , & reset_value , sizeof (reset_value )) != 0 ) {
1202+ min_addr = flash_area_get_off (BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY ));
1203+ max_addr = flash_area_get_size (BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY )) + min_addr ;
1204+
1205+ #ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS
1206+ internal_img_addr = secondary_hdr -> ih_load_addr ;
1207+ #else
1208+ /* Read reset vector from ARM vector table */
1209+ if (flash_area_read (fap , offset , & internal_img_addr , sizeof (internal_img_addr )) != 0 ) {
1210+ LOG_ERR ("Failed to read image load address" );
11781211 fih_rc = FIH_NO_BOOTABLE_IMAGE ;
11791212 goto out ;
11801213 }
1214+ #endif
1215+ BOOT_LOG_DBG ("Image %d expected load address 0x%x" , BOOT_CURR_IMG (state ), internal_img_addr );
11811216
1182- #ifdef PM_CPUNET_APP_ADDRESS
1217+ #ifdef CONFIG_PARTITION_MANAGER_ENABLED
11831218 /* The primary slot for the network core is emulated in RAM.
11841219 * Its flash_area hasn't got relevant boundaries.
11851220 * Therfore need to override its boundaries for the check.
11861221 */
1222+ #ifdef PM_CPUNET_APP_ADDRESS
11871223 if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER ) {
11881224 min_addr = PM_CPUNET_APP_ADDRESS ;
11891225 max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE ;
11901226 check_addresses = true;
1191- } else
1192- #endif
1193- #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1227+ }
1228+ #endif /* PM_CPUNET_APP_SIZE */
1229+
1230+ #if CHECK_MCUBOOT_IMAGE == 1
11941231 if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER ) {
1195- #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1196- min_addr = PM_S0_ADDRESS ;
1197- max_addr = (PM_S0_ADDRESS + PM_S0_SIZE );
1198- #else
1199- min_addr = PM_S1_ADDRESS ;
1200- max_addr = (PM_S1_ADDRESS + PM_S1_SIZE );
1201- #endif
1232+
1233+ LOG_DBG ("Image %d is another stage MCBoot image" , BOOT_CURR_IMG (state ));
1234+
1235+ min_addr = SLOT_MIN_ADDR ;
1236+ max_addr = SLOT_MAX_ADDR ;
12021237 check_addresses = true;
1203- } else
1204- #endif
1205- if ( BOOT_CURR_IMG ( state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
1238+ }
1239+ #endif /* CHECK_MCUBOOT_IMAGE */
1240+
12061241#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1207- #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1208- min_addr = MIN (pri_fa -> fa_off , PM_S0_ADDRESS );
1209- max_addr = MAX ((pri_fa -> fa_off + pri_fa -> fa_size ), (PM_S0_ADDRESS + PM_S0_SIZE ));
1210- #else
1211- min_addr = MIN (pri_fa -> fa_off , PM_S1_ADDRESS );
1212- max_addr = MAX ((pri_fa -> fa_off + pri_fa -> fa_size ), (PM_S1_ADDRESS + PM_S1_SIZE ));
1213- #endif
1214- #else
1215- min_addr = pri_fa -> fa_off ;
1216- max_addr = pri_fa -> fa_off + pri_fa -> fa_size ;
1217- #endif
1242+ if (CHECK_MCUBOOT_IMAGE && BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
1243+
1244+ LOG_DBG ("Image %d is application MCBoot image" , BOOT_CURR_IMG (state ));
1245+
1246+ if (CHECK_MCUBOOT_IMAGE ) {
1247+ min_addr = MIN (min_addr , SLOT_MIN_ADDR );
1248+ max_addr = MAX (max_addr , (SLOT_MAX_ADDR ));
1249+ }
12181250 check_addresses = true;
12191251 }
1252+ #endif
1253+ if (check_addresses == false) {
1254+ goto out ;
1255+ }
1256+ #endif /* CONFIG_PARTITION_MANAGER_ENABLED */
12201257
1221- if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr )) {
1258+ LOG_DBG ("Check 0x%x is within [min_addr, max_addr] = [0x%x, 0x%x)" ,
1259+ internal_img_addr , min_addr , max_addr );
1260+ if (internal_img_addr < min_addr || internal_img_addr >= max_addr ) {
12221261 BOOT_LOG_ERR ("Reset address of image in secondary slot is not in the primary slot" );
12231262 BOOT_LOG_ERR ("Erasing image from secondary slot" );
12241263
@@ -1232,6 +1271,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
12321271 fih_rc = FIH_NO_BOOTABLE_IMAGE ;
12331272 goto out ;
12341273 }
1274+ LOG_DBG ("Image %d validation OK" , BOOT_CURR_IMG (state ));
12351275 }
12361276#endif
12371277
@@ -1435,6 +1475,18 @@ static inline void sec_slot_cleanup_if_unusable(void)
14351475#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\
14361476 defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */
14371477
1478+ #define IS_IN_RANGE_CPUNET_APP_ADDR (_addr ) (((_addr) >= PM_CPUNET_APP_ADDRESS) && ((_addr) < PM_CPUNET_APP_END_ADDRESS))
1479+ #define _IS_IN_RANGE_S_VARIANT_ADDR (_addr , x ) (((_addr) >= PM_S##x##_ADDRESS) && ((_addr) <= (PM_S##x##_ADDRESS + PM_S##x##_SIZE)))
1480+ #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1481+ #define IS_IN_RANGE_S_ALTERNATE_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
1482+ #define IS_IN_RANGE_S_CURRENT_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
1483+ #else
1484+ #define IS_IN_RANGE_S_ALTERNATE_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
1485+ #define IS_IN_RANGE_S_CURRENT_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
1486+ #endif
1487+ #define IS_IN_RANGE_IMAGE_ADDR (_addr , _fa ) \
1488+ (((_addr) >= flash_area_get_off(_fa)) && (_addr) < (flash_area_get_off(_fa) + flash_area_get_size(_fa)))
1489+
14381490/**
14391491 * Determines which swap operation to perform, if any. If it is determined
14401492 * that a swap operation is required, the image in the secondary slot is checked
@@ -1458,8 +1510,9 @@ boot_validated_swap_type(struct boot_loader_state *state,
14581510 const struct flash_area * secondary_fa =
14591511 BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY );
14601512 struct image_header * hdr = boot_img_hdr (state , BOOT_SLOT_SECONDARY );
1461- uint32_t reset_addr = 0 ;
1513+ uint32_t internal_img_addr = 0 ; /* either the reset handler addres or the image beginning addres */
14621514 int rc = 0 ;
1515+
14631516 /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other
14641517 * B1 slot S0 or S1) share the same secondary slot, we need to check
14651518 * whether the update candidate in the secondary slot is intended for
@@ -1469,18 +1522,22 @@ boot_validated_swap_type(struct boot_loader_state *state,
14691522 */
14701523
14711524 if (hdr -> ih_magic == IMAGE_MAGIC ) {
1525+ #ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS
1526+ internal_img_addr = hdr -> ih_load_addr ;
1527+ #else
14721528 rc = flash_area_read (secondary_fa , hdr -> ih_hdr_size +
1473- sizeof (uint32_t ), & reset_addr ,
1474- sizeof (reset_addr ));
1529+ sizeof (uint32_t ), & internal_img_addr ,
1530+ sizeof (internal_img_addr ));
14751531 if (rc != 0 ) {
14761532 return BOOT_SWAP_TYPE_FAIL ;
14771533 }
1534+ #endif /* CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS */
14781535
14791536 sec_slot_touch (state );
14801537
14811538#ifdef PM_S1_ADDRESS
14821539#ifdef PM_CPUNET_B0N_ADDRESS
1483- if (!( reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS ))
1540+ if (!IS_IN_RANGE_CPUNET_APP_ADDR ( internal_img_addr ))
14841541#endif
14851542 {
14861543 const struct flash_area * primary_fa ;
@@ -1492,11 +1549,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
14921549 }
14931550
14941551 /* Check start and end of primary slot for current image */
1495- #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1496- if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE )) {
1497- #else
1498- if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE )) {
1499- #endif
1552+ if (IS_IN_RANGE_S_ALTERNATE_ADDR (internal_img_addr )) {
15001553 if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
15011554 /* This is not the s0/s1 upgrade image but the application image, pretend
15021555 * there is no image so the NSIB update can be loaded
@@ -1505,18 +1558,14 @@ boot_validated_swap_type(struct boot_loader_state *state,
15051558 }
15061559
15071560 owner_nsib [BOOT_CURR_IMG (state )] = true;
1508- #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1509- } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE )) {
1510- #else
1511- } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE )) {
1512- #endif
1561+ } else if (IS_IN_RANGE_S_CURRENT_ADDR (internal_img_addr )) {
15131562 /* NSIB upgrade but for the wrong slot, must be erased */
15141563 BOOT_LOG_ERR ("Image in slot is for wrong s0/s1 image" );
15151564 flash_area_erase (secondary_fa , 0 , secondary_fa -> fa_size );
15161565 sec_slot_untouch (state );
15171566 BOOT_LOG_ERR ("Cleaned-up secondary slot of image %d" , BOOT_CURR_IMG (state ));
15181567 return BOOT_SWAP_TYPE_FAIL ;
1519- } else if (reset_addr < primary_fa -> fa_off || reset_addr > ( primary_fa -> fa_off + primary_fa -> fa_size )) {
1568+ } else if (! IS_IN_RANGE_IMAGE_ADDR ( internal_img_addr , primary_fa )) {
15201569 /* The image in the secondary slot is not intended for any */
15211570 return BOOT_SWAP_TYPE_NONE ;
15221571 }
@@ -1553,8 +1602,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
15531602 * update and indicate to the caller of this function that no update is
15541603 * available
15551604 */
1556- if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS &&
1557- reset_addr < PM_CPUNET_APP_END_ADDRESS ) {
1605+ if (upgrade_valid && IS_IN_RANGE_CPUNET_APP_ADDR (internal_img_addr )) {
15581606 struct image_header * hdr = (struct image_header * )secondary_fa -> fa_off ;
15591607 uint32_t vtable_addr = (uint32_t )hdr + hdr -> ih_hdr_size ;
15601608 uint32_t * net_core_fw_addr = (uint32_t * )(vtable_addr );
0 commit comments