diff options
Diffstat (limited to 'tools/dtoc/fdt.py')
-rw-r--r-- | tools/dtoc/fdt.py | 148 |
1 files changed, 84 insertions, 64 deletions
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 |