Skip to content

Commit 352b2a4

Browse files
nordicjmrlubos
authored andcommitted
[nrf noup] treewide: Add support for sysbuild assigned images
Adds support for image IDs that are assigned by sysbuild, which allows for dynamically supporting different configurations without needing dummy images to support different modes. Also fixes multiple deficiencies with the previous code where things were not properly accounted for e.g. using the swap algorithm including all swap status parts when updating s0/s1 MCUboot image which could overwrite and corrupt the image data in the other slot Adds support for getting the maximum allowable image size for NSIB Signed-off-by: Jamie McCrae <[email protected]> Signed-off-by: Dominik Ermel <[email protected]> (cherry picked from commit 99601b6)
1 parent 599a1b9 commit 352b2a4

File tree

6 files changed

+241
-105
lines changed

6 files changed

+241
-105
lines changed

boot/bootutil/src/bootutil_misc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,18 @@ boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
427427

428428
uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct flash_area *fap)
429429
{
430+
#if defined(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
431+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
432+
/* NSIB is a direct upgrade without any status or trailer, get the full size of the
433+
* primary slot.
434+
*/
435+
const struct flash_area *fap_nsib = BOOT_IMG_AREA(state, 0);
436+
assert(fap_nsib != NULL);
437+
438+
return flash_area_get_size(fap_nsib);
439+
}
440+
#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */
441+
430442
#if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \
431443
defined(MCUBOOT_FIRMWARE_LOADER) || \
432444
defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD)

boot/bootutil/src/loader.c

Lines changed: 117 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all,
160160
*
161161
* Failure to read any headers is a fatal error.
162162
*/
163-
#ifdef PM_S1_ADDRESS
163+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
164164
/* Patch needed for NCS. The primary slot of the second image
165165
* (image 1) will not contain a valid image header until an upgrade
166166
* of mcuboot has happened (filling S1 with the new version).
167167
*/
168-
if (BOOT_CURR_IMG(state) == 1 && i == 0) {
168+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) {
169169
continue;
170170
}
171-
#endif /* PM_S1_ADDRESS */
171+
#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */
172172
if (i > 0 && !require_all) {
173173
return 0;
174174
} else {
@@ -1176,7 +1176,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
11761176

11771177
#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \
11781178
&& defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION)
1179-
if (BOOT_CURR_IMG(state) == 1) {
1179+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) {
11801180
rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT));
11811181
} else {
11821182
rc = boot_version_cmp(
@@ -1247,35 +1247,54 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
12471247
struct image_header *secondary_hdr = boot_img_hdr(state, slot);
12481248
uint32_t reset_value = 0;
12491249
uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value);
1250+
uint32_t min_addr, max_addr;
1251+
bool check_addresses = false;
12501252

12511253
if (flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)) != 0) {
12521254
fih_rc = FIH_NO_BOOTABLE_IMAGE;
12531255
goto out;
12541256
}
12551257

1256-
uint32_t min_addr, max_addr;
1257-
12581258
#ifdef PM_CPUNET_APP_ADDRESS
12591259
/* The primary slot for the network core is emulated in RAM.
12601260
* Its flash_area hasn't got relevant boundaries.
12611261
* Therfore need to override its boundaries for the check.
12621262
*/
1263-
if (BOOT_CURR_IMG(state) == 1) {
1263+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) {
12641264
min_addr = PM_CPUNET_APP_ADDRESS;
12651265
max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE;
1266-
#ifdef PM_S1_ADDRESS
1267-
} else if (BOOT_CURR_IMG(state) == 0) {
1266+
check_addresses = true;
1267+
} else
1268+
#endif
1269+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1270+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
1271+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
12681272
min_addr = PM_S0_ADDRESS;
1269-
max_addr = pri_fa->fa_off + pri_fa->fa_size;
1273+
max_addr = (PM_S0_ADDRESS + PM_S0_SIZE);
1274+
#else
1275+
min_addr = PM_S1_ADDRESS;
1276+
max_addr = (PM_S1_ADDRESS + PM_S1_SIZE);
12701277
#endif
1278+
check_addresses = true;
12711279
} else
12721280
#endif
1273-
{
1281+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1282+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1283+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1284+
min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS);
1285+
max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE));
1286+
#else
1287+
min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS);
1288+
max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE));
1289+
#endif
1290+
#else
12741291
min_addr = pri_fa->fa_off;
12751292
max_addr = pri_fa->fa_off + pri_fa->fa_size;
1293+
#endif
1294+
check_addresses = true;
12761295
}
12771296

