Skip to content

Commit 5155061

Browse files
committed
[nrf noup] boot/bootutil/loader: image discovery by ih_load_address
Introduce alternative procedure for detecting to which partition image candidate belongs. This method uses ih_load_address field of the image header instead of reset vector address. This allows to match incoming image to the partition even when it is for instance encrypted, as the image header is always plain-text. This new procedure can be enabled using CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDR=y. Firmware need to be signed with imgtool.py sign --rom-fixed <partition_address> parameter. ref.: NCSIDB-1173 Signed-off-by: Andrzej Puzdrowski <[email protected]>
1 parent d24b28f commit 5155061

File tree

2 files changed

+40
-22
lines changed

2 files changed

+40
-22
lines changed

boot/bootutil/src/loader.c

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,15 +1331,19 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
13311331
if (fap == BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT)) {
13321332
const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
13331333
struct image_header *secondary_hdr = boot_img_hdr(state, slot);
1334-
uint32_t reset_value = 0;
1335-
uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value);
1334+
uint32_t internal_img_addr = 0; /* either the reset handler addres or the image beginning addres */
13361335
uint32_t min_addr, max_addr;
13371336
bool check_addresses = false;
13381337

1339-
if (flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)) != 0) {
1338+
#ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDR
1339+
internal_img_addr = secondary_hdr->ih_load_addr;
1340+
#else
1341+
if (flash_area_read(fap, secondary_hdr->ih_hdr_size + sizeof(internal_img_addr),
1342+
&internal_img_addr, sizeof(internal_img_addr)) != 0) {
13401343
fih_rc = FIH_NO_BOOTABLE_IMAGE;
13411344
goto out;
13421345
}
1346+
#endif
13431347

13441348
#ifdef PM_CPUNET_APP_ADDRESS
13451349
/* The primary slot for the network core is emulated in RAM.
@@ -1380,7 +1384,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
13801384
check_addresses = true;
13811385
}
13821386

1383-
if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) {
1387+
if (check_addresses == true && (internal_img_addr < min_addr || internal_img_addr > max_addr)) {
13841388
BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot");
13851389
BOOT_LOG_ERR("Erasing image from secondary slot");
13861390

@@ -1597,6 +1601,17 @@ static inline void sec_slot_cleanup_if_unusable(void)
15971601
#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\
15981602
defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */
15991603

1604+
#define IS_IN_RANGE_CPUNET_APP_ADDR(_addr) ((_addr) >= PM_CPUNET_APP_ADDRESS && (_addr) < PM_CPUNET_APP_END_ADDRESS)
1605+
#define _IS_IN_RANGE_S_VARIANT_ADDR(_addr, x) ((_addr) >= PM_S##x_ADDRESS && (_addr) <= (PM_S##x_ADDRESS + PM_S##x_SIZE))
1606+
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1607+
#define IS_IN_RANGE_S_ALTERNATE_ADDR(_addr) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
1608+
#define IS_IN_RANGE_S_CURRENT_ADDR(_addr) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
1609+
#else
1610+
#define IS_IN_RANGE_S_ALTERNATE_ADDR(_addr) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 1)
1611+
#define IS_IN_RANGE_S_CURRENT_ADDR(_addr) _IS_IN_RANGE_S_VARIANT_ADDR(_addr, 0)
1612+
#endif
1613+
#define IS_IN_RANGE_IMAGE_ADDR(_addr, _fa) ((_addr) >= _fa->fa_off && (_addr) < (_fa->fa_off + _fa->fa_size))
1614+
16001615
/**
16011616
* Determines which swap operation to perform, if any. If it is determined
16021617
* that a swap operation is required, the image in the secondary slot is checked
@@ -1620,8 +1635,9 @@ boot_validated_swap_type(struct boot_loader_state *state,
16201635
const struct flash_area *secondary_fa =
16211636
BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
16221637
struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
1623-
uint32_t reset_addr = 0;
1638+
uint32_t internal_img_addr = 0; /* either the reset handler addres or the image beginning addres */
16241639
int rc = 0;
1640+
16251641
/* Patch needed for NCS. Since image 0 (the app) and image 1 (the other
16261642
* B1 slot S0 or S1) share the same secondary slot, we need to check
16271643
* whether the update candidate in the secondary slot is intended for
@@ -1631,18 +1647,22 @@ boot_validated_swap_type(struct boot_loader_state *state,
16311647
*/
16321648

16331649
if (hdr->ih_magic == IMAGE_MAGIC) {
1650+
#ifdef CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDR
1651+
internal_img_addr = hdr->ih_load_addr;
1652+
#else
16341653
rc = flash_area_read(secondary_fa, hdr->ih_hdr_size +
1635-
sizeof(uint32_t), &reset_addr,
1636-
sizeof(reset_addr));
1654+
sizeof(uint32_t), &internal_img_addr,
1655+
sizeof(internal_img_addr));
16371656
if (rc != 0) {
16381657
return BOOT_SWAP_TYPE_FAIL;
16391658
}
1659+
#endif /* CONFIG_MCUBOOT_USE_CHECK_LOAD_ADDR */
16401660

16411661
sec_slot_touch(state);
16421662

16431663
#ifdef PM_S1_ADDRESS
16441664
#ifdef PM_CPUNET_B0N_ADDRESS
1645-
if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS))
1665+
if(!IS_IN_RANGE_CPUNET_APP_ADDR(internal_img_addr))
16461666
#endif
16471667
{
16481668
const struct flash_area *primary_fa;
@@ -1654,11 +1674,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
16541674
}
16551675

