$(call filechk,timestamp.h)
checkbinman: tools
- @if ! ( echo 'import libfdt' | ( PYTHONPATH=tools $(PYTHON) )); then \
+ @if ! ( echo 'import libfdt' | ( PYTHONPATH=scripts/dtc/pylibfdt $(PYTHON) )); then \
echo >&2; \
echo >&2 '*** binman needs the Python libfdt library.'; \
echo >&2 '*** Either install it on your system, or try:'; \
+++ /dev/null
-/*
- * pylibfdt - Flat Device Tree manipulation in Python
- * Copyright (C) 2017 Google, Inc.
- * Written by Simon Glass <sjg@chromium.org>
- *
- * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
- */
-
-%module libfdt
-
-%include <stdint.i>
-
-%{
-#define SWIG_FILE_WITH_INIT
-#include "libfdt.h"
-%}
-
-%pythoncode %{
-
-import struct
-
-# Error codes, corresponding to FDT_ERR_... in libfdt.h
-(NOTFOUND,
- EXISTS,
- NOSPACE,
- BADOFFSET,
- BADPATH,
- BADPHANDLE,
- BADSTATE,
- TRUNCATED,
- BADMAGIC,
- BADVERSION,
- BADSTRUCTURE,
- BADLAYOUT,
- INTERNAL,
- BADNCELLS,
- BADVALUE,
- BADOVERLAY,
- NOPHANDLES) = QUIET_ALL = range(1, 18)
-# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
-# altogether. All # functions passed this value will return an error instead
-# of raising an exception.
-
-# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
-# instead of raising an exception.
-QUIET_NOTFOUND = (NOTFOUND,)
-
-
-class FdtException(Exception):
- """An exception caused by an error such as one of the codes above"""
- def __init__(self, err):
- self.err = err
-
- def __str__(self):
- return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
-
-def strerror(fdt_err):
- """Get the string for an error number
-
- Args:
- fdt_err: Error number (-ve)
-
- Returns:
- String containing the associated error
- """
- return fdt_strerror(fdt_err)
-
-def check_err(val, quiet=()):
- """Raise an error if the return value is -ve
-
- This is used to check for errors returned by libfdt C functions.
-
- Args:
- val: Return value from a libfdt function
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- val if val >= 0
-
- Raises
- FdtException if val < 0
- """
- if val < 0:
- if -val not in quiet:
- raise FdtException(val)
- return val
-
-def check_err_null(val, quiet=()):
- """Raise an error if the return value is NULL
-
- This is used to check for a NULL return value from certain libfdt C
- functions
-
- Args:
- val: Return value from a libfdt function
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- val if val is a list, None if not
-
- Raises
- FdtException if val indicates an error was reported and the error
- is not in @quiet.
- """
- # Normally a list is returned which contains the data and its length.
- # If we get just an integer error code, it means the function failed.
- if not isinstance(val, list):
- if -val not in quiet:
- raise FdtException(val)
- return val
-
-class Fdt:
- """Device tree class, supporting all operations
-
- The Fdt object is created is created from a device tree binary file,
- e.g. with something like:
-
- fdt = Fdt(open("filename.dtb").read())
-
- Operations can then be performed using the methods in this class. Each
- method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
-
- All methods raise an FdtException if an error occurs. To avoid this
- behaviour a 'quiet' parameter is provided for some functions. This
- defaults to empty, but you can pass a list of errors that you expect.
- If one of these errors occurs, the function will return an error number
- (e.g. -NOTFOUND).
- """
- def __init__(self, data):
- self._fdt = bytearray(data)
- check_err(fdt_check_header(self._fdt));
-
- def subnode_offset(self, parentoffset, name, quiet=()):
- """Get the offset of a named subnode
-
- Args:
- parentoffset: Offset of the parent node to check
- name: Name of the required subnode, e.g. 'subnode@1'
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- The node offset of the found node, if any
-
- Raises
- FdtException if there is no node with that name, or other error
- """
- return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
- quiet)
-
- def path_offset(self, path, quiet=()):
- """Get the offset for a given path
-
- Args:
- path: Path to the required node, e.g. '/node@3/subnode@1'
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- Node offset
-
- Raises
- FdtException if the path is not valid or not found
- """
- return check_err(fdt_path_offset(self._fdt, path), quiet)
-
- def first_property_offset(self, nodeoffset, quiet=()):
- """Get the offset of the first property in a node offset
-
- Args:
- nodeoffset: Offset to the node to check
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- Offset of the first property
-
- Raises
- FdtException if the associated node has no properties, or some
- other error occurred
- """
- return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
- quiet)
-
- def next_property_offset(self, prop_offset, quiet=()):
- """Get the next property in a node
-
- Args:
- prop_offset: Offset of the previous property
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- Offset of the next property
-
- Raises:
- FdtException if the associated node has no more properties, or
- some other error occurred
- """
- return check_err(fdt_next_property_offset(self._fdt, prop_offset),
- quiet)
-
- def get_name(self, nodeoffset):
- """Get the name of a node
-
- Args:
- nodeoffset: Offset of node to check
-
- Returns:
- Node name
-
- Raises:
- FdtException on error (e.g. nodeoffset is invalid)
- """
- return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
-
- def get_property_by_offset(self, prop_offset, quiet=()):
- """Obtains a property that can be examined
-
- Args:
- prop_offset: Offset of property (e.g. from first_property_offset())
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- Property object, or None if not found
-
- Raises:
- FdtException on error (e.g. invalid prop_offset or device
- tree format)
- """
- pdata = check_err_null(
- fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
- if isinstance(pdata, (int)):
- return pdata
- return Property(pdata[0], pdata[1])
-
- def first_subnode(self, nodeoffset, quiet=()):
- """Find the first subnode of a parent node
-
- Args:
- nodeoffset: Node offset of parent node
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- The offset of the first subnode, if any
-
- Raises:
- FdtException if no subnode found or other error occurs
- """
- return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
-
- def next_subnode(self, nodeoffset, quiet=()):
- """Find the next subnode
-
- Args:
- nodeoffset: Node offset of previous subnode
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- The offset of the next subnode, if any
-
- Raises:
- FdtException if no more subnode found or other error occurs
- """
- return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
-
- def totalsize(self):
- """Return the total size of the device tree
-
- Returns:
- Total tree size in bytes
- """
- return check_err(fdt_totalsize(self._fdt))
-
- def off_dt_struct(self):
- """Return the start of the device tree struct area
-
- Returns:
- Start offset of struct area
- """
- return check_err(fdt_off_dt_struct(self._fdt))
-
- def pack(self, quiet=()):
- """Pack the device tree to remove unused space
-
- This adjusts the tree in place.
-
- Args:
- quiet: Errors to ignore (empty to raise on all errors)
-
- Raises:
- FdtException if any error occurs
- """
- return check_err(fdt_pack(self._fdt), quiet)
-
- def delprop(self, nodeoffset, prop_name):
- """Delete a property from a node
-
- Args:
- nodeoffset: Node offset containing property to delete
- prop_name: Name of property to delete
-
- Raises:
- FdtError if the property does not exist, or another error occurs
- """
- return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
-
- def getprop(self, nodeoffset, prop_name, quiet=()):
- """Get a property from a node
-
- Args:
- nodeoffset: Node offset containing property to get
- prop_name: Name of property to get
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- Value of property as a bytearray, or -ve error number
-
- Raises:
- FdtError if any error occurs (e.g. the property is not found)
- """
- pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
- quiet)
- if isinstance(pdata, (int)):
- return pdata
- return bytearray(pdata[0])
-
- def get_phandle(self, nodeoffset):
- """Get the phandle of a node
-
- Args:
- nodeoffset: Node offset to check
-
- Returns:
- phandle of node, or 0 if the node has no phandle or another error
- occurs
- """
- return fdt_get_phandle(self._fdt, nodeoffset)
-
- def parent_offset(self, nodeoffset, quiet=()):
- """Get the offset of a node's parent
-
- Args:
- nodeoffset: Node offset to check
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- The offset of the parent node, if any
-
- Raises:
- FdtException if no parent found or other error occurs
- """
- return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
-
- def node_offset_by_phandle(self, phandle, quiet=()):
- """Get the offset of a node with the given phandle
-
- Args:
- phandle: Phandle to search for
- quiet: Errors to ignore (empty to raise on all errors)
-
- Returns:
- The offset of node with that phandle, if any
-
- Raises:
- FdtException if no node found or other error occurs
- """
- return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
-
-class Property:
- """Holds a device tree property name and value.
-
- This holds a copy of a property taken from the device tree. It does not
- reference the device tree, so if anything changes in the device tree,
- a Property object will remain valid.
-
- Properties:
- name: Property name
- value: Proper value as a bytearray
- """
- def __init__(self, name, value):
- self.name = name
- self.value = value
-%}
-
-%rename(fdt_property) fdt_property_func;
-
-typedef int fdt32_t;
-
-%include "libfdt/fdt.h"
-
-%include "typemaps.i"
-
-/* Most functions don't change the device tree, so use a const void * */
-%typemap(in) (const void *)(const void *fdt) {
- if (!PyByteArray_Check($input)) {
- SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
- "', argument " "$argnum"" of type '" "$type""'");
- }
- $1 = (void *)PyByteArray_AsString($input);
- fdt = $1;
- fdt = fdt; /* avoid unused variable warning */
-}
-
-/* Some functions do change the device tree, so use void * */
-%typemap(in) (void *)(const void *fdt) {
- if (!PyByteArray_Check($input)) {
- SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
- "', argument " "$argnum"" of type '" "$type""'");
- }
- $1 = PyByteArray_AsString($input);
- fdt = $1;
- fdt = fdt; /* avoid unused variable warning */
-}
-
-%typemap(out) (struct fdt_property *) {
- PyObject *buff;
-
- if ($1) {
- resultobj = PyString_FromString(
- fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
- buff = PyByteArray_FromStringAndSize(
- (const char *)($1 + 1), fdt32_to_cpu($1->len));
- resultobj = SWIG_Python_AppendOutput(resultobj, buff);
- }
-}
-
-%apply int *OUTPUT { int *lenp };
-
-/* typemap used for fdt_getprop() */
-%typemap(out) (const void *) {
- if (!$1)
- $result = Py_None;
- else
- $result = Py_BuildValue("s#", $1, *arg4);
-}
-
-/* We have both struct fdt_property and a function fdt_property() */
-%warnfilter(302) fdt_property;
-
-/* These are macros in the header so have to be redefined here */
-int fdt_magic(const void *fdt);
-int fdt_totalsize(const void *fdt);
-int fdt_off_dt_struct(const void *fdt);
-int fdt_off_dt_strings(const void *fdt);
-int fdt_off_mem_rsvmap(const void *fdt);
-int fdt_version(const void *fdt);
-int fdt_last_comp_version(const void *fdt);
-int fdt_boot_cpuid_phys(const void *fdt);
-int fdt_size_dt_strings(const void *fdt);
-int fdt_size_dt_struct(const void *fdt);
-
-%include <../libfdt/libfdt.h>
+++ /dev/null
-#!/usr/bin/env python
-
-"""
-setup.py file for SWIG libfdt
-Copyright (C) 2017 Google, Inc.
-Written by Simon Glass <sjg@chromium.org>
-
-SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
-
-Files to be built into the extension are provided in SOURCES
-C flags to use are provided in CPPFLAGS
-Object file directory is provided in OBJDIR
-Version is provided in VERSION
-
-If these variables are not given they are parsed from the Makefiles. This
-allows this script to be run stand-alone, e.g.:
-
- ./pylibfdt/setup.py install [--prefix=...]
-"""
-
-from distutils.core import setup, Extension
-import os
-import re
-import sys
-
-# Decodes a Makefile assignment line into key and value (and plus for +=)
-RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')
-
-
-def ParseMakefile(fname):
- """Parse a Makefile to obtain its variables.
-
- This collects variable assigments of the form:
-
- VAR = value
- VAR += more
-
- It does not pick out := assignments, as these are not needed here. It does
- handle line continuation.
-
- Returns a dict:
- key: Variable name (e.g. 'VAR')
- value: Variable value (e.g. 'value more')
- """
- makevars = {}
- with open(fname) as fd:
- prev_text = '' # Continuation text from previous line(s)
- for line in fd.read().splitlines():
- if line and line[-1] == '\\': # Deal with line continuation
- prev_text += line[:-1]
- continue
- elif prev_text:
- line = prev_text + line
- prev_text = '' # Continuation is now used up
- m = RE_KEY_VALUE.match(line)
- if m:
- value = m.group('value') or ''
- key = m.group('key')
-
- # Appending to a variable inserts a space beforehand
- if 'plus' in m.groupdict() and key in makevars:
- makevars[key] += ' ' + value
- else:
- makevars[key] = value
- return makevars
-
-def GetEnvFromMakefiles():
- """Scan the Makefiles to obtain the settings we need.
-
- This assumes that this script is being run from the top-level directory,
- not the pylibfdt directory.
-
- Returns:
- Tuple with:
- List of swig options
- Version string
- List of files to build
- List of extra C preprocessor flags needed
- Object directory to use (always '')
- """
- basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
- swig_opts = ['-I%s' % basedir]
- makevars = ParseMakefile(os.path.join(basedir, 'Makefile'))
- version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'],
- makevars['SUBLEVEL'])
- makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
- files = makevars['LIBFDT_SRCS'].split()
- files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
- files.append('pylibfdt/libfdt.i')
- cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
- objdir = ''
- return swig_opts, version, files, cflags, objdir
-
-
-progname = sys.argv[0]
-files = os.environ.get('SOURCES', '').split()
-cflags = os.environ.get('CPPFLAGS', '').split()
-objdir = os.environ.get('OBJDIR')
-version = os.environ.get('VERSION')
-swig_opts = os.environ.get('SWIG_OPTS', '').split()
-
-# If we were called directly rather than through our Makefile (which is often
-# the case with Python module installation), read the settings from the
-# Makefile.
-if not all((swig_opts, version, files, cflags, objdir)):
- swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()
-
-libfdt_module = Extension(
- '_libfdt',
- sources = files,
- extra_compile_args = cflags,
- swig_opts = swig_opts,
-)
-
-setup(
- name='libfdt',
- version= version,
- author='Simon Glass <sjg@chromium.org>',
- description='Python binding for libfdt',
- ext_modules=[libfdt_module],
- package_dir={'': objdir},
- py_modules=['pylibfdt/libfdt'],
-)
$(obj)/$(SPL_BIN).dtb: dts/dt.dtb $(objtree)/tools/fdtgrep FORCE
$(call if_changed,fdtgrep)
-pythonpath = PYTHONPATH=tools
+pythonpath = PYTHONPATH=scripts/dtc/pylibfdt
quiet_cmd_dtocc = DTOC C $@
cmd_dtocc = $(pythonpath) $(srctree)/tools/dtoc/dtoc -d $(obj)/$(SPL_BIN).dtb -o $@ platdata
endif
checkdtoc: tools
- @if ! ( echo 'import libfdt' | ( PYTHONPATH=tools $(PYTHON) )); then \
+ @if ! ( echo 'import libfdt' | ( PYTHONPATH=scripts/dtc/pylibfdt $(PYTHON) )); then \
echo '*** dtoc needs the Python libfdt library. Either '; \
echo '*** install it on your system, or try:'; \
echo '***'; \
# generated files need to be cleaned explicitly
clean-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
+
+# Added for U-Boot
+subdir-y += pylibfdt
--- /dev/null
+/_libfdt.so
+/libfdt.py
+/libfdt.pyc
+/libfdt_wrap.c
--- /dev/null
+# 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_srcdir = $(abspath $(srctree)/$(src)/../libfdt)
+
+include $(LIBFDT_srcdir)/Makefile.libfdt
+
+# 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 "ship" .i file into the objtree.
+PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \
+ $(obj)/libfdt.i
+
+quiet_cmd_pymod = PYMOD $@
+ cmd_pymod = unset CC; unset CROSS_COMPILE; unset CFLAGS;\
+ LDFLAGS="$(HOSTLDFLAGS)" \
+ VERSION="u-boot-$(UBOOTVERSION)" \
+ CPPFLAGS="$(HOSTCFLAGS) -I$(LIBFDT_srcdir)" OBJDIR=$(obj) \
+ SOURCES="$(PYLIBFDT_srcs)" \
+ SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \
+ $(PYTHON) $< --quiet build_ext --inplace
+
+$(obj)/_libfdt.so: $(src)/setup.py $(PYLIBFDT_srcs) FORCE
+ $(call if_changed,pymod)
+
+always += _libfdt.so
+
+clean-files += libfdt.i _libfdt.so libfdt.py libfdt_wrap.c
--- /dev/null
+/*
+ * pylibfdt - Flat Device Tree manipulation in Python
+ * Copyright (C) 2017 Google, Inc.
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
+ */
+
+%module libfdt
+
+%include <stdint.i>
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "libfdt.h"
+%}
+
+%pythoncode %{
+
+import struct
+
+# Error codes, corresponding to FDT_ERR_... in libfdt.h
+(NOTFOUND,
+ EXISTS,
+ NOSPACE,
+ BADOFFSET,
+ BADPATH,
+ BADPHANDLE,
+ BADSTATE,
+ TRUNCATED,
+ BADMAGIC,
+ BADVERSION,
+ BADSTRUCTURE,
+ BADLAYOUT,
+ INTERNAL,
+ BADNCELLS,
+ BADVALUE,
+ BADOVERLAY,
+ NOPHANDLES) = QUIET_ALL = range(1, 18)
+# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
+# altogether. All # functions passed this value will return an error instead
+# of raising an exception.
+
+# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
+# instead of raising an exception.
+QUIET_NOTFOUND = (NOTFOUND,)
+
+
+class FdtException(Exception):
+ """An exception caused by an error such as one of the codes above"""
+ def __init__(self, err):
+ self.err = err
+
+ def __str__(self):
+ return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
+
+def strerror(fdt_err):
+ """Get the string for an error number
+
+ Args:
+ fdt_err: Error number (-ve)
+
+ Returns:
+ String containing the associated error
+ """
+ return fdt_strerror(fdt_err)
+
+def check_err(val, quiet=()):
+ """Raise an error if the return value is -ve
+
+ This is used to check for errors returned by libfdt C functions.
+
+ Args:
+ val: Return value from a libfdt function
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ val if val >= 0
+
+ Raises
+ FdtException if val < 0
+ """
+ if val < 0:
+ if -val not in quiet:
+ raise FdtException(val)
+ return val
+
+def check_err_null(val, quiet=()):
+ """Raise an error if the return value is NULL
+
+ This is used to check for a NULL return value from certain libfdt C
+ functions
+
+ Args:
+ val: Return value from a libfdt function
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ val if val is a list, None if not
+
+ Raises
+ FdtException if val indicates an error was reported and the error
+ is not in @quiet.
+ """
+ # Normally a list is returned which contains the data and its length.
+ # If we get just an integer error code, it means the function failed.
+ if not isinstance(val, list):
+ if -val not in quiet:
+ raise FdtException(val)
+ return val
+
+class Fdt:
+ """Device tree class, supporting all operations
+
+ The Fdt object is created is created from a device tree binary file,
+ e.g. with something like:
+
+ fdt = Fdt(open("filename.dtb").read())
+
+ Operations can then be performed using the methods in this class. Each
+ method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
+
+ All methods raise an FdtException if an error occurs. To avoid this
+ behaviour a 'quiet' parameter is provided for some functions. This
+ defaults to empty, but you can pass a list of errors that you expect.
+ If one of these errors occurs, the function will return an error number
+ (e.g. -NOTFOUND).
+ """
+ def __init__(self, data):
+ self._fdt = bytearray(data)
+ check_err(fdt_check_header(self._fdt));
+
+ def subnode_offset(self, parentoffset, name, quiet=()):
+ """Get the offset of a named subnode
+
+ Args:
+ parentoffset: Offset of the parent node to check
+ name: Name of the required subnode, e.g. 'subnode@1'
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The node offset of the found node, if any
+
+ Raises
+ FdtException if there is no node with that name, or other error
+ """
+ return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
+ quiet)
+
+ def path_offset(self, path, quiet=()):
+ """Get the offset for a given path
+
+ Args:
+ path: Path to the required node, e.g. '/node@3/subnode@1'
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ Node offset
+
+ Raises
+ FdtException if the path is not valid or not found
+ """
+ return check_err(fdt_path_offset(self._fdt, path), quiet)
+
+ def first_property_offset(self, nodeoffset, quiet=()):
+ """Get the offset of the first property in a node offset
+
+ Args:
+ nodeoffset: Offset to the node to check
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ Offset of the first property
+
+ Raises
+ FdtException if the associated node has no properties, or some
+ other error occurred
+ """
+ return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
+ quiet)
+
+ def next_property_offset(self, prop_offset, quiet=()):
+ """Get the next property in a node
+
+ Args:
+ prop_offset: Offset of the previous property
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ Offset of the next property
+
+ Raises:
+ FdtException if the associated node has no more properties, or
+ some other error occurred
+ """
+ return check_err(fdt_next_property_offset(self._fdt, prop_offset),
+ quiet)
+
+ def get_name(self, nodeoffset):
+ """Get the name of a node
+
+ Args:
+ nodeoffset: Offset of node to check
+
+ Returns:
+ Node name
+
+ Raises:
+ FdtException on error (e.g. nodeoffset is invalid)
+ """
+ return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
+
+ def get_property_by_offset(self, prop_offset, quiet=()):
+ """Obtains a property that can be examined
+
+ Args:
+ prop_offset: Offset of property (e.g. from first_property_offset())
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ Property object, or None if not found
+
+ Raises:
+ FdtException on error (e.g. invalid prop_offset or device
+ tree format)
+ """
+ pdata = check_err_null(
+ fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
+ if isinstance(pdata, (int)):
+ return pdata
+ return Property(pdata[0], pdata[1])
+
+ def first_subnode(self, nodeoffset, quiet=()):
+ """Find the first subnode of a parent node
+
+ Args:
+ nodeoffset: Node offset of parent node
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The offset of the first subnode, if any
+
+ Raises:
+ FdtException if no subnode found or other error occurs
+ """
+ return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
+
+ def next_subnode(self, nodeoffset, quiet=()):
+ """Find the next subnode
+
+ Args:
+ nodeoffset: Node offset of previous subnode
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The offset of the next subnode, if any
+
+ Raises:
+ FdtException if no more subnode found or other error occurs
+ """
+ return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
+
+ def totalsize(self):
+ """Return the total size of the device tree
+
+ Returns:
+ Total tree size in bytes
+ """
+ return check_err(fdt_totalsize(self._fdt))
+
+ def off_dt_struct(self):
+ """Return the start of the device tree struct area
+
+ Returns:
+ Start offset of struct area
+ """
+ return check_err(fdt_off_dt_struct(self._fdt))
+
+ def pack(self, quiet=()):
+ """Pack the device tree to remove unused space
+
+ This adjusts the tree in place.
+
+ Args:
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Raises:
+ FdtException if any error occurs
+ """
+ return check_err(fdt_pack(self._fdt), quiet)
+
+ def delprop(self, nodeoffset, prop_name):
+ """Delete a property from a node
+
+ Args:
+ nodeoffset: Node offset containing property to delete
+ prop_name: Name of property to delete
+
+ Raises:
+ FdtError if the property does not exist, or another error occurs
+ """
+ return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
+
+ def getprop(self, nodeoffset, prop_name, quiet=()):
+ """Get a property from a node
+
+ Args:
+ nodeoffset: Node offset containing property to get
+ prop_name: Name of property to get
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ Value of property as a bytearray, or -ve error number
+
+ Raises:
+ FdtError if any error occurs (e.g. the property is not found)
+ """
+ pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
+ quiet)
+ if isinstance(pdata, (int)):
+ return pdata
+ return bytearray(pdata[0])
+
+ def get_phandle(self, nodeoffset):
+ """Get the phandle of a node
+
+ Args:
+ nodeoffset: Node offset to check
+
+ Returns:
+ phandle of node, or 0 if the node has no phandle or another error
+ occurs
+ """
+ return fdt_get_phandle(self._fdt, nodeoffset)
+
+ def parent_offset(self, nodeoffset, quiet=()):
+ """Get the offset of a node's parent
+
+ Args:
+ nodeoffset: Node offset to check
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The offset of the parent node, if any
+
+ Raises:
+ FdtException if no parent found or other error occurs
+ """
+ return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
+
+ def node_offset_by_phandle(self, phandle, quiet=()):
+ """Get the offset of a node with the given phandle
+
+ Args:
+ phandle: Phandle to search for
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The offset of node with that phandle, if any
+
+ Raises:
+ FdtException if no node found or other error occurs
+ """
+ return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
+
+class Property:
+ """Holds a device tree property name and value.
+
+ This holds a copy of a property taken from the device tree. It does not
+ reference the device tree, so if anything changes in the device tree,
+ a Property object will remain valid.
+
+ Properties:
+ name: Property name
+ value: Proper value as a bytearray
+ """
+ def __init__(self, name, value):
+ self.name = name
+ self.value = value
+%}
+
+%rename(fdt_property) fdt_property_func;
+
+typedef int fdt32_t;
+
+%include "libfdt/fdt.h"
+
+%include "typemaps.i"
+
+/* Most functions don't change the device tree, so use a const void * */
+%typemap(in) (const void *)(const void *fdt) {
+ if (!PyByteArray_Check($input)) {
+ SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
+ "', argument " "$argnum"" of type '" "$type""'");
+ }
+ $1 = (void *)PyByteArray_AsString($input);
+ fdt = $1;
+ fdt = fdt; /* avoid unused variable warning */
+}
+
+/* Some functions do change the device tree, so use void * */
+%typemap(in) (void *)(const void *fdt) {
+ if (!PyByteArray_Check($input)) {
+ SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
+ "', argument " "$argnum"" of type '" "$type""'");
+ }
+ $1 = PyByteArray_AsString($input);
+ fdt = $1;
+ fdt = fdt; /* avoid unused variable warning */
+}
+
+%typemap(out) (struct fdt_property *) {
+ PyObject *buff;
+
+ if ($1) {
+ resultobj = PyString_FromString(
+ fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
+ buff = PyByteArray_FromStringAndSize(
+ (const char *)($1 + 1), fdt32_to_cpu($1->len));
+ resultobj = SWIG_Python_AppendOutput(resultobj, buff);
+ }
+}
+
+%apply int *OUTPUT { int *lenp };
+
+/* typemap used for fdt_getprop() */
+%typemap(out) (const void *) {
+ if (!$1)
+ $result = Py_None;
+ else
+ $result = Py_BuildValue("s#", $1, *arg4);
+}
+
+/* We have both struct fdt_property and a function fdt_property() */
+%warnfilter(302) fdt_property;
+
+/* These are macros in the header so have to be redefined here */
+int fdt_magic(const void *fdt);
+int fdt_totalsize(const void *fdt);
+int fdt_off_dt_struct(const void *fdt);
+int fdt_off_dt_strings(const void *fdt);
+int fdt_off_mem_rsvmap(const void *fdt);
+int fdt_version(const void *fdt);
+int fdt_last_comp_version(const void *fdt);
+int fdt_boot_cpuid_phys(const void *fdt);
+int fdt_size_dt_strings(const void *fdt);
+int fdt_size_dt_struct(const void *fdt);
+
+%include <../libfdt/libfdt.h>
--- /dev/null
+#!/usr/bin/env python
+
+"""
+setup.py file for SWIG libfdt
+Copyright (C) 2017 Google, Inc.
+Written by Simon Glass <sjg@chromium.org>
+
+SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
+
+Files to be built into the extension are provided in SOURCES
+C flags to use are provided in CPPFLAGS
+Object file directory is provided in OBJDIR
+Version is provided in VERSION
+
+If these variables are not given they are parsed from the Makefiles. This
+allows this script to be run stand-alone, e.g.:
+
+ ./pylibfdt/setup.py install [--prefix=...]
+"""
+
+from distutils.core import setup, Extension
+import os
+import re
+import sys
+
+# Decodes a Makefile assignment line into key and value (and plus for +=)
+RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')
+
+
+def ParseMakefile(fname):
+ """Parse a Makefile to obtain its variables.
+
+ This collects variable assigments of the form:
+
+ VAR = value
+ VAR += more
+
+ It does not pick out := assignments, as these are not needed here. It does
+ handle line continuation.
+
+ Returns a dict:
+ key: Variable name (e.g. 'VAR')
+ value: Variable value (e.g. 'value more')
+ """
+ makevars = {}
+ with open(fname) as fd:
+ prev_text = '' # Continuation text from previous line(s)
+ for line in fd.read().splitlines():
+ if line and line[-1] == '\\': # Deal with line continuation
+ prev_text += line[:-1]
+ continue
+ elif prev_text:
+ line = prev_text + line
+ prev_text = '' # Continuation is now used up
+ m = RE_KEY_VALUE.match(line)
+ if m:
+ value = m.group('value') or ''
+ key = m.group('key')
+
+ # Appending to a variable inserts a space beforehand
+ if 'plus' in m.groupdict() and key in makevars:
+ makevars[key] += ' ' + value
+ else:
+ makevars[key] = value
+ return makevars
+
+def GetEnvFromMakefiles():
+ """Scan the Makefiles to obtain the settings we need.
+
+ This assumes that this script is being run from the top-level directory,
+ not the pylibfdt directory.
+
+ Returns:
+ Tuple with:
+ List of swig options
+ Version string
+ List of files to build
+ List of extra C preprocessor flags needed
+ Object directory to use (always '')
+ """
+ basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
+ swig_opts = ['-I%s' % basedir]
+ makevars = ParseMakefile(os.path.join(basedir, 'Makefile'))
+ version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'],
+ makevars['SUBLEVEL'])
+ makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
+ files = makevars['LIBFDT_SRCS'].split()
+ files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
+ files.append('pylibfdt/libfdt.i')
+ cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
+ objdir = ''
+ return swig_opts, version, files, cflags, objdir
+
+
+progname = sys.argv[0]
+files = os.environ.get('SOURCES', '').split()
+cflags = os.environ.get('CPPFLAGS', '').split()
+objdir = os.environ.get('OBJDIR')
+version = os.environ.get('VERSION')
+swig_opts = os.environ.get('SWIG_OPTS', '').split()
+
+# If we were called directly rather than through our Makefile (which is often
+# the case with Python module installation), read the settings from the
+# Makefile.
+if not all((swig_opts, version, files, cflags, objdir)):
+ swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()
+
+libfdt_module = Extension(
+ '_libfdt',
+ sources = files,
+ extra_compile_args = cflags,
+ swig_opts = swig_opts,
+)
+
+setup(
+ name='libfdt',
+ version= version,
+ author='Simon Glass <sjg@chromium.org>',
+ description='Python binding for libfdt',
+ ext_modules=[libfdt_module],
+ package_dir={'': objdir},
+ py_modules=['pylibfdt/libfdt'],
+)
-/_libfdt.so
/atmel_pmecc_params
/bin2header
/bmp_logo
/img2srec
/kwboot
/lib/
-/libfdt.py
-/libfdt.pyc
-/libfdt_wrap.c
/mips-relocs
/mkenvimage
/mkexynosspl
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/, \
fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
-# 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)
- $(Q)cp $(LIBFDT_SWIG) tools/.
- $(Q)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" \
- $(PYTHON) $(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
# the mxsimage support within tools/mxsimage.c .
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
sys.path.insert(0, os.path.join(our_path, dirname))
# Bring in the libfdt module
-sys.path.insert(0, 'tools')
+sys.path.insert(0, 'scripts/dtc/pylibfdt')
# Also allow entry-type modules to be brought in from the etype directory.
sys.path.insert(0, os.path.join(our_path, 'etype'))