1278-
if (reset_value < min_addr || reset_value> (max_addr)) {
1297+
if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) {
12791298
BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot");
12801299
BOOT_LOG_ERR("Erasing image from secondary slot");
12811300

@@ -1397,36 +1416,54 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_
13971416
#define SEC_SLOT_TOUCHED 1
13981417
#define SEC_SLOT_ASSIGNED 2
13991418

1400-
#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \
1401-
!defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE)
1402-
/* This configuration is peculiar - the one physical secondary slot is
1403-
* mocking two logical secondary
1404-
*/
1405-
#define SEC_SLOT_PHYSICAL_CNT 1
1419+
static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0};
1420+
1421+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1422+
static inline void sec_slot_untouch(struct boot_loader_state *state)
1423+
{
1424+
sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_VIRGIN;
1425+
sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_VIRGIN;
1426+
}
14061427
#else
1407-
#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER
1428+
static inline void sec_slot_untouch(struct boot_loader_state *state)
1429+
{
1430+
}
14081431
#endif
14091432

1410-
static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0};
1411-
14121433
static inline void sec_slot_touch(struct boot_loader_state *state)
14131434
{
1414-
uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state);
1435+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1436+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
1437+
if (sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) {
1438+
sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED;
1439+
}
1440+
} else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1441+
if (sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) {
1442+
sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED;
1443+
}
1444+
}
1445+
#endif
14151446

1416-
if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) {
1417-
sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED;
1447+
if (sec_slot_assignment[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) {
1448+
sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED;
14181449
}
14191450
}
14201451

14211452
static inline void sec_slot_mark_assigned(struct boot_loader_state *state)
14221453
{
1423-
uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state);
1454+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1455+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
1456+
sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED;
1457+
} else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1458+
sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED;
1459+
}
1460+
#endif
14241461

1425-
sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED;
1462+
sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED;
14261463
}
14271464

14281465
/**
1429-
* Cleanu up all secondary slot which couldn't be assigned to any primary slot.
1466+
* Cleanup up all secondary slot which couldn't be assigned to any primary slot.
14301467
*
14311468
* This function erases content of each secondary slot which contains valid
14321469
* header but couldn't be assigned to any of supported primary images.
@@ -1438,8 +1475,8 @@ static void sec_slot_cleanup_if_unusable(void)
14381475
{
14391476
uint8_t idx;
14401477

1441-
for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) {
1442-
if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) {
1478+
for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) {
1479+
if (SEC_SLOT_TOUCHED == sec_slot_assignment[idx]) {
14431480
const struct flash_area *secondary_fa;
14441481
int rc;
14451482

@@ -1448,17 +1485,20 @@ static void sec_slot_cleanup_if_unusable(void)
14481485
if (!rc) {
14491486
rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
14501487
if (!rc) {
1451-
BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx);
1488+
BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx);
14521489
}
14531490
}
14541491

14551492
if (rc) {
1456-
BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx);
1493+
BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc);
14571494
}
14581495
}
14591496
}
14601497
}
14611498
#else
1499+
static inline void sec_slot_untouch(struct boot_loader_state *state)
1500+
{
1501+
}
14621502
static inline void sec_slot_touch(struct boot_loader_state *state)
14631503
{
14641504
}
@@ -1490,7 +1530,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
14901530
owner_nsib[BOOT_CURR_IMG(state)] = false;
14911531
#endif
14921532

1493-
#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)
1533+
#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS)
14941534
const struct flash_area *secondary_fa =
14951535
BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
14961536
struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
@@ -1528,31 +1568,31 @@ boot_validated_swap_type(struct boot_loader_state *state,
15281568
}
15291569

15301570
/* Check start and end of primary slot for current image */
1531-
if (reset_addr < primary_fa->fa_off) {
1532-
#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE)
1533-
const struct flash_area *nsib_fa;
1534-
1535-
/* NSIB upgrade slot */
1536-
rc = flash_area_open((uint32_t)_image_1_primary_slot_id,
1537-
&nsib_fa);
1538-
1539-
if (rc != 0) {
1540-
return BOOT_SWAP_TYPE_FAIL;
1541-
}
1542-
1543-
/* Image is placed before Primary and within the NSIB slot */
1544-
if (reset_addr > nsib_fa->fa_off
1545-
&& reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) {
1546-
/* Set primary to be NSIB upgrade slot */
1547-
BOOT_IMG_AREA(state, 0) = nsib_fa;
1548-
owner_nsib[BOOT_CURR_IMG(state)] = true;
1549-
}
1571+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1572+
if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
15501573
#else
1551-
return BOOT_SWAP_TYPE_NONE;
1552-
1574+
if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
15531575
#endif
1576+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1577+
/* This is not the s0/s1 upgrade image but the application image, pretend
1578+
* there is no image so the NSIB update can be loaded
1579+
*/
1580+
return BOOT_SWAP_TYPE_NONE;
1581+
}
15541582

