1#!/usr/bin/env python3 2"""This hacky script generates a partition from a manifest file""" 3 4# Copyright The Mbed TLS Contributors 5# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 7import json 8import os 9import sys 10from os import listdir 11 12if len(sys.argv) != 2: 13 print("Usage: psa_autogen <manifest_file>") 14 sys.exit(1) 15 16FILENAME = str(sys.argv[1]) 17 18SCRIPT_PATH = os.path.dirname(__file__) 19GENERATED_H_PATH = os.path.join(SCRIPT_PATH, "..", "include", "psa_manifest") 20GENERATED_C_PATH = os.path.join(SCRIPT_PATH, "..", "src") 21 22MANIFEST_FILE = os.path.join(GENERATED_H_PATH, "manifest.h") 23PID_FILE = os.path.join(GENERATED_H_PATH, "pid.h") 24SID_FILE = os.path.join(GENERATED_H_PATH, "sid.h") 25 26with open(str(FILENAME), "r") as read_file: 27 data = json.load(read_file) 28 FILENAME = os.path.basename(FILENAME) 29 FILENAME = FILENAME.split('.')[0] 30 print("Base filename is " + str(FILENAME)) 31 32 if str(data['psa_framework_version'] == "1.0"): 33 entry_point = str(data['entry_point']) 34 partition_name = str(data['name']) 35 services = data['services'] 36 try: 37 irqs = data['irqs'] 38 except KeyError: 39 irqs = [] 40 41 try: 42 os.mkdir(GENERATED_H_PATH) 43 print("Generating psa_manifest directory") 44 except OSError: 45 print("PSA manifest directory already exists") 46 47 manifest_content = [] 48 pids_content = [] 49 sids_content = [] 50 51 if len(services) > 28: 52 print ("Unsupported number of services") 53 54 count = 4 # For creating SID array 55 nsacl = "const int ns_allowed[32] = { " 56 policy = "const int strict_policy[32] = { " 57 qcode = "const char *psa_queues[] = { " 58 versions = "const uint32_t versions[32] = { " 59 queue_path = "psa_service_" 60 start = False 61 62 for x in range(0, count): 63 qcode = qcode + "\"\", " 64 nsacl = nsacl + "0, " 65 policy = policy + "0, " 66 versions = versions + "0, " 67 68 # Go through all the services to make sid.h and pid.h 69 for svc in services: 70 manifest_content.append("#define {}_SIGNAL 0x{:08x}".format(svc['signal'], 2**count)) 71 sids_content.append("#define {}_SID {}".format(svc['name'], svc['sid'])) 72 qcode = qcode + "\"" + queue_path + str(int(svc['sid'], 16)) + "\"," 73 ns_clients = svc['non_secure_clients'] 74 print(str(svc)) 75 if ns_clients == "true": 76 nsacl = nsacl + "1, " 77 else: 78 nsacl = nsacl + "0, " 79 try: 80 versions = versions + str(svc['minor_version']) + ", " 81 except KeyError: 82 versions = versions + "1, " 83 84 strict = 0 85 try: 86 if str(svc['minor_policy']).lower() == "strict": 87 strict = 1 88 policy = policy + "1, " 89 else: 90 policy = policy + "0, " 91 except KeyError: 92 strict = 0 93 policy = policy + "0, " 94 95 count = count+1 96 97 sigcode = "" 98 handlercode = "void __sig_handler(int signo) {\n" 99 irqcount = count 100 for irq in irqs: 101 manifest_content.append("#define {} 0x{:08x}".format(irq['signal'], 2**irqcount)) 102 sigcode = sigcode + " signal({}, __sig_handler);\n".format(irq['source']) 103 handlercode = handlercode + \ 104 " if (signo == {}) {{ raise_signal(0x{:08x}); }};\n".format(irq['source'], 2**irqcount) 105 irqcount = irqcount+1 106 107 handlercode = handlercode + "}\n" 108 109 while (count < 32): 110 qcode = qcode + "\"\", " 111 nsacl = nsacl + "0, " 112 versions = versions + "0, " 113 policy = policy + "0, " 114 count = count + 1 115 116 qcode = qcode + "};\n" 117 nsacl = nsacl + "};\n" 118 versions = versions + "};\n" 119 policy = policy + "};\n" 120 121 with open(MANIFEST_FILE, "wt") as output: 122 output.write("\n".join(manifest_content)) 123 with open(SID_FILE, "wt") as output: 124 output.write("\n".join(sids_content)) 125 with open(PID_FILE, "wt") as output: 126 output.write("\n".join(pids_content)) 127 128 symbols = [] 129 130 # Go through source files and look for the entrypoint 131 for root, directories, filenames in os.walk(GENERATED_C_PATH): 132 for filename in filenames: 133 if "psa_ff_bootstrap" in filename or filename == "psa_manifest": 134 continue 135 try: 136 fullpath = os.path.join(root,filename) 137 with open(fullpath, encoding='utf-8') as currentFile: 138 text = currentFile.read() 139 if str(entry_point + "(") in text: 140 symbols.append(filename) 141 except IOError: 142 print("Couldn't open " + filename) 143 except UnicodeDecodeError: 144 pass 145 146 print(str("Number of entrypoints detected: " + str(len(symbols)))) 147 if len(symbols) < 1: 148 print("Couldn't find function " + entry_point) 149 sys.exit(1) 150 elif len(symbols) > 1: 151 print("Duplicate entrypoint symbol detected: " + str(symbols)) 152 sys.exit(2) 153 else: 154 C_FILENAME = os.path.join(GENERATED_C_PATH, "psa_ff_bootstrap_" + partition_name + ".c") 155 c_content = [] 156 c_content.append("#include <init.h>") 157 c_content.append("#include \"" + symbols[0] + "\"") 158 c_content.append("#include <signal.h>") 159 c_content.append(qcode) 160 c_content.append(nsacl) 161 c_content.append(policy) 162 c_content.append(versions) 163 c_content.append(handlercode) 164 c_content.append("int main(int argc, char *argv[]) {") 165 c_content.append(" (void) argc;") 166 c_content.append(sigcode) 167 c_content.append(" __init_psasim(psa_queues, 32, ns_allowed, versions," 168 "strict_policy);") 169 c_content.append(" " + entry_point + "(argc, argv);") 170 c_content.append("}") 171 with open(C_FILENAME, "wt") as output: 172 output.write("\n".join(c_content)) 173 174 print("Success") 175