Tools: Various refinements on manifest tool

This patch refines the manifest tool:
- Simplify the SID duplication check: only checks if there are
  duplications
- Make the 'context' variable as local variable and return it so that
  the process_partition_manifests method does not need to return
  several varibales
- Move process_stateless_services into process_partition_manifests as
  it is part of process_partition_manifests
- Variable renamings
- Some logic simplifications
- Unify the usage of double and single quatations - use single ones in
  most of codes as they seem to be used more than double ones.
- Others.

Change-Id: Id41890bb38fa74fcf9075f534e984ac7fdec2c47
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 1a9170c..2fde44c 100644
--- a/tools/tfm_parse_manifest_list.py
+++ b/tools/tfm_parse_manifest_list.py
@@ -14,25 +14,19 @@
 try:
     import yaml
 except ImportError as e:
-    print (str(e) + " To install it, type:")
-    print ("pip install PyYAML")
+    print (str(e) + ' To install it, type:')
+    print ('pip install PyYAML')
     exit(1)
 
 donotedit_warning = \
-                    "/*********** " + \
-                    "WARNING: This is an auto-generated file. Do not edit!" + \
-                    " ***********/"
+                    '/*********** ' + \
+                    'WARNING: This is an auto-generated file. Do not edit!' + \
+                    ' ***********/'
 
 OUT_DIR = None # The root directory that files are generated to
 
 # variable for checking for duplicated sid
 sid_list = []
-partition_list_sid = []
-service_list = []
-sid_duplicated_partition = []
-sid_duplicated_sid = []
-sid_duplicated_service = []
-
 class TemplateLoader(BaseLoader):
     """
     Template loader class.
@@ -64,6 +58,7 @@
     default values for optional attributes.
     More validation items will be added.
     """
+
     # Service FF-M manifest validation
     if 'services' not in partition_manifest.keys():
         return partition_manifest
@@ -72,21 +67,13 @@
         if 'version' not in service.keys():
             service['version'] = 1
         if 'version_policy' not in service.keys():
-            service['version_policy'] = "STRICT"
+            service['version_policy'] = 'STRICT'
 
-        for k in range (len(sid_list)):
-            sid_item = sid_list[k]
-            if ((service['sid'] == sid_item) & (service['name'] != service_list[k])):
-                sid_duplicated_partition.append(partition_list_sid[k])
-                sid_duplicated_partition.append(partition_manifest['name'])
-                sid_duplicated_sid.append(sid_item)
-                sid_duplicated_sid.append(service['sid'])
-                sid_duplicated_service.append(service_list[k])
-                sid_duplicated_service.append(service['name'])
-
-        sid_list.append(service['sid'])
-        partition_list_sid.append(partition_manifest['name'])
-        service_list.append(service['name'])
+        # SID duplication check
+        if service['sid'] in sid_list:
+            raise Exception('Service ID: {} has duplications!'.format(service['sid']))
+        else:
+            sid_list.append(service['sid'])
 
     return partition_manifest
 
@@ -104,9 +91,11 @@
 
     Returns
     -------
