112468Sglenn.bergmans@arm.com# -*- coding: utf-8 -*-
212468Sglenn.bergmans@arm.com"""
312468Sglenn.bergmans@arm.comDevice Tree Blob Parser
412468Sglenn.bergmans@arm.com
512468Sglenn.bergmans@arm.com   Copyright 2014  Neil 'superna' Armstrong <superna9999@gmail.com>
612468Sglenn.bergmans@arm.com
712468Sglenn.bergmans@arm.com   Licensed under the Apache License, Version 2.0 (the "License");
812468Sglenn.bergmans@arm.com   you may not use this file except in compliance with the License.
912468Sglenn.bergmans@arm.com   You may obtain a copy of the License at
1012468Sglenn.bergmans@arm.com
1112468Sglenn.bergmans@arm.com     http://www.apache.org/licenses/LICENSE-2.0
1212468Sglenn.bergmans@arm.com
1312468Sglenn.bergmans@arm.com   Unless required by applicable law or agreed to in writing, software
1412468Sglenn.bergmans@arm.com   distributed under the License is distributed on an "AS IS" BASIS,
1512468Sglenn.bergmans@arm.com   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1612468Sglenn.bergmans@arm.com   See the License for the specific language governing permissions and
1712468Sglenn.bergmans@arm.com   limitations under the License.
1812468Sglenn.bergmans@arm.com
1912468Sglenn.bergmans@arm.com@author: Neil 'superna' Armstrong <superna9999@gmail.com>
2012468Sglenn.bergmans@arm.com"""
2112468Sglenn.bergmans@arm.com
2213714Sandreas.sandberg@arm.comfrom __future__ import print_function
2313714Sandreas.sandberg@arm.comfrom __future__ import absolute_import
2413714Sandreas.sandberg@arm.com
2512468Sglenn.bergmans@arm.comimport string
2612468Sglenn.bergmans@arm.comimport os
2712468Sglenn.bergmans@arm.comimport json
2812468Sglenn.bergmans@arm.comfrom copy import deepcopy, copy
2912468Sglenn.bergmans@arm.comfrom struct import Struct, unpack, pack
3012468Sglenn.bergmans@arm.com
3112468Sglenn.bergmans@arm.comFDT_MAGIC = 0xd00dfeed
3212468Sglenn.bergmans@arm.comFDT_BEGIN_NODE = 0x1
3312468Sglenn.bergmans@arm.comFDT_END_NODE = 0x2
3412468Sglenn.bergmans@arm.comFDT_PROP = 0x3
3512468Sglenn.bergmans@arm.comFDT_NOP = 0x4
3612468Sglenn.bergmans@arm.comFDT_END = 0x9
3712468Sglenn.bergmans@arm.com
3812468Sglenn.bergmans@arm.comINDENT = ' ' * 4
3912468Sglenn.bergmans@arm.com
4012468Sglenn.bergmans@arm.comFDT_MAX_VERSION = 17
4112468Sglenn.bergmans@arm.com
4212468Sglenn.bergmans@arm.com
4312468Sglenn.bergmans@arm.comclass FdtProperty(object):
4412468Sglenn.bergmans@arm.com    """ Represents an empty property"""
4512468Sglenn.bergmans@arm.com
4612468Sglenn.bergmans@arm.com    @staticmethod
4712468Sglenn.bergmans@arm.com    def __validate_dt_name(name):
4812468Sglenn.bergmans@arm.com        """Checks the name validity"""
4912468Sglenn.bergmans@arm.com        return not any([True for char in name
5012468Sglenn.bergmans@arm.com                        if char not in string.printable])
5112468Sglenn.bergmans@arm.com
5212468Sglenn.bergmans@arm.com    def __init__(self, name):
5312468Sglenn.bergmans@arm.com        """Init with name"""
5412468Sglenn.bergmans@arm.com        self.name = name
5512468Sglenn.bergmans@arm.com        if not FdtProperty.__validate_dt_name(self.name):
5612468Sglenn.bergmans@arm.com            raise Exception("Invalid name '%s'" % self.name)
5712468Sglenn.bergmans@arm.com
5812468Sglenn.bergmans@arm.com    def get_name(self):
5912468Sglenn.bergmans@arm.com        """Get property name"""
6012468Sglenn.bergmans@arm.com        return self.name
6112468Sglenn.bergmans@arm.com
6212468Sglenn.bergmans@arm.com    def __str__(self):
6312468Sglenn.bergmans@arm.com        """String representation"""
6412468Sglenn.bergmans@arm.com        return "Property(%s)" % self.name
6512468Sglenn.bergmans@arm.com
6612468Sglenn.bergmans@arm.com    def dts_represent(self, depth=0):
6712468Sglenn.bergmans@arm.com        """Get dts string representation"""
6812468Sglenn.bergmans@arm.com        return INDENT*depth + self.name + ';'
6912468Sglenn.bergmans@arm.com
7012468Sglenn.bergmans@arm.com    def dtb_represent(self, string_store, pos=0, version=17):
7112468Sglenn.bergmans@arm.com        """Get blob representation"""
7212468Sglenn.bergmans@arm.com        # print "%x:%s" % (pos, self)
7312468Sglenn.bergmans@arm.com        strpos = string_store.find(self.name+'\0')
7412468Sglenn.bergmans@arm.com        if strpos < 0:
7512468Sglenn.bergmans@arm.com            strpos = len(string_store)
7612468Sglenn.bergmans@arm.com            string_store += self.name+'\0'
7712468Sglenn.bergmans@arm.com        pos += 12
7812468Sglenn.bergmans@arm.com        return (pack('>III', FDT_PROP, 0, strpos),
7912468Sglenn.bergmans@arm.com                string_store, pos)
8012468Sglenn.bergmans@arm.com
8112468Sglenn.bergmans@arm.com    def json_represent(self, depth=0):
8212468Sglenn.bergmans@arm.com        """Ouput JSON"""
8312468Sglenn.bergmans@arm.com        return '%s: null' % json.dumps(self.name)
8412468Sglenn.bergmans@arm.com
8512468Sglenn.bergmans@arm.com    def to_raw(self):
8612468Sglenn.bergmans@arm.com        """Return RAW value representation"""
8712468Sglenn.bergmans@arm.com        return ''
8812468Sglenn.bergmans@arm.com
8912468Sglenn.bergmans@arm.com    def __getitem__(self, value):
9012468Sglenn.bergmans@arm.com        """Returns No Items"""
9112468Sglenn.bergmans@arm.com        return None
9212468Sglenn.bergmans@arm.com
9312468Sglenn.bergmans@arm.com    def __ne__(self, node):
9412468Sglenn.bergmans@arm.com        """Check property inequality
9512468Sglenn.bergmans@arm.com        """
9612468Sglenn.bergmans@arm.com        return not self.__eq__(node)
9712468Sglenn.bergmans@arm.com
9812468Sglenn.bergmans@arm.com    def __eq__(self, node):
9912468Sglenn.bergmans@arm.com        """Check node equality
10012468Sglenn.bergmans@arm.com           check properties are the same (same values)
10112468Sglenn.bergmans@arm.com        """
10212468Sglenn.bergmans@arm.com        if not isinstance(node, FdtProperty):
10312468Sglenn.bergmans@arm.com            raise Exception("Invalid object type")
10412468Sglenn.bergmans@arm.com        if self.name != node.get_name():
10512468Sglenn.bergmans@arm.com            return False
10612468Sglenn.bergmans@arm.com        return True
10712468Sglenn.bergmans@arm.com
10812468Sglenn.bergmans@arm.com    @staticmethod
10912468Sglenn.bergmans@arm.com    def __check_prop_strings(value):
11012468Sglenn.bergmans@arm.com        """Check property string validity
11112468Sglenn.bergmans@arm.com           Python version of util_is_printable_string from dtc
11212468Sglenn.bergmans@arm.com        """
11312468Sglenn.bergmans@arm.com        pos = 0
11412468Sglenn.bergmans@arm.com        posi = 0
11512468Sglenn.bergmans@arm.com        end = len(value)
11612468Sglenn.bergmans@arm.com
11712468Sglenn.bergmans@arm.com        if not len(value):
11812468Sglenn.bergmans@arm.com            return None
11912468Sglenn.bergmans@arm.com
12012468Sglenn.bergmans@arm.com        #Needed for python 3 support: If a bytes object is passed,
12112468Sglenn.bergmans@arm.com        #decode it with the ascii codec. If the decoding fails, assume
12212468Sglenn.bergmans@arm.com        #it was not a string object.
12312468Sglenn.bergmans@arm.com        try:
12412468Sglenn.bergmans@arm.com            value = value.decode('ascii')
12512468Sglenn.bergmans@arm.com        except ValueError:
12612468Sglenn.bergmans@arm.com            return None
12712468Sglenn.bergmans@arm.com
12812468Sglenn.bergmans@arm.com        #Test both against string 0 and int 0 because of
12912468Sglenn.bergmans@arm.com        # python2/3 compatibility
13012468Sglenn.bergmans@arm.com        if value[-1] != '\0':
13112468Sglenn.bergmans@arm.com            return None
13212468Sglenn.bergmans@arm.com
13312468Sglenn.bergmans@arm.com        while pos < end:
13412468Sglenn.bergmans@arm.com            posi = pos
13512468Sglenn.bergmans@arm.com            while pos < end and value[pos] != '\0' \
13612468Sglenn.bergmans@arm.com                  and value[pos] in string.printable \
13712468Sglenn.bergmans@arm.com                  and value[pos] not in ('\r', '\n'):
13812468Sglenn.bergmans@arm.com                pos += 1
13912468Sglenn.bergmans@arm.com
14012468Sglenn.bergmans@arm.com            if value[pos] != '\0' or pos == posi:
14112468Sglenn.bergmans@arm.com                return None
14212468Sglenn.bergmans@arm.com            pos += 1
14312468Sglenn.bergmans@arm.com
14412468Sglenn.bergmans@arm.com        return True
14512468Sglenn.bergmans@arm.com
14612468Sglenn.bergmans@arm.com    @staticmethod
14712468Sglenn.bergmans@arm.com    def new_raw_property(name, raw_value):
14812468Sglenn.bergmans@arm.com        """Instantiate property with raw value type"""
14912468Sglenn.bergmans@arm.com        if FdtProperty.__check_prop_strings(raw_value):
15012468Sglenn.bergmans@arm.com            return FdtPropertyStrings.init_raw(name, raw_value)
15112468Sglenn.bergmans@arm.com        elif len(raw_value) and len(raw_value) % 4 == 0:
15212468Sglenn.bergmans@arm.com            return FdtPropertyWords.init_raw(name, raw_value)
15312468Sglenn.bergmans@arm.com        elif len(raw_value) and len(raw_value):
15412468Sglenn.bergmans@arm.com            return FdtPropertyBytes.init_raw(name, raw_value)
15512468Sglenn.bergmans@arm.com        else:
15612468Sglenn.bergmans@arm.com            return FdtProperty(name)
15712468Sglenn.bergmans@arm.com
15812468Sglenn.bergmans@arm.com
15912468Sglenn.bergmans@arm.comclass FdtPropertyStrings(FdtProperty):
16012468Sglenn.bergmans@arm.com    """Property with strings as value"""
16112468Sglenn.bergmans@arm.com
16212468Sglenn.bergmans@arm.com    @classmethod
16312468Sglenn.bergmans@arm.com    def __extract_prop_strings(cls, value):
16412468Sglenn.bergmans@arm.com        """Extract strings from raw_value"""
16512468Sglenn.bergmans@arm.com        return [st for st in \
16612468Sglenn.bergmans@arm.com            value.decode('ascii').split('\0') if len(st)]
16712468Sglenn.bergmans@arm.com
16812468Sglenn.bergmans@arm.com    def __init__(self, name, strings):
16912468Sglenn.bergmans@arm.com        """Init with strings"""
17012468Sglenn.bergmans@arm.com        FdtProperty.__init__(self, name)
17112468Sglenn.bergmans@arm.com        if not strings:
17212468Sglenn.bergmans@arm.com            raise Exception("Invalid strings")
17312468Sglenn.bergmans@arm.com        for stri in strings:
17412468Sglenn.bergmans@arm.com            if len(stri) == 0:
17512468Sglenn.bergmans@arm.com                raise Exception("Invalid strings")
17612468Sglenn.bergmans@arm.com            if any([True for char in stri
17712468Sglenn.bergmans@arm.com                        if char not in string.printable
17812468Sglenn.bergmans@arm.com                           or char in ('\r', '\n')]):
17912468Sglenn.bergmans@arm.com                raise Exception("Invalid chars in strings")
18012468Sglenn.bergmans@arm.com        self.strings = strings
18112468Sglenn.bergmans@arm.com
18212468Sglenn.bergmans@arm.com    @classmethod
18312468Sglenn.bergmans@arm.com    def init_raw(cls, name, raw_value):
18412468Sglenn.bergmans@arm.com        """Init from raw"""
18512468Sglenn.bergmans@arm.com        return cls(name, cls.__extract_prop_strings(raw_value))
18612468Sglenn.bergmans@arm.com
18712468Sglenn.bergmans@arm.com    def dts_represent(self, depth=0):
18812468Sglenn.bergmans@arm.com        """Get dts string representation"""
18912468Sglenn.bergmans@arm.com        return INDENT*depth + self.name + ' = "' + \
19012468Sglenn.bergmans@arm.com            '", "'.join(self.strings) + '";'
19112468Sglenn.bergmans@arm.com
19212468Sglenn.bergmans@arm.com    def dtb_represent(self, string_store, pos=0, version=17):
19312468Sglenn.bergmans@arm.com        """Get blob representation"""
19412468Sglenn.bergmans@arm.com        # print "%x:%s" % (pos, self)
19512468Sglenn.bergmans@arm.com        blob = pack('')
19612468Sglenn.bergmans@arm.com        for chars in self.strings:
19712468Sglenn.bergmans@arm.com            blob += chars.encode('ascii') + pack('b', 0)
19812468Sglenn.bergmans@arm.com        blob_len = len(blob)
19912468Sglenn.bergmans@arm.com        if version < 16 and (pos+12) % 8 != 0:
20012468Sglenn.bergmans@arm.com            blob = pack('b', 0) * (8-((pos+12) % 8)) + blob
20112468Sglenn.bergmans@arm.com        if blob_len % 4:
20212468Sglenn.bergmans@arm.com            blob += pack('b', 0) * (4-(blob_len % 4))
20312468Sglenn.bergmans@arm.com        strpos = string_store.find(self.name+'\0')
20412468Sglenn.bergmans@arm.com        if strpos < 0:
20512468Sglenn.bergmans@arm.com            strpos = len(string_store)
20612468Sglenn.bergmans@arm.com            string_store += self.name+'\0'
20712468Sglenn.bergmans@arm.com        blob = pack('>III', FDT_PROP, blob_len, strpos) + blob
20812468Sglenn.bergmans@arm.com        pos += len(blob)
20912468Sglenn.bergmans@arm.com        return (blob, string_store, pos)
21012468Sglenn.bergmans@arm.com
21112468Sglenn.bergmans@arm.com    def json_represent(self, depth=0):
21212468Sglenn.bergmans@arm.com        """Ouput JSON"""
21312468Sglenn.bergmans@arm.com        result = '%s: ["strings", ' % json.dumps(self.name)
21412468Sglenn.bergmans@arm.com        result += ', '.join([json.dumps(stri) for stri in self.strings])
21512468Sglenn.bergmans@arm.com        result += ']'
21612468Sglenn.bergmans@arm.com        return result
21712468Sglenn.bergmans@arm.com
21812468Sglenn.bergmans@arm.com    def to_raw(self):
21912468Sglenn.bergmans@arm.com        """Return RAW value representation"""
22012468Sglenn.bergmans@arm.com        return ''.join([chars+'\0' for chars in self.strings])
22112468Sglenn.bergmans@arm.com
22212468Sglenn.bergmans@arm.com    def __str__(self):
22312468Sglenn.bergmans@arm.com        """String representation"""
22412468Sglenn.bergmans@arm.com        return "Property(%s,Strings:%s)" % (self.name, self.strings)
22512468Sglenn.bergmans@arm.com
22612468Sglenn.bergmans@arm.com    def __getitem__(self, index):
22712468Sglenn.bergmans@arm.com        """Get strings, returns a string"""
22812468Sglenn.bergmans@arm.com        return self.strings[index]
22912468Sglenn.bergmans@arm.com
23012468Sglenn.bergmans@arm.com    def __len__(self):
23112468Sglenn.bergmans@arm.com        """Get strings count"""
23212468Sglenn.bergmans@arm.com        return len(self.strings)
23312468Sglenn.bergmans@arm.com
23412468Sglenn.bergmans@arm.com    def __eq__(self, node):
23512468Sglenn.bergmans@arm.com        """Check node equality
23612468Sglenn.bergmans@arm.com           check properties are the same (same values)
23712468Sglenn.bergmans@arm.com        """
23812468Sglenn.bergmans@arm.com        if not FdtProperty.__eq__(self, node):
23912468Sglenn.bergmans@arm.com            return False
24012468Sglenn.bergmans@arm.com        if self.__len__() != len(node):
24112468Sglenn.bergmans@arm.com            return False
24212468Sglenn.bergmans@arm.com        for index in range(self.__len__()):
24312468Sglenn.bergmans@arm.com            if self.strings[index] != node[index]:
24412468Sglenn.bergmans@arm.com                return False
24512468Sglenn.bergmans@arm.com        return True
24612468Sglenn.bergmans@arm.com
24712468Sglenn.bergmans@arm.comclass FdtPropertyWords(FdtProperty):
24812468Sglenn.bergmans@arm.com    """Property with words as value"""
24912468Sglenn.bergmans@arm.com
25012468Sglenn.bergmans@arm.com    def __init__(self, name, words):
25112468Sglenn.bergmans@arm.com        """Init with words"""
25212468Sglenn.bergmans@arm.com        FdtProperty.__init__(self, name)
25312468Sglenn.bergmans@arm.com        for word in words:
25412468Sglenn.bergmans@arm.com            if not 0 <= word <= 4294967295:
25512468Sglenn.bergmans@arm.com                raise Exception(("Invalid word value %d, requires " +
25612468Sglenn.bergmans@arm.com                                 "0 <= number <= 4294967295") % word)
25712468Sglenn.bergmans@arm.com        if not len(words):
25812468Sglenn.bergmans@arm.com            raise Exception("Invalid Words")
25912468Sglenn.bergmans@arm.com        self.words = words
26012468Sglenn.bergmans@arm.com
26112468Sglenn.bergmans@arm.com    @classmethod
26212468Sglenn.bergmans@arm.com    def init_raw(cls, name, raw_value):
26312468Sglenn.bergmans@arm.com        """Init from raw"""
26412468Sglenn.bergmans@arm.com        if len(raw_value) % 4 == 0:
26512468Sglenn.bergmans@arm.com            words = [unpack(">I", raw_value[i:i+4])[0]
26612468Sglenn.bergmans@arm.com                     for i in range(0, len(raw_value), 4)]
26712468Sglenn.bergmans@arm.com            return cls(name, words)
26812468Sglenn.bergmans@arm.com        else:
26912468Sglenn.bergmans@arm.com            raise Exception("Invalid raw Words")
27012468Sglenn.bergmans@arm.com
27112468Sglenn.bergmans@arm.com    def dts_represent(self, depth=0):
27212468Sglenn.bergmans@arm.com        """Get dts string representation"""
27312468Sglenn.bergmans@arm.com        return INDENT*depth + self.name + ' = <' + \
27412468Sglenn.bergmans@arm.com               ' '.join(["0x%08x" % word for word in self.words]) + ">;"
27512468Sglenn.bergmans@arm.com
27612468Sglenn.bergmans@arm.com    def dtb_represent(self, string_store, pos=0, version=17):
27712468Sglenn.bergmans@arm.com        """Get blob representation"""
27812468Sglenn.bergmans@arm.com        # # print "%x:%s" % (pos, self)
27912468Sglenn.bergmans@arm.com        strpos = string_store.find(self.name+'\0')
28012468Sglenn.bergmans@arm.com        if strpos < 0:
28112468Sglenn.bergmans@arm.com            strpos = len(string_store)
28212468Sglenn.bergmans@arm.com            string_store += self.name+'\0'
28312468Sglenn.bergmans@arm.com        blob = pack('>III', FDT_PROP, len(self.words)*4, strpos) + \
28412468Sglenn.bergmans@arm.com                pack('').join([pack('>I', word) for word in self.words])
28512468Sglenn.bergmans@arm.com        pos += len(blob)
28612468Sglenn.bergmans@arm.com        return (blob, string_store, pos)
28712468Sglenn.bergmans@arm.com
28812468Sglenn.bergmans@arm.com    def json_represent(self, depth=0):
28912468Sglenn.bergmans@arm.com        """Ouput JSON"""
29012468Sglenn.bergmans@arm.com        result = '%s: ["words", "' % json.dumps(self.name)
29112468Sglenn.bergmans@arm.com        result += '", "'.join(["0x%08x" % word for word in self.words])
29212468Sglenn.bergmans@arm.com        result += '"]'
29312468Sglenn.bergmans@arm.com        return result
29412468Sglenn.bergmans@arm.com
29512468Sglenn.bergmans@arm.com    def to_raw(self):
29612468Sglenn.bergmans@arm.com        """Return RAW value representation"""
29712468Sglenn.bergmans@arm.com        return ''.join([pack('>I', word) for word in self.words])
29812468Sglenn.bergmans@arm.com
29912468Sglenn.bergmans@arm.com    def __str__(self):
30012468Sglenn.bergmans@arm.com        """String representation"""
30112468Sglenn.bergmans@arm.com        return "Property(%s,Words:%s)" % (self.name, self.words)
30212468Sglenn.bergmans@arm.com
30312468Sglenn.bergmans@arm.com    def __getitem__(self, index):
30412468Sglenn.bergmans@arm.com        """Get words, returns a word integer"""
30512468Sglenn.bergmans@arm.com        return self.words[index]
30612468Sglenn.bergmans@arm.com
30712468Sglenn.bergmans@arm.com    def __len__(self):
30812468Sglenn.bergmans@arm.com        """Get words count"""
30912468Sglenn.bergmans@arm.com        return len(self.words)
31012468Sglenn.bergmans@arm.com
31112468Sglenn.bergmans@arm.com    def __eq__(self, node):
31212468Sglenn.bergmans@arm.com        """Check node equality
31312468Sglenn.bergmans@arm.com           check properties are the same (same values)
31412468Sglenn.bergmans@arm.com        """
31512468Sglenn.bergmans@arm.com        if not FdtProperty.__eq__(self, node):
31612468Sglenn.bergmans@arm.com            return False
31712468Sglenn.bergmans@arm.com        if self.__len__() != len(node):
31812468Sglenn.bergmans@arm.com            return False
31912468Sglenn.bergmans@arm.com        for index in range(self.__len__()):
32012468Sglenn.bergmans@arm.com            if self.words[index] != node[index]:
32112468Sglenn.bergmans@arm.com                return False
32212468Sglenn.bergmans@arm.com        return True
32312468Sglenn.bergmans@arm.com
32412468Sglenn.bergmans@arm.com
32512468Sglenn.bergmans@arm.comclass FdtPropertyBytes(FdtProperty):
32612468Sglenn.bergmans@arm.com    """Property with signed bytes as value"""
32712468Sglenn.bergmans@arm.com
32812468Sglenn.bergmans@arm.com    def __init__(self, name, bytez):
32912468Sglenn.bergmans@arm.com        """Init with bytes"""
33012468Sglenn.bergmans@arm.com        FdtProperty.__init__(self, name)
33112468Sglenn.bergmans@arm.com        for byte in bytez:
33212468Sglenn.bergmans@arm.com            if not -128 <= byte <= 127:
33312468Sglenn.bergmans@arm.com                raise Exception(("Invalid value for byte %d, " +
33412468Sglenn.bergmans@arm.com                                 "requires -128 <= number <= 127") % byte)
33512468Sglenn.bergmans@arm.com        if not bytez:
33612468Sglenn.bergmans@arm.com            raise Exception("Invalid Bytes")
33712468Sglenn.bergmans@arm.com        self.bytes = bytez
33812468Sglenn.bergmans@arm.com
33912468Sglenn.bergmans@arm.com    @classmethod
34012468Sglenn.bergmans@arm.com    def init_raw(cls, name, raw_value):
34112468Sglenn.bergmans@arm.com        """Init from raw"""
34212468Sglenn.bergmans@arm.com        return cls(name, unpack('b' * len(raw_value), raw_value))
34312468Sglenn.bergmans@arm.com
34412468Sglenn.bergmans@arm.com    def dts_represent(self, depth=0):
34512468Sglenn.bergmans@arm.com        """Get dts string representation"""
34612468Sglenn.bergmans@arm.com        return INDENT*depth + self.name + ' = [' + \
34712468Sglenn.bergmans@arm.com            ' '.join(["%02x" % (byte & int('ffffffff',16))
34812468Sglenn.bergmans@arm.com                      for byte in self.bytes]) + "];"
34912468Sglenn.bergmans@arm.com
35012468Sglenn.bergmans@arm.com    def dtb_represent(self, string_store, pos=0, version=17):
35112468Sglenn.bergmans@arm.com        """Get blob representation"""
35212468Sglenn.bergmans@arm.com        # print "%x:%s" % (pos, self)
35312468Sglenn.bergmans@arm.com        strpos = string_store.find(self.name+'\0')
35412468Sglenn.bergmans@arm.com        if strpos < 0:
35512468Sglenn.bergmans@arm.com            strpos = len(string_store)
35612468Sglenn.bergmans@arm.com            string_store += self.name+'\0'
35712468Sglenn.bergmans@arm.com        blob = pack('>III', FDT_PROP, len(self.bytes), strpos)
35812468Sglenn.bergmans@arm.com        blob += pack('').join([pack('>b', byte) for byte in self.bytes])
35912468Sglenn.bergmans@arm.com        if len(blob) % 4:
36012468Sglenn.bergmans@arm.com            blob += pack('b', 0) * (4-(len(blob) % 4))
36112468Sglenn.bergmans@arm.com        pos += len(blob)
36212468Sglenn.bergmans@arm.com        return (blob, string_store, pos)
36312468Sglenn.bergmans@arm.com
36412468Sglenn.bergmans@arm.com    def json_represent(self, depth=0):
36512468Sglenn.bergmans@arm.com        """Ouput JSON"""
36612468Sglenn.bergmans@arm.com        result = '%s: ["bytes", "' % json.dumps(self.name)
36712468Sglenn.bergmans@arm.com        result += '", "'.join(["%02x" % byte
36812468Sglenn.bergmans@arm.com                                for byte in self.bytes])
36912468Sglenn.bergmans@arm.com        result += '"]'
37012468Sglenn.bergmans@arm.com        return result
37112468Sglenn.bergmans@arm.com
37212468Sglenn.bergmans@arm.com    def to_raw(self):
37312468Sglenn.bergmans@arm.com        """Return RAW value representation"""
37412468Sglenn.bergmans@arm.com        return ''.join([pack('>b', byte) for byte in self.bytes])
37512468Sglenn.bergmans@arm.com
37612468Sglenn.bergmans@arm.com    def __str__(self):
37712468Sglenn.bergmans@arm.com        """String representation"""
37812468Sglenn.bergmans@arm.com        return "Property(%s,Bytes:%s)" % (self.name, self.bytes)
37912468Sglenn.bergmans@arm.com
38012468Sglenn.bergmans@arm.com    def __getitem__(self, index):
38112468Sglenn.bergmans@arm.com        """Get bytes, returns a byte"""
38212468Sglenn.bergmans@arm.com        return self.bytes[index]
38312468Sglenn.bergmans@arm.com
38412468Sglenn.bergmans@arm.com    def __len__(self):
38512468Sglenn.bergmans@arm.com        """Get strings count"""
38612468Sglenn.bergmans@arm.com        return len(self.bytes)
38712468Sglenn.bergmans@arm.com
38812468Sglenn.bergmans@arm.com    def __eq__(self, node):
38912468Sglenn.bergmans@arm.com        """Check node equality
39012468Sglenn.bergmans@arm.com           check properties are the same (same values)
39112468Sglenn.bergmans@arm.com        """
39212468Sglenn.bergmans@arm.com        if not FdtProperty.__eq__(self, node):
39312468Sglenn.bergmans@arm.com            return False
39412468Sglenn.bergmans@arm.com        if self.__len__() != len(node):
39512468Sglenn.bergmans@arm.com            return False
39612468Sglenn.bergmans@arm.com        for index in range(self.__len__()):
39712468Sglenn.bergmans@arm.com            if self.bytes[index] != node[index]:
39812468Sglenn.bergmans@arm.com                return False
39912468Sglenn.bergmans@arm.com        return True
40012468Sglenn.bergmans@arm.com
40112468Sglenn.bergmans@arm.com
40212468Sglenn.bergmans@arm.comclass FdtNop(object):  # pylint: disable-msg=R0903
40312468Sglenn.bergmans@arm.com    """Nop child representation"""
40412468Sglenn.bergmans@arm.com
40512468Sglenn.bergmans@arm.com    def __init__(self):
40612468Sglenn.bergmans@arm.com        """Init with nothing"""
40712468Sglenn.bergmans@arm.com
40812468Sglenn.bergmans@arm.com    def get_name(self):  # pylint: disable-msg=R0201
40912468Sglenn.bergmans@arm.com        """Return name"""
41012468Sglenn.bergmans@arm.com        return None
41112468Sglenn.bergmans@arm.com
41212468Sglenn.bergmans@arm.com    def __str__(self):
41312468Sglenn.bergmans@arm.com        """String representation"""
41412468Sglenn.bergmans@arm.com        return ''
41512468Sglenn.bergmans@arm.com
41612468Sglenn.bergmans@arm.com    def dts_represent(self, depth=0):  # pylint: disable-msg=R0201
41712468Sglenn.bergmans@arm.com        """Get dts string representation"""
41812468Sglenn.bergmans@arm.com        return INDENT*depth+'// [NOP]'
41912468Sglenn.bergmans@arm.com
42012468Sglenn.bergmans@arm.com    def dtb_represent(self, string_store, pos=0, version=17):
42112468Sglenn.bergmans@arm.com        """Get blob representation"""
42212468Sglenn.bergmans@arm.com        # print "%x:%s" % (pos, self)
42312468Sglenn.bergmans@arm.com        pos += 4
42412468Sglenn.bergmans@arm.com        return (pack('>I', FDT_NOP), string_store, pos)
42512468Sglenn.bergmans@arm.com
42612468Sglenn.bergmans@arm.com
42712468Sglenn.bergmans@arm.comclass FdtNode(object):
42812468Sglenn.bergmans@arm.com    """Node representation"""
42912468Sglenn.bergmans@arm.com
43012468Sglenn.bergmans@arm.com    @staticmethod
43112468Sglenn.bergmans@arm.com    def __validate_dt_name(name):
43212468Sglenn.bergmans@arm.com        """Checks the name validity"""
43312468Sglenn.bergmans@arm.com        return not any([True for char in name
43412468Sglenn.bergmans@arm.com                        if char not in string.printable])
43512468Sglenn.bergmans@arm.com
43612468Sglenn.bergmans@arm.com    def __init__(self, name):
43712468Sglenn.bergmans@arm.com        """Init node with name"""
43812468Sglenn.bergmans@arm.com        self.name = name
43912468Sglenn.bergmans@arm.com        self.subdata = []
44012468Sglenn.bergmans@arm.com        self.parent = None
44112468Sglenn.bergmans@arm.com        if not FdtNode.__validate_dt_name(self.name):
44212468Sglenn.bergmans@arm.com            raise Exception("Invalid name '%s'" % self.name)
44312468Sglenn.bergmans@arm.com
44412468Sglenn.bergmans@arm.com    def get_name(self):
44512468Sglenn.bergmans@arm.com        """Get property name"""
44612468Sglenn.bergmans@arm.com        return self.name
44712468Sglenn.bergmans@arm.com
44812468Sglenn.bergmans@arm.com    def __check_name_duplicate(self, name):
44912468Sglenn.bergmans@arm.com        """Checks if name is not in a subnode"""
45012468Sglenn.bergmans@arm.com        for data in self.subdata:
45112468Sglenn.bergmans@arm.com            if not isinstance(data, FdtNop) \
45212468Sglenn.bergmans@arm.com               and data.get_name() == name:
45312468Sglenn.bergmans@arm.com                   return True
45412468Sglenn.bergmans@arm.com        return False
45512468Sglenn.bergmans@arm.com
45612468Sglenn.bergmans@arm.com    def add_subnode(self, node):
45712468Sglenn.bergmans@arm.com        """Add child, deprecated use append()"""
45812468Sglenn.bergmans@arm.com        self.append(node)
45912468Sglenn.bergmans@arm.com
46012468Sglenn.bergmans@arm.com    def add_raw_attribute(self, name, raw_value):
46112468Sglenn.bergmans@arm.com        """Construct a raw attribute and add to child"""
46212468Sglenn.bergmans@arm.com        self.append(FdtProperty.new_raw_property(name, raw_value))
46312468Sglenn.bergmans@arm.com
46412468Sglenn.bergmans@arm.com    def set_parent_node(self, node):
46512468Sglenn.bergmans@arm.com        """Set parent node, None and FdtNode accepted"""
46612468Sglenn.bergmans@arm.com        if node is not None and \
46712468Sglenn.bergmans@arm.com           not isinstance(node, FdtNode):
46812468Sglenn.bergmans@arm.com            raise Exception("Invalid object type")
46912468Sglenn.bergmans@arm.com        self.parent = node
47012468Sglenn.bergmans@arm.com
47112468Sglenn.bergmans@arm.com    def get_parent_node(self):
47212468Sglenn.bergmans@arm.com        """Get parent node"""
47312468Sglenn.bergmans@arm.com        return self.parent
47412468Sglenn.bergmans@arm.com
47512468Sglenn.bergmans@arm.com    def __str__(self):
47612468Sglenn.bergmans@arm.com        """String representation"""
47712468Sglenn.bergmans@arm.com        return "Node(%s)" % self.name
47812468Sglenn.bergmans@arm.com
47912468Sglenn.bergmans@arm.com    def dts_represent(self, depth=0):
48012468Sglenn.bergmans@arm.com        """Get dts string representation"""
48112468Sglenn.bergmans@arm.com        result = ('\n').join([sub.dts_represent(depth+1)
48212468Sglenn.bergmans@arm.com                                         for sub in self.subdata])
48312468Sglenn.bergmans@arm.com        if len(result) > 0:
48412468Sglenn.bergmans@arm.com            result += '\n'
48512468Sglenn.bergmans@arm.com        return INDENT*depth + self.name + ' {\n' + \
48612468Sglenn.bergmans@arm.com               result + INDENT*depth + "};"
48712468Sglenn.bergmans@arm.com
48812468Sglenn.bergmans@arm.com    def dtb_represent(self, strings_store, pos=0, version=17):
48912468Sglenn.bergmans@arm.com        """Get blob representation
49012468Sglenn.bergmans@arm.com           Pass string storage as strings_store, pos for current node start
49112468Sglenn.bergmans@arm.com           and version as current dtb version
49212468Sglenn.bergmans@arm.com        """
49312468Sglenn.bergmans@arm.com        # print "%x:%s" % (pos, self)
49412468Sglenn.bergmans@arm.com        strings = strings_store
49512468Sglenn.bergmans@arm.com        if self.get_name() == '/':
49612468Sglenn.bergmans@arm.com            blob = pack('>II', FDT_BEGIN_NODE, 0)
49712468Sglenn.bergmans@arm.com        else:
49812468Sglenn.bergmans@arm.com            blob = pack('>I', FDT_BEGIN_NODE)
49912468Sglenn.bergmans@arm.com            blob += self.get_name().encode('ascii') + pack('b', 0)
50012468Sglenn.bergmans@arm.com        if len(blob) % 4:
50112468Sglenn.bergmans@arm.com            blob += pack('b', 0) * (4-(len(blob) % 4))
50212468Sglenn.bergmans@arm.com        pos += len(blob)
50312468Sglenn.bergmans@arm.com        for sub in self.subdata:
50412468Sglenn.bergmans@arm.com            (data, strings, pos) = sub.dtb_represent(strings, pos, version)
50512468Sglenn.bergmans@arm.com            blob += data
50612468Sglenn.bergmans@arm.com        pos += 4
50712468Sglenn.bergmans@arm.com        blob += pack('>I', FDT_END_NODE)
50812468Sglenn.bergmans@arm.com        return (blob, strings, pos)
50912468Sglenn.bergmans@arm.com
51012468Sglenn.bergmans@arm.com    def json_represent(self, depth=0):
51112468Sglenn.bergmans@arm.com        """Get dts string representation"""
51212468Sglenn.bergmans@arm.com        result = (',\n'+ \
51312468Sglenn.bergmans@arm.com                  INDENT*(depth+1)).join([sub.json_represent(depth+1)
51412468Sglenn.bergmans@arm.com                                          for sub in self.subdata
51512468Sglenn.bergmans@arm.com                                          if not isinstance(sub, FdtNop)])
51612468Sglenn.bergmans@arm.com        if len(result) > 0:
51712468Sglenn.bergmans@arm.com            result = INDENT + result + '\n'+INDENT*depth
51812468Sglenn.bergmans@arm.com        if self.get_name() == '/':
51912468Sglenn.bergmans@arm.com            return "{\n" + INDENT*(depth) + result + "}"
52012468Sglenn.bergmans@arm.com        else:
52112468Sglenn.bergmans@arm.com            return json.dumps(self.name) + ': {\n' + \
52212468Sglenn.bergmans@arm.com                   INDENT*(depth) + result + "}"
52312468Sglenn.bergmans@arm.com
52412468Sglenn.bergmans@arm.com    def __getitem__(self, index):
52512468Sglenn.bergmans@arm.com        """Get subnodes, returns either a Node, a Property or a Nop"""
52612468Sglenn.bergmans@arm.com        return self.subdata[index]
52712468Sglenn.bergmans@arm.com
52812468Sglenn.bergmans@arm.com    def __setitem__(self, index, subnode):
52912468Sglenn.bergmans@arm.com        """Set node at index, replacing previous subnode,
53012468Sglenn.bergmans@arm.com           must not be a duplicate name
53112468Sglenn.bergmans@arm.com        """
53212468Sglenn.bergmans@arm.com        if self.subdata[index].get_name() != subnode.get_name() and \
53312468Sglenn.bergmans@arm.com           self.__check_name_duplicate(subnode.get_name()):
53412468Sglenn.bergmans@arm.com            raise Exception("%s : %s subnode already exists" % \
53512468Sglenn.bergmans@arm.com                                        (self, subnode))
53612468Sglenn.bergmans@arm.com        if not isinstance(subnode, (FdtNode, FdtProperty, FdtNop)):
53712468Sglenn.bergmans@arm.com            raise Exception("Invalid object type")
53812468Sglenn.bergmans@arm.com        self.subdata[index] = subnode
53912468Sglenn.bergmans@arm.com
54012468Sglenn.bergmans@arm.com    def __len__(self):
54112468Sglenn.bergmans@arm.com        """Get strings count"""
54212468Sglenn.bergmans@arm.com        return len(self.subdata)
54312468Sglenn.bergmans@arm.com
54412468Sglenn.bergmans@arm.com    def __ne__(self, node):
54512468Sglenn.bergmans@arm.com        """Check node inequality
54612468Sglenn.bergmans@arm.com           i.e. is subnodes are the same, in either order
54712468Sglenn.bergmans@arm.com           and properties are the same (same values)
54812468Sglenn.bergmans@arm.com           The FdtNop is excluded from the check
54912468Sglenn.bergmans@arm.com        """
55012468Sglenn.bergmans@arm.com        return not self.__eq__(node)
55112468Sglenn.bergmans@arm.com
55212468Sglenn.bergmans@arm.com    def __eq__(self, node):
55312468Sglenn.bergmans@arm.com        """Check node equality
55412468Sglenn.bergmans@arm.com           i.e. is subnodes are the same, in either order
55512468Sglenn.bergmans@arm.com           and properties are the same (same values)
55612468Sglenn.bergmans@arm.com           The FdtNop is excluded from the check
55712468Sglenn.bergmans@arm.com        """
55812468Sglenn.bergmans@arm.com        if not isinstance(node, FdtNode):
55912468Sglenn.bergmans@arm.com            raise Exception("Invalid object type")
56012468Sglenn.bergmans@arm.com        if self.name != node.get_name():
56112468Sglenn.bergmans@arm.com            return False
56212468Sglenn.bergmans@arm.com        curnames = set([subnode.get_name() for subnode in self.subdata
56312468Sglenn.bergmans@arm.com                                    if not isinstance(subnode, FdtNop)])
56412468Sglenn.bergmans@arm.com        cmpnames = set([subnode.get_name() for subnode in node
56512468Sglenn.bergmans@arm.com                                    if not isinstance(subnode, FdtNop)])
56612468Sglenn.bergmans@arm.com        if curnames != cmpnames:
56712468Sglenn.bergmans@arm.com            return False
56812468Sglenn.bergmans@arm.com        for subnode in [subnode for subnode in self.subdata
56912468Sglenn.bergmans@arm.com                                    if not isinstance(subnode, FdtNop)]:
57012468Sglenn.bergmans@arm.com            index = node.index(subnode.get_name())
57112468Sglenn.bergmans@arm.com            if subnode != node[index]:
57212468Sglenn.bergmans@arm.com                return False
57312468Sglenn.bergmans@arm.com        return True
57412468Sglenn.bergmans@arm.com
57512468Sglenn.bergmans@arm.com    def append(self, subnode):
57612468Sglenn.bergmans@arm.com        """Append subnode, same as add_subnode"""
57712468Sglenn.bergmans@arm.com        if self.__check_name_duplicate(subnode.get_name()):
57812468Sglenn.bergmans@arm.com            raise Exception("%s : %s subnode already exists" % \
57912468Sglenn.bergmans@arm.com                                    (self, subnode))
58012468Sglenn.bergmans@arm.com        if not isinstance(subnode, (FdtNode, FdtProperty, FdtNop)):
58112468Sglenn.bergmans@arm.com            raise Exception("Invalid object type")
58212468Sglenn.bergmans@arm.com        self.subdata.append(subnode)
58312468Sglenn.bergmans@arm.com
58412468Sglenn.bergmans@arm.com    def pop(self, index=-1):
58512468Sglenn.bergmans@arm.com        """Remove and returns subnode at index, default the last"""
58612468Sglenn.bergmans@arm.com        return self.subdata.pop(index)
58712468Sglenn.bergmans@arm.com
58812468Sglenn.bergmans@arm.com    def insert(self, index, subnode):
58912468Sglenn.bergmans@arm.com        """Insert subnode before index, must not be a duplicate name"""
59012468Sglenn.bergmans@arm.com        if self.__check_name_duplicate(subnode.get_name()):
59112468Sglenn.bergmans@arm.com            raise Exception("%s : %s subnode already exists" % \
59212468Sglenn.bergmans@arm.com                                (self, subnode))
59312468Sglenn.bergmans@arm.com        if not isinstance(subnode, (FdtNode, FdtProperty, FdtNop)):
59412468Sglenn.bergmans@arm.com            raise Exception("Invalid object type")
59512468Sglenn.bergmans@arm.com        self.subdata.insert(index, subnode)
59612468Sglenn.bergmans@arm.com
59712468Sglenn.bergmans@arm.com    def _find(self, name):
59812468Sglenn.bergmans@arm.com        """Find name in subnodes"""
59912468Sglenn.bergmans@arm.com        for i in range(0, len(self.subdata)):
60012468Sglenn.bergmans@arm.com            if not isinstance(self.subdata[i], FdtNop) and \
60112468Sglenn.bergmans@arm.com               name == self.subdata[i].get_name():
60212468Sglenn.bergmans@arm.com                return i
60312468Sglenn.bergmans@arm.com        return None
60412468Sglenn.bergmans@arm.com
60512468Sglenn.bergmans@arm.com    def remove(self, name):
60612468Sglenn.bergmans@arm.com        """Remove subnode with the name
60712468Sglenn.bergmans@arm.com           Raises ValueError is not present
60812468Sglenn.bergmans@arm.com        """
60912468Sglenn.bergmans@arm.com        index = self._find(name)
61012468Sglenn.bergmans@arm.com        if index is None:
61112468Sglenn.bergmans@arm.com            raise ValueError("Not present")
61212468Sglenn.bergmans@arm.com        return self.subdata.pop(index)
61312468Sglenn.bergmans@arm.com
61412468Sglenn.bergmans@arm.com    def index(self, name):
61512468Sglenn.bergmans@arm.com        """Returns position of subnode with the name
61612468Sglenn.bergmans@arm.com           Raises ValueError is not present
61712468Sglenn.bergmans@arm.com        """
61812468Sglenn.bergmans@arm.com        index = self._find(name)
61912468Sglenn.bergmans@arm.com        if index is None:
62012468Sglenn.bergmans@arm.com            raise ValueError("Not present")
62112468Sglenn.bergmans@arm.com        return index
62212468Sglenn.bergmans@arm.com
62312468Sglenn.bergmans@arm.com    def merge(self, node):
62412468Sglenn.bergmans@arm.com        """Merge two nodes and subnodes
62512468Sglenn.bergmans@arm.com           Replace current properties with the given properties
62612468Sglenn.bergmans@arm.com        """
62712468Sglenn.bergmans@arm.com        if not isinstance(node, FdtNode):
62812468Sglenn.bergmans@arm.com            raise Exception("Can only merge with a FdtNode")
62912468Sglenn.bergmans@arm.com        for subnode in [obj for obj in node
63012468Sglenn.bergmans@arm.com                        if isinstance(obj, (FdtNode, FdtProperty))]:
63112468Sglenn.bergmans@arm.com            index = self._find(subnode.get_name())
63212468Sglenn.bergmans@arm.com            if index is None:
63312468Sglenn.bergmans@arm.com                dup = deepcopy(subnode)
63412468Sglenn.bergmans@arm.com                if isinstance(subnode, FdtNode):
63512468Sglenn.bergmans@arm.com                    dup.set_parent_node(self)
63612468Sglenn.bergmans@arm.com                self.append(dup)
63712468Sglenn.bergmans@arm.com            elif isinstance(subnode, FdtNode):
63812468Sglenn.bergmans@arm.com                self.subdata[index].merge(subnode)
63912468Sglenn.bergmans@arm.com            else:
64012468Sglenn.bergmans@arm.com                self.subdata[index] = copy(subnode)
64112468Sglenn.bergmans@arm.com
64212468Sglenn.bergmans@arm.com    def walk(self):
64312468Sglenn.bergmans@arm.com        """Walk into subnodes and yield paths and objects
64412468Sglenn.bergmans@arm.com           Returns set with (path string, node object)
64512468Sglenn.bergmans@arm.com        """
64612468Sglenn.bergmans@arm.com        node = self
64712468Sglenn.bergmans@arm.com        start = 0
64812468Sglenn.bergmans@arm.com        hist = []
64912468Sglenn.bergmans@arm.com        curpath = []
65012468Sglenn.bergmans@arm.com
65112468Sglenn.bergmans@arm.com        while True:
65212468Sglenn.bergmans@arm.com            for index in range(start, len(node)):
65312468Sglenn.bergmans@arm.com                if isinstance(node[index], (FdtNode, FdtProperty)):
65412468Sglenn.bergmans@arm.com                    yield ('/' + '/'.join(curpath+[node[index].get_name()]),
65512468Sglenn.bergmans@arm.com                            node[index])
65612468Sglenn.bergmans@arm.com                if isinstance(node[index], FdtNode):
65712468Sglenn.bergmans@arm.com                    if len(node[index]):
65812468Sglenn.bergmans@arm.com                        hist.append((node, index+1))
65912468Sglenn.bergmans@arm.com                        curpath.append(node[index].get_name())
66012468Sglenn.bergmans@arm.com                        node = node[index]
66112468Sglenn.bergmans@arm.com                        start = 0
66212468Sglenn.bergmans@arm.com                        index = -1
66312468Sglenn.bergmans@arm.com                        break
66412468Sglenn.bergmans@arm.com            if index >= 0:
66512468Sglenn.bergmans@arm.com                if len(hist):
66612468Sglenn.bergmans@arm.com                    (node, start) = hist.pop()
66712468Sglenn.bergmans@arm.com                    curpath.pop()
66812468Sglenn.bergmans@arm.com                else:
66912468Sglenn.bergmans@arm.com                    break
67012468Sglenn.bergmans@arm.com
67112468Sglenn.bergmans@arm.com
67212468Sglenn.bergmans@arm.comclass Fdt(object):
67312468Sglenn.bergmans@arm.com    """Flattened Device Tree representation"""
67412468Sglenn.bergmans@arm.com
67512468Sglenn.bergmans@arm.com    def __init__(self, version=17, last_comp_version=16, boot_cpuid_phys=0):
67612468Sglenn.bergmans@arm.com        """Init FDT object with version and boot values"""
67712468Sglenn.bergmans@arm.com        self.header = {'magic': FDT_MAGIC,
67812468Sglenn.bergmans@arm.com                       'totalsize': 0,
67912468Sglenn.bergmans@arm.com                       'off_dt_struct': 0,
68012468Sglenn.bergmans@arm.com                       'off_dt_strings': 0,
68112468Sglenn.bergmans@arm.com                       'off_mem_rsvmap': 0,
68212468Sglenn.bergmans@arm.com                       'version': version,
68312468Sglenn.bergmans@arm.com                       'last_comp_version': last_comp_version,
68412468Sglenn.bergmans@arm.com                       'boot_cpuid_phys': boot_cpuid_phys,
68512468Sglenn.bergmans@arm.com                       'size_dt_strings': 0,
68612468Sglenn.bergmans@arm.com                       'size_dt_struct': 0}
68712468Sglenn.bergmans@arm.com        self.rootnode = None
68812468Sglenn.bergmans@arm.com        self.prenops = None
68912468Sglenn.bergmans@arm.com        self.postnops = None
69012468Sglenn.bergmans@arm.com        self.reserve_entries = None
69112468Sglenn.bergmans@arm.com
69212468Sglenn.bergmans@arm.com    def add_rootnode(self, rootnode, prenops=None, postnops=None):
69312468Sglenn.bergmans@arm.com        """Add root node"""
69412468Sglenn.bergmans@arm.com        self.rootnode = rootnode
69512468Sglenn.bergmans@arm.com        self.prenops = prenops
69612468Sglenn.bergmans@arm.com        self.postnops = postnops
69712468Sglenn.bergmans@arm.com
69812468Sglenn.bergmans@arm.com    def get_rootnode(self):
69912468Sglenn.bergmans@arm.com        """Get root node"""
70012468Sglenn.bergmans@arm.com        return self.rootnode
70112468Sglenn.bergmans@arm.com
70212468Sglenn.bergmans@arm.com    def add_reserve_entries(self, reserve_entries):
70312468Sglenn.bergmans@arm.com        """Add reserved entries as list of dict with
70412468Sglenn.bergmans@arm.com           'address' and 'size' keys"""
70512468Sglenn.bergmans@arm.com        self.reserve_entries = reserve_entries
70612468Sglenn.bergmans@arm.com
70712468Sglenn.bergmans@arm.com    def to_dts(self):
70812468Sglenn.bergmans@arm.com        """Export to DTS representation in string format"""
70912468Sglenn.bergmans@arm.com        result = "/dts-v1/;\n"
71012468Sglenn.bergmans@arm.com        result += "// version:\t\t%d\n" % self.header['version']
71112468Sglenn.bergmans@arm.com        result += "// last_comp_version:\t%d\n" % \
71212468Sglenn.bergmans@arm.com                  self.header['last_comp_version']
71312468Sglenn.bergmans@arm.com        if self.header['version'] >= 2:
71412468Sglenn.bergmans@arm.com            result += "// boot_cpuid_phys:\t0x%x\n" % \
71512468Sglenn.bergmans@arm.com                self.header['boot_cpuid_phys']
71612468Sglenn.bergmans@arm.com        result += '\n'
71712468Sglenn.bergmans@arm.com        if self.reserve_entries is not None:
71812468Sglenn.bergmans@arm.com            for entry in self.reserve_entries:
71912468Sglenn.bergmans@arm.com                result += "/memreserve/ "
72012468Sglenn.bergmans@arm.com                if entry['address']:
72112468Sglenn.bergmans@arm.com                    result += "%#x " % entry['address']
72212468Sglenn.bergmans@arm.com                else:
72312468Sglenn.bergmans@arm.com                    result += "0 "
72412468Sglenn.bergmans@arm.com                if entry['size']:
72512468Sglenn.bergmans@arm.com                    result += "%#x" % entry['size']
72612468Sglenn.bergmans@arm.com                else:
72712468Sglenn.bergmans@arm.com                    result += "0"
72812468Sglenn.bergmans@arm.com                result += ";\n"
72912468Sglenn.bergmans@arm.com        if self.prenops:
73012468Sglenn.bergmans@arm.com            result += '\n'.join([nop.dts_represent() for nop in self.prenops])
73112468Sglenn.bergmans@arm.com            result += '\n'
73212468Sglenn.bergmans@arm.com        if self.rootnode is not None:
73312468Sglenn.bergmans@arm.com            result += self.rootnode.dts_represent()
73412468Sglenn.bergmans@arm.com        if self.postnops:
73512468Sglenn.bergmans@arm.com            result += '\n'
73612468Sglenn.bergmans@arm.com            result += '\n'.join([nop.dts_represent() for nop in self.postnops])
73712468Sglenn.bergmans@arm.com        return result
73812468Sglenn.bergmans@arm.com
73912468Sglenn.bergmans@arm.com    def to_dtb(self):
74012468Sglenn.bergmans@arm.com        """Export to Blob format"""
74112468Sglenn.bergmans@arm.com        if self.rootnode is None:
74212468Sglenn.bergmans@arm.com            return None
74312468Sglenn.bergmans@arm.com        blob_reserve_entries = pack('')
74412468Sglenn.bergmans@arm.com        if self.reserve_entries is not None:
74512468Sglenn.bergmans@arm.com            for entry in self.reserve_entries:
74612468Sglenn.bergmans@arm.com                blob_reserve_entries += pack('>QQ',
74712468Sglenn.bergmans@arm.com                                             entry['address'],
74812468Sglenn.bergmans@arm.com                                             entry['size'])
74912468Sglenn.bergmans@arm.com        blob_reserve_entries += pack('>QQ', 0, 0)
75012468Sglenn.bergmans@arm.com        header_size = 7 * 4
75112468Sglenn.bergmans@arm.com        if self.header['version'] >= 2:
75212468Sglenn.bergmans@arm.com            header_size += 4
75312468Sglenn.bergmans@arm.com        if self.header['version'] >= 3:
75412468Sglenn.bergmans@arm.com            header_size += 4
75512468Sglenn.bergmans@arm.com        if self.header['version'] >= 17:
75612468Sglenn.bergmans@arm.com            header_size += 4
75712468Sglenn.bergmans@arm.com        header_adjust = pack('')
75812468Sglenn.bergmans@arm.com        if header_size % 8 != 0:
75912468Sglenn.bergmans@arm.com            header_adjust = pack('b', 0) * (8 - (header_size % 8))
76012468Sglenn.bergmans@arm.com            header_size += len(header_adjust)
76112468Sglenn.bergmans@arm.com        dt_start = header_size + len(blob_reserve_entries)
76212468Sglenn.bergmans@arm.com        # print "dt_start %d" % dt_start
76312468Sglenn.bergmans@arm.com        (blob_dt, blob_strings, dt_pos) = \
76412468Sglenn.bergmans@arm.com            self.rootnode.dtb_represent('', dt_start, self.header['version'])
76512468Sglenn.bergmans@arm.com        if self.prenops is not None:
76612468Sglenn.bergmans@arm.com            blob_dt = pack('').join([nop.dtb_represent('')[0]
76712468Sglenn.bergmans@arm.com                               for nop in self.prenops])\
76812468Sglenn.bergmans@arm.com                      + blob_dt
76912468Sglenn.bergmans@arm.com        if self.postnops is not None:
77012468Sglenn.bergmans@arm.com            blob_dt += pack('').join([nop.dtb_represent('')[0]
77112468Sglenn.bergmans@arm.com                                for nop in self.postnops])
77212468Sglenn.bergmans@arm.com        blob_dt += pack('>I', FDT_END)
77312468Sglenn.bergmans@arm.com        self.header['size_dt_strings'] = len(blob_strings)
77412468Sglenn.bergmans@arm.com        self.header['size_dt_struct'] = len(blob_dt)
77512468Sglenn.bergmans@arm.com        self.header['off_mem_rsvmap'] = header_size
77612468Sglenn.bergmans@arm.com        self.header['off_dt_struct'] = dt_start
77712468Sglenn.bergmans@arm.com        self.header['off_dt_strings'] = dt_start + len(blob_dt)
77812468Sglenn.bergmans@arm.com        self.header['totalsize'] = dt_start + len(blob_dt) + len(blob_strings)
77912468Sglenn.bergmans@arm.com        blob_header = pack('>IIIIIII', self.header['magic'],
78012468Sglenn.bergmans@arm.com                           self.header['totalsize'],
78112468Sglenn.bergmans@arm.com                           self.header['off_dt_struct'],
78212468Sglenn.bergmans@arm.com                           self.header['off_dt_strings'],
78312468Sglenn.bergmans@arm.com                           self.header['off_mem_rsvmap'],
78412468Sglenn.bergmans@arm.com                           self.header['version'],
78512468Sglenn.bergmans@arm.com                           self.header['last_comp_version'])
78612468Sglenn.bergmans@arm.com        if self.header['version'] >= 2:
78712468Sglenn.bergmans@arm.com            blob_header += pack('>I', self.header['boot_cpuid_phys'])
78812468Sglenn.bergmans@arm.com        if self.header['version'] >= 3:
78912468Sglenn.bergmans@arm.com            blob_header += pack('>I', self.header['size_dt_strings'])
79012468Sglenn.bergmans@arm.com        if self.header['version'] >= 17:
79112468Sglenn.bergmans@arm.com            blob_header += pack('>I', self.header['size_dt_struct'])
79212468Sglenn.bergmans@arm.com        return blob_header + header_adjust + blob_reserve_entries + \
79312468Sglenn.bergmans@arm.com            blob_dt + blob_strings.encode('ascii')
79412468Sglenn.bergmans@arm.com
79512468Sglenn.bergmans@arm.com    def to_json(self):
79612468Sglenn.bergmans@arm.com        """Ouput JSON"""
79712468Sglenn.bergmans@arm.com        if self.rootnode is None:
79812468Sglenn.bergmans@arm.com            return None
79912468Sglenn.bergmans@arm.com        return self.rootnode.json_represent()
80012468Sglenn.bergmans@arm.com
80112468Sglenn.bergmans@arm.com    def resolve_path(self, path):
80212468Sglenn.bergmans@arm.com        """Resolve path like /memory/reg and return either a FdtNode,
80312468Sglenn.bergmans@arm.com            a FdtProperty or None"""
80412468Sglenn.bergmans@arm.com        if self.rootnode is None:
80512468Sglenn.bergmans@arm.com            return None
80612468Sglenn.bergmans@arm.com        if not path.startswith('/'):
80712468Sglenn.bergmans@arm.com            return None
80812468Sglenn.bergmans@arm.com        if len(path) > 1 and path.endswith('/'):
80912468Sglenn.bergmans@arm.com            path = path[:-1]
81012468Sglenn.bergmans@arm.com        if path == '/':
81112468Sglenn.bergmans@arm.com            return self.rootnode
81212468Sglenn.bergmans@arm.com        curnode = self.rootnode
81312468Sglenn.bergmans@arm.com        for subpath in path[1:].split('/'):
81412468Sglenn.bergmans@arm.com            found = None
81512468Sglenn.bergmans@arm.com            if not isinstance(curnode, FdtNode):
81612468Sglenn.bergmans@arm.com                return None
81712468Sglenn.bergmans@arm.com            for node in curnode:
81812468Sglenn.bergmans@arm.com                if subpath == node.get_name():
81912468Sglenn.bergmans@arm.com                    found = node
82012468Sglenn.bergmans@arm.com                    break
82112468Sglenn.bergmans@arm.com            if found is None:
82212468Sglenn.bergmans@arm.com                return None
82312468Sglenn.bergmans@arm.com            curnode = found
82412468Sglenn.bergmans@arm.com        return curnode
82512468Sglenn.bergmans@arm.com
82612468Sglenn.bergmans@arm.comdef _add_json_to_fdtnode(node, subjson):
82712468Sglenn.bergmans@arm.com    """Populate FdtNode with JSON dict items"""
82812468Sglenn.bergmans@arm.com    for (key, value) in subjson.items():
82912468Sglenn.bergmans@arm.com        if isinstance(value, dict):
83012468Sglenn.bergmans@arm.com            subnode = FdtNode(key)
83112468Sglenn.bergmans@arm.com            subnode.set_parent_node(node)
83212468Sglenn.bergmans@arm.com            node.append(subnode)
83312468Sglenn.bergmans@arm.com            _add_json_to_fdtnode(subnode, value)
83412468Sglenn.bergmans@arm.com        elif isinstance(value, list):
83512468Sglenn.bergmans@arm.com            if len(value) < 2:
83612468Sglenn.bergmans@arm.com                raise Exception("Invalid list for %s" % key)
83712468Sglenn.bergmans@arm.com            if value[0] == "words":
83812468Sglenn.bergmans@arm.com                words = [int(word, 16) for word in value[1:]]
83912468Sglenn.bergmans@arm.com                node.append(FdtPropertyWords(key, words))
84012468Sglenn.bergmans@arm.com            elif value[0] == "bytes":
84112468Sglenn.bergmans@arm.com                bytez = [int(byte, 16) for byte in value[1:]]
84212468Sglenn.bergmans@arm.com                node.append(FdtPropertyBytes(key, bytez))
84312468Sglenn.bergmans@arm.com            elif value[0] == "strings":
84412468Sglenn.bergmans@arm.com                node.append(FdtPropertyStrings(key, \
84512468Sglenn.bergmans@arm.com                            [s for s in value[1:]]))
84612468Sglenn.bergmans@arm.com            else:
84712468Sglenn.bergmans@arm.com                raise Exception("Invalid list for %s" % key)
84812468Sglenn.bergmans@arm.com        elif value is None:
84912468Sglenn.bergmans@arm.com            node.append(FdtProperty(key))
85012468Sglenn.bergmans@arm.com        else:
85112468Sglenn.bergmans@arm.com            raise Exception("Invalid value for %s" % key)
85212468Sglenn.bergmans@arm.com
85312468Sglenn.bergmans@arm.comdef FdtJsonParse(buf):
85412468Sglenn.bergmans@arm.com    """Import FDT from JSON representation, see JSONDeviceTree.md for
85512468Sglenn.bergmans@arm.com       structure and encoding
85612468Sglenn.bergmans@arm.com       Returns an Fdt object
85712468Sglenn.bergmans@arm.com    """
85812468Sglenn.bergmans@arm.com    tree = json.loads(buf)
85912468Sglenn.bergmans@arm.com
86012468Sglenn.bergmans@arm.com    root = FdtNode('/')
86112468Sglenn.bergmans@arm.com
86212468Sglenn.bergmans@arm.com    _add_json_to_fdtnode(root, tree)
86312468Sglenn.bergmans@arm.com
86412468Sglenn.bergmans@arm.com    fdt = Fdt()
86512468Sglenn.bergmans@arm.com    fdt.add_rootnode(root)
86612468Sglenn.bergmans@arm.com    return fdt
86712468Sglenn.bergmans@arm.com
86812468Sglenn.bergmans@arm.comdef FdtFsParse(path):
86912468Sglenn.bergmans@arm.com    """Parse device tree filesystem and return a Fdt instance
87012468Sglenn.bergmans@arm.com       Should be /proc/device-tree on a device, or the fusemount.py
87112468Sglenn.bergmans@arm.com       mount point.
87212468Sglenn.bergmans@arm.com    """
87312468Sglenn.bergmans@arm.com    root = FdtNode("/")
87412468Sglenn.bergmans@arm.com
87512468Sglenn.bergmans@arm.com    if path.endswith('/'):
87612468Sglenn.bergmans@arm.com        path = path[:-1]
87712468Sglenn.bergmans@arm.com
87812468Sglenn.bergmans@arm.com    nodes = {path: root}
87912468Sglenn.bergmans@arm.com
88012468Sglenn.bergmans@arm.com    for subpath, subdirs, files in os.walk(path):
88112468Sglenn.bergmans@arm.com        if subpath not in nodes.keys():
88212468Sglenn.bergmans@arm.com            raise Exception("os.walk error")
88312468Sglenn.bergmans@arm.com        cur = nodes[subpath]
88412468Sglenn.bergmans@arm.com        for f in files:
88512468Sglenn.bergmans@arm.com            with open(subpath+'/'+f, 'rb') as content_file:
88612468Sglenn.bergmans@arm.com                content = content_file.read()
88712468Sglenn.bergmans@arm.com            prop = FdtProperty.new_raw_property(f, content)
88812468Sglenn.bergmans@arm.com            cur.add_subnode(prop)
88912468Sglenn.bergmans@arm.com        for subdir in subdirs:
89012468Sglenn.bergmans@arm.com            subnode = FdtNode(subdir)
89112468Sglenn.bergmans@arm.com            cur.add_subnode(subnode)
89212468Sglenn.bergmans@arm.com            subnode.set_parent_node(cur)
89312468Sglenn.bergmans@arm.com            nodes[subpath+'/'+subdir] = subnode
89412468Sglenn.bergmans@arm.com
89512468Sglenn.bergmans@arm.com    fdt = Fdt()
89612468Sglenn.bergmans@arm.com    fdt.add_rootnode(root)
89712468Sglenn.bergmans@arm.com    return fdt
89812468Sglenn.bergmans@arm.com
89912468Sglenn.bergmans@arm.comclass FdtBlobParse(object):  # pylint: disable-msg=R0903
90012468Sglenn.bergmans@arm.com    """Parse from file input"""
90112468Sglenn.bergmans@arm.com
90212468Sglenn.bergmans@arm.com    __fdt_header_format = ">IIIIIII"
90312468Sglenn.bergmans@arm.com    __fdt_header_names = ('magic', 'totalsize', 'off_dt_struct',
90412468Sglenn.bergmans@arm.com                          'off_dt_strings', 'off_mem_rsvmap', 'version',
90512468Sglenn.bergmans@arm.com                          'last_comp_version')
90612468Sglenn.bergmans@arm.com
90712468Sglenn.bergmans@arm.com    __fdt_reserve_entry_format = ">QQ"
90812468Sglenn.bergmans@arm.com    __fdt_reserve_entry_names = ('address', 'size')
90912468Sglenn.bergmans@arm.com
91012468Sglenn.bergmans@arm.com    __fdt_dt_cell_format = ">I"
91112468Sglenn.bergmans@arm.com    __fdt_dt_prop_format = ">II"
91212468Sglenn.bergmans@arm.com    __fdt_dt_tag_name = {FDT_BEGIN_NODE: 'node_begin',
91312468Sglenn.bergmans@arm.com                         FDT_END_NODE: 'node_end',
91412468Sglenn.bergmans@arm.com                         FDT_PROP: 'prop',
91512468Sglenn.bergmans@arm.com                         FDT_NOP: 'nop',
91612468Sglenn.bergmans@arm.com                         FDT_END: 'end'}
91712468Sglenn.bergmans@arm.com
91812468Sglenn.bergmans@arm.com    def __extract_fdt_header(self):
91912468Sglenn.bergmans@arm.com        """Extract DTB header"""
92012468Sglenn.bergmans@arm.com        header = Struct(self.__fdt_header_format)
92112468Sglenn.bergmans@arm.com        header_entry = Struct(">I")
92212468Sglenn.bergmans@arm.com        data = self.infile.read(header.size)
92312468Sglenn.bergmans@arm.com        result = dict(zip(self.__fdt_header_names, header.unpack_from(data)))
92412468Sglenn.bergmans@arm.com        if result['version'] >= 2:
92512468Sglenn.bergmans@arm.com            data = self.infile.read(header_entry.size)
92612468Sglenn.bergmans@arm.com            result['boot_cpuid_phys'] = header_entry.unpack_from(data)[0]
92712468Sglenn.bergmans@arm.com        if result['version'] >= 3:
92812468Sglenn.bergmans@arm.com            data = self.infile.read(header_entry.size)
92912468Sglenn.bergmans@arm.com            result['size_dt_strings'] = header_entry.unpack_from(data)[0]
93012468Sglenn.bergmans@arm.com        if result['version'] >= 17:
93112468Sglenn.bergmans@arm.com            data = self.infile.read(header_entry.size)
93212468Sglenn.bergmans@arm.com            result['size_dt_struct'] = header_entry.unpack_from(data)[0]
93312468Sglenn.bergmans@arm.com        return result
93412468Sglenn.bergmans@arm.com
93512468Sglenn.bergmans@arm.com    def __extract_fdt_reserve_entries(self):
93612468Sglenn.bergmans@arm.com        """Extract reserved memory entries"""
93712468Sglenn.bergmans@arm.com        header = Struct(self.__fdt_reserve_entry_format)
93812468Sglenn.bergmans@arm.com        entries = []
93912468Sglenn.bergmans@arm.com        self.infile.seek(self.fdt_header['off_mem_rsvmap'])
94012468Sglenn.bergmans@arm.com        while True:
94112468Sglenn.bergmans@arm.com            data = self.infile.read(header.size)
94212468Sglenn.bergmans@arm.com            result = dict(zip(self.__fdt_reserve_entry_names,
94312468Sglenn.bergmans@arm.com                              header.unpack_from(data)))
94412468Sglenn.bergmans@arm.com            if result['address'] == 0 and result['size'] == 0:
94512468Sglenn.bergmans@arm.com                return entries
94612468Sglenn.bergmans@arm.com            entries.append(result)
94712468Sglenn.bergmans@arm.com
94812468Sglenn.bergmans@arm.com    def __extract_fdt_nodename(self):
94912468Sglenn.bergmans@arm.com        """Extract node name"""
95012468Sglenn.bergmans@arm.com        data = ''
95112468Sglenn.bergmans@arm.com        pos = self.infile.tell()
95212468Sglenn.bergmans@arm.com        while True:
95312468Sglenn.bergmans@arm.com            byte = self.infile.read(1)
95412468Sglenn.bergmans@arm.com            if ord(byte) == 0:
95512468Sglenn.bergmans@arm.com                break
95612468Sglenn.bergmans@arm.com            data += byte.decode('ascii')
95712468Sglenn.bergmans@arm.com        align_pos = pos + len(data) + 1
95812468Sglenn.bergmans@arm.com        align_pos = (((align_pos) + ((4) - 1)) & ~((4) - 1))
95912468Sglenn.bergmans@arm.com        self.infile.seek(align_pos)
96012468Sglenn.bergmans@arm.com        return data
96112468Sglenn.bergmans@arm.com
96212468Sglenn.bergmans@arm.com    def __extract_fdt_string(self, prop_string_pos):
96312468Sglenn.bergmans@arm.com        """Extract string from string pool"""
96412468Sglenn.bergmans@arm.com        data = ''
96512468Sglenn.bergmans@arm.com        pos = self.infile.tell()
96612468Sglenn.bergmans@arm.com        self.infile.seek(self.fdt_header['off_dt_strings']+prop_string_pos)
96712468Sglenn.bergmans@arm.com        while True:
96812468Sglenn.bergmans@arm.com            byte = self.infile.read(1)
96912468Sglenn.bergmans@arm.com            if ord(byte) == 0:
97012468Sglenn.bergmans@arm.com                break
97112468Sglenn.bergmans@arm.com            data += byte.decode('ascii')
97212468Sglenn.bergmans@arm.com        self.infile.seek(pos)
97312468Sglenn.bergmans@arm.com        return data
97412468Sglenn.bergmans@arm.com
97512468Sglenn.bergmans@arm.com    def __extract_fdt_prop(self):
97612468Sglenn.bergmans@arm.com        """Extract property"""
97712468Sglenn.bergmans@arm.com        prop = Struct(self.__fdt_dt_prop_format)
97812468Sglenn.bergmans@arm.com        pos = self.infile.tell()
97912468Sglenn.bergmans@arm.com        data = self.infile.read(prop.size)
98012468Sglenn.bergmans@arm.com        (prop_size, prop_string_pos,) = prop.unpack_from(data)
98112468Sglenn.bergmans@arm.com
98212468Sglenn.bergmans@arm.com        prop_start = pos + prop.size
98312468Sglenn.bergmans@arm.com        if self.fdt_header['version'] < 16 and prop_size >= 8:
98412468Sglenn.bergmans@arm.com            prop_start = (((prop_start) + ((8) - 1)) & ~((8) - 1))
98512468Sglenn.bergmans@arm.com
98612468Sglenn.bergmans@arm.com        self.infile.seek(prop_start)
98712468Sglenn.bergmans@arm.com        value = self.infile.read(prop_size)
98812468Sglenn.bergmans@arm.com
98912468Sglenn.bergmans@arm.com        align_pos = self.infile.tell()
99012468Sglenn.bergmans@arm.com        align_pos = (((align_pos) + ((4) - 1)) & ~((4) - 1))
99112468Sglenn.bergmans@arm.com        self.infile.seek(align_pos)
99212468Sglenn.bergmans@arm.com
99312468Sglenn.bergmans@arm.com        return (self.__extract_fdt_string(prop_string_pos), value)
99412468Sglenn.bergmans@arm.com
99512468Sglenn.bergmans@arm.com    def __extract_fdt_dt(self):
99612468Sglenn.bergmans@arm.com        """Extract tags"""
99712468Sglenn.bergmans@arm.com        cell = Struct(self.__fdt_dt_cell_format)
99812468Sglenn.bergmans@arm.com        tags = []
99912468Sglenn.bergmans@arm.com        self.infile.seek(self.fdt_header['off_dt_struct'])
100012468Sglenn.bergmans@arm.com        while True:
100112468Sglenn.bergmans@arm.com            data = self.infile.read(cell.size)
100212468Sglenn.bergmans@arm.com            if len(data) < cell.size:
100312468Sglenn.bergmans@arm.com                break
100412468Sglenn.bergmans@arm.com            tag, = cell.unpack_from(data)
100512468Sglenn.bergmans@arm.com            # print "*** %s" % self.__fdt_dt_tag_name.get(tag, '')
100612468Sglenn.bergmans@arm.com            if self.__fdt_dt_tag_name.get(tag, '') in 'node_begin':
100712468Sglenn.bergmans@arm.com                name = self.__extract_fdt_nodename()
100812468Sglenn.bergmans@arm.com                if len(name) == 0:
100912468Sglenn.bergmans@arm.com                    name = '/'
101012468Sglenn.bergmans@arm.com                tags.append((tag, name))
101112468Sglenn.bergmans@arm.com            elif self.__fdt_dt_tag_name.get(tag, '') in ('node_end', 'nop'):
101212468Sglenn.bergmans@arm.com                tags.append((tag, ''))
101312468Sglenn.bergmans@arm.com            elif self.__fdt_dt_tag_name.get(tag, '') in 'end':
101412468Sglenn.bergmans@arm.com                tags.append((tag, ''))
101512468Sglenn.bergmans@arm.com                break
101612468Sglenn.bergmans@arm.com            elif self.__fdt_dt_tag_name.get(tag, '') in 'prop':
101712468Sglenn.bergmans@arm.com                propdata = self.__extract_fdt_prop()
101812468Sglenn.bergmans@arm.com                tags.append((tag, propdata))
101912468Sglenn.bergmans@arm.com            else:
102012468Sglenn.bergmans@arm.com                print("Unknown Tag %d" % tag)
102112468Sglenn.bergmans@arm.com        return tags
102212468Sglenn.bergmans@arm.com
102312468Sglenn.bergmans@arm.com    def __init__(self, infile):
102412468Sglenn.bergmans@arm.com        """Init with file input"""
102512468Sglenn.bergmans@arm.com        self.infile = infile
102612468Sglenn.bergmans@arm.com        self.fdt_header = self.__extract_fdt_header()
102712468Sglenn.bergmans@arm.com        if self.fdt_header['magic'] != FDT_MAGIC:
102812468Sglenn.bergmans@arm.com            raise Exception('Invalid Magic')
102912468Sglenn.bergmans@arm.com        if self.fdt_header['version'] > FDT_MAX_VERSION:
103012468Sglenn.bergmans@arm.com            raise Exception('Invalid Version %d' % self.fdt_header['version'])
103112468Sglenn.bergmans@arm.com        if self.fdt_header['last_comp_version'] > FDT_MAX_VERSION-1:
103212468Sglenn.bergmans@arm.com            raise Exception('Invalid last compatible Version %d' %
103312468Sglenn.bergmans@arm.com                            self.fdt_header['last_comp_version'])
103412468Sglenn.bergmans@arm.com        self.fdt_reserve_entries = self.__extract_fdt_reserve_entries()
103512468Sglenn.bergmans@arm.com        self.fdt_dt_tags = self.__extract_fdt_dt()
103612468Sglenn.bergmans@arm.com
103712468Sglenn.bergmans@arm.com    def __to_nodes(self):
103812468Sglenn.bergmans@arm.com        """Represent fdt as Node and properties structure
103912468Sglenn.bergmans@arm.com           Returns a set with the pre-node Nops, the Root Node,
104012468Sglenn.bergmans@arm.com            and the post-node Nops.
104112468Sglenn.bergmans@arm.com        """
104212468Sglenn.bergmans@arm.com        prenops = []
104312468Sglenn.bergmans@arm.com        postnops = []
104412468Sglenn.bergmans@arm.com        rootnode = None
104512468Sglenn.bergmans@arm.com        curnode = None
104612468Sglenn.bergmans@arm.com        for tag in self.fdt_dt_tags:
104712468Sglenn.bergmans@arm.com            if self.__fdt_dt_tag_name.get(tag[0], '') in 'node_begin':
104812468Sglenn.bergmans@arm.com                newnode = FdtNode(tag[1])
104912468Sglenn.bergmans@arm.com                if rootnode is None:
105012468Sglenn.bergmans@arm.com                    rootnode = newnode
105112468Sglenn.bergmans@arm.com                if curnode is not None:
105212468Sglenn.bergmans@arm.com                    curnode.add_subnode(newnode)
105312468Sglenn.bergmans@arm.com                    newnode.set_parent_node(curnode)
105412468Sglenn.bergmans@arm.com                curnode = newnode
105512468Sglenn.bergmans@arm.com            elif self.__fdt_dt_tag_name.get(tag[0], '') in 'node_end':
105612468Sglenn.bergmans@arm.com                if curnode is not None:
105712468Sglenn.bergmans@arm.com                    curnode = curnode.get_parent_node()
105812468Sglenn.bergmans@arm.com            elif self.__fdt_dt_tag_name.get(tag[0], '') in 'nop':
105912468Sglenn.bergmans@arm.com                if curnode is not None:
106012468Sglenn.bergmans@arm.com                    curnode.add_subnode(FdtNop())
106112468Sglenn.bergmans@arm.com                elif rootnode is not None:
106212468Sglenn.bergmans@arm.com                    postnops.append(FdtNop())
106312468Sglenn.bergmans@arm.com                else:
106412468Sglenn.bergmans@arm.com                    prenops.append(FdtNop())
106512468Sglenn.bergmans@arm.com            elif self.__fdt_dt_tag_name.get(tag[0], '') in 'prop':
106612468Sglenn.bergmans@arm.com                if curnode is not None:
106712468Sglenn.bergmans@arm.com                    curnode.add_raw_attribute(tag[1][0], tag[1][1])
106812468Sglenn.bergmans@arm.com            elif self.__fdt_dt_tag_name.get(tag[0], '') in 'end':
106912468Sglenn.bergmans@arm.com                continue
107012468Sglenn.bergmans@arm.com        return (prenops, rootnode, postnops)
107112468Sglenn.bergmans@arm.com
107212468Sglenn.bergmans@arm.com    def to_fdt(self):
107312468Sglenn.bergmans@arm.com        """Create a fdt object
107412468Sglenn.bergmans@arm.com            Returns a Fdt object
107512468Sglenn.bergmans@arm.com        """
107612468Sglenn.bergmans@arm.com        if self.fdt_header['version'] >= 2:
107712468Sglenn.bergmans@arm.com            boot_cpuid_phys = self.fdt_header['boot_cpuid_phys']
107812468Sglenn.bergmans@arm.com        else:
107912468Sglenn.bergmans@arm.com            boot_cpuid_phys = 0
108012468Sglenn.bergmans@arm.com        fdt = Fdt(version=self.fdt_header['version'],
108112468Sglenn.bergmans@arm.com                  last_comp_version=self.fdt_header['last_comp_version'],
108212468Sglenn.bergmans@arm.com                  boot_cpuid_phys=boot_cpuid_phys)
108312468Sglenn.bergmans@arm.com        (prenops, rootnode, postnops) = self.__to_nodes()
108412468Sglenn.bergmans@arm.com        fdt.add_rootnode(rootnode, prenops=prenops, postnops=postnops)
108512468Sglenn.bergmans@arm.com        fdt.add_reserve_entries(self.fdt_reserve_entries)
108612468Sglenn.bergmans@arm.com        return fdt
1087