1#!/usr/bin/env python3 2# 3# Arm SCP/MCP Software 4# Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. 5# 6# SPDX-License-Identifier: BSD-3-Clause 7# 8# Description: 9# This tool takes a list of module names and generates two files: 10# * fwk_modules_idx.h: Contains an enumeration giving the modules' indices. 11# * fwk_modules_list.c: Contains a table of pointers to a module descriptor. 12# 13# Note: The files are updated only if their contents will differ, relative to 14# the last time the tool was run. 15# 16 17import argparse 18import os 19import sys 20import tempfile 21 22DEFAULT_PATH = 'build/' 23 24FILENAME_H = "fwk_module_idx.h" 25TEMPLATE_H = "/* This file was auto generated using {} */\n" \ 26 "#ifndef FWK_MODULE_IDX_H\n" \ 27 "#define FWK_MODULE_IDX_H\n" \ 28 "\n" \ 29 "#include <fwk_id.h>\n" \ 30 "\n" \ 31 "enum fwk_module_idx {{\n" \ 32 "{}" \ 33 "}};\n" \ 34 "\n" \ 35 "{}" \ 36 "\n" \ 37 "#endif /* FWK_MODULE_IDX_H */\n" 38 39FILENAME_C = "fwk_module_list.c" 40TEMPLATE_C = "/* This file was auto generated using {} */\n" \ 41 "#include <stddef.h>\n" \ 42 "#include <fwk_module.h>\n" \ 43 "\n" \ 44 "{}" \ 45 "\n" \ 46 "const struct fwk_module *module_table[] = {{\n" \ 47 "{}" \ 48 "}};\n" \ 49 "\n" \ 50 "const struct fwk_module_config *module_config_table[] = {{\n" \ 51 "{}" \ 52 "}};\n" 53 54 55def generate_file(path, filename, content): 56 full_filename = os.path.join(path, filename) 57 58 try: 59 with open(full_filename) as f: 60 rewrite = f.read() != content 61 except FileNotFoundError: 62 rewrite = True 63 64 if rewrite: 65 with tempfile.NamedTemporaryFile(prefix="gen-module-code", 66 dir=path, 67 delete=False, 68 mode="wt") as f: 69 print("[GEN] {}...".format(full_filename)) 70 f.write(content) 71 os.replace(f.name, full_filename) 72 73 74def generate_header(path, modules): 75 enum = "" 76 const = "" 77 for idx, module in enumerate(modules): 78 enum += " FWK_MODULE_IDX_{} = {},\n".format(module.upper(), idx) 79 const += "static const fwk_id_t fwk_module_id_{} = " \ 80 "FWK_ID_MODULE_INIT(FWK_MODULE_IDX_{});\n".format(module, 81 module 82 .upper()) 83 84 enum += " FWK_MODULE_IDX_COUNT = {},\n".format(idx + 1) 85 86 content = TEMPLATE_H.format(sys.argv[0], enum, const) 87 generate_file(path, FILENAME_H, content) 88 89 90def generate_c(path, modules): 91 module_entry = "" 92 config_entry = "" 93 extern_entry = "" 94 for module in modules: 95 extern_entry += "extern const struct fwk_module module_{};\n"\ 96 .format(module.lower()) 97 extern_entry += "extern const struct fwk_module_config config_{};\n"\ 98 .format(module.lower()) 99 module_entry += " &module_{},\n".format(module.lower()) 100 config_entry += " &config_{},\n".format(module.lower()) 101 102 content = TEMPLATE_C.format(sys.argv[0], extern_entry, module_entry, 103 config_entry) 104 generate_file(path, FILENAME_C, content) 105 106 107def main(): 108 parser = argparse.ArgumentParser(description="Generates a header file and \ 109 source file enumerating the modules that are included in a firmware.") 110 111 parser.add_argument('modules', 112 metavar='module', 113 type=str, 114 nargs='*', 115 help='A list of module names that are included in a \ 116 firmware.') 117 118 parser.add_argument('-p', '--path', 119 help='Path to the location where generated files are \ 120 written. If the files exist then they will be \ 121 overwritten.', 122 default=DEFAULT_PATH) 123 124 args = parser.parse_args() 125 126 modules = args.modules 127 128 generate_header(args.path, modules) 129 generate_c(args.path, modules) 130 131 132if __name__ == "__main__": 133 main() 134