Build: Sign the S and NS images separately

This patch modifies the build system to sign the secure and non-secure
images independently if the MCUBOOT_IMAGE_NUMBER build time switch is
greater than 1. This way the bootloader will be able to handle and
update the S and NS images separately.

Add separate security counter and image version variables for the S and
NS images in the build system. They can be specified at build time with
the SECURITY_COUNTER_S/_NS and IMAGE_VERSION_S/_NS defines.
In that case if any of the security counter values is missing, the
counter value will be generated just like in case of single image boot
(derived from image version).

Change-Id: Ia971fda818b92a7b27ee26f1b3893986322fd62e
Signed-off-by: David Vincze <david.vincze@arm.com>
diff --git a/CommonConfig.cmake b/CommonConfig.cmake
index 58cabd1..aa261c0 100644
--- a/CommonConfig.cmake
+++ b/CommonConfig.cmake
@@ -54,10 +54,6 @@
 	include(${PLATFORM_CMAKE_FILE})
 endif()
 
-if (NOT DEFINED IMAGE_VERSION)
-	set(IMAGE_VERSION 0.0.0+0)
-endif()
-
 if(${COMPILER} STREQUAL "ARMCLANG")
 	#Use any ARMCLANG version found on PATH. Note: Only versions supported by the
 	#build system will work. A file cmake/Common/CompilerArmClangXY.cmake
diff --git a/bl2/ext/mcuboot/MCUBoot.cmake b/bl2/ext/mcuboot/MCUBoot.cmake
index 621c9ba..d40ca7e 100644
--- a/bl2/ext/mcuboot/MCUBoot.cmake
+++ b/bl2/ext/mcuboot/MCUBoot.cmake
@@ -8,9 +8,9 @@
 cmake_minimum_required(VERSION 3.7)
 
 function(mcuboot_create_boot_payload)
-	set( _OPTIONS_ARGS)                                          #Option (on/off) arguments (e.g. IGNORE_CASE)
+	set( _OPTIONS_ARGS)										  #Option (on/off) arguments (e.g. IGNORE_CASE)
 	set( _ONE_VALUE_ARGS S_BIN NS_BIN FULL_BIN SIGN_BIN POSTFIX) #Single option arguments (e.g. PATH "./foo/bar")
-	set( _MULTI_VALUE_ARGS)                                      #List arguments (e.g. LANGUAGES C ASM CXX)
+	set( _MULTI_VALUE_ARGS)									  #List arguments (e.g. LANGUAGES C ASM CXX)
 	cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
 
 	if (NOT DEFINED _MY_PARAMS_S_BIN)
@@ -55,15 +55,7 @@
 		message(FATAL_ERROR "${MCUBOOT_SIGNATURE_TYPE} is not supported as firmware signing algorithm")
 	endif()
 
-	if (SECURITY_COUNTER)
-		set (ADD_SECURITY_COUNTER "-s ${SECURITY_COUNTER}")
-	else()
-		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"
+	set(PARTIAL_CONTENT_FOR_PREPROCESSING "#include \"${FLASH_LAYOUT}\"\n\n"
 		"/* Enumeration that is used by the assemble.py and imgtool.py scripts\n"
 		" * for correct binary generation when nested macros are used\n"
 		" */\n"
@@ -75,9 +67,129 @@
 		"#ifdef IMAGE_LOAD_ADDRESS\n"
 		"\tRE_IMAGE_LOAD_ADDRESS = IMAGE_LOAD_ADDRESS,\n"
 		"#endif\n"
-		"\tRE_SIGN_BIN_SIZE = SIGN_BIN_SIZE\n}\;"
 	)
 
