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