From 16856ae8e56290bb00f2f075ae563fdb8da42efb Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 13 Jun 2025 15:00:10 +0200 Subject: [PATCH] [nrf fromlist] linker: Use zephyr,code-partition value Enforce usage of values from devicetree if USE_DT_CODE_PARTITION Kconfig symbol is enabled. Currently even if this symbol is enabled, the FLASH_LOAD_OFFSET value is used in the linker script. The FLASH_LOAD_OFFSET symbol, even being promptless is such case, may be changed, leading to a very confusing situation, where devicetree values have no effect on the build. A good example of the build that wants to use exactly the same set of configs, but a different link address is the A/B update scheme (known ad Direct XIP in MCUboot), where the same application is linked to two different addresses. If the source of the address remains in the Kconifg, the current approach forces a usage of two different configurations. Upstream PR #: 91591 Signed-off-by: Tomasz Chyrowicz --- CMakeLists.txt | 24 +++++++++--- cmake/linker_script/arm/linker.cmake | 17 +++++++-- .../arch/arm/cortex_a_r/scripts/linker.ld | 16 ++++++-- .../arch/arm/cortex_m/scripts/linker.ld | 16 ++++++-- include/zephyr/arch/arm64/scripts/linker.ld | 16 ++++++-- include/zephyr/arch/riscv/common/linker.ld | 10 ++++- scripts/west_commands/runners/core.py | 38 ++++++++++++++++++- .../mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c | 14 +++++-- 8 files changed, 122 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abe74033e62..b0d46b4121e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1874,16 +1874,30 @@ if(CONFIG_BUILD_OUTPUT_BIN AND CONFIG_BUILD_OUTPUT_UF2) if(CONFIG_BUILD_OUTPUT_UF2_USE_FLASH_BASE) set(code_address "${CONFIG_FLASH_BASE_ADDRESS}") else() - set(code_address "${CONFIG_FLASH_LOAD_OFFSET}") + if(CONFIG_USE_DT_CODE_PARTITION) + dt_chosen(chosen_code_partition PROPERTY "zephyr,code-partition") + dt_reg_addr(code_address PATH ${chosen_code_partition}) + else() + set(code_address "${CONFIG_FLASH_LOAD_OFFSET}") + endif() endif() if(CONFIG_BUILD_OUTPUT_UF2_USE_FLASH_OFFSET) # Note, the `+ 0` in formula below avoids errors in cases where a Kconfig # variable is undefined and thus expands to nothing. - math(EXPR code_address - "${code_address} + ${CONFIG_FLASH_LOAD_OFFSET} + 0" - OUTPUT_FORMAT HEXADECIMAL - ) + if(CONFIG_USE_DT_CODE_PARTITION) + dt_chosen(chosen_code_partition PROPERTY "zephyr,code-partition") + dt_reg_addr(flash_code_partition_addr PATH ${chosen_code_partition}) + math(EXPR code_address + "${code_address} + ${flash_code_partition_addr} + 0" + OUTPUT_FORMAT HEXADECIMAL + ) + else() + math(EXPR code_address + "${code_address} + ${CONFIG_FLASH_LOAD_OFFSET} + 0" + OUTPUT_FORMAT HEXADECIMAL + ) + endif() endif() # No-XIP images (such as ones for RP2350 with CONFIG_XIP=n) diff --git a/cmake/linker_script/arm/linker.cmake b/cmake/linker_script/arm/linker.cmake index 116c2485b0b..a47349f3af6 100644 --- a/cmake/linker_script/arm/linker.cmake +++ b/cmake/linker_script/arm/linker.cmake @@ -33,21 +33,30 @@ endif() zephyr_linker_include_var(VAR APP_SHARED_ALIGN_BYTES VALUE ${region_min_align}) zephyr_linker_include_var(VAR SMEM_PARTITION_ALIGN_BYTES VALUE ${MPU_ALIGN_BYTES}) +if(CONFIG_USE_DT_CODE_PARTITION) + dt_chosen(chosen_code_partition PROPERTY "zephyr,code-partition") + dt_reg_addr(flash_code_partition_addr PATH ${chosen_code_partition}) + dt_reg_size(flash_code_partition_size PATH ${chosen_code_partition}) +else() + set(flash_code_partition_addr "${CONFIG_FLASH_LOAD_OFFSET}") + set(flash_code_partition_size "${CONFIG_FLASH_LOAD_SIZE}") +endif() + # Note, the `+ 0` in formulas below avoids errors in cases where a Kconfig # variable is undefined and thus expands to nothing. math(EXPR FLASH_ADDR - "${CONFIG_FLASH_BASE_ADDRESS} + ${CONFIG_FLASH_LOAD_OFFSET} + 0" + "${CONFIG_FLASH_BASE_ADDRESS} + ${flash_code_partition_addr} + 0" OUTPUT_FORMAT HEXADECIMAL ) -if(CONFIG_FLASH_LOAD_SIZE GREATER 0) +if(flash_code_partition_size GREATER 0) math(EXPR FLASH_SIZE - "(${CONFIG_FLASH_LOAD_SIZE} + 0) - (${CONFIG_ROM_END_OFFSET} + 0)" + "(${flash_code_partition_size} + 0) - (${CONFIG_ROM_END_OFFSET} + 0)" OUTPUT_FORMAT HEXADECIMAL ) else() math(EXPR FLASH_SIZE - "(${CONFIG_FLASH_SIZE} + 0) * 1024 - (${CONFIG_FLASH_LOAD_OFFSET} + 0) - (${CONFIG_ROM_END_OFFSET} + 0)" + "(${CONFIG_FLASH_SIZE} + 0) * 1024 - (${flash_code_partition_addr} + 0) - (${CONFIG_ROM_END_OFFSET} + 0)" OUTPUT_FORMAT HEXADECIMAL ) endif() diff --git a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld index 1567c50a780..ca3824576a9 100644 --- a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld @@ -34,10 +34,18 @@ #define ROMSTART_REGION ROMABLE_REGION #endif +#if CONFIG_USE_DT_CODE_PARTITION +#define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) +#define FLASH_LOAD_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_code_partition)) +#else +#define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET +#define FLASH_LOAD_SIZE CONFIG_FLASH_LOAD_SIZE +#endif + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else - #define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET) + #define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + FLASH_LOAD_OFFSET) #endif #if defined(CONFIG_ROM_END_OFFSET) @@ -46,10 +54,10 @@ #define ROM_END_OFFSET 0 #endif -#if CONFIG_FLASH_LOAD_SIZE > 0 - #define ROM_SIZE (CONFIG_FLASH_LOAD_SIZE - ROM_END_OFFSET) +#if FLASH_LOAD_SIZE > 0 + #define ROM_SIZE (FLASH_LOAD_SIZE - ROM_END_OFFSET) #else - #define ROM_SIZE (CONFIG_FLASH_SIZE*1K - CONFIG_FLASH_LOAD_OFFSET - ROM_END_OFFSET) + #define ROM_SIZE (CONFIG_FLASH_SIZE*1K - FLASH_LOAD_OFFSET - ROM_END_OFFSET) #endif #define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index c8579f2a802..a023f57d34d 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -67,10 +67,18 @@ _image_1_primary_slot_id = PM_S1_ID; #else /* ! USE_PARTITION_MANAGER */ +#if CONFIG_USE_DT_CODE_PARTITION +#define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) +#define FLASH_LOAD_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_code_partition)) +#else +#define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET +#define FLASH_LOAD_SIZE CONFIG_FLASH_LOAD_SIZE +#endif + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else -#define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET) +#define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + FLASH_LOAD_OFFSET) #endif #if defined(CONFIG_ROM_END_OFFSET) @@ -79,10 +87,10 @@ _image_1_primary_slot_id = PM_S1_ID; #define ROM_END_OFFSET 0 #endif -#if CONFIG_FLASH_LOAD_SIZE > 0 -#define ROM_SIZE (CONFIG_FLASH_LOAD_SIZE - ROM_END_OFFSET) +#if FLASH_LOAD_SIZE > 0 +#define ROM_SIZE (FLASH_LOAD_SIZE - ROM_END_OFFSET) #else -#define ROM_SIZE (CONFIG_FLASH_SIZE * 1024 - CONFIG_FLASH_LOAD_OFFSET - ROM_END_OFFSET) +#define ROM_SIZE (CONFIG_FLASH_SIZE * 1024 - FLASH_LOAD_OFFSET - ROM_END_OFFSET) #endif #define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) diff --git a/include/zephyr/arch/arm64/scripts/linker.ld b/include/zephyr/arch/arm64/scripts/linker.ld index ee29e43b77b..3db32be2cf9 100644 --- a/include/zephyr/arch/arm64/scripts/linker.ld +++ b/include/zephyr/arch/arm64/scripts/linker.ld @@ -26,10 +26,18 @@ #endif #define RAMABLE_REGION RAM +#if CONFIG_USE_DT_CODE_PARTITION +#define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) +#define FLASH_LOAD_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_code_partition)) +#else +#define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET +#define FLASH_LOAD_SIZE CONFIG_FLASH_LOAD_SIZE +#endif + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else - #define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET) + #define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + FLASH_LOAD_OFFSET) #endif #if defined(CONFIG_ROM_END_OFFSET) @@ -38,10 +46,10 @@ #define ROM_END_OFFSET 0 #endif -#if CONFIG_FLASH_LOAD_SIZE > 0 - #define ROM_SIZE (CONFIG_FLASH_LOAD_SIZE - ROM_END_OFFSET) +#if FLASH_LOAD_SIZE > 0 + #define ROM_SIZE (FLASH_LOAD_SIZE - ROM_END_OFFSET) #else - #define ROM_SIZE (CONFIG_FLASH_SIZE * 1K - CONFIG_FLASH_LOAD_OFFSET - ROM_END_OFFSET) + #define ROM_SIZE (CONFIG_FLASH_SIZE * 1K - FLASH_LOAD_OFFSET - ROM_END_OFFSET) #endif #define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) diff --git a/include/zephyr/arch/riscv/common/linker.ld b/include/zephyr/arch/riscv/common/linker.ld index 62b04b919cd..f03e249d88b 100644 --- a/include/zephyr/arch/riscv/common/linker.ld +++ b/include/zephyr/arch/riscv/common/linker.ld @@ -35,16 +35,22 @@ #define ROM_END_OFFSET 0 #endif +#if CONFIG_USE_DT_CODE_PARTITION +#define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) +#define FLASH_LOAD_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_code_partition)) +#else #if defined(CONFIG_FLASH_LOAD_OFFSET) #define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET #else #define FLASH_LOAD_OFFSET 0 #endif +#define FLASH_LOAD_SIZE CONFIG_FLASH_LOAD_SIZE +#endif #ifdef CONFIG_XIP -#if CONFIG_FLASH_LOAD_SIZE > 0 -#define ROM_SIZE (CONFIG_FLASH_LOAD_SIZE - ROM_END_OFFSET) +#if FLASH_LOAD_SIZE > 0 +#define ROM_SIZE (FLASH_LOAD_SIZE - ROM_END_OFFSET) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), soc_nv_flash, okay) diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index 611848f671c..e4682396c6d 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -16,6 +16,8 @@ import errno import logging import os +import pathlib +import pickle import platform import re import selectors @@ -715,13 +717,45 @@ def get_flash_address(args: argparse.Namespace, else: return default + @staticmethod + def get_chosen_code_partition_offset(build_dir: str): + '''Get the offset corresponding to the zephyr,code-partition.''' + b = pathlib.Path(build_dir) + edt_pickle = b / 'zephyr' / 'edt.pickle' + if not edt_pickle.is_file(): + raise RuntimeError('cannot load devicetree; expected to find:' + + str(edt_pickle)) + + # Load the devicetree. + try: + with open(edt_pickle, 'rb') as f: + edt = pickle.load(f) + except ModuleNotFoundError as err: + raise RuntimeError('could not load devicetree, something may be' + 'wrong with the python environment') from err + + # Find the zephyr,code-partition node. + node = edt.chosen_node('zephyr,code-partition') + if node is not None: + return node.regs[0].addr + + return None + @staticmethod def flash_address_from_build_conf(build_conf: BuildConfiguration): - '''If CONFIG_HAS_FLASH_LOAD_OFFSET is n in build_conf, + '''If CONFIG_USE_DT_CODE_PARTITION return zephyr,code-partition + offset + CONFIG_FLASH_BASE_ADDRESS. + If CONFIG_HAS_FLASH_LOAD_OFFSET is n in build_conf, return the CONFIG_FLASH_BASE_ADDRESS value. Otherwise, return CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET. ''' - if build_conf.getboolean('CONFIG_HAS_FLASH_LOAD_OFFSET'): + if build_conf.getboolean('CONFIG_USE_DT_CODE_PARTITION'): + offset = ZephyrBinaryRunner.get_chosen_code_partition_offset(build_conf.build_dir) + if offset is None: + raise RuntimeError('The device tree zephyr,code-partition chosen' + ' node must be defined.') + return build_conf['CONFIG_FLASH_BASE_ADDRESS'] + offset + elif build_conf.getboolean('CONFIG_HAS_FLASH_LOAD_OFFSET'): return (build_conf['CONFIG_FLASH_BASE_ADDRESS'] + build_conf['CONFIG_FLASH_LOAD_OFFSET']) else: diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c index 05e3a9c6488..5ce815a582f 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c @@ -60,14 +60,20 @@ BUILD_ASSERT(PM_MCUBOOT_PAD_SIZE == PM_MCUBOOT_SECONDARY_PAD_SIZE); (FIXED_PARTITION_OFFSET(label) == (PM_ADDRESS - PM_ADDRESS_OFFSET)) #else /* ! USE_PARTITION_MANAGER */ -#ifndef CONFIG_FLASH_LOAD_OFFSET + +#ifdef CONFIG_USE_DT_CODE_PARTITION +#define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) +#elif defined(CONFIG_FLASH_LOAD_OFFSET) +#define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET +#endif + +#ifndef FLASH_LOAD_OFFSET #error MCUmgr requires application to be built with CONFIG_FLASH_LOAD_OFFSET set \ to be able to figure out application running slot. #endif -#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ - (FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET) -#endif /* USE_PARTITION_MANAGER */ +#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (FIXED_PARTITION_OFFSET(label) == FLASH_LOAD_OFFSET) BUILD_ASSERT(sizeof(struct image_header) == IMAGE_HEADER_SIZE, "struct image_header not required size");