From 7eb4147e4369d68a4aa6cd884a4ae816e1ce406b Mon Sep 17 00:00:00 2001 From: Simon Shields Date: Tue, 5 Nov 2019 10:46:48 +1100 Subject: [PATCH] hardware_gen: add elfloader output The elfloader is going to start using devices based on the device tree. Add an output method for hardware_gen.py that generates header files that the elfloader can use. Currently they contain an array of "devices", where each device has a compatiblity string and a series of regions (represented simply as the physical address of the region). For now, the elfloader only uses the serial device specified by the stdout-path property in the DTB. --- tools/hardware/outputs/elfloader.py | 134 ++++++++++++++++++++++++++++ tools/hardware_gen.py | 3 +- 2 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 tools/hardware/outputs/elfloader.py diff --git a/tools/hardware/outputs/elfloader.py b/tools/hardware/outputs/elfloader.py new file mode 100644 index 000000000..cabfc95b9 --- /dev/null +++ b/tools/hardware/outputs/elfloader.py @@ -0,0 +1,134 @@ +# +# Copyright 2019, Data61 +# Commonwealth Scientific and Industrial Research Organisation (CSIRO) +# ABN 41 687 119 230. +# +# This software may be distributed and modified according to the terms of +# the GNU General Public License version 2. Note that NO WARRANTY is provided. +# See "LICENSE_GPLv2.txt" for details. +# +# @TAG(DATA61_GPL) +# + +''' generate a header file for the elfloader from a device tree ''' + +import argparse +import builtins +import logging +import pyfdt.pyfdt + +from jinja2 import Environment, BaseLoader + +from hardware import config, fdt +from hardware.utils import memory, rule + + +HEADER_TEMPLATE = '''/* + * Copyright 2019, Data61 + * Commonwealth Scientific and Industrial Research Organisation (CSIRO) + * ABN 41 687 119 230. + * + * This software may be distributed and modified according to the terms of + * the GNU General Public License version 2. Note that NO WARRANTY is provided. + * See "LICENSE_GPLv2.txt" for details. + * + * @TAG(DATA61_GPL) + */ +/* + * This file is autogenerated by kernel/tools/hardware_gen.py + */ + +#pragma once + +#define MAX_NUM_REGIONS {{ max_reg }} + +struct elfloader_driver; + +struct elfloader_device { + const char *compat; + volatile void *region_bases[MAX_NUM_REGIONS]; + struct elfloader_driver *drv; +}; + +#ifdef DRIVER_COMMON +struct elfloader_device elfloader_devices[] = { +{% for d in devices %} + { + /* {{ d['path'] }} */ + .compat = "{{ d['compat'] }}", + .region_bases = { + {% for r in d['regions'] %} + (void *){{ "0x{:x}".format(r.base) }}, + {% endfor %} + {% for i in range(max_reg - len(d['regions'])) %} + (void *)0, + {% endfor %} + }, + }, +{% endfor %} +{% if devices | length == 0 %} + { + .compat = NULL, + .region_bases = { + {% for i in range(max_reg) %} + NULL, + {% endfor %} + }, + }, +{% endif %} +}; +#else +struct elfloader_device *elfloader_devices; +#endif +''' + + +def get_elfloader_devices(tree: fdt.FdtParser, rules: rule.HardwareYaml): + devices = [] + + # serial device + chosen = tree.get_path('/chosen') + if not chosen.has_prop('stdout-path') or type(chosen.get_prop('stdout-path')) != pyfdt.pyfdt.FdtPropertyStrings: + logging.info('DT has no stdout-path, elfloader may not produce output!') + else: + val = chosen.get_prop('stdout-path').strings[0] + if val[0] == '/': + path = val + else: + path = tree.lookup_alias(val) + devices.append(tree.get_path(path)) + return devices + + +def run(tree: fdt.FdtParser, hardware: rule.HardwareYaml, config: config.Config, args: argparse.Namespace): + devices = get_elfloader_devices(tree, hardware) + device_info = [] + max_reg = 1 + for dev in devices: + obj = { + 'compat': hardware.get_matched_compatible(dev), + 'path': dev.path, + 'regions': dev.get_regions() + } + max_reg = max(len(obj['regions']), max_reg) + + device_info.append(obj) + + device_info.sort(key=lambda a: a['compat']) + + template = Environment(loader=BaseLoader, trim_blocks=True, + lstrip_blocks=True).from_string(HEADER_TEMPLATE) + + template_args = dict(builtins.__dict__, **{ + 'devices': device_info, + 'max_reg': max_reg + }) + + data = template.render(template_args) + args.elfloader_out.write(data) + args.elfloader_out.close() + + +def add_args(parser): + parser.add_argument('--elfloader-out', help='output file for elfloader header', + type=argparse.FileType('w')) diff --git a/tools/hardware_gen.py b/tools/hardware_gen.py index bee7f024b..f4451571c 100644 --- a/tools/hardware_gen.py +++ b/tools/hardware_gen.py @@ -17,12 +17,13 @@ import logging import yaml from hardware import config, fdt -from hardware.outputs import c_header, compat_strings, yaml as yaml_out +from hardware.outputs import c_header, compat_strings, yaml as yaml_out, elfloader from hardware.utils.rule import HardwareYaml OUTPUTS = { 'c_header': c_header, 'compat_strings': compat_strings, + 'elfloader': elfloader, 'yaml': yaml_out, }