#!/usr/bin/python
#
# Copyright (C) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier:	GPL-2.0+
#

import copy
from optparse import OptionError, OptionParser
import os
import struct
import sys

# Bring in the patman libraries
our_path = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(our_path, '../patman'))

import fdt
import fdt_select
import fdt_util

# When we see these properties we ignore them - i.e. do not create a structure member
PROP_IGNORE_LIST = [
    '#address-cells',
    '#gpio-cells',
    '#size-cells',
    'compatible',
    'linux,phandle',
    "status",
    'phandle',
    'u-boot,dm-pre-reloc',
    'u-boot,dm-tpl',
    'u-boot,dm-spl',
]

# C type declarations for the tyues we support
TYPE_NAMES = {
    fdt.TYPE_INT: 'fdt32_t',
    fdt.TYPE_BYTE: 'unsigned char',
    fdt.TYPE_STRING: 'const char *',
    fdt.TYPE_BOOL: 'bool',
};

STRUCT_PREFIX = 'dtd_'
VAL_PREFIX = 'dtv_'

def Conv_name_to_c(name):
    """Convert a device-tree name to a C identifier

    Args:
        name:   Name to convert
    Return:
        String containing the C version of this name
    """
    str = name.replace('@', '_at_')
    str = str.replace('-', '_')
    str = str.replace(',', '_')
    str = str.replace('.', '_')
    str = str.replace('/', '__')
    return str

