cmake: support ELF image adjustment

This commit adds support for adjust the addresses of the final image.
This is useful when the image is to be flashed at a location different
from the LMA address encoded in the ELF file by the linker.

An example use-case is multicore systems where core A might load image
from a flash partition into RAM in order for core B to execute and load,
but where the image itself is build with the RAM addresses as LMA.

It updates the zephyr_image_info.h header with information of adjustment
value.

Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit is contained in:
Torsten Rasmussen 2022-01-12 14:21:07 +01:00 committed by Christopher Friedt
commit d51a67b7c0
4 changed files with 45 additions and 2 deletions

View file

@ -1393,6 +1393,18 @@ if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE)
endif()
endif()
if(CONFIG_BUILD_OUTPUT_ADJUST_LMA)
math(EXPR adjustment "${CONFIG_BUILD_OUTPUT_ADJUST_LMA}" OUTPUT_FORMAT DECIMAL)
list(APPEND
post_build_commands
COMMAND $<TARGET_PROPERTY:bintools,elfconvert_command>
$<TARGET_PROPERTY:bintools,elfconvert_flag_final>
$<TARGET_PROPERTY:bintools,elfconvert_flag_lma_adjust>${adjustment}
$<TARGET_PROPERTY:bintools,elfconvert_flag_infile>${KERNEL_ELF_NAME}
$<TARGET_PROPERTY:bintools,elfconvert_flag_outfile>${KERNEL_ELF_NAME}
)
endif()
if(CONFIG_BUILD_OUTPUT_HEX OR BOARD_FLASH_RUNNER STREQUAL openocd)
get_property(elfconvert_formats TARGET bintools PROPERTY elfconvert_formats)
if(ihex IN_LIST elfconvert_formats)
@ -1582,6 +1594,7 @@ if(CONFIG_BUILD_OUTPUT_INFO_HEADER)
COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/gen_image_info.py
--elf-file=${KERNEL_ELF_NAME}
--header-file=${PROJECT_BINARY_DIR}/include/public/zephyr_image_info.h
$<$<BOOL:${adjustment}>:--adjusted-lma=${adjustment}>
)
list(APPEND
post_build_byproducts

View file

@ -494,6 +494,30 @@ config BUILD_OUTPUT_STRIPPED
Build a stripped binary zephyr/zephyr.strip in the build directory.
The name of this file can be customized with CONFIG_KERNEL_BIN_NAME.
config BUILD_OUTPUT_ADJUST_LMA
string
help
This will adjust the LMA address in the final ELF and hex files with
the value provided.
This will not affect the internal address symbols inside the image but
can be useful when adjusting the LMA address for flash tools or multi
stage loaders where a pre-loader may copy image to a second location
before booting a second core.
The value will be evaluated as a math expression, this means that
following are valid expression
- 1024
- 0x1000
- -0x1000
- 0x20000000 - 0x10000000
Note: negative numbers are valid.
To adjust according to a chosen flash partition one can specify a
default as:
DT_CHOSEN_IMAGE_<name> := <name>,<name>-partition
DT_CHOSEN_Z_FLASH := zephyr,flash
config BUILD_OUTPUT_ADJUST_LMA
default "$(dt_chosen_reg_addr_hex,$(DT_CHOSEN_IMAGE_M4))-\
$(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH))"
config BUILD_OUTPUT_INFO_HEADER
bool "Create a image information header"
help

View file

@ -41,6 +41,8 @@ set_property(TARGET bintools PROPERTY elfconvert_flag_section_remove "--remove-s
set_property(TARGET bintools PROPERTY elfconvert_flag_section_only "--only-section=")
set_property(TARGET bintools PROPERTY elfconvert_flag_section_rename "--rename-section;")
set_property(TARGET bintools PROPERTY elfconvert_flag_lma_adjust "--change-section-lma;*+")
# Note, placing a ';' at the end results in the following param to be a list,
# and hence space separated.
# Thus the command line argument becomes:

View file

@ -16,6 +16,7 @@ Information included in the image information header:
- Number of segments in the image
- LMA address of each segment
- VMA address of each segment
- LMA adjusted of each segment if the LMA addresses has been adjusted after linking
- Size of each segment
'''
@ -23,7 +24,7 @@ import argparse
from elftools.elf.elffile import ELFFile
def write_header(filename, segments):
def write_header(filename, segments, adjusted_lma):
content = []
filename_we = filename.split('.h')[0].upper()
@ -31,6 +32,7 @@ def write_header(filename, segments):
content.append(f'#define {filename_we}_H')
content.append(f'')
content.append(f'#define SEGMENT_NUM {len(segments)}')
content.append(f'#define ADJUSTED_LMA {adjusted_lma}')
for idx, segment in enumerate(segments):
segment_header = segment['segment'].header
@ -69,10 +71,12 @@ def main():
help="""Header file to write with image data.""")
parser.add_argument('--elf-file', required=True,
help="""ELF File to process.""")
parser.add_argument('--adjusted-lma', required=False, default=0,
help="""Adjusted LMA address value.""")
args = parser.parse_args()
segments = read_segments(args.elf_file)
write_header(args.header_file, segments)
write_header(args.header_file, segments, args.adjusted_lma)
if __name__ == "__main__":