1#!/usr/bin/env python
2#
3# Copyright 2017, Data61
4# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
5# ABN 41 687 119 230.
6#
7# This software may be distributed and modified according to the terms of
8# the BSD 2-Clause license. Note that NO WARRANTY is provided.
9# See "LICENSE_BSD2.txt" for details.
10#
11# @TAG(DATA61_BSD)
12#
13
14# seL4 Invocation ID Generator
15# ============================
16
17from __future__ import print_function
18import argparse
19import sys
20import xml.dom.minidom
21import pkg_resources;
22# We require jinja2 to be at least version 2.10 as we use the 'namespace' feature from
23# that version
24pkg_resources.require("jinja2>=2.10")
25from jinja2 import Environment, BaseLoader
26
27
28COMMON_HEADER = """
29{%- if libsel4 -%}
30/*
31 * Copyright 2017, Data61
32 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
33 * ABN 41 687 119 230.
34 *
35 * This software may be distributed and modified according to the terms of
36 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
37 * See "LICENSE_BSD2.txt" for details.
38 *
39 * @TAG(DATA61_BSD)
40 */
41{%- else -%}
42/*
43 * Copyright 2014, General Dynamics C4 Systems
44 *
45 * This software may be distributed and modified according to the terms of
46 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
47 * See "LICENSE_GPLv2.txt" for details.
48 *
49 * @TAG(GD_GPL)
50 */
51{%- endif %}
52
53/* This header was generated by kernel/tools/invocation_header_gen.py.
54 *
55 * To add an invocation call number, edit libsel4/include/interfaces/sel4.xml.
56 *
57 */"""
58
59INVOCATION_TEMPLATE = COMMON_HEADER + """
60#ifndef __{{header_title}}_INVOCATION_H
61#define __{{header_title}}_INVOCATION_H
62
63enum invocation_label {
64    InvalidInvocation,
65    {%- for label, condition in invocations %}
66    {%- if condition %}
67#if {{condition}}
68    {%- endif %}
69    {{label}},
70    {%- if condition %}
71#endif
72    {%- endif %}
73    {%- endfor %}
74    nInvocationLabels
75};
76
77{%- if libsel4 %}
78#include <sel4/sel4_arch/invocation.h>
79#include <sel4/arch/invocation.h>
80{%- endif %}
81
82#endif /* __{{header_title}}_INVOCATION_H */
83
84"""
85
86SEL4_ARCH_INVOCATION_TEMPLATE = COMMON_HEADER + """
87#ifndef __{{header_title}}_SEL4_ARCH_INVOCATION_H
88#define __{{header_title}}_SEL4_ARCH_INVOCATION_H
89
90{%- if not libsel4 %}
91#include <api/invocation.h>
92{%- endif %}
93
94{%- set ns = namespace(first=True) %}
95enum sel4_arch_invocation_label {
96    {%- for label, condition in invocations %}
97        {%- if condition %}
98            {%- if ns.first %}
99#error "First sel4_arch invocation label cannot be conditional"
100            {%- endif %}
101#if {{condition}}
102        {%- endif %}
103        {%- if ns.first %}
104            {%- set ns.first = False %}
105    {{label}} = nInvocationLabels,
106        {%- else %}
107    {{label}},
108        {%- endif %}
109        {%- if condition %}
110#endif
111        {%- endif %}
112    {%- endfor %}
113    {%- if ns.first %}
114    nSeL4ArchInvocationLabels = nInvocationLabels
115    {%- else %}
116    nSeL4ArchInvocationLabels
117    {%- endif %}
118};
119
120#endif /* __{{header_title}}_SEL4_ARCH_INVOCATION_H */
121
122"""
123
124ARCH_INVOCATION_TEMPLATE = COMMON_HEADER + """
125#ifndef __{{header_title}}_ARCH_INVOCATION_H
126#define __{{header_title}}_ARCH_INVOCATION_H
127
128{%- if not libsel4 %}
129#include <arch/api/sel4_invocation.h>
130{%- endif %}
131
132{%- set ns = namespace(first=1) %}
133enum arch_invocation_label {
134    {%- for label, condition in invocations %}
135    {%- if condition %}
136    {%- if ns.first  %}
137#error "First arch invocation label cannot be conditional"
138    {%- endif %}
139#if {{condition}}
140    {%- endif %}
141    {%- if ns.first %}
142    {{label}} = nSeL4ArchInvocationLabels,
143    {%- set ns.first = False %}
144    {%- else %}
145    {{label}},
146    {%- endif %}
147    {%- if condition %}
148#endif
149    {%- endif %}
150    {%- endfor %}
151    {%- if ns.first %}
152    nArchInvocationLabels = nSeL4ArchInvocationLabels
153    {%- else %}
154    nArchInvocationLabels
155    {%- endif %}
156};
157
158#endif /* __{{header_title}}_ARCH_INVOCATION_H */
159
160"""
161
162def parse_args():
163    parser = argparse.ArgumentParser(description='Generate seL4 invocation API \
164        constants and header files')
165    parser.add_argument('--xml', type=argparse.FileType('r'),
166            help='Name of xml file with invocation definitions', required=True)
167    parser.add_argument('--dest', type=argparse.FileType('w'),
168            help='Name of file to create', required=True)
169    parser.add_argument('--libsel4', action='store_true',
170        help='Is this being generated for libsel4?')
171    group = parser.add_mutually_exclusive_group()
172    group.add_argument('--arch', action='store_true',
173            help='Is this being generated for the arch layer?')
174    group.add_argument('--sel4_arch', action='store_true',
175            help='Is this being generated for the seL4 arch layer?')
176
177    return parser.parse_args()
178
179def parse_xml(xml_file):
180    try:
181        doc = xml.dom.minidom.parse(xml_file)
182    except:
183        print("Error: invalid xml file", file=sys.stderr)
184        sys.exit(-1)
185
186    invocation_labels = []
187    for method in doc.getElementsByTagName("method"):
188        invocation_labels.append((str(method.getAttribute("id")), str(method.getAttribute("condition"))))
189
190    return invocation_labels
191
192def generate(args, invocations):
193
194    header_title = "API"
195    if args.libsel4:
196        header_title = "LIBSEL4"
197
198    if args.arch:
199        template = Environment(loader=BaseLoader).from_string(ARCH_INVOCATION_TEMPLATE)
200
201    elif args.sel4_arch:
202        template = Environment(loader=BaseLoader).from_string(SEL4_ARCH_INVOCATION_TEMPLATE)
203    else:
204        template = Environment(loader=BaseLoader).from_string(INVOCATION_TEMPLATE)
205
206    data = template.render({'header_title': header_title, 'libsel4' : args.libsel4, 'invocations' : invocations, 'num_invocations' : len(invocations)})
207    args.dest.write(data)
208
209    args.dest.close()
210
211if __name__ == "__main__":
212    args = parse_args()
213
214    invocations = parse_xml(args.xml)
215    args.xml.close()
216
217    generate(args, invocations)
218
219