def TabTo(num_tabs, str):
    if len(str) >= num_tabs * 8:
        return str + ' '
    return str + '\t' * (num_tabs - len(str) // 8)

class DtbPlatdata:
    """Provide a means to convert device tree binary data to platform data

    The output of this process is C structures which can be used in space-
    constrained encvironments where the ~3KB code overhead of device tree
    code is not affordable.

    Properties:
        fdt: Fdt object, referencing the device tree
        _dtb_fname: Filename of the input device tree binary file
        _valid_nodes: A list of Node object with compatible strings
        _options: Command-line options
        _phandle_node: A dict of nodes indexed by phandle number (1, 2...)
        _outfile: The current output file (sys.stdout or a real file)
        _lines: Stashed list of output lines for outputting in the future
        _phandle_node: A dict of Nodes indexed by phandle (an integer)
    """
    def __init__(self, dtb_fname, options):
        self._dtb_fname = dtb_fname
        self._valid_nodes = None
        self._options = options
        self._phandle_node = {}
        self._outfile = None
        self._lines = []

    def SetupOutput(self, fname):
        """Set up the output destination

        Once this is done, future calls to self.Out() will output to this
        file.

        Args:
            fname: Filename to send output to, or '-' for stdout
        """
        if fname == '-':
            self._outfile = sys.stdout
        else:
            self._outfile = open(fname, 'w')

    def Out(self, str):
        """Output a string to the output file

        Args:
            str: String to output
        """
        self._outfile.write(str)

    def Buf(self, str):
        """Buffer up a string to send later

        Args:
            str: String to add to our 'buffer' list
        """
        self._lines.append(str)

    def GetBuf(self):
        """Get the contents of the output buffer, and clear it

        Returns:
            The output buffer, which is then cleared for future use
        """
        lines = self._lines
        self._lines = []
        return lines

    def GetValue(self, type, value):
        """Get a value as a C expression

        For integers this returns a byte-swapped (little-endian) hex string
        For bytes this returns a hex string, e.g. 0x12
        For strings this returns a literal string enclosed in quotes
        For booleans this return 'true'

        Args:
            type: Data type (fdt_util)
            value: Data value, as a string of bytes
        """
        if type == fdt.TYPE_INT:
            return '%#x' % fdt_util.fdt32_to_cpu(value)
        elif type == fdt.TYPE_BYTE:
            return '%#x' % ord(value[0])
        elif type == fdt.TYPE_STRING:
            return '"%s"' % value
        elif type == fdt.TYPE_BOOL:
            return 'true'

    def GetCompatName(self, node):
        """Get a node's first compatible string as a C identifier

        Args:
            node: Node object to check
        Return:
            C identifier for the first compatible string
        """
        compat = node.props['compatible'].value
        if type(compat) == list:
            compat = compat[0]
        return Conv_name_to_c(compat)

    def ScanDtb(self):
        """Scan the device tree to obtain a tree of notes and properties

        Once this is done, self.fdt.GetRoot() can be called to obtain the
        device tree root node, and progress from there.
        """
        self.fdt = fdt_select.FdtScan(self._dtb_fname)

    def ScanNode(self, root):
        for node in root.subnodes:
            if 'compatible' in node.props:
                status = node.props.get('status')
                if (not options.include_disabled and not status or
                    status.value != 'disabled'):
                    self._valid_nodes.append(node)
                    phandle_prop = node.props.get('phandle')
                    if phandle_prop:
                        phandle = phandle_prop.GetPhandle()
                        self._phandle_node[phandle] = node

            # recurse to handle any subnodes
            self.ScanNode(node);

    def ScanTree(self):
        """Scan the device tree for useful information

        This fills in the following properties:
            _phandle_node: A dict of Nodes indexed by phandle (an integer)
            _valid_nodes: A list of nodes we wish to consider include in the
                platform data
        """
        self._phandle_node = {}
        self._valid_nodes = []
        return self.ScanNode(self.fdt.GetRoot());

        for node in self.fdt.GetRoot().subnodes:
            if 'compatible' in node.props:
                status = node.props.get('status')
                if (not options.include_disabled and not status or
                    status.value != 'disabled'):
                    node_list.append(node)
                    phandle_prop = node.props.get('phandle')
                    if phandle_prop:
                        phandle = phandle_prop.GetPhandle()
                        self._phandle_node[phandle] = node

        self._valid_nodes = node_list

    def IsPhandle(self, prop):
        """Check if a node contains phandles

        We have no reliable way of detecting whether a node uses a phandle
        or not. As an interim measure, use a list of known property names.

        Args:
            prop: Prop object to check
        Return:
            True if the object value contains phandles, else False
        """
        if prop.name in ['clocks']:
            return True
        return False

    def ScanStructs(self):
        """Scan the device tree building up the C structures we will use.

        Build a dict keyed by C struct name containing a dict of Prop
        object for each struct field (keyed by property name). Where the
        same struct appears multiple times, try to use the 'widest'
        property, i.e. the one with a type which can express all others.

        Once the widest property is determined, all other properties are
        updated to match that width.
        """
        structs = {}
        for node in self._valid_nodes:
            node_name = self.GetCompatName(node)
            fields = {}

            # Get a list of all the valid properties in this node.
            for name, prop in node.props.items():
                if name not in PROP_IGNORE_LIST and name[0] != '#':
                    fields[name] = copy.deepcopy(prop)

            # If we've seen this node_name before, update the existing struct.
            if node_name in structs:
                struct = structs[node_name]
                for name, prop in fields.items():
                    oldprop = struct.get(name)
                    if oldprop:
                        oldprop.Widen(prop)
                    else:
                        struct[name] = prop

            # Otherwise store this as a new struct.
            else:
                structs[node_name] = fields

        upto = 0
        for node in self._valid_nodes:
            node_name = self.GetCompatName(node)
            struct = structs[node_name]
            for name, prop in node.props.items():
                if name not in PROP_IGNORE_LIST and name[0] != '#':
                    prop.Widen(struct[name])
            upto += 1
        return structs

    def ScanPhandles(self):
        """Figure out what phandles each node uses

        We need to be careful when outputing nodes that use phandles since
        they must come after the declaration of the phandles in the C file.
        Otherwise we get a compiler error since the phandle struct is not yet
        declared.

        This function adds to each node a list of phandle nodes that the node
        depends on. This allows us to output things in the right order.
        """
        for node in self._valid_nodes:
            node.phandles = set()
            for pname, prop in node.props.items():
                if pname in PROP_IGNORE_LIST or pname[0] == '#':
                    continue
                if type(prop.value) == list:
                    if self.IsPhandle(prop):
                        # Process the list as pairs of (phandle, id)
                        it = iter(prop.value)
                        for phandle_cell, id_cell in zip(it, it):
                            phandle = fdt_util.fdt32_to_cpu(phandle_cell)
                            id = fdt_util.fdt32_to_cpu(id_cell)
                            target_node = self._phandle_node[phandle]
                            node.phandles.add(target_node)


    def GenerateStructs(self, structs):
        """Generate struct defintions for the platform data

        This writes out the body of a header file consisting of structure
        definitions for node in self._valid_nodes. See the documentation in
        README.of-plat for more information.
        """
        self.Out('#include <stdbool.h>\n')
        self.Out('#include <libfdt.h>\n')

        # Output the struct definition
        for name in sorted(structs):
            self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name));
            for pname in sorted(structs[name]):
                prop = structs[name][pname]
                if self.IsPhandle(prop):
                    # For phandles, include a reference to the target
                    self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'),
                                             Conv_name_to_c(prop.name),
                                             len(prop.value) / 2))
                else:
                    ptype = TYPE_NAMES[prop.type]
                    self.Out('\t%s%s' % (TabTo(2, ptype),
                                         Conv_name_to_c(prop.name)))
                    if type(prop.value) == list:
                        self.Out('[%d]' % len(prop.value))
                self.Out(';\n')
            self.Out('};\n')

    def OutputNode(self, node):
        """Output the C code for a node

        Args:
            node: node to output
        """
        struct_name = self.GetCompatName(node)
        var_name = Conv_name_to_c(node.name)
        self.Buf('static struct %s%s %s%s = {\n' %
            (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
        for pname, prop in node.props.items():
            if pname in PROP_IGNORE_LIST or pname[0] == '#':
                continue
            ptype = TYPE_NAMES[prop.type]
            member_name = Conv_name_to_c(prop.name)
            self.Buf('\t%s= ' % TabTo(3, '.' + member_name))

            # Special handling for lists
            if type(prop.value) == list:
                self.Buf('{')
                vals = []
                # For phandles, output a reference to the platform data
                # of the target node.
                if self.IsPhandle(prop):
                    # Process the list as pairs of (phandle, id)
                    it = iter(prop.value)
                    for phandle_cell, id_cell in zip(it, it):
                        phandle = fdt_util.fdt32_to_cpu(phandle_cell)
                        id = fdt_util.fdt32_to_cpu(id_cell)
                        target_node = self._phandle_node[phandle]
                        name = Conv_name_to_c(target_node.name)
                        vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id))
                else:
                    for val in prop.value:
                        vals.append(self.GetValue(prop.type, val))
                self.Buf(', '.join(vals))
                self.Buf('}')
            else:
                self.Buf(self.GetValue(prop.type, prop.value))
            self.Buf(',\n')
        self.Buf('};\n')

        # Add a device declaration
        self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
        self.Buf('\t.name\t\t= "%s",\n' % struct_name)
        self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
        self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' %
                    (VAL_PREFIX, var_name))
        self.Buf('};\n')
        self.Buf('\n')

        self.Out(''.join(self.GetBuf()))

    def GenerateTables(self):
        """Generate device defintions for the platform data

        This writes out C platform data initialisation data and
        U_BOOT_DEVICE() declarations for each valid node. See the
        documentation in README.of-plat for more information.
        """
        self.Out('#include <common.h>\n')
        self.Out('#include <dm.h>\n')
        self.Out('#include <dt-structs.h>\n')
        self.Out('\n')
        nodes_to_output = list(self._valid_nodes)

        # Keep outputing nodes until there is none left
        while nodes_to_output:
            node = nodes_to_output[0]
            # Output all the node's dependencies first
            for req_node in node.phandles:
                if req_node in nodes_to_output:
                    self.OutputNode(req_node)
                    nodes_to_output.remove(req_node)
            self.OutputNode(node)
            nodes_to_output.remove(node)


if __name__ != "__main__":
    pass

parser = OptionParser()
parser.add_option('-d', '--dtb-file', action='store',
                  help='Specify the .dtb input file')
parser.add_option('--include-disabled', action='store_true',
                  help='Include disabled nodes')
parser.add_option('-o', '--output', action='store', default='-',
                  help='Select output filename')
(options, args) = parser.parse_args()

if not args:
    raise ValueError('Please specify a command: struct, platdata')

plat = DtbPlatdata(options.dtb_file, options)
plat.ScanDtb()
plat.ScanTree()
plat.SetupOutput(options.output)
structs = plat.ScanStructs()
plat.ScanPhandles()

for cmd in args[0].split(','):
    if cmd == 'struct':
        plat.GenerateStructs(structs)
    elif cmd == 'platdata':
        plat.GenerateTables()
    else:
        raise ValueError("Unknown command '%s': (use: struct, platdata)" % cmd)
