Skip to content

Commit ba255be

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 Signed-off-by: Jamie McCrae <[email protected]> (cherry picked from commit 5646583)
1 parent b3c7d3d commit ba255be

File tree

5 files changed

+209
-105
lines changed

5 files changed

+209
-105
lines changed

boot/bootutil/src/loader.c

Lines changed: 97 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all,
153153
*
154154
* Failure to read any headers is a fatal error.
155155
*/
156-
#ifdef PM_S1_ADDRESS
156+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
157157
/* Patch needed for NCS. The primary slot of the second image
158158
* (image 1) will not contain a valid image header until an upgrade
159159
* of mcuboot has happened (filling S1 with the new version).
160160
*/
161-
if (BOOT_CURR_IMG(state) == 1 && i == 0) {
161+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) {
162162
continue;
163163
}
164-
#endif /* PM_S1_ADDRESS */
164+
#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */
165165
if (i > 0 && !require_all) {
166166
return 0;
167167
} else {
@@ -1160,7 +1160,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
11601160

11611161
#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \
11621162
&& defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION)
1163-
if (BOOT_CURR_IMG(state) == 1) {
1163+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) {
11641164
rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT));
11651165
} else {
11661166
rc = boot_version_cmp(
@@ -1229,36 +1229,55 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
12291229
struct image_header *secondary_hdr = boot_img_hdr(state, slot);
12301230
uint32_t reset_value = 0;
12311231
uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value);
1232+
uint32_t min_addr, max_addr;
1233+
bool check_addresses = false;
12321234

12331235
rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value));
12341236
if (rc != 0) {
12351237
fih_rc = FIH_NO_BOOTABLE_IMAGE;
12361238
goto out;
12371239
}
12381240

1239-
uint32_t min_addr, max_addr;
1240-
12411241
#ifdef PM_CPUNET_APP_ADDRESS
12421242
/* The primary slot for the network core is emulated in RAM.
12431243
* Its flash_area hasn't got relevant boundaries.
12441244
* Therfore need to override its boundaries for the check.
12451245
*/
1246-
if (BOOT_CURR_IMG(state) == 1) {
1246+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) {
12471247
min_addr = PM_CPUNET_APP_ADDRESS;
12481248
max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE;
1249-
#ifdef PM_S1_ADDRESS
1250-
} else if (BOOT_CURR_IMG(state) == 0) {
1249+
check_addresses = true;
1250+
} else
1251+
#endif
1252+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1253+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
1254+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
12511255
min_addr = PM_S0_ADDRESS;
1252-
max_addr = pri_fa->fa_off + pri_fa->fa_size;
1256+
max_addr = (PM_S0_ADDRESS + PM_S0_SIZE);
1257+
#else
1258+
min_addr = PM_S1_ADDRESS;
1259+
max_addr = (PM_S1_ADDRESS + PM_S1_SIZE);
12531260
#endif
1261+
check_addresses = true;
12541262
} else
12551263
#endif
1256-
{
1264+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1265+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1266+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1267+
min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS);
1268+
max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE));
1269+
#else
1270+
min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS);
1271+
max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE));
1272+
#endif
1273+
#else
12571274
min_addr = pri_fa->fa_off;
12581275
max_addr = pri_fa->fa_off + pri_fa->fa_size;
1276+
#endif
1277+
check_addresses = true;
12591278
}
12601279

1261-
if (reset_value < min_addr || reset_value> (max_addr)) {
1280+
if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) {
12621281
BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot");
12631282
BOOT_LOG_ERR("Erasing image from secondary slot");
12641283

@@ -1335,36 +1354,42 @@ boot_update_security_counter(uint8_t image_index, int slot,
13351354
#define SEC_SLOT_TOUCHED 1
13361355
#define SEC_SLOT_ASSIGNED 2
13371356

1338-
#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \
1339-
!defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE)
1340-
/* This configuration is peculiar - the one physical secondary slot is
1341-
* mocking two logical secondary
1342-
*/
1343-
#define SEC_SLOT_PHYSICAL_CNT 1
1344-
#else
1345-
#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER
1346-
#endif
1347-
1348-
static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0};
1357+
static uint8_t sec_slot_assignmnet[MCUBOOT_IMAGE_NUMBER] = {0};
13491358

