Files
seL4/tools/hardware/outputs/c_header.py
Victor Phan 66bc2b1724 rename KDEV_PPTR/PPTR_KDEV to KDEV_BASE
This is the virtual address for the start of the kernel device mapping
region.
2019-11-21 15:53:11 +11:00

199 lines
5.9 KiB
Python

#
# 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 c header file from the device tree '''
import argparse
import builtins
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.
*/
#ifndef __PLAT_DEVICES_GEN_H
#define __PLAT_DEVICES_GEN_H
#include <linker.h>
#ifndef KDEV_BASE
#include <mode/hardware.h>
#endif
#define physBase {{ "0x{:x}".format(physBase) }}
/* INTERRUPTS */
{% for irq in kernel_irqs %}
/* {{ irq.desc }} */
{% if irq.has_enable() %}
{{ irq.get_enable_macro_str() }}
{% endif %}
{% if irq.has_sel() %}
{{ irq.get_sel_macro_str() }}
{% endif %}
#define {{ irq.label }} {{ irq.irq }}
{% if irq.has_sel() %}
#else
#define {{ irq.label }} {{ irq.false_irq }}
{{ irq.get_sel_endif() }}
{% endif %}
{% if irq.has_enable() %}
{{ irq.get_enable_endif() }}
{% endif %}
{% endfor -%}
/* KERNEL DEVICES */
{% for (addr, macro) in sorted(kernel_macros.items()) %}
#define {{ macro }} (KDEV_BASE + {{ "0x{:x}".format(addr) }})
{% endfor %}
#ifndef __ASSEMBLER__
{% if len(kernel_regions) > 0 %}
static const kernel_frame_t BOOT_RODATA kernel_devices[] = {
{% for group in kernel_regions %}
{% if group.has_macro() %}
{{ group.get_macro() }}
{% endif %}
/* {{ group.get_desc() }} */
{% for reg in group.regions %}
{
{% set map_addr = group.get_map_offset(reg) %}
{{ "0x{:x}".format(reg.base) }},
{% if map_addr in kernel_macros %}
{{ kernel_macros[map_addr] }},
{% else %}
/* contains {{ ', '.join(group.labels.keys()) }} */
KDEV_BASE + {{ "0x{:x}".format(map_addr) }},
{% endif %}
{% if args.arch == 'arm' %}
true, /* armExecuteNever */
{% endif %}
{% if group.user_ok %}
true, /* userAvailable */
{% else %}
false, /* userAvailable */
{% endif %}
},
{% endfor %}
{% if group.has_macro() %}
{{ group.get_endif() }}
{% endif %}
{% endfor %}
};
{% else %}
static const kernel_frame_t BOOT_RODATA *kernel_devices = NULL;
{% endif %}
/* PHYSICAL MEMORY */
static const p_region_t BOOT_RODATA avail_p_regs[] = {
{% for reg in physical_memory %}
{ {{ "0x{:x}".format(reg.base) }}, {{ "0x{:x}".format(reg.base + reg.size) }} }, /* {{reg.owner.path}} */
{% endfor %}
};
#endif /* !__ASSEMBLER__ */
#endif /* __PLAT_DEVICES_GEN_H */
'''
def get_kernel_devices(tree: fdt.FdtParser, rules: rule.HardwareYaml):
''' Given a device tree and a set of rules, returns a tuple (groups, offsets).
Groups is a list of 'KernelRegionGroups', each of which represents a single contiguous region of memory that is associated with a device.
Offsets is a dict of offset -> label, where label is the name given to the kernel for that address (e.g. SERIAL_PPTR) and offset is the offset from KDEV_BASE at which it's mapped.'''
kernel_devices = tree.get_kernel_devices()
kernel_offset = 0
groups = []
for dev in kernel_devices:
dev_rule = rules.get_rule(dev)
new_regions = dev_rule.get_regions(dev)
for reg in new_regions:
if reg in groups:
other = groups[groups.index(reg)]
other.take_labels(reg)
else:
groups.append(reg)
offsets = {}
for group in groups:
kernel_offset = group.set_kernel_offset(kernel_offset)
offsets.update(group.get_labelled_addresses())
return (groups, offsets)
def get_interrupts(tree: fdt.FdtParser, rules: rule.HardwareYaml):
''' Get dict of interrupts, {label: KernelInterrupt} from the DT and hardware rules. '''
kernel_devices = tree.get_kernel_devices()
irqs = []
for dev in kernel_devices:
dev_rule = rules.get_rule(dev)
print(f"interrupts for device {dev.path}")
irqs += dev_rule.get_interrupts(tree, dev)
ret = {}
for irq in irqs:
if irq.label in ret:
if irq.prio > ret[irq.label].prio:
ret[irq.label] = irq
else:
ret[irq.label] = irq
ret = list(ret.values())
ret.sort(key=lambda a: a.label)
return ret
def run(tree: fdt.FdtParser, hardware: rule.HardwareYaml, config: config.Config, args: argparse.Namespace):
if not args.header_out:
raise ValueError('You need to specify a header-out to use c header output')
physical_memory, reserved, physBase = memory.get_physical_memory(tree, config)
kernel_regions, kernel_macros = get_kernel_devices(tree, hardware)
kernel_irqs = get_interrupts(tree, hardware)
template = Environment(loader=BaseLoader, trim_blocks=True,
lstrip_blocks=True).from_string(HEADER_TEMPLATE)
template_args = dict(builtins.__dict__, **{
'args': args,
'kernel_irqs': kernel_irqs,
'kernel_macros': kernel_macros,
'kernel_regions': kernel_regions,
'physBase': physBase,
'physical_memory': physical_memory,
})
data = template.render(template_args)
args.header_out.write(data)
args.header_out.close()
def add_args(parser):
parser.add_argument('--header-out', help='output file for c header',
type=argparse.FileType('w'))