dtoc: Fix pylint warnings

Unfortunately I neglected to run pylint on this tool with its initial
submission. Fix the warnings.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2017-06-18 22:08:59 -06:00
parent 7581c01a15
commit 2be282ca01
2 changed files with 142 additions and 129 deletions

View File

@ -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,29 @@ 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
new = name.replace('@', '_at_')
new = new.replace('-', '_')
new = new.replace(',', '_')
new = new.replace('.', '_')
new = new.replace('/', '__')
return new
def TabTo(num_tabs, str):
if len(str) >= num_tabs * 8:
return str + ' '
return str + '\t' * (num_tabs - len(str) // 8)
def tab_to(num_tabs, line):
"""Append tabs to a line of text to reach a tab stop.
class DtbPlatdata:
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 +81,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 +114,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 +140,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 +153,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 +173,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 ScanNode(self, root):
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.
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());
return self.scan_node(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
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 +236,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 +249,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 +273,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 +302,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 <stdbool.h>\n')
self.Out('#include <libfdt.h>\n')
self.out('#include <stdbool.h>\n')
self.out('#include <libfdt.h>\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 +406,10 @@ class DtbPlatdata:
See the documentation in doc/driver-model/of-plat.txt for more
information.
"""
self.Out('#include <common.h>\n')
self.Out('#include <dm.h>\n')
self.Out('#include <dt-structs.h>\n')
self.Out('\n')
self.out('#include <common.h>\n')
self.out('#include <dm.h>\n')
self.out('#include <dt-structs.h>\n')
self.out('\n')
nodes_to_output = list(self._valid_nodes)
# Keep outputing nodes until there is none left
@ -405,7 +418,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)

View File

@ -53,16 +53,16 @@ if not args:
raise ValueError('Please specify a command: struct, platdata')
plat = dtb_platdata.DtbPlatdata(options.dtb_file, options)
plat.ScanDtb()
plat.ScanTree()
plat.SetupOutput(options.output)
structs = plat.ScanStructs()
plat.ScanPhandles()
plat.scan_dtb()
plat.scan_tree()
plat.setup_output(options.output)
structs = plat.scan_structs()
plat.scan_phandles()
for cmd in args[0].split(','):
if cmd == 'struct':
plat.GenerateStructs(structs)
plat.generate_structs(structs)
elif cmd == 'platdata':
plat.GenerateTables()
plat.generate_tables()
else:
raise ValueError("Unknown command '%s': (use: struct, platdata)" % cmd)