@@ -84,6 +84,29 @@ 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
+ #define THREE_CAT (a , b , c ) THREE_CAT_(a, b, c)
90
+
91
+ #ifdef CONFIG_NCS_IS_VARIANT_IMAGE
92
+ /* Running from slot 1, checking slot 0 */
93
+ #define NCS_VARIANT_SLOT_ID 0
94
+ #else /* CONFIG_NCS_IS_VARIANT_IMAGE */
95
+ /* Running from slot 0, checking slot 1 */
96
+ #define NCS_VARIANT_SLOT_ID 1
97
+ #endif /* CONFIG_NCS_IS_VARIANT_IMAGE */
98
+
99
+ #define NCS_VARIANT_SLOT_MIN_ADDR THREE_CAT(PM_S, NCS_VARIANT_SLOT_ID, _ADDRESS)
100
+ #define NCS_VARIANT_SLOT_MAX_ADDR ((NCS_VARIANT_SLOT_MIN_ADDR) + THREE_CAT(PM_S, NCS_VARIANT_SLOT_ID, _SIZE))
101
+
102
+ #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER == -1
103
+ #define CHECK_MCUBOOT_IMAGE 0
104
+ #else
105
+ #define CHECK_MCUBOOT_IMAGE 1
106
+ #endif
107
+
108
+ #endif /* CONFIG_PARTITION_MANAGER_ENABLED */
109
+
87
110
BOOT_LOG_MODULE_DECLARE (mcuboot );
88
111
89
112
static struct boot_loader_state boot_data ;
@@ -1150,12 +1173,15 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
1150
1173
goto out ;
1151
1174
}
1152
1175
1153
- #if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES ) && defined(MCUBOOT_VERIFY_IMG_ADDRESS )
1176
+ #if MCUBOOT_IMAGE_NUMBER > 1 && \
1177
+ (!defined(MCUBOOT_ENC_IMAGES ) || defined(CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS )) && \
1178
+ defined(MCUBOOT_VERIFY_IMG_ADDRESS )
1154
1179
/* Verify that the image in the secondary slot has a reset address
1155
1180
* located in the primary slot. This is done to avoid users incorrectly
1156
1181
* overwriting an application written to the incorrect slot.
1157
1182
* This feature is only supported by ARM platforms.
1158
1183
*/
1184
+
1159
1185
#if MCUBOOT_IMAGE_NUMBER >= 3
1160
1186
/* Currently the MCUboot can be configured for up to 3 image, where image number 2 is
1161
1187
* designated for XIP, where it is the second part of image stored in slots of image
@@ -1167,58 +1193,72 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
1167
1193
}
1168
1194
#endif
1169
1195
if (fap == BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY )) {
1170
- const struct flash_area * pri_fa = BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY );
1171
1196
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 ;
1175
- bool check_addresses = false;
1197
+ uint32_t internal_img_addr = 0 ; /* either the reset handler addres or the image beginning addres */
1198
+ uint32_t min_addr ;
1199
+ uint32_t max_addr ;
1200
+
1201
+ min_addr = flash_area_get_off (BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY ));
1202
+ max_addr = flash_area_get_size (BOOT_IMG_AREA (state , BOOT_SLOT_PRIMARY )) + min_addr ;
1176
1203
1177
- if (flash_area_read (fap , reset_addr , & reset_value , sizeof (reset_value )) != 0 ) {
1204
+ #ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS
1205
+ internal_img_addr = secondary_hdr -> ih_load_addr ;
1206
+ #else
1207
+ const uint32_t offset = secondary_hdr -> ih_hdr_size + sizeof (internal_img_addr );
1208
+ BOOT_LOG_DBG ("Getting image %d internal addr from offset %d" ,
1209
+ BOOT_CURR_IMG (state ), offset );
1210
+ /* Read reset vector from ARM vector table */
1211
+ if (flash_area_read (fap , offset , & internal_img_addr , sizeof (internal_img_addr )) != 0 ) {
1212
+ BOOT_LOG_ERR ("Failed to read image load address" , BOOT_CURR_IMG (state ));
1178
1213
fih_rc = FIH_NO_BOOTABLE_IMAGE ;
1179
1214
goto out ;
1180
1215
}
1216
+ #endif
1217
+ BOOT_LOG_DBG ("Image %d expected load address 0x%x" , BOOT_CURR_IMG (state ), internal_img_addr );
1181
1218
1182
- #ifdef PM_CPUNET_APP_ADDRESS
1219
+ #ifdef CONFIG_PARTITION_MANAGER_ENABLED
1183
1220
/* The primary slot for the network core is emulated in RAM.
1184
1221
* Its flash_area hasn't got relevant boundaries.
1185
1222
* Therfore need to override its boundaries for the check.
1186
1223
*/
1224
+ #ifdef PM_CPUNET_APP_ADDRESS
1187
1225
if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER ) {
1226
+
1227
+ BOOT_LOG_DBG ("Image %d is NETCORE image" , BOOT_CURR_IMG (state ));
1228
+
1188
1229
min_addr = PM_CPUNET_APP_ADDRESS ;
1189
1230
max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE ;
1190
- check_addresses = true;
1191
- } else
1192
- #endif
1193
- #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != - 1
1231
+ }
1232
+ #endif /* PM_CPUNET_APP_SIZE */
1233
+
1234
+ #if CHECK_MCUBOOT_IMAGE == 1
1194
1235
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
1202
- check_addresses = true;
1203
- } else
1204
- #endif
1236
+
1237
+ BOOT_LOG_DBG ("Image %d is another stage MCBoot image" , BOOT_CURR_IMG (state ));
1238
+
1239
+ min_addr = NCS_VARIANT_SLOT_MIN_ADDR ;
1240
+ max_addr = NCS_VARIANT_SLOT_MAX_ADDR ;
1241
+ }
1242
+ #endif /* CHECK_MCUBOOT_IMAGE */
1243
+
1244
+ #if CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1
1205
1245
if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
1206
- #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
1218
- check_addresses = true;
1246
+
1247
+ BOOT_LOG_DBG ("Image %d is application MCBoot image" , BOOT_CURR_IMG (state ));
1248
+
1249
+ /* If not checking the MCUboot image, then we leave the original
1250
+ * min/max assignments from the primary slot read. */
1251
+ if (CHECK_MCUBOOT_IMAGE ) {
1252
+ min_addr = MIN (min_addr , NCS_VARIANT_SLOT_MIN_ADDR );
1253
+ max_addr = MAX (max_addr , NCS_VARIANT_SLOT_MAX_ADDR );
1254
+ }
1219
1255
}
1256
+ #endif
1257
+ #endif /* CONFIG_PARTITION_MANAGER_ENABLED */
1220
1258
1221
- if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr )) {
1259
+ LOG_DBG ("Check 0x%x is within [min_addr, max_addr] = [0x%x, 0x%x)" ,
1260
+ internal_img_addr , min_addr , max_addr );
1261
+ if (internal_img_addr < min_addr || internal_img_addr >= max_addr ) {
1222
1262
BOOT_LOG_ERR ("Reset address of image in secondary slot is not in the primary slot" );
1223
1263
BOOT_LOG_ERR ("Erasing image from secondary slot" );
1224
1264
@@ -1232,6 +1272,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
1232
1272
fih_rc = FIH_NO_BOOTABLE_IMAGE ;
1233
1273
goto out ;
1234
1274
}
1275
+ LOG_DBG ("Image %d validation OK" , BOOT_CURR_IMG (state ));
1235
1276
}
1236
1277
#endif
1237
1278
@@ -1435,6 +1476,18 @@ static inline void sec_slot_cleanup_if_unusable(void)
1435
1476
#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\
1436
1477
defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */
1437
1478
1479
+ #define IS_IN_RANGE_CPUNET_APP_ADDR (_addr ) (((_addr) >= PM_CPUNET_APP_ADDRESS) && ((_addr) < PM_CPUNET_APP_END_ADDRESS))
1480
+ #define _IS_IN_RANGE_S_VARIANT_ADDR (_addr , x ) (((_addr) >= PM_S##x##_ADDRESS) && ((_addr) <= (PM_S##x##_ADDRESS + PM_S##x##_SIZE)))
1481
+ #if defined(CONFIG_NCS_IS_VARIANT_IMAGE )
1482
+ #define IS_IN_RANGE_S_ALTERNATE_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
1483
+ #define IS_IN_RANGE_S_CURRENT_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
1484
+ #else
1485
+ #define IS_IN_RANGE_S_ALTERNATE_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
1486
+ #define IS_IN_RANGE_S_CURRENT_ADDR (_addr ) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
1487
+ #endif
1488
+ #define IS_IN_RANGE_IMAGE_ADDR (_addr , _fa ) \
1489
+ (((_addr) >= flash_area_get_off(_fa)) && (_addr) < (flash_area_get_off(_fa) + flash_area_get_size(_fa)))
1490
+
1438
1491
/**
1439
1492
* Determines which swap operation to perform, if any. If it is determined
1440
1493
* that a swap operation is required, the image in the secondary slot is checked
@@ -1458,8 +1511,9 @@ boot_validated_swap_type(struct boot_loader_state *state,
1458
1511
const struct flash_area * secondary_fa =
1459
1512
BOOT_IMG_AREA (state , BOOT_SLOT_SECONDARY );
1460
1513
struct image_header * hdr = boot_img_hdr (state , BOOT_SLOT_SECONDARY );
1461
- uint32_t reset_addr = 0 ;
1514
+ uint32_t internal_img_addr = 0 ; /* either the reset handler addres or the image beginning addres */
1462
1515
int rc = 0 ;
1516
+
1463
1517
/* Patch needed for NCS. Since image 0 (the app) and image 1 (the other
1464
1518
* B1 slot S0 or S1) share the same secondary slot, we need to check
1465
1519
* whether the update candidate in the secondary slot is intended for
@@ -1469,18 +1523,22 @@ boot_validated_swap_type(struct boot_loader_state *state,
1469
1523
*/
1470
1524
1471
1525
if (hdr -> ih_magic == IMAGE_MAGIC ) {
1526
+ #ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS
1527
+ internal_img_addr = hdr -> ih_load_addr ;
1528
+ #else
1472
1529
rc = flash_area_read (secondary_fa , hdr -> ih_hdr_size +
1473
- sizeof (uint32_t ), & reset_addr ,
1474
- sizeof (reset_addr ));
1530
+ sizeof (uint32_t ), & internal_img_addr ,
1531
+ sizeof (internal_img_addr ));
1475
1532
if (rc != 0 ) {
1476
1533
return BOOT_SWAP_TYPE_FAIL ;
1477
1534
}
1535
+ #endif /* CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDRESS */
1478
1536
1479
1537
sec_slot_touch (state );
1480
1538
1481
1539
#ifdef PM_S1_ADDRESS
1482
1540
#ifdef PM_CPUNET_B0N_ADDRESS
1483
- if (!( reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS ))
1541
+ if (!IS_IN_RANGE_CPUNET_APP_ADDR ( internal_img_addr ))
1484
1542
#endif
1485
1543
{
1486
1544
const struct flash_area * primary_fa ;
@@ -1492,11 +1550,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
1492
1550
}
1493
1551
1494
1552
/* 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
1553
+ if (IS_IN_RANGE_S_ALTERNATE_ADDR (internal_img_addr )) {
1500
1554
if (BOOT_CURR_IMG (state ) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER ) {
1501
1555
/* This is not the s0/s1 upgrade image but the application image, pretend
1502
1556
* there is no image so the NSIB update can be loaded
@@ -1505,18 +1559,14 @@ boot_validated_swap_type(struct boot_loader_state *state,
1505
1559
}
1506
1560
1507
1561
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
1562
+ } else if (IS_IN_RANGE_S_CURRENT_ADDR (internal_img_addr )) {
1513
1563
/* NSIB upgrade but for the wrong slot, must be erased */
1514
1564
BOOT_LOG_ERR ("Image in slot is for wrong s0/s1 image" );
1515
1565
flash_area_erase (secondary_fa , 0 , secondary_fa -> fa_size );
1516
1566
sec_slot_untouch (state );
1517
1567
BOOT_LOG_ERR ("Cleaned-up secondary slot of image %d" , BOOT_CURR_IMG (state ));
1518
1568
return BOOT_SWAP_TYPE_FAIL ;
1519
- } else if (reset_addr < primary_fa -> fa_off || reset_addr > ( primary_fa -> fa_off + primary_fa -> fa_size )) {
1569
+ } else if (! IS_IN_RANGE_IMAGE_ADDR ( internal_img_addr , primary_fa )) {
1520
1570
/* The image in the secondary slot is not intended for any */
1521
1571
return BOOT_SWAP_TYPE_NONE ;
1522
1572
}
@@ -1553,8 +1603,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
1553
1603
* update and indicate to the caller of this function that no update is
1554
1604
* available
1555
1605
*/
1556
- if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS &&
1557
- reset_addr < PM_CPUNET_APP_END_ADDRESS ) {
1606
+ if (upgrade_valid && IS_IN_RANGE_CPUNET_APP_ADDR (internal_img_addr )) {
1558
1607
struct image_header * hdr = (struct image_header * )secondary_fa -> fa_off ;
1559
1608
uint32_t vtable_addr = (uint32_t )hdr + hdr -> ih_hdr_size ;
1560
1609
uint32_t * net_core_fw_addr = (uint32_t * )(vtable_addr );
0 commit comments