X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=tools%2Fdtoc%2Fdtb_platdata.py;h=d86651b9aa9a076eea03b7882c628e7cc605c040;hb=86290ce40e76ad2e09da096cc7686cdc86756ee1;hp=94db274c098c765ed98d612e7d008704c99a63fb;hpb=7581c01a159ce04101798a39c04b5fa37ac718d2;p=people%2Fms%2Fu-boot.git diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 94db274c09..d86651b9aa 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -6,7 +6,14 @@ # SPDX-License-Identifier: GPL-2.0+ # +"""Device tree to platform data class + +This supports converting device tree data to C structures definitions and +static data. +""" + import copy +import sys import fdt import fdt_util @@ -31,12 +38,12 @@ TYPE_NAMES = { fdt.TYPE_BYTE: 'unsigned char', fdt.TYPE_STRING: 'const char *', fdt.TYPE_BOOL: 'bool', -}; +} STRUCT_PREFIX = 'dtd_' VAL_PREFIX = 'dtv_' -def Conv_name_to_c(name): +def conv_name_to_c(name): """Convert a device-tree name to a C identifier Args: @@ -44,19 +51,28 @@ def Conv_name_to_c(name): Return: String containing the C version of this name """ - str = name.replace('@', '_at_') - str = str.replace('-', '_') - str = str.replace(',', '_') - str = str.replace('.', '_') - str = str.replace('/', '__') - return str - -def TabTo(num_tabs, str): - if len(str) >= num_tabs * 8: - return str + ' ' - return str + '\t' * (num_tabs - len(str) // 8) - -class DtbPlatdata: + new = name.replace('@', '_at_') + new = new.replace('-', '_') + new = new.replace(',', '_') + new = new.replace('.', '_') + return new + +def tab_to(num_tabs, line): + """Append tabs to a line of text to reach a tab stop. + + Args: + num_tabs: Tab stop to obtain (0 = column 0, 1 = column 8, etc.) + line: Line of text to append to + + Returns: + line with the correct number of tabs appeneded. If the line already + extends past that tab stop then a single space is appended. + """ + if len(line) >= num_tabs * 8: + return line + ' ' + return line + '\t' * (num_tabs - len(line) // 8) + +class DtbPlatdata(object): """Provide a means to convert device tree binary data to platform data The output of this process is C structures which can be used in space- @@ -64,28 +80,29 @@ class DtbPlatdata: code is not affordable. Properties: - fdt: Fdt object, referencing the device tree + _fdt: Fdt object, referencing the device tree _dtb_fname: Filename of the input device tree binary file _valid_nodes: A list of Node object with compatible strings _options: Command-line options - _phandle_node: A dict of nodes indexed by phandle number (1, 2...) + _phandle_nodes: A dict of nodes indexed by phandle number (1, 2...) _outfile: The current output file (sys.stdout or a real file) _lines: Stashed list of output lines for outputting in the future - _phandle_node: A dict of Nodes indexed by phandle (an integer) + _phandle_nodes: A dict of Nodes indexed by phandle (an integer) """ def __init__(self, dtb_fname, options): + self._fdt = None self._dtb_fname = dtb_fname self._valid_nodes = None self._options = options - self._phandle_node = {} + self._phandle_nodes = {} self._outfile = None self._lines = [] self._aliases = {} - def SetupOutput(self, fname): + def setup_output(self, fname): """Set up the output destination - Once this is done, future calls to self.Out() will output to this + Once this is done, future calls to self.out() will output to this file. Args: @@ -96,23 +113,23 @@ class DtbPlatdata: else: self._outfile = open(fname, 'w') - def Out(self, str): + def out(self, line): """Output a string to the output file Args: - str: String to output + line: String to output """ - self._outfile.write(str) + self._outfile.write(line) - def Buf(self, str): + def buf(self, line): """Buffer up a string to send later Args: - str: String to add to our 'buffer' list + line: String to add to our 'buffer' list """ - self._lines.append(str) + self._lines.append(line) - def GetBuf(self): + def get_buf(self): """Get the contents of the output buffer, and clear it Returns: @@ -122,7 +139,8 @@ class DtbPlatdata: self._lines = [] return lines - def GetValue(self, type, value): + @staticmethod + def get_value(ftype, value): """Get a value as a C expression For integers this returns a byte-swapped (little-endian) hex string @@ -134,16 +152,17 @@ class DtbPlatdata: type: Data type (fdt_util) value: Data value, as a string of bytes """ - if type == fdt.TYPE_INT: + if ftype == fdt.TYPE_INT: return '%#x' % fdt_util.fdt32_to_cpu(value) - elif type == fdt.TYPE_BYTE: + elif ftype == fdt.TYPE_BYTE: return '%#x' % ord(value[0]) - elif type == fdt.TYPE_STRING: + elif ftype == fdt.TYPE_STRING: return '"%s"' % value - elif type == fdt.TYPE_BOOL: + elif ftype == fdt.TYPE_BOOL: return 'true' - def GetCompatName(self, node): + @staticmethod + def get_compat_name(node): """Get a node's first compatible string as a C identifier Args: @@ -153,59 +172,55 @@ class DtbPlatdata: """ compat = node.props['compatible'].value aliases = [] - if type(compat) == list: + if isinstance(compat, list): compat, aliases = compat[0], compat[1:] - return Conv_name_to_c(compat), [Conv_name_to_c(a) for a in aliases] + return conv_name_to_c(compat), [conv_name_to_c(a) for a in aliases] - def ScanDtb(self): + def scan_dtb(self): """Scan the device tree to obtain a tree of notes and properties - Once this is done, self.fdt.GetRoot() can be called to obtain the + Once this is done, self._fdt.GetRoot() can be called to obtain the device tree root node, and progress from there. """ - self.fdt = fdt.FdtScan(self._dtb_fname) + self._fdt = fdt.FdtScan(self._dtb_fname) + + def scan_node(self, root): + """Scan a node and subnodes to build a tree of node and phandle info + + This adds each node to self._valid_nodes and each phandle to + self._phandle_nodes. - def ScanNode(self, root): + Args: + root: Root node for scan + """ for node in root.subnodes: if 'compatible' in node.props: status = node.props.get('status') if (not self._options.include_disabled and not status or - status.value != 'disabled'): + status.value != 'disabled'): self._valid_nodes.append(node) phandle_prop = node.props.get('phandle') if phandle_prop: phandle = phandle_prop.GetPhandle() - self._phandle_node[phandle] = node + self._phandle_nodes[phandle] = node # recurse to handle any subnodes - self.ScanNode(node); + self.scan_node(node) - def ScanTree(self): + def scan_tree(self): """Scan the device tree for useful information This fills in the following properties: - _phandle_node: A dict of Nodes indexed by phandle (an integer) + _phandle_nodes: A dict of Nodes indexed by phandle (an integer) _valid_nodes: A list of nodes we wish to consider include in the platform data """ - self._phandle_node = {} + self._phandle_nodes = {} self._valid_nodes = [] - return self.ScanNode(self.fdt.GetRoot()); - - for node in self.fdt.GetRoot().subnodes: - if 'compatible' in node.props: - status = node.props.get('status') - if (not self._options.include_disabled and not status or - status.value != 'disabled'): - node_list.append(node) - phandle_prop = node.props.get('phandle') - if phandle_prop: - phandle = phandle_prop.GetPhandle() - self._phandle_node[phandle] = node - - self._valid_nodes = node_list + return self.scan_node(self._fdt.GetRoot()) - def IsPhandle(self, prop): + @staticmethod + def is_phandle(prop): """Check if a node contains phandles We have no reliable way of detecting whether a node uses a phandle @@ -220,7 +235,7 @@ class DtbPlatdata: return True return False - def ScanStructs(self): + def scan_structs(self): """Scan the device tree building up the C structures we will use. Build a dict keyed by C struct name containing a dict of Prop @@ -233,7 +248,7 @@ class DtbPlatdata: """ structs = {} for node in self._valid_nodes: - node_name, _ = self.GetCompatName(node) + node_name, _ = self.get_compat_name(node) fields = {} # Get a list of all the valid properties in this node. @@ -257,20 +272,20 @@ class DtbPlatdata: upto = 0 for node in self._valid_nodes: - node_name, _ = self.GetCompatName(node) + node_name, _ = self.get_compat_name(node) struct = structs[node_name] for name, prop in node.props.items(): if name not in PROP_IGNORE_LIST and name[0] != '#': prop.Widen(struct[name]) upto += 1 - struct_name, aliases = self.GetCompatName(node) + struct_name, aliases = self.get_compat_name(node) for alias in aliases: self._aliases[alias] = struct_name return structs - def ScanPhandles(self): + def scan_phandles(self): """Figure out what phandles each node uses We need to be careful when outputing nodes that use phandles since @@ -286,104 +301,101 @@ class DtbPlatdata: for pname, prop in node.props.items(): if pname in PROP_IGNORE_LIST or pname[0] == '#': continue - if type(prop.value) == list: - if self.IsPhandle(prop): + if isinstance(prop.value, list): + if self.is_phandle(prop): # Process the list as pairs of (phandle, id) - it = iter(prop.value) - for phandle_cell, id_cell in zip(it, it): + value_it = iter(prop.value) + for phandle_cell, _ in zip(value_it, value_it): phandle = fdt_util.fdt32_to_cpu(phandle_cell) - id = fdt_util.fdt32_to_cpu(id_cell) - target_node = self._phandle_node[phandle] + target_node = self._phandle_nodes[phandle] node.phandles.add(target_node) - def GenerateStructs(self, structs): + def generate_structs(self, structs): """Generate struct defintions for the platform data This writes out the body of a header file consisting of structure definitions for node in self._valid_nodes. See the documentation in README.of-plat for more information. """ - self.Out('#include \n') - self.Out('#include \n') + self.out('#include \n') + self.out('#include \n') # Output the struct definition for name in sorted(structs): - self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name)); + self.out('struct %s%s {\n' % (STRUCT_PREFIX, name)) for pname in sorted(structs[name]): prop = structs[name][pname] - if self.IsPhandle(prop): + if self.is_phandle(prop): # For phandles, include a reference to the target - self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'), - Conv_name_to_c(prop.name), + self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'), + conv_name_to_c(prop.name), len(prop.value) / 2)) else: ptype = TYPE_NAMES[prop.type] - self.Out('\t%s%s' % (TabTo(2, ptype), - Conv_name_to_c(prop.name))) - if type(prop.value) == list: - self.Out('[%d]' % len(prop.value)) - self.Out(';\n') - self.Out('};\n') + self.out('\t%s%s' % (tab_to(2, ptype), + conv_name_to_c(prop.name))) + if isinstance(prop.value, list): + self.out('[%d]' % len(prop.value)) + self.out(';\n') + self.out('};\n') for alias, struct_name in self._aliases.iteritems(): - self.Out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias, + self.out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias, STRUCT_PREFIX, struct_name)) - def OutputNode(self, node): + def output_node(self, node): """Output the C code for a node Args: node: node to output """ - struct_name, _ = self.GetCompatName(node) - var_name = Conv_name_to_c(node.name) - self.Buf('static struct %s%s %s%s = {\n' % - (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) + struct_name, _ = self.get_compat_name(node) + var_name = conv_name_to_c(node.name) + self.buf('static struct %s%s %s%s = {\n' % + (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) for pname, prop in node.props.items(): if pname in PROP_IGNORE_LIST or pname[0] == '#': continue - ptype = TYPE_NAMES[prop.type] - member_name = Conv_name_to_c(prop.name) - self.Buf('\t%s= ' % TabTo(3, '.' + member_name)) + member_name = conv_name_to_c(prop.name) + self.buf('\t%s= ' % tab_to(3, '.' + member_name)) # Special handling for lists - if type(prop.value) == list: - self.Buf('{') + if isinstance(prop.value, list): + self.buf('{') vals = [] # For phandles, output a reference to the platform data # of the target node. - if self.IsPhandle(prop): + if self.is_phandle(prop): # Process the list as pairs of (phandle, id) - it = iter(prop.value) - for phandle_cell, id_cell in zip(it, it): + value_it = iter(prop.value) + for phandle_cell, id_cell in zip(value_it, value_it): phandle = fdt_util.fdt32_to_cpu(phandle_cell) - id = fdt_util.fdt32_to_cpu(id_cell) - target_node = self._phandle_node[phandle] - name = Conv_name_to_c(target_node.name) - vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id)) + id_num = fdt_util.fdt32_to_cpu(id_cell) + target_node = self._phandle_nodes[phandle] + name = conv_name_to_c(target_node.name) + vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num)) else: for val in prop.value: - vals.append(self.GetValue(prop.type, val)) - self.Buf(', '.join(vals)) - self.Buf('}') + vals.append(self.get_value(prop.type, val)) + self.buf(', '.join(vals)) + self.buf('}') else: - self.Buf(self.GetValue(prop.type, prop.value)) - self.Buf(',\n') - self.Buf('};\n') + self.buf(self.get_value(prop.type, prop.value)) + self.buf(',\n') + self.buf('};\n') # Add a device declaration - self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name) - self.Buf('\t.name\t\t= "%s",\n' % struct_name) - self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) - self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' % - (VAL_PREFIX, var_name)) - self.Buf('};\n') - self.Buf('\n') + self.buf('U_BOOT_DEVICE(%s) = {\n' % var_name) + self.buf('\t.name\t\t= "%s",\n' % struct_name) + self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) + self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name)) + self.buf('};\n') + self.buf('\n') - self.Out(''.join(self.GetBuf())) + self.out(''.join(self.get_buf())) - def GenerateTables(self): + def generate_tables(self): """Generate device defintions for the platform data This writes out C platform data initialisation data and @@ -393,10 +405,10 @@ class DtbPlatdata: See the documentation in doc/driver-model/of-plat.txt for more information. """ - self.Out('#include \n') - self.Out('#include \n') - self.Out('#include \n') - self.Out('\n') + self.out('#include \n') + self.out('#include \n') + self.out('#include \n') + self.out('\n') nodes_to_output = list(self._valid_nodes) # Keep outputing nodes until there is none left @@ -405,7 +417,7 @@ class DtbPlatdata: # Output all the node's dependencies first for req_node in node.phandles: if req_node in nodes_to_output: - self.OutputNode(req_node) + self.output_node(req_node) nodes_to_output.remove(req_node) - self.OutputNode(node) + self.output_node(node) nodes_to_output.remove(node)