+if (MCUBOOT_IMAGE_NUMBER GREATER 1)
+	if (SECURITY_COUNTER_S)
+		set(ADD_SECURITY_COUNTER_S "-s ${SECURITY_COUNTER_S}")
+	else()
+		set(ADD_SECURITY_COUNTER_S "")
+	endif()
+	if (SECURITY_COUNTER_NS)
+		set(ADD_SECURITY_COUNTER_NS "-s ${SECURITY_COUNTER_NS}")
+	else()
+		set(ADD_SECURITY_COUNTER_NS "")
+	endif()
+	if (DEFINED SECURITY_COUNTER)
+		message(WARNING "In case of multiple updatable images the security counter value can be specified"
+			" for the Secure and Non-secure images separately with the SECURITY_COUNTER_S and SECURITY_COUNTER_NS"
+			" defines. The value of SECURITY_COUNTER was ignored.")
+		set(SECURITY_COUNTER "")
+	endif()
+
+	if (NOT IMAGE_VERSION_S)
+		set(IMAGE_VERSION_S 0.0.0+0)
+	endif()
+	if (NOT IMAGE_VERSION_NS)
+		set(IMAGE_VERSION_NS 0.0.0+0)
+	endif()
+	if (DEFINED IMAGE_VERSION)
+		message(WARNING "In case of multiple updatable images the image version can be specified"
+			" for the Secure and Non-secure images separately with the IMAGE_VERSION_S and IMAGE_VERSION_NS"
+			" defines. The value of IMAGE_VERSION was ignored.")
+		set(IMAGE_VERSION "")
+	endif()
+
+	set(FILE_TO_PREPROCESS ${CMAKE_BINARY_DIR}/image_macros_to_preprocess)
+	set(PREPROCESSED_FILE ${CMAKE_BINARY_DIR}/image_macros_preprocessed)
+
+	#Create files that will be preprocessed later in order to be able to handle
+	# nested macros in header files for certain macros
+	string(CONCAT CONTENT_FOR_PREPROCESSING ${PARTIAL_CONTENT_FOR_PREPROCESSING}
+			"\tRE_SIGN_BIN_SIZE = FLASH_AREA_0_SIZE,\n}\;")
+	file(WRITE ${FILE_TO_PREPROCESS}_s.c ${CONTENT_FOR_PREPROCESSING})
+	string(CONCAT CONTENT_FOR_PREPROCESSING ${PARTIAL_CONTENT_FOR_PREPROCESSING}
+			"\tRE_SIGN_BIN_SIZE = FLASH_AREA_1_SIZE,\n}\;")
+	file(WRITE ${FILE_TO_PREPROCESS}_ns.c ${CONTENT_FOR_PREPROCESSING})
+
+	#Preprocess the _s.c file that contains the secure image related macros
+	compiler_preprocess_file(SRC ${FILE_TO_PREPROCESS}_s.c
+							DST ${PREPROCESSED_FILE}_s.c
+							BEFORE_TARGET ${_MY_PARAMS_S_BIN}
+							TARGET_PREFIX ${_MY_PARAMS_S_BIN}
+							DEFINES "MCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER}")
+
+	#Preprocess the _ns.c file that contains the non-secure image related macros
+	compiler_preprocess_file(SRC ${FILE_TO_PREPROCESS}_ns.c
+							DST ${PREPROCESSED_FILE}_ns.c
+							BEFORE_TARGET ${_MY_PARAMS_NS_BIN}
+							TARGET_PREFIX ${_MY_PARAMS_NS_BIN}
+							DEFINES "MCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER}")
+
+	add_custom_command(TARGET ${_MY_PARAMS_NS_BIN}
+						POST_BUILD
+
+						#Sign secure binary image with default public key in mcuboot folder
+						COMMAND ${PYTHON_EXECUTABLE} ${MCUBOOT_DIR}/scripts/imgtool.py
+						ARGS sign
+							 --layout ${PREPROCESSED_FILE}_s.c
+							 -k ${KEY_FILE}
+							 --align 1
+							 -v ${IMAGE_VERSION_S}
+							 ${ADD_SECURITY_COUNTER_S}
+							 -H 0x400
+							 $<TARGET_FILE_DIR:${_MY_PARAMS_S_BIN}>/${_MY_PARAMS_S_BIN}.bin
+							 ${CMAKE_BINARY_DIR}/${_MY_PARAMS_S_BIN}_signed.bin
+
+						#Sign non-secure binary image with default public key in mcuboot folder
+						COMMAND ${PYTHON_EXECUTABLE} ${MCUBOOT_DIR}/scripts/imgtool.py
+						ARGS sign
+							 --layout ${PREPROCESSED_FILE}_ns.c
+							 -k ${KEY_FILE}
+							 --align 1
+							 -v ${IMAGE_VERSION_NS}
+							 ${ADD_SECURITY_COUNTER_NS}
+							 -H 0x400
+							 $<TARGET_FILE_DIR:${_MY_PARAMS_NS_BIN}>/${_MY_PARAMS_NS_BIN}.bin
+							 ${CMAKE_BINARY_DIR}/${_MY_PARAMS_NS_BIN}_signed.bin
+
+						#Create concatenated binary image from the two independently signed binary file
+						COMMAND ${PYTHON_EXECUTABLE} ${MCUBOOT_DIR}/scripts/assemble.py
+						ARGS --layout ${PREPROCESSED_FILE}_s.c
+							 -s ${CMAKE_BINARY_DIR}/${_MY_PARAMS_S_BIN}_signed.bin
+							 -n ${CMAKE_BINARY_DIR}/${_MY_PARAMS_NS_BIN}_signed.bin
+							 -o ${CMAKE_BINARY_DIR}/${_MY_PARAMS_SIGN_BIN}.bin)
+
+else() # MCUBOOT_IMAGE_NUMBER = 1
+	if (SECURITY_COUNTER)
+		set(ADD_SECURITY_COUNTER "-s ${SECURITY_COUNTER}")
+	else()
+		set(ADD_SECURITY_COUNTER "")
+	endif()
+	if (DEFINED SECURITY_COUNTER_S OR
+		DEFINED SECURITY_COUNTER_NS)
+		message(WARNING "In case of a single updatable image the security counter value can be specified with"
+			" the SECURITY_COUNTER define. The values of SECURITY_COUNTER_S and/or SECURITY_COUNTER_NS were ignored.")
+		set(SECURITY_COUNTER_S "")
+		set(SECURITY_COUNTER_NS "")
+	endif()
+
+	if (NOT IMAGE_VERSION)
+		set(IMAGE_VERSION 0.0.0+0)
+	endif()
+	if (DEFINED IMAGE_VERSION_S OR
+		DEFINED IMAGE_VERSION_NS)
+		message(WARNING "In case of a single updatable image the image version can be specified with"
+			" the IMAGE_VERSION define. The values of IMAGE_VERSION_S and/or IMAGE_VERSION_NS were ignored.")
+		set(IMAGE_VERSION_S "")
+		set(IMAGE_VERSION_NS "")
+	endif()
+
+	set(FILE_TO_PREPROCESS ${CMAKE_BINARY_DIR}/image_macros_to_preprocess.c)
+	set(PREPROCESSED_FILE ${CMAKE_BINARY_DIR}/image_macros_preprocessed.c)
+	string(CONCAT CONTENT_FOR_PREPROCESSING ${PARTIAL_CONTENT_FOR_PREPROCESSING}
+			"\tRE_SIGN_BIN_SIZE = FLASH_AREA_0_SIZE,\n}\;")
+
 	#Create a file that will be preprocessed later in order to be able to handle nested macros
 	#in header files for certain macros
 	file(WRITE ${FILE_TO_PREPROCESS} ${CONTENT_FOR_PREPROCESSING})
