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