13501359
static inline void sec_slot_touch(struct boot_loader_state *state)
13511360
{
1352-
uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state);
1361+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1362+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
1363+
if (sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) {
1364+
sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED;
1365+
}
1366+
} else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1367+
if (sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) {
1368+
sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED;
1369+
}
1370+
}
1371+
#endif
13531372

1354-
if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) {
1355-
sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED;
1373+
if (sec_slot_assignmnet[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) {
1374+
sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED;
13561375
}
13571376
}
13581377

13591378
static inline void sec_slot_mark_assigned(struct boot_loader_state *state)
13601379
{
1361-
uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state);
1380+
#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
1381+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
1382+
sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED;
1383+
} else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1384+
sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED;
1385+
}
1386+
#endif
13621387

1363-
sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED;
1388+
sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED;
13641389
}
13651390

13661391
/**
1367-
* Cleanu up all secondary slot which couldn't be assigned to any primary slot.
1392+
* Cleanup up all secondary slot which couldn't be assigned to any primary slot.
13681393
*
13691394
* This function erases content of each secondary slot which contains valid
13701395
* header but couldn't be assigned to any of supported primary images.
@@ -1376,7 +1401,7 @@ static void sec_slot_cleanup_if_unusable(void)
13761401
{
13771402
uint8_t idx;
13781403

1379-
for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) {
1404+
for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) {
13801405
if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) {
13811406
const struct flash_area *secondary_fa;
13821407
int rc;
@@ -1386,12 +1411,12 @@ static void sec_slot_cleanup_if_unusable(void)
13861411
if (!rc) {
13871412
rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
13881413
if (!rc) {
1389-
BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx);
1414+
BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx);
13901415
}
13911416
}
13921417

13931418
if (rc) {
1394-
BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx);
1419+
BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc);
13951420
}
13961421
}
13971422
}
@@ -1428,7 +1453,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
14281453
owner_nsib[BOOT_CURR_IMG(state)] = false;
14291454
#endif
14301455

1431-
#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)
1456+
#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS)
14321457
const struct flash_area *secondary_fa =
14331458
BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
14341459
struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
@@ -1466,31 +1491,29 @@ boot_validated_swap_type(struct boot_loader_state *state,
14661491
}
14671492

14681493
/* Check start and end of primary slot for current image */
1469-
if (reset_addr < primary_fa->fa_off) {
1470-
#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE)
1471-
const struct flash_area *nsib_fa;
1472-
1473-
/* NSIB upgrade slot */
1474-
rc = flash_area_open((uint32_t)_image_1_primary_slot_id,
1475-
&nsib_fa);
1476-
1477-
if (rc != 0) {
1478-
return BOOT_SWAP_TYPE_FAIL;
1479-
}
1480-
1481-
/* Image is placed before Primary and within the NSIB slot */
1482-
if (reset_addr > nsib_fa->fa_off
1483-
&& reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) {
1484-
/* Set primary to be NSIB upgrade slot */
1485-
BOOT_IMG_AREA(state, 0) = nsib_fa;
1486-
owner_nsib[BOOT_CURR_IMG(state)] = true;
1487-
}
1494+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1495+
if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
14881496
#else
1489-
return BOOT_SWAP_TYPE_NONE;
1490-
1497+
if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
14911498
#endif
1499+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1500+
/* This is not the s0/s1 upgrade image but the application image, pretend
1501+
* there is no image so the NSIB update can be loaded
1502+
*/
1503+
return BOOT_SWAP_TYPE_NONE;
1504+
}
14921505

1493-
} else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) {
1506+
owner_nsib[BOOT_CURR_IMG(state)] = true;
1507+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1508+
} else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
1509+
#else
1510+
} else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
1511+
#endif
1512+
/* NSIB upgrade but for the wrong slot, must be erased */
1513+
BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image");
1514+
flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
1515+
return BOOT_SWAP_TYPE_FAIL;
1516+
} else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) {
14941517
/* The image in the secondary slot is not intended for any */
14951518
return BOOT_SWAP_TYPE_NONE;
14961519
}
@@ -1503,7 +1526,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
15031526
sec_slot_mark_assigned(state);
15041527
}
15051528

1506-
#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */
1529+
#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */
15071530