@@ -109,9 +221,9 @@
 							 -H 0x400
 							 ${CMAKE_BINARY_DIR}/${_MY_PARAMS_FULL_BIN}.bin
 							 ${CMAKE_BINARY_DIR}/${_MY_PARAMS_SIGN_BIN}.bin)
+endif()
 
 	#Collect executables to common location: build/install/outputs/
-	set(TFM_FULL_NAME tfm_s_ns_concatenated)
 	set(TFM_SIGN_NAME tfm_s_ns_signed)
 
 	if (DEFINED MY_POSTFIX)
@@ -123,16 +235,27 @@
 				DESTINATION outputs/${TARGET_PLATFORM}/)
 	endif()
 
-	install(FILES  ${CMAKE_BINARY_DIR}/${_MY_PARAMS_FULL_BIN}.bin
-			DESTINATION outputs/${TARGET_PLATFORM}/)
-
-	install(FILES  ${CMAKE_BINARY_DIR}/${_MY_PARAMS_FULL_BIN}.bin
-			RENAME ${TFM_FULL_NAME}${_MY_PARAMS_POSTFIX}.bin
-			DESTINATION outputs/fvp/)
-
 	install(FILES  ${CMAKE_BINARY_DIR}/${_MY_PARAMS_SIGN_BIN}.bin
 			RENAME ${TFM_SIGN_NAME}${_MY_PARAMS_POSTFIX}.bin
 			DESTINATION outputs/fvp/)
