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 <Torsten.Rasmussen@nordicsemi.no>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af6c8cc..092b9ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1576,6 +1576,19 @@
)
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 bc64c6c..04f7c19 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 d2d3e0a..9d43b6b 100644
--- a/Kconfig.zephyr
+++ b/Kconfig.zephyr
@@ -494,6 +494,17 @@
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 0000000..aad71b1
--- /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()