Beispiel #1
0
    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
Beispiel #2
0
 def get_matched_compatible(self, device: WrappedNode) -> str:
     ''' Returns the best matching compatible string for this device '''
     if not device.has_prop('compatible'):
         raise ValueError(
             'Not sure what to do with node {} with no compatible!'.format(device.path))
     for compat in device.get_prop('compatible').strings:
         if compat in self.rules:
             return compat
     return None
Beispiel #3
0
Datei: fdt.py Projekt: niwis/seL4
    def _walk(self):
        ''' walk the underlying fdt, constructing wrapped nodes as we go '''
        root = self.fdt.get_rootnode()
        self.wrapped_root = WrappedNode(root, None, '/')

        # for easier parent lookups
        self.by_path = {'/': self.wrapped_root}
        for (name, node) in root.walk():
            if not isinstance(node, pyfdt.pyfdt.FdtNode):
                continue
            parent_path = name.rsplit('/', 1)[0]
            if parent_path == '':
                parent_path = '/'

            parent = self.by_path[parent_path]
            wrapped = WrappedNode(node, parent, name)
            self.by_path[name] = wrapped

            if not wrapped.get_phandle():
                continue
            self.by_phandle[wrapped.get_phandle()] = wrapped
            # We only care about interrupt controllers with phandles -
            # if an interrupt controller has no phandle, it isn't used anywhere
            # and so we can safely ignore it.
            if wrapped.has_prop('interrupt-controller') or wrapped.has_prop(
                    'interrupt-map'):
                self.irq_controllers[
                    wrapped.get_phandle()] = create_irq_controller(
                        wrapped, self)
Beispiel #4
0
def create_irq_controller(node: WrappedNode, tree: 'FdtParser'):
    if node.has_prop('interrupt-map'):
        # interrupt nexus
        return InterruptNexus(node, tree)
    elif node.has_prop('compatible'):
        # try and find a matching class that will know how to parse it
        for compat in node.get_prop('compatible').strings:
            if compat in CONTROLLERS:
                return CONTROLLERS[compat](node, tree)
    # otherwise, just return a dummy irq controller
    return IrqController(node, tree)
Beispiel #5
0
    def get_rule(self, device: WrappedNode) -> DeviceRule:
        ''' Returns the matching DeviceRule for this device. '''
        if not device.has_prop('compatible'):
            raise ValueError(
                'Not sure what to do with node {} with no compatible!'.format(device.path))

        for compat in device.get_prop('compatible').strings:
            if compat in self.rules:
                return self.rules[compat]

        raise ValueError('Failed to match compatibles "{}" for node {}!'.format(
            ', '.join(device.get_prop('compatible').strings), device.path))
Beispiel #6
0
    def get_regions(self, node: WrappedNode) -> List[KernelRegionGroup]:
        ''' Returns a list of KernelRegionGroups that this rule specifies should be mapped into the kernel for this device. '''
        ret = []
        regions = node.get_regions()

        for (i, rule) in self.regions.items():
            if i >= len(regions):
                # XXX: skip this rule silently
                continue
            reg = regions[i]

            kernel_name = rule['kernel']
            user = rule.get('user', False)
            macro = rule.get('macro', None)
            max_size = 1 << self.config.get_page_bits()
            if 'kernel_size' in rule:
                max_size = rule['kernel_size']
            elif max_size < reg.size:
                logging.warning(
                    "Only mapping {}/{} bytes from node {}, region {}. Set kernel_size in YAML to silence."
                    .format(max_size, reg.size, node.path, i))
            ret.append(
                KernelRegionGroup(reg, kernel_name,
                                  self.config.get_page_bits(), max_size, macro,
                                  user))

        return ret
Beispiel #7
0
 def visitor(node: WrappedNode):
     if node.has_prop('device_type') and node.get_prop(
             'device_type').strings[0] == 'memory':
         regions.update(node.get_regions())
Beispiel #8
0
Datei: fdt.py Projekt: niwis/seL4
class FdtParser:
    ''' Parse a DTB into a python representation '''
    def __init__(self, dtb_file: IO[bytes]):
        self.fdt = pyfdt.pyfdt.FdtBlobParse(dtb_file).to_fdt()
        self.wrapped_root: WrappedNode
        self.by_phandle: Dict[int, WrappedNode] = {}
        self.by_path: Dict[str, WrappedNode] = {}
        self.irq_controllers: Dict[int, IrqController] = {}
        # initialise the "nice" representation of the tree
        self._walk()

    def _walk(self):
        ''' walk the underlying fdt, constructing wrapped nodes as we go '''
        root = self.fdt.get_rootnode()
        self.wrapped_root = WrappedNode(root, None, '/')

        # for easier parent lookups
        self.by_path = {'/': self.wrapped_root}
        for (name, node) in root.walk():
            if not isinstance(node, pyfdt.pyfdt.FdtNode):
                continue
            parent_path = name.rsplit('/', 1)[0]
            if parent_path == '':
                parent_path = '/'

            parent = self.by_path[parent_path]
            wrapped = WrappedNode(node, parent, name)
            self.by_path[name] = wrapped

            if not wrapped.get_phandle():
                continue
            self.by_phandle[wrapped.get_phandle()] = wrapped
            # We only care about interrupt controllers with phandles -
            # if an interrupt controller has no phandle, it isn't used anywhere
            # and so we can safely ignore it.
            if wrapped.has_prop('interrupt-controller') or wrapped.has_prop(
                    'interrupt-map'):
                self.irq_controllers[
                    wrapped.get_phandle()] = create_irq_controller(
                        wrapped, self)

    def get_phandle(self, phandle: int) -> WrappedNode:
        ''' Look up a node by phandle '''
        return self.by_phandle[phandle]

    def get_path(self, path: str) -> WrappedNode:
        ''' Look up a node by path '''
        return self.by_path.get(path, None)

    def get_irq_controller(self, phandle: int) -> IrqController:
        ''' Get an IRQ controller by phandle '''
        return self.irq_controllers[phandle]

    def lookup_alias(self, alias: str) -> str:
        ''' Look up a node by its alias '''
        alias = alias.split(':')[0]
        aliases = self.get_path('/aliases')

        if aliases is None or not aliases.has_prop(alias):
            raise KeyError('Unmatched alias {}'.format(alias))

        prop = aliases.get_prop(alias)
        return prop.strings[0]

    def get_kernel_devices(self) -> List[WrappedNode]:
        ''' Returns a list of devices that are used by the kernel '''
        chosen = self.get_path('/chosen')
        if not chosen.has_prop('seL4,kernel-devices'):
            return []

        ret = []
        paths = chosen.get_prop('seL4,kernel-devices').strings

        for path in paths:
            if path[0] != '/':
                path = self.lookup_alias(path)
            ret.append(self.get_path(path))
        return ret

    def get_boot_cpu(self) -> int:
        ''' Returns phandle of the cpu node specified by the seL4,boot-cpu property '''
        chosen = self.get_path('/chosen')
        if not chosen.has_prop('seL4,boot-cpu'):
            raise KeyError(
                'must specify seL4,boot-cpu in /chosen to get boot cpu')

        prop = chosen.get_prop('seL4,boot-cpu')
        return prop.words[0]

    def visit(self, visitor: Any):
        ''' Walk the tree, calling the given visitor function on each node '''
        self.wrapped_root.visit(visitor)