1#!/usr/bin/env python3 2# 3# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 4# 5# SPDX-License-Identifier: GPL-2.0-only 6# 7 8from __future__ import print_function, division 9import argparse 10import logging 11import yaml 12 13from hardware import config, fdt 14from hardware.outputs import c_header, compat_strings, yaml as yaml_out, elfloader 15from hardware.utils.rule import HardwareYaml 16 17OUTPUTS = { 18 'c_header': c_header, 19 'compat_strings': compat_strings, 20 'elfloader': elfloader, 21 'yaml': yaml_out, 22} 23 24 25def validate_rules(rules, schema): 26 ''' Try and validate a hardware rules file against a schema. 27 If jsonschema is not installed, succeed with a warning. ''' 28 try: 29 from jsonschema import validate 30 return validate(rules, schema) 31 except ImportError: 32 logging.warning('Skipping hardware YAML validation; `pip install jsonschema` to validate') 33 return True 34 35 36def add_task_args(outputs: dict, parser: argparse.ArgumentParser): 37 ''' Add arguments for each output type. ''' 38 for t in sorted(outputs.keys()): 39 task = outputs[t] 40 name = t.replace('_', '-') 41 group = parser.add_argument_group('{} pass'.format(name)) 42 group.add_argument('--' + name, help=task.__doc__.strip(), action='store_true') 43 task.add_args(group) 44 45 46def main(args: argparse.Namespace): 47 ''' Parse the DT and hardware config YAML and run each 48 selected output method. ''' 49 cfg = config.get_arch_config(args.arch, args.addrspace_max) 50 parsed_dt = fdt.FdtParser(args.dtb) 51 rules = yaml.load(args.hardware_config, Loader=yaml.FullLoader) 52 schema = yaml.load(args.hardware_schema, Loader=yaml.FullLoader) 53 validate_rules(rules, schema) 54 hardware = HardwareYaml(rules, cfg) 55 56 arg_dict = vars(args) 57 for t in sorted(OUTPUTS.keys()): 58 if arg_dict[t]: 59 OUTPUTS[t].run(parsed_dt, hardware, cfg, args) 60 61 62if __name__ == '__main__': 63 parser = argparse.ArgumentParser( 64 description='transform device tree input to seL4 build configuration artefacts' 65 ) 66 67 parser.add_argument('--dtb', help='device tree blob to parse for generation', 68 required=True, type=argparse.FileType('rb')) 69 parser.add_argument('--hardware-config', help='YAML file containing configuration for kernel devices', 70 required=True, type=argparse.FileType('r')) 71 parser.add_argument('--hardware-schema', help='YAML file containing schema for hardware config', 72 required=True, type=argparse.FileType('r')) 73 parser.add_argument('--arch', help='architecture to generate for', default='arm') 74 parser.add_argument('--addrspace-max', 75 help='maximum address that is available as device untyped', type=int, default=32) 76 77 parser.add_argument('--enable-profiling', help='enable profiling', 78 action='store_const', const=True, default=False) 79 80 add_task_args(OUTPUTS, parser) 81 82 args = parser.parse_args() 83 84 if args.enable_profiling: 85 import cProfile 86 cProfile.run('main(args)', sort='cumtime') 87 else: 88 main(args) 89