summaryrefslogtreecommitdiff
path: root/tools/dtoc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dtoc')
-rw-r--r--tools/dtoc/dtb_platdata.py10
-rwxr-xr-xtools/dtoc/dtoc.py8
-rw-r--r--tools/dtoc/fdt.py148
-rw-r--r--tools/dtoc/fdt_util.py15
-rw-r--r--tools/dtoc/test_dtoc.py16
-rwxr-xr-xtools/dtoc/test_fdt.py52
6 files changed, 137 insertions, 112 deletions
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 17a3dccb11..037e82c8bb 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -17,6 +17,7 @@ import sys
import fdt
import fdt_util
+import tools
# When we see these properties we ignore them - i.e. do not create a structure member
PROP_IGNORE_LIST = [
@@ -99,7 +100,7 @@ def get_value(ftype, value):
if ftype == fdt.TYPE_INT:
return '%#x' % fdt_util.fdt32_to_cpu(value)
elif ftype == fdt.TYPE_BYTE:
- return '%#x' % ord(value[0])
+ return '%#x' % tools.ToByte(value[0])
elif ftype == fdt.TYPE_STRING:
return '"%s"' % value
elif ftype == fdt.TYPE_BOOL:
@@ -449,7 +450,7 @@ class DtbPlatdata(object):
self.out(';\n')
self.out('};\n')
- for alias, struct_name in self._aliases.iteritems():
+ for alias, struct_name in self._aliases.items():
if alias not in sorted(structs):
self.out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias,
STRUCT_PREFIX, struct_name))
@@ -464,7 +465,8 @@ class DtbPlatdata(object):
var_name = conv_name_to_c(node.name)
self.buf('static const struct %s%s %s%s = {\n' %
(STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
- for pname, prop in node.props.items():
+ for pname in sorted(node.props):
+ prop = node.props[pname]
if pname in PROP_IGNORE_LIST or pname[0] == '#':
continue
member_name = conv_name_to_c(prop.name)
@@ -498,7 +500,7 @@ class DtbPlatdata(object):
vals.append(get_value(prop.type, val))
# Put 8 values per line to avoid very long lines.
- for i in xrange(0, len(vals), 8):
+ for i in range(0, len(vals), 8):
if i:
self.buf(',\n\t\t')
self.buf(', '.join(vals[i:i + 8]))
diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py
index 2277af9bf7..c1a1d3534d 100755
--- a/tools/dtoc/dtoc.py
+++ b/tools/dtoc/dtoc.py
@@ -25,6 +25,8 @@ options. For more information about the use of this options and tool please
see doc/driver-model/of-plat.txt
"""
+from __future__ import print_function
+
from optparse import OptionParser
import os
import sys
@@ -64,11 +66,11 @@ def run_tests(args):
suite = unittest.TestLoader().loadTestsFromTestCase(module)
suite.run(result)
- print result
+ print(result)
for _, err in result.errors:
- print err
+ print(err)
for _, err in result.failures:
- print err
+ print(err)
def RunTestCoverage():
"""Run the tests and check that we get 100% coverage"""
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 9ad72f89ec..d9471c4381 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -11,6 +11,7 @@ import sys
import fdt_util
import libfdt
from libfdt import QUIET_NOTFOUND
+import tools
# This deals with a device tree, presenting it as an assortment of Node and
# Prop objects, representing nodes and properties, respectively. This file
@@ -28,6 +29,66 @@ def CheckErr(errnum, msg):
raise ValueError('Error %d: %s: %s' %
(errnum, libfdt.fdt_strerror(errnum), msg))
+
+def BytesToValue(data):
+ """Converts a string of bytes into a type and value
+
+ Args:
+ A bytes value (which on Python 2 is an alias for str)
+
+ Return:
+ A tuple:
+ Type of data
+ Data, either a single element or a list of elements. Each element
+ is one of:
+ TYPE_STRING: str/bytes value from the property
+ TYPE_INT: a byte-swapped integer stored as a 4-byte str/bytes
+ TYPE_BYTE: a byte stored as a single-byte str/bytes
+ """
+ data = bytes(data)
+ size = len(data)
+ strings = data.split(b'\0')
+ is_string = True
+ count = len(strings) - 1
+ if count > 0 and not len(strings[-1]):
+ for string in strings[:-1]:
+ if not string:
+ is_string = False
+ break
+ for ch in string:
+ # Handle Python 2 treating bytes as str
+ if type(ch) == str:
+ ch = ord(ch)
+ if ch < 32 or ch > 127:
+ is_string = False
+ break
+ else:
+ is_string = False
+ if is_string:
+ if count == 1:
+ if sys.version_info[0] >= 3: # pragma: no cover
+ return TYPE_STRING, strings[0].decode()
+ else:
+ return TYPE_STRING, strings[0]
+ else:
+ if sys.version_info[0] >= 3: # pragma: no cover
+ return TYPE_STRING, [s.decode() for s in strings[:-1]]
+ else:
+ return TYPE_STRING, strings[:-1]
+ if size % 4:
+ if size == 1:
+ return TYPE_BYTE, tools.ToChar(data[0])
+ else:
+ return TYPE_BYTE, [tools.ToChar(ch) for ch in list(data)]
+ val = []
+ for i in range(0, size, 4):
+ val.append(data[i:i + 4])
+ if size == 4:
+ return TYPE_INT, val[0]
+ else:
+ return TYPE_INT, val
+
+
class Prop:
"""A device tree property
@@ -37,18 +98,18 @@ class Prop:
bytes
type: Value type
"""
- def __init__(self, node, offset, name, bytes):
+ def __init__(self, node, offset, name, data):
self._node = node
self._offset = offset
self.name = name
self.value = None
- self.bytes = str(bytes)
+ self.bytes = bytes(data)
self.dirty = False
- if not bytes:
+ if not data:
self.type = TYPE_BOOL
self.value = True
return
- self.type, self.value = self.BytesToValue(bytes)
+ self.type, self.value = BytesToValue(bytes(data))
def RefreshOffset(self, poffset):
self._offset = poffset
@@ -87,55 +148,6 @@ class Prop:
while len(self.value) < len(newprop.value):
self.value.append(val)
- def BytesToValue(self, bytes):
- """Converts a string of bytes into a type and value
-
- Args:
- A string containing bytes
-
- Return:
- A tuple:
- Type of data
- Data, either a single element or a list of elements. Each element
- is one of:
- TYPE_STRING: string value from the property
- TYPE_INT: a byte-swapped integer stored as a 4-byte string
- TYPE_BYTE: a byte stored as a single-byte string
- """
- bytes = str(bytes)
- size = len(bytes)
- strings = bytes.split('\0')
- is_string = True
- count = len(strings) - 1
- if count > 0 and not strings[-1]:
- for string in strings[:-1]:
- if not string:
- is_string = False
- break
- for ch in string:
- if ch < ' ' or ch > '~':
- is_string = False
- break
- else:
- is_string = False
- if is_string:
- if count == 1:
- return TYPE_STRING, strings[0]
- else:
- return TYPE_STRING, strings[:-1]
- if size % 4:
- if size == 1:
- return TYPE_BYTE, bytes[0]
- else:
- return TYPE_BYTE, list(bytes)
- val = []
- for i in range(0, size, 4):
- val.append(bytes[i:i + 4])
- if size == 4:
- return TYPE_INT, val[0]
- else:
- return TYPE_INT, val
-
@classmethod
def GetEmpty(self, type):
"""Get an empty / zero value of the given type
@@ -181,8 +193,8 @@ class Prop:
Args:
bytes: New property value to set
"""
- self.bytes = str(bytes)
- self.type, self.value = self.BytesToValue(bytes)
+ self.bytes = bytes
+ self.type, self.value = BytesToValue(bytes)
self.dirty = True
def Sync(self, auto_resize=False):
@@ -334,7 +346,8 @@ class Node:
Args:
prop_name: Name of property
"""
- self.props[prop_name] = Prop(self, None, prop_name, '\0' * 4)
+ self.props[prop_name] = Prop(self, None, prop_name,
+ tools.GetBytes(0, 4))
def AddEmptyProp(self, prop_name, len):
"""Add a property with a fixed data size, for filling in later
@@ -346,7 +359,7 @@ class Node:
prop_name: Name of property
len: Length of data in property
"""
- value = chr(0) * len
+ value = tools.GetBytes(0, len)
self.props[prop_name] = Prop(self, None, prop_name, value)
def SetInt(self, prop_name, val):
@@ -385,7 +398,9 @@ class Node:
prop_name: Name of property to set
val: String value to set (will be \0-terminated in DT)
"""
- self.props[prop_name].SetData(val + chr(0))
+ if sys.version_info[0] >= 3: # pragma: no cover
+ val = bytes(val, 'utf-8')
+ self.props[prop_name].SetData(val + b'\0')
def AddString(self, prop_name, val):
"""Add a new string property to a node
@@ -397,7 +412,9 @@ class Node:
prop_name: Name of property to add
val: String value of property
"""
- self.props[prop_name] = Prop(self, None, prop_name, val + chr(0))
+ if sys.version_info[0] >= 3: # pragma: no cover
+ val = bytes(val, 'utf-8')
+ self.props[prop_name] = Prop(self, None, prop_name, val + b'\0')
def AddSubnode(self, name):
"""Add a new subnode to the node
@@ -448,8 +465,11 @@ class Node:
# Sync properties now, whose offsets should not have been disturbed.
# We do this after subnodes, since this disturbs the offsets of these
- # properties.
- prop_list = sorted(self.props.values(), key=lambda prop: prop._offset,
+ # properties. Note that new properties will have an offset of None here,
+ # which Python 3 cannot sort against int. So use a large value instead
+ # to ensure that the new properties are added first.
+ prop_list = sorted(self.props.values(),
+ key=lambda prop: prop._offset or 1 << 31,
reverse=True)
for prop in prop_list:
prop.Sync(auto_resize)
@@ -469,7 +489,7 @@ class Fdt:
if self._fname:
self._fname = fdt_util.EnsureCompiled(self._fname)
- with open(self._fname) as fd:
+ with open(self._fname, 'rb') as fd:
self._fdt_obj = libfdt.Fdt(fd.read())
@staticmethod
@@ -483,7 +503,7 @@ class Fdt:
Fdt object containing the data
"""
fdt = Fdt(None)
- fdt._fdt_obj = libfdt.Fdt(bytearray(data))
+ fdt._fdt_obj = libfdt.Fdt(bytes(data))
return fdt
def LookupPhandle(self, phandle):
@@ -573,7 +593,7 @@ class Fdt:
Returns:
The FDT contents as a string of bytes
"""
- return self._fdt_obj.as_bytearray()
+ return bytes(self._fdt_obj.as_bytearray())
def GetFdtObj(self):
"""Get the contents of the FDT
diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py
index 5fbfc8877b..f47879ac00 100644
--- a/tools/dtoc/fdt_util.py
+++ b/tools/dtoc/fdt_util.py
@@ -16,14 +16,6 @@ import tempfile
import command
import tools
-VERSION3 = sys.version_info > (3, 0)
-
-def get_plain_bytes(val):
- """Handle Python 3 strings"""
- if isinstance(val, bytes):
- val = val.decode('utf-8')
- return val.encode('raw_unicode_escape')
-
def fdt32_to_cpu(val):
"""Convert a device tree cell to an integer
@@ -33,9 +25,6 @@ def fdt32_to_cpu(val):
Return:
A native-endian integer value
"""
- if VERSION3:
- # This code is not reached in Python 2
- val = get_plain_bytes(val) # pragma: no cover
return struct.unpack('>I', val)[0]
def fdt_cells_to_cpu(val, cells):
@@ -45,11 +34,11 @@ def fdt_cells_to_cpu(val, cells):
Value to convert (array of one or more 4-character strings)
Return:
- A native-endian long value
+ A native-endian integer value
"""
if not cells:
return 0
- out = long(fdt32_to_cpu(val[0]))
+ out = int(fdt32_to_cpu(val[0]))
if cells == 2:
out = out << 32 | fdt32_to_cpu(val[1])
return out
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index cb6d6e7baf..b915b27856 100644
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -8,6 +8,8 @@ This includes unit tests for some functions and functional tests for the dtoc
tool.
"""
+from __future__ import print_function
+
import collections
import os
import struct
@@ -97,7 +99,7 @@ class TestDtoc(unittest.TestCase):
if expected != actual:
self._WritePythonString('/tmp/binman.expected', expected)
self._WritePythonString('/tmp/binman.actual', actual)
- print 'Failures written to /tmp/binman.{expected,actual}'
+ print('Failures written to /tmp/binman.{expected,actual}')
self.assertEquals(expected, actual)
def test_name(self):
@@ -197,16 +199,16 @@ struct dtd_sandbox_spl_test_2 {
data = infile.read()
self._CheckStrings(C_HEADER + '''
static const struct dtd_sandbox_spl_test dtv_spl_test = {
+\t.boolval\t\t= true,
\t.bytearray\t\t= {0x6, 0x0, 0x0},
\t.byteval\t\t= 0x5,
+\t.intarray\t\t= {0x2, 0x3, 0x4, 0x0},
\t.intval\t\t\t= 0x1,
-\t.notstring\t\t= {0x20, 0x21, 0x22, 0x10, 0x0},
\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
\t\t0x11},
-\t.stringval\t\t= "message",
-\t.boolval\t\t= true,
-\t.intarray\t\t= {0x2, 0x3, 0x4, 0x0},
+\t.notstring\t\t= {0x20, 0x21, 0x22, 0x10, 0x0},
\t.stringarray\t\t= {"multi-word", "message", ""},
+\t.stringval\t\t= "message",
};
U_BOOT_DEVICE(spl_test) = {
\t.name\t\t= "sandbox_spl_test",
@@ -217,12 +219,12 @@ U_BOOT_DEVICE(spl_test) = {
static const struct dtd_sandbox_spl_test dtv_spl_test2 = {
\t.bytearray\t\t= {0x1, 0x23, 0x34},
\t.byteval\t\t= 0x8,
+\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
\t.intval\t\t\t= 0x3,
\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
\t\t0x0},
-\t.stringval\t\t= "message2",
-\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
\t.stringarray\t\t= {"another", "multi-word", "message"},
+\t.stringval\t\t= "message2",
};
U_BOOT_DEVICE(spl_test2) = {
\t.name\t\t= "sandbox_spl_test",
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index 8d70dd2a29..bf469dbd54 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -4,6 +4,8 @@
# Written by Simon Glass <sjg@chromium.org>
#
+from __future__ import print_function
+
from optparse import OptionParser
import glob
import os
@@ -17,7 +19,7 @@ for dirname in ['../patman', '..']:
import command
import fdt
-from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL
+from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
import fdt_util
from fdt_util import fdt32_to_cpu
import libfdt
@@ -45,7 +47,7 @@ def _GetPropertyValue(dtb, node, prop_name):
# Add 12, which is sizeof(struct fdt_property), to get to start of data
offset = prop.GetOffset() + 12
data = dtb.GetContents()[offset:offset + len(prop.value)]
- return prop, [chr(x) for x in data]
+ return prop, [tools.ToChar(x) for x in data]
class TestFdt(unittest.TestCase):
@@ -83,13 +85,13 @@ class TestFdt(unittest.TestCase):
def testFlush(self):
"""Check that we can flush the device tree out to its file"""
fname = self.dtb._fname
- with open(fname) as fd:
+ with open(fname, 'rb') as fd:
data = fd.read()
os.remove(fname)
with self.assertRaises(IOError):
- open(fname)
+ open(fname, 'rb')
self.dtb.Flush()
- with open(fname) as fd:
+ with open(fname, 'rb') as fd:
data = fd.read()
def testPack(self):
@@ -119,6 +121,10 @@ class TestFdt(unittest.TestCase):
node = self.dtb.GetNode('/spl-test')
self.assertEqual(self.dtb, node.GetFdt())
+ def testBytesToValue(self):
+ self.assertEqual(BytesToValue(b'this\0is\0'),
+ (TYPE_STRING, ['this', 'is']))
+
class TestNode(unittest.TestCase):
"""Test operation of the Node class"""
@@ -277,7 +283,7 @@ class TestProp(unittest.TestCase):
"""Tests the GetEmpty() function for the various supported types"""
self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
- self.assertEqual(chr(0) * 4, fdt.Prop.GetEmpty(fdt.TYPE_INT))
+ self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
def testGetOffset(self):
@@ -381,7 +387,7 @@ class TestProp(unittest.TestCase):
self.node.AddString('string', val)
self.dtb.Sync(auto_resize=True)
data = self.fdt.getprop(self.node.Offset(), 'string')
- self.assertEqual(val + '\0', data)
+ self.assertEqual(tools.ToBytes(val) + b'\0', data)
self.fdt.pack()
self.node.SetString('string', val + 'x')
@@ -391,21 +397,21 @@ class TestProp(unittest.TestCase):
self.node.SetString('string', val[:-1])
prop = self.node.props['string']
- prop.SetData(val)
+ prop.SetData(tools.ToBytes(val))
self.dtb.Sync(auto_resize=False)
data = self.fdt.getprop(self.node.Offset(), 'string')
- self.assertEqual(val, data)
+ self.assertEqual(tools.ToBytes(val), data)
self.node.AddEmptyProp('empty', 5)
self.dtb.Sync(auto_resize=True)
prop = self.node.props['empty']
- prop.SetData(val)
+ prop.SetData(tools.ToBytes(val))
self.dtb.Sync(auto_resize=False)
data = self.fdt.getprop(self.node.Offset(), 'empty')
- self.assertEqual(val, data)
+ self.assertEqual(tools.ToBytes(val), data)
- self.node.SetData('empty', '123')
- self.assertEqual('123', prop.bytes)
+ self.node.SetData('empty', b'123')
+ self.assertEqual(b'123', prop.bytes)
def testFromData(self):
dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
@@ -496,18 +502,22 @@ class TestFdtUtil(unittest.TestCase):
self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
- node2 = dtb2.GetNode('/test1')
- val = node2.props['reg'].value
+ node1 = dtb2.GetNode('/test1')
+ val = node1.props['reg'].value
self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
+ node2 = dtb2.GetNode('/test2')
+ val = node2.props['reg'].value
+ self.assertEqual(0x1234567890123456, fdt_util.fdt_cells_to_cpu(val, 2))
+ self.assertEqual(0x9876543210987654, fdt_util.fdt_cells_to_cpu(val[2:],
+ 2))
+ self.assertEqual(0x12345678, fdt_util.fdt_cells_to_cpu(val, 1))
+
def testEnsureCompiled(self):
"""Test a degenerate case of this function"""
dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
- def testGetPlainBytes(self):
- self.assertEqual('fred', fdt_util.get_plain_bytes('fred'))
-
def RunTestCoverage():
"""Run the tests and check that we get 100% coverage"""
@@ -535,11 +545,11 @@ def RunTests(args):
suite = unittest.TestLoader().loadTestsFromTestCase(module)
suite.run(result)
- print result
+ print(result)
for _, err in result.errors:
- print err
+ print(err)
for _, err in result.failures:
- print err
+ print(err)
if __name__ != '__main__':
sys.exit(1)