Skip to content

Commit 7bf2111

Browse files
committed
[nrf noup] loader: Handle encrypted MCUboot updates
Use either load_address from the image header or the UUID identification to detect an encrypted MCUboot update candidate image. Ref: NCSDK-35089 Signed-off-by: Tomasz Chyrowicz <tomasz.chyrowicz@nordicsemi.no>
1 parent e869f8b commit 7bf2111

4 files changed

Lines changed: 259 additions & 7 deletions

File tree

boot/bootutil/include/bootutil/mcuboot_uuid.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ fih_ret boot_uuid_vid_match(const struct flash_area *fap, const struct image_uui
5757
*/
5858
fih_ret boot_uuid_cid_match(const struct flash_area *fap, const struct image_uuid *uuid_cid);
5959

60+
/**
61+
* @brief Find the image index and partition index for a given class ID and vendor ID.
62+
*
63+
* @param[in] cid The class ID to search for.
64+
* @param[in] vid The vendor ID to search for.
65+
* @param[out] image_index The index of the image found.
66+
* @param[out] partition_index The index of the partition found.
67+
*
68+
* @retval 0 on success,
69+
* @retval -EINVAL if the input parameters are invalid.
70+
* @retval -ENOENT if the image or partition is not found.
71+
*/
72+
int boot_uuid_find_image(const struct image_uuid *cid, const struct image_uuid *vid,
73+
size_t *image_index, size_t *partition_index);
74+
6075
#ifdef __cplusplus
6176
}
6277
#endif

boot/bootutil/src/loader.c

Lines changed: 150 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr);
9292
#include <load_ironside_se_conf.h>
9393
#endif
9494

95+
#if defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID)
96+
#include "bootutil/mcuboot_uuid.h"
97+
98+
#ifdef SECOND_STAGE_MCUBOOT_RUNNING_FROM_S0
99+
#define MCUBOOT_INACTIVE_PARTITION_INDEX 1
100+
#define MCUBOOT_ACTIVE_PARTITION_INDEX 0
101+
#else
102+
#define MCUBOOT_INACTIVE_PARTITION_INDEX 0
103+
#define MCUBOOT_ACTIVE_PARTITION_INDEX 1
104+
#endif
105+
#endif
106+
95107
#ifdef CONFIG_SOC_EARLY_RESET_HOOK
96108
void s2ram_designate_slot(uint8_t slot);
97109
#endif
@@ -1024,6 +1036,56 @@ static inline void sec_slot_cleanup_if_unusable(void)
10241036
#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\
10251037
defined(MCUBOOT_IS_SECOND_STAGE) || defined(CONFIG_SOC_NRF5340_CPUAPP) */
10261038

