#!/usr/bin/env python3
#
# Copyright (c) 2017 Intel Corporation
# Copyright (c) 2020 Nordic Semiconductor NA
#
# SPDX-License-Identifier: Apache-2.0
"""Translate generic handles into ones optimized for the application.

Immutable device data includes information about dependencies,
e.g. that a particular sensor is controlled through a specific I2C bus
and that it signals event on a pin on a specific GPIO controller.
This information is encoded in the first-pass binary using identifiers
derived from the devicetree.  This script extracts those identifiers
and replaces them with ones optimized for use with the devices
actually present.

For example the sensor might have a first-pass handle defined by its
devicetree ordinal 52, with the I2C driver having ordinal 24 and the
GPIO controller ordinal 14.  The runtime ordinal is the index of the
corresponding device in the static devicetree array, which might be 6,
5, and 3, respectively.

The output is a C source file that provides alternative definitions
for the array contents referenced from the immutable device objects.
In the final link these definitions supersede the ones in the
driver-specific object file.
"""

import sys
import argparse
import os
import struct
import pickle
from distutils.version import LooseVersion

import elftools
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection
import elftools.elf.enums

# This is needed to load edt.pickle files.
sys.path.append(os.path.join(os.path.dirname(__file__),
                             'dts', 'python-devicetree', 'src'))
from devicetree import edtlib  # pylint: disable=unused-import

if LooseVersion(elftools.__version__) < LooseVersion('0.24'):
    sys.exit("pyelftools is out of date, need version 0.24 or later")

scr = os.path.basename(sys.argv[0])

def debug(text):
    if not args.verbose:
        return
    sys.stdout.write(scr + ": " + text + "\n")

def parse_args():
    global args

    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument("-k", "--kernel", required=True,
                        help="Input zephyr ELF binary")
    parser.add_argument("-o", "--output-source", required=True,
            help="Output source file")

    parser.add_argument("-v", "--verbose", action="store_true",
                        help="Print extra debugging information")

    parser.add_argument("-z", "--zephyr-base",
                        help="Path to current Zephyr base. If this argument \
                        is not provided the environment will be checked for \
                        the ZEPHYR_BASE environment variable.")

    parser.add_argument("-s", "--start-symbol", required=True,
                        help="Symbol name of the section which contains the \
                        devices. The symbol name must point to the first \
                        device in that section.")

    args = parser.parse_args()
    if "VERBOSE" in os.environ:
        args.verbose = 1

    ZEPHYR_BASE = args.zephyr_base or os.getenv("ZEPHYR_BASE")

    if ZEPHYR_BASE is None:
        sys.exit("-z / --zephyr-base not provided. Please provide "
                 "--zephyr-base or set ZEPHYR_BASE in environment")

    sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/dts"))


def symbol_data(elf, sym):
    addr = sym.entry.st_value
    len = sym.entry.st_size
    for section in elf.iter_sections():
        start = section['sh_addr']
        end = start + section['sh_size']

        if (start <= addr) and (addr + len) <= end:
            offset = addr - section['sh_addr']
            return bytes(section.data()[offset:offset + len])

def symbol_handle_data(elf, sym):
    data = symbol_data(elf, sym)
    if data:
        format = "<" if elf.little_endian else ">"
        format += "%uh" % (len(data) / 2)
        return struct.unpack(format, data)

# These match the corresponding constants in <device.h>
DEVICE_HANDLE_SEP = -32768
DEVICE_HANDLE_ENDS = 32767
def handle_name(hdl):
    if hdl == DEVICE_HANDLE_SEP:
        return "DEVICE_HANDLE_SEP"
    if hdl == DEVICE_HANDLE_ENDS:
        return "DEVICE_HANDLE_ENDS"
    if hdl == 0:
        return "DEVICE_HANDLE_NULL"
    return str(int(hdl))