+
+if (MCUBOOT_IMAGE_NUMBER GREATER 1)
+	install(FILES ${CMAKE_BINARY_DIR}/${_MY_PARAMS_S_BIN}_signed.bin
+			${CMAKE_BINARY_DIR}/${_MY_PARAMS_NS_BIN}_signed.bin
+			DESTINATION outputs/${TARGET_PLATFORM}/)
+	install(FILES ${CMAKE_BINARY_DIR}/${_MY_PARAMS_S_BIN}_signed.bin
+			${CMAKE_BINARY_DIR}/${_MY_PARAMS_NS_BIN}_signed.bin
+			DESTINATION outputs/fvp/)
+
+else() # MCUBOOT_IMAGE_NUMBER = 1
+	set(TFM_FULL_NAME tfm_s_ns_concatenated)
+
+	install(FILES  ${CMAKE_BINARY_DIR}/${_MY_PARAMS_FULL_BIN}.bin
+			DESTINATION outputs/${TARGET_PLATFORM}/)
+	install(FILES  ${CMAKE_BINARY_DIR}/${_MY_PARAMS_FULL_BIN}.bin
+			RENAME ${TFM_FULL_NAME}${_MY_PARAMS_POSTFIX}.bin
+			DESTINATION outputs/fvp/)
+endif()
 endfunction()
 
 #Validate and override the upgrade strategy to be used by the bootloader.
diff --git a/bl2/ext/mcuboot/MCUBootConfig.cmake b/bl2/ext/mcuboot/MCUBootConfig.cmake
index 2aa6112..f0d8114 100644
--- a/bl2/ext/mcuboot/MCUBootConfig.cmake
+++ b/bl2/ext/mcuboot/MCUBootConfig.cmake
@@ -44,8 +44,21 @@
 		set(MCUBOOT_SIGNATURE_TYPE "")
 	endif()
 
-	if (DEFINED SECURITY_COUNTER)
-		message(WARNING "Ignoring the value of SECURITY_COUNTER variable as BL2 option is set to False.")
+	if (DEFINED SECURITY_COUNTER OR
+		DEFINED SECURITY_COUNTER_S OR
+		DEFINED SECURITY_COUNTER_NS)
+		message(WARNING "Ignoring the values of SECURITY_COUNTER and/or SECURITY_COUNTER_* variables as BL2 option is set to False.")
 		set(SECURITY_COUNTER "")
+		set(SECURITY_COUNTER_S "")
+		set(SECURITY_COUNTER_NS "")
+	endif()
+
+	if (DEFINED IMAGE_VERSION OR
+		DEFINED IMAGE_VERSION_S OR
+		DEFINED IMAGE_VERSION_NS)
+		message(WARNING "Ignoring the values of IMAGE_VERSION and/or IMAGE_VERSION_* variables as BL2 option is set to False.")
+		set(IMAGE_VERSION "")
+		set(IMAGE_VERSION_S "")
+		set(IMAGE_VERSION_NS "")
 	endif()
 endif()
diff --git a/bl2/ext/mcuboot/scripts/imgtool.py b/bl2/ext/mcuboot/scripts/imgtool.py
index b226faf..1976f72 100644
--- a/bl2/ext/mcuboot/scripts/imgtool.py
+++ b/bl2/ext/mcuboot/scripts/imgtool.py
@@ -42,6 +42,7 @@
 
 def next_version_number(args, defaultVersion, path):
     newVersion = None
+    versionProvided = False
     if (version.compare(args.version, defaultVersion) == 0): # Default version
         lastVersion = get_last_version(path)
         if (lastVersion is not None):
@@ -49,6 +50,7 @@
         else:
             newVersion = version.increment_build_num(defaultVersion)
     else: # Version number has been explicitly provided (not using the default)
+        versionProvided = True
         newVersion = args.version
     versionString = "{a}.{b}.{c}+{d}".format(
                     a=str(newVersion.major),
@@ -56,8 +58,9 @@
                     c=str(newVersion.revision),
                     d=str(newVersion.build)
     )
-    with open(path, "w") as newFile:
-        newFile.write(versionString)
+    if not versionProvided:
+        with open(path, "w") as newFile:
+            newFile.write(versionString)
     print("**[INFO]** Image version number set to " + versionString)
     return newVersion
 
diff --git a/platform/ext/readme.rst b/platform/ext/readme.rst
index 6b2e1d4..cc28aa3 100644
--- a/platform/ext/readme.rst
+++ b/platform/ext/readme.rst
@@ -139,10 +139,8 @@
 Image tool
 ^^^^^^^^^^^^^
 The ``imgtool.py`` tool is used to handle the tasks related to signing the
-binary. It requires the following definitions:
+binary. It requires the following definition:
 
-- ``SIGN_BIN_SIZE`` - Defines the size of the concatenated binary that is to
-  be signed.
 - ``IMAGE_LOAD_ADDRESS`` - Defines the address to where the image is loaded
   and is executed from. Only used in case the ``MCUBOOT_UPGRADE_STRATEGY``
   is configured to be ``RAM_LOADING``.
