@@ -84,6 +84,28 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr);
84
84
#include "bootutil/key_revocation.h"
85
85
#endif
86
86
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
+
87
109
BOOT_LOG_MODULE_DECLARE (mcuboot );
88
110
89
111
static struct boot_loader_state boot_data ;
@@ -1150,12 +1172,15 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
1150
1172
goto out ;
1151
1173
}
1152
1174
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 )
1154
1178
/* Verify that the image in the secondary slot has a reset address
1155
1179
* located in the primary slot. This is done to avoid users incorrectly
1156
1180
* overwriting an application written to the incorrect slot.
1157
1181
* This feature is only supported by ARM platforms.
1158
1182
*/
1183
+
1159
1184
#if MCUBOOT_IMAGE_NUMBER >= 3
1160
1185
/* Currently the MCUboot can be configured for up to 3 image, where image number 2 is
1161
1186
* 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,
1167
1192
}
1168
1193
#endif
1169
1194
if (fap == BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY )) {
1170
- const struct flash_area * pri_fa = BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY );
1171
1195
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 );
1175
1200
bool check_addresses = false;
1176
1201
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" );
1178
1211
fih_rc = FIH_NO_BOOTABLE_IMAGE ;
1179
1212
goto out ;
1180
1213
}
1214
+ #endif
1215
+ BOOT_LOG_DBG ("Image %d expected load address 0x%x" , BOOT_CURR_IMG (state ), internal_img_addr );
1181
1216
1182
- #ifdef PM_CPUNET_APP_ADDRESS
1217
+ #ifdef CONFIG_PARTITION_MANAGER_ENABLED
1183
1218
/* The primary slot for the network core is emulated in RAM.
1184
1219
* Its flash_area hasn't got relevant boundaries.
1185
1220
* Therfore need to override its boundaries for the check.
1186
1221
*/
1222
+ #ifdef PM_CPUNET_APP_ADDRESS
1187
1223
if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER ) {
1188
1224
min_addr = PM_CPUNET_APP_ADDRESS ;
1189
1225
max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE ;
1190
1226
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
1194
1231
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 ;
1202
1237
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
+
1206
1241
#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 (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
+ }
1218
1250
check_addresses = true;
1219
1251
}
1252
+ #endif
1253
+ if (check_addresses == false) {
1254
+ goto out ;
1255
+ }
1256
+ #endif /* CONFIG_PARTITION_MANAGER_ENABLED */
1220
1257
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 ) {
1222
1261
BOOT_LOG_ERR ("Reset address of image in secondary slot is not in the primary slot" );
1223
1262
BOOT_LOG_ERR ("Erasing image from secondary slot" );
1224
1263
@@ -1232,6 +1271,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
1232
1271
fih_rc = FIH_NO_BOOTABLE_IMAGE ;
1233
1272
goto out ;
1234
1273
}
1274
+ LOG_DBG ("Image %d validation OK" , BOOT_CURR_IMG (state ));
1235
1275
}
1236
1276
#endif
1237
1277
@@ -1435,6 +1475,18 @@ static inline void sec_slot_cleanup_if_unusable(void)
1435
1475
#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\
1436
1476
defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */
1437
1477
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
+
1438
1490
/**
1439
1491
* Determines which swap operation to perform, if any. If it is determined
1440
1492
* 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,
1458
1510
const struct flash_area * secondary_fa =
1459
1511
BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY );
1460
1512
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 */
1462
1514
int rc = 0 ;
1515
+
1463
1516
/* Patch needed for NCS. Since image 0 (the app) and image 1 (the other
1464
1517
* B1 slot S0 or S1) share the same secondary slot, we need to check
1465
1518
* whether the update candidate in the secondary slot is intended for
@@ -1469,18 +1522,22 @@ boot_validated_swap_type(struct boot_loader_state *state,
1469
1522
*/
1470
1523
1471
1524
if (hdr -> ih_magic == IMAGE_MAGIC ) {
1525
+ #ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS
1526
+ internal_img_addr = hdr -> ih_load_addr ;
1527
+ #else
1472
1528
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 ));
1475
1531
if (rc != 0 ) {
1476
1532
return BOOT_SWAP_TYPE_FAIL ;
1477
1533
}
1534
+ #endif /* CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS */
1478
1535
1479
1536
sec_slot_touch (state );
1480
1537
1481
1538
#ifdef PM_S1_ADDRESS
1482
1539
#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 ))
1484
1541
#endif
1485
1542
{
1486
1543
const struct flash_area * primary_fa ;
@@ -1492,11 +1549,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
1492
1549
}
1493
1550
1494
1551
/* 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 )) {
1500
1553
if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
1501
1554
/* This is not the s0/s1 upgrade image but the application image, pretend
1502
1555
* there is no image so the NSIB update can be loaded
@@ -1505,18 +1558,14 @@ boot_validated_swap_type(struct boot_loader_state *state,
1505
1558
}
1506
1559
1507
1560
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 )) {
1513
1562
/* NSIB upgrade but for the wrong slot, must be erased */
1514
1563
BOOT_LOG_ERR ("Image in slot is for wrong s0/s1 image" );
1515
1564
flash_area_erase (secondary_fa , 0 , secondary_fa -> fa_size );
1516
1565
sec_slot_untouch (state );
1517
1566
BOOT_LOG_ERR ("Cleaned-up secondary slot of image %d" , BOOT_CURR_IMG (state ));
1518
1567
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 )) {
1520
1569
/* The image in the secondary slot is not intended for any */
1521
1570
return BOOT_SWAP_TYPE_NONE ;
1522
1571
}
@@ -1553,8 +1602,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
1553
1602
* update and indicate to the caller of this function that no update is
1554
1603
* available
1555
1604
*/
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 )) {
1558
1606
struct image_header * hdr = (struct image_header * )secondary_fa -> fa_off ;
1559
1607
uint32_t vtable_addr = (uint32_t )hdr + hdr -> ih_hdr_size ;
1560
1608
uint32_t * net_core_fw_addr = (uint32_t * )(vtable_addr );
0 commit comments