Skip to content

Commit 06b2bb6

Browse files
committed
[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]>
1 parent 94212b4 commit 06b2bb6

File tree

5 files changed

+280
-84
lines changed

5 files changed

+280
-84
lines changed

boot/bootutil/src/loader.c

Lines changed: 86 additions & 43 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

@@ -1364,7 +1383,7 @@ static inline void sec_slot_mark_assigned(struct boot_loader_state *state)
13641383
}
13651384

13661385
/**
1367-
* Cleanu up all secondary slot which couldn't be assigned to any primary slot.
1386+
* Cleanup up all secondary slot which couldn't be assigned to any primary slot.
13681387
*
13691388
* This function erases content of each secondary slot which contains valid
13701389
* header but couldn't be assigned to any of supported primary images.
@@ -1428,7 +1447,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
14281447
owner_nsib[BOOT_CURR_IMG(state)] = false;
14291448
#endif
14301449

1431-
#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)
1450+
#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS)
14321451
const struct flash_area *secondary_fa =
14331452
BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
14341453
struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
@@ -1466,31 +1485,45 @@ boot_validated_swap_type(struct boot_loader_state *state,
14661485
}
14671486

14681487
/* 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;
1488+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1489+
if (reset_addr >= PM_S0_ADDRESS && PM_S0_ADDRESS <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
1490+
#else
1491+
if (reset_addr >= PM_S1_ADDRESS && PM_S1_ADDRESS <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
1492+
#endif
1493+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
1494+
/* This is not the s0/s1 upgrade image but the application image, pretend
1495+
* there is no image so the NSIB update can be loaded
1496+
*/
1497+
return BOOT_SWAP_TYPE_NONE;
1498+
}
1499+
#if 0 && defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE)
1500+
const struct flash_area *nsib_fa;
14721501

1473-
/* NSIB upgrade slot */
1474-
rc = flash_area_open((uint32_t)_image_1_primary_slot_id,
1475-
&nsib_fa);
1502+
/* NSIB upgrade slot */
1503+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1504+
rc = flash_area_open(PM_S0_ID, &nsib_fa);
1505+
#else
1506+
rc = flash_area_open(PM_S1_ID, &nsib_fa);
1507+
#endif
14761508

1477-
if (rc != 0) {
1478-
return BOOT_SWAP_TYPE_FAIL;
1479-
}
1509+
if (rc != 0) {
1510+
return BOOT_SWAP_TYPE_FAIL;
1511+
}
14801512

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-
}
1513+
/* Set primary to be NSIB upgrade slot */
1514+
BOOT_IMG_AREA(state, 0) = nsib_fa;
1515+
#endif
1516+
owner_nsib[BOOT_CURR_IMG(state)] = true;
1517+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1518+
} else if (reset_addr >= PM_S1_ADDRESS && PM_S1_ADDRESS <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
14881519
#else
1489-
return BOOT_SWAP_TYPE_NONE;
1490-
1520+
} else if (reset_addr >= PM_S0_ADDRESS && PM_S0_ADDRESS <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
14911521
#endif
1492-
1493-
} else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) {
1522+
/* NSIB upgrade but for the wrong slot, must be erased */
1523+
LOG_ERR("Image in slot is for wrong s0/s1 image");
1524+
flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
1525+
return BOOT_SWAP_TYPE_FAIL;
1526+
} else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) {
14941527
/* The image in the secondary slot is not intended for any */
14951528
return BOOT_SWAP_TYPE_NONE;
14961529
}
@@ -1503,7 +1536,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
15031536
sec_slot_mark_assigned(state);
15041537
}
15051538

1506-
#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */
1539+
#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */
15071540

15081541
swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
15091542
if (BOOT_IS_UPGRADE(swap_type)) {
@@ -2035,7 +2068,22 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
20352068
flash_area_close(fap);
20362069
}
20372070

2038-
swap_run(state, bs, copy_size);
2071+
#if defined(PM_S1_ADDRESS) && !MCUBOOT_OVERWRITE_ONLY && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1
2072+
if (owner_nsib[BOOT_CURR_IMG(state)]) {
2073+
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) {
2074+
/* For NSIB, move the image instead of swapping it */
2075+
nsib_swap_run(state, bs);
2076+
2077+
#if defined(CONFIG_REBOOT)
2078+
/* Should also reboot at this point so the new S0/S1 update is applied */
2079+
sys_reboot(SYS_REBOOT_COLD);
2080+
#endif
2081+
}
2082+
} else
2083+
#endif
2084+
{
2085+
swap_run(state, bs, copy_size);
2086+
}
20392087