class Device:
    """
    Represents information about a device object and its references to other objects.
    """
    def __init__(self, elf, ld_constants, sym, addr):
        self.elf = elf
        self.ld_constants = ld_constants
        self.sym = sym
        self.addr = addr
        # Point to the handles instance associated with the device;
        # assigned by correlating the device struct handles pointer
        # value with the addr of a Handles instance.
        self.__handles = None

    @property
    def obj_handles(self):
        """
        Returns the value from the device struct handles field, pointing to the
        array of handles for devices this device depends on.
        """
        if self.__handles is None:
            data = symbol_data(self.elf, self.sym)
            format = "<" if self.elf.little_endian else ">"
            if self.elf.elfclass == 32:
                format += "I"
                size = 4
            else:
                format += "Q"
                size = 8
            offset = self.ld_constants["_DEVICE_STRUCT_HANDLES_OFFSET"]
            self.__handles = struct.unpack(format, data[offset:offset + size])[0]
        return self.__handles

class Handles:
    def __init__(self, sym, addr, handles, node):
        self.sym = sym
        self.addr = addr
        self.handles = handles
        self.node = node
        self.dep_ord = None
        self.dev_deps = None
        self.ext_deps = None

def main():
    parse_args()

    assert args.kernel, "--kernel ELF required to extract data"
    elf = ELFFile(open(args.kernel, "rb"))

    edtser = os.path.join(os.path.split(args.kernel)[0], "edt.pickle")
    with open(edtser, 'rb') as f:
        edt = pickle.load(f)

    devices = []
    handles = []
    # Leading _ are stripped from the stored constant key

    want_constants = set([args.start_symbol,
                          "_DEVICE_STRUCT_SIZEOF",
                          "_DEVICE_STRUCT_HANDLES_OFFSET"])
    ld_constants = dict()

    for section in elf.iter_sections():
        if isinstance(section, SymbolTableSection):
            for sym in section.iter_symbols():
                if sym.name in want_constants:
                    ld_constants[sym.name] = sym.entry.st_value
                    continue
                if sym.entry.st_info.type != 'STT_OBJECT':
                    continue
                if sym.name.startswith("__device"):
                    addr = sym.entry.st_value
                    if sym.name.startswith("__device_"):
                        devices.append(Device(elf, ld_constants, sym, addr))
                        debug("device %s" % (sym.name,))
                    elif sym.name.startswith("__devicehdl_"):
                        hdls = symbol_handle_data(elf, sym)

                        # The first element of the hdls array is the dependency
                        # ordinal of the device, which identifies the devicetree
                        # node.
                        node = edt.dep_ord2node[hdls[0]] if (hdls and hdls[0] != 0) else None
                        handles.append(Handles(sym, addr, hdls, node))
                        debug("handles %s %d %s" % (sym.name, hdls[0] if hdls else -1, node))

    assert len(want_constants) == len(ld_constants), "linker map data incomplete"

    devices = sorted(devices, key = lambda k: k.sym.entry.st_value)

    device_start_addr = ld_constants[args.start_symbol]
    device_size = 0

    assert len(devices) == len(handles), 'mismatch devices and handles'

    used_nodes = set()
    for handle in handles:
        handle.device = None
        for device in devices:
            if handle.addr == device.obj_handles:
                handle.device = device
                break
        device = handle.device
        assert device, 'no device for %s' % (handle.sym.name,)

        device.handle = handle

        if device_size == 0:
            device_size = device.sym.entry.st_size

        # The device handle is one plus the ordinal of this device in
        # the device table.
        device.dev_handle = 1 + int((device.sym.entry.st_value - device_start_addr) / device_size)
        debug("%s dev ordinal %d" % (device.sym.name, device.dev_handle))

        n = handle.node
        if n is not None:
            debug("%s dev ordinal %d\n\t%s" % (n.path, device.dev_handle, ' ; '.join(str(_) for _ in handle.handles)))
            used_nodes.add(n)
            n.__device = device
        else:
            debug("orphan %d" % (device.dev_handle,))
        hv = handle.handles
        hvi = 1
        handle.dev_deps = []
        handle.ext_deps = []
        handle.dev_sups = []
        hdls = handle.dev_deps
        while hvi < len(hv):
            h = hv[hvi]
            if h == DEVICE_HANDLE_ENDS:
                break
            if h == DEVICE_HANDLE_SEP:
                if hdls == handle.dev_deps:
                    hdls = handle.ext_deps
                else:
                    hdls = handle.dev_sups
            else:
                hdls.append(h)
                n = edt
            hvi += 1

    # Compute the dependency graph induced from the full graph restricted to the
    # the nodes that exist in the application.  Note that the edges in the
    # induced graph correspond to paths in the full graph.
    root = edt.dep_ord2node[0]
    assert root not in used_nodes

    for sn in used_nodes:
        # Where we're storing the final set of nodes: these are all used
        sn.__depends = set()
        sn.__supports = set()

        deps = set(sn.depends_on)
        debug("\nNode: %s\nOrig deps:\n\t%s" % (sn.path, "\n\t".join([dn.path for dn in deps])))
        while len(deps) > 0:
            dn = deps.pop()
            if dn in used_nodes:
                # this is used
                sn.__depends.add(dn)
            elif dn != root:
                # forward the dependency up one level
                for ddn in dn.depends_on:
                    deps.add(ddn)
        debug("Final deps:\n\t%s\n" % ("\n\t".join([ _dn.path for _dn in sn.__depends])))

        sups = set(sn.required_by)
        debug("\nOrig sups:\n\t%s" % ("\n\t".join([dn.path for dn in sups])))
        while len(sups) > 0:
            dn = sups.pop()
            if dn in used_nodes:
                # this is used
                sn.__supports.add(dn)
        debug("\nFinal sups:\n\t%s" % ("\n\t".join([dn.path for dn in sn.__supports])))

    with open(args.output_source, "w") as fp:
        fp.write('#include <device.h>\n')
        fp.write('#include <toolchain.h>\n')

        for dev in devices:
            hs = dev.handle
            assert hs, "no hs for %s" % (dev.sym.name,)
            dep_paths = []
            ext_paths = []
            sup_paths = []
            hdls = []

            sn = hs.node
            if sn:
                hdls.extend(dn.__device.dev_handle for dn in sn.__depends)
                for dn in sn.depends_on:
                    if dn in sn.__depends:
                        dep_paths.append(dn.path)
                    else:
                        dep_paths.append('(%s)' % dn.path)

            # Force separator to signal start of injected dependencies
            hdls.append(DEVICE_HANDLE_SEP)
            if len(hs.ext_deps) > 0:
                # TODO: map these to something smaller?
                ext_paths.extend(map(str, hs.ext_deps))
                hdls.extend(hs.ext_deps)

            # Force separator to signal start of supported devices
            hdls.append(DEVICE_HANDLE_SEP)
            if len(hs.dev_sups) > 0:
                for dn in sn.required_by:
                    if dn in sn.__supports:
                        sup_paths.append(dn.path)
                    else:
                        sup_paths.append('(%s)' % dn.path)
                hdls.extend(dn.__device.dev_handle for dn in sn.__supports)

            # When CONFIG_USERSPACE is enabled the pre-built elf is
            # also used to get hashes that identify kernel objects by
            # address. We can't allow the size of any object in the
            # final elf to change. We also must make sure at least one
            # DEVICE_HANDLE_ENDS is inserted.
            assert len(hdls) < len(hs.handles), "%s no DEVICE_HANDLE_ENDS inserted" % (dev.sym.name,)
            while len(hdls) < len(hs.handles):
                hdls.append(DEVICE_HANDLE_ENDS)
            assert len(hdls) == len(hs.handles), "%s handle overflow" % (dev.sym.name,)

            lines = [
                '',
                '/* %d : %s:' % (dev.dev_handle, (sn and sn.path) or "sysinit"),
            ]

            if len(dep_paths) > 0:
                lines.append(' * Direct Dependencies:')
                lines.append(' *   - %s' % ('\n *   - '.join(dep_paths)))
            if len(ext_paths) > 0:
                lines.append(' * Injected Dependencies:')
                lines.append(' *   - %s' % ('\n *   - '.join(ext_paths)))
            if len(sup_paths) > 0:
                lines.append(' * Supported:')
                lines.append(' *   - %s' % ('\n *   - '.join(sup_paths)))

            lines.extend([
                ' */',
                'const device_handle_t __aligned(2) __attribute__((__section__(".__device_handles_pass2")))',
                '%s[] = { %s };' % (hs.sym.name, ', '.join([handle_name(_h) for _h in hdls])),
                '',
            ])

            fp.write('\n'.join(lines))

if __name__ == "__main__":
    main()
