From c8ddc34bb87ffcbb7c52a73bd1f332eaee98a152 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Mon, 10 Jan 2022 11:02:26 +0100 Subject: [PATCH] scripts: generate image info header file This commit adds the `gen_image_info.py` script which supports creation of a header file with image information from the EFL file. This version populates the header file with: - Number of segments in the image - LMA address of each segment - VMA address of each segment - Size of each segment The header file can be used by a secondary build system which needs this information. Signed-off-by: Torsten Rasmussen --- CMakeLists.txt | 13 +++++++ CODEOWNERS | 1 + Kconfig.zephyr | 11 ++++++ scripts/gen_image_info.py | 79 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 scripts/gen_image_info.py diff --git a/CMakeLists.txt b/CMakeLists.txt index af6c8cc3682..092b9ad31f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1576,6 +1576,19 @@ if(CONFIG_BUILD_OUTPUT_EXE) ) endif() +if(CONFIG_BUILD_OUTPUT_INFO_HEADER) + list(APPEND + post_build_commands + 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 + ) + list(APPEND + post_build_byproducts + ${PROJECT_BINARY_DIR}/include/public/zephyr_image_info.h + ) +endif() + # Generate and use MCUboot related artifacts as needed. if(CONFIG_BOOTLOADER_MCUBOOT) include(${CMAKE_CURRENT_LIST_DIR}/cmake/mcuboot.cmake) diff --git a/CODEOWNERS b/CODEOWNERS index bc64c6c7fc7..04f7c19f02b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -658,6 +658,7 @@ /scripts/pylib/twister/expr_parser.py @nashif /scripts/schemas/twister/ @nashif /scripts/gen_app_partitions.py @dcpleung @nashif +scripts/gen_image_info.py @tejlmand /scripts/get_maintainer.py @nashif /scripts/dts/ @mbolivar-nordic @galak /scripts/release/ @nashif diff --git a/Kconfig.zephyr b/Kconfig.zephyr index d2d3e0a8db1..9d43b6bab63 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -494,6 +494,17 @@ 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_INFO_HEADER + bool "Create a image information header" + help + Create an image information header which will contain image + information from the Zephyr binary. + Example of information contained in the header file: + - Number of segments in the image + - LMA address of each segment + - VMA address of each segment + - Size of each segment + config APPLICATION_DEFINED_SYSCALL bool "Scan application folder for any syscall definition" help diff --git a/scripts/gen_image_info.py b/scripts/gen_image_info.py new file mode 100644 index 00000000000..aad71b1e3e5 --- /dev/null +++ b/scripts/gen_image_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022, Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +''' +Script to generate image information files. + +This script creates a image information header which can be included by a +second build system. +This allows a second stage build system to use image information from a Zephyr +build by including the generated header. + +Information included in the image information header: +- Number of segments in the image +- LMA address of each segment +- VMA address of each segment +- Size of each segment +''' + +import argparse +from elftools.elf.elffile import ELFFile + + +def write_header(filename, segments): + content = [] + + filename_we = filename.split('.h')[0].upper() + content.append(f'#ifndef {filename_we}_H') + content.append(f'#define {filename_we}_H') + content.append(f'') + content.append(f'#define SEGMENT_NUM {len(segments)}') + + for idx, segment in enumerate(segments): + segment_header = segment['segment'].header + hex_lma_addr = hex(segment_header.p_paddr) + hex_vma_addr = hex(segment_header.p_vaddr) + hex_size = hex(segment_header.p_filesz) + + content.append(f'') + content.append(f'#define SEGMENT_LMA_ADDRESS_{idx} {hex_lma_addr}') + content.append(f'#define SEGMENT_VMA_ADDRESS_{idx} {hex_vma_addr}') + content.append(f'#define SEGMENT_SIZE_{idx} {hex_size}') + + content.append(f'') + content.append(f'#endif /* {filename_we}_H */') + + with open(filename, 'w') as out_file: + out_file.write('\n'.join(content)) + + +def read_segments(filename): + elffile = ELFFile(open(filename, 'rb')) + segments = list() + for segment_idx in range(elffile.num_segments()): + segments.insert(segment_idx, dict()) + segments[segment_idx]['segment'] = elffile.get_segment(segment_idx) + return segments + + +def main(): + parser = argparse.ArgumentParser(description=''' + Process ELF file and extract image information. + Create header file with extracted image information which can be included + in other build systems.''') + + parser.add_argument('--header-file', required=True, + help="""Header file to write with image data.""") + parser.add_argument('--elf-file', required=True, + help="""ELF File to process.""") + args = parser.parse_args() + + segments = read_segments(args.elf_file) + write_header(args.header_file, segments) + + +if __name__ == "__main__": + main()