* [PATCH 0/4] Introduce Python bindings for libfdt
@ 2016-11-17 22:53 Simon Glass
[not found] ` <1479423205-9817-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
0 siblings, 1 reply; 8+ messages in thread
From: Simon Glass @ 2016-11-17 22:53 UTC (permalink / raw)
To: Devicetree Compiler; +Cc: David Gibson, Simon Glass
At present libfdt consists of only a C implementation. Many scripts are
written using Python so it useful to have Python bindings for libfdt.
Apparently this has never been attempted before, or if so I cannot find a
reference.
This series starts the process of adding this support, with just a
bare-bones set of methods, to attract initial comments.
Simon Glass (4):
Add an initial Python library for libfdt
Add tests for pylibfdt
Mention pylibfdt in the documentation
RFC: Build pylibfdt as part of the normal build process
Makefile | 16 +++-
README | 6 ++
pylibfdt/.gitignore | 3 +
pylibfdt/Makefile.pylibfdt | 21 ++++++
pylibfdt/libfdt.swig | 157 +++++++++++++++++++++++++++++++++++++++
pylibfdt/setup.py | 34 +++++++++
tests/pylibfdt_tests.py | 179 +++++++++++++++++++++++++++++++++++++++++++++
tests/run_tests.sh | 19 ++++-
8 files changed, 433 insertions(+), 2 deletions(-)
create mode 100644 pylibfdt/.gitignore
create mode 100644 pylibfdt/Makefile.pylibfdt
create mode 100644 pylibfdt/libfdt.swig
create mode 100644 pylibfdt/setup.py
create mode 100644 tests/pylibfdt_tests.py
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] Add an initial Python library for libfdt
[not found] ` <1479423205-9817-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2016-11-17 22:53 ` Simon Glass
[not found] ` <1479423205-9817-2-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2016-11-17 22:53 ` [PATCH 2/4] Add tests for pylibfdt Simon Glass
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Simon Glass @ 2016-11-17 22:53 UTC (permalink / raw)
To: Devicetree Compiler; +Cc: David Gibson, Simon Glass
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-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
pylibfdt/.gitignore | 3 +
pylibfdt/Makefile.pylibfdt | 21 ++++++
pylibfdt/libfdt.swig | 157 +++++++++++++++++++++++++++++++++++++++++++++
pylibfdt/setup.py | 34 ++++++++++
4 files changed, 215 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/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..fbdbca5
--- /dev/null
+++ b/pylibfdt/Makefile.pylibfdt
@@ -0,0 +1,21 @@
+# Makefile.pylibfdt
+#
+# This is not a complete Makefile of itself. Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+
+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
+PYLIBFDT_CLEANFILES = $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles))
diff --git a/pylibfdt/libfdt.swig b/pylibfdt/libfdt.swig
new file mode 100644
index 0000000..91887da
--- /dev/null
+++ b/pylibfdt/libfdt.swig
@@ -0,0 +1,157 @@
+/*
+ * pylibfdt - Flat Device Tree manipulation in Python
+ * Copyright (C) 2016 Google, Inc.
+ * Written by Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.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 %{
+
+def Raise(errnum):
+ raise ValueError('Error %s' % fdt_strerror(errnum))
+
+def Name(fdt, offset):
+ name, len = fdt_get_name(fdt, offset)
+ return name
+
+def String(fdt, offset):
+ offset = fdt32_to_cpu(offset)
+ name = fdt_string(fdt, offset)
+ return name
+
+def fdt32_to_cpu(val):
+ return struct.unpack("=I", struct.pack(">I", val))[0]
+
+def Data(prop):
+ set_prop(prop)
+ return get_prop_data()
+%}
+
+%include "typemaps.i"
+%include "cstring.i"
+
+%typemap(in) void* = char*;
+
+typedef int fdt32_t;
+
+struct fdt_property {
+ fdt32_t tag;
+ fdt32_t len;
+ fdt32_t nameoff;
+ char data[0];
+};
+
+/*
+ * This is a work-around since I'm not sure of a better way to copy out the
+ * contents of a string. This is used in dtoc/GetProps(). The intent is to
+ * pass in a pointer to a property and access the data field at the end of
+ * it. Ideally the Data() function above would be able to do this directly,
+ * but I'm not sure how to do that. Needs another look.
+ */
+#pragma SWIG nowarn=454
+%inline %{
+ static struct fdt_property *cur_prop;
+
+ void set_prop(struct fdt_property *prop) {
+ cur_prop = prop;
+ }
+%}
+
+%cstring_output_allocate_size(char **s, int *sz, free(*$1));
+%inline %{
+ void get_prop_data(char **s, int *sz) {
+ *sz = fdt32_to_cpu(cur_prop->len);
+ *s = (char *)malloc(*sz);
+ if (!*s)
+ *sz = 0;
+ else
+ memcpy(*s, cur_prop + 1, *sz);
+ }
+%}
+
+%typemap(in) (const void *) {
+ if (!PyByteArray_Check($input)) {
+ SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
+ "$argnum"" of type '" "$type""'");
+ }
+ $1 = (void *) PyByteArray_AsString($input);
+}
+
+int fdt_path_offset(const void *fdt, const char *path);
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+int fdt_next_property_offset(const void *fdt, int offset);
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *OUTPUT);
+const char *fdt_string(const void *fdt, int stroffset);
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *OUTPUT);
+const char *fdt_strerror(int errval);
+int fdt_first_subnode(const void *fdt, int offset);
+int fdt_next_subnode(const void *fdt, int offset);
+
+%typemap(in) (void *) {
+ if (!PyByteArray_Check($input)) {
+ SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
+ "$argnum"" of type '" "$type""'");
+ }
+ $1 = PyByteArray_AsString($input);
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+
+int fdt_pack(void *fdt);
+
+int fdt_totalsize(const void *fdt);
+int fdt_off_dt_struct(const void *fdt);
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
new file mode 100644
index 0000000..8f8618e
--- /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 = "SWIG Docs",
+ description = """Simple swig libfdt from docs""",
+ ext_modules = [libfdt_module],
+ py_modules = ["libfdt"],
+ )
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] Add tests for pylibfdt
[not found] ` <1479423205-9817-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2016-11-17 22:53 ` [PATCH 1/4] Add an initial Python library " Simon Glass
@ 2016-11-17 22:53 ` Simon Glass
2016-11-17 22:53 ` [PATCH 3/4] Mention pylibfdt in the documentation Simon Glass
2016-11-17 22:53 ` [PATCH 4/4] RFC: Build pylibfdt as part of the normal build process Simon Glass
3 siblings, 0 replies; 8+ messages in thread
From: Simon Glass @ 2016-11-17 22:53 UTC (permalink / raw)
To: Devicetree Compiler; +Cc: David Gibson, Simon Glass
Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
tests/pylibfdt_tests.py | 179 ++++++++++++++++++++++++++++++++++++++++++++++++
tests/run_tests.sh | 19 ++++-
2 files changed, 197 insertions(+), 1 deletion(-)
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..c406ac9
--- /dev/null
+++ b/tests/pylibfdt_tests.py
@@ -0,0 +1,179 @@
+# pylibfdt - Tests for Flat Device Tree manipulation in Python
+# Copyright (C) 2016 Google, Inc.
+# Written by Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.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 unittest
+
+sys.path.append('../pylibfdt')
+import libfdt
+
+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 = self._ReadFdt('test_tree1.dtb')
+
+ def _ReadFdt(self, fname):
+ """Read a device tree file into a bytearray ready for use
+
+ Args:
+ fname: Filename to read from
+
+ Returns:
+ Fdt bytearray suitable for passing to libfdt functions
+ """
+ return bytearray(open(fname).read())
+
+ 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 = libfdt.fdt_path_offset(self.fdt, node_path)
+ poffset = libfdt.fdt_first_property_offset(self.fdt, node)
+ while poffset >= 0:
+ pdata, plen = libfdt.fdt_get_property_by_offset(self.fdt, poffset)
+ prop_list.append(libfdt.String(self.fdt, pdata.nameoff))
+ poffset = libfdt.fdt_next_property_offset(self.fdt, poffset)
+ return prop_list
+
+ def testImport(self):
+ """Check that we can import the library correctly"""
+ self.assertEquals(type(libfdt), type(sys))
+
+ def testPathOffset(self):
+ """Check that we can find the offset of a node"""
+ self.assertEquals(libfdt.fdt_path_offset(self.fdt, '/'), 0)
+ self.assertEquals(libfdt.fdt_path_offset(self.fdt, '/subnode@1'), 124)
+
+ def testPropertyOffset(self):
+ """Walk through all the properties in the root node"""
+ self.assertEquals(libfdt.fdt_first_property_offset(self.fdt, 0), 8)
+ self.assertEquals(libfdt.fdt_next_property_offset(self.fdt, 8), 32)
+ self.assertEquals(libfdt.fdt_next_property_offset(self.fdt, 32), 48)
+ self.assertEquals(libfdt.fdt_next_property_offset(self.fdt, 48), 68)
+ self.assertEquals(libfdt.fdt_next_property_offset(self.fdt, 68), 92)
+ self.assertEquals(libfdt.fdt_next_property_offset(self.fdt, 92), 108)
+ self.assertEquals(libfdt.fdt_next_property_offset(self.fdt, 108), -1)
+
+ def testGetName(self):
+ """Check that we can get the name of a node"""
+ self.assertEquals(libfdt.fdt_get_name(self.fdt, 0), ['', 0])
+ node = libfdt.fdt_path_offset(self.fdt, '/subnode@1/subsubnode')
+ self.assertEquals(libfdt.fdt_get_name(self.fdt, node),
+ ['subsubnode', 10])
+
+ def testGetString(self):
+ """Test that we can get a string from the string table"""
+ node = libfdt.fdt_path_offset(self.fdt, '/subnode@2')
+ poffset = libfdt.fdt_first_property_offset(self.fdt, node)
+ pdata, plen = libfdt.fdt_get_property_by_offset(self.fdt, poffset)
+ self.assertEquals(libfdt.String(self.fdt, pdata.nameoff), 'reg')
+
+ def testGetPropertyByOffset(self):
+ """Check that we can read the name and contents of a property"""
+ root = libfdt.fdt_path_offset(self.fdt, '/')
+ poffset = libfdt.fdt_first_property_offset(self.fdt, root)
+ pdata, plen = libfdt.fdt_get_property_by_offset(self.fdt, poffset)
+ self.assertEquals(libfdt.fdt32_to_cpu(pdata.tag), 3)
+ self.assertEquals(libfdt.fdt32_to_cpu(pdata.len), 11)
+ self.assertEquals(libfdt.String(self.fdt, pdata.nameoff), 'compatible')
+ self.assertEquals(libfdt.Data(pdata), 'test_tree1\0')
+
+ def testStrError(self):
+ """Check that we can get an error string"""
+ self.assertEquals(libfdt.fdt_strerror(-1), 'FDT_ERR_NOTFOUND')
+
+ def testFirstNextSubnode(self):
+ """Check that we can walk through subnodes"""
+ node_list = []
+ node = libfdt.fdt_first_subnode(self.fdt, 0)
+ while node >= 0:
+ node_list.append(libfdt.fdt_get_name(self.fdt, node)[0])
+ node = libfdt.fdt_next_subnode(self.fdt, node)
+ self.assertEquals(node_list, ['subnode@1', 'subnode@2'])
+
+ 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 = libfdt.fdt_path_offset(self.fdt, '/%s' % node_name)
+ self.assertEquals(libfdt.fdt_delprop(self.fdt, 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(libfdt.fdt_totalsize(self.fdt), 693)
+ self.assertEquals(libfdt.fdt_off_dt_struct(self.fdt), 88)
+
+ def testPack(self):
+ """Test that we can pack the tree after deleting something"""
+ self.assertEquals(libfdt.fdt_totalsize(self.fdt), 693)
+ node = libfdt.fdt_path_offset(self.fdt, '/subnode@2')
+ self.assertEquals(libfdt.fdt_delprop(self.fdt, node, 'prop-int'), 0)
+ self.assertEquals(libfdt.fdt_totalsize(self.fdt), 693)
+ self.assertEquals(libfdt.fdt_pack(self.fdt), 0)
+ self.assertEquals(libfdt.fdt_totalsize(self.fdt), 677)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e4139dd..707702d 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -720,6 +720,20 @@ fdtdump_tests () {
run_fdtdump_test fdtdump.dts
}
+pylibfdt_tests () {
+ TMP=/tmp/tests.stderr.$$
+ python pylibfdt_tests.py 2> ${TMP}
+ result=$(head -1 ${TMP} | awk \
+ '{ for (i = 1; i <= length($0); i++) { \
+ result = substr($0,i,1); fail = fail + (result == "F"); \
+ ok = ok + (result == ".")}; } END { print fail, ok, fail + ok}')
+
+ # Extract the test results and add them to our totals
+ tot_fail=$((tot_fail + $(echo $result | cut -d" " -f 1)))
+ tot_pass=$((tot_pass + $(echo $result | cut -d" " -f 2)))
+ tot_tests=$((tot_tests + $(echo $result | cut -d" " -f 3)))
+}
+
while getopts "vt:me" ARG ; do
case $ARG in
"v")
@@ -738,7 +752,7 @@ while getopts "vt:me" ARG ; do
done
if [ -z "$TESTSETS" ]; then
- TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump"
+ TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump pylibfdt"
fi
# Make sure we don't have stale blobs lying around
@@ -767,6 +781,9 @@ for set in $TESTSETS; do
"fdtdump")
fdtdump_tests
;;
+ "pylibfdt")
+ pylibfdt_tests
+ ;;
esac
done
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] Mention pylibfdt in the documentation
[not found] ` <1479423205-9817-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2016-11-17 22:53 ` [PATCH 1/4] Add an initial Python library " Simon Glass
2016-11-17 22:53 ` [PATCH 2/4] Add tests for pylibfdt Simon Glass
@ 2016-11-17 22:53 ` Simon Glass
2016-11-17 22:53 ` [PATCH 4/4] RFC: Build pylibfdt as part of the normal build process Simon Glass
3 siblings, 0 replies; 8+ messages in thread
From: Simon Glass @ 2016-11-17 22:53 UTC (permalink / raw)
To: Devicetree Compiler; +Cc: David Gibson, Simon Glass
Add a note about pylibfdt in the README.
Full documentation for pylibfdt will need to be provided also.
Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
README | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/README b/README
index f92008f..dee77c8 100644
--- a/README
+++ b/README
@@ -7,6 +7,12 @@ DTC and LIBFDT are maintained by:
David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
Jon Loeliger <jdl-CYoMK+44s/E@public.gmane.org>
+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
+
+
Mailing list
------------
The following list is for discussion about dtc and libfdt implementation
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] RFC: Build pylibfdt as part of the normal build process
[not found] ` <1479423205-9817-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
` (2 preceding siblings ...)
2016-11-17 22:53 ` [PATCH 3/4] Mention pylibfdt in the documentation Simon Glass
@ 2016-11-17 22:53 ` Simon Glass
3 siblings, 0 replies; 8+ messages in thread
From: Simon Glass @ 2016-11-17 22:53 UTC (permalink / raw)
To: Devicetree Compiler; +Cc: David Gibson, Simon Glass
Possible this needs to be made optional. For now just hook it up.
Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
Makefile | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 32dcfcf..4996cfd 100644
--- a/Makefile
+++ b/Makefile
@@ -115,7 +115,7 @@ BIN += fdtput
SCRIPTS = dtdiff
-all: $(BIN) libfdt
+all: $(BIN) libfdt pylibfdt
ifneq ($(DEPTARGETS),)
@@ -202,6 +202,19 @@ 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
+
+
#
# Release signing and uploading
# This is for maintainer convenience, don't try this at home.
@@ -240,6 +253,7 @@ STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \
clean: libfdt_clean tests_clean
@$(VECHO) CLEAN
rm -f $(STD_CLEANFILES)
+ rm -f $(PYLIBFDT_CLEANFILES)
rm -f $(VERSION_FILE)
rm -f $(BIN)
rm -f dtc-*.tar dtc-*.tar.sign dtc-*.tar.asc
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] Add an initial Python library for libfdt
[not found] ` <1479423205-9817-2-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2016-11-18 0:36 ` David Gibson
[not found] ` <20161118003645.GC31640-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
0 siblings, 1 reply; 8+ messages in thread
From: David Gibson @ 2016-11-18 0:36 UTC (permalink / raw)
To: Simon Glass; +Cc: Devicetree Compiler
[-- Attachment #1: Type: text/plain, Size: 10393 bytes --]
On Thu, Nov 17, 2016 at 03:53:22PM -0700, Simon Glass wrote:
> Add Python bindings for a bare-bones set of libfdt functions. These allow
> navigating the tree and reading node names and properties.
Nice idea. Some nits in the details..
>
> Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> ---
>
> pylibfdt/.gitignore | 3 +
> pylibfdt/Makefile.pylibfdt | 21 ++++++
> pylibfdt/libfdt.swig | 157 +++++++++++++++++++++++++++++++++++++++++++++
> pylibfdt/setup.py | 34 ++++++++++
> 4 files changed, 215 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/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..fbdbca5
> --- /dev/null
> +++ b/pylibfdt/Makefile.pylibfdt
> @@ -0,0 +1,21 @@
> +# Makefile.pylibfdt
> +#
> +# This is not a complete Makefile of itself. Instead, it is designed to
> +# be easily embeddable into other systems of Makefiles.
So, Makefile.libfdt is explicitly designed for easily embedding libfdt
in other projecs - even ones with weird build environments, like
bootloaders. It's less clear that that's valuable for Python
wrappers.
> +#
> +
> +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
> +PYLIBFDT_CLEANFILES = $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles))
> diff --git a/pylibfdt/libfdt.swig b/pylibfdt/libfdt.swig
> new file mode 100644
> index 0000000..91887da
> --- /dev/null
> +++ b/pylibfdt/libfdt.swig
> @@ -0,0 +1,157 @@
> +/*
> + * pylibfdt - Flat Device Tree manipulation in Python
> + * Copyright (C) 2016 Google, Inc.
> + * Written by Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.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 %{
> +
> +def Raise(errnum):
> + raise ValueError('Error %s' % fdt_strerror(errnum))
So, first, I believe this and several things below break normal Python
capitalization conventions for functions (capital-followed-by-lower
generally indicates a class).
More importantly, wouldn't it make more sense to have an Exception
subclass for libfdt errors, rather than shuffling everything through
ValueError?
> +def Name(fdt, offset):
> + name, len = fdt_get_name(fdt, offset)
> + return name
> +
> +def String(fdt, offset):
> + offset = fdt32_to_cpu(offset)
> + name = fdt_string(fdt, offset)
> + return name
> +
> +def fdt32_to_cpu(val):
> + return struct.unpack("=I", struct.pack(">I", val))[0]
> +
> +def Data(prop):
> + set_prop(prop)
> + return get_prop_data()
> +%}
> +
> +%include "typemaps.i"
> +%include "cstring.i"
> +
> +%typemap(in) void* = char*;
> +
> +typedef int fdt32_t;
> +
> +struct fdt_property {
> + fdt32_t tag;
> + fdt32_t len;
> + fdt32_t nameoff;
> + char data[0];
> +};
Can't you include this directly from fdt.h? That header is guaranteed
never to have actual function definitions, just data structures and
constants.
> +/*
> + * This is a work-around since I'm not sure of a better way to copy out the
> + * contents of a string. This is used in dtoc/GetProps(). The intent is to
> + * pass in a pointer to a property and access the data field at the end of
> + * it. Ideally the Data() function above would be able to do this directly,
> + * but I'm not sure how to do that. Needs another look.
> + */
> +#pragma SWIG nowarn=454
> +%inline %{
> + static struct fdt_property *cur_prop;
> +
> + void set_prop(struct fdt_property *prop) {
> + cur_prop = prop;
> + }
Eugh... a global variable making this totally non thread safe. You
really need a better solution. Property values you should be able to
represent nicely as Python strings (since unlike C strings, those can
include embedded \0). Uh.. I guess that's 'bytes' for Python3
Of course, in the other direction, node and property names can't
include \0, so you probably need some sort of exception if a Python
string which includes them is passed in.
> +%}
> +
> +%cstring_output_allocate_size(char **s, int *sz, free(*$1));
> +%inline %{
> + void get_prop_data(char **s, int *sz) {
> + *sz = fdt32_to_cpu(cur_prop->len);
> + *s = (char *)malloc(*sz);
> + if (!*s)
> + *sz = 0;
> + else
> + memcpy(*s, cur_prop + 1, *sz);
> + }
> +%}
> +
> +%typemap(in) (const void *) {
> + if (!PyByteArray_Check($input)) {
> + SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
> + "$argnum"" of type '" "$type""'");
> + }
> + $1 = (void *) PyByteArray_AsString($input);
> +}
> +
> +int fdt_path_offset(const void *fdt, const char *path);
> +int fdt_first_property_offset(const void *fdt, int nodeoffset);
> +int fdt_next_property_offset(const void *fdt, int offset);
> +const char *fdt_get_name(const void *fdt, int nodeoffset, int *OUTPUT);
> +const char *fdt_string(const void *fdt, int stroffset);
> +const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> + int offset,
> + int *OUTPUT);
> +const char *fdt_strerror(int errval);
> +int fdt_first_subnode(const void *fdt, int offset);
> +int fdt_next_subnode(const void *fdt, int offset);
> +
> +%typemap(in) (void *) {
> + if (!PyByteArray_Check($input)) {
> + SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
> + "$argnum"" of type '" "$type""'");
> + }
> + $1 = PyByteArray_AsString($input);
> +}
> +
> +int fdt_delprop(void *fdt, int nodeoffset, const char *name);
> +
> +int fdt_pack(void *fdt);
> +
> +int fdt_totalsize(const void *fdt);
> +int fdt_off_dt_struct(const void *fdt);
> diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
> new file mode 100644
> index 0000000..8f8618e
> --- /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 = "SWIG Docs",
> + description = """Simple swig libfdt from docs""",
> + ext_modules = [libfdt_module],
> + py_modules = ["libfdt"],
> + )
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] Add an initial Python library for libfdt
[not found] ` <20161118003645.GC31640-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
@ 2016-11-24 18:08 ` Simon Glass
[not found] ` <CAPnjgZ1=QTBNZa4G_uFpka3acr91ywH2P1QF8FJkfS-7Wpd5OQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 8+ messages in thread
From: Simon Glass @ 2016-11-24 18:08 UTC (permalink / raw)
To: David Gibson; +Cc: Devicetree Compiler
Hi David,
On 17 November 2016 at 17:36, David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> On Thu, Nov 17, 2016 at 03:53:22PM -0700, Simon Glass wrote:
>> Add Python bindings for a bare-bones set of libfdt functions. These allow
>> navigating the tree and reading node names and properties.
>
> Nice idea. Some nits in the details..
>
>>
>> Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
>> ---
>>
>> pylibfdt/.gitignore | 3 +
>> pylibfdt/Makefile.pylibfdt | 21 ++++++
>> pylibfdt/libfdt.swig | 157 +++++++++++++++++++++++++++++++++++++++++++++
>> pylibfdt/setup.py | 34 ++++++++++
>> 4 files changed, 215 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/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..fbdbca5
>> --- /dev/null
>> +++ b/pylibfdt/Makefile.pylibfdt
>> @@ -0,0 +1,21 @@
>> +# Makefile.pylibfdt
>> +#
>> +# This is not a complete Makefile of itself. Instead, it is designed to
>> +# be easily embeddable into other systems of Makefiles.
>
> So, Makefile.libfdt is explicitly designed for easily embedding libfdt
> in other projecs - even ones with weird build environments, like
> bootloaders. It's less clear that that's valuable for Python
> wrappers.
OK, but what should i do instead?
Regards,
Simon
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] Add an initial Python library for libfdt
[not found] ` <CAPnjgZ1=QTBNZa4G_uFpka3acr91ywH2P1QF8FJkfS-7Wpd5OQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2016-11-24 22:03 ` David Gibson
0 siblings, 0 replies; 8+ messages in thread
From: David Gibson @ 2016-11-24 22:03 UTC (permalink / raw)
To: Simon Glass; +Cc: Devicetree Compiler
[-- Attachment #1: Type: text/plain, Size: 2259 bytes --]
On Thu, Nov 24, 2016 at 11:08:00AM -0700, Simon Glass wrote:
> Hi David,
>
> On 17 November 2016 at 17:36, David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> > On Thu, Nov 17, 2016 at 03:53:22PM -0700, Simon Glass wrote:
> >> Add Python bindings for a bare-bones set of libfdt functions. These allow
> >> navigating the tree and reading node names and properties.
> >
> > Nice idea. Some nits in the details..
> >
> >>
> >> Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> >> ---
> >>
> >> pylibfdt/.gitignore | 3 +
> >> pylibfdt/Makefile.pylibfdt | 21 ++++++
> >> pylibfdt/libfdt.swig | 157 +++++++++++++++++++++++++++++++++++++++++++++
> >> pylibfdt/setup.py | 34 ++++++++++
> >> 4 files changed, 215 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/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..fbdbca5
> >> --- /dev/null
> >> +++ b/pylibfdt/Makefile.pylibfdt
> >> @@ -0,0 +1,21 @@
> >> +# Makefile.pylibfdt
> >> +#
> >> +# This is not a complete Makefile of itself. Instead, it is designed to
> >> +# be easily embeddable into other systems of Makefiles.
> >
> > So, Makefile.libfdt is explicitly designed for easily embedding libfdt
> > in other projecs - even ones with weird build environments, like
> > bootloaders. It's less clear that that's valuable for Python
> > wrappers.
>
> OK, but what should i do instead?
Sorry, I just meant that that copied comment doesn't really make sense
in its entirity here. Otherwise the makefile is fine.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-11-24 22:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-17 22:53 [PATCH 0/4] Introduce Python bindings for libfdt Simon Glass
[not found] ` <1479423205-9817-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2016-11-17 22:53 ` [PATCH 1/4] Add an initial Python library " Simon Glass
[not found] ` <1479423205-9817-2-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2016-11-18 0:36 ` David Gibson
[not found] ` <20161118003645.GC31640-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2016-11-24 18:08 ` Simon Glass
[not found] ` <CAPnjgZ1=QTBNZa4G_uFpka3acr91ywH2P1QF8FJkfS-7Wpd5OQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-11-24 22:03 ` David Gibson
2016-11-17 22:53 ` [PATCH 2/4] Add tests for pylibfdt Simon Glass
2016-11-17 22:53 ` [PATCH 3/4] Mention pylibfdt in the documentation Simon Glass
2016-11-17 22:53 ` [PATCH 4/4] RFC: Build pylibfdt as part of the normal build process Simon Glass
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).