blob: ada81acc0a125abb091b3fe8e89fd2f0c61a6b75 [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
Andrew Boiec78c5e62019-03-11 14:45:43 -07007"""
8Script to generate system call invocation macros
9
10This script parses the system call metadata JSON file emitted by
11parse_syscalls.py to create several files:
12
13- A file containing weak aliases of any potentially unimplemented system calls,
14 as well as the system call dispatch table, which maps system call type IDs
15 to their handler functions.
16
17- A header file defing the system call type IDs, as well as function
18 prototypes for all system call handler functions.
19
20- A directory containing header files. Each header corresponds to a header
21 that was identified as containing system call declarations. These
22 generated headers contain the inline invocation functions for each system
23 call in that header.
24"""
25
Andrew Boiefa94ee72017-09-28 16:54:35 -070026import sys
27import re
28import argparse
29import os
Sebastian Bøe13a68402017-11-20 13:03:55 +010030import json
Andrew Boiefa94ee72017-09-28 16:54:35 -070031
32table_template = """/* auto-generated by gen_syscalls.py, don't edit */
33
Paul Sokolovsky94620bd2017-10-01 23:47:43 +030034/* Weak handler functions that get replaced by the real ones unless a system
35 * call is not implemented due to kernel configuration.
Andrew Boiefa94ee72017-09-28 16:54:35 -070036 */
37%s
38
39const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = {
40\t%s
41};
42"""
43
44list_template = """
45/* auto-generated by gen_syscalls.py, don't edit */
Flavio Ceolina7fffa92018-09-13 15:06:35 -070046#ifndef ZEPHYR_SYSCALL_LIST_H
47#define ZEPHYR_SYSCALL_LIST_H
Andrew Boiefa94ee72017-09-28 16:54:35 -070048
Sebastian Bøe1a409902018-08-10 15:23:00 +020049%s
50
Andrew Boiefa94ee72017-09-28 16:54:35 -070051#ifndef _ASMLANGUAGE
52
Andrew Boiec67eb562018-03-26 13:44:44 -070053#include <zephyr/types.h>
54
Andrew Boiefa94ee72017-09-28 16:54:35 -070055#ifdef __cplusplus
56extern "C" {
57#endif
58
Andrew Boiefa94ee72017-09-28 16:54:35 -070059%s
60
61#ifdef __cplusplus
62}
63#endif
64
65#endif /* _ASMLANGUAGE */
66
Flavio Ceolina7fffa92018-09-13 15:06:35 -070067#endif /* ZEPHYR_SYSCALL_LIST_H */
Andrew Boiefa94ee72017-09-28 16:54:35 -070068"""
69
70syscall_template = """
71/* auto-generated by gen_syscalls.py, don't edit */
72
73#ifndef _ASMLANGUAGE
74
75#include <syscall_list.h>
76#include <syscall_macros.h>
77
78#ifdef __cplusplus
79extern "C" {
80#endif
81
82%s
83
84#ifdef __cplusplus
85}
86#endif
87
88#endif
89"""
90
91handler_template = """
92extern u32_t %s(u32_t arg1, u32_t arg2, u32_t arg3,
93 u32_t arg4, u32_t arg5, u32_t arg6, void *ssf);
94"""
95
96weak_template = """
Leandro Pereiraa1ae8452018-03-06 15:08:55 -080097__weak ALIAS_OF(handler_no_syscall)
Andrew Boiefa94ee72017-09-28 16:54:35 -070098u32_t %s(u32_t arg1, u32_t arg2, u32_t arg3,
99 u32_t arg4, u32_t arg5, u32_t arg6, void *ssf);
100"""
101
102
Andrew Boiea698e842018-07-23 17:27:57 -0700103typename_regex = re.compile(r'(.*?)([A-Za-z0-9_]+)$')
104
105
106class SyscallParseException(Exception):
107 pass
108
109
110def typename_split(item):
111 if "[" in item:
112 raise SyscallParseException(
113 "Please pass arrays to syscalls as pointers, unable to process '%s'" %
114 item)
115
116 if "(" in item:
117 raise SyscallParseException(
118 "Please use typedefs for function pointers")
119
120 mo = typename_regex.match(item)
121 if not mo:
122 raise SyscallParseException("Malformed system call invocation")
123
124 m = mo.groups()
125 return (m[0].strip(), m[1])
126
127
128def analyze_fn(match_group):
129 func, args = match_group
130
131 try:
132 if args == "void":
133 args = []
134 else:
135 args = [typename_split(a.strip()) for a in args.split(",")]
136
137 func_type, func_name = typename_split(func)
138 except SyscallParseException:
139 sys.stderr.write("In declaration of %s\n" % func)
140 raise
141
142 sys_id = "K_SYSCALL_" + func_name.upper()
143
144 if func_type == "void":
145 suffix = "_VOID"
146 is_void = True
147 else:
148 is_void = False
149 if func_type in ["s64_t", "u64_t"]:
150 suffix = "_RET64"
151 else:
152 suffix = ""
153
154 is_void = (func_type == "void")
155
156 # Get the proper system call macro invocation, which depends on the
157 # number of arguments, the return type, and whether the implementation
158 # is an inline function
159 macro = "K_SYSCALL_DECLARE%d%s" % (len(args), suffix)
160
161 # Flatten the argument lists and generate a comma separated list
162 # of t0, p0, t1, p1, ... tN, pN as expected by the macros
163 flat_args = [i for sublist in args for i in sublist]
164 if not is_void:
165 flat_args = [func_type] + flat_args
166 flat_args = [sys_id, func_name] + flat_args
167 argslist = ", ".join(flat_args)
168
Mark Ruvald Pedersenf0e2e1b2018-09-11 12:21:02 +0200169 invocation = "%s(%s)" % (macro, argslist)
Andrew Boiea698e842018-07-23 17:27:57 -0700170
Andrew Boie7ea21122019-03-15 10:47:05 -0700171 handler = "z_hdlr_" + func_name
Andrew Boiea698e842018-07-23 17:27:57 -0700172
173 # Entry in _k_syscall_table
174 table_entry = "[%s] = %s" % (sys_id, handler)
175
176 return (handler, invocation, sys_id, table_entry)
177
Andrew Boiefa94ee72017-09-28 16:54:35 -0700178def parse_args():
179 global args
Anas Nashif72565532017-12-12 08:19:25 -0500180 parser = argparse.ArgumentParser(
181 description=__doc__,
182 formatter_class=argparse.RawDescriptionHelpFormatter)
Andrew Boiefa94ee72017-09-28 16:54:35 -0700183
Sebastian Bøe13a68402017-11-20 13:03:55 +0100184 parser.add_argument("-i", "--json-file", required=True,
Anas Nashif72565532017-12-12 08:19:25 -0500185 help="Read syscall information from json file")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700186 parser.add_argument("-d", "--syscall-dispatch", required=True,
Anas Nashif72565532017-12-12 08:19:25 -0500187 help="output C system call dispatch table file")
Andrew Boie353acf42018-07-23 18:10:15 -0700188 parser.add_argument("-l", "--syscall-list", required=True,
189 help="output C system call list header")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700190 parser.add_argument("-o", "--base-output", required=True,
Anas Nashif72565532017-12-12 08:19:25 -0500191 help="Base output directory for syscall macro headers")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700192 args = parser.parse_args()
193
194
195def main():
196 parse_args()
197
Sebastian Bøe13a68402017-11-20 13:03:55 +0100198 with open(args.json_file, 'r') as fd:
199 syscalls = json.load(fd)
200
Andrew Boiefa94ee72017-09-28 16:54:35 -0700201 invocations = {}
202 ids = []
203 table_entries = []
204 handlers = []
205
Andrew Boiea698e842018-07-23 17:27:57 -0700206 for match_group, fn in syscalls:
207 handler, inv, sys_id, entry = analyze_fn(match_group)
208
Andrew Boiefa94ee72017-09-28 16:54:35 -0700209 if fn not in invocations:
210 invocations[fn] = []
211
212 invocations[fn].append(inv)
213 ids.append(sys_id)
214 table_entries.append(entry)
215 handlers.append(handler)
216
217 with open(args.syscall_dispatch, "w") as fp:
Leandro Pereiraa1ae8452018-03-06 15:08:55 -0800218 table_entries.append("[K_SYSCALL_BAD] = handler_bad_syscall")
Andrew Boiefa94ee72017-09-28 16:54:35 -0700219
220 weak_defines = "".join([weak_template % name for name in handlers])
221
222 fp.write(table_template % (weak_defines, ",\n\t".join(table_entries)))
223
224 # Listing header emitted to stdout
225 ids.sort()
226 ids.extend(["K_SYSCALL_BAD", "K_SYSCALL_LIMIT"])
Sebastian Bøe1a409902018-08-10 15:23:00 +0200227
228 ids_as_defines = ""
229 for i, item in enumerate(ids):
230 ids_as_defines += "#define {} {}\n".format(item, i)
231
Andrew Boiefa94ee72017-09-28 16:54:35 -0700232 handler_defines = "".join([handler_template % name for name in handlers])
Andrew Boie353acf42018-07-23 18:10:15 -0700233 with open(args.syscall_list, "w") as fp:
Sebastian Bøe1a409902018-08-10 15:23:00 +0200234 fp.write(list_template % (ids_as_defines, handler_defines))
Andrew Boiefa94ee72017-09-28 16:54:35 -0700235
236 os.makedirs(args.base_output, exist_ok=True)
237 for fn, invo_list in invocations.items():
238 out_fn = os.path.join(args.base_output, fn)
239
240 header = syscall_template % "\n\n".join(invo_list)
241
Andrew Boiefa94ee72017-09-28 16:54:35 -0700242 with open(out_fn, "w") as fp:
243 fp.write(header)
244
Anas Nashif72565532017-12-12 08:19:25 -0500245
Andrew Boiefa94ee72017-09-28 16:54:35 -0700246if __name__ == "__main__":
247 main()