-    The partition data base.
+    The manifest data base.
     """
 
+    context = {}
+
     partition_list = []
     manifest_list = []
     ipc_partition_num = 0
@@ -117,7 +106,7 @@
     for f in manifest_list_files:
         with open(f) as manifest_list_yaml_file:
             manifest_dic = yaml.safe_load(manifest_list_yaml_file)
-            manifest_list.extend(manifest_dic["manifest_list"])
+            manifest_list.extend(manifest_dic['manifest_list'])
             manifest_list_yaml_file.close()
 
     # Out-of-tree secure partition build
@@ -130,7 +119,7 @@
             # 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)
-                extra_manifest_dic = manifest_dic["manifest_list"]
+                extra_manifest_dic = manifest_dic['manifest_list']
                 for dict in extra_manifest_dic:
                     # Append original directory of out-of-tree partition's
                     # manifest list source code
@@ -144,7 +133,7 @@
             no_pid_manifest_idx.append(i)
         # Check if partition ID is duplicated
         elif manifest_item['pid'] in pid_list:
-            raise Exception("PID No. {pid} has already been used!".format(pid=manifest_item['pid']))
+            raise Exception('PID No. {pid} has already been used!'.format(pid=manifest_item['pid']))
         else:
             pid_list.append(manifest_item['pid'])
 
@@ -158,16 +147,16 @@
                 # manifest list path
                 manifest_path = os.path.join(manifest_item['extra_path'], manifest_path).replace('\\', '/')
 
-        file = open(manifest_path)
-        manifest = manifest_validation(yaml.safe_load(file))
-        file.close()
+        with open(manifest_path) as manifest_file:
+            manifest = manifest_validation(yaml.safe_load(manifest_file))
 
         # Count the number of IPC partitions
-        if manifest["psa_framework_version"] == 1.1 and manifest["model"] == 'IPC':
+        if manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'IPC':
             ipc_partition_num += 1
-        elif manifest["psa_framework_version"] == 1.1 and manifest["model"] == 'SFN':
+        elif manifest['psa_framework_version'] == 1.1 and manifest['model'] == 'SFN':
             sfn_partition_num += 1
-        elif "services" in manifest.keys():
+        elif 'services' in manifest.keys() or 'irqs' in manifest.keys():
+            # This is only to skip Library Model Partitions
             ipc_partition_num += 1
 
         manifest_dir, manifest_name = os.path.split(manifest_path)
@@ -177,23 +166,24 @@
             # Build up generated files directory accroding to the relative
             # path specified in output_path by the partition
             output_path = os.path.expandvars(manifest_item['output_path'])
-            manifest_head_file = os.path.join(output_path, "psa_manifest", manifest_out_basename + '.h')
-            intermedia_file = os.path.join(output_path, "auto_generated", 'intermedia_' + manifest_out_basename + '.c')
-            load_info_file = os.path.join(output_path, "auto_generated", 'load_info_' + manifest_out_basename + '.c')
         else:
-            manifest_head_file = os.path.join(manifest_dir, "psa_manifest", manifest_out_basename + '.h')
-            intermedia_file = os.path.join(manifest_dir, "auto_generated", 'intermedia_' + manifest_out_basename + '.c')
-            load_info_file = os.path.join(manifest_dir, "auto_generated", 'load_info_' + manifest_out_basename + '.c')
+            output_path = manifest_dir
 
-        manifest_head_file = os.path.join(OUT_DIR, manifest_head_file).replace('\\', '/')
-        intermedia_file = os.path.join(OUT_DIR, intermedia_file).replace('\\', '/')
-        load_info_file = os.path.join(OUT_DIR, load_info_file).replace('\\', '/')
+        manifest_head_file = os.path.join(OUT_DIR, output_path, 'psa_manifest',
+                                          '{}.h'.format(manifest_out_basename))\
+                                              .replace('\\', '/')
+        intermedia_file    = os.path.join(OUT_DIR, output_path, 'auto_generated',
+                                          'intermedia_{}.c'.format(manifest_out_basename))\
+                                              .replace('\\', '/')
+        load_info_file     = os.path.join(OUT_DIR, output_path, 'auto_generated',
+                                          'load_info_{}.c'.format(manifest_out_basename))\
+                                              .replace('\\', '/')
 
-        partition_list.append({"manifest": manifest, "attr": manifest_item,
-                               "manifest_out_basename": manifest_out_basename,
-                               "header_file": manifest_head_file,
-                               "intermedia_file": intermedia_file,
-                               "loadinfo_file": load_info_file})
+        partition_list.append({'manifest': manifest, 'attr': manifest_item,
+                               'manifest_out_basename': manifest_out_basename,
+                               'header_file': manifest_head_file,
+                               'intermedia_file': intermedia_file,
+                               'loadinfo_file': load_info_file})
 
     # Automatically assign PIDs for partitions without 'pid' attribute
     pid = 256
@@ -203,19 +193,13 @@
         manifest_list[idx]['pid'] = pid
         pid_list.append(pid)
 
-    if len(sid_duplicated_sid) != 0:
-        print("The following signals have duplicated sids."
-              "A Service requires a unique sid")
-        for i in range(len(sid_duplicated_sid)):
-            print("Partition: {parti} , Service: {servi} , SID: {sidn}".format(
-                  parti = sid_duplicated_partition[i],
-                  servi = sid_duplicated_service[i],
-                  sidn = sid_duplicated_sid[i])
-                 )
+    context['partitions'] = partition_list
+    context['ipc_partition_num'] = ipc_partition_num
+    context['sfn_partition_num'] = sfn_partition_num
 
-        raise Exception("Duplicated SID found, check above for details")
+    context['stateless_services'] = process_stateless_services(partition_list, 32)
 
-    return partition_list, ipc_partition_num, sfn_partition_num
+    return context
 
 def gen_per_partition_files(context):
     """
