Build: Enable nested macros for image script
This change enables the usage of nested macros in flash_layout.h
for setting the offset and max size for secure and non-secure images.
Change-Id: I87e2aec67550debb4d36286ed46bfe935a9003c8
Signed-off-by: Sverteczky, Marcell <marcell.sverteczky@arm.com>
diff --git a/bl2/ext/mcuboot/MCUBoot.cmake b/bl2/ext/mcuboot/MCUBoot.cmake
index c880f78..9770f99 100644
--- a/bl2/ext/mcuboot/MCUBoot.cmake
+++ b/bl2/ext/mcuboot/MCUBoot.cmake
@@ -61,11 +61,32 @@
set (ADD_SECURITY_COUNTER "")
endif()
+ set(FILE_TO_PREPROCESS ${CMAKE_BINARY_DIR}/image_macros_to_preprocess.c)
+ set(PREPROCESSED_FILE ${CMAKE_BINARY_DIR}/image_macros_preprocessed.c)
+ set(CONTENT_FOR_PREPROCESSING "#include \"${FLASH_LAYOUT}\"\n\n"
+ "/* Enumeration that is used by the assemble.py script for correct binary generation when nested macros are used */\n"
+ "enum image_attributes {\n"
+ "\tRE_SECURE_IMAGE_OFFSET = SECURE_IMAGE_OFFSET,\n"
+ "\tRE_SECURE_IMAGE_MAX_SIZE = SECURE_IMAGE_MAX_SIZE,\n"
+ "\tRE_NON_SECURE_IMAGE_OFFSET = NON_SECURE_IMAGE_OFFSET,\n"
+ "\tRE_NON_SECURE_IMAGE_MAX_SIZE = NON_SECURE_IMAGE_MAX_SIZE\n}\;"
+ )
+
+ #Create a file that will be preprocessed later in order to be able to handle nested macros
+ #in the flash_layout.h file for certain macros
+ file(WRITE ${FILE_TO_PREPROCESS} ${CONTENT_FOR_PREPROCESSING})
+
+ #Preprocess the .c file that contains the image related macros
+ compiler_preprocess_file(SRC ${FILE_TO_PREPROCESS}
+ DST ${PREPROCESSED_FILE}
+ BEFORE_TARGET ${_MY_PARAMS_NS_BIN}
+ TARGET_PREFIX ${_MY_PARAMS_NS_BIN})
+
add_custom_command(TARGET ${_MY_PARAMS_NS_BIN}
POST_BUILD
#Create concatenated binary image from the two binary file
COMMAND ${PYTHON_EXECUTABLE} ${MCUBOOT_DIR}/scripts/assemble.py
- ARGS -l ${FLASH_LAYOUT}
+ ARGS -l ${PREPROCESSED_FILE}
-s $<TARGET_FILE_DIR:${_MY_PARAMS_S_BIN}>/${_MY_PARAMS_S_BIN}.bin
-n $<TARGET_FILE_DIR:${_MY_PARAMS_NS_BIN}>/${_MY_PARAMS_NS_BIN}.bin
-o ${CMAKE_BINARY_DIR}/${_MY_PARAMS_FULL_BIN}.bin
diff --git a/bl2/ext/mcuboot/scripts/assemble.py b/bl2/ext/mcuboot/scripts/assemble.py
index 0bb41f1..f446f90 100644
--- a/bl2/ext/mcuboot/scripts/assemble.py
+++ b/bl2/ext/mcuboot/scripts/assemble.py
@@ -1,7 +1,7 @@
#! /usr/bin/env python3
#
# Copyright 2017 Linaro Limited
-# Copyright (c) 2017-2018, Arm Limited.
+# Copyright (c) 2017-2019, Arm Limited.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -26,8 +26,25 @@
import os
import shutil
-offset_re = re.compile(r"^#define ([0-9A-Z_]+)_IMAGE_OFFSET\s+((0x)?[0-9a-fA-F]+)")
-size_re = re.compile(r"^#define ([0-9A-Z_]+)_IMAGE_MAX_SIZE\s+((0x)?[0-9a-fA-F]+)")
+offset_re = re.compile(r"^\s*RE_([0-9A-Z_]+)_IMAGE_OFFSET\s*=\s*(((0x)?[0-9a-fA-F]+)\s*([\+\-]\s*((0x)?[0-9a-fA-F]+)\s*)*)")
+size_re = re.compile(r"^\s*RE_([0-9A-Z_]+)_IMAGE_MAX_SIZE\s*=\s*(((0x)?[0-9a-fA-F]+)\s*([\+\-]\s*((0x)?[0-9a-fA-F]+)\s*)*)")
+
+#Simple parser that takes a string and evaluates an expression from it.
+#The expression might contain additions and subtractions amongst numbers that are
+#written in decimal or hexadecimal form.
+def parse_and_sum(text):
+ nums = re.findall(r'[0x\d]+|[\d]+', text)
+ for i in range(len(nums)):
+ nums[i] = int(nums[i], 0)
+ ops = re.findall(r'\+|\-', text)
+ sum = nums[0]
+ for i in range(len(ops)):
+ if ops[i] == '+':
+ sum += nums[i+1]
+ else:
+ sum -= nums[i+1]
+ return sum
+
class Assembly():
def __init__(self, layout_path, output):
@@ -54,10 +71,10 @@
for line in fd:
m = offset_re.match(line)
if m is not None:
- offsets[m.group(1)] = int(m.group(2), 0)
+ offsets[m.group(1)] = parse_and_sum(m.group(2))
m = size_re.match(line)
if m is not None:
- sizes[m.group(1)] = int(m.group(2), 0)
+ sizes[m.group(1)] = parse_and_sum(m.group(2))
if 'SECURE' not in offsets:
raise Exception("Image config does not have secure partition")
@@ -97,7 +114,6 @@
args = parser.parse_args()
output = Assembly(args.layout, args.output)
-
output.add_image(args.secure, "SECURE")
output.add_image(args.non_secure, "NON_SECURE")
diff --git a/cmake/Common/CompilerArmClangCommon.cmake b/cmake/Common/CompilerArmClangCommon.cmake
index 53f143a..de3fea4 100644
--- a/cmake/Common/CompilerArmClangCommon.cmake
+++ b/cmake/Common/CompilerArmClangCommon.cmake
@@ -148,3 +148,75 @@
function(compiler_generate_binary_output TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_ARMCCLANG_FROMELF} ARGS --bincombined --output=$<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin $<TARGET_FILE:${TARGET}>)
endfunction()
+
+# Function for creating a new target that preprocesses a .c file
+#INPUTS:
+# SRC - (mandatory) - file to be preprocessed
+# DST - (mandatory) - output file for the preprocessing
+# TARGET_PREFIX - (optional) - prefix for the target that this function creates and which manages the preprocessing
+# BEFORE_TARGET - (optional) - target which is dependent on the preprocessing target in the below function
+function(compiler_preprocess_file)
+ #Option (on/off) arguments.
+ set( _OPTIONS_ARGS)
+ #Single option arguments.
+ set( _ONE_VALUE_ARGS SRC DST TARGET_PREFIX BEFORE_TARGET)
+ #List arguments
+ set( _MULTI_VALUE_ARGS)
+ cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} )
+
+ #Check passed parameters
+ if(NOT DEFINED _MY_PARAMS_SRC)
+ message(FATAL_ERROR "compiler_preprocess_file: mandatory parameter 'SRC' is missing.")
+ endif()
+
+ if(NOT DEFINED _MY_PARAMS_DST)
+ message(FATAL_ERROR "compiler_preprocess_file: mandatory parameter 'DST' is missing.")
+ endif()
+
+ if(DEFINED _MY_PARAMS_BEFORE_TARGET)
+ if(NOT TARGET ${_MY_PARAMS_BEFORE_TARGET})
+ message(FATAL_ERROR "compiler_preprocess_file: optional parameter 'BEFORE_TARGET' is not target.")
+ endif()
+ endif()
+
+ #The compiler flag might contain leading spaces which can fail the preprocess operation, these are removed
+ STRING(STRIP ${CMAKE_C_FLAGS_CPU} _MY_TEMP_CMAKE_C_FLAGS_CPU)
+ #If a string contains spaces, then it is inserted amongst quotation marks. Furthermore the compiler fails if it is
+ #called with multiple switches included in one quotation mark. If the extra spaces are replaced by semicolons,
+ #then the insertion will be advantageous for the compiler.
+ STRING(REPLACE " " ";" _MY_TEMP2_CMAKE_C_FLAGS_CPU ${_MY_TEMP_CMAKE_C_FLAGS_CPU})
+ set(_LOCAL_CMAKE_C_FLAGS_CPU "")
+ foreach(_C_FLAG IN LISTS _MY_TEMP2_CMAKE_C_FLAGS_CPU)
+ list(APPEND _LOCAL_CMAKE_C_FLAGS_CPU "${_C_FLAG}")
+ endforeach()
+
+ add_custom_command(OUTPUT ${_MY_PARAMS_DST}
+ COMMAND ${CMAKE_C_COMPILER} ${_LOCAL_CMAKE_C_FLAGS_CPU} -E -P -xc ${_MY_PARAMS_SRC} -o ${_MY_PARAMS_DST}
+ DEPENDS ${_MY_PARAMS_SRC}
+ COMMENT "Preprocess the ${_MY_PARAMS_SRC} file"
+ )
+
+ set(_MY_TARGET_PREFIX "")
+ if(TARGET ${_MY_PARAMS_TARGET_PREFIX})
+ set(_MY_TARGET_PREFIX "${_MY_PARAMS_TARGET_PREFIX}")
+ endif()
+ #The preprocessing related target name is obtained by indexing the file's name that is to be preprocessed
+ get_filename_component(_MY_FILENAME_TO_BE_INDEXED ${_MY_PARAMS_SRC} NAME_WE)
+ foreach(_SUFFIX RANGE 1 100)
+ if (NOT TARGET ${_MY_TARGET_PREFIX}_pp_${_MY_FILENAME_TO_BE_INDEXED}_${_SUFFIX})
+ set(_PREPROCESS_TARGET_NAME "${_MY_TARGET_PREFIX}_pp_${_MY_FILENAME_TO_BE_INDEXED}_${_SUFFIX}")
+ break()
+ endif()
+ if (_SUFFIX EQUAL 100)
+ message(FATAL_ERROR "You have called 'compiler_preprocess_file' too many times (${_SUFFIX} function calls).")
+ endif()
+ endforeach()
+
+ #Make the original target depend on the new one.
+ if(TARGET ${_MY_PARAMS_BEFORE_TARGET})
+ add_custom_target(${_PREPROCESS_TARGET_NAME} DEPENDS ${_MY_PARAMS_DST})
+ add_dependencies(${_MY_PARAMS_BEFORE_TARGET} ${_PREPROCESS_TARGET_NAME})
+ else()
+ add_custom_target(${_PREPROCESS_TARGET_NAME} ALL DEPENDS ${_MY_PARAMS_DST})
+ endif()
+endfunction()
diff --git a/cmake/Common/CompilerGNUARMCommon.cmake b/cmake/Common/CompilerGNUARMCommon.cmake
index 51945c6..2f7639f 100644
--- a/cmake/Common/CompilerGNUARMCommon.cmake
+++ b/cmake/Common/CompilerGNUARMCommon.cmake
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+# Copyright (c) 2017-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -75,37 +75,20 @@
endif()
set(_FILE_PATH ${_MY_PARAMS_PATH})
- #Compose additional command line switches from macro definitions.
- set(_FLAGS "")
- if (_MY_PARAMS_DEFINES)
- foreach(_DEFINE IN LISTS _MY_PARAMS_DEFINES)
- list(APPEND _FLAGS "-D${_DEFINE}")
- endforeach()
- endif()
- #Compose additional command line switches from include paths.
- if (_MY_PARAMS_INCLUDES)
- foreach(_INCLUDE_P IN LISTS _MY_PARAMS_INCLUDES)
- list(APPEND _FLAGS "-I${_INCLUDE_P}")
- endforeach()
- endif()
-
#Create additional target if linker script needs to be pre-processed.
if (_MY_PARAMS_DEFINES OR _MY_PARAMS_INCLUDES)
#Name of pre-processed linker script file.
set(FINAL_LD_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${_MY_PARAMS_TARGET}.ld.i")
#Name of the target doing the pre-processing
set(LD_PP_TARGET_NAME "${_MY_PARAMS_TARGET}_ldpp")
- #The target definition.
- add_custom_target(${LD_PP_TARGET_NAME}
- COMMENT "Pre-processing linker command file ${_MY_PARAMS_PATH}..."
- COMMAND ${CMAKE_C_COMPILER} -E -P -xc ${_FLAGS} -o ${FINAL_LD_FILE_NAME} ${_MY_PARAMS_PATH}
- DEPENDS ${_MY_PARAMS_PATH}
- BYPRODUCTS ${FINAL_LD_FILE_NAME}
- )
- #Make the original target depend on the new one.
- add_dependencies(${_MY_PARAMS_TARGET} ${LD_PP_TARGET_NAME})
- #Tell cmake to delete the intermediate linker script when the clean rule
- #is executed.
+ compiler_preprocess_file(SRC ${_MY_PARAMS_PATH}
+ DST ${FINAL_LD_FILE_NAME}
+ TARGET_PREFIX ${_MY_PARAMS_TARGET}
+ BEFORE_TARGET ${_MY_PARAMS_TARGET}
+ DEFINES ${_MY_PARAMS_DEFINES}
+ INCLUDES ${_MY_PARAMS_INCLUDES})
+
+ #Tell cmake to delete the intermediate linker script when the clean rule is executed.
get_directory_property(_ADDITIONAL_MAKE_CLEAN_FILES DIRECTORY "./" ADDITIONAL_MAKE_CLEAN_FILES)
set_directory_properties(PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_ADDITIONAL_MAKE_CLEAN_FILES} ${FINAL_LD_FILE_NAME}")
#Set the path to linker script point to the intermediate file.
@@ -169,3 +152,92 @@
function(compiler_generate_binary_output TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_GNUARM_OBJCOPY} ARGS -O binary $<TARGET_FILE:${TARGET}> $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin)
endfunction()
+
+# Function for creating a new target that preprocesses a .c file
+#INPUTS:
+# SRC - (mandatory) - file to be preprocessed
+# DST - (mandatory) - output file for the preprocessing
+# TARGET_PREFIX - (optional) - prefix for the target that this function creates and which manages the preprocessing
+# BEFORE_TARGET - (optional) - target which is dependent on the preprocessing target in the below function
+# DEFINES - (optional) - additional command line switches from macro definitions for preprocessing
+# INCLUDES - (optional) - additional command line switches from include paths for preprocessing
+function(compiler_preprocess_file)
+ #Option (on/off) arguments.
+ set( _OPTIONS_ARGS)
+ #Single option arguments.
+ set( _ONE_VALUE_ARGS SRC DST TARGET_PREFIX BEFORE_TARGET)
+ #List arguments
+ set( _MULTI_VALUE_ARGS DEFINES INCLUDES)
+ cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} )
+
+ #Check passed parameters
+ if(NOT DEFINED _MY_PARAMS_SRC)
+ message(FATAL_ERROR "compiler_preprocess_file: mandatory parameter 'SRC' is missing.")
+ endif()
+
+ if(NOT DEFINED _MY_PARAMS_DST)
+ message(FATAL_ERROR "compiler_preprocess_file: mandatory parameter 'DST' is missing.")
+ endif()
+
+ if(DEFINED _MY_PARAMS_BEFORE_TARGET)
+ if(NOT TARGET ${_MY_PARAMS_BEFORE_TARGET})
+ message(FATAL_ERROR "compiler_preprocess_file: optional parameter 'BEFORE_TARGET' is not target.")
+ endif()
+ endif()
+
+ #Compose additional command line switches from macro definitions.
+ set(_FLAGS "")
+ if (_MY_PARAMS_DEFINES)
+ foreach(_DEFINE IN LISTS _MY_PARAMS_DEFINES)
+ list(APPEND _FLAGS "-D${_DEFINE}")
+ endforeach()
+ endif()
+
+ #Compose additional command line switches from include paths.
+ if (_MY_PARAMS_INCLUDES)
+ foreach(_INCLUDE IN LISTS _MY_PARAMS_INCLUDES)
+ list(APPEND _FLAGS "-I${_INCLUDE}")
+ endforeach()
+ endif()
+
+ #The compiler flag might contain leading spaces which can fail the preprocess operation, these are removed
+ STRING(STRIP ${CMAKE_C_FLAGS_CPU} _MY_TEMP_CMAKE_C_FLAGS_CPU)
+ #If a string contains spaces, then it is inserted amongst quotation marks. Furthermore the compiler fails if it is
+ #called with multiple switches included in one quotation mark. If the extra spaces are replaced by semicolons,
+ #then the insertion will be advantageous for the compiler.
+ STRING(REPLACE " " ";" _MY_TEMP2_CMAKE_C_FLAGS_CPU ${_MY_TEMP_CMAKE_C_FLAGS_CPU})
+ set(_LOCAL_CMAKE_C_FLAGS_CPU "")
+ foreach(_C_FLAG IN LISTS _MY_TEMP2_CMAKE_C_FLAGS_CPU)
+ list(APPEND _LOCAL_CMAKE_C_FLAGS_CPU "${_C_FLAG}")
+ endforeach()
+
+ add_custom_command(OUTPUT ${_MY_PARAMS_DST}
+ COMMAND ${CMAKE_C_COMPILER} ${_LOCAL_CMAKE_C_FLAGS_CPU} -E -P -xc ${_FLAGS} ${_MY_PARAMS_SRC} -o ${_MY_PARAMS_DST}
+ DEPENDS ${_MY_PARAMS_SRC}
+ COMMENT "Preprocess the ${_MY_PARAMS_SRC} file"
+ )
+
+ set(_MY_TARGET_PREFIX "")
+ if(TARGET ${_MY_PARAMS_TARGET_PREFIX})
+ set(_MY_TARGET_PREFIX "${_MY_PARAMS_TARGET_PREFIX}")
+ endif()
+ #The preprocessing related target name is obtained by indexing the file's name that is to be preprocessed
+ get_filename_component(_MY_FILENAME_TO_BE_INDEXED ${_MY_PARAMS_SRC} NAME_WE)
+ foreach(_SUFFIX RANGE 1 100)
+ if (NOT TARGET ${_MY_TARGET_PREFIX}_pp_${_MY_FILENAME_TO_BE_INDEXED}_${_SUFFIX})
+ set(_PREPROCESS_TARGET_NAME "${_MY_TARGET_PREFIX}_pp_${_MY_FILENAME_TO_BE_INDEXED}_${_SUFFIX}")
+ break()
+ endif()
+ if (_SUFFIX EQUAL 100)
+ message(FATAL_ERROR "You have called 'compiler_preprocess_file' too many times (${_SUFFIX} function calls).")
+ endif()
+ endforeach()
+
+ #Make the original target depend on the new one.
+ if(TARGET ${_MY_PARAMS_BEFORE_TARGET})
+ add_custom_target(${_PREPROCESS_TARGET_NAME} DEPENDS ${_MY_PARAMS_DST})
+ add_dependencies(${_MY_PARAMS_BEFORE_TARGET} ${_PREPROCESS_TARGET_NAME})
+ else()
+ add_custom_target(${_PREPROCESS_TARGET_NAME} ALL DEPENDS ${_MY_PARAMS_DST})
+ endif()
+endfunction()