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.
This commit is contained in:
parent
32e31e3a01
commit
7eb4147e43
2 changed files with 136 additions and 1 deletions
134
tools/hardware/outputs/elfloader.py
Normal file
134
tools/hardware/outputs/elfloader.py
Normal file
|
|
@ -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'))
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue