[REDO]: Pass build configurations through header file

This patch re-applies 56979ee5579dbb90bbf598af4c252259e5f20777
as it was reverted.

The CI failure was because the patch that triggered CI was not
rebased for dependency changes between TF-M and TF-M test repo.

Change-Id: I7f96e285c2659ef39731e8736bd641895413818a
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
diff --git a/tools/tfm_parse_manifest_list.py b/tools/tfm_parse_manifest_list.py
index 5cc25ce..3f76a85 100644
--- a/tools/tfm_parse_manifest_list.py
+++ b/tools/tfm_parse_manifest_list.py
@@ -88,6 +88,37 @@
 
     return macro_def
 
+def parse_configurations(file_paths):
+    """
+    Parses the given config files and return a dict whose key-values are build
+    configurations and their values.
+
+    Valid configurations should be in the format of:
+    "#define VAR [...]" in a single line.
+    The value of the config is optional.
+    """
+    configurations = {}
+
+    lines = []
+    for file in file_paths:
+        with open(file, 'r') as config_file:
+            lines += config_file.readlines()
+
+    for line in lines:
+        if not line.startswith('#define'):
+            continue
+
+        line = line.rstrip('\r\n')
+        line_items = line.split(maxsplit=2)
+        if len(line_items) == 3:
+            configurations[line_items[1]] = line_items[2]
+        elif len(line_items) == 2:
+            configurations[line_items[1]] = ''
+
+    logging.debug(configurations)
+
+    return configurations
+
 def manifest_validation(manifest, pid):
     """
     This function validates FF-M compliance for partition manifest, and sets
@@ -212,7 +243,7 @@
         validate_dependency_chain(dependency, dependency_table, dependency_chain)
     dependency_table[partition]['validated'] = True
 
-def process_partition_manifests(manifest_lists, isolation_level, backend):
+def process_partition_manifests(manifest_lists, configs):
     """
     Parse the input manifest lists, check if manifest settings are valid,
     generate the data base for generated files
@@ -221,11 +252,7 @@
     Parameters
     ----------
     manifest_lists:
-        A list of Secure Partition manifest lists and their original paths.
-        The manifest lists might be processed by CMake and the paths might be
-        different to the original ones. Original paths are needed to handle
-        relative paths in the lists.
-        The format must be [list A, original path A, list B, orignal path B, ...]
+        A list of Secure Partition manifest lists
 
     Returns
     -------
@@ -256,42 +283,43 @@
         'CONFIG_TFM_SLIH_API'                     : '0'
     }
 
+    isolation_level = int(configs['TFM_ISOLATION_LEVEL'], base = 10)
+    backend = configs['CONFIG_TFM_SPM_BACKEND']
+
     # Get all the manifests information as a dictionary
     for i, item in enumerate(manifest_lists):
-        if i % 2 == 0 and not os.path.isfile(item):
+        if not os.path.isfile(item):
             logging.error('Manifest list item [{}] must be a file'.format(i))
             exit(1)
 
-        if i % 2 == 1:
-            if not os.path.isdir(item):
-                logging.error('Manifest list item [{}] must be a directory'.format(i))
-                exit(1)
-
-            # Skip original manifest paths
-            continue
-
         # The manifest list file generated by configure_file()
         with open(item) as manifest_list_yaml_file:
             manifest_dic = yaml.safe_load(manifest_list_yaml_file)['manifest_list']
             for dict in manifest_dic:
-                # Add original path of manifest list.
-                # The validation will be done in the next loop.
-                dict['list_path'] = manifest_lists[i + 1]
+                # Replace environment variables in the manifest path and convert to absolute path.
+                # If it's already abspath, the path will not be changed.
+                manifest_path = os.path.join(os.path.dirname(item), # path of manifest list
+                                             os.path.expandvars(dict['manifest']))\
+                                             .replace('\\', '/')
+                dict['manifest'] = manifest_path
                 all_manifests.append(dict)
 
     logging.info("------------ Display partition configuration - start ------------")
 
     # Parse the manifests
     for i, manifest_item in enumerate(all_manifests):
-        valid_enabled_conditions  = ['on',  'true',  'enabled']
-        valid_disabled_conditions = ['off', 'false', 'disabled', '']
+        valid_enabled_conditions  = ['1', 'on',  'true',  'enabled']
+        valid_disabled_conditions = ['0', 'off', 'false', 'disabled', '']
         is_enabled = ''
 
         if 'conditional' in manifest_item.keys():
-            is_enabled = str(manifest_item['conditional']).lower()
+            if manifest_item['conditional'] not in configs.keys():
+                logging.error('Configuration "{}" is not defined!'.format(manifest_item['conditional']))
+                exit(1)
+            is_enabled = configs[manifest_item['conditional']].lower()
         else:
-            # Partitions without 'conditional' are always on
-            is_enabled = 'on'
+            # Partitions without 'conditional' is always on
+            is_enabled = '1'
 
         if is_enabled in valid_disabled_conditions:
             logging.info("   {:40s}  OFF".format(manifest_item['name']))
@@ -318,11 +346,7 @@
             else:
                 pid_list.append(pid)
 
-        # Replace environment variables in the manifest path
-        manifest_path = os.path.expandvars(manifest_item['manifest'])
-        # Convert to absolute path. If it's already abspath, the path will not be changed.
-        manifest_path = os.path.join(manifest_item['list_path'], manifest_path).replace('\\', '/')
-
+        manifest_path = manifest_item['manifest']
         with open(manifest_path) as manifest_file:
             manifest = yaml.safe_load(manifest_file)
             if manifest.get('model', None) == 'dual':
@@ -655,18 +679,12 @@
                         , metavar='file-list'
                         , help='These files describe the file list to generate')
 
-    parser.add_argument('-l', '--isolation-level'
-                        , dest='isolation_level'
+    parser.add_argument('-c', '--config-files'
+                        , nargs='+'
+                        , dest='config_files'
                         , required=True
-                        , choices=['1', '2', '3']
-                        , metavar='isolation-level')
-
-    parser.add_argument('-b', '--backend'
-                        , dest='backend'
-                        , required=True
-                        , choices=['IPC', 'SFN']
-                        , metavar='spm-backend'
-                        , help='The isolation level')
+                        , metavar='config-files'
+                        , help='A header file contains build configurations')
 
     parser.add_argument('-q', '--quiet'
                         , dest='quiet'
@@ -677,11 +695,6 @@
 
     args = parser.parse_args()
 
-    if len(args.manifest_lists) % 2 != 0:
-        logging.error('Invalid structure in manifest lists.\n'
-              'Each element shall consist of a manifest list and its original path')
-        exit(1)
-
     return args
 
 ENV = Environment(
@@ -721,8 +734,7 @@
     os.chdir(os.path.join(sys.path[0], '..'))
 
     context = process_partition_manifests(manifest_lists,
-                                          int(args.isolation_level),
-                                          args.backend)
+                                          parse_configurations(args.config_files))
 
     utilities = {}
     utilities['donotedit_warning'] = donotedit_warning