20402088
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
20412089
extern int boot_status_fails;
@@ -2701,12 +2749,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
27012749
rc = boot_perform_update(state, &bs);
27022750
}
27032751
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
27102752
break;
27112753

27122754
case BOOT_SWAP_TYPE_FAIL:
@@ -2780,7 +2822,8 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
27802822
* executing MCUBoot image, and is therefore already validated by NSIB and
27812823
* does not need to also be validated by MCUBoot.
27822824
*/
2783-
bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1;
2825+
bool image_validated_by_nsib = BOOT_CURR_IMG(state) ==
2826+
CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER;
27842827
if (!image_validated_by_nsib)
27852828
#endif
27862829
{

boot/bootutil/src/swap_nsib.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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+
#if 0
34+
uint32_t
35+
find_last_idx(struct boot_loader_state *state, uint32_t swap_size)
36+
{
37+
uint32_t sector_sz;
38+
uint32_t sz;
39+
uint32_t last_idx;
40+
41+
sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0);
42+
sz = 0;
43+
last_idx = 0;
44+
while (1) {
45+
sz += sector_sz;
46+
last_idx++;
47+
if (sz >= swap_size) {
48+
break;
49+
}
50+
}
51+
52+
return last_idx;
53+
}
54+
#endif
55+
56+
#if 0
57+
static int app_max_sectors(struct boot_loader_state *state)
58+
{
59+
uint32_t sz = 0;
60+
uint32_t sector_sz;
61+
uint32_t trailer_sz;
62+
uint32_t first_trailer_idx;
63+
64+
sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0);
65+
trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
66+
first_trailer_idx = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;
67+
68+
while (1) {
69+
sz += sector_sz;
70+
if (sz >= trailer_sz) {
71+
break;
72+
}
73+
first_trailer_idx--;
74+
}
75+
76+
return first_trailer_idx;
77+
}
78+
#endif
79+
80+
void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs)
81+
{
82+
// uint32_t sz;
83+
uint32_t sector_sz;
84+
// uint32_t idx;
85+
// uint32_t trailer_sz;
86+
// uint32_t first_trailer_idx;
87+
// uint32_t last_idx;
88+
uint8_t image_index;
89+
const struct flash_area *fap_pri;
90+
const struct flash_area *fap_sec;
91+
int rc;
92+
93+
BOOT_LOG_INF("Starting swap using nsib algorithm.");
94+
95+
sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0);
96+
97+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
98+
rc = flash_area_open(PM_S0_ID, &fap_pri);
99+
#else
100+
rc = flash_area_open(PM_S1_ID, &fap_pri);
101+
#endif
102+
assert (rc == 0);
103+
104+
/*
105+
* When starting a new swap upgrade, check that there is enough space.
106+
*/
107+
#if 0
108+
if (boot_status_is_reset(bs)) {
109+
sz = 0;
110+
trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
111+
first_trailer_idx = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;
112+
113+
while (1) {
114+
sz += sector_sz;
115+
if (sz >= trailer_sz) {
116+
break;
117+
}
118+
first_trailer_idx--;
119+
}
120+
121+
if (last_idx >= first_trailer_idx) {
122+
BOOT_LOG_WRN("Not enough free space to run swap upgrade");
123+
BOOT_LOG_WRN("required %d bytes but only %d are available",
124+
(last_idx + 1) * sector_sz,
125+
first_trailer_idx * sector_sz);
126+
bs->swap_type = BOOT_SWAP_TYPE_NONE;
127+
return;
128+
}
129+
}
130+
#endif
131+
132+
image_index = BOOT_CURR_IMG(state);
133+
134+
rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec);
135+
assert (rc == 0);
136+
137+
rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size);
138+
assert(rc == 0);
139+
140+
rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size);
141+
assert(rc == 0);
142+
143+
rc = swap_erase_trailer_sectors(state, fap_sec);
144+
assert(rc == 0);
145+
146+
rc = boot_erase_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size));
147+
assert(rc == 0);
148+
149+
flash_area_close(fap_pri);
150+
flash_area_close(fap_sec);
151+
}

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_ */

0 commit comments

Comments
 (0)