From 555ba4889c8ffc5bac933976db9fd915c796f72d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 May 2017 07:38:18 -0600 Subject: fdt: Rename existing python libfdt module Now that this module has been accepted upstream we should stop using the local U-Boot one. In preparation for this, rename it to indicate it is for legacy use. Signed-off-by: Simon Glass --- tools/dtoc/fdt_normal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/dtoc') diff --git a/tools/dtoc/fdt_normal.py b/tools/dtoc/fdt_normal.py index cce5c06d8c..17b0a9a726 100644 --- a/tools/dtoc/fdt_normal.py +++ b/tools/dtoc/fdt_normal.py @@ -12,7 +12,7 @@ import sys import fdt from fdt import Fdt, NodeBase, PropBase import fdt_util -import libfdt +import libfdt_legacy as libfdt # This deals with a device tree, presenting it as a list of Node and Prop # objects, representing nodes and properties, respectively. -- cgit From b4360206a4bc67404125b0478132aeaeea41683f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 May 2017 07:38:22 -0600 Subject: fdt: Support use of the new python libfdt library Use the new library if available, while retaining backwards compatibility with the old library for now. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 1 + tools/dtoc/fdt_normal.py | 35 ++++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'tools/dtoc') diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 816fdbe525..c40b9b6bab 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -96,6 +96,7 @@ class PropBase: 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 diff --git a/tools/dtoc/fdt_normal.py b/tools/dtoc/fdt_normal.py index 17b0a9a726..e793f49fa8 100644 --- a/tools/dtoc/fdt_normal.py +++ b/tools/dtoc/fdt_normal.py @@ -12,7 +12,13 @@ import sys import fdt from fdt import Fdt, NodeBase, PropBase import fdt_util -import libfdt_legacy as libfdt +try: + import libfdt + legacy = False +except ImportError: + import libfdt_legacy as libfdt + legacy = True + # This deals with a device tree, presenting it as a list of Node and Prop # objects, representing nodes and properties, respectively. @@ -36,7 +42,7 @@ class Prop(PropBase): """ def __init__(self, node, offset, name, bytes): PropBase.__init__(self, node, offset, name) - self.bytes = bytes + self.bytes = str(bytes) if not bytes: self.type = fdt.TYPE_BOOL self.value = True @@ -86,7 +92,10 @@ class Node(NodeBase): offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset()) while offset >= 0: sep = '' if self.path[-1] == '/' else '/' - name = libfdt.Name(self._fdt.GetFdt(), offset) + if legacy: + name = libfdt.Name(self._fdt.GetFdt(), offset) + else: + name = self._fdt._fdt_obj.get_name(offset) path = self.path + sep + name node = Node(self._fdt, offset, name, path) self.subnodes.append(node) @@ -139,6 +148,8 @@ class FdtNormal(Fdt): with open(self._fname) as fd: self._fdt = bytearray(fd.read()) + if not legacy: + self._fdt_obj = libfdt.Fdt(self._fdt) def GetFdt(self): """Get the contents of the FDT @@ -175,12 +186,18 @@ class FdtNormal(Fdt): props_dict = {} poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset) while poffset >= 0: - dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset) - prop = Prop(node, poffset, libfdt.String(self._fdt, dprop.nameoff), - libfdt.Data(dprop)) - props_dict[prop.name] = prop - - poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) + if legacy: + dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, + poffset) + prop = Prop(node, poffset, + libfdt.String(self._fdt, dprop.nameoff), + libfdt.Data(dprop)) + else: + p = self._fdt_obj.get_property_by_offset(poffset) + prop = Prop(node, poffset, p.name, p.value) + props_dict[prop.name] = prop + + poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) return props_dict def Invalidate(self): -- cgit From 6d804eafc12263fcba423284d453ca9f4fff639f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 May 2017 07:38:25 -0600 Subject: fdt: Drop use of the legacy libfdt python module Now that this is no-longer available, stop looking for it. The new module will be used if available. Signed-off-by: Simon Glass --- tools/dtoc/fdt_normal.py | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) (limited to 'tools/dtoc') diff --git a/tools/dtoc/fdt_normal.py b/tools/dtoc/fdt_normal.py index e793f49fa8..a0e58a4464 100644 --- a/tools/dtoc/fdt_normal.py +++ b/tools/dtoc/fdt_normal.py @@ -12,12 +12,7 @@ import sys import fdt from fdt import Fdt, NodeBase, PropBase import fdt_util -try: - import libfdt - legacy = False -except ImportError: - import libfdt_legacy as libfdt - legacy = True +import libfdt # This deals with a device tree, presenting it as a list of Node and Prop @@ -92,10 +87,7 @@ class Node(NodeBase): offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset()) while offset >= 0: sep = '' if self.path[-1] == '/' else '/' - if legacy: - name = libfdt.Name(self._fdt.GetFdt(), offset) - else: - name = self._fdt._fdt_obj.get_name(offset) + name = self._fdt._fdt_obj.get_name(offset) path = self.path + sep + name node = Node(self._fdt, offset, name, path) self.subnodes.append(node) @@ -148,8 +140,7 @@ class FdtNormal(Fdt): with open(self._fname) as fd: self._fdt = bytearray(fd.read()) - if not legacy: - self._fdt_obj = libfdt.Fdt(self._fdt) + self._fdt_obj = libfdt.Fdt(self._fdt) def GetFdt(self): """Get the contents of the FDT @@ -186,18 +177,11 @@ class FdtNormal(Fdt): props_dict = {} poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset) while poffset >= 0: - if legacy: - dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, - poffset) - prop = Prop(node, poffset, - libfdt.String(self._fdt, dprop.nameoff), - libfdt.Data(dprop)) - else: - p = self._fdt_obj.get_property_by_offset(poffset) - prop = Prop(node, poffset, p.name, p.value) - props_dict[prop.name] = prop - - poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) + p = self._fdt_obj.get_property_by_offset(poffset) + prop = Prop(node, poffset, p.name, p.value) + props_dict[prop.name] = prop + + poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) return props_dict def Invalidate(self): -- cgit From 160a7664252c937d57caf9bc588519ede6e46a34 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 May 2017 07:38:26 -0600 Subject: fdt: Drop fdt_fallback library Drop this now-unused library and associated tests. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 4 +- tools/dtoc/fdt_fallback.py | 181 --------------------------------------------- tools/dtoc/fdt_select.py | 24 +----- 3 files changed, 5 insertions(+), 204 deletions(-) delete mode 100644 tools/dtoc/fdt_fallback.py (limited to 'tools/dtoc') diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index c40b9b6bab..dedd3d7501 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -14,8 +14,8 @@ import fdt_util # This deals with a device tree, presenting it as an assortment of Node and # Prop objects, representing nodes and properties, respectively. This file # contains the base classes and defines the high-level API. Most of the -# implementation is in the FdtFallback and FdtNormal subclasses. See -# fdt_select.py for how to create an Fdt object. +# implementation is in the FdtNormal subclass. See fdt_select.py for how to +# create an Fdt object. # A list of types we support (TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4) diff --git a/tools/dtoc/fdt_fallback.py b/tools/dtoc/fdt_fallback.py deleted file mode 100644 index 23e26796c8..0000000000 --- a/tools/dtoc/fdt_fallback.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2016 Google, Inc -# Written by Simon Glass -# -# SPDX-License-Identifier: GPL-2.0+ -# - -import command -import fdt -from fdt import Fdt, NodeBase, PropBase -import fdt_util -import sys - -# This deals with a device tree, presenting it as a list of Node and Prop -# objects, representing nodes and properties, respectively. -# -# This implementation uses the fdtget tool to access the device tree, so it -# is not very efficient for larger trees. The tool is called once for each -# node and property in the tree. - -class Prop(PropBase): - """A device tree property - - Properties: - name: Property name (as per the device tree) - value: Property value as a string of bytes, or a list of strings of - bytes - type: Value type - """ - def __init__(self, node, name, byte_list_str): - PropBase.__init__(self, node, 0, name) - if not byte_list_str.strip(): - self.type = fdt.TYPE_BOOL - return - self.bytes = [chr(int(byte, 16)) - for byte in byte_list_str.strip().split(' ')] - self.type, self.value = self.BytesToValue(''.join(self.bytes)) - - -class Node(NodeBase): - """A device tree node - - Properties: - name: Device tree node tname - path: Full path to node, along with the node name itself - _fdt: Device tree object - subnodes: A list of subnodes for this node, each a Node object - props: A dict of properties for this node, each a Prop object. - Keyed by property name - """ - def __init__(self, fdt, offset, name, path): - NodeBase.__init__(self, fdt, offset, name, path) - - def Scan(self): - """Scan a node's properties and subnodes - - This fills in the props and subnodes properties, recursively - searching into subnodes so that the entire tree is built. - """ - for name, byte_list_str in self._fdt.GetProps(self.path).items(): - prop = Prop(self, name, byte_list_str) - self.props[name] = prop - - for name in self._fdt.GetSubNodes(self.path): - sep = '' if self.path[-1] == '/' else '/' - path = self.path + sep + name - node = Node(self._fdt, 0, name, path) - self.subnodes.append(node) - - node.Scan() - - def DeleteProp(self, prop_name): - """Delete a property of a node - - The property is deleted using fdtput. - - Args: - prop_name: Name of the property to delete - Raises: - CommandError if the property does not exist - """ - args = [self._fdt._fname, '-d', self.path, prop_name] - command.Output('fdtput', *args) - del self.props[prop_name] - -class FdtFallback(Fdt): - """Provides simple access to a flat device tree blob using fdtget/fdtput - - Properties: - See superclass - """ - - def __init__(self, fname): - Fdt.__init__(self, fname) - if self._fname: - self._fname = fdt_util.EnsureCompiled(self._fname) - - def GetSubNodes(self, node): - """Returns a list of sub-nodes of a given node - - Args: - node: Node name to return children from - - Returns: - List of children in the node (each a string node name) - - Raises: - CmdError: if the node does not exist. - """ - out = command.Output('fdtget', self._fname, '-l', node) - return out.strip().splitlines() - - def GetProps(self, node): - """Get all properties from a node - - Args: - node: full path to node name to look in - - Returns: - A dictionary containing all the properties, indexed by node name. - The entries are simply strings - no decoding of lists or numbers - is done. - - Raises: - CmdError: if the node does not exist. - """ - out = command.Output('fdtget', self._fname, node, '-p') - props = out.strip().splitlines() - props_dict = {} - for prop in props: - name = prop - props_dict[prop] = self.GetProp(node, name) - return props_dict - - def GetProp(self, node, prop, default=None, typespec=None): - """Get a property from a device tree. - - This looks up the given node and property, and returns the value as a - string, - - If the node or property does not exist, this will return the default - value. - - Args: - node: Full path to node to look up. - prop: Property name to look up. - default: Default value to return if nothing is present in the fdt, - or None to raise in this case. This will be converted to a - string. - typespec: Type character to use (None for default, 's' for string) - - Returns: - string containing the property value. - - Raises: - CmdError: if the property does not exist and no default is provided. - """ - args = [self._fname, node, prop, '-t', 'bx'] - if default is not None: - args += ['-d', str(default)] - if typespec is not None: - args += ['-t', typespec] - out = command.Output('fdtget', *args) - return out.strip() - - @classmethod - def Node(self, fdt, offset, name, path): - """Create a new node - - This is used by Fdt.Scan() to create a new node using the correct - class. - - Args: - fdt: Fdt object - offset: Offset of node - name: Node name - path: Full path to node - """ - node = Node(fdt, offset, name, path) - return node diff --git a/tools/dtoc/fdt_select.py b/tools/dtoc/fdt_select.py index ea78c527fc..54a3ef2e46 100644 --- a/tools/dtoc/fdt_select.py +++ b/tools/dtoc/fdt_select.py @@ -6,31 +6,13 @@ # SPDX-License-Identifier: GPL-2.0+ # -import fdt_fallback - # Bring in either the normal fdt library (which relies on libfdt) or the # fallback one (which uses fdtget and is slower). Both provide the same # interface for this file to use. -try: - import fdt_normal - have_libfdt = True -except ImportError: - have_libfdt = False - -force_fallback = False +import fdt_normal -def FdtScan(fname, _force_fallback=False): +def FdtScan(fname): """Returns a new Fdt object from the implementation we are using""" - if have_libfdt and not force_fallback and not _force_fallback: - dtb = fdt_normal.FdtNormal(fname) - else: - dtb = fdt_fallback.FdtFallback(fname) + dtb = fdt_normal.FdtNormal(fname) dtb.Scan() return dtb - -def UseFallback(fallback): - global force_fallback - - old_val = force_fallback - force_fallback = fallback - return old_val -- cgit From 7b75b4482ddee4ea8248f1f64f2b0d1c752dd273 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 May 2017 07:38:28 -0600 Subject: fdt: Merge fdt_normal with its base class Since we only have one Fdt implementation now we don't need to have a base class. Merge the implementation and the base class together. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 176 +++++++++++++++++++++++++++++++----- tools/dtoc/fdt_normal.py | 226 ----------------------------------------------- tools/dtoc/fdt_select.py | 8 +- 3 files changed, 157 insertions(+), 253 deletions(-) delete mode 100644 tools/dtoc/fdt_normal.py (limited to 'tools/dtoc') diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index dedd3d7501..bff31d1c92 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -10,12 +10,15 @@ import struct import sys import fdt_util +import libfdt # This deals with a device tree, presenting it as an assortment of Node and # Prop objects, representing nodes and properties, respectively. This file -# contains the base classes and defines the high-level API. Most of the -# implementation is in the FdtNormal subclass. See fdt_select.py for how to -# create an Fdt object. +# contains the base classes and defines the high-level API. See fdt_select.py +# for how to create an Fdt object. + +# This implementation uses a libfdt Python library to access the device tree, +# so it is fairly efficient. # A list of types we support (TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4) @@ -25,7 +28,7 @@ def CheckErr(errnum, msg): raise ValueError('Error %d: %s: %s' % (errnum, libfdt.fdt_strerror(errnum), msg)) -class PropBase: +class Prop: """A device tree property Properties: @@ -34,11 +37,17 @@ class PropBase: bytes type: Value type """ - def __init__(self, node, offset, name): + def __init__(self, node, offset, name, bytes): self._node = node self._offset = offset self.name = name self.value = None + self.bytes = str(bytes) + if not bytes: + self.type = TYPE_BOOL + self.value = True + return + self.type, self.value = self.BytesToValue(bytes) def GetPhandle(self): """Get a (single) phandle value from a property @@ -148,15 +157,12 @@ class PropBase: def GetOffset(self): """Get the offset of a property - This can be implemented by subclasses. - Returns: - The offset of the property (struct fdt_property) within the - file, or None if not known. + The offset of the property (struct fdt_property) within the file """ - return None + return self._node._fdt.GetStructOffset(self._offset) -class NodeBase: +class Node: """A device tree node Properties: @@ -189,25 +195,65 @@ class NodeBase: return subnode return None + def Offset(self): + """Returns the offset of a node, after checking the cache + + This should be used instead of self._offset directly, to ensure that + the cache does not contain invalid offsets. + """ + self._fdt.CheckCache() + return self._offset + def Scan(self): - """Scan the subnodes of a node + """Scan a node's properties and subnodes + + This fills in the props and subnodes properties, recursively + searching into subnodes so that the entire tree is built. + """ + self.props = self._fdt.GetProps(self) + + offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset()) + while offset >= 0: + sep = '' if self.path[-1] == '/' else '/' + name = self._fdt._fdt_obj.get_name(offset) + path = self.path + sep + name + node = Node(self._fdt, offset, name, path) + self.subnodes.append(node) - This should be implemented by subclasses + node.Scan() + offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset) + + def Refresh(self, my_offset): + """Fix up the _offset for each node, recursively + + Note: This does not take account of property offsets - these will not + be updated. """ - raise NotImplementedError() + if self._offset != my_offset: + #print '%s: %d -> %d\n' % (self.path, self._offset, my_offset) + self._offset = my_offset + offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset) + for subnode in self.subnodes: + subnode.Refresh(offset) + offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset) def DeleteProp(self, prop_name): """Delete a property of a node - This should be implemented by subclasses + The property is deleted and the offset cache is invalidated. Args: prop_name: Name of the property to delete + Raises: + ValueError if the property does not exist """ - raise NotImplementedError() + CheckErr(libfdt.fdt_delprop(self._fdt.GetFdt(), self.Offset(), prop_name), + "Node '%s': delete property: '%s'" % (self.path, prop_name)) + del self.props[prop_name] + self._fdt.Invalidate() class Fdt: - """Provides simple access to a flat device tree blob. + """Provides simple access to a flat device tree blob using libfdts. Properties: fname: Filename of fdt @@ -215,6 +261,13 @@ class Fdt: """ def __init__(self, fname): self._fname = fname + self._cached_offsets = False + if self._fname: + self._fname = fdt_util.EnsureCompiled(self._fname) + + with open(self._fname) as fd: + self._fdt = bytearray(fd.read()) + self._fdt_obj = libfdt.Fdt(self._fdt) def Scan(self, root='/'): """Scan a device tree, building up a tree of Node objects @@ -256,15 +309,94 @@ class Fdt: """Flush device tree changes back to the file If the device tree has changed in memory, write it back to the file. - Subclasses can implement this if needed. """ - pass + with open(self._fname, 'wb') as fd: + fd.write(self._fdt) def Pack(self): """Pack the device tree down to its minimum size When nodes and properties shrink or are deleted, wasted space can - build up in the device tree binary. Subclasses can implement this - to remove that spare space. + build up in the device tree binary. + """ + CheckErr(libfdt.fdt_pack(self._fdt), 'pack') + fdt_len = libfdt.fdt_totalsize(self._fdt) + del self._fdt[fdt_len:] + + def GetFdt(self): + """Get the contents of the FDT + + Returns: + The FDT contents as a string of bytes + """ + return self._fdt + + def CheckErr(errnum, msg): + if errnum: + raise ValueError('Error %d: %s: %s' % + (errnum, libfdt.fdt_strerror(errnum), msg)) + + + def GetProps(self, node): + """Get all properties from a node. + + Args: + node: Full path to node name to look in. + + Returns: + A dictionary containing all the properties, indexed by node name. + The entries are Prop objects. + + Raises: + ValueError: if the node does not exist. + """ + props_dict = {} + poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset) + while poffset >= 0: + p = self._fdt_obj.get_property_by_offset(poffset) + prop = Prop(node, poffset, p.name, p.value) + props_dict[prop.name] = prop + + poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) + return props_dict + + def Invalidate(self): + """Mark our offset cache as invalid""" + self._cached_offsets = False + + def CheckCache(self): + """Refresh the offset cache if needed""" + if self._cached_offsets: + return + self.Refresh() + self._cached_offsets = True + + def Refresh(self): + """Refresh the offset cache""" + self._root.Refresh(0) + + def GetStructOffset(self, offset): + """Get the file offset of a given struct offset + + Args: + offset: Offset within the 'struct' region of the device tree + Returns: + Position of @offset within the device tree binary """ - pass + return libfdt.fdt_off_dt_struct(self._fdt) + offset + + @classmethod + def Node(self, fdt, offset, name, path): + """Create a new node + + This is used by Fdt.Scan() to create a new node using the correct + class. + + Args: + fdt: Fdt object + offset: Offset of node + name: Node name + path: Full path to node + """ + node = Node(fdt, offset, name, path) + return node diff --git a/tools/dtoc/fdt_normal.py b/tools/dtoc/fdt_normal.py deleted file mode 100644 index a0e58a4464..0000000000 --- a/tools/dtoc/fdt_normal.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2016 Google, Inc -# Written by Simon Glass -# -# SPDX-License-Identifier: GPL-2.0+ -# - -import struct -import sys - -import fdt -from fdt import Fdt, NodeBase, PropBase -import fdt_util -import libfdt - - -# This deals with a device tree, presenting it as a list of Node and Prop -# objects, representing nodes and properties, respectively. -# -# This implementation uses a libfdt Python library to access the device tree, -# so it is fairly efficient. - -def CheckErr(errnum, msg): - if errnum: - raise ValueError('Error %d: %s: %s' % - (errnum, libfdt.fdt_strerror(errnum), msg)) - -class Prop(PropBase): - """A device tree property - - Properties: - name: Property name (as per the device tree) - value: Property value as a string of bytes, or a list of strings of - bytes - type: Value type - """ - def __init__(self, node, offset, name, bytes): - PropBase.__init__(self, node, offset, name) - self.bytes = str(bytes) - if not bytes: - self.type = fdt.TYPE_BOOL - self.value = True - return - self.type, self.value = self.BytesToValue(bytes) - - def GetOffset(self): - """Get the offset of a property - - Returns: - The offset of the property (struct fdt_property) within the file - """ - return self._node._fdt.GetStructOffset(self._offset) - -class Node(NodeBase): - """A device tree node - - Properties: - offset: Integer offset in the device tree - name: Device tree node tname - path: Full path to node, along with the node name itself - _fdt: Device tree object - subnodes: A list of subnodes for this node, each a Node object - props: A dict of properties for this node, each a Prop object. - Keyed by property name - """ - def __init__(self, fdt, offset, name, path): - NodeBase.__init__(self, fdt, offset, name, path) - - def Offset(self): - """Returns the offset of a node, after checking the cache - - This should be used instead of self._offset directly, to ensure that - the cache does not contain invalid offsets. - """ - self._fdt.CheckCache() - return self._offset - - def Scan(self): - """Scan a node's properties and subnodes - - This fills in the props and subnodes properties, recursively - searching into subnodes so that the entire tree is built. - """ - self.props = self._fdt.GetProps(self) - - offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset()) - while offset >= 0: - sep = '' if self.path[-1] == '/' else '/' - name = self._fdt._fdt_obj.get_name(offset) - path = self.path + sep + name - node = Node(self._fdt, offset, name, path) - self.subnodes.append(node) - - node.Scan() - offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset) - - def Refresh(self, my_offset): - """Fix up the _offset for each node, recursively - - Note: This does not take account of property offsets - these will not - be updated. - """ - if self._offset != my_offset: - #print '%s: %d -> %d\n' % (self.path, self._offset, my_offset) - self._offset = my_offset - offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset) - for subnode in self.subnodes: - subnode.Refresh(offset) - offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset) - - def DeleteProp(self, prop_name): - """Delete a property of a node - - The property is deleted and the offset cache is invalidated. - - Args: - prop_name: Name of the property to delete - Raises: - ValueError if the property does not exist - """ - CheckErr(libfdt.fdt_delprop(self._fdt.GetFdt(), self.Offset(), prop_name), - "Node '%s': delete property: '%s'" % (self.path, prop_name)) - del self.props[prop_name] - self._fdt.Invalidate() - -class FdtNormal(Fdt): - """Provides simple access to a flat device tree blob using libfdt. - - Properties: - _fdt: Device tree contents (bytearray) - _cached_offsets: True if all the nodes have a valid _offset property, - False if something has changed to invalidate the offsets - """ - def __init__(self, fname): - Fdt.__init__(self, fname) - self._cached_offsets = False - if self._fname: - self._fname = fdt_util.EnsureCompiled(self._fname) - - with open(self._fname) as fd: - self._fdt = bytearray(fd.read()) - self._fdt_obj = libfdt.Fdt(self._fdt) - - def GetFdt(self): - """Get the contents of the FDT - - Returns: - The FDT contents as a string of bytes - """ - return self._fdt - - def Flush(self): - """Flush device tree changes back to the file""" - with open(self._fname, 'wb') as fd: - fd.write(self._fdt) - - def Pack(self): - """Pack the device tree down to its minimum size""" - CheckErr(libfdt.fdt_pack(self._fdt), 'pack') - fdt_len = libfdt.fdt_totalsize(self._fdt) - del self._fdt[fdt_len:] - - def GetProps(self, node): - """Get all properties from a node. - - Args: - node: Full path to node name to look in. - - Returns: - A dictionary containing all the properties, indexed by node name. - The entries are Prop objects. - - Raises: - ValueError: if the node does not exist. - """ - props_dict = {} - poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset) - while poffset >= 0: - p = self._fdt_obj.get_property_by_offset(poffset) - prop = Prop(node, poffset, p.name, p.value) - props_dict[prop.name] = prop - - poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) - return props_dict - - def Invalidate(self): - """Mark our offset cache as invalid""" - self._cached_offsets = False - - def CheckCache(self): - """Refresh the offset cache if needed""" - if self._cached_offsets: - return - self.Refresh() - self._cached_offsets = True - - def Refresh(self): - """Refresh the offset cache""" - self._root.Refresh(0) - - def GetStructOffset(self, offset): - """Get the file offset of a given struct offset - - Args: - offset: Offset within the 'struct' region of the device tree - Returns: - Position of @offset within the device tree binary - """ - return libfdt.fdt_off_dt_struct(self._fdt) + offset - - @classmethod - def Node(self, fdt, offset, name, path): - """Create a new node - - This is used by Fdt.Scan() to create a new node using the correct - class. - - Args: - fdt: Fdt object - offset: Offset of node - name: Node name - path: Full path to node - """ - node = Node(fdt, offset, name, path) - return node diff --git a/tools/dtoc/fdt_select.py b/tools/dtoc/fdt_select.py index 54a3ef2e46..d6337ea227 100644 --- a/tools/dtoc/fdt_select.py +++ b/tools/dtoc/fdt_select.py @@ -6,13 +6,11 @@ # SPDX-License-Identifier: GPL-2.0+ # -# Bring in either the normal fdt library (which relies on libfdt) or the -# fallback one (which uses fdtget and is slower). Both provide the same -# interface for this file to use. -import fdt_normal +# Bring in the normal fdt library (which relies on libfdt) +import fdt def FdtScan(fname): """Returns a new Fdt object from the implementation we are using""" - dtb = fdt_normal.FdtNormal(fname) + dtb = fdt.Fdt(fname) dtb.Scan() return dtb -- cgit From 99ed4a2e979150879fb70aea71898709536375d3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 May 2017 07:38:30 -0600 Subject: fdt: Drop fdt_select.py This file was used to select between the normal and fallback libfdt implementations. Now that we only have one, it is not needed. Drop it and fix up all users. Signed-off-by: Simon Glass --- tools/dtoc/dtoc.py | 3 +-- tools/dtoc/fdt.py | 10 ++++++++-- tools/dtoc/fdt_select.py | 16 ---------------- 3 files changed, 9 insertions(+), 20 deletions(-) delete mode 100644 tools/dtoc/fdt_select.py (limited to 'tools/dtoc') diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py index 2e0b9c04e2..08e35f148c 100755 --- a/tools/dtoc/dtoc.py +++ b/tools/dtoc/dtoc.py @@ -17,7 +17,6 @@ our_path = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(our_path, '../patman')) import fdt -import fdt_select import fdt_util # When we see these properties we ignore them - i.e. do not create a structure member @@ -170,7 +169,7 @@ class DtbPlatdata: Once this is done, self.fdt.GetRoot() can be called to obtain the device tree root node, and progress from there. """ - self.fdt = fdt_select.FdtScan(self._dtb_fname) + self.fdt = fdt.FdtScan(self._dtb_fname) def ScanNode(self, root): for node in root.subnodes: diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index bff31d1c92..63a32ea2d7 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -14,8 +14,8 @@ import libfdt # This deals with a device tree, presenting it as an assortment of Node and # Prop objects, representing nodes and properties, respectively. This file -# contains the base classes and defines the high-level API. See fdt_select.py -# for how to create an Fdt object. +# contains the base classes and defines the high-level API. You can use +# FdtScan() as a convenience function to create and scan an Fdt. # This implementation uses a libfdt Python library to access the device tree, # so it is fairly efficient. @@ -400,3 +400,9 @@ class Fdt: """ node = Node(fdt, offset, name, path) return node + +def FdtScan(fname): + """Returns a new Fdt object from the implementation we are using""" + dtb = Fdt(fname) + dtb.Scan() + return dtb diff --git a/tools/dtoc/fdt_select.py b/tools/dtoc/fdt_select.py deleted file mode 100644 index d6337ea227..0000000000 --- a/tools/dtoc/fdt_select.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2016 Google, Inc -# Written by Simon Glass -# -# SPDX-License-Identifier: GPL-2.0+ -# - -# Bring in the normal fdt library (which relies on libfdt) -import fdt - -def FdtScan(fname): - """Returns a new Fdt object from the implementation we are using""" - dtb = fdt.Fdt(fname) - dtb.Scan() - return dtb -- cgit