summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile54
-rwxr-xr-xtools/binman/binman.py3
-rw-r--r--tools/binman/control.py12
-rw-r--r--tools/binman/etype/u_boot_dtb_with_ucode.py24
-rw-r--r--tools/binman/fdt_test.py64
-rw-r--r--tools/binman/func_test.py48
-rw-r--r--tools/binman/test/45_prop_test.dts23
-rwxr-xr-xtools/dtoc/dtoc.py3
-rw-r--r--tools/dtoc/fdt.py183
-rw-r--r--tools/dtoc/fdt_fallback.py181
-rw-r--r--tools/dtoc/fdt_normal.py225
-rw-r--r--tools/dtoc/fdt_select.py36
12 files changed, 304 insertions, 552 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 2fc4a583d4..cb1683e153 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -60,9 +60,21 @@ hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
# Flattened device tree objects
-LIBFDT_OBJS := $(addprefix lib/libfdt/, \
- fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o \
- fdt_region.o fdt_sw.o)
+LIBFDT_CSRCS := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c \
+ fdt_empty_tree.c fdt_addresses.c fdt_overlay.c \
+ fdt_region.c
+
+# Unfortunately setup.py below cannot handle srctree being ".." which it often
+# is. It fails with an error like:
+# Fatal error: can't create build/temp.linux-x86_64-2.7/../lib/libfdt/fdt.o:
+# No such file or directory
+# To fix this, use an absolute path.
+libfdt_tree := $(shell readlink -f $(srctree)/lib/libfdt)
+
+LIBFDT_SRCS := $(addprefix $(libfdt_tree)/, $(LIBFDT_CSRCS))
+LIBFDT_SWIG := $(addprefix $(libfdt_tree)/, pylibfdt/libfdt.i)
+LIBFDT_OBJS := $(addprefix lib/libfdt/, $(patsubst %.c, %.o, $(LIBFDT_CSRCS)))
+
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
rsa-sign.o rsa-verify.o rsa-checksum.o \
rsa-mod-exp.o)
@@ -112,22 +124,22 @@ mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o
fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
-# Build a libfdt Python module if swig is available
-# Use 'sudo apt-get install swig libpython-dev' to enable this
-hostprogs-y += \
- $(if $(shell which swig 2> /dev/null),_libfdt.so)
-_libfdt.so-sharedobjs += $(LIBFDT_OBJS)
-libfdt:
-
-tools/_libfdt.so: $(patsubst %.o,%.c,$(LIBFDT_OBJS)) tools/libfdt_wrap.c
- LDFLAGS="$(HOSTLDFLAGS)" CFLAGS= ${PYTHON} $(srctree)/lib/libfdt/setup.py \
- "$(_hostc_flags)" $^
- mv _libfdt.so $@
-
-tools/libfdt_wrap.c: $(srctree)/lib/libfdt/libfdt.swig
- swig -python -o $@ $<
-
-# TODO(sjg@chromium.org): Is this correct on Mac OS?
+# Unfortunately setup.py (or actually the Python distutil implementation)
+# puts files into the same directory as the .i file. We cannot touch the source
+# directory, so we copy the .i file into the tools/ build subdirectory before
+# calling setup. This directory is safe to write to. This ensures that we get
+# all three files in $(obj)/tools: _libfdt.so, libfdt.py and libfdt_wrap.c
+# The latter is a temporary file which we could actually remove.
+tools/_libfdt.so: $(LIBFDT_SRCS) $(LIBFDT_SWIG)
+ cp $(LIBFDT_SWIG) tools/.
+ unset CC; \
+ unset CROSS_COMPILE; \
+ LDFLAGS="$(HOSTLDFLAGS)" CFLAGS= VERSION="u-boot-$(UBOOTVERSION)" \
+ CPPFLAGS="$(_hostc_flags)" OBJDIR=tools \
+ SOURCES="$(LIBFDT_SRCS) tools/libfdt.i" \
+ SWIG_OPTS="-I$(srctree)/lib/libfdt -I$(srctree)/lib" \
+ $(libfdt_tree)/pylibfdt/setup.py --quiet build_ext \
+ --build-lib tools
ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
@@ -216,6 +228,10 @@ clean-dirs := lib common
always := $(hostprogs-y)
+# Build a libfdt Python module if swig is available
+# Use 'sudo apt-get install swig libpython-dev' to enable this
+always += $(if $(shell which swig 2> /dev/null),_libfdt.so)
+
# Generated LCD/video logo
LOGO_H = $(objtree)/include/bmp_logo.h
LOGO_DATA_H = $(objtree)/include/bmp_logo_data.h
diff --git a/tools/binman/binman.py b/tools/binman/binman.py
index 857d698b4c..95d3a048d8 100755
--- a/tools/binman/binman.py
+++ b/tools/binman/binman.py
@@ -21,6 +21,9 @@ sys.path.append(os.path.join(our_path, '../patman'))
sys.path.append(os.path.join(our_path, '../dtoc'))
sys.path.append(os.path.join(our_path, '../'))
+# Bring in the libfdt module
+sys.path.append('tools')
+
# Also allow entry-type modules to be brought in from the etype directory.
sys.path.append(os.path.join(our_path, 'etype'))
diff --git a/tools/binman/control.py b/tools/binman/control.py
index e90967807c..e9d48df030 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -12,7 +12,7 @@ import sys
import tools
import command
-import fdt_select
+import fdt
import fdt_util
from image import Image
import tout
@@ -40,15 +40,15 @@ def _ReadImageDesc(binman_node):
images['image'] = Image('image', binman_node)
return images
-def _FindBinmanNode(fdt):
+def _FindBinmanNode(dtb):
"""Find the 'binman' node in the device tree
Args:
- fdt: Fdt object to scan
+ dtb: Fdt object to scan
Returns:
Node object of /binman node, or None if not found
"""
- for node in fdt.GetRoot().subnodes:
+ for node in dtb.GetRoot().subnodes:
if node.name == 'binman':
return node
return None
@@ -92,8 +92,8 @@ def Binman(options, args):
try:
tools.SetInputDirs(options.indir)
tools.PrepareOutputDir(options.outdir, options.preserve)
- fdt = fdt_select.FdtScan(dtb_fname)
- node = _FindBinmanNode(fdt)
+ dtb = fdt.FdtScan(dtb_fname)
+ node = _FindBinmanNode(dtb)
if not node:
raise ValueError("Device tree '%s' does not have a 'binman' "
"node" % dtb_fname)
diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
index fc02c67c14..a384a759c4 100644
--- a/tools/binman/etype/u_boot_dtb_with_ucode.py
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -6,7 +6,7 @@
# Entry-type module for U-Boot device tree with the microcode removed
#
-import fdt_select
+import fdt
from entry import Entry
from blob import Entry_blob
import tools
@@ -44,9 +44,8 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
fd.write(self.data)
# Remove the microcode
- fdt = fdt_select.FdtScan(fname)
- fdt.Scan()
- ucode = fdt.GetNode('/microcode')
+ dtb = fdt.FdtScan(fname)
+ ucode = dtb.GetNode('/microcode')
if not ucode:
raise self.Raise("No /microcode node found in '%s'" % fname)
@@ -57,20 +56,15 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
data_prop = node.props.get('data')
if data_prop:
self.ucode_data += ''.join(data_prop.bytes)
- if not self.collate:
- poffset = data_prop.GetOffset()
- if poffset is None:
- # We cannot obtain a property offset. Collate instead.
- self.collate = True
- else:
- # Find the offset in the device tree of the ucode data
- self.ucode_offset = poffset + 12
- self.ucode_size = len(data_prop.bytes)
if self.collate:
prop = node.DeleteProp('data')
+ else:
+ # Find the offset in the device tree of the ucode data
+ self.ucode_offset = data_prop.GetOffset() + 12
+ self.ucode_size = len(data_prop.bytes)
if self.collate:
- fdt.Pack()
- fdt.Flush()
+ dtb.Pack()
+ dtb.Flush()
# Make this file the contents of this entry
self._pathname = fname
diff --git a/tools/binman/fdt_test.py b/tools/binman/fdt_test.py
index 1d9494e52f..249a9ea388 100644
--- a/tools/binman/fdt_test.py
+++ b/tools/binman/fdt_test.py
@@ -11,7 +11,8 @@ import sys
import tempfile
import unittest
-from fdt_select import FdtScan
+import fdt
+from fdt import FdtScan
import fdt_util
import tools
@@ -28,21 +29,56 @@ class TestFdt(unittest.TestCase):
def GetCompiled(self, fname):
return fdt_util.EnsureCompiled(self.TestFile(fname))
- def _DeleteProp(self, fdt):
- node = fdt.GetNode('/microcode/update@0')
+ def _DeleteProp(self, dt):
+ node = dt.GetNode('/microcode/update@0')
node.DeleteProp('data')
def testFdtNormal(self):
fname = self.GetCompiled('34_x86_ucode.dts')
- fdt = FdtScan(fname)
- self._DeleteProp(fdt)
+ dt = FdtScan(fname)
+ self._DeleteProp(dt)
- def testFdtFallback(self):
- fname = self.GetCompiled('34_x86_ucode.dts')
- fdt = FdtScan(fname, True)
- fdt.GetProp('/microcode/update@0', 'data')
- self.assertEqual('fred',
- fdt.GetProp('/microcode/update@0', 'none', default='fred'))
- self.assertEqual('12345678 12345679',
- fdt.GetProp('/microcode/update@0', 'data', typespec='x'))
- self._DeleteProp(fdt)
+ def testFdtNormalProp(self):
+ fname = self.GetCompiled('45_prop_test.dts')
+ dt = FdtScan(fname)
+ node = dt.GetNode('/binman/intel-me')
+ self.assertEquals('intel-me', node.name)
+ val = fdt_util.GetString(node, 'filename')
+ self.assertEquals(str, type(val))
+ self.assertEquals('me.bin', val)
+
+ prop = node.props['intval']
+ self.assertEquals(fdt.TYPE_INT, prop.type)
+ self.assertEquals(3, fdt_util.GetInt(node, 'intval'))
+
+ prop = node.props['intarray']
+ self.assertEquals(fdt.TYPE_INT, prop.type)
+ self.assertEquals(list, type(prop.value))
+ self.assertEquals(2, len(prop.value))
+ self.assertEquals([5, 6],
+ [fdt_util.fdt32_to_cpu(val) for val in prop.value])
+
+ prop = node.props['byteval']
+ self.assertEquals(fdt.TYPE_BYTE, prop.type)
+ self.assertEquals(chr(8), prop.value)
+
+ prop = node.props['bytearray']
+ self.assertEquals(fdt.TYPE_BYTE, prop.type)
+ self.assertEquals(list, type(prop.value))
+ self.assertEquals(str, type(prop.value[0]))
+ self.assertEquals(3, len(prop.value))
+ self.assertEquals([chr(1), '#', '4'], prop.value)
+
+ prop = node.props['longbytearray']
+ self.assertEquals(fdt.TYPE_INT, prop.type)
+ self.assertEquals(0x090a0b0c, fdt_util.GetInt(node, 'longbytearray'))
+
+ prop = node.props['stringval']
+ self.assertEquals(fdt.TYPE_STRING, prop.type)
+ self.assertEquals('message2', fdt_util.GetString(node, 'stringval'))
+
+ prop = node.props['stringarray']
+ self.assertEquals(fdt.TYPE_STRING, prop.type)
+ self.assertEquals(list, type(prop.value))
+ self.assertEquals(3, len(prop.value))
+ self.assertEquals(['another', 'multi-word', 'message'], prop.value)
diff --git a/tools/binman/func_test.py b/tools/binman/func_test.py
index 740fa9e4e2..8b4db41659 100644
--- a/tools/binman/func_test.py
+++ b/tools/binman/func_test.py
@@ -21,7 +21,7 @@ import cmdline
import command
import control
import entry
-import fdt_select
+import fdt
import fdt_util
import tools
import tout
@@ -658,8 +658,8 @@ class TestFunctional(unittest.TestCase):
fname = tools.GetOutputFilename('test.dtb')
with open(fname, 'wb') as fd:
fd.write(second)
- fdt = fdt_select.FdtScan(fname)
- ucode = fdt.GetNode('/microcode')
+ dtb = fdt.FdtScan(fname)
+ ucode = dtb.GetNode('/microcode')
self.assertTrue(ucode)
for node in ucode.subnodes:
self.assertFalse(node.props.get('data'))
@@ -683,7 +683,7 @@ class TestFunctional(unittest.TestCase):
self.assertEqual('nodtb with microcode' + pos_and_size +
' somewhere in here', first)
- def _RunPackUbootSingleMicrocode(self, collate):
+ def _RunPackUbootSingleMicrocode(self):
"""Test that x86 microcode can be handled correctly
We expect to see the following in the image, in order:
@@ -695,8 +695,6 @@ class TestFunctional(unittest.TestCase):
# We need the libfdt library to run this test since only that allows
# finding the offset of a property. This is required by
# Entry_u_boot_dtb_with_ucode.ObtainContents().
- if not fdt_select.have_libfdt:
- return
data = self._DoReadFile('35_x86_single_ucode.dts', True)
second = data[len(U_BOOT_NODTB_DATA):]
@@ -705,34 +703,22 @@ class TestFunctional(unittest.TestCase):
third = second[fdt_len:]
second = second[:fdt_len]
- if not collate:
- ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
- self.assertIn(ucode_data, second)
- ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
+ ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
+ self.assertIn(ucode_data, second)
+ ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
- # Check that the microcode pointer was inserted. It should match the
- # expected position and size
- pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
- len(ucode_data))
- first = data[:len(U_BOOT_NODTB_DATA)]
- self.assertEqual('nodtb with microcode' + pos_and_size +
- ' somewhere in here', first)
+ # Check that the microcode pointer was inserted. It should match the
+ # expected position and size
+ pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
+ len(ucode_data))
+ first = data[:len(U_BOOT_NODTB_DATA)]
+ self.assertEqual('nodtb with microcode' + pos_and_size +
+ ' somewhere in here', first)
def testPackUbootSingleMicrocode(self):
"""Test that x86 microcode can be handled correctly with fdt_normal.
"""
- self._RunPackUbootSingleMicrocode(False)
-
- def testPackUbootSingleMicrocodeFallback(self):
- """Test that x86 microcode can be handled correctly with fdt_fallback.
-
- This only supports collating the microcode.
- """
- try:
- old_val = fdt_select.UseFallback(True)
- self._RunPackUbootSingleMicrocode(True)
- finally:
- fdt_select.UseFallback(old_val)
+ self._RunPackUbootSingleMicrocode()
def testUBootImg(self):
"""Test that u-boot.img can be put in a file"""
@@ -763,14 +749,12 @@ class TestFunctional(unittest.TestCase):
def testMicrocodeWithoutPtrInElf(self):
"""Test that a U-Boot binary without the microcode symbol is detected"""
# ELF file without a '_dt_ucode_base_size' symbol
- if not fdt_select.have_libfdt:
- return
try:
with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
TestFunctional._MakeInputFile('u-boot', fd.read())
with self.assertRaises(ValueError) as e:
- self._RunPackUbootSingleMicrocode(False)
+ self._RunPackUbootSingleMicrocode()
self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
"_dt_ucode_base_size symbol in u-boot", str(e.exception))
diff --git a/tools/binman/test/45_prop_test.dts b/tools/binman/test/45_prop_test.dts
new file mode 100644
index 0000000000..d22e460d29
--- /dev/null
+++ b/tools/binman/test/45_prop_test.dts
@@ -0,0 +1,23 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <16>;
+ intel-me {
+ filename = "me.bin";
+ pos-unset;
+ intval = <3>;
+ intarray = <5 6>;
+ byteval = [08];
+ bytearray = [01 23 34];
+ longbytearray = [09 0a 0b 0c];
+ stringval = "message2";
+ stringarray = "another", "multi-word", "message";
+ };
+ };
+};
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 816fdbe525..63a32ea2d7 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 FdtFallback and FdtNormal subclasses. 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.
# 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
@@ -96,6 +105,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
@@ -147,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:
@@ -188,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 should be implemented by subclasses
+ This fills in the props and subnodes properties, recursively
+ searching into subnodes so that the entire tree is built.
"""
- raise NotImplementedError()
+ 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
- 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
@@ -214,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
@@ -255,15 +309,100 @@ 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.
"""
- pass
+ 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
+ """
+ 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
+
+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_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 <sjg@chromium.org>
-#
-# 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_normal.py b/tools/dtoc/fdt_normal.py
deleted file mode 100644
index cce5c06d8c..0000000000
--- a/tools/dtoc/fdt_normal.py
+++ /dev/null
@@ -1,225 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2016 Google, Inc
-# Written by Simon Glass <sjg@chromium.org>
-#
-# 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 = 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 = libfdt.Name(self._fdt.GetFdt(), 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())
-
- 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:
- 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)
- 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
deleted file mode 100644
index ea78c527fc..0000000000
--- a/tools/dtoc/fdt_select.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2016 Google, Inc
-# Written by Simon Glass <sjg@chromium.org>
-#
-# 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
-
-def FdtScan(fname, _force_fallback=False):
- """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.Scan()
- return dtb
-
-def UseFallback(fallback):
- global force_fallback
-
- old_val = force_fallback
- force_fallback = fallback
- return old_val