Tools: Make SPM backend a user configuration

The backend is decided by the number of SFN/IPC Partitions in building.
But sometimes the build system needs to know the backend in advance.
For example, the build system enables different test Partitions for
different backends. And The IPC backend will support both IPC and SFN
Partitions in the future.

This patch makes the SPM backend a user configuration.
The default backend is IPC backend.

To use the SFN backend, users need to enable it manually.
The build system will check if it can be enabled as it can be enabled
only in specific configuration combinations.

Change-Id: I4a08ee19d466778fac2cebef4a3c63fc99e7b258
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
diff --git a/config/config_default.cmake b/config/config_default.cmake
index ffd1b06..4c0e80e 100755
--- a/config/config_default.cmake
+++ b/config/config_default.cmake
@@ -26,6 +26,7 @@
 set(TFM_PROFILE                         ""          CACHE STRING    "Profile to use")
 set(TFM_FIH_PROFILE                     OFF         CACHE STRING    "Fault injection hardening profile [OFF, LOW, MEDIUM, HIGH]")
 set(CONFIG_TFM_CONN_HANDLE_MAX_NUM      8           CACHE STRING    "The maximal number of secure services that are connected or requested at the same time")
+set(CONFIG_TFM_SPM_BACKEND              "IPC"       CACHE STRING    "The SPM backend [IPC, SFN]")
 
 # An NSPE client_id is provided by the NSPE OS via the SPM or directly by the SPM.
 # When `TFM_NS_MANAGE_NSID` is `ON`, TF-M supports NSPE OS providing NSPE client_id.
diff --git a/config/set_config.cmake b/config/set_config.cmake
index 9f1a24b..da37fe4 100644
--- a/config/set_config.cmake
+++ b/config/set_config.cmake
@@ -54,7 +54,9 @@
 # Load TF-M model specific default config
 if (TFM_LIB_MODEL)
     include(config/tfm_library_config_default.cmake)
-else()
+elseif (CONFIG_TFM_SPM_BACKEND STREQUAL "SFN")
+    include(config/tfm_sfn_config_default.cmake)
+else() #The default backend is IPC
     include(config/tfm_ipc_config_default.cmake)
 endif()
 
diff --git a/config/tfm_ipc_config_default.cmake b/config/tfm_ipc_config_default.cmake
index b8b16b4..fbe6b09 100644
--- a/config/tfm_ipc_config_default.cmake
+++ b/config/tfm_ipc_config_default.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,4 +7,6 @@
 
 ############################ Partitions ########################################
 
-set(TFM_PSA_API          ON          CACHE BOOL      "Use PSA API instead of secure library model")
+set(TFM_PSA_API                 ON          CACHE BOOL      "Use PSA API instead of secure library model")
+set(CONFIG_TFM_SPM_BACKEND_IPC  ON)
+set(CONFIG_TFM_SPM_BACKEND_SFN  OFF)
diff --git a/config/tfm_sfn_config_default.cmake b/config/tfm_sfn_config_default.cmake
new file mode 100644
index 0000000..c9ea496
--- /dev/null
+++ b/config/tfm_sfn_config_default.cmake
@@ -0,0 +1,12 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+############################ Partitions ########################################
+
+set(TFM_PSA_API                 ON          CACHE BOOL      "Use PSA API instead of secure library model")
+set(CONFIG_TFM_SPM_BACKEND_IPC  OFF)
+set(CONFIG_TFM_SPM_BACKEND_SFN  ON)
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 7bb5a00..970dc90 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -134,6 +134,7 @@
                                   -m ${COMBINED_LIST}
                                   -f ${GENERATED_FILE_LISTS}
                                   -l ${TFM_ISOLATION_LEVEL}
+                                  -b ${CONFIG_TFM_SPM_BACKEND}
                                   -o ${CMAKE_BINARY_DIR}/generated
                                   ${PARSE_MANIFEST_QUIET_FLAG}
     DEPENDS ${TEMPLATE_FILES} ${MANIFEST_FILES}
@@ -148,6 +149,7 @@
                                   -m ${COMBINED_LIST}
                                   -f ${GENERATED_FILE_LISTS}
                                   -l ${TFM_ISOLATION_LEVEL}
+                                  -b ${CONFIG_TFM_SPM_BACKEND}
                                   -o ${CMAKE_BINARY_DIR}/generated
                                   ${PARSE_MANIFEST_QUIET_FLAG}
     RESULT_VARIABLE RET