1555-
} else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) {
1583+
owner_nsib[BOOT_CURR_IMG(state)] = true;
1584+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1585+
} else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
1586+
#else
1587+
} else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
1588+
#endif
1589+
/* NSIB upgrade but for the wrong slot, must be erased */
1590+
BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image");
1591+
flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
1592+
sec_slot_untouch(state);
1593+
BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state));
1594+
return BOOT_SWAP_TYPE_FAIL;
1595+
} else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) {
15561596
/* The image in the secondary slot is not intended for any */
15571597
return BOOT_SWAP_TYPE_NONE;
15581598
}
@@ -1565,7 +1605,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
15651605
sec_slot_mark_assigned(state);
15661606
}
15671607

1568-
#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */
1608+
#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */
15691609

15701610
swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
15711611
if (BOOT_IS_UPGRADE(swap_type)) {
@@ -2237,7 +2277,22 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
22372277
flash_area_close(fap);
22382278
}
22392279

2240-
swap_run(state, bs, copy_size);
2280+
#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
2281+
if (owner_nsib[BOOT_CURR_IMG(state)]) {
2282+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
2283+
/* For NSIB, move the image instead of swapping it */
2284+
nsib_swap_run(state, bs);
2285+
2286+
#if defined(CONFIG_REBOOT)
2287+
/* Should also reboot at this point so the new S0/S1 update is applied */
2288+
sys_reboot(SYS_REBOOT_COLD);
2289+
#endif
2290+
}
2291+
} else
2292+
#endif
2293+
{
2294+
swap_run(state, bs, copy_size);
2295+
}
22412296

22422297
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
22432298
extern int boot_status_fails;
@@ -2931,12 +2986,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
29312986
rc = boot_perform_update(state, &bs);
29322987
}
29332988
assert(rc == 0);
2934-
#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT)
2935-
if (owner_nsib[BOOT_CURR_IMG(state)]) {
2936-
sys_reboot(SYS_REBOOT_COLD);
2937-
2938-
}
2939-
#endif
29402989
break;
29412990

29422991
case BOOT_SWAP_TYPE_FAIL:
@@ -3004,13 +3053,17 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
30043053
*/
30053054
}
30063055

3007-
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
30083056
#ifdef PM_S1_ADDRESS
30093057
/* Patch needed for NCS. Image 1 primary is the currently
30103058
* executing MCUBoot image, and is therefore already validated by NSIB and
30113059
* does not need to also be validated by MCUBoot.
30123060
*/
3013-
bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1;
3061+
bool image_validated_by_nsib = BOOT_CURR_IMG(state) ==
3062+
CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER;
3063+
#endif
3064+
3065+
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
3066+
#ifdef PM_S1_ADDRESS
30143067
if (!image_validated_by_nsib)
30153068
#endif
30163069
{

0 commit comments

Comments
 (0)