# Copyright (c) 2016,2019 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Glenn Bergmans

import six
if six.PY3:
    long = int

from m5.ext.pyfdt import pyfdt
import re
import os
from m5.SimObject import SimObject
from m5.util import fatal

class FdtProperty(pyfdt.FdtProperty):
    """Create a property without values."""
    pass

class FdtPropertyWords(pyfdt.FdtPropertyWords):
    """Create a property with word (32-bit unsigned) values."""
    def __init__(self, name, words):
        if type(words) != list:
            words = [words]
        # Make sure all values are ints (use automatic base detection if the
        # type is str)
        words = [long(w, base=0) if type(w) == str else long(w) for w in words]
        super(FdtPropertyWords, self).__init__(name, words)

class FdtPropertyStrings(pyfdt.FdtPropertyStrings):
    """Create a property with string values."""

    def __init__(self, name, strings):
        if type(strings) == str:
            strings = [strings]
        strings = [str(string) for string in strings] # Make all values strings
        super(FdtPropertyStrings, self).__init__(name, strings)

class FdtPropertyBytes(pyfdt.FdtPropertyBytes):
    """Create a property with integer (8-bit signed) values."""

    def __init__(self, name, values):
        if type(values) != list:
            values = [values]
        # Make sure all values are ints (use automatic base detection if the
        # type is str)
        values = [int(v, base=0)
                   if isinstance(v, str) else int(v) for v in values]
        super(FdtPropertyBytes, self).__init__(name, values)

class FdtState(object):
    """Class for maintaining state while recursively generating a flattened
    device tree. The state tracks address, size and CPU address cell sizes, and
    maintains a dictionary of allocated phandles."""

    phandle_counter = 0
    phandles = dict()

    def __init__(self, **kwargs):
        """Instantiate values of this state. The state can only be initialized
        once."""

        self.addr_cells = kwargs.pop('addr_cells', 0)
        self.size_cells = kwargs.pop('size_cells', 0)
        self.cpu_cells = kwargs.pop('cpu_cells', 0)
        self.interrupt_cells = kwargs.pop('interrupt_cells', 0)

    def phandle(self, obj):
        """Return a unique phandle number for a key. The key can be a SimObject
        or any value that is castable to a string. If the phandle doesn't exist
        a new one is created, otherwise the existing one is returned."""

        if isinstance(obj, SimObject):
            key = str(id(obj))
        else:
            try:
                key = str(obj)
            except ValueError:
                raise ValueError('Phandle keys must be castable to str')

        if not key in FdtState.phandles:
            FdtState.phandle_counter += 1

        return FdtState.phandles.setdefault(key, FdtState.phandle_counter)

    def resetPhandles(self):
        FdtState.phandle_counter = 0
        FdtState.phandles = dict()

    def int_to_cells(self, value, cells):
        """Helper function for: generates a list of 32 bit cells from an int,
        used to split up addresses in appropriate 32 bit chunks."""
        value = long(value)

        if (value >> (32 * cells)) != 0:
            fatal("Value %d doesn't fit in %d cells" % (value, cells))

        return [(value >> 32*(x-1)) & 0xFFFFFFFF for x in range(cells, 0, -1)]

    def addrCells(self, addr):
        """Format an integer type according to the address_cells value of this
        state."""
        return self.int_to_cells(addr, self.addr_cells)

    def CPUAddrCells(self, addr):
        """Format an integer type according to the cpu_cells value of this
        state."""
        return self.int_to_cells(addr, self.cpu_cells)

    def sizeCells(self, size):
        """Format an integer type according to the size_cells value of this
        state."""
        return self.int_to_cells(size, self.size_cells)

    def interruptCells(self, interrupt):
        """Format an integer type according to the interrupt_cells value
        of this state."""
        return self.int_to_cells(interrupt, self.interrupt_cells)

    def addrCellsProperty(self):
        """Return an #address-cells property with the value of this state."""
        return FdtPropertyWords("#address-cells", self.addr_cells)

    def sizeCellsProperty(self):
        """Return an #size-cells property with the value of this state."""
        return FdtPropertyWords("#size-cells", self.size_cells)

    def CPUCellsProperty(self):
        """Return an #address-cells property for cpu nodes with the value
        of this state."""
        return FdtPropertyWords("#address-cells", self.cpu_cells)

    def interruptCellsProperty(self):
        """Return an #interrupt-cells property for cpu nodes with the value
        of this state."""
        return FdtPropertyWords("#interrupt-cells", self.interrupt_cells)


