blob: 957bf14be3d52a50a7b1f6cb595d812b3542f7a4 [file] [log] [blame]
Andrew Boiefa94ee72017-09-28 16:54:35 -07001#!/usr/bin/env python3
2#
3# Copyright (c) 2017 Intel Corporation
4#
5# SPDX-License-Identifier: Apache-2.0
6
7import sys
8import re
9import argparse
10import os
Sebastian Bøe13a68402017-11-20 13:03:55 +010011import json
Andrew Boiefa94ee72017-09-28 16:54:35 -070012
13table_template = """/* auto-generated by gen_syscalls.py, don't edit */
14
Paul Sokolovsky94620bd2017-10-01 23:47:43 +030015/* Weak handler functions that get replaced by the real ones unless a system
16 * call is not implemented due to kernel configuration.
Andrew Boiefa94ee72017-09-28 16:54:35 -070017 */
18%s
19
20const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = {
21\t%s
22};
23"""
24
25list_template = """
26/* auto-generated by gen_syscalls.py, don't edit */
Flavio Ceolina7fffa92018-09-13 15:06:35 -070027#ifndef ZEPHYR_SYSCALL_LIST_H
28#define ZEPHYR_SYSCALL_LIST_H
Andrew Boiefa94ee72017-09-28 16:54:35 -070029
Sebastian Bøe1a409902018-08-10 15:23:00 +020030%s
31
Andrew Boiefa94ee72017-09-28 16:54:35 -070032#ifndef _ASMLANGUAGE
33
Andrew Boiec67eb562018-03-26 13:44:44 -070034#include <zephyr/types.h>
35
Andrew Boiefa94ee72017-09-28 16:54:35 -070036#ifdef __cplusplus
37extern "C" {
38#endif
39
Andrew Boiefa94ee72017-09-28 16:54:35 -070040%s
41
42#ifdef __cplusplus
43}
44#endif
45
46#endif /* _ASMLANGUAGE */
47
Flavio Ceolina7fffa92018-09-13 15:06:35 -070048#endif /* ZEPHYR_SYSCALL_LIST_H */
Andrew Boiefa94ee72017-09-28 16:54:35 -070049"""
50
51syscall_template = """
52/* auto-generated by gen_syscalls.py, don't edit */
53
54#ifndef _ASMLANGUAGE
55
56#include <syscall_list.h>
57#include <syscall_macros.h>
58
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63%s
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
70"""
71
72handler_template = """
73extern u32_t %s(u32_t arg1, u32_t arg2, u32_t arg3,
74 u32_t arg4, u32_t arg5, u32_t arg6, void *ssf);
75"""
76
77weak_template = """
Leandro Pereiraa1ae8452018-03-06 15:08:55 -080078__weak ALIAS_OF(handler_no_syscall)
Andrew Boiefa94ee72017-09-28 16:54:35 -070079u32_t %s(u32_t arg1, u32_t arg2, u32_t arg3,
80 u32_t arg4, u32_t arg5, u32_t arg6, void *ssf);
81"""
82
83
Andrew Boiea698e842018-07-23 17:27:57 -070084typename_regex = re.compile(r'(.*?)([A-Za-z0-9_]+)$')
85
86
87class SyscallParseException(Exception):
88 pass
89
90
91def typename_split(item):
92 if "[" in item:
93 raise SyscallParseException(
94 "Please pass arrays to syscalls as pointers, unable to process '%s'" %
95 item)
96
97 if "(" in item:
98 raise SyscallParseException(
99 "Please use typedefs for function pointers")
100
101 mo = typename_regex.match(item)
102 if not mo:
103 raise SyscallParseException("Malformed system call invocation")
104
105 m = mo.groups()
106 return (m[0].strip(), m[1])
107
108
109def analyze_fn(match_group):
110 func, args = match_group
111
112 try:
113 if args == "void":
114 args = []
115 else:
116 args = [typename_split(a.strip()) for a in args.split(",")]
117
118 func_type, func_name = typename_split(func)
119 except SyscallParseException:
120 sys.stderr.write("In declaration of %s\n" % func)
121 raise
122
123 sys_id = "K_SYSCALL_" + func_name.upper()
124
125 if func_type == "void":
126 suffix = "_VOID"
127 is_void = True
128 else:
129 is_void = False
130 if func_type in ["s64_t", "u64_t"]:
131 suffix = "_RET64"
132 else:
133 suffix = ""
134
135 is_void = (func_type == "void")
136
137 # Get the proper system call macro invocation, which depends on the
138 # number of arguments, the return type, and whether the implementation
139 # is an inline function
140 macro = "K_SYSCALL_DECLARE%d%s" % (len(args), suffix)
141
142 # Flatten the argument lists and generate a comma separated list
143 # of t0, p0, t1, p1, ... tN, pN as expected by the macros
144 flat_args = [i for sublist in args for i in sublist]
145 if not is_void:
146 flat_args = [func_type] + flat_args
147 flat_args = [sys_id, func_name] + flat_args
148 argslist = ", ".join(flat_args)
149
Mark Ruvald Pedersenf0e2e1b2018-09-11 12:21:02 +0200150 invocation = "%s(%s)" % (macro, argslist)
Andrew Boiea698e842018-07-23 17:27:57 -0700151
Flavio Ceolin6fc84fe2018-09-24 16:29:10 -0700152 handler = "hdlr_" + func_name
Andrew Boiea698e842018-07-23 17:27:57 -0700153
154 # Entry in _k_syscall_table
155 table_entry = "[%s] = %s" % (sys_id, handler)
156
157 return (handler, invocation, sys_id, table_entry)
158
Andrew Boiefa94ee72017-09-28 16:54:35 -0700159def parse_args():
160 global args
Anas Nashif72565532017-12-12 08:19:25 -0500161 parser = argparse.ArgumentParser(
162 description=__doc__,
163 formatter_class=argparse.RawDescriptionHelpFormatter)
Andrew Boiefa94ee72017-09-28 16:54:35 -0700164
Sebastian Bøe13a68402017-11-20 13:03:55 +0100165 parser.add_argument("-i", "--json-file", required=True,
Anas Nashif72565532017-12-12 08:19:25 -0500166 help="Read syscall information from json file")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700167 parser.add_argument("-d", "--syscall-dispatch", required=True,
Anas Nashif72565532017-12-12 08:19:25 -0500168 help="output C system call dispatch table file")
Andrew Boie353acf42018-07-23 18:10:15 -0700169 parser.add_argument("-l", "--syscall-list", required=True,
170 help="output C system call list header")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700171 parser.add_argument("-o", "--base-output", required=True,
Anas Nashif72565532017-12-12 08:19:25 -0500172 help="Base output directory for syscall macro headers")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700173 args = parser.parse_args()
174
175
176def main():
177 parse_args()
178
Sebastian Bøe13a68402017-11-20 13:03:55 +0100179 with open(args.json_file, 'r') as fd:
180 syscalls = json.load(fd)
181
Andrew Boiefa94ee72017-09-28 16:54:35 -0700182 invocations = {}
183 ids = []
184 table_entries = []
185 handlers = []
186
Andrew Boiea698e842018-07-23 17:27:57 -0700187 for match_group, fn in syscalls:
188 handler, inv, sys_id, entry = analyze_fn(match_group)
189
Andrew Boiefa94ee72017-09-28 16:54:35 -0700190 if fn not in invocations:
191 invocations[fn] = []
192
193 invocations[fn].append(inv)
194 ids.append(sys_id)
195 table_entries.append(entry)
196 handlers.append(handler)
197
198 with open(args.syscall_dispatch, "w") as fp:
Leandro Pereiraa1ae8452018-03-06 15:08:55 -0800199 table_entries.append("[K_SYSCALL_BAD] = handler_bad_syscall")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700200
201 weak_defines = "".join([weak_template % name for name in handlers])
202
203 fp.write(table_template % (weak_defines, ",\n\t".join(table_entries)))
204
205 # Listing header emitted to stdout
206 ids.sort()
207 ids.extend(["K_SYSCALL_BAD", "K_SYSCALL_LIMIT"])
Sebastian Bøe1a409902018-08-10 15:23:00 +0200208
209 ids_as_defines = ""
210 for i, item in enumerate(ids):
211 ids_as_defines += "#define {} {}\n".format(item, i)
212
Andrew Boiefa94ee72017-09-28 16:54:35 -0700213 handler_defines = "".join([handler_template % name for name in handlers])
Andrew Boie353acf42018-07-23 18:10:15 -0700214 with open(args.syscall_list, "w") as fp:
Sebastian Bøe1a409902018-08-10 15:23:00 +0200215 fp.write(list_template % (ids_as_defines, handler_defines))
Andrew Boiefa94ee72017-09-28 16:54:35 -0700216
217 os.makedirs(args.base_output, exist_ok=True)
218 for fn, invo_list in invocations.items():
219 out_fn = os.path.join(args.base_output, fn)
220
221 header = syscall_template % "\n\n".join(invo_list)
222
Andrew Boiefa94ee72017-09-28 16:54:35 -0700223 with open(out_fn, "w") as fp:
224 fp.write(header)
225
Anas Nashif72565532017-12-12 08:19:25 -0500226
Andrew Boiefa94ee72017-09-28 16:54:35 -0700227if __name__ == "__main__":
228 main()