From cbbdbef1b020a5b78b2af3cd9369910949c2b3aa 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 0effc0c381c..205b5c4e42a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1793,16 +1793,30 @@ if(CONFIG_BUILD_OUTPUT_BIN AND CONFIG_BUILD_OUTPUT_UF2) if(CONFIG_BUILD_OUTPUT_UF2_USE_FLASH_BASE) set(flash_addr "${CONFIG_FLASH_BASE_ADDRESS}") else() - set(flash_addr "${CONFIG_FLASH_LOAD_OFFSET}") + if(CONFIG_USE_DT_CODE_PARTITION) + dt_chosen(chosen_code_partition PROPERTY "zephyr,code-partition") + dt_reg_addr(flash_addr PATH ${chosen_code_partition}) + else() + set(flash_addr "${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 flash_addr - "${flash_addr} + ${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 flash_addr + "${flash_addr} + ${flash_code_partition_addr} + 0" + OUTPUT_FORMAT HEXADECIMAL + ) + else() + math(EXPR flash_addr + "${flash_addr} + ${CONFIG_FLASH_LOAD_OFFSET} + 0" + OUTPUT_FORMAT HEXADECIMAL + ) + endif() endif() list(APPEND diff --git a/cmake/linker_script/arm/linker.cmake b/cmake/linker_script/arm/linker.cmake index 2a4f61f6e15..7a634607e35 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 ba5413c1a77..1eaf1e16e86 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 ae4fbcaedda..ba9d50ea429 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 a63bc034d64..67803d6d2f4 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 eb380d9403a..85bea454519 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 8d84e445606..008b39e2149 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");