1039+
#ifdef CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID
1040+
/**
1041+
* Read the image UUID from the TLV.
1042+
*
1043+
* @param[in] fap Pointer to the flash area structure.
1044+
* @param[in] hdr Pointer to the image header structure.
1045+
* @param[in] tlv_type The type of the TLV to read.
1046+
* @param[out] uuid Pointer to the image UUID structure.
1047+
*
1048+
* @return 0 on success,
1049+
* @retval -EINVAL if the input parameters are invalid.
1050+
* @retval -EIO if the TLV cannot be read.
1051+
* @retval -ENOENT if the TLV cannot be found.
1052+
*/
1053+
int read_image_uuid_tlv(const struct flash_area *fap,
1054+
const struct image_header *hdr,
1055+
uint16_t tlv_type,
1056+
struct image_uuid *uuid)
1057+
{
1058+
struct image_tlv_iter it;
1059+
uint32_t off;
1060+
uint16_t len;
1061+
int rc;
1062+
1063+
if ((fap == NULL) || (hdr == NULL) || (uuid == NULL)) {
1064+
return -EINVAL;
1065+
}
1066+
1067+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, tlv_type, false);
1068+
if (rc != 0) {
1069+
return -ENOENT;
1070+
}
1071+
1072+
rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
1073+
if (rc != 0) {
1074+
return -ENOENT;
1075+
}
1076+
1077+
if (len != sizeof(uuid->raw)) {
1078+
return -EINVAL;
1079+
}
1080+
1081+
if (flash_area_read(fap, off, uuid->raw, len) != 0) {
1082+
return -EIO;
1083+
}
1084+
1085+
return 0;
1086+
}
1087+
#endif /* CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID */
1088+
10271089
/**
10281090
* Determines which swap operation to perform, if any. If it is determined
10291091
* that a swap operation is required, the image in the secondary slot is checked
@@ -1038,12 +1100,25 @@ boot_validated_swap_type(struct boot_loader_state *state,
10381100
{
10391101
int swap_type;
10401102
FIH_DECLARE(fih_rc, FIH_FAILURE);
1103+
#if CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 \
1104+
&& !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP)
10411105
bool upgrade_valid = false;
1106+
#endif
10421107

10431108
#if defined(MCUBOOT_IS_SECOND_STAGE) || CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1
10441109
const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY);
10451110
struct image_header *hdr = boot_img_hdr(state, BOOT_SLOT_SECONDARY);
1111+
#if defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_LOAD_ADDRESS) || \
1112+
defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_RESET_VECTOR)
10461113
uint32_t reset_addr = 0;
1114+
#elif defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID)
1115+
struct image_uuid img_uuid_cid;
1116+
#ifdef MCUBOOT_UUID_VID
1117+
struct image_uuid img_uuid_vid;
1118+
#endif
1119+
size_t target_image = 0;
1120+
size_t target_partition = 0;
1121+
#endif
10471122
int rc = 0;
10481123
/* Patch needed for NCS. Since image 0 (the app) and image 1 (the other
10491124
* B1 slot S0 or S1) share the same secondary slot, we need to check
@@ -1054,13 +1129,19 @@ boot_validated_swap_type(struct boot_loader_state *state,
10541129
*/
10551130
NSIB_OWNED_UNSET(BOOT_CURR_IMG(state));
10561131

1132+
#if defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_LOAD_ADDRESS) || \
1133+
defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_RESET_VECTOR)
10571134
if (hdr->ih_magic == IMAGE_MAGIC) {
1135+
#ifdef CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_LOAD_ADDRESS
1136+
reset_addr = hdr->ih_load_addr;
1137+
#else
10581138
rc = flash_area_read(secondary_fa, hdr->ih_hdr_size +
10591139
sizeof(uint32_t), &reset_addr,
10601140
sizeof(reset_addr));
10611141
if (rc != 0) {
10621142
return BOOT_SWAP_TYPE_FAIL;
10631143
}
1144+
#endif
10641145

10651146
sec_slot_touch(state);
10661147

@@ -1110,7 +1191,62 @@ boot_validated_swap_type(struct boot_loader_state *state,
11101191
sec_slot_mark_assigned(state);
11111192
}
11121193

1113-
#endif /* MCUBOOT_IS_SECOND_STAGE || CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 */
1194+
#elif defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID)
1195+
if (hdr->ih_magic == IMAGE_MAGIC) {
1196+
rc = read_image_uuid_tlv(secondary_fa, hdr, IMAGE_TLV_UUID_CID, &img_uuid_cid);
1197+
if (rc != 0) {
1198+
return BOOT_SWAP_TYPE_NONE;
1199+
}
1200+
#ifdef MCUBOOT_UUID_VID
1201+
rc = read_image_uuid_tlv(secondary_fa, hdr, IMAGE_TLV_UUID_VID, &img_uuid_vid);
1202+
if (rc != 0) {
1203+
return BOOT_SWAP_TYPE_NONE;
1204+
}
1205+
#endif
1206+
1207+
sec_slot_touch(state);
1208+
1209+
rc = boot_uuid_find_image(&img_uuid_cid,
1210+
#ifdef MCUBOOT_UUID_VID
1211+
&img_uuid_vid,
1212+
#else
1213+
NULL,
1214+
#endif
1215+
&target_image, &target_partition);
1216+
if (rc != 0) {
1217+
/* Unable to find a matching image index. */
1218+
BOOT_LOG_ERR("Image in slot does not match any known UUID");
1219+
flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
1220+
sec_slot_untouch(state);
1221+
BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state));
1222+
return BOOT_SWAP_TYPE_FAIL;
1223+
}
1224+
1225+
if (target_image == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) {
1226+
/* This is a valid network core update candidate. */
1227+
#ifdef MCUBOOT_IS_SECOND_STAGE
1228+
} else if ((target_image == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) &&
1229+
(target_partition == MCUBOOT_INACTIVE_PARTITION_INDEX)) {
1230+
/* This is a valid MCUboot update candidate. */
1231+
NSIB_OWNED_SET(BOOT_CURR_IMG(state));
1232+
} else if ((target_image == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) &&
1233+
(target_partition == MCUBOOT_ACTIVE_PARTITION_INDEX)) {
1234+
/* NSIB upgrade but for the wrong slot, must be erased */
1235+
BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image");
1236+
flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
1237+
sec_slot_untouch(state);
1238+
BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state));
1239+
return BOOT_SWAP_TYPE_FAIL;
1240+
#endif /* MCUBOOT_IS_SECOND_STAGE */
1241+
} else {
1242+
/* The image in the secondary slot is not intended for any */
1243+
return BOOT_SWAP_TYPE_NONE;
1244+
}
1245+
1246+
sec_slot_mark_assigned(state);
1247+
}
1248+
#endif /* CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID */
1249+
#endif /* defined(MCUBOOT_IS_SECOND_STAGE) || CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 */
11141250