diff --git a/platform/ext/target/mps2/an519/partition/flash_layout.h b/platform/ext/target/mps2/an519/partition/flash_layout.h
index d78199c..37938b4 100644
--- a/platform/ext/target/mps2/an519/partition/flash_layout.h
+++ b/platform/ext/target/mps2/an519/partition/flash_layout.h
@@ -166,10 +166,6 @@
                                          SECURE_IMAGE_MAX_SIZE)
 #define NON_SECURE_IMAGE_MAX_SIZE       FLASH_NS_PARTITION_SIZE
 
-/* Concatenated binary size used by imgtool.py */
-#define SIGN_BIN_SIZE                   (FLASH_S_PARTITION_SIZE + \
-                                         FLASH_NS_PARTITION_SIZE)
-
 /* Flash device name used by BL2
  * Name is defined in flash driver file: Driver_Flash.c
  */
diff --git a/platform/ext/target/mps2/an521/partition/flash_layout.h b/platform/ext/target/mps2/an521/partition/flash_layout.h
index 5700878..d09ef07 100644
--- a/platform/ext/target/mps2/an521/partition/flash_layout.h
+++ b/platform/ext/target/mps2/an521/partition/flash_layout.h
@@ -166,10 +166,6 @@
                                          SECURE_IMAGE_MAX_SIZE)
 #define NON_SECURE_IMAGE_MAX_SIZE       FLASH_NS_PARTITION_SIZE
 
-/* Concatenated binary size used by imgtool.py */
-#define SIGN_BIN_SIZE                   (FLASH_S_PARTITION_SIZE + \
-                                         FLASH_NS_PARTITION_SIZE)
-
 /* Flash device name used by BL2
  * Name is defined in flash driver file: Driver_Flash.c
  */
diff --git a/platform/ext/target/mps3/an524/partition/flash_layout.h b/platform/ext/target/mps3/an524/partition/flash_layout.h
index c1b84b4..35d472a 100644
--- a/platform/ext/target/mps3/an524/partition/flash_layout.h
+++ b/platform/ext/target/mps3/an524/partition/flash_layout.h
@@ -142,10 +142,6 @@
                                          SECURE_IMAGE_MAX_SIZE)
 #define NON_SECURE_IMAGE_MAX_SIZE       FLASH_NS_PARTITION_SIZE
 
-/* Concatenated binary size used by imgtool.py */
-#define SIGN_BIN_SIZE                   (FLASH_S_PARTITION_SIZE + \
-                                         FLASH_NS_PARTITION_SIZE)
-
 /* Flash device name used by BL2
  * Name is defined in flash driver file: Driver_Flash.c
  */
diff --git a/platform/ext/target/musca_a/partition/flash_layout.h b/platform/ext/target/musca_a/partition/flash_layout.h
index 6ab4dab..89d8083 100644
--- a/platform/ext/target/musca_a/partition/flash_layout.h
+++ b/platform/ext/target/musca_a/partition/flash_layout.h
@@ -146,9 +146,7 @@
                                          SECURE_IMAGE_MAX_SIZE)
 #define NON_SECURE_IMAGE_MAX_SIZE       FLASH_NS_PARTITION_SIZE
 
-/* Concatenated binary size and image load address used by imgtool.py */
-#define SIGN_BIN_SIZE                   (FLASH_S_PARTITION_SIZE + \
-                                         FLASH_NS_PARTITION_SIZE)
+/* Image load address used by imgtool.py */
 #define IMAGE_LOAD_ADDRESS              (S_SRAM_ALIAS_BASE + \
                                          FLASH_AREA_BL2_SIZE)
 
diff --git a/platform/ext/target/musca_b1/partition/flash_layout.h b/platform/ext/target/musca_b1/partition/flash_layout.h
index f730d74..10108d9 100644
--- a/platform/ext/target/musca_b1/partition/flash_layout.h
+++ b/platform/ext/target/musca_b1/partition/flash_layout.h
@@ -144,10 +144,6 @@
                                          SECURE_IMAGE_MAX_SIZE)
 #define NON_SECURE_IMAGE_MAX_SIZE       FLASH_NS_PARTITION_SIZE
 
-/* Concatenated binary size used by imgtool.py */
-#define SIGN_BIN_SIZE                   (FLASH_S_PARTITION_SIZE + \
-                                         FLASH_NS_PARTITION_SIZE)
-
 /* Flash device name used by BL2
  * Name is defined in flash driver file: Driver_Flash.c
  */