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