16561676
/* Check start and end of primary slot for current image */
1657-
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1658-
if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
1659-
#else
1660-
if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
1661-
#endif
1677+
if (IS_IN_RANGE_S_ALTERNATE_ADDR(internal_img_addr)) {
16621678
if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) {
16631679
/* This is not the s0/s1 upgrade image but the application image, pretend
16641680
* there is no image so the NSIB update can be loaded
@@ -1667,18 +1683,14 @@ boot_validated_swap_type(struct boot_loader_state *state,
16671683
}
16681684

16691685
owner_nsib[BOOT_CURR_IMG(state)] = true;
1670-
#if (CONFIG_NCS_IS_VARIANT_IMAGE)
1671-
} else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) {
1672-
#else
1673-
} else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) {
1674-
#endif
1686+
} else if (IS_IN_RANGE_S_CURRENT_ADDR(internal_img_addr)) {
16751687
/* NSIB upgrade but for the wrong slot, must be erased */
16761688
BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image");
16771689
flash_area_erase(secondary_fa, 0, secondary_fa->fa_size);
16781690
sec_slot_untouch(state);
16791691
BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state));
16801692
return BOOT_SWAP_TYPE_FAIL;
1681-
} else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) {
1693+
} else if (!IS_IN_RANGE_IMAGE_ADDR(internal_img_addr, primary_fa)) {
16821694
/* The image in the secondary slot is not intended for any */
16831695
return BOOT_SWAP_TYPE_NONE;
16841696
}
@@ -1715,8 +1727,7 @@ boot_validated_swap_type(struct boot_loader_state *state,
17151727
* update and indicate to the caller of this function that no update is
17161728
* available
17171729
*/
1718-
if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS &&
1719-
reset_addr < PM_CPUNET_APP_END_ADDRESS) {
1730+
if (upgrade_valid && IS_IN_RANGE_CPUNET_APP_ADDR(internal_img_addr)) {
17201731
struct image_header *hdr = (struct image_header *)secondary_fa->fa_off;
17211732
uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size;
17221733
uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr);

boot/zephyr/Kconfig

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1283,10 +1283,17 @@ config USB_DEVICE_PRODUCT
12831283
config MCUBOOT_BOOTUTIL_LIB_OWN_LOG
12841284
bool
12851285

1286+
config MCUBOOT_USE_CHECK_LOAD_ADDR
1287+
bool "use check of load address"
1288+
help
1289+
If y, the bootloader will use the load address from image header
1290+
for checking to which slot image belongs instead of usage of reset
1291+
handler address reading from the image.
1292+
12861293
config MCUBOOT_VERIFY_IMG_ADDRESS
12871294
bool "Verify reset address of image in secondary slot"
12881295
depends on UPDATEABLE_IMAGE_NUMBER > 1
1289-
depends on !BOOT_ENCRYPT_IMAGE
1296+
depends on !BOOT_ENCRYPT_IMAGE || MCUBOOT_USE_CHECK_LOAD_ADDR
12901297
depends on ARM
12911298
default y if BOOT_UPGRADE_ONLY
12921299
help

0 commit comments

Comments
 (0)