15081531
swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
15091532
if (BOOT_IS_UPGRADE(swap_type)) {
@@ -2035,7 +2058,22 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
20352058
flash_area_close(fap);
20362059
}
20372060

2038-
swap_run(state, bs, copy_size);
2061+
#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
2062+
if (owner_nsib[BOOT_CURR_IMG(state)]) {
2063+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
2064+
/* For NSIB, move the image instead of swapping it */
2065+
nsib_swap_run(state, bs);
2066+
2067+
#if defined(CONFIG_REBOOT)
2068+
/* Should also reboot at this point so the new S0/S1 update is applied */
2069+
sys_reboot(SYS_REBOOT_COLD);
2070+
#endif
2071+
}
2072+
} else
2073+
#endif
2074+
{
2075+
swap_run(state, bs, copy_size);
2076+
}
20392077

20402078
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
20412079
extern int boot_status_fails;
@@ -2701,12 +2739,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
27012739
rc = boot_perform_update(state, &bs);
27022740
}
27032741
assert(rc == 0);
2704-
#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT)
2705-
if (owner_nsib[BOOT_CURR_IMG(state)]) {
2706-
sys_reboot(SYS_REBOOT_COLD);
2707-
2708-
}
2709-
#endif
27102742
break;
27112743

27122744
case BOOT_SWAP_TYPE_FAIL:
@@ -2780,7 +2812,8 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
27802812
* executing MCUBoot image, and is therefore already validated by NSIB and
27812813
* does not need to also be validated by MCUBoot.
27822814
*/
2783-
bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1;
2815+
bool image_validated_by_nsib = BOOT_CURR_IMG(state) ==
2816+
CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER;
27842817
if (!image_validated_by_nsib)
27852818
#endif
27862819
{

boot/bootutil/src/swap_nsib.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2024 Nordic Semiconductor ASA
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include <stddef.h>
20+
#include <stdbool.h>
21+
#include <inttypes.h>
22+
#include <stdlib.h>
23+
#include <string.h>
24+
#include "bootutil/bootutil.h"
25+
#include "bootutil_priv.h"
26+
#include "swap_priv.h"
27+
#include "bootutil/bootutil_log.h"
28+
29+
#include "mcuboot_config/mcuboot_config.h"
30+
31+
BOOT_LOG_MODULE_DECLARE(mcuboot);
32+
33+
void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs)
34+
{
35+
uint32_t sector_sz;
36+
uint8_t image_index;
37+
const struct flash_area *fap_pri;
38+
const struct flash_area *fap_sec;
39+
int rc;
40+
41+
BOOT_LOG_INF("Starting swap using nsib algorithm.");
42+
43+
sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0);
44+
45+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
46+
rc = flash_area_open(PM_S0_ID, &fap_pri);
47+
#else
48+
rc = flash_area_open(PM_S1_ID, &fap_pri);
49+
#endif
50+
assert (rc == 0);
51+
image_index = BOOT_CURR_IMG(state);
52+
53+
rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec);
54+
assert (rc == 0);
55+
56+
rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size);
57+
assert(rc == 0);
58+
59+
rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size);
60+
assert(rc == 0);
61+
62+
rc = swap_erase_trailer_sectors(state, fap_sec);
63+
assert(rc == 0);
64+
65+
rc = boot_erase_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size));
66+
assert(rc == 0);
67+
68+
flash_area_close(fap_pri);
69+
flash_area_close(fap_sec);
70+
}

boot/bootutil/src/swap_priv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,12 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat
106106
*/
107107
int app_max_size(struct boot_loader_state *state);
108108

109+
#if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \
110+
(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED))
111+
/**
112+
* Performs an NSIB update
113+
*/
114+
void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs);
115+
#endif
116+
109117
#endif /* H_SWAP_PRIV_ */

boot/zephyr/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ zephyr_library_sources(
152152
${BOOT_DIR}/bootutil/src/swap_move.c
153153
${BOOT_DIR}/bootutil/src/caps.c
154154
)
155+
156+
if(NOT CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER EQUAL "-1" AND NOT CONFIG_BOOT_UPGRADE_ONLY)
157+
zephyr_library_sources(
158+
${BOOT_DIR}/bootutil/src/swap_nsib.c
159+
)
160+
endif()
155161
endif()
156162

157163
if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256)

0 commit comments

Comments
 (0)