@@ -227,49 +211,49 @@
         context contains partition infos
     """
 
-    subutilities = {}
-    subutilities['donotedit_warning'] = donotedit_warning
+    utilities = {}
+    utilities['donotedit_warning'] = donotedit_warning
 
-    subcontext = {}
-    subcontext['utilities'] = subutilities
+    partition_context = {}
+    partition_context['utilities'] = utilities
 
-    manifesttemplate = ENV.get_template(os.path.join(os.path.relpath(os.path.dirname(__file__)), 'templates/manifestfilename.template'))
-    memorytemplate = ENV.get_template(os.path.join(os.path.relpath(os.path.dirname(__file__)), 'templates/partition_intermedia.template'))
-    infotemplate = ENV.get_template(os.path.join(os.path.relpath(os.path.dirname(__file__)), 'templates/partition_load_info.template'))
+    manifesttemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/manifestfilename.template'))
+    memorytemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_intermedia.template'))
+    infotemplate = ENV.get_template(os.path.join(sys.path[0], 'templates/partition_load_info.template'))
 
-    print ("Start to generate partition files:")
+    print ('Start to generate partition files:')
 
     for one_partition in context['partitions']:
-        subcontext['manifest'] = one_partition['manifest']
-        subcontext['attr'] = one_partition['attr']
-        subcontext['manifest_out_basename'] = one_partition['manifest_out_basename']
+        partition_context['manifest'] = one_partition['manifest']
+        partition_context['attr'] = one_partition['attr']
+        partition_context['manifest_out_basename'] = one_partition['manifest_out_basename']
 
-        print ("Generating Header: " + one_partition['header_file'])
+        print ('Generating Header: ' + one_partition['header_file'])
         outfile_path = os.path.dirname(one_partition['header_file'])
         if not os.path.exists(outfile_path):
             os.makedirs(outfile_path)
 
-        headerfile = io.open(one_partition['header_file'], "w", newline=None)
-        headerfile.write(manifesttemplate.render(subcontext))
+        headerfile = io.open(one_partition['header_file'], 'w', newline=None)
+        headerfile.write(manifesttemplate.render(partition_context))
         headerfile.close()
 
-        print ("Generating Intermedia: " + one_partition['intermedia_file'])
+        print ('Generating Intermedia: ' + one_partition['intermedia_file'])
         intermediafile_path = os.path.dirname(one_partition['intermedia_file'])
         if not os.path.exists(intermediafile_path):
             os.makedirs(intermediafile_path)
-        intermediafile = io.open(one_partition['intermedia_file'], "w", newline=None)
-        intermediafile.write(memorytemplate.render(subcontext))
+        intermediafile = io.open(one_partition['intermedia_file'], 'w', newline=None)
+        intermediafile.write(memorytemplate.render(partition_context))
         intermediafile.close()
 
-        print ("Generating Loadinfo: " + one_partition['loadinfo_file'])
+        print ('Generating Loadinfo: ' + one_partition['loadinfo_file'])
         infofile_path = os.path.dirname(one_partition['loadinfo_file'])
         if not os.path.exists(infofile_path):
             os.makedirs(infofile_path)
-        infooutfile = io.open(one_partition['loadinfo_file'], "w", newline=None)
-        infooutfile.write(infotemplate.render(subcontext))
+        infooutfile = io.open(one_partition['loadinfo_file'], 'w', newline=None)
+        infooutfile.write(infotemplate.render(partition_context))
         infooutfile.close()
 
-    print ("Per-partition files done:")
+    print ('Per-partition files done:')
 
 def gen_summary_files(context, gen_file_lists):
     """
@@ -285,18 +269,18 @@
     for f in gen_file_lists:
         with open(f) as file_list_yaml_file:
             file_list_yaml = yaml.safe_load(file_list_yaml_file)
-            file_list.extend(file_list_yaml["file_list"])
+            file_list.extend(file_list_yaml['file_list'])
 
-    print("Start to generate file from the generated list:")
+    print('Start to generate file from the generated list:')
     for file in file_list:
         # Replace environment variables in the output filepath
-        manifest_out_file = os.path.expandvars(file["output"])
+        manifest_out_file = os.path.expandvars(file['output'])
         # Replace environment variables in the template filepath
-        templatefile_name = os.path.expandvars(file["template"])
+        templatefile_name = os.path.expandvars(file['template'])
 
         manifest_out_file = os.path.join(OUT_DIR, manifest_out_file)
 
-        print ("Generating " + manifest_out_file)
+        print ('Generating ' + manifest_out_file)
 
         outfile_path = os.path.dirname(manifest_out_file)
         if not os.path.exists(outfile_path):
@@ -304,11 +288,11 @@
 
         template = ENV.get_template(templatefile_name)
 
-        outfile = io.open(manifest_out_file, "w", newline=None)
+        outfile = io.open(manifest_out_file, 'w', newline=None)
         outfile.write(template.render(context))
         outfile.close()
 