diff --git a/tools/config_impl.cmake.template b/tools/config_impl.cmake.template
index 5aeb360..00bd4ed 100644
--- a/tools/config_impl.cmake.template
+++ b/tools/config_impl.cmake.template
@@ -9,9 +9,6 @@
 ########{{utilities.donotedit_warning}}########
 
 if(TFM_PSA_API)
-    set(CONFIG_TFM_SPM_BACKEND_SFN {{config_impl['CONFIG_TFM_SPM_BACKEND_SFN']}} PARENT_SCOPE)
-    set(CONFIG_TFM_SPM_BACKEND_IPC {{config_impl['CONFIG_TFM_SPM_BACKEND_IPC']}} PARENT_SCOPE)
-
     set(CONFIG_TFM_PSA_API_SFN_CALL        {{config_impl['CONFIG_TFM_PSA_API_SFN_CALL']}}        PARENT_SCOPE)
     set(CONFIG_TFM_PSA_API_CROSS_CALL      {{config_impl['CONFIG_TFM_PSA_API_CROSS_CALL']}}      PARENT_SCOPE)
     set(CONFIG_TFM_PSA_API_SUPERVISOR_CALL {{config_impl['CONFIG_TFM_PSA_API_SUPERVISOR_CALL']}} PARENT_SCOPE)
diff --git a/tools/tfm_parse_manifest_list.py b/tools/tfm_parse_manifest_list.py
index 63cda08..ac74f45 100644
--- a/tools/tfm_parse_manifest_list.py
+++ b/tools/tfm_parse_manifest_list.py
@@ -117,7 +117,7 @@
 
     return partition_manifest
 
-def process_partition_manifests(manifest_lists, isolation_level):
+def process_partition_manifests(manifest_lists, isolation_level, backend):
     """
     Parse the input manifest lists, generate the data base for genereated files
     and generate manifest header files.
@@ -275,27 +275,27 @@
         pid_list.append(pid)
 
     # Set up configurations
-    if partition_statistics['ipc_partition_num'] == 0 and \
-        partition_statistics['sfn_partition_num'] > 0:
-        if isolation_level > 1:
-            print('High isolation level SFN model is not supported.')
+    if backend == 'SFN':
+        if partition_statistics['ipc_partition_num'] > 0:
+            logging.error('SFN backend does not support IPC Partitions.')
             exit(1)
+
+        if isolation_level > 1:
+            logging.error('SFN backend does not support high isolation levels.')
+            exit(1)
+
         config_impl['CONFIG_TFM_SPM_BACKEND_SFN'] = '1'
         config_impl['CONFIG_TFM_PSA_API_SFN_CALL'] = '1'
-    elif partition_statistics['ipc_partition_num'] > 0 and \
-        partition_statistics['sfn_partition_num'] == 0:
+    elif backend == 'IPC':
+        if partition_statistics['sfn_partition_num'] > 0:
+            logging.error('IPC backend does not support SFN Partitions.')
+            exit(1)
+
         config_impl['CONFIG_TFM_SPM_BACKEND_IPC'] = '1'
         if isolation_level > 1:
             config_impl['CONFIG_TFM_PSA_API_SUPERVISOR_CALL'] = '1'
         else:
             config_impl['CONFIG_TFM_PSA_API_CROSS_CALL'] = '1'
-    elif partition_statistics['ipc_partition_num'] > 0 and \
-        partition_statistics['sfn_partition_num'] > 0:
-        print('IPC and SFN co-work not supported yet.')
-        exit(1)
-    else:
-        print('Invalid partition number input, check configurations.')
-        exit(1)
 
     if partition_statistics['connection_based_srv_num'] > 0:
         config_impl['CONFIG_TFM_CONNECTION_BASED_SERVICE_API'] = 1
@@ -539,7 +539,13 @@
                         , dest='isolation_level'
                         , required=True
                         , choices=['1', '2', '3']
-                        , metavar='isolation-level'
+                        , metavar='isolation-level')
+
+    parser.add_argument('-b', '--backend'
+                        , dest='backend'
+                        , required=True
+                        , choices=['IPC', 'SFN']
+                        , metavar='spm-backend'
                         , help='The isolation level')
 
     parser.add_argument('-q', '--quiet'
@@ -594,7 +600,9 @@
     """
     os.chdir(os.path.join(sys.path[0], '..'))
 
-    context = process_partition_manifests(manifest_lists, int(args.isolation_level))
+    context = process_partition_manifests(manifest_lists,
+                                          int(args.isolation_level),
+                                          args.backend)
 
     utilities = {}
     utilities['donotedit_warning'] = donotedit_warning