11151251
swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
11161252
if (BOOT_IS_UPGRADE(swap_type)) {
@@ -1124,8 +1260,11 @@ boot_validated_swap_type(struct boot_loader_state *state,
11241260
} else {
11251261
swap_type = BOOT_SWAP_TYPE_FAIL;
11261262
}
1263+
#if CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 \
1264+
&& !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP)
11271265
} else {
11281266
upgrade_valid = true;
1267+
#endif
11291268
}
11301269

11311270
#if CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 \
@@ -1134,8 +1273,16 @@ boot_validated_swap_type(struct boot_loader_state *state,
11341273
* update and indicate to the caller of this function that no update is
11351274
* available
11361275
*/
1137-
if (upgrade_valid && reset_addr >= NETCPU_APP_SLOT_OFFSET &&
1138-
reset_addr < NETCPU_APP_SLOT_END) {
1276+
if (upgrade_valid
1277+
#if defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_LOAD_ADDRESS) || \
1278+
defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_RESET_VECTOR)
1279+
&& reset_addr >= NETCPU_APP_SLOT_OFFSET && reset_addr < NETCPU_APP_SLOT_END
1280+
#elif defined(CONFIG_NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID)
1281+
&& (target_image == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER)
1282+
#else
1283+
#error Unable to detect radio image update candidate.
1284+
#endif
1285+
) {
11391286
struct image_header *hdr = (struct image_header *)secondary_fa->fa_off;
11401287
uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size;
11411288
uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr);

boot/zephyr/Kconfig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,36 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS
15431543
Time between image validation attempts, in milliseconds.
15441544
Allows for recovery from transient bit flips or similar situations.
15451545

1546+
choice NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE
1547+
prompt "Secondary slot image resolve method"
1548+
depends on MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1
1549+
default NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID if MCUBOOT_UUID_CID
1550+
default NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_LOAD_ADDRESS if MCUBOOT_CHECK_HEADER_LOAD_ADDRESS
1551+
default NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_RESET_VECTOR
1552+
1553+
config NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_RESET_VECTOR
1554+
bool "Reset vector"
1555+
help
1556+
The bootloader will use the reset vector, read from image, to assign image for a given
1557+
secondary slot.
1558+
This is the default behavior.
1559+
1560+
config NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_LOAD_ADDRESS
1561+
bool "Load address"
1562+
depends on MCUBOOT_CHECK_HEADER_LOAD_ADDRESS
1563+
help
1564+
The bootloader will use the load address, from the image header,
1565+
to assign image for a given secondary slot.
1566+
1567+
config NCS_MCUBOOT_SECONDARY_SLOT_IMAGE_RESOLVE_UUID
1568+
bool "Class ID (and Vendor ID if enabled) UUIDs"
1569+
depends on MCUBOOT_UUID_CID
1570+
help
1571+
The bootloader will use the Class ID and Vendor ID UUIDs, read from image, to assign
1572+
image for a given secondary slot.
1573+
1574+
endchoice
1575+
15461576
config PM_APP_ALIGNMENT
15471577
hex
15481578
default 0x1000 if SOC_SERIES_NRF54L

boot/zephyr/uuid/uuid.c

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,29 @@ static bool boot_uuid_compare(const struct image_uuid *uuid1, const struct image
1414
return false;
1515
}
1616

17-
return memcmp(uuid1->raw, uuid2->raw, ARRAY_SIZE(uuid1->raw)) == 0;
17+
return memcmp(uuid1->raw, uuid2->raw, sizeof(uuid1->raw)) == 0;
1818
}
1919

