@@ -88,6 +88,57 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr);
8888void s2ram_designate_slot (uint8_t slot );
8989#endif
9090
91+ #ifdef CONFIG_PARTITION_MANAGER_ENABLED
92+ #define THREE_CAT_ (a , b , c ) (a##b##c)
93+ #define THREE_CAT (a , b , c ) THREE_CAT_(a, b, c)
94+
95+ /* Current S0/S1 slot macros.
96+ * These macros are used to generate min/max address of the alternate,
97+ * potential DFU target, Sx slot from the running one.
98+ */
99+ #ifdef CONFIG_NCS_IS_VARIANT_IMAGE
100+ /* Running from slot 1, checking slot 0 */
101+ #define NCS_VARIANT_SLOT_ID 0
102+ #else /* CONFIG_NCS_IS_VARIANT_IMAGE */
103+ /* Running from slot 0, checking slot 1 */
104+ #define NCS_VARIANT_SLOT_ID 1
105+ #endif /* CONFIG_NCS_IS_VARIANT_IMAGE */
106+
107+ #define NCS_VARIANT_SLOT_MIN_ADDR THREE_CAT(PM_S, NCS_VARIANT_SLOT_ID, _ADDRESS)
108+ #define NCS_VARIANT_SLOT_MAX_ADDR ((NCS_VARIANT_SLOT_MIN_ADDR) + THREE_CAT(PM_S, NCS_VARIANT_SLOT_ID, _SIZE))
109+ /* End: Current S0/S1 slot macros */
110+
111+ #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER == -1
112+ #define CHECK_MCUBOOT_IMAGE 0
113+ #else
114+ #define CHECK_MCUBOOT_IMAGE 1
115+ #endif
116+
117+ /* PM partition check macros.
118+ * These macros are universal, regardles of slot the MCUboot is called from
119+ * and may be invoked to figure out to which area given address belongs to.
120+ */
121+
122+ /* Net core address check */
123+ #define IS_IN_RANGE_CPUNET_APP_ADDR (_addr ) (((_addr) >= PM_CPUNET_APP_ADDRESS) && ((_addr) < PM_CPUNET_APP_END_ADDRESS))
124+
125+ /* Current/alternate Sx slot check macros */
126+ #define _IS_IN_RANGE_S_VARIANT_ADDR (_addr , x ) (((_addr) >= PM_S##x##_ADDRESS) && ((_addr) < (PM_S##x##_ADDRESS + PM_S##x##_SIZE)))
127+ #if defined(CONFIG_NCS_IS_VARIANT_IMAGE )
128+ #define IS_IN_RANGE_S_ALTERNATE_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
129+ #define IS_IN_RANGE_S_CURRENT_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
130+ #else
131+ #define IS_IN_RANGE_S_ALTERNATE_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
132+ #define IS_IN_RANGE_S_CURRENT_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
133+ #endif
134+
135+ /* Application image partition check */
136+ #define IS_IN_RANGE_IMAGE_ADDR (_addr , _fa ) \
137+ (((_addr) >= flash_area_get_off(_fa)) && (_addr) < (flash_area_get_off(_fa) + flash_area_get_size(_fa)))
138+ /* End: PM partition check macros */
139+
140+ #endif /* CONFIG_PARTITION_MANAGER_ENABLED */
141+
91142BOOT_LOG_MODULE_DECLARE (mcuboot );
92143
93144static struct boot_loader_state boot_data ;
@@ -1154,7 +1205,8 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
11541205 goto out ;
11551206 }
11561207
1157- #if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES ) && defined(MCUBOOT_VERIFY_IMG_ADDRESS )
1208+ #if defined(MCUBOOT_VERIFY_IMG_ADDRESS ) && !defined(MCUBOOT_ENC_IMAGES ) || \
1209+ defined(CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS )
11581210 /* Verify that the image in the secondary slot has a reset address
11591211 * located in the primary slot. This is done to avoid users incorrectly
11601212 * overwriting an application written to the incorrect slot.
@@ -1171,58 +1223,72 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
11711223 }
11721224#endif
11731225 if (fap == BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY )) {
1174- const struct flash_area * pri_fa = BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY );
11751226 struct image_header * secondary_hdr = boot_img_hdr (state , slot );
1176- uint32_t reset_value = 0 ;
1177- uint32_t reset_addr = secondary_hdr -> ih_hdr_size + sizeof (reset_value );
1178- uint32_t min_addr , max_addr ;
1179- bool check_addresses = false;
1227+ uint32_t internal_img_addr = 0 ; /* either the reset handler addres or the image beginning address */
1228+ uint32_t min_addr ;
1229+ uint32_t max_addr ;
1230+
1231+ min_addr = flash_area_get_off (BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY ));
1232+ max_addr = flash_area_get_size (BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY )) + min_addr ;
11801233
1181- if (flash_area_read (fap , reset_addr , & reset_value , sizeof (reset_value )) != 0 ) {
1234+ #ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS
1235+ internal_img_addr = secondary_hdr -> ih_load_addr ;
1236+ #else
1237+ const uint32_t offset = secondary_hdr -> ih_hdr_size + sizeof (internal_img_addr );
1238+ BOOT_LOG_DBG ("Getting image %d internal addr from offset %u" ,
1239+ BOOT_CURR_IMG (state ), offset );
1240+ /* Read reset vector from ARM vector table */
1241+ if (flash_area_read (fap , offset , & internal_img_addr , sizeof (internal_img_addr )) != 0 ) {
1242+ BOOT_LOG_ERR ("Failed to read image %d load address" , BOOT_CURR_IMG (state ));
11821243 fih_rc = FIH_NO_BOOTABLE_IMAGE ;
11831244 goto out ;
11841245 }
1246+ #endif
1247+ BOOT_LOG_DBG ("Image %d expected load address 0x%x" , BOOT_CURR_IMG (state ), internal_img_addr );
11851248
1186- #ifdef PM_CPUNET_APP_ADDRESS
1249+ #ifdef CONFIG_PARTITION_MANAGER_ENABLED
11871250 /* The primary slot for the network core is emulated in RAM.
11881251 * Its flash_area hasn't got relevant boundaries.
11891252 * Therfore need to override its boundaries for the check.
11901253 */
1254+ #ifdef PM_CPUNET_APP_ADDRESS
11911255 if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER ) {
1256+
1257+ BOOT_LOG_DBG ("Image %d is NETCORE image" , BOOT_CURR_IMG (state ));
1258+
11921259 min_addr = PM_CPUNET_APP_ADDRESS ;
11931260 max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE ;
1194- check_addresses = true;
1195- } else
1196- #endif
1197- #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != - 1
1261+ }
1262+ #endif /* PM_CPUNET_APP_SIZE */
1263+
1264+ #if CHECK_MCUBOOT_IMAGE == 1
11981265 if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER ) {
1199- #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1200- min_addr = PM_S0_ADDRESS ;
1201- max_addr = (PM_S0_ADDRESS + PM_S0_SIZE );
1202- #else
1203- min_addr = PM_S1_ADDRESS ;
1204- max_addr = (PM_S1_ADDRESS + PM_S1_SIZE );
1205- #endif
1206- check_addresses = true;
1207- } else
1208- #endif
1266+
1267+ BOOT_LOG_DBG ("Image %d is another stage MCBoot image" , BOOT_CURR_IMG (state ));
1268+
1269+ min_addr = NCS_VARIANT_SLOT_MIN_ADDR ;
1270+ max_addr = NCS_VARIANT_SLOT_MAX_ADDR ;
1271+ }
1272+ #endif /* CHECK_MCUBOOT_IMAGE */
1273+
1274+ #if CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1
12091275 if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
1210- #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1211- #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1212- min_addr = MIN (pri_fa -> fa_off , PM_S0_ADDRESS );
1213- max_addr = MAX ((pri_fa -> fa_off + pri_fa -> fa_size ), (PM_S0_ADDRESS + PM_S0_SIZE ));
1214- #else
1215- min_addr = MIN (pri_fa -> fa_off , PM_S1_ADDRESS );
1216- max_addr = MAX ((pri_fa -> fa_off + pri_fa -> fa_size ), (PM_S1_ADDRESS + PM_S1_SIZE ));
1217- #endif
1218- #else
1219- min_addr = pri_fa -> fa_off ;
1220- max_addr = pri_fa -> fa_off + pri_fa -> fa_size ;
1276+
1277+ BOOT_LOG_DBG ("Image %d is application MCBoot image" , BOOT_CURR_IMG (state ));
1278+
1279+ /* If not checking the MCUboot image, then we leave the original
1280+ * min/max assignments from the primary slot read. */
1281+ #if CHECK_MCUBOOT_IMAGE == 1
1282+ min_addr = MIN (min_addr , NCS_VARIANT_SLOT_MIN_ADDR );
1283+ max_addr = MAX (max_addr , NCS_VARIANT_SLOT_MAX_ADDR );
12211284#endif
1222- check_addresses = true;
12231285 }
1286+ #endif
1287+ #endif /* CONFIG_PARTITION_MANAGER_ENABLED */
12241288
1225- if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr )) {
1289+ BOOT_LOG_DBG ("Check 0x%x is within [min_addr, max_addr] = [0x%x, 0x%x)" ,
1290+ internal_img_addr , min_addr , max_addr );
1291+ if (internal_img_addr < min_addr || internal_img_addr >= max_addr ) {
12261292 BOOT_LOG_ERR ("Reset address of image in secondary slot is not in the primary slot" );
12271293 BOOT_LOG_ERR ("Erasing image from secondary slot" );
12281294
@@ -1236,6 +1302,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
12361302 fih_rc = FIH_NO_BOOTABLE_IMAGE ;
12371303 goto out ;
12381304 }
1305+ BOOT_LOG_DBG ("Image %d validation OK" , BOOT_CURR_IMG (state ));
12391306 }
12401307#endif
12411308
@@ -1462,8 +1529,9 @@ boot_validated_swap_type(struct boot_loader_state *state,
14621529 const struct flash_area * secondary_fa =
14631530 BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY );
14641531 struct image_header * hdr = boot_img_hdr (state , BOOT_SLOT_SECONDARY );
1465- uint32_t reset_addr = 0 ;
1532+ uint32_t internal_img_addr = 0 ; /* either the reset handler addres or the image beginning addres */
14661533 int rc = 0 ;
1534+
14671535 /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other
14681536 * B1 slot S0 or S1) share the same secondary slot, we need to check
14691537 * whether the update candidate in the secondary slot is intended for
@@ -1472,60 +1540,65 @@ boot_validated_swap_type(struct boot_loader_state *state,
14721540 * the swap info.
14731541 */
14741542
1543+ BOOT_LOG_DBG ("boot_validated_swap_type: current image %d" , BOOT_CURR_IMG (state ));
14751544 if (hdr -> ih_magic == IMAGE_MAGIC ) {
1545+ #ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS
1546+ internal_img_addr = hdr -> ih_load_addr ;
1547+ #else
14761548 rc = flash_area_read (secondary_fa , hdr -> ih_hdr_size +
1477- sizeof (uint32_t ), & reset_addr ,
1478- sizeof (reset_addr ));
1549+ sizeof (uint32_t ), & internal_img_addr ,
1550+ sizeof (internal_img_addr ));
14791551 if (rc != 0 ) {
14801552 return BOOT_SWAP_TYPE_FAIL ;
14811553 }
1554+ #endif /* CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS */
1555+ BOOT_LOG_DBG ("boot_validated_swap_type: check addr 0x%x" , internal_img_addr );
14821556
14831557 sec_slot_touch (state );
14841558
14851559#ifdef PM_S1_ADDRESS
14861560#ifdef PM_CPUNET_B0N_ADDRESS
1487- if (!( reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS ))
1561+ if (!IS_IN_RANGE_CPUNET_APP_ADDR ( internal_img_addr ))
14881562#endif
14891563 {
1490- const struct flash_area * primary_fa ;
1491- rc = flash_area_open (flash_area_id_from_multi_image_slot (
1492- BOOT_CURR_IMG (state ), BOOT_SLOT_PRIMARY ),
1493- & primary_fa );
1564+ const struct flash_area * primary_fa = BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY );
1565+ const uint32_t pfa_off = flash_area_get_off (primary_fa );
1566+
14941567 if (rc != 0 ) {
14951568 return BOOT_SWAP_TYPE_FAIL ;
14961569 }
14971570
14981571 /* Check start and end of primary slot for current image */
1499- #if ( CONFIG_NCS_IS_VARIANT_IMAGE )
1500- if ( reset_addr >= PM_S0_ADDRESS && reset_addr <= ( PM_S0_ADDRESS + PM_S0_SIZE )) {
1501- #else
1502- if (reset_addr >= PM_S1_ADDRESS && reset_addr <= ( PM_S1_ADDRESS + PM_S1_SIZE )) {
1503- #endif
1572+ BOOT_LOG_DBG ( "boot_validated_swap_type: S%d is alternative" , NCS_VARIANT_SLOT_ID );
1573+ BOOT_LOG_DBG ( "boot_validated_swap_type: S0 [0x%x, 0x%x)" , PM_S0_ADDRESS , PM_S0_ADDRESS + PM_S0_SIZE );
1574+ BOOT_LOG_DBG ( "boot_validated_swap_type: S1 [0x%x, 0x%x)" , PM_S1_ADDRESS , PM_S1_ADDRESS + PM_S1_SIZE );
1575+ if (IS_IN_RANGE_S_ALTERNATE_ADDR ( internal_img_addr )) {
1576+ BOOT_LOG_DBG ( "boot_validated_swap_type: matched alternative" );
15041577 if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
15051578 /* This is not the s0/s1 upgrade image but the application image, pretend
15061579 * there is no image so the NSIB update can be loaded
15071580 */
1581+ BOOT_LOG_DBG ("boot_validated_swap_type: ignoring application image" );
15081582 return BOOT_SWAP_TYPE_NONE ;
15091583 }
15101584
15111585 owner_nsib [BOOT_CURR_IMG (state )] = true;
1512- #if (CONFIG_NCS_IS_VARIANT_IMAGE )
1513- } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE )) {
1514- #else
1515- } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE )) {
1516- #endif
1586+ } else if (IS_IN_RANGE_S_CURRENT_ADDR (internal_img_addr )) {
15171587 /* NSIB upgrade but for the wrong slot, must be erased */
15181588 BOOT_LOG_ERR ("Image in slot is for wrong s0/s1 image" );
15191589 flash_area_erase (secondary_fa , 0 , secondary_fa -> fa_size );
15201590 sec_slot_untouch (state );
15211591 BOOT_LOG_ERR ("Cleaned-up secondary slot of image %d" , BOOT_CURR_IMG (state ));
15221592 return BOOT_SWAP_TYPE_FAIL ;
1523- } else if (reset_addr < primary_fa -> fa_off || reset_addr > ( primary_fa -> fa_off + primary_fa -> fa_size )) {
1593+ } else if (! IS_IN_RANGE_IMAGE_ADDR ( internal_img_addr , primary_fa )) {
15241594 /* The image in the secondary slot is not intended for any */
1595+ BOOT_LOG_DBG ("boot_validated_swap_type: no match" );
15251596 return BOOT_SWAP_TYPE_NONE ;
15261597 }
15271598
1528- if ((primary_fa -> fa_off == PM_S0_ADDRESS ) || (primary_fa -> fa_off == PM_S1_ADDRESS )) {
1599+ BOOT_LOG_DBG ("boot_validated_swap_type: matching primary slot offset to S0/S1" );
1600+ if ((pfa_off == PM_S0_ADDRESS ) || (pfa_off == PM_S1_ADDRESS )) {
1601+ BOOT_LOG_DBG ("boot_validated_swap_type: setting nsib ownership over image %d" , BOOT_CURR_IMG (state ));
15291602 owner_nsib [BOOT_CURR_IMG (state )] = true;
15301603 }
15311604 }
@@ -1557,8 +1630,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
15571630 * update and indicate to the caller of this function that no update is
15581631 * available
15591632 */
1560- if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS &&
1561- reset_addr < PM_CPUNET_APP_END_ADDRESS ) {
1633+ if (upgrade_valid && IS_IN_RANGE_CPUNET_APP_ADDR (internal_img_addr )) {
15621634 struct image_header * hdr = (struct image_header * )secondary_fa -> fa_off ;
15631635 uint32_t vtable_addr = (uint32_t )hdr + hdr -> ih_hdr_size ;
15641636 uint32_t * net_core_fw_addr = (uint32_t * )(vtable_addr );
0 commit comments