2300 lines
74 KiB
Diff
2300 lines
74 KiB
Diff
From 50f2507016315e0b9499dd58876ffc1acf91cc5a Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 17 Mar 2017 16:14:30 -0600
|
|
Subject: [PATCH 01/29] Add an initial Python library for libfdt
|
|
|
|
Add Python bindings for a bare-bones set of libfdt functions. These allow
|
|
navigating the tree and reading node names and properties.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 1 +
|
|
pylibfdt/.gitignore | 3 +
|
|
pylibfdt/Makefile.pylibfdt | 17 ++
|
|
pylibfdt/libfdt.swig | 433 +++++++++++++++++++++++++++++++++++++++++++++
|
|
pylibfdt/setup.py | 34 ++++
|
|
5 files changed, 488 insertions(+)
|
|
create mode 100644 pylibfdt/.gitignore
|
|
create mode 100644 pylibfdt/Makefile.pylibfdt
|
|
create mode 100644 pylibfdt/libfdt.swig
|
|
create mode 100644 pylibfdt/setup.py
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index c3f72e0..1b69f53 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -22,6 +22,7 @@ CFLAGS = -g -Os -fPIC -Werror $(WARNINGS)
|
|
|
|
BISON = bison
|
|
LEX = flex
|
|
+SWIG = swig
|
|
|
|
INSTALL = /usr/bin/install
|
|
DESTDIR =
|
|
diff --git a/pylibfdt/.gitignore b/pylibfdt/.gitignore
|
|
new file mode 100644
|
|
index 0000000..5e8c5e3
|
|
--- /dev/null
|
|
+++ b/pylibfdt/.gitignore
|
|
@@ -0,0 +1,3 @@
|
|
+libfdt.py
|
|
+libfdt.pyc
|
|
+libfdt_wrap.c
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
new file mode 100644
|
|
index 0000000..0d8c010
|
|
--- /dev/null
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -0,0 +1,17 @@
|
|
+# Makefile.pylibfdt
|
|
+#
|
|
+
|
|
+PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS))
|
|
+WRAP = $(PYLIBFDT_objdir)/libfdt_wrap.c
|
|
+PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
|
+
|
|
+$(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
+ @$(VECHO) PYMOD $@
|
|
+ python $(PYLIBFDT_objdir)/setup.py "$(CPPFLAGS)" $^
|
|
+ mv _libfdt.so $(PYMODULE)
|
|
+
|
|
+$(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
+ @$(VECHO) SWIG $@
|
|
+ $(SWIG) -python -o $@ $<
|
|
+
|
|
+PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so
|
|
diff --git a/pylibfdt/libfdt.swig b/pylibfdt/libfdt.swig
|
|
new file mode 100644
|
|
index 0000000..cd1c6a9
|
|
--- /dev/null
|
|
+++ b/pylibfdt/libfdt.swig
|
|
@@ -0,0 +1,433 @@
|
|
+/*
|
|
+ * pylibfdt - Flat Device Tree manipulation in Python
|
|
+ * Copyright (C) 2017 Google, Inc.
|
|
+ * Written by Simon Glass <sjg@chromium.org>
|
|
+ *
|
|
+ * libfdt is dual licensed: you can use it either under the terms of
|
|
+ * the GPL, or the BSD license, at your option.
|
|
+ *
|
|
+ * a) This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License as
|
|
+ * published by the Free Software Foundation; either version 2 of the
|
|
+ * License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public
|
|
+ * License along with this library; if not, write to the Free
|
|
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
+ * MA 02110-1301 USA
|
|
+ *
|
|
+ * Alternatively,
|
|
+ *
|
|
+ * b) Redistribution and use in source and binary forms, with or
|
|
+ * without modification, are permitted provided that the following
|
|
+ * conditions are met:
|
|
+ *
|
|
+ * 1. Redistributions of source code must retain the above
|
|
+ * copyright notice, this list of conditions and the following
|
|
+ * disclaimer.
|
|
+ * 2. Redistributions in binary form must reproduce the above
|
|
+ * copyright notice, this list of conditions and the following
|
|
+ * disclaimer in the documentation and/or other materials
|
|
+ * provided with the distribution.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
+ */
|
|
+
|
|
+%module libfdt
|
|
+
|
|
+%{
|
|
+#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 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])
|
|
+
|
|
+
|
|
+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>
|
|
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
|
|
new file mode 100644
|
|
index 0000000..0ff160c
|
|
--- /dev/null
|
|
+++ b/pylibfdt/setup.py
|
|
@@ -0,0 +1,34 @@
|
|
+#!/usr/bin/env python
|
|
+
|
|
+"""
|
|
+setup.py file for SWIG libfdt
|
|
+"""
|
|
+
|
|
+from distutils.core import setup, Extension
|
|
+import os
|
|
+import sys
|
|
+
|
|
+progname = sys.argv[0]
|
|
+cflags = sys.argv[1]
|
|
+files = sys.argv[2:]
|
|
+
|
|
+if cflags:
|
|
+ cflags = [flag for flag in cflags.split(' ') if flag]
|
|
+else:
|
|
+ cflags = None
|
|
+
|
|
+libfdt_module = Extension(
|
|
+ '_libfdt',
|
|
+ sources = files,
|
|
+ extra_compile_args = cflags
|
|
+)
|
|
+
|
|
+sys.argv = [progname, '--quiet', 'build_ext', '--inplace']
|
|
+
|
|
+setup (name = 'libfdt',
|
|
+ version = '0.1',
|
|
+ author = "Simon Glass <sjg@chromium.org>",
|
|
+ description = """Python binding for libfdt""",
|
|
+ ext_modules = [libfdt_module],
|
|
+ py_modules = ["libfdt"],
|
|
+ )
|
|
--
|
|
2.13.0
|
|
|
|
From 12cfb740cc76c9c9fa906fee240dc028da2bddd0 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 17 Mar 2017 16:14:31 -0600
|
|
Subject: [PATCH 02/29] Add tests for pylibfdt
|
|
|
|
Add a set of tests to cover the functionality in pylibfdt.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
tests/pylibfdt_tests.py | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 288 insertions(+)
|
|
create mode 100644 tests/pylibfdt_tests.py
|
|
|
|
diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py
|
|
new file mode 100644
|
|
index 0000000..ae392bb
|
|
--- /dev/null
|
|
+++ b/tests/pylibfdt_tests.py
|
|
@@ -0,0 +1,288 @@
|
|
+# pylibfdt - Tests for Flat Device Tree manipulation in Python
|
|
+# Copyright (C) 2017 Google, Inc.
|
|
+# Written by Simon Glass <sjg@chromium.org>
|
|
+#
|
|
+# libfdt is dual licensed: you can use it either under the terms of
|
|
+# the GPL, or the BSD license, at your option.
|
|
+#
|
|
+# a) This library is free software; you can redistribute it and/or
|
|
+# modify it under the terms of the GNU General Public License as
|
|
+# published by the Free Software Foundation; either version 2 of the
|
|
+# License, or (at your option) any later version.
|
|
+#
|
|
+# This library is distributed in the hope that it will be useful,
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+# GNU General Public License for more details.
|
|
+#
|
|
+# You should have received a copy of the GNU General Public
|
|
+# License along with this library; if not, write to the Free
|
|
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
+# MA 02110-1301 USA
|
|
+#
|
|
+# Alternatively,
|
|
+#
|
|
+# b) Redistribution and use in source and binary forms, with or
|
|
+# without modification, are permitted provided that the following
|
|
+# conditions are met:
|
|
+#
|
|
+# 1. Redistributions of source code must retain the above
|
|
+# copyright notice, this list of conditions and the following
|
|
+# disclaimer.
|
|
+# 2. Redistributions in binary form must reproduce the above
|
|
+# copyright notice, this list of conditions and the following
|
|
+# disclaimer in the documentation and/or other materials
|
|
+# provided with the distribution.
|
|
+#
|
|
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
+# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
+#
|
|
+
|
|
+import sys
|
|
+import types
|
|
+import unittest
|
|
+
|
|
+sys.path.append('../pylibfdt')
|
|
+import libfdt
|
|
+from libfdt import FdtException, QUIET_NOTFOUND, QUIET_ALL
|
|
+
|
|
+def get_err(err_code):
|
|
+ """Convert an error code into an error message
|
|
+
|
|
+ Args:
|
|
+ err_code: Error code value (FDT_ERR_...)
|
|
+
|
|
+ Returns:
|
|
+ String error code
|
|
+ """
|
|
+ return 'pylibfdt error %d: %s' % (-err_code, libfdt.fdt_strerror(-err_code))
|
|
+
|
|
+def _ReadFdt(fname):
|
|
+ """Read a device tree file into an Fdt object, ready for use
|
|
+
|
|
+ Args:
|
|
+ fname: Filename to read from
|
|
+
|
|
+ Returns:
|
|
+ Fdt bytearray suitable for passing to libfdt functions
|
|
+ """
|
|
+ return libfdt.Fdt(open(fname).read())
|
|
+
|
|
+class PyLibfdtTests(unittest.TestCase):
|
|
+ """Test class for pylibfdt
|
|
+
|
|
+ Properties:
|
|
+ fdt: Device tree file used for testing
|
|
+ """
|
|
+
|
|
+ def setUp(self):
|
|
+ """Read in the device tree we use for testing"""
|
|
+ self.fdt = _ReadFdt('test_tree1.dtb')
|
|
+
|
|
+ def GetPropList(self, node_path):
|
|
+ """Read a list of properties from a node
|
|
+
|
|
+ Args:
|
|
+ node_path: Full path to node, e.g. '/subnode@1/subsubnode'
|
|
+
|
|
+ Returns:
|
|
+ List of property names for that node, e.g. ['compatible', 'reg']
|
|
+ """
|
|
+ prop_list = []
|
|
+ node = self.fdt.path_offset(node_path)
|
|
+ poffset = self.fdt.first_property_offset(node, QUIET_NOTFOUND)
|
|
+ while poffset > 0:
|
|
+ prop = self.fdt.get_property_by_offset(poffset)
|
|
+ prop_list.append(prop.name)
|
|
+ poffset = self.fdt.next_property_offset(poffset, QUIET_NOTFOUND)
|
|
+ return prop_list
|
|
+
|
|
+ def testImport(self):
|
|
+ """Check that we can import the library correctly"""
|
|
+ self.assertEquals(type(libfdt), types.ModuleType)
|
|
+
|
|
+ def testBadFdt(self):
|
|
+ """Check that a filename provided accidentally is not accepted"""
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ fdt = libfdt.Fdt('a string')
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADMAGIC)
|
|
+
|
|
+ def testPathOffset(self):
|
|
+ """Check that we can find the offset of a node"""
|
|
+ self.assertEquals(self.fdt.path_offset('/'), 0)
|
|
+ self.assertTrue(self.fdt.path_offset('/subnode@1') > 0)
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.path_offset('/wibble')
|
|
+ self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
|
|
+ self.assertEquals(self.fdt.path_offset('/wibble', QUIET_NOTFOUND),
|
|
+ -libfdt.NOTFOUND)
|
|
+
|
|
+ def testPropertyOffset(self):
|
|
+ """Walk through all the properties in the root node"""
|
|
+ offset = self.fdt.first_property_offset(0)
|
|
+ self.assertTrue(offset > 0)
|
|
+ for i in range(5):
|
|
+ next_offset = self.fdt.next_property_offset(offset)
|
|
+ self.assertTrue(next_offset > offset)
|
|
+ offset = next_offset
|
|
+ self.assertEquals(self.fdt.next_property_offset(offset, QUIET_NOTFOUND),
|
|
+ -libfdt.NOTFOUND)
|
|
+
|
|
+ def testPropertyOffsetExceptions(self):
|
|
+ """Check that exceptions are raised as expected"""
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.first_property_offset(107)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+
|
|
+ # Quieten the NOTFOUND exception and check that a BADOFFSET
|
|
+ # exception is still raised.
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.first_property_offset(107, QUIET_NOTFOUND)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.next_property_offset(107, QUIET_NOTFOUND)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+
|
|
+ # Check that NOTFOUND can be quietened.
|
|
+ node = self.fdt.path_offset('/subnode@1/ss1')
|
|
+ self.assertEquals(self.fdt.first_property_offset(node, QUIET_NOTFOUND),
|
|
+ -libfdt.NOTFOUND)
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.first_property_offset(node)
|
|
+ self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
|
|
+
|
|
+ def testGetName(self):
|
|
+ """Check that we can get the name of a node"""
|
|
+ self.assertEquals(self.fdt.get_name(0), '')
|
|
+ node = self.fdt.path_offset('/subnode@1/subsubnode')
|
|
+ self.assertEquals(self.fdt.get_name(node), 'subsubnode')
|
|
+
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.get_name(-2)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+
|
|
+ def testGetPropertyByOffset(self):
|
|
+ """Check that we can read the name and contents of a property"""
|
|
+ root = 0
|
|
+ poffset = self.fdt.first_property_offset(root)
|
|
+ prop = self.fdt.get_property_by_offset(poffset)
|
|
+ self.assertEquals(prop.name, 'compatible')
|
|
+ self.assertEquals(prop.value, 'test_tree1\0')
|
|
+
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.get_property_by_offset(-2)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+ self.assertEquals(
|
|
+ -libfdt.BADOFFSET,
|
|
+ self.fdt.get_property_by_offset(-2, [libfdt.BADOFFSET]))
|
|
+
|
|
+ def testGetProp(self):
|
|
+ """Check that we can read the contents of a property by name"""
|
|
+ root = self.fdt.path_offset('/')
|
|
+ value = self.fdt.getprop(root, "compatible")
|
|
+ self.assertEquals(value, 'test_tree1\0')
|
|
+ self.assertEquals(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing',
|
|
+ QUIET_NOTFOUND))
|
|
+
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.getprop(root, 'missing')
|
|
+ self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
|
|
+
|
|
+ node = self.fdt.path_offset('/subnode@1/subsubnode')
|
|
+ value = self.fdt.getprop(node, "compatible")
|
|
+ self.assertEquals(value, 'subsubnode1\0subsubnode\0')
|
|
+
|
|
+ def testStrError(self):
|
|
+ """Check that we can get an error string"""
|
|
+ self.assertEquals(libfdt.strerror(-libfdt.NOTFOUND),
|
|
+ 'FDT_ERR_NOTFOUND')
|
|
+
|
|
+ def testFirstNextSubnodeOffset(self):
|
|
+ """Check that we can walk through subnodes"""
|
|
+ node_list = []
|
|
+ node = self.fdt.first_subnode(0, QUIET_NOTFOUND)
|
|
+ while node >= 0:
|
|
+ node_list.append(self.fdt.get_name(node))
|
|
+ node = self.fdt.next_subnode(node, QUIET_NOTFOUND)
|
|
+ self.assertEquals(node_list, ['subnode@1', 'subnode@2'])
|
|
+
|
|
+ def testFirstNextSubnodeOffsetExceptions(self):
|
|
+ """Check except handling for first/next subnode functions"""
|
|
+ node = self.fdt.path_offset('/subnode@1/subsubnode', QUIET_NOTFOUND)
|
|
+ self.assertEquals(self.fdt.first_subnode(node, QUIET_NOTFOUND),
|
|
+ -libfdt.NOTFOUND)
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.first_subnode(node)
|
|
+ self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
|
|
+
|
|
+ node = self.fdt.path_offset('/subnode@1/ss1', QUIET_NOTFOUND)
|
|
+ self.assertEquals(self.fdt.next_subnode(node, QUIET_NOTFOUND),
|
|
+ -libfdt.NOTFOUND)
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.next_subnode(node)
|
|
+ self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
|
|
+
|
|
+ def testDeleteProperty(self):
|
|
+ """Test that we can delete a property"""
|
|
+ node_name = '/subnode@1'
|
|
+ self.assertEquals(self.GetPropList(node_name),
|
|
+ ['compatible', 'reg', 'prop-int'])
|
|
+ node = self.fdt.path_offset('/%s' % node_name)
|
|
+ self.assertEquals(self.fdt.delprop(node, 'reg'), 0)
|
|
+ self.assertEquals(self.GetPropList(node_name),
|
|
+ ['compatible', 'prop-int'])
|
|
+
|
|
+ def testHeader(self):
|
|
+ """Test that we can access the header values"""
|
|
+ self.assertEquals(self.fdt.totalsize(), len(self.fdt._fdt))
|
|
+ self.assertEquals(self.fdt.off_dt_struct(), 88)
|
|
+
|
|
+ def testPack(self):
|
|
+ """Test that we can pack the tree after deleting something"""
|
|
+ orig_size = self.fdt.totalsize()
|
|
+ node = self.fdt.path_offset('/subnode@2', QUIET_NOTFOUND)
|
|
+ self.assertEquals(self.fdt.delprop(node, 'prop-int'), 0)
|
|
+ self.assertEquals(orig_size, self.fdt.totalsize())
|
|
+ self.assertEquals(self.fdt.pack(), 0)
|
|
+ self.assertTrue(self.fdt.totalsize() < orig_size)
|
|
+
|
|
+ def testBadPropertyOffset(self):
|
|
+ """Test that bad property offsets are detected"""
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.get_property_by_offset(13)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.first_property_offset(3)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+ with self.assertRaises(FdtException) as e:
|
|
+ self.fdt.next_property_offset(3)
|
|
+ self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
|
|
+
|
|
+ def testBadPathOffset(self):
|
|
+ """Test that bad path names are detected"""
|
|
+ with self.assertRaisesRegexp(FdtException, get_err(libfdt.BADPATH)):
|
|
+ self.fdt.path_offset('not-present')
|
|
+
|
|
+ def testQuietAll(self):
|
|
+ """Check that exceptions can be masked by QUIET_ALL"""
|
|
+ self.assertEquals(-libfdt.NOTFOUND,
|
|
+ self.fdt.path_offset('/missing', QUIET_ALL))
|
|
+ self.assertEquals(-libfdt.BADOFFSET,
|
|
+ self.fdt.get_property_by_offset(13, QUIET_ALL))
|
|
+ self.assertEquals(-libfdt.BADPATH,
|
|
+ self.fdt.path_offset('missing', QUIET_ALL))
|
|
+
|
|
+
|
|
+if __name__ == "__main__":
|
|
+ unittest.main()
|
|
--
|
|
2.13.0
|
|
|
|
From b40aa8359affa52bd79afe468c26683d6bb41c68 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 17 Mar 2017 16:14:32 -0600
|
|
Subject: [PATCH 03/29] Mention pylibfdt in the documentation
|
|
|
|
Add a note about pylibfdt in the README.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
README | 47 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 47 insertions(+)
|
|
|
|
diff --git a/README b/README
|
|
index f92008f..96d8486 100644
|
|
--- a/README
|
|
+++ b/README
|
|
@@ -7,6 +7,53 @@ DTC and LIBFDT are maintained by:
|
|
David Gibson <david@gibson.dropbear.id.au>
|
|
Jon Loeliger <jdl@jdl.com>
|
|
|
|
+
|
|
+Python library
|
|
+--------------
|
|
+
|
|
+A Python library is also available. To build this you will need to install
|
|
+swig and Python development files. On Debian distributions:
|
|
+
|
|
+ sudo apt-get install swig python-dev
|
|
+
|
|
+The library provides an Fdt class which you can use like this:
|
|
+
|
|
+$ PYTHONPATH=../pylibfdt python
|
|
+>>> import libfdt
|
|
+>>> fdt = libfdt.Fdt(open('test_tree1.dtb').read())
|
|
+>>> node = fdt.path_offset('/subnode@1')
|
|
+>>> print node
|
|
+124
|
|
+>>> prop_offset = fdt.first_property_offset(node)
|
|
+>>> prop = fdt.get_property_by_offset(prop_offset)
|
|
+>>> print '%s=%r' % (prop.name, prop.value)
|
|
+compatible=bytearray(b'subnode1\x00')
|
|
+>>> print '%s=%s' % (prop.name, prop.value)
|
|
+compatible=subnode1
|
|
+>>> node2 = fdt.path_offset('/')
|
|
+>>> print fdt.getprop(node2, 'compatible')
|
|
+test_tree1
|
|
+
|
|
+You will find tests in tests/pylibfdt_tests.py showing how to use each
|
|
+method. Help is available using the Python help command, e.g.:
|
|
+
|
|
+ $ cd pylibfdt
|
|
+ $ python -c "import libfdt; help(libfdt)"
|
|
+
|
|
+If you add new features, please check code coverage:
|
|
+
|
|
+ $ sudo apt-get install python-pip python-pytest
|
|
+ $ sudo pip install coverage
|
|
+ $ cd tests
|
|
+ $ coverage run pylibfdt_tests.py
|
|
+ $ coverage html
|
|
+ # Open 'htmlcov/index.html' in your browser
|
|
+
|
|
+
|
|
+More work remains to support all of libfdt, including access to numeric
|
|
+values.
|
|
+
|
|
+
|
|
Mailing list
|
|
------------
|
|
The following list is for discussion about dtc and libfdt implementation
|
|
--
|
|
2.13.0
|
|
|
|
From 8cb3896358e9f70b6f742772734b038ed0d4ea19 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 17 Mar 2017 16:14:33 -0600
|
|
Subject: [PATCH 04/29] Adjust libfdt.h to work with swig
|
|
|
|
There are a few places where libfdt.h cannot be used as is with swig:
|
|
|
|
- macros like fdt_totalsize() have to be defined as C declarations
|
|
- fdt_offset_ptr() and fdt_getprop_namelen() need special treatment due to
|
|
a TODO in the wrapper for fdt_getprop(). However they are not useful to
|
|
Python so can be removed
|
|
|
|
Add #ifdefs to work around these problem.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
libfdt/libfdt.h | 21 ++++++++++++++++++++-
|
|
1 file changed, 20 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
|
|
index ac42e04..2c9ddb4 100644
|
|
--- a/libfdt/libfdt.h
|
|
+++ b/libfdt/libfdt.h
|
|
@@ -143,7 +143,9 @@
|
|
/* Low-level functions (you probably don't need these) */
|
|
/**********************************************************************/
|
|
|
|
+#ifndef SWIG /* This function is not useful in Python */
|
|
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
|
|
+#endif
|
|
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
|
|
{
|
|
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
|
|
@@ -210,7 +212,6 @@ int fdt_next_subnode(const void *fdt, int offset);
|
|
/**********************************************************************/
|
|
/* General functions */
|
|
/**********************************************************************/
|
|
-
|
|
#define fdt_get_header(fdt, field) \
|
|
(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
|
|
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
|
|
@@ -354,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
|
|
* useful for finding subnodes based on a portion of a larger string,
|
|
* such as a full path.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
/**
|
|
* fdt_subnode_offset - find a subnode of a given node
|
|
* @fdt: pointer to the device tree blob
|
|
@@ -391,7 +394,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
|
|
* Identical to fdt_path_offset(), but only consider the first namelen
|
|
* characters of path as the path name.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_path_offset - find a tree node by its full path
|
|
@@ -550,10 +555,12 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
|
* Identical to fdt_get_property(), but only examine the first namelen
|
|
* characters of name for matching the property name.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
|
int nodeoffset,
|
|
const char *name,
|
|
int namelen, int *lenp);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_get_property - find a given property in a given node
|
|
@@ -624,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
|
|
* -FDT_ERR_BADSTRUCTURE,
|
|
* -FDT_ERR_TRUNCATED, standard meanings
|
|
*/
|
|
+#ifndef SWIG /* This function is not useful in Python */
|
|
const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
const char **namep, int *lenp);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_getprop_namelen - get property value based on substring
|
|
@@ -638,6 +647,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
* Identical to fdt_getprop(), but only examine the first namelen
|
|
* characters of name for matching the property name.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|
const char *name, int namelen, int *lenp);
|
|
static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
|
|
@@ -647,6 +657,7 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
|
|
return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
|
|
namelen, lenp);
|
|
}
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_getprop - retrieve the value of a given property
|
|
@@ -707,8 +718,10 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
|
|
* Identical to fdt_get_alias(), but only examine the first namelen
|
|
* characters of name for matching the alias name.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
const char *fdt_get_alias_namelen(const void *fdt,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_get_alias - retrieve the path referenced by a given alias
|
|
@@ -1106,10 +1119,12 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
|
|
* of the name. It is useful when you want to manipulate only one value of
|
|
* an array and you have a string that doesn't end with \0.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
|
const char *name, int namelen,
|
|
uint32_t idx, const void *val,
|
|
int len);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_setprop_inplace - change a property's value, but not its size
|
|
@@ -1139,8 +1154,10 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
|
* -FDT_ERR_BADSTRUCTURE,
|
|
* -FDT_ERR_TRUNCATED, standard meanings
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
|
const void *val, int len);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
|
|
@@ -1734,8 +1751,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
|
|
* creating subnodes based on a portion of a larger string, such as a
|
|
* full path.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_add_subnode - creates a new node
|
|
--
|
|
2.13.0
|
|
|
|
From 756ffc4f52f6863ba8bf3a67129271566ba2000c Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 17 Mar 2017 16:14:34 -0600
|
|
Subject: [PATCH 05/29] Build pylibfdt as part of the normal build process
|
|
|
|
If swig and the Python are available, build pylibfdt automatically.
|
|
Adjust the tests to run Python tests too in this case.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
[dwg: Make error message clearer that missing swig or python-dev isn't
|
|
fatal to the whole build]
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 34 ++++++++++++++++++++++++++++++++--
|
|
tests/run_tests.sh | 28 ++++++++++++++++++++++++++++
|
|
2 files changed, 60 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 1b69f53..ed95384 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -116,7 +116,21 @@ BIN += fdtput
|
|
|
|
SCRIPTS = dtdiff
|
|
|
|
-all: $(BIN) libfdt
|
|
+# We need both Python and swig to build pylibfdt.
|
|
+.PHONY: maybe_pylibfdt
|
|
+maybe_pylibfdt: FORCE
|
|
+ if pkg-config --cflags python >/dev/null 2>&1; then \
|
|
+ if which swig >/dev/null 2>&1; then \
|
|
+ can_build=yes; \
|
|
+ fi; \
|
|
+ fi; \
|
|
+ if [ "$$can_build" = "yes" ]; then \
|
|
+ $(MAKE) pylibfdt; \
|
|
+ else \
|
|
+ echo "## Skipping pylibgfdt (install python dev and swig to build)"; \
|
|
+ fi
|
|
+
|
|
+all: $(BIN) libfdt maybe_pylibfdt
|
|
|
|
|
|
ifneq ($(DEPTARGETS),)
|
|
@@ -203,6 +217,22 @@ dist:
|
|
cat ../dtc-$(dtc_version).tar | \
|
|
gzip -9 > ../dtc-$(dtc_version).tar.gz
|
|
|
|
+
|
|
+#
|
|
+# Rules for pylibfdt
|
|
+#
|
|
+PYLIBFDT_srcdir = pylibfdt
|
|
+PYLIBFDT_objdir = pylibfdt
|
|
+
|
|
+include $(PYLIBFDT_srcdir)/Makefile.pylibfdt
|
|
+
|
|
+.PHONY: pylibfdt
|
|
+pylibfdt: $(PYLIBFDT_objdir)/_libfdt.so
|
|
+
|
|
+pylibfdt_clean:
|
|
+ @$(VECHO) CLEAN "(pylibfdt)"
|
|
+ rm -f $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles))
|
|
+
|
|
#
|
|
# Release signing and uploading
|
|
# This is for maintainer convenience, don't try this at home.
|
|
@@ -244,7 +274,7 @@ include tests/Makefile.tests
|
|
STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \
|
|
*.tab.[ch] *.lex.c *.output
|
|
|
|
-clean: libfdt_clean tests_clean
|
|
+clean: libfdt_clean pylibfdt_clean tests_clean
|
|
@$(VECHO) CLEAN
|
|
rm -f $(STD_CLEANFILES)
|
|
rm -f $(VERSION_FILE)
|
|
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
|
|
index 0f5c3db..2a1ba44 100755
|
|
--- a/tests/run_tests.sh
|
|
+++ b/tests/run_tests.sh
|
|
@@ -771,6 +771,26 @@ fdtdump_tests () {
|
|
run_fdtdump_test fdtdump.dts
|
|
}
|
|
|
|
+pylibfdt_tests () {
|
|
+ TMP=/tmp/tests.stderr.$$
|
|
+ python pylibfdt_tests.py -v 2> $TMP
|
|
+
|
|
+ # Use the 'ok' message meaning the test passed, 'ERROR' meaning it failed
|
|
+ # and the summary line for total tests (e.g. 'Ran 17 tests in 0.002s').
|
|
+ # We could add pass + fail to get total tests, but this provides a useful
|
|
+ # sanity check.
|
|
+ pass_count=$(grep "\.\.\. ok$" $TMP | wc -l)
|
|
+ fail_count=$(grep "^ERROR: " $TMP | wc -l)
|
|
+ total_tests=$(sed -n 's/^Ran \([0-9]*\) tests.*$/\1/p' $TMP)
|
|
+ cat $TMP
|
|
+ rm $TMP
|
|
+
|
|
+ # Extract the test results and add them to our totals
|
|
+ tot_fail=$((tot_fail + $fail_count))
|
|
+ tot_pass=$((tot_pass + $pass_count))
|
|
+ tot_tests=$((tot_tests + $total_tests))
|
|
+}
|
|
+
|
|
while getopts "vt:me" ARG ; do
|
|
case $ARG in
|
|
"v")
|
|
@@ -790,6 +810,11 @@ done
|
|
|
|
if [ -z "$TESTSETS" ]; then
|
|
TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump"
|
|
+
|
|
+ # Test pylibfdt if the libfdt Python module is available.
|
|
+ if [ -f ../pylibfdt/_libfdt.so ]; then
|
|
+ TESTSETS="$TESTSETS pylibfdt"
|
|
+ fi
|
|
fi
|
|
|
|
# Make sure we don't have stale blobs lying around
|
|
@@ -818,6 +843,9 @@ for set in $TESTSETS; do
|
|
"fdtdump")
|
|
fdtdump_tests
|
|
;;
|
|
+ "pylibfdt")
|
|
+ pylibfdt_tests
|
|
+ ;;
|
|
esac
|
|
done
|
|
|
|
--
|
|
2.13.0
|
|
|
|
From 6afd7d9688f58436bcc6025180473aa2ec1cdec4 Mon Sep 17 00:00:00 2001
|
|
From: David Gibson <david@gibson.dropbear.id.au>
|
|
Date: Wed, 22 Mar 2017 16:34:39 +1100
|
|
Subject: [PATCH 06/29] Correct typo: s/pylibgfdt/pylibfdt/
|
|
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index ed95384..1d08ec1 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -127,7 +127,7 @@ maybe_pylibfdt: FORCE
|
|
if [ "$$can_build" = "yes" ]; then \
|
|
$(MAKE) pylibfdt; \
|
|
else \
|
|
- echo "## Skipping pylibgfdt (install python dev and swig to build)"; \
|
|
+ echo "## Skipping pylibfdt (install python dev and swig to build)"; \
|
|
fi
|
|
|
|
all: $(BIN) libfdt maybe_pylibfdt
|
|
--
|
|
2.13.0
|
|
|
|
From 4e0e0d049757b15d53209a9687d9ea33ab3704c5 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sun, 26 Mar 2017 13:06:17 -0600
|
|
Subject: [PATCH 07/29] pylibfdt: Allow pkg-config to be supplied in the
|
|
environment
|
|
|
|
Some build systems have their own version of the pkg-config tool.
|
|
Use a variable for this instead of hard-coding it, to allow for this.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Suggested-by: Mike Frysinger <vapier@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 1d08ec1..e6d8251 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -23,6 +23,7 @@ CFLAGS = -g -Os -fPIC -Werror $(WARNINGS)
|
|
BISON = bison
|
|
LEX = flex
|
|
SWIG = swig
|
|
+PKG_CONFIG ?= pkg-config
|
|
|
|
INSTALL = /usr/bin/install
|
|
DESTDIR =
|
|
@@ -119,7 +120,7 @@ SCRIPTS = dtdiff
|
|
# We need both Python and swig to build pylibfdt.
|
|
.PHONY: maybe_pylibfdt
|
|
maybe_pylibfdt: FORCE
|
|
- if pkg-config --cflags python >/dev/null 2>&1; then \
|
|
+ if $(PKG_CONFIG) --cflags python >/dev/null 2>&1; then \
|
|
if which swig >/dev/null 2>&1; then \
|
|
can_build=yes; \
|
|
fi; \
|
|
--
|
|
2.13.0
|
|
|
|
From 89a5062ab23163a7cc4f6ec3d693e6b6883ac0a1 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sun, 26 Mar 2017 13:06:19 -0600
|
|
Subject: [PATCH 08/29] pylibfdt: Use environment to pass C flags and files
|
|
|
|
At present setup.py adjusts its command line when running, so that the
|
|
C flags and file list can be passed as arguments. Pass them in environment
|
|
variables instead, so we can avoid this messiness. It also allows us to
|
|
support the 'install' command.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
pylibfdt/Makefile.pylibfdt | 3 ++-
|
|
pylibfdt/setup.py | 16 ++++++----------
|
|
2 files changed, 8 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index 0d8c010..3d99fd4 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -7,7 +7,8 @@ PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
|
|
|
$(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
@$(VECHO) PYMOD $@
|
|
- python $(PYLIBFDT_objdir)/setup.py "$(CPPFLAGS)" $^
|
|
+ SOURCES="$^" CPPFLAGS="$(CPPFLAGS)" \
|
|
+ python $(PYLIBFDT_objdir)/setup.py --quiet build_ext --inplace
|
|
mv _libfdt.so $(PYMODULE)
|
|
|
|
$(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
|
|
index 0ff160c..e45f110 100644
|
|
--- a/pylibfdt/setup.py
|
|
+++ b/pylibfdt/setup.py
|
|
@@ -2,6 +2,9 @@
|
|
|
|
"""
|
|
setup.py file for SWIG libfdt
|
|
+
|
|
+Files to be built into the extension are provided in SOURCES
|
|
+C flags to use are provided in CPPFLAGS
|
|
"""
|
|
|
|
from distutils.core import setup, Extension
|
|
@@ -9,22 +12,15 @@ import os
|
|
import sys
|
|
|
|
progname = sys.argv[0]
|
|
-cflags = sys.argv[1]
|
|
-files = sys.argv[2:]
|
|
-
|
|
-if cflags:
|
|
- cflags = [flag for flag in cflags.split(' ') if flag]
|
|
-else:
|
|
- cflags = None
|
|
+files = os.environ['SOURCES'].split()
|
|
+cflags = os.environ['CPPFLAGS'].split()
|
|
|
|
libfdt_module = Extension(
|
|
'_libfdt',
|
|
sources = files,
|
|
- extra_compile_args = cflags
|
|
+ extra_compile_args = cflags
|
|
)
|
|
|
|
-sys.argv = [progname, '--quiet', 'build_ext', '--inplace']
|
|
-
|
|
setup (name = 'libfdt',
|
|
version = '0.1',
|
|
author = "Simon Glass <sjg@chromium.org>",
|
|
--
|
|
2.13.0
|
|
|
|
From 14c4171f4f9ad2674249e06c54eb9ce0b533d4b6 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sun, 26 Mar 2017 13:06:20 -0600
|
|
Subject: [PATCH 09/29] pylibfdt: Use package_dir to set the package directory
|
|
|
|
At present we manually move _libfdt.so into the correct place. Provide a
|
|
package directory so we can avoid needing to do this.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
pylibfdt/Makefile.pylibfdt | 3 +--
|
|
pylibfdt/setup.py | 3 +++
|
|
2 files changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index 3d99fd4..861e67c 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -7,9 +7,8 @@ PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
|
|
|
$(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
@$(VECHO) PYMOD $@
|
|
- SOURCES="$^" CPPFLAGS="$(CPPFLAGS)" \
|
|
+ SOURCES="$^" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" \
|
|
python $(PYLIBFDT_objdir)/setup.py --quiet build_ext --inplace
|
|
- mv _libfdt.so $(PYMODULE)
|
|
|
|
$(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
@$(VECHO) SWIG $@
|
|
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
|
|
index e45f110..ef6e2c0 100644
|
|
--- a/pylibfdt/setup.py
|
|
+++ b/pylibfdt/setup.py
|
|
@@ -5,6 +5,7 @@ setup.py file for SWIG libfdt
|
|
|
|
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
|
|
"""
|
|
|
|
from distutils.core import setup, Extension
|
|
@@ -14,6 +15,7 @@ import sys
|
|
progname = sys.argv[0]
|
|
files = os.environ['SOURCES'].split()
|
|
cflags = os.environ['CPPFLAGS'].split()
|
|
+objdir = os.environ['OBJDIR']
|
|
|
|
libfdt_module = Extension(
|
|
'_libfdt',
|
|
@@ -26,5 +28,6 @@ setup (name = 'libfdt',
|
|
author = "Simon Glass <sjg@chromium.org>",
|
|
description = """Python binding for libfdt""",
|
|
ext_modules = [libfdt_module],
|
|
+ package_dir = {'': objdir},
|
|
py_modules = ["libfdt"],
|
|
)
|
|
--
|
|
2.13.0
|
|
|
|
From 8a892fd85d94c733bbf184ff6df5d0ad5422be12 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sun, 26 Mar 2017 13:06:18 -0600
|
|
Subject: [PATCH 11/29] pylibfdt: Allow building to be disabled
|
|
|
|
Some build systems want to build python libraries separately from the
|
|
rest of the build.
|
|
|
|
Add a NO_PYTHON option to enable this.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 1 +
|
|
README | 6 ++++++
|
|
2 files changed, 7 insertions(+)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index e6d8251..5cf4aee 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -120,6 +120,7 @@ SCRIPTS = dtdiff
|
|
# We need both Python and swig to build pylibfdt.
|
|
.PHONY: maybe_pylibfdt
|
|
maybe_pylibfdt: FORCE
|
|
+ if [ -n "${NO_PYTHON}" ]; then exit; fi; \
|
|
if $(PKG_CONFIG) --cflags python >/dev/null 2>&1; then \
|
|
if which swig >/dev/null 2>&1; then \
|
|
can_build=yes; \
|
|
diff --git a/README b/README
|
|
index 96d8486..d2323fd 100644
|
|
--- a/README
|
|
+++ b/README
|
|
@@ -50,6 +50,12 @@ If you add new features, please check code coverage:
|
|
# Open 'htmlcov/index.html' in your browser
|
|
|
|
|
|
+To disable building the python library, even if swig and Python are available,
|
|
+use:
|
|
+
|
|
+ make NO_PYTHON=1
|
|
+
|
|
+
|
|
More work remains to support all of libfdt, including access to numeric
|
|
values.
|
|
|
|
--
|
|
2.13.0
|
|
|
|
From e91c652af21557698751c3944ceb7c46e5e58164 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sun, 26 Mar 2017 13:06:21 -0600
|
|
Subject: [PATCH 12/29] pylibfdt: Enable installation of Python module
|
|
|
|
Adjust the setup script to support installation, and call it from the
|
|
Makefile if enabled. It will be disabled if we were unable to build the
|
|
module (e.g. due to swig being missing), or the NO_PYTHON environment
|
|
variable is set.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 2 +-
|
|
README | 7 +++++++
|
|
pylibfdt/Makefile.pylibfdt | 14 ++++++++++++++
|
|
3 files changed, 22 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 5cf4aee..52ff72c 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -195,7 +195,7 @@ install-includes:
|
|
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
|
|
$(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
|
|
|
|
-install: install-bin install-lib install-includes
|
|
+install: install-bin install-lib install-includes maybe_install_pylibfdt
|
|
|
|
$(VERSION_FILE): Makefile FORCE
|
|
$(call filechk,version)
|
|
diff --git a/README b/README
|
|
index d2323fd..5add557 100644
|
|
--- a/README
|
|
+++ b/README
|
|
@@ -50,6 +50,13 @@ If you add new features, please check code coverage:
|
|
# Open 'htmlcov/index.html' in your browser
|
|
|
|
|
|
+To install the library use:
|
|
+
|
|
+ make install_pylibfdt SETUP_PREFIX=/path/to/install_dir
|
|
+
|
|
+If SETUP_PREFIX is not provided, the default prefix is used, typically '/usr'
|
|
+or '/usr/local'. See Python's distutils documentation for details.
|
|
+
|
|
To disable building the python library, even if swig and Python are available,
|
|
use:
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index 861e67c..a0271da 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -14,4 +14,18 @@ $(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
@$(VECHO) SWIG $@
|
|
$(SWIG) -python -o $@ $<
|
|
|
|
+install_pylibfdt: $(WRAP) $(PYMODULE)
|
|
+ $(VECHO) INSTALL-PYLIB; \
|
|
+ SOURCES="$(PYLIBFDT_srcs) $(WRAP)" CPPFLAGS="$(CPPFLAGS)" \
|
|
+ OBJDIR="$(PYLIBFDT_objdir)" \
|
|
+ python $(PYLIBFDT_objdir)/setup.py --quiet install \
|
|
+ $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX))
|
|
+
|
|
+maybe_install_pylibfdt:
|
|
+ if [ -e $(PYMODULE) ]; then \
|
|
+ if [ -z "$(NO_PYTHON)" ]; then \
|
|
+ $(MAKE) install_pylibfdt; \
|
|
+ fi; \
|
|
+ fi
|
|
+
|
|
PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so
|
|
--
|
|
2.13.0
|
|
|
|
From 9f2e3a3a1f19b569b9524fa0f4cb4790e23ad983 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sun, 26 Mar 2017 13:06:22 -0600
|
|
Subject: [PATCH 13/29] pylibfdt: Use the correct libfdt version in the module
|
|
|
|
Use the same version number in the module as with the rest of libfdt. This
|
|
can be examined with:
|
|
|
|
import pkg_resources
|
|
print pkg_resources.require('libfdt')[0].version
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
pylibfdt/Makefile.pylibfdt | 3 ++-
|
|
pylibfdt/setup.py | 3 ++-
|
|
2 files changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index a0271da..a74cd30 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -8,6 +8,7 @@ PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
|
$(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
@$(VECHO) PYMOD $@
|
|
SOURCES="$^" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" \
|
|
+ VERSION="$(dtc_version)" \
|
|
python $(PYLIBFDT_objdir)/setup.py --quiet build_ext --inplace
|
|
|
|
$(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
@@ -17,7 +18,7 @@ $(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
install_pylibfdt: $(WRAP) $(PYMODULE)
|
|
$(VECHO) INSTALL-PYLIB; \
|
|
SOURCES="$(PYLIBFDT_srcs) $(WRAP)" CPPFLAGS="$(CPPFLAGS)" \
|
|
- OBJDIR="$(PYLIBFDT_objdir)" \
|
|
+ OBJDIR="$(PYLIBFDT_objdir)" VERSION="$(dtc_version)" \
|
|
python $(PYLIBFDT_objdir)/setup.py --quiet install \
|
|
$(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX))
|
|
|
|
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
|
|
index ef6e2c0..3bafe30 100644
|
|
--- a/pylibfdt/setup.py
|
|
+++ b/pylibfdt/setup.py
|
|
@@ -16,6 +16,7 @@ progname = sys.argv[0]
|
|
files = os.environ['SOURCES'].split()
|
|
cflags = os.environ['CPPFLAGS'].split()
|
|
objdir = os.environ['OBJDIR']
|
|
+version = os.environ['VERSION']
|
|
|
|
libfdt_module = Extension(
|
|
'_libfdt',
|
|
@@ -24,7 +25,7 @@ libfdt_module = Extension(
|
|
)
|
|
|
|
setup (name = 'libfdt',
|
|
- version = '0.1',
|
|
+ version = version,
|
|
author = "Simon Glass <sjg@chromium.org>",
|
|
description = """Python binding for libfdt""",
|
|
ext_modules = [libfdt_module],
|
|
--
|
|
2.13.0
|
|
|
|
From ab15256d8d027fc379438a18a8bd85e7765557c6 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sun, 26 Mar 2017 13:06:23 -0600
|
|
Subject: [PATCH 14/29] pylibfdt: Use the call function to simplify the
|
|
Makefile
|
|
|
|
This is in a separate patch since I not sure if GNU make features
|
|
are permitted in the Makefile.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
pylibfdt/Makefile.pylibfdt | 14 +++++++-------
|
|
1 file changed, 7 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index a74cd30..0d95c11 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -5,11 +5,13 @@ PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS))
|
|
WRAP = $(PYLIBFDT_objdir)/libfdt_wrap.c
|
|
PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
|
|
|
+run_setup = SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" \
|
|
+ VERSION="$(dtc_version)" \
|
|
+ python $(PYLIBFDT_objdir)/setup.py --quiet $(2)
|
|
+
|
|
$(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
@$(VECHO) PYMOD $@
|
|
- SOURCES="$^" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" \
|
|
- VERSION="$(dtc_version)" \
|
|
- python $(PYLIBFDT_objdir)/setup.py --quiet build_ext --inplace
|
|
+ $(call run_setup, $^, build_ext --inplace)
|
|
|
|
$(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
@$(VECHO) SWIG $@
|
|
@@ -17,10 +19,8 @@ $(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
|
|
install_pylibfdt: $(WRAP) $(PYMODULE)
|
|
$(VECHO) INSTALL-PYLIB; \
|
|
- SOURCES="$(PYLIBFDT_srcs) $(WRAP)" CPPFLAGS="$(CPPFLAGS)" \
|
|
- OBJDIR="$(PYLIBFDT_objdir)" VERSION="$(dtc_version)" \
|
|
- python $(PYLIBFDT_objdir)/setup.py --quiet install \
|
|
- $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX))
|
|
+ $(call run_setup, $(PYLIBFDT_srcs) $(WRAP), \
|
|
+ install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)))
|
|
|
|
maybe_install_pylibfdt:
|
|
if [ -e $(PYMODULE) ]; then \
|
|
--
|
|
2.13.0
|
|
|
|
From 580a9f6c288079e952eae6707c267644338f7c7b Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Sat, 1 Apr 2017 09:31:41 -0600
|
|
Subject: [PATCH 15/29] Add a libfdt function to write a property placeholder
|
|
|
|
The existing function to add a new property to a tree being built requires
|
|
that the entire contents of the new property be passed in. For some
|
|
applications it is more convenient to be able to add the property contents
|
|
later, perhaps by reading from a file. This avoids double-buffering of the
|
|
contents.
|
|
|
|
Add a new function to support this and adjust the existing fdt_property() to
|
|
use it.
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
libfdt/fdt_sw.c | 16 ++++++++++++++--
|
|
libfdt/libfdt.h | 16 ++++++++++++++++
|
|
tests/include7.dts | 1 +
|
|
tests/sw_tree1.c | 5 +++++
|
|
tests/test_tree1.dts | 1 +
|
|
tests/test_tree1_label_noderef.dts | 1 +
|
|
tests/trees.S | 2 ++
|
|
7 files changed, 40 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
|
|
index 6a80485..2bd15e7 100644
|
|
--- a/libfdt/fdt_sw.c
|
|
+++ b/libfdt/fdt_sw.c
|
|
@@ -220,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
|
return offset;
|
|
}
|
|
|
|
-int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
|
|
{
|
|
struct fdt_property *prop;
|
|
int nameoff;
|
|
@@ -238,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
prop->tag = cpu_to_fdt32(FDT_PROP);
|
|
prop->nameoff = cpu_to_fdt32(nameoff);
|
|
prop->len = cpu_to_fdt32(len);
|
|
- memcpy(prop->data, val, len);
|
|
+ *valp = prop->data;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
+{
|
|
+ void *ptr;
|
|
+ int ret;
|
|
+
|
|
+ ret = fdt_property_placeholder(fdt, name, len, &ptr);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ memcpy(ptr, val, len);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
|
|
index 2c9ddb4..a248b1b 100644
|
|
--- a/libfdt/libfdt.h
|
|
+++ b/libfdt/libfdt.h
|
|
@@ -1314,6 +1314,22 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
|
|
{
|
|
return fdt_property_u32(fdt, name, val);
|
|
}
|
|
+
|
|
+/**
|
|
+ * fdt_property_placeholder - add a new property and return a ptr to its value
|
|
+ *
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @name: name of property to add
|
|
+ * @len: length of property value in bytes
|
|
+ * @valp: returns a pointer to where where the value should be placed
|
|
+ *
|
|
+ * returns:
|
|
+ * 0, on success
|
|
+ * -FDT_ERR_BADMAGIC,
|
|
+ * -FDT_ERR_NOSPACE, standard meanings
|
|
+ */
|
|
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
|
|
+
|
|
#define fdt_property_string(fdt, name, str) \
|
|
fdt_property(fdt, name, str, strlen(str)+1)
|
|
int fdt_end_node(void *fdt);
|
|
diff --git a/tests/include7.dts b/tests/include7.dts
|
|
index 2f6eb89..ab2c948 100644
|
|
--- a/tests/include7.dts
|
|
+++ b/tests/include7.dts
|
|
@@ -5,6 +5,7 @@
|
|
|
|
subsubnode {
|
|
compatible = "subsubnode1", "subsubnode";
|
|
+ placeholder = "this is a placeholder string", "string2";
|
|
prop-int = <0xdeadbeef>;
|
|
};
|
|
|
|
diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c
|
|
index 4887dc3..6a338fc 100644
|
|
--- a/tests/sw_tree1.c
|
|
+++ b/tests/sw_tree1.c
|
|
@@ -85,6 +85,9 @@ int main(int argc, char *argv[])
|
|
size_t size;
|
|
int err;
|
|
bool created = false;
|
|
+ void *place;
|
|
+ const char place_str[] = "this is a placeholder string\0string2";
|
|
+ int place_len = sizeof(place_str);
|
|
|
|
test_init(argc, argv);
|
|
|
|
@@ -135,6 +138,8 @@ int main(int argc, char *argv[])
|
|
CHECK(fdt_begin_node(fdt, "subsubnode"));
|
|
CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode",
|
|
23));
|
|
+ CHECK(fdt_property_placeholder(fdt, "placeholder", place_len, &place));
|
|
+ memcpy(place, place_str, place_len);
|
|
CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
|
|
CHECK(fdt_end_node(fdt));
|
|
CHECK(fdt_begin_node(fdt, "ss1"));
|
|
diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts
|
|
index 67ecfd0..77ea325 100644
|
|
--- a/tests/test_tree1.dts
|
|
+++ b/tests/test_tree1.dts
|
|
@@ -18,6 +18,7 @@
|
|
|
|
subsubnode {
|
|
compatible = "subsubnode1", "subsubnode";
|
|
+ placeholder = "this is a placeholder string", "string2";
|
|
prop-int = <0xdeadbeef>;
|
|
};
|
|
|
|
diff --git a/tests/test_tree1_label_noderef.dts b/tests/test_tree1_label_noderef.dts
|
|
index b2b194c..cfe5946 100644
|
|
--- a/tests/test_tree1_label_noderef.dts
|
|
+++ b/tests/test_tree1_label_noderef.dts
|
|
@@ -18,6 +18,7 @@
|
|
|
|
subsubnode {
|
|
compatible = "subsubnode1", "subsubnode";
|
|
+ placeholder = "this is a placeholder string", "string2";
|
|
prop-int = <0xdeadbeef>;
|
|
};
|
|
|
|
diff --git a/tests/trees.S b/tests/trees.S
|
|
index 3d24aa2..9854d1d 100644
|
|
--- a/tests/trees.S
|
|
+++ b/tests/trees.S
|
|
@@ -102,6 +102,7 @@ test_tree1_struct:
|
|
|
|
BEGIN_NODE("subsubnode")
|
|
PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode")
|
|
+ PROP_STR(test_tree1, placeholder, "this is a placeholder string\0string2")
|
|
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
|
|
END_NODE
|
|
|
|
@@ -141,6 +142,7 @@ test_tree1_strings:
|
|
STRING(test_tree1, linux_phandle, "linux,phandle")
|
|
STRING(test_tree1, phandle, "phandle")
|
|
STRING(test_tree1, reg, "reg")
|
|
+ STRING(test_tree1, placeholder, "placeholder")
|
|
STRING(test_tree1, address_cells, "#address-cells")
|
|
STRING(test_tree1, size_cells, "#size-cells")
|
|
test_tree1_strings_end:
|
|
--
|
|
2.13.0
|
|
|
|
From 1c5170d3a466dc96ec67c08f71a570631b404c62 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Wed, 5 Apr 2017 10:01:38 -0600
|
|
Subject: [PATCH 16/29] pylibfdt: Rename libfdt.swig to libfdt.i
|
|
|
|
The .i extension allows Python distutils to automatically handle the swig
|
|
file. Rename it.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Suggested-by: Mike Frysinger <vapier@gentoo.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
pylibfdt/Makefile.pylibfdt | 2 +-
|
|
pylibfdt/{libfdt.swig => libfdt.i} | 0
|
|
2 files changed, 1 insertion(+), 1 deletion(-)
|
|
rename pylibfdt/{libfdt.swig => libfdt.i} (100%)
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index 0d95c11..06f9296 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -13,7 +13,7 @@ $(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
@$(VECHO) PYMOD $@
|
|
$(call run_setup, $^, build_ext --inplace)
|
|
|
|
-$(WRAP): $(PYLIBFDT_srcdir)/libfdt.swig
|
|
+$(WRAP): $(PYLIBFDT_srcdir)/libfdt.i
|
|
@$(VECHO) SWIG $@
|
|
$(SWIG) -python -o $@ $<
|
|
|
|
diff --git a/pylibfdt/libfdt.swig b/pylibfdt/libfdt.i
|
|
similarity index 100%
|
|
rename from pylibfdt/libfdt.swig
|
|
rename to pylibfdt/libfdt.i
|
|
--
|
|
2.13.0
|
|
|
|
From b04a2cf08862ddac1ff7da40eef58ecb360da941 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Wed, 5 Apr 2017 10:01:39 -0600
|
|
Subject: [PATCH 17/29] pylibfdt: Fix code style in setup.py
|
|
|
|
We should follow PEP8 even for our setup() call.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Suggested-by: Mike Frysinger <vapier@gentoo.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
pylibfdt/setup.py | 17 +++++++++--------
|
|
1 file changed, 9 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
|
|
index 3bafe30..1597b44 100644
|
|
--- a/pylibfdt/setup.py
|
|
+++ b/pylibfdt/setup.py
|
|
@@ -24,11 +24,12 @@ libfdt_module = Extension(
|
|
extra_compile_args = cflags
|
|
)
|
|
|
|
-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 = ["libfdt"],
|
|
- )
|
|
+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=['libfdt'],
|
|
+)
|
|
--
|
|
2.13.0
|
|
|
|
From 90db6d9989ca09ed3c32fbdc646d284ebf9fe1cf Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 7 Apr 2017 15:51:32 -0600
|
|
Subject: [PATCH 19/29] pylibfdt: Allow setup.py to operate stand-alone
|
|
|
|
At present we require that setup.py is executed from the Makefile, which
|
|
sets up various important things like the list of files to build and the
|
|
version number.
|
|
|
|
However many installation systems expect to be able to change to the
|
|
directory containing setup.py and run it. This allows them to support (for
|
|
example) building/installing for multiple Python versions, varying
|
|
installation paths, particular C flags, etc.
|
|
|
|
The problem in implementing this is that we don't want to duplicate the
|
|
information in the Makefile. A common solution (so I am told) is to parse
|
|
the Makefile to obtain the required information.
|
|
|
|
Update the setup.py script to read a few Makefiles when it does not see
|
|
the required information in its environment. This allows installation
|
|
using:
|
|
|
|
./pylibfdt/setup.py install
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 1 +
|
|
README | 14 +++++--
|
|
pylibfdt/Makefile.pylibfdt | 9 +++--
|
|
pylibfdt/setup.py | 98 +++++++++++++++++++++++++++++++++++++++++++---
|
|
tests/Makefile.tests | 6 +--
|
|
5 files changed, 112 insertions(+), 16 deletions(-)
|
|
mode change 100644 => 100755 pylibfdt/setup.py
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 52ff72c..154f5bf 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -267,6 +267,7 @@ TESTS_BIN += convert-dtsv0
|
|
TESTS_BIN += fdtput
|
|
TESTS_BIN += fdtget
|
|
TESTS_BIN += fdtdump
|
|
+TESTS_PYLIBFDT += maybe_pylibfdt
|
|
|
|
include tests/Makefile.tests
|
|
|
|
diff --git a/README b/README
|
|
index 5add557..17dc845 100644
|
|
--- a/README
|
|
+++ b/README
|
|
@@ -50,12 +50,18 @@ If you add new features, please check code coverage:
|
|
# Open 'htmlcov/index.html' in your browser
|
|
|
|
|
|
-To install the library use:
|
|
+To install the library via the normal setup.py method, use:
|
|
|
|
- make install_pylibfdt SETUP_PREFIX=/path/to/install_dir
|
|
+ ./pylibfdt/setup.py [--prefix=/path/to/install_dir]
|
|
|
|
-If SETUP_PREFIX is not provided, the default prefix is used, typically '/usr'
|
|
-or '/usr/local'. See Python's distutils documentation for details.
|
|
+If --prefix is not provided, the default prefix is used, typically '/usr'
|
|
+or '/usr/local'. See Python's distutils documentation for details. You can
|
|
+also install via the Makefile if you like, but the above is more common.
|
|
+
|
|
+To install both libfdt and pylibfdt you can use:
|
|
+
|
|
+ make install [SETUP_PREFIX=/path/to/install_dir] \
|
|
+ [PREFIX=/path/to/install_dir]
|
|
|
|
To disable building the python library, even if swig and Python are available,
|
|
use:
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index 06f9296..0e8ac5f 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -5,13 +5,16 @@ PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS))
|
|
WRAP = $(PYLIBFDT_objdir)/libfdt_wrap.c
|
|
PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
|
|
|
-run_setup = SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" \
|
|
- VERSION="$(dtc_version)" \
|
|
- python $(PYLIBFDT_objdir)/setup.py --quiet $(2)
|
|
+define run_setup
|
|
+ SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)"
|
|
+ VERSION="$(dtc_version)"
|
|
+ $(PYLIBFDT_objdir)/setup.py --quiet $(2)
|
|
+endef
|
|
|
|
$(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
@$(VECHO) PYMOD $@
|
|
$(call run_setup, $^, build_ext --inplace)
|
|
+ mv _libfdt.so $@
|
|
|
|
$(WRAP): $(PYLIBFDT_srcdir)/libfdt.i
|
|
@$(VECHO) SWIG $@
|
|
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
|
|
old mode 100644
|
|
new mode 100755
|
|
index 1597b44..90e80f3
|
|
--- a/pylibfdt/setup.py
|
|
+++ b/pylibfdt/setup.py
|
|
@@ -2,26 +2,112 @@
|
|
|
|
"""
|
|
setup.py file for SWIG libfdt
|
|
+Copyright (C) 2017 Google, Inc.
|
|
+Written by Simon Glass <sjg@chromium.org>
|
|
|
|
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['SOURCES'].split()
|
|
-cflags = os.environ['CPPFLAGS'].split()
|
|
-objdir = os.environ['OBJDIR']
|
|
-version = os.environ['VERSION']
|
|
+files = os.environ.get('SOURCES', '').split()
|
|
+cflags = os.environ.get('CPPFLAGS', '').split()
|
|
+objdir = os.environ.get('OBJDIR')
|
|
+version = os.environ.get('VERSION')
|
|
+swig_opts = []
|
|
+
|
|
+# 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((version, files, cflags, objdir)):
|
|
+ swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()
|
|
|
|
libfdt_module = Extension(
|
|
'_libfdt',
|
|
sources = files,
|
|
- extra_compile_args = cflags
|
|
+ extra_compile_args = cflags,
|
|
+ swig_opts = swig_opts,
|
|
)
|
|
|
|
setup(
|
|
@@ -31,5 +117,5 @@ setup(
|
|
description='Python binding for libfdt',
|
|
ext_modules=[libfdt_module],
|
|
package_dir={'': objdir},
|
|
- py_modules=['libfdt'],
|
|
+ py_modules=['pylibfdt/libfdt'],
|
|
)
|
|
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
|
|
index 3d7a4f8..2258135 100644
|
|
--- a/tests/Makefile.tests
|
|
+++ b/tests/Makefile.tests
|
|
@@ -72,13 +72,13 @@ tests_clean:
|
|
rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%)
|
|
rm -f $(TESTS_CLEANFILES)
|
|
|
|
-check: tests ${TESTS_BIN}
|
|
+check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
|
|
cd $(TESTS_PREFIX); ./run_tests.sh
|
|
|
|
-checkm: tests ${TESTS_BIN}
|
|
+checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
|
|
cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$
|
|
|
|
-checkv: tests ${TESTS_BIN}
|
|
+checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
|
|
cd $(TESTS_PREFIX); ./run_tests.sh -v
|
|
|
|
ifneq ($(DEPTARGETS),)
|
|
--
|
|
2.13.0
|
|
|
|
From 896f1c1332650f5370a21c1c507106a87d17fd3d Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 7 Apr 2017 15:51:33 -0600
|
|
Subject: [PATCH 20/29] pylibfdt: Use Makefile constructs to implement
|
|
NO_PYTHON
|
|
|
|
The current mechanism uses a shell construct, but it seems better to use
|
|
a Makefile approach.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Suggested-by: Mike Frysinger <vapier@gentoo.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
Makefile | 15 ++++++++++++---
|
|
pylibfdt/Makefile.pylibfdt | 7 -------
|
|
2 files changed, 12 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 154f5bf..beca4a0 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -117,10 +117,11 @@ BIN += fdtput
|
|
|
|
SCRIPTS = dtdiff
|
|
|
|
+all: $(BIN) libfdt
|
|
+
|
|
# We need both Python and swig to build pylibfdt.
|
|
.PHONY: maybe_pylibfdt
|
|
maybe_pylibfdt: FORCE
|
|
- if [ -n "${NO_PYTHON}" ]; then exit; fi; \
|
|
if $(PKG_CONFIG) --cflags python >/dev/null 2>&1; then \
|
|
if which swig >/dev/null 2>&1; then \
|
|
can_build=yes; \
|
|
@@ -132,7 +133,9 @@ maybe_pylibfdt: FORCE
|
|
echo "## Skipping pylibfdt (install python dev and swig to build)"; \
|
|
fi
|
|
|
|
-all: $(BIN) libfdt maybe_pylibfdt
|
|
+ifeq ($(NO_PYTHON),)
|
|
+all: maybe_pylibfdt
|
|
+endif
|
|
|
|
|
|
ifneq ($(DEPTARGETS),)
|
|
@@ -195,7 +198,11 @@ install-includes:
|
|
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
|
|
$(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
|
|
|
|
-install: install-bin install-lib install-includes maybe_install_pylibfdt
|
|
+install: install-bin install-lib install-includes
|
|
+
|
|
+ifeq ($(NO_PYTHON),)
|
|
+install: install_pylibfdt
|
|
+endif
|
|
|
|
$(VERSION_FILE): Makefile FORCE
|
|
$(call filechk,version)
|
|
@@ -267,7 +274,9 @@ TESTS_BIN += convert-dtsv0
|
|
TESTS_BIN += fdtput
|
|
TESTS_BIN += fdtget
|
|
TESTS_BIN += fdtdump
|
|
+ifeq ($(NO_PYTHON),)
|
|
TESTS_PYLIBFDT += maybe_pylibfdt
|
|
+endif
|
|
|
|
include tests/Makefile.tests
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index 0e8ac5f..4036b1f 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -25,11 +25,4 @@ install_pylibfdt: $(WRAP) $(PYMODULE)
|
|
$(call run_setup, $(PYLIBFDT_srcs) $(WRAP), \
|
|
install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)))
|
|
|
|
-maybe_install_pylibfdt:
|
|
- if [ -e $(PYMODULE) ]; then \
|
|
- if [ -z "$(NO_PYTHON)" ]; then \
|
|
- $(MAKE) install_pylibfdt; \
|
|
- fi; \
|
|
- fi
|
|
-
|
|
PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so
|
|
--
|
|
2.13.0
|
|
|
|
From e56f2b07be3866eff49651cbe34be3bce79ceb38 Mon Sep 17 00:00:00 2001
|
|
From: Simon Glass <sjg@chromium.org>
|
|
Date: Fri, 7 Apr 2017 15:51:34 -0600
|
|
Subject: [PATCH 21/29] pylibfdt: Use setup.py to build the swig file
|
|
|
|
Since we are using the standard .i extension for the swig file, we can use
|
|
setup.py to build the wrapper. Drop the existing build code since it is
|
|
not needed.
|
|
|
|
Signed-off-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
---
|
|
pylibfdt/Makefile.pylibfdt | 14 +++++---------
|
|
1 file changed, 5 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
|
|
index 4036b1f..9507d3d 100644
|
|
--- a/pylibfdt/Makefile.pylibfdt
|
|
+++ b/pylibfdt/Makefile.pylibfdt
|
|
@@ -1,8 +1,8 @@
|
|
# Makefile.pylibfdt
|
|
#
|
|
|
|
-PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS))
|
|
-WRAP = $(PYLIBFDT_objdir)/libfdt_wrap.c
|
|
+PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \
|
|
+ $(PYLIBFDT_srcdir)/libfdt.i
|
|
PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
|
|
|
define run_setup
|
|
@@ -11,18 +11,14 @@ define run_setup
|
|
$(PYLIBFDT_objdir)/setup.py --quiet $(2)
|
|
endef
|
|
|
|
-$(PYMODULE): $(PYLIBFDT_srcs) $(WRAP)
|
|
+$(PYMODULE): $(PYLIBFDT_srcs)
|
|
@$(VECHO) PYMOD $@
|
|
$(call run_setup, $^, build_ext --inplace)
|
|
mv _libfdt.so $@
|
|
|
|
-$(WRAP): $(PYLIBFDT_srcdir)/libfdt.i
|
|
- @$(VECHO) SWIG $@
|
|
- $(SWIG) -python -o $@ $<
|
|
-
|
|
-install_pylibfdt: $(WRAP) $(PYMODULE)
|
|
+install_pylibfdt: $(PYMODULE)
|
|
$(VECHO) INSTALL-PYLIB; \
|
|
- $(call run_setup, $(PYLIBFDT_srcs) $(WRAP), \
|
|
+ $(call run_setup, $(PYLIBFDT_srcs), \
|
|
install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)))
|
|
|
|
PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so
|
|
--
|
|
2.13.0
|
|
|