20-
fih_ret boot_uuid_init(void)
20+
#ifdef CONFIG_MCUBOOT_UUID_VID
21+
static bool vid_matches_map_entry(const struct image_uuid *vid, const struct uuid_map_entry *entry)
2122
{
22-
FIH_RET(FIH_SUCCESS);
23+
const struct uuid_map_entry *vid_map = NULL;
24+
size_t n_entries = boot_uuid_vid_map_get(&vid_map);
25+
26+
if (vid == NULL) {
27+
return false;
28+
}
29+
30+
for (size_t i = 0; i < n_entries; i++) {
31+
if ((vid_map[i].dev == entry->dev) && (vid_map[i].off == entry->off) &&
32+
(vid_map[i].size == entry->size) && boot_uuid_compare(vid, &vid_map[i].uuid)) {
33+
return true;
34+
}
35+
}
36+
37+
return false;
2338
}
2439

25-
#ifdef CONFIG_MCUBOOT_UUID_VID
2640
fih_ret boot_uuid_vid_match(const struct flash_area *fap, const struct image_uuid *uuid_vid)
2741
{
2842
const struct uuid_map_entry *map = NULL;
@@ -82,4 +96,50 @@ fih_ret boot_uuid_cid_match(const struct flash_area *fap, const struct image_uui
8296

8397
FIH_RET(FIH_FAILURE);
8498
}
99+
100+
int boot_uuid_find_image(const struct image_uuid *cid, const struct image_uuid *vid,
101+
size_t *image_index, size_t *partition_index)
102+
{
103+
const struct uuid_map_entry *cid_map = NULL;
104+
size_t n_entries;
105+
106+
if ((cid == NULL) || (image_index == NULL) || (partition_index == NULL)) {
107+
return -EINVAL;
108+
}
109+
110+
#ifdef MCUBOOT_UUID_VID
111+
if (vid == NULL) {
112+
return -EINVAL;
113+
}
114+
#endif
115+
116+
n_entries = boot_uuid_cid_map_get(&cid_map);
117+
if ((n_entries == 0) || (cid_map == NULL)) {
118+
return -ENOENT;
119+
}
120+
121+
for (size_t i = 0; i < n_entries; i++) {
122+
if (!boot_uuid_compare(cid, &cid_map[i].uuid)) {
123+
continue;
124+
}
125+
126+
#ifdef MCUBOOT_UUID_VID
127+
if (!vid_matches_map_entry(vid, &cid_map[i])) {
128+
continue;
129+
}
130+
#endif
131+
132+
*image_index = cid_map[i].image_index;
133+
*partition_index = cid_map[i].partition_index;
134+
135+
return 0;
136+
}
137+
138+
return -ENOENT;
139+
}
85140
#endif /* CONFIG_MCUBOOT_UUID_CID */
141+
142+
fih_ret boot_uuid_init(void)
143+
{
144+
FIH_RET(FIH_SUCCESS);
145+
}

0 commit comments

Comments
 (0)