class FdtNop(pyfdt.FdtNop):
    """Create an empty node."""
    pass

class FdtNode(pyfdt.FdtNode):
    def __init__(self, name, obj=None):
        """Create a new node and immediately set the phandle property, if obj
        is supplied"""
        super(FdtNode, self).__init__(name)
        if obj != None:
            self.appendPhandle(obj)

    def append(self, subnodes):
        """Change the behavior of the normal append to override if a node with
        the same name already exists or merge if the name exists and is a node
        type. Can also take a list of subnodes, that each get appended."""
        if not hasattr(subnodes, '__iter__'):
            subnodes = [subnodes]

        for subnode in subnodes:
            try:
                if not issubclass(type(subnode), pyfdt.FdtNop):
                    index = self.index(subnode.name)
                    item = self.pop(index)
                else:
                    item = None
            except ValueError:
                item = None

            if isinstance(item,  pyfdt.FdtNode) and \
               isinstance(subnode,  pyfdt.FdtNode):
                item.merge(subnode)
                subnode = item

            super(FdtNode, self).append(subnode)

    def appendList(self, subnode_list):
        """Append all properties/nodes in the iterable."""
        for subnode in subnode_list:
            self.append(subnode)

    def appendCompatible(self, compatible):
        """Append a compatible property with the supplied compatibility
        strings."""
        if isinstance(compatible, str):
            compatible = [compatible]
        self.append(FdtPropertyStrings('compatible', compatible))

    def appendPhandle(self, obj):
        """Append a phandle property to this node with the phandle of the
        supplied object."""
        # Create a bogus state because we only need the Phandle dictionary
        state = FdtState(addr_cells=1, size_cells=1, cpu_cells=1)

        phandle = state.phandle(obj)
        self.append(FdtPropertyWords("phandle", [phandle]))

class Fdt(pyfdt.Fdt):
    def sortNodes(self, node):
        """Move all properties to the beginning and subnodes to the end
        while maintaining the order of the subnodes. DTB files require the
        properties to go before the nodes, but the PyFdt doesn't account for
        defining nodes and properties in a random order."""
        properties = FdtNode(node.name)
        subnodes = FdtNode(node.name)

        while len(node):
            subnode = node.pop(0)
            if issubclass(type(subnode), pyfdt.FdtNode):
                subnode = self.sortNodes(subnode)
                subnodes.append(subnode)
            else:
                properties.append(subnode)

        properties.merge(subnodes)

        return properties

    def add_rootnode(self, rootnode, prenops=None, postnops=None):
        """First sort the device tree, so that properties are before nodes."""
        rootnode = self.sortNodes(rootnode)
        super(Fdt, self).add_rootnode(rootnode, prenops, postnops)

    def writeDtbFile(self, filename):
        """Convert the device tree to DTB and write to a file."""
        filename = os.path.realpath(filename)
        try:
            with open(filename, 'wb') as f:
                f.write(self.to_dtb())
            return filename
        except IOError:
            raise RuntimeError("Failed to open DTB output file")

    def writeDtsFile(self, filename):
        """Convert the device tree to DTS and write to a file."""
        filename = os.path.realpath(filename)
        try:
            with open(filename, 'w') as f:
                f.write(self.to_dts())
            return filename
        except IOError:
            raise RuntimeError("Failed to open DTS output file")
