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")