[U-Boot] [PATCH 08/30] dtoc: Create a base class for Fdt
Simon Glass
sjg at chromium.org
Tue Jul 26 02:59:04 CEST 2016
At present we have two separate implementations of the Fdt library, one which
uses fdtget/fdtput and one which uses libfdt (via swig).
Before adding more functionality it makes sense to create a base class for
these. This will allow common functions to be shared, and make the Fdt API
a little clearer.
Create a new fdt.py file with the base class, and adjust fdt_normal.py and
fdt_fallback.py to use it.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
tools/dtoc/fdt.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++
tools/dtoc/fdt_fallback.py | 61 +++++++++++++++++++++++++----------------
tools/dtoc/fdt_normal.py | 58 +++++++++++++++++++++++++--------------
tools/dtoc/fdt_select.py | 9 ++++--
4 files changed, 148 insertions(+), 48 deletions(-)
create mode 100644 tools/dtoc/fdt.py
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
new file mode 100644
index 0000000..413d45d
--- /dev/null
+++ b/tools/dtoc/fdt.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016 Google, Inc
+# Written by Simon Glass <sjg at chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+import struct
+import sys
+
+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.
+
+def CheckErr(errnum, msg):
+ if errnum:
+ raise ValueError('Error %d: %s: %s' %
+ (errnum, libfdt.fdt_strerror(errnum), msg))
+
+class 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):
+ self._node = node
+ self._offset = offset
+ self.name = name
+ self.value = None
+
+class 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):
+ self._fdt = fdt
+ self._offset = offset
+ self.name = name
+ self.path = path
+ self.subnodes = []
+ self.props = {}
+
+class Fdt:
+ """Provides simple access to a flat device tree blob.
+
+ Properties:
+ fname: Filename of fdt
+ _root: Root of device tree (a Node object)
+ """
+ def __init__(self, fname):
+ self._fname = fname
diff --git a/tools/dtoc/fdt_fallback.py b/tools/dtoc/fdt_fallback.py
index 14decf3..7d912e2 100644
--- a/tools/dtoc/fdt_fallback.py
+++ b/tools/dtoc/fdt_fallback.py
@@ -7,6 +7,8 @@
#
import command
+import fdt
+from fdt import Fdt, NodeBase, PropBase
import fdt_util
import sys
@@ -17,7 +19,7 @@ import sys
# is not very efficient for larger trees. The tool is called once for each
# node and property in the tree.
-class Prop:
+class Prop(PropBase):
"""A device tree property
Properties:
@@ -26,14 +28,14 @@ class Prop:
bytes
type: Value type
"""
- def __init__(self, name, byte_list_str):
- self.name = name
- self.value = None
+ def __init__(self, node, name, byte_list_str):
+ PropBase.__init__(self, node, 0, name)
if not byte_list_str.strip():
self.type = fdt_util.TYPE_BOOL
return
- bytes = [chr(int(byte, 16)) for byte in byte_list_str.strip().split(' ')]
- self.type, self.value = fdt_util.BytesToValue(''.join(bytes))
+ self.bytes = [chr(int(byte, 16))
+ for byte in byte_list_str.strip().split(' ')]
+ self.type, self.value = fdt_util.BytesToValue(''.join(self.bytes))
def GetPhandle(self):
"""Get a (single) phandle value from a property
@@ -71,7 +73,7 @@ class Prop:
if type(newprop.value) == list and type(self.value) != list:
self.value = newprop.value
-class Node:
+class Node(NodeBase):
"""A device tree node
Properties:
@@ -82,12 +84,8 @@ class Node:
props: A dict of properties for this node, each a Prop object.
Keyed by property name
"""
- def __init__(self, fdt, name, path):
- self.name = name
- self.path = path
- self._fdt = fdt
- self.subnodes = []
- self.props = {}
+ def __init__(self, fdt, offset, name, path):
+ NodeBase.__init__(self, fdt, offset, name, path)
def Scan(self):
"""Scan a node's properties and subnodes
@@ -96,35 +94,34 @@ class Node:
searching into subnodes so that the entire tree is built.
"""
for name, byte_list_str in self._fdt.GetProps(self.path).iteritems():
- prop = Prop(name, byte_list_str)
+ 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, name, path)
+ node = Node(self._fdt, 0, name, path)
self.subnodes.append(node)
node.Scan()
-class Fdt:
- """Provides simple access to a flat device tree blob.
+class FdtFallback(Fdt):
+ """Provides simple access to a flat device tree blob using fdtget/fdtput
Properties:
- fname: Filename of fdt
- _root: Root of device tree (a Node object)
+ See superclass
"""
def __init__(self, fname):
- self.fname = fname
+ Fdt.__init__(self, fname)
def Scan(self):
"""Scan a device tree, building up a tree of Node objects
This fills in the self._root property
"""
- self._root = Node(self, '/', '/')
+ self._root = Node(self, 0, '/', '/')
self._root.Scan()
def GetRoot(self):
@@ -147,7 +144,7 @@ class Fdt:
Raises:
CmdError: if the node does not exist.
"""
- out = command.Output('fdtget', self.fname, '-l', node)
+ out = command.Output('fdtget', self._fname, '-l', node)
return out.strip().splitlines()
def GetProps(self, node, convert_dashes=False):
@@ -165,7 +162,7 @@ class Fdt:
Raises:
CmdError: if the node does not exist.
"""
- out = command.Output('fdtget', self.fname, node, '-p')
+ out = command.Output('fdtget', self._fname, node, '-p')
props = out.strip().splitlines()
props_dict = {}
for prop in props:
@@ -198,10 +195,26 @@ class Fdt:
Raises:
CmdError: if the property does not exist and no default is provided.
"""
- args = [self.fname, node, prop, '-t', 'bx']
+ args = [self._fname, node, prop, '-t', 'bx']
if default is not None:
args += ['-d', str(default)]
if typespec is not None:
args += ['-t%s' % 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_normal.py b/tools/dtoc/fdt_normal.py
index 1d913a9..ca5335b 100644
--- a/tools/dtoc/fdt_normal.py
+++ b/tools/dtoc/fdt_normal.py
@@ -6,9 +6,13 @@
# SPDX-License-Identifier: GPL-2.0+
#
+import struct
+import sys
+
+import fdt
+from fdt import Fdt, NodeBase, PropBase
import fdt_util
import libfdt
-import sys
# This deals with a device tree, presenting it as a list of Node and Prop
# objects, representing nodes and properties, respectively.
@@ -16,7 +20,7 @@ import sys
# This implementation uses a libfdt Python library to access the device tree,
# so it is fairly efficient.
-class Prop:
+class Prop(PropBase):
"""A device tree property
Properties:
@@ -25,9 +29,9 @@ class Prop:
bytes
type: Value type
"""
- def __init__(self, name, bytes):
- self.name = name
- self.value = None
+ def __init__(self, node, offset, name, bytes):
+ PropBase.__init__(self, node, offset, name)
+ self.bytes = bytes
if not bytes:
self.type = fdt_util.TYPE_BOOL
self.value = True
@@ -76,7 +80,7 @@ class Prop:
self.value.append(val)
-class Node:
+class Node(NodeBase):
"""A device tree node
Properties:
@@ -89,12 +93,7 @@ class Node:
Keyed by property name
"""
def __init__(self, fdt, offset, name, path):
- self.offset = offset
- self.name = name
- self.path = path
- self._fdt = fdt
- self.subnodes = []
- self.props = {}
+ NodeBase.__init__(self, fdt, offset, name, path)
def Scan(self):
"""Scan a node's properties and subnodes
@@ -104,7 +103,7 @@ class Node:
"""
self.props = self._fdt.GetProps(self.path)
- offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.offset)
+ 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)
@@ -116,17 +115,17 @@ class Node:
offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
-class Fdt:
- """Provides simple access to a flat device tree blob.
+class FdtNormal(Fdt):
+ """Provides simple access to a flat device tree blob using libfdt.
Properties:
- fname: Filename of fdt
- _root: Root of device tree (a Node object)
+ _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):
- self.fname = fname
- with open(fname) as fd:
+ Fdt.__init__(self, fname)
+ with open(self._fname) as fd:
self._fdt = fd.read()
def GetFdt(self):
@@ -173,8 +172,25 @@ class Fdt:
poffset = libfdt.fdt_first_property_offset(self._fdt, offset)
while poffset >= 0:
dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset)
- prop = Prop(libfdt.String(self._fdt, dprop.nameoff), libfdt.Data(dprop))
+ 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)
return props_dict
+
+ @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 681dfbf..18a36d8 100644
--- a/tools/dtoc/fdt_select.py
+++ b/tools/dtoc/fdt_select.py
@@ -10,14 +10,17 @@
# fallback one (which uses fdtget and is slower). Both provide the same
# interface for this file to use.
try:
- import fdt_normal as fdt
+ import fdt_normal
have_libfdt = True
except ImportError:
have_libfdt = False
- import fdt_fallback as fdt
+ import fdt_fallback
def FdtScan(fname):
"""Returns a new Fdt object from the implementation we are using"""
- dtb = fdt.Fdt(fname)
+ if have_libfdt:
+ dtb = fdt_normal.FdtNormal(fname)
+ else:
+ dtb = fdt_fallback.FdtFallback(fname)
dtb.Scan()
return dtb
--
2.8.0.rc3.226.g39d4020
More information about the U-Boot
mailing list