def get_memory_regions(tree: FdtParser): ''' Get all regions with device_type = memory in the tree ''' regions = set() def visitor(node: WrappedNode): if node.has_prop('device_type') and node.get_prop( 'device_type').strings[0] == 'memory': regions.update(node.get_regions()) tree.visit(visitor) return regions
def get_kernel_devices(tree: FdtParser, hw_yaml: HardwareYaml) -> (List, Dict): ''' 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 = hw_yaml.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 run(tree: fdt.FdtParser, hardware: rule.HardwareYaml, config: config.Config, args: argparse.Namespace): devices = tree.get_elfloader_devices() cpu_info = get_elfloader_cpus(tree, devices) max_reg = 1 device_info = [] 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__, **{ 'cpus': cpu_info, 'devices': device_info, 'max_reg': max_reg, 'uses_psci': any([c['enable_method'] == 'psci' for c in cpu_info]) }) data = template.render(template_args) args.elfloader_out.write(data) args.elfloader_out.close()
def get_interrupts(self, tree: FdtParser, node: WrappedNode) -> List[KernelInterrupt]: ''' Returns a list of KernelInterrupts that this rule says are used by the kernel for this device. ''' ret = [] interrupts = node.get_interrupts(tree) for name, rule in self.interrupts.items(): irq_desc = '{} generated from {}'.format(name, node.path) if type(rule) == dict: en_macro = rule.get('enable_macro', None) if rule['index'] >= len(interrupts): # XXX: skip this rule silently. continue defaultIrq = interrupts[rule['index']] sel_macro = rule.get('sel_macro', None) falseIrq = interrupts[rule['undef_index']] if 'undef_index' in rule else -1 prio = rule.get('priority', 0) irq = KernelInterrupt(name, defaultIrq, prio, sel_macro, falseIrq, en_macro, desc=irq_desc) elif type(rule) == int: if rule >= len(interrupts): # XXX: skip this rule silently. continue irq = KernelInterrupt(name, interrupts[rule], desc=irq_desc) else: # rule == 'boot-cpu' affinities = node.get_interrupt_affinities() boot_cpu = tree.get_boot_cpu() idx = affinities.index(boot_cpu) irq = KernelInterrupt(name, interrupts[idx]) ret.append(irq) return ret
def get_physical_memory(tree: FdtParser, config: Config) -> List[Region]: ''' returns a list of regions representing physical memory as used by the kernel ''' regions = get_memory_regions(tree) reserved = parse_reserved_regions(tree.get_path('/reserved-memory')) regions = reserve_regions(regions, reserved) regions, extra_reserved, physBase = align_memory(regions, config) return regions, reserved.union(extra_reserved), physBase
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 get_kernel_devices(tree: fdt.FdtParser, rules: rule.HardwareYaml): kernel_devices = tree.get_kernel_devices() groups = [] for dev in kernel_devices: rule = rules.get_rule(dev) groups += rule.get_regions(dev) return groups
def get_kernel_devices(tree: FdtParser, hw_yaml: HardwareYaml): kernel_devices = tree.get_kernel_devices() groups = [] for dev in kernel_devices: rule = hw_yaml.get_rule(dev) groups += rule.get_regions(dev) return groups
def get_cpus(tree: FdtParser) -> List[WrappedNode]: ' Return a list of all the CPUs described in this device tree. ' cpus_node = tree.get_path('/cpus') found_cpus = [] for node in cpus_node: if node.has_prop('device_type') and node.get_prop('device_type').strings[0] == 'cpu': found_cpus.append(node) return found_cpus
def main(args: argparse.Namespace): ''' Parse the DT and hardware config YAML and run each selected output method. ''' cfg = hardware.config.get_arch_config(args.sel4arch, args.addrspace_max) parsed_dt = FdtParser(args.dtb) rules = yaml.load(args.hardware_config, Loader=yaml.FullLoader) schema = yaml.load(args.hardware_schema, Loader=yaml.FullLoader) validate_rules(rules, schema) hw_yaml = HardwareYaml(rules, cfg) arg_dict = vars(args) for t in sorted(OUTPUTS.keys()): if arg_dict[t]: OUTPUTS[t].run(parsed_dt, hw_yaml, cfg, args)
def run(tree: FdtParser, hw_yaml: HardwareYaml, config: Config, args: argparse.Namespace): if not args.compat_strings_out: raise ValueError( 'You need to specify a compat-strings-out to use compat strings output' ) chosen = tree.get_kernel_devices() compatibles = set() for dev in chosen: compatibles.add(hw_yaml.get_matched_compatible(dev)) args.compat_strings_out.write(';'.join(sorted(compatibles)) + ';\n') args.compat_strings_out.close()
def get_interrupts(tree: FdtParser, hw_yaml: HardwareYaml) -> List: ''' 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 = hw_yaml.get_rule(dev) if len(dev_rule.interrupts.items()) > 0: 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 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