-    print ("Generation of files done")
+    print ('Generation of files done')
 
 def process_stateless_services(partitions, stateless_index_max_num):
     """
@@ -337,7 +321,7 @@
         return []
 
     if len(collected_stateless_services) > stateless_index_max_num:
-        raise Exception("Stateless service numbers range exceed {number}.".format(number=stateless_index_max_num))
+        raise Exception('Stateless service numbers range exceed {number}.'.format(number=stateless_index_max_num))
 
     """
     Allocate an empty stateless service list to store services.
@@ -358,17 +342,17 @@
         # Fill in service list with specified stateless handle, otherwise skip
         if isinstance(service_handle, int):
             if service_handle < 1 or service_handle > stateless_index_max_num:
-                raise Exception("Invalid stateless_handle setting: {handle}.".format(handle=service['stateless_handle']))
+                raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
             # Convert handle index to reordered service list index
             service_handle = service_handle - 1
 
             if reordered_stateless_services[service_handle] is not None:
-                raise Exception("Duplicated stateless_handle setting: {handle}.".format(handle=service['stateless_handle']))
+                raise Exception('Duplicated stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
             reordered_stateless_services[service_handle] = service
         elif service_handle == 'auto':
             auto_alloc_services.append(service)
         else:
-            raise Exception("Invalid stateless_handle setting: {handle}.".format(handle=service['stateless_handle']))
+            raise Exception('Invalid stateless_handle setting: {handle}.'.format(handle=service['stateless_handle']))
 
     # Auto-allocate stateless handle and encode the stateless handle
     for i in range(0, stateless_index_max_num):
@@ -408,11 +392,11 @@
                         , metavar='out_dir'
                         , help='The root directory for generated files')
 
-    parser.add_argument('-m', '--manifest'
+    parser.add_argument('-m', '--manifest-lists'
                         , nargs='+'
-                        , dest='manifest_args'
+                        , dest='manifest_lists'
                         , required=True
-                        , metavar='manifest'
+                        , metavar='manifest-lists'
                         , help='A set of secure partition manifest lists to parse')
 
     parser.add_argument('-f', '--file-list'
@@ -431,8 +415,6 @@
                         , help='Optional. Manifest lists and original paths for out-of-tree secure partitions.')
 
     args = parser.parse_args()
-    manifest_args = args.manifest_args
-    gen_file_args = args.gen_file_args
 
     return args
 
@@ -455,18 +437,16 @@
 
     args = parse_args()
 
-    manifest_args = args.manifest_args
-    gen_file_args = args.gen_file_args
     extra_manifests_args = args.extra_manifests_args
-    OUT_DIR = args.outdir
+    OUT_DIR = os.path.abspath(args.outdir)
 
-    manifest_list = [os.path.abspath(x) for x in args.manifest_args]
-    gen_file_list = [os.path.abspath(x) for x in args.gen_file_args]
+    manifest_lists = [os.path.abspath(x) for x in args.manifest_lists]
+    gen_file_lists = [os.path.abspath(x) for x in args.gen_file_args]
 
     if extra_manifests_args is not None:
-        extra_manifests_list = [os.path.abspath(x) for x in extra_manifests_args]
+        extra_manifests_lists = [os.path.abspath(x) for x in extra_manifests_args]
     else:
-        extra_manifests_list = None
+        extra_manifests_lists = None
 
     """
     Relative path to TF-M root folder is supported in the manifests
@@ -475,23 +455,17 @@
     By doing this, the script can be executed anywhere
     The script is located in <TF-M root folder>/tools, so sys.path[0]<location of the script>/.. is TF-M root folder.
     """
-    os.chdir(os.path.join(sys.path[0], ".."))
+    os.chdir(os.path.join(sys.path[0], '..'))
 
-    partition_list, ipc_partition_num, sfn_partition_num = process_partition_manifests(manifest_list, extra_manifests_list)
+    context = process_partition_manifests(manifest_lists, extra_manifests_lists)
 
     utilities = {}
     utilities['donotedit_warning'] = donotedit_warning
 
-    context = {}
-    context['partitions'] = partition_list
     context['utilities'] = utilities
-    context['stateless_services'] = process_stateless_services(partition_list, 32)
-
-    context['ipc_partition_num'] = ipc_partition_num
-    context['sfn_partition_num'] = sfn_partition_num
 
     gen_per_partition_files(context)
-    gen_summary_files(context, gen_file_list)
+    gen_summary_files(context, gen_file_lists)
 
-if __name__ == "__main__":
+if __name__ == '__main__':
     main()