1# Copyright (c) 2016 ARM Limited 2# All rights reserved. 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Redistribution and use in source and binary forms, with or without 14# modification, are permitted provided that the following conditions are 15# met: redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer; 17# redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution; 20# neither the name of the copyright holders nor the names of its 21# contributors may be used to endorse or promote products derived from 22# this software without specific prior written permission. 23# 24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35# 36# Author: Glenn Bergmans 37
| 1# Copyright (c) 2016 ARM Limited 2# All rights reserved. 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Redistribution and use in source and binary forms, with or without 14# modification, are permitted provided that the following conditions are 15# met: redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer; 17# redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution; 20# neither the name of the copyright holders nor the names of its 21# contributors may be used to endorse or promote products derived from 22# this software without specific prior written permission. 23# 24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35# 36# Author: Glenn Bergmans 37
|
38from m5.ext.pyfdt import pyfdt 39import re 40import os 41from m5.SimObject import SimObject 42 43class FdtProperty(pyfdt.FdtProperty): 44 """Create a property without values.""" 45 pass 46 47class FdtPropertyWords(pyfdt.FdtPropertyWords): 48 """Create a property with word (32-bit unsigned) values.""" 49 def __init__(self, name, words): 50 if type(words) != list: 51 words = [words] 52 # Make sure all values are ints (use automatic base detection if the 53 # type is str) 54 words = [long(w, base=0) if type(w) == str else long(w) for w in words] 55 super(FdtPropertyWords, self).__init__(name, words) 56 57class FdtPropertyStrings(pyfdt.FdtPropertyStrings): 58 """Create a property with string values.""" 59 60 def __init__(self, name, strings): 61 if type(strings) == str: 62 strings = [strings] 63 strings = [str(string) for string in strings] # Make all values strings 64 super(FdtPropertyStrings, self).__init__(name, strings) 65 66class FdtPropertyBytes(pyfdt.FdtPropertyBytes): 67 """Create a property with integer (8-bit signed) values.""" 68 69 def __init__(self, name, values): 70 if type(values) != list: 71 values = [values] 72 # Make sure all values are ints (use automatic base detection if the 73 # type is str) 74 values = [int(v, base=0) 75 if isinstance(v, str) else int(v) for v in values] 76 super(FdtPropertyBytes, self).__init__(name, values) 77 78class FdtState(object): 79 """Class for maintaining state while recursively generating a flattened 80 device tree. The state tracks address, size and CPU address cell sizes, and 81 maintains a dictionary of allocated phandles.""" 82 83 phandle_counter = 0 84 phandles = dict() 85 86 def __init__(self, addr_cells, size_cells, cpu_cells): 87 """Instantiate values of this state. The state can only be initialized 88 once.""" 89 90 self.addr_cells = addr_cells 91 self.size_cells = size_cells 92 self.cpu_cells = cpu_cells 93 94 def phandle(self, obj): 95 """Return a unique phandle number for a key. The key can be a SimObject 96 or any value that is castable to a string. If the phandle doesn't exist 97 a new one is created, otherwise the existing one is returned.""" 98 99 if isinstance(obj, SimObject): 100 key = str(id(obj)) 101 else: 102 try: 103 key = str(obj) 104 except ValueError: 105 raise ValueError('Phandle keys must be castable to str') 106 107 if not key in FdtState.phandles: 108 FdtState.phandle_counter += 1 109 110 return FdtState.phandles.setdefault(key, FdtState.phandle_counter) 111 112 def resetPhandles(self): 113 FdtState.phandle_counter = 0 114 FdtState.phandles = dict() 115 116 def int_to_cells(self, value, cells): 117 """Helper function for: generates a list of 32 bit cells from an int, 118 used to split up addresses in appropriate 32 bit chunks.""" 119 value = long(value) 120 121 if (value >> (32 * cells)) != 0: 122 fatal("Value %d doesn't fit in %d cells" % (value, cells)) 123 124 return [(value >> 32*(x-1)) & 0xFFFFFFFF for x in range(cells, 0, -1)] 125 126 def addrCells(self, addr): 127 """Format an integer type according to the address_cells value of this 128 state.""" 129 return self.int_to_cells(addr, self.addr_cells) 130 131 def CPUAddrCells(self, addr): 132 """Format an integer type according to the cpu_cells value of this 133 state.""" 134 return self.int_to_cells(addr, self.cpu_cells) 135 136 def sizeCells(self, size): 137 """Format an integer type according to the size_cells value of this 138 state.""" 139 return self.int_to_cells(size, self.size_cells) 140 141 def addrCellsProperty(self): 142 """Return an #address-cells property with the value of this state.""" 143 return FdtPropertyWords("#address-cells", self.addr_cells) 144 145 def sizeCellsProperty(self): 146 """Return an #size-cells property with the value of this state.""" 147 return FdtPropertyWords("#size-cells", self.size_cells) 148 149 def CPUCellsProperty(self): 150 """Return an #address-cells property for cpu nodes with the value 151 of this state.""" 152 return FdtPropertyWords("#address-cells", self.cpu_cells) 153 154class FdtNop(pyfdt.FdtNop): 155 """Create an empty node.""" 156 pass 157 158class FdtNode(pyfdt.FdtNode): 159 def __init__(self, name, obj=None): 160 """Create a new node and immediately set the phandle property, if obj 161 is supplied""" 162 super(FdtNode, self).__init__(name) 163 if obj != None: 164 self.appendPhandle(obj) 165 166 def append(self, subnodes): 167 """Change the behavior of the normal append to override if a node with 168 the same name already exists or merge if the name exists and is a node 169 type. Can also take a list of subnodes, that each get appended.""" 170 if not hasattr(subnodes, '__iter__'): 171 subnodes = [subnodes] 172 173 for subnode in subnodes: 174 try: 175 if not issubclass(type(subnode), pyfdt.FdtNop): 176 index = self.index(subnode.name) 177 item = self.pop(index) 178 else: 179 item = None 180 except ValueError: 181 item = None 182 183 if isinstance(item, pyfdt.FdtNode) and \ 184 isinstance(subnode, pyfdt.FdtNode): 185 item.merge(subnode) 186 subnode = item 187 188 super(FdtNode, self).append(subnode) 189 190 def appendList(self, subnode_list): 191 """Append all properties/nodes in the iterable.""" 192 for subnode in subnode_list: 193 self.append(subnode) 194 195 def appendCompatible(self, compatible): 196 """Append a compatible property with the supplied compatibility 197 strings.""" 198 if isinstance(compatible, str): 199 compatible = [compatible] 200 self.append(FdtPropertyStrings('compatible', compatible)) 201 202 def appendPhandle(self, obj): 203 """Append a phandle property to this node with the phandle of the 204 supplied object.""" 205 # Create a bogus state because we only need the Phandle dictionary 206 state = FdtState(addr_cells=1, size_cells=1, cpu_cells=1) 207 208 phandle = state.phandle(obj) 209 self.append(FdtPropertyWords("phandle", [phandle])) 210 211class Fdt(pyfdt.Fdt): 212 def sortNodes(self, node): 213 """Move all properties to the beginning and subnodes to the end 214 while maintaining the order of the subnodes. DTB files require the 215 properties to go before the nodes, but the PyFdt doesn't account for 216 defining nodes and properties in a random order.""" 217 properties = FdtNode(node.name) 218 subnodes = FdtNode(node.name) 219 220 while len(node): 221 subnode = node.pop(0) 222 if issubclass(type(subnode), pyfdt.FdtNode): 223 subnode = self.sortNodes(subnode) 224 subnodes.append(subnode) 225 else: 226 properties.append(subnode) 227 228 properties.merge(subnodes) 229 230 return properties 231 232 def add_rootnode(self, rootnode, prenops=None, postnops=None): 233 """First sort the device tree, so that properties are before nodes.""" 234 rootnode = self.sortNodes(rootnode) 235 super(Fdt, self).add_rootnode(rootnode, prenops, postnops) 236 237 def writeDtbFile(self, filename): 238 """Convert the device tree to DTB and write to a file.""" 239 filename = os.path.realpath(filename) 240 try: 241 with open(filename, 'wb') as f: 242 f.write(self.to_dtb()) 243 return filename 244 except IOError: 245 raise RuntimeError("Failed to open DTB output file") 246 247 def writeDtsFile(self, filename): 248 """Convert the device tree to DTS and write to a file.""" 249 filename = os.path.realpath(filename) 250 try: 251 with open(filename, 'w') as f: 252 f.write(self.to_dts()) 253 return filename 254 except IOError: 255 raise RuntimeError("Failed to open DTS output file")
| 42from m5.ext.pyfdt import pyfdt 43import re 44import os 45from m5.SimObject import SimObject 46 47class FdtProperty(pyfdt.FdtProperty): 48 """Create a property without values.""" 49 pass 50 51class FdtPropertyWords(pyfdt.FdtPropertyWords): 52 """Create a property with word (32-bit unsigned) values.""" 53 def __init__(self, name, words): 54 if type(words) != list: 55 words = [words] 56 # Make sure all values are ints (use automatic base detection if the 57 # type is str) 58 words = [long(w, base=0) if type(w) == str else long(w) for w in words] 59 super(FdtPropertyWords, self).__init__(name, words) 60 61class FdtPropertyStrings(pyfdt.FdtPropertyStrings): 62 """Create a property with string values.""" 63 64 def __init__(self, name, strings): 65 if type(strings) == str: 66 strings = [strings] 67 strings = [str(string) for string in strings] # Make all values strings 68 super(FdtPropertyStrings, self).__init__(name, strings) 69 70class FdtPropertyBytes(pyfdt.FdtPropertyBytes): 71 """Create a property with integer (8-bit signed) values.""" 72 73 def __init__(self, name, values): 74 if type(values) != list: 75 values = [values] 76 # Make sure all values are ints (use automatic base detection if the 77 # type is str) 78 values = [int(v, base=0) 79 if isinstance(v, str) else int(v) for v in values] 80 super(FdtPropertyBytes, self).__init__(name, values) 81 82class FdtState(object): 83 """Class for maintaining state while recursively generating a flattened 84 device tree. The state tracks address, size and CPU address cell sizes, and 85 maintains a dictionary of allocated phandles.""" 86 87 phandle_counter = 0 88 phandles = dict() 89 90 def __init__(self, addr_cells, size_cells, cpu_cells): 91 """Instantiate values of this state. The state can only be initialized 92 once.""" 93 94 self.addr_cells = addr_cells 95 self.size_cells = size_cells 96 self.cpu_cells = cpu_cells 97 98 def phandle(self, obj): 99 """Return a unique phandle number for a key. The key can be a SimObject 100 or any value that is castable to a string. If the phandle doesn't exist 101 a new one is created, otherwise the existing one is returned.""" 102 103 if isinstance(obj, SimObject): 104 key = str(id(obj)) 105 else: 106 try: 107 key = str(obj) 108 except ValueError: 109 raise ValueError('Phandle keys must be castable to str') 110 111 if not key in FdtState.phandles: 112 FdtState.phandle_counter += 1 113 114 return FdtState.phandles.setdefault(key, FdtState.phandle_counter) 115 116 def resetPhandles(self): 117 FdtState.phandle_counter = 0 118 FdtState.phandles = dict() 119 120 def int_to_cells(self, value, cells): 121 """Helper function for: generates a list of 32 bit cells from an int, 122 used to split up addresses in appropriate 32 bit chunks.""" 123 value = long(value) 124 125 if (value >> (32 * cells)) != 0: 126 fatal("Value %d doesn't fit in %d cells" % (value, cells)) 127 128 return [(value >> 32*(x-1)) & 0xFFFFFFFF for x in range(cells, 0, -1)] 129 130 def addrCells(self, addr): 131 """Format an integer type according to the address_cells value of this 132 state.""" 133 return self.int_to_cells(addr, self.addr_cells) 134 135 def CPUAddrCells(self, addr): 136 """Format an integer type according to the cpu_cells value of this 137 state.""" 138 return self.int_to_cells(addr, self.cpu_cells) 139 140 def sizeCells(self, size): 141 """Format an integer type according to the size_cells value of this 142 state.""" 143 return self.int_to_cells(size, self.size_cells) 144 145 def addrCellsProperty(self): 146 """Return an #address-cells property with the value of this state.""" 147 return FdtPropertyWords("#address-cells", self.addr_cells) 148 149 def sizeCellsProperty(self): 150 """Return an #size-cells property with the value of this state.""" 151 return FdtPropertyWords("#size-cells", self.size_cells) 152 153 def CPUCellsProperty(self): 154 """Return an #address-cells property for cpu nodes with the value 155 of this state.""" 156 return FdtPropertyWords("#address-cells", self.cpu_cells) 157 158class FdtNop(pyfdt.FdtNop): 159 """Create an empty node.""" 160 pass 161 162class FdtNode(pyfdt.FdtNode): 163 def __init__(self, name, obj=None): 164 """Create a new node and immediately set the phandle property, if obj 165 is supplied""" 166 super(FdtNode, self).__init__(name) 167 if obj != None: 168 self.appendPhandle(obj) 169 170 def append(self, subnodes): 171 """Change the behavior of the normal append to override if a node with 172 the same name already exists or merge if the name exists and is a node 173 type. Can also take a list of subnodes, that each get appended.""" 174 if not hasattr(subnodes, '__iter__'): 175 subnodes = [subnodes] 176 177 for subnode in subnodes: 178 try: 179 if not issubclass(type(subnode), pyfdt.FdtNop): 180 index = self.index(subnode.name) 181 item = self.pop(index) 182 else: 183 item = None 184 except ValueError: 185 item = None 186 187 if isinstance(item, pyfdt.FdtNode) and \ 188 isinstance(subnode, pyfdt.FdtNode): 189 item.merge(subnode) 190 subnode = item 191 192 super(FdtNode, self).append(subnode) 193 194 def appendList(self, subnode_list): 195 """Append all properties/nodes in the iterable.""" 196 for subnode in subnode_list: 197 self.append(subnode) 198 199 def appendCompatible(self, compatible): 200 """Append a compatible property with the supplied compatibility 201 strings.""" 202 if isinstance(compatible, str): 203 compatible = [compatible] 204 self.append(FdtPropertyStrings('compatible', compatible)) 205 206 def appendPhandle(self, obj): 207 """Append a phandle property to this node with the phandle of the 208 supplied object.""" 209 # Create a bogus state because we only need the Phandle dictionary 210 state = FdtState(addr_cells=1, size_cells=1, cpu_cells=1) 211 212 phandle = state.phandle(obj) 213 self.append(FdtPropertyWords("phandle", [phandle])) 214 215class Fdt(pyfdt.Fdt): 216 def sortNodes(self, node): 217 """Move all properties to the beginning and subnodes to the end 218 while maintaining the order of the subnodes. DTB files require the 219 properties to go before the nodes, but the PyFdt doesn't account for 220 defining nodes and properties in a random order.""" 221 properties = FdtNode(node.name) 222 subnodes = FdtNode(node.name) 223 224 while len(node): 225 subnode = node.pop(0) 226 if issubclass(type(subnode), pyfdt.FdtNode): 227 subnode = self.sortNodes(subnode) 228 subnodes.append(subnode) 229 else: 230 properties.append(subnode) 231 232 properties.merge(subnodes) 233 234 return properties 235 236 def add_rootnode(self, rootnode, prenops=None, postnops=None): 237 """First sort the device tree, so that properties are before nodes.""" 238 rootnode = self.sortNodes(rootnode) 239 super(Fdt, self).add_rootnode(rootnode, prenops, postnops) 240 241 def writeDtbFile(self, filename): 242 """Convert the device tree to DTB and write to a file.""" 243 filename = os.path.realpath(filename) 244 try: 245 with open(filename, 'wb') as f: 246 f.write(self.to_dtb()) 247 return filename 248 except IOError: 249 raise RuntimeError("Failed to open DTB output file") 250 251 def writeDtsFile(self, filename): 252 """Convert the device tree to DTS and write to a file.""" 253 filename = os.path.realpath(filename) 254 try: 255 with open(filename, 'w') as f: 256 f.write(self.to_dts()) 257 return filename 258 except IOError: 259 raise RuntimeError("Failed to open DTS output file")
|