Update dtc to the version of 20170713 of upstream
am: a058df1cff
Change-Id: Idc39b25e3aa0d1c8cf118a65331539c6694aea1d
This commit is contained in:
commit
06f6876f93
35 changed files with 1677 additions and 29 deletions
25
.travis.yml
25
.travis.yml
|
@ -1,5 +1,30 @@
|
|||
language: c
|
||||
|
||||
# Coverity Scan uploads
|
||||
env:
|
||||
global:
|
||||
# COVERITY_SCAN_TOKEN (dgibson/dtc)
|
||||
- secure: "vlHvXe618//IM9LQaKzqsrUbjs7ng0L9UCST4kJbJnFQDXvVe5JiSmJGd4ef7mm0NUv5bMRl2W3xCiu6BYAu/NvU3tMNHoLG+JgCJs0+wLJXbWOwji/NmH7olqgJG+CmpaCMXjARF6+nrTnBYHJL6cYyf4KVoV4B0I/hLUW91+s="
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- addons:
|
||||
apt:
|
||||
packages:
|
||||
- swig
|
||||
- python-dev
|
||||
coverity_scan:
|
||||
project:
|
||||
name: dtc
|
||||
description: Device Tree Compiler
|
||||
notification_email: david@gibson.dropbear.id.au
|
||||
build_command: make
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
- addons:
|
||||
apt:
|
||||
packages:
|
||||
|
||||
script:
|
||||
- make
|
||||
- make check
|
||||
|
|
|
@ -674,4 +674,22 @@ The fdtdump program prints a readable version of a flat device tree file.
|
|||
|
||||
The syntax of the fdtdump command line is:
|
||||
|
||||
fdtdump <DTB-file-name>
|
||||
fdtdump [options] <DTB-file-name>
|
||||
|
||||
Where options are:
|
||||
-d,--debug Dump debug information while decoding the file
|
||||
-s,--scan Scan for an embedded fdt in given file
|
||||
|
||||
3) fdtoverlay -- Flat Device Tree overlay applicator
|
||||
|
||||
The fdtoverlay applies an arbitrary number of FDT overlays to a base FDT blob
|
||||
to a given output file.
|
||||
|
||||
The syntax of the fdtoverlay command line is:
|
||||
|
||||
fdtoverlay -i <base-blob> -o <output-blob> <overlay-blob0> [<overlay-blob1> ...]
|
||||
|
||||
Where options are:
|
||||
-i, --input Input base DT blob
|
||||
-o, --output Output DT blob
|
||||
-v, --verbose Verbose message output
|
||||
|
|
70
Makefile
70
Makefile
|
@ -18,10 +18,12 @@ CONFIG_LOCALVERSION =
|
|||
CPPFLAGS = -I libfdt -I .
|
||||
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
|
||||
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
|
||||
CFLAGS = -g -Os -fPIC -Werror $(WARNINGS)
|
||||
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS)
|
||||
|
||||
BISON = bison
|
||||
LEX = flex
|
||||
SWIG = swig
|
||||
PKG_CONFIG ?= pkg-config
|
||||
|
||||
INSTALL = /usr/bin/install
|
||||
DESTDIR =
|
||||
|
@ -31,14 +33,20 @@ LIBDIR = $(PREFIX)/lib
|
|||
INCLUDEDIR = $(PREFIX)/include
|
||||
|
||||
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
|
||||
sed -e 's/\(cygwin\).*/cygwin/')
|
||||
sed -e 's/\(cygwin\|msys\).*/\1/')
|
||||
|
||||
ifeq ($(HOSTOS),darwin)
|
||||
SHAREDLIB_EXT=dylib
|
||||
SHAREDLIB_LINK_OPTIONS=-dynamiclib -Wl,-install_name -Wl,
|
||||
SHAREDLIB_EXT = dylib
|
||||
SHAREDLIB_CFLAGS = -fPIC
|
||||
SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl,
|
||||
else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
|
||||
SHAREDLIB_EXT = so
|
||||
SHAREDLIB_CFLAGS =
|
||||
SHAREDLIB_LDFLAGS = -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
|
||||
else
|
||||
SHAREDLIB_EXT=so
|
||||
SHAREDLIB_LINK_OPTIONS=-shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
|
||||
SHAREDLIB_EXT = so
|
||||
SHAREDLIB_CFLAGS = -fPIC
|
||||
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
|
||||
endif
|
||||
|
||||
#
|
||||
|
@ -112,11 +120,30 @@ BIN += dtc
|
|||
BIN += fdtdump
|
||||
BIN += fdtget
|
||||
BIN += fdtput
|
||||
BIN += fdtoverlay
|
||||
|
||||
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 pylibfdt (install python dev and swig to build)"; \
|
||||
fi
|
||||
|
||||
ifeq ($(NO_PYTHON),)
|
||||
all: maybe_pylibfdt
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(DEPTARGETS),)
|
||||
-include $(DTC_OBJS:%.o=%.d)
|
||||
|
@ -124,6 +151,7 @@ ifneq ($(DEPTARGETS),)
|
|||
-include $(FDTDUMP_OBJS:%.o=%.d)
|
||||
-include $(FDTGET_OBJS:%.o=%.d)
|
||||
-include $(FDTPUT_OBJS:%.o=%.d)
|
||||
-include $(FDTOVERLAY_OBJS:%.o=%.d)
|
||||
endif
|
||||
|
||||
|
||||
|
@ -180,6 +208,10 @@ install-includes:
|
|||
|
||||
install: install-bin install-lib install-includes
|
||||
|
||||
ifeq ($(NO_PYTHON),)
|
||||
install: install_pylibfdt
|
||||
endif
|
||||
|
||||
$(VERSION_FILE): Makefile FORCE
|
||||
$(call filechk,version)
|
||||
|
||||
|
@ -196,12 +228,30 @@ fdtget: $(FDTGET_OBJS) $(LIBFDT_archive)
|
|||
|
||||
fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive)
|
||||
|
||||
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_archive)
|
||||
|
||||
dist:
|
||||
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
|
||||
> ../dtc-$(dtc_version).tar
|
||||
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.
|
||||
|
@ -234,6 +284,10 @@ TESTS_BIN += convert-dtsv0
|
|||
TESTS_BIN += fdtput
|
||||
TESTS_BIN += fdtget
|
||||
TESTS_BIN += fdtdump
|
||||
TESTS_BIN += fdtoverlay
|
||||
ifeq ($(NO_PYTHON),)
|
||||
TESTS_PYLIBFDT += maybe_pylibfdt
|
||||
endif
|
||||
|
||||
include tests/Makefile.tests
|
||||
|
||||
|
@ -243,7 +297,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)
|
||||
|
@ -287,7 +341,7 @@ clean: libfdt_clean tests_clean
|
|||
|
||||
$(LIBFDT_lib):
|
||||
@$(VECHO) LD $@
|
||||
$(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^
|
||||
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^
|
||||
|
||||
%.lex.c: %.l
|
||||
@$(VECHO) LEX $@
|
||||
|
|
|
@ -22,3 +22,9 @@ FDTPUT_SRCS = \
|
|||
util.c
|
||||
|
||||
FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o)
|
||||
|
||||
FDTOVERLAY_SRCS = \
|
||||
fdtoverlay.c \
|
||||
util.c
|
||||
|
||||
FDTOVERLAY_OBJS = $(FDTOVERLAY_SRCS:%.c=%.o)
|
||||
|
|
66
README
66
README
|
@ -7,6 +7,72 @@ 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
|
||||
|
||||
|
||||
To install the library via the normal setup.py method, use:
|
||||
|
||||
./pylibfdt/setup.py [--prefix=/path/to/install_dir]
|
||||
|
||||
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:
|
||||
|
||||
make NO_PYTHON=1
|
||||
|
||||
|
||||
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
|
||||
|
|
231
checks.c
231
checks.c
|
@ -681,6 +681,229 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
|
|||
}
|
||||
WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
|
||||
|
||||
static const struct bus_type pci_bus = {
|
||||
.name = "PCI",
|
||||
};
|
||||
|
||||
static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
|
||||
{
|
||||
struct property *prop;
|
||||
cell_t *cells;
|
||||
|
||||
prop = get_property(node, "device_type");
|
||||
if (!prop || !streq(prop->val.val, "pci"))
|
||||
return;
|
||||
|
||||
node->bus = &pci_bus;
|
||||
|
||||
if (!strneq(node->name, "pci", node->basenamelen) &&
|
||||
!strneq(node->name, "pcie", node->basenamelen))
|
||||
FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
|
||||
node->fullpath);
|
||||
|
||||
prop = get_property(node, "ranges");
|
||||
if (!prop)
|
||||
FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)",
|
||||
node->fullpath);
|
||||
|
||||
if (node_addr_cells(node) != 3)
|
||||
FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
|
||||
node->fullpath);
|
||||
if (node_size_cells(node) != 2)
|
||||
FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
|
||||
node->fullpath);
|
||||
|
||||
prop = get_property(node, "bus-range");
|
||||
if (!prop) {
|
||||
FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
|
||||
node->fullpath);
|
||||
return;
|
||||
}
|
||||
if (prop->val.len != (sizeof(cell_t) * 2)) {
|
||||
FAIL(c, dti, "Node %s bus-range must be 2 cells",
|
||||
node->fullpath);
|
||||
return;
|
||||
}
|
||||
cells = (cell_t *)prop->val.val;
|
||||
if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
|
||||
FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell",
|
||||
node->fullpath);
|
||||
if (fdt32_to_cpu(cells[1]) > 0xff)
|
||||
FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256",
|
||||
node->fullpath);
|
||||
}
|
||||
WARNING(pci_bridge, check_pci_bridge, NULL,
|
||||
&device_type_is_string, &addr_size_cells);
|
||||
|
||||
static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node)
|
||||
{
|
||||
struct property *prop;
|
||||
unsigned int bus_num, min_bus, max_bus;
|
||||
cell_t *cells;
|
||||
|
||||
if (!node->parent || (node->parent->bus != &pci_bus))
|
||||
return;
|
||||
|
||||
prop = get_property(node, "reg");
|
||||
if (!prop)
|
||||
return;
|
||||
|
||||
cells = (cell_t *)prop->val.val;
|
||||
bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16;
|
||||
|
||||
prop = get_property(node->parent, "bus-range");
|
||||
if (!prop) {
|
||||
min_bus = max_bus = 0;
|
||||
} else {
|
||||
cells = (cell_t *)prop->val.val;
|
||||
min_bus = fdt32_to_cpu(cells[0]);
|
||||
max_bus = fdt32_to_cpu(cells[0]);
|
||||
}
|
||||
if ((bus_num < min_bus) || (bus_num > max_bus))
|
||||
FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)",
|
||||
node->fullpath, bus_num, min_bus, max_bus);
|
||||
}
|
||||
WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge);
|
||||
|
||||
static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node)
|
||||
{
|
||||
struct property *prop;
|
||||
const char *unitname = get_unitname(node);
|
||||
char unit_addr[5];
|
||||
unsigned int dev, func, reg;
|
||||
cell_t *cells;
|
||||
|
||||
if (!node->parent || (node->parent->bus != &pci_bus))
|
||||
return;
|
||||
|
||||
prop = get_property(node, "reg");
|
||||
if (!prop) {
|
||||
FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
cells = (cell_t *)prop->val.val;
|
||||
if (cells[1] || cells[2])
|
||||
FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0",
|
||||
node->fullpath);
|
||||
|
||||
reg = fdt32_to_cpu(cells[0]);
|
||||
dev = (reg & 0xf800) >> 11;
|
||||
func = (reg & 0x700) >> 8;
|
||||
|
||||
if (reg & 0xff000000)
|
||||
FAIL(c, dti, "Node %s PCI reg address is not configuration space",
|
||||
node->fullpath);
|
||||
if (reg & 0x000000ff)
|
||||
FAIL(c, dti, "Node %s PCI reg config space address register number must be 0",
|
||||
node->fullpath);
|
||||
|
||||
if (func == 0) {
|
||||
snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
|
||||
if (streq(unitname, unit_addr))
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
|
||||
if (streq(unitname, unit_addr))
|
||||
return;
|
||||
|
||||
FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
|
||||
node->fullpath, unit_addr);
|
||||
}
|
||||
WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge);
|
||||
|
||||
static const struct bus_type simple_bus = {
|
||||
.name = "simple-bus",
|
||||
};
|
||||
|
||||
static bool node_is_compatible(struct node *node, const char *compat)
|
||||
{
|
||||
struct property *prop;
|
||||
const char *str, *end;
|
||||
|
||||
prop = get_property(node, "compatible");
|
||||
if (!prop)
|
||||
return false;
|
||||
|
||||
for (str = prop->val.val, end = str + prop->val.len; str < end;
|
||||
str += strnlen(str, end - str) + 1) {
|
||||
if (strneq(str, compat, end - str))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
|
||||
{
|
||||
if (node_is_compatible(node, "simple-bus"))
|
||||
node->bus = &simple_bus;
|
||||
}
|
||||
WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
|
||||
|
||||
static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
|
||||
{
|
||||
struct property *prop;
|
||||
const char *unitname = get_unitname(node);
|
||||
char unit_addr[17];
|
||||
unsigned int size;
|
||||
uint64_t reg = 0;
|
||||
cell_t *cells = NULL;
|
||||
|
||||
if (!node->parent || (node->parent->bus != &simple_bus))
|
||||
return;
|
||||
|
||||
prop = get_property(node, "reg");
|
||||
if (prop)
|
||||
cells = (cell_t *)prop->val.val;
|
||||
else {
|
||||
prop = get_property(node, "ranges");
|
||||
if (prop && prop->val.len)
|
||||
/* skip of child address */
|
||||
cells = ((cell_t *)prop->val.val) + node_addr_cells(node);
|
||||
}
|
||||
|
||||
if (!cells) {
|
||||
if (node->parent->parent && !(node->bus == &simple_bus))
|
||||
FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
size = node_addr_cells(node->parent);
|
||||
while (size--)
|
||||
reg = (reg << 32) | fdt32_to_cpu(*(cells++));
|
||||
|
||||
snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
|
||||
if (!streq(unitname, unit_addr))
|
||||
FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
|
||||
node->fullpath, unit_addr);
|
||||
}
|
||||
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge);
|
||||
|
||||
static void check_unit_address_format(struct check *c, struct dt_info *dti,
|
||||
struct node *node)
|
||||
{
|
||||
const char *unitname = get_unitname(node);
|
||||
|
||||
if (node->parent && node->parent->bus)
|
||||
return;
|
||||
|
||||
if (!unitname[0])
|
||||
return;
|
||||
|
||||
if (!strncmp(unitname, "0x", 2)) {
|
||||
FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
|
||||
node->fullpath);
|
||||
/* skip over 0x for next test */
|
||||
unitname += 2;
|
||||
}
|
||||
if (unitname[0] == '0' && isxdigit(unitname[1]))
|
||||
FAIL(c, dti, "Node %s unit name should not have leading 0s",
|
||||
node->fullpath);
|
||||
}
|
||||
WARNING(unit_address_format, check_unit_address_format, NULL,
|
||||
&node_name_format, &pci_bridge, &simple_bus_bridge);
|
||||
|
||||
/*
|
||||
* Style checks
|
||||
*/
|
||||
|
@ -752,6 +975,14 @@ static struct check *check_table[] = {
|
|||
&addr_size_cells, ®_format, &ranges_format,
|
||||
|
||||
&unit_address_vs_reg,
|
||||
&unit_address_format,
|
||||
|
||||
&pci_bridge,
|
||||
&pci_device_reg,
|
||||
&pci_device_bus_num,
|
||||
|
||||
&simple_bus_bridge,
|
||||
&simple_bus_reg,
|
||||
|
||||
&avoid_default_addr_size,
|
||||
&obsolete_chosen_interrupt_controller,
|
||||
|
|
2
dtc.c
2
dtc.c
|
@ -31,7 +31,7 @@ int reservenum; /* Number of memory reservation slots */
|
|||
int minsize; /* Minimum blob size */
|
||||
int padsize; /* Additional padding to blob */
|
||||
int alignsize; /* Additional padding to blob accroding to the alignsize */
|
||||
int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
|
||||
int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
|
||||
int generate_symbols; /* enable symbols & fixup support */
|
||||
int generate_fixups; /* suppress generation of fixups on symbol support */
|
||||
int auto_label_aliases; /* auto generate labels -> aliases */
|
||||
|
|
6
dtc.h
6
dtc.h
|
@ -31,6 +31,7 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <libfdt_env.h>
|
||||
#include <fdt.h>
|
||||
|
@ -135,6 +136,10 @@ struct label {
|
|||
struct label *next;
|
||||
};
|
||||
|
||||
struct bus_type {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct property {
|
||||
bool deleted;
|
||||
char *name;
|
||||
|
@ -161,6 +166,7 @@ struct node {
|
|||
int addr_cells, size_cells;
|
||||
|
||||
struct label *labels;
|
||||
const struct bus_type *bus;
|
||||
};
|
||||
|
||||
#define for_each_label_withdel(l0, l) \
|
||||
|
|
|
@ -165,7 +165,7 @@ static bool valid_header(char *p, off_t len)
|
|||
if (len < sizeof(struct fdt_header) ||
|
||||
fdt_magic(p) != FDT_MAGIC ||
|
||||
fdt_version(p) > MAX_VERSION ||
|
||||
fdt_last_comp_version(p) >= MAX_VERSION ||
|
||||
fdt_last_comp_version(p) > MAX_VERSION ||
|
||||
fdt_totalsize(p) >= len ||
|
||||
fdt_off_dt_struct(p) >= len ||
|
||||
fdt_off_dt_strings(p) >= len)
|
||||
|
@ -183,6 +183,11 @@ int main(int argc, char *argv[])
|
|||
bool scan = false;
|
||||
off_t len;
|
||||
|
||||
fprintf(stderr, "\n"
|
||||
"**** fdtdump is a low-level debugging tool, not meant for general use.\n"
|
||||
"**** If you want to decompile a dtb, you probably want\n"
|
||||
"**** dtc -I dtb -O dts <filename>\n\n"
|
||||
);
|
||||
while ((opt = util_getopt_long()) != EOF) {
|
||||
switch (opt) {
|
||||
case_USAGE_COMMON_FLAGS
|
||||
|
|
168
fdtoverlay.c
Normal file
168
fdtoverlay.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
|
||||
*
|
||||
* Author:
|
||||
* Pantelis Antoniou <pantelis.antoniou@konsulko.com>
|
||||
*
|
||||
* This program 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 program 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 program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <alloca.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/* Usage related data. */
|
||||
static const char usage_synopsis[] =
|
||||
"apply a number of overlays to a base blob\n"
|
||||
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
|
||||
"\n"
|
||||
USAGE_TYPE_MSG;
|
||||
static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
|
||||
static struct option const usage_long_opts[] = {
|
||||
{"input", required_argument, NULL, 'i'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
USAGE_COMMON_LONG_OPTS,
|
||||
};
|
||||
static const char * const usage_opts_help[] = {
|
||||
"Input base DT blob",
|
||||
"Output DT blob",
|
||||
"Verbose messages",
|
||||
USAGE_COMMON_OPTS_HELP
|
||||
};
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
static int do_fdtoverlay(const char *input_filename,
|
||||
const char *output_filename,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char *blob = NULL;
|
||||
char **ovblob = NULL;
|
||||
off_t blob_len, ov_len, total_len;
|
||||
int i, ret = -1;
|
||||
|
||||
blob = utilfdt_read_len(input_filename, &blob_len);
|
||||
if (!blob) {
|
||||
fprintf(stderr, "\nFailed to read base blob %s\n",
|
||||
input_filename);
|
||||
goto out_err;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
/* allocate blob pointer array */
|
||||
ovblob = alloca(sizeof(*ovblob) * argc);
|
||||
memset(ovblob, 0, sizeof(*ovblob) * argc);
|
||||
|
||||
/* read and keep track of the overlay blobs */
|
||||
total_len = 0;
|
||||
for (i = 0; i < argc; i++) {
|
||||
ovblob[i] = utilfdt_read_len(argv[i], &ov_len);
|
||||
if (!ovblob[i]) {
|
||||
fprintf(stderr, "\nFailed to read overlay %s\n",
|
||||
argv[i]);
|
||||
goto out_err;
|
||||
}
|
||||
total_len += ov_len;
|
||||
}
|
||||
|
||||
/* grow the blob to worst case */
|
||||
blob_len = fdt_totalsize(blob) + total_len;
|
||||
blob = xrealloc(blob, blob_len);
|
||||
fdt_open_into(blob, blob, blob_len);
|
||||
|
||||
/* apply the overlays in sequence */
|
||||
for (i = 0; i < argc; i++) {
|
||||
ret = fdt_overlay_apply(blob, ovblob[i]);
|
||||
if (ret) {
|
||||
fprintf(stderr, "\nFailed to apply %s (%d)\n",
|
||||
argv[i], ret);
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
fdt_pack(blob);
|
||||
ret = utilfdt_write(output_filename, blob);
|
||||
if (ret)
|
||||
fprintf(stderr, "\nFailed to write output blob %s\n",
|
||||
output_filename);
|
||||
|
||||
out_err:
|
||||
if (ovblob) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (ovblob[i])
|
||||
free(ovblob[i]);
|
||||
}
|
||||
}
|
||||
free(blob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt, i;
|
||||
char *input_filename = NULL;
|
||||
char *output_filename = NULL;
|
||||
|
||||
while ((opt = util_getopt_long()) != EOF) {
|
||||
switch (opt) {
|
||||
case_USAGE_COMMON_FLAGS
|
||||
|
||||
case 'i':
|
||||
input_filename = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
output_filename = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!input_filename)
|
||||
usage("missing input file");
|
||||
|
||||
if (!output_filename)
|
||||
usage("missing output file");
|
||||
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
if (argc <= 0)
|
||||
usage("missing overlay file(s)");
|
||||
|
||||
if (verbose) {
|
||||
printf("input = %s\n", input_filename);
|
||||
printf("output = %s\n", output_filename);
|
||||
for (i = 0; i < argc; i++)
|
||||
printf("overlay[%d] = %s\n", i, argv[i]);
|
||||
}
|
||||
|
||||
if (do_fdtoverlay(input_filename, output_filename, argc, argv))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
|
|||
|
||||
return fdt_open_into(buf, buf, bufsize);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
|
|||
{
|
||||
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
|
||||
|
||||
if (! p)
|
||||
if (!p)
|
||||
/* short match */
|
||||
return 0;
|
||||
|
||||
|
@ -327,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|||
const struct fdt_property *prop;
|
||||
|
||||
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return NULL;
|
||||
|
||||
return prop->data;
|
||||
|
|
|
@ -207,7 +207,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
|||
int err;
|
||||
|
||||
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
||||
if (! (*prop))
|
||||
if (!*prop)
|
||||
return oldlen;
|
||||
|
||||
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
||||
|
@ -323,7 +323,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
|
|||
FDT_RW_CHECK_HEADER(fdt);
|
||||
|
||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return len;
|
||||
|
||||
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
|||
int proplen;
|
||||
|
||||
propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
|
||||
if (! propval)
|
||||
if (!propval)
|
||||
return proplen;
|
||||
|
||||
if (proplen != len)
|
||||
|
@ -107,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
|
|||
int len;
|
||||
|
||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return len;
|
||||
|
||||
_fdt_nop_region(prop, len + sizeof(*prop));
|
||||
|
|
|
@ -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
|
||||
|
@ -1297,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);
|
||||
|
@ -1734,8 +1767,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
|
||||
|
|
|
@ -500,7 +500,8 @@ struct node *get_node_by_path(struct node *tree, const char *path)
|
|||
p = strchr(path, '/');
|
||||
|
||||
for_each_child(tree, child) {
|
||||
if (p && strneq(path, child->name, p-path))
|
||||
if (p && (strlen(child->name) == p-path) &&
|
||||
strneq(path, child->name, p-path))
|
||||
return get_node_by_path(child, p+1);
|
||||
else if (!p && streq(path, child->name))
|
||||
return child;
|
||||
|
|
3
pylibfdt/.gitignore
vendored
Normal file
3
pylibfdt/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
libfdt.py
|
||||
libfdt.pyc
|
||||
libfdt_wrap.c
|
24
pylibfdt/Makefile.pylibfdt
Normal file
24
pylibfdt/Makefile.pylibfdt
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Makefile.pylibfdt
|
||||
#
|
||||
|
||||
PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \
|
||||
$(PYLIBFDT_srcdir)/libfdt.i
|
||||
PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
|
||||
|
||||
define run_setup
|
||||
SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)"
|
||||
VERSION="$(dtc_version)"
|
||||
$(PYLIBFDT_objdir)/setup.py --quiet $(2)
|
||||
endef
|
||||
|
||||
$(PYMODULE): $(PYLIBFDT_srcs)
|
||||
@$(VECHO) PYMOD $@
|
||||
$(call run_setup, $^, build_ext --inplace)
|
||||
mv _libfdt.so $@
|
||||
|
||||
install_pylibfdt: $(PYMODULE)
|
||||
$(VECHO) INSTALL-PYLIB; \
|
||||
$(call run_setup, $(PYLIBFDT_srcs), \
|
||||
install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)))
|
||||
|
||||
PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so
|
433
pylibfdt/libfdt.i
Normal file
433
pylibfdt/libfdt.i
Normal file
|
@ -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>
|
121
pylibfdt/setup.py
Executable file
121
pylibfdt/setup.py
Executable file
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
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.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,
|
||||
swig_opts = swig_opts,
|
||||
)
|
||||
|
||||
setup(
|
||||
name='libfdt',
|
||||
version= version,
|
||||
author='Simon Glass <sjg@chromium.org>',
|
||||
description='Python binding for libfdt',
|
||||
ext_modules=[libfdt_module],
|
||||
package_dir={'': objdir},
|
||||
py_modules=['pylibfdt/libfdt'],
|
||||
)
|
|
@ -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),)
|
||||
|
|
40
tests/fdtoverlay-runtest.sh
Normal file
40
tests/fdtoverlay-runtest.sh
Normal file
|
@ -0,0 +1,40 @@
|
|||
#! /bin/sh
|
||||
|
||||
# Run script for fdtoverlay tests
|
||||
# We run fdtoverlay to generate a target device tree, thn fdtget to check it
|
||||
|
||||
# Usage
|
||||
# fdtoverlay-runtest.sh name expected_output dtb_file node property flags value
|
||||
|
||||
. ./tests.sh
|
||||
|
||||
LOG=tmp.log.$$
|
||||
EXPECT=tmp.expect.$$
|
||||
rm -f $LOG $EXPECT
|
||||
trap "rm -f $LOG $EXPECT" 0
|
||||
|
||||
expect="$1"
|
||||
echo $expect >$EXPECT
|
||||
node="$2"
|
||||
property="$3"
|
||||
flags="$4"
|
||||
basedtb="$5"
|
||||
targetdtb="$6"
|
||||
shift 6
|
||||
overlays="$@"
|
||||
|
||||
# First run fdtoverlay
|
||||
verbose_run_check $VALGRIND "$FDTOVERLAY" -i "$basedtb" -o "$targetdtb" $overlays
|
||||
|
||||
# Now fdtget to read the value
|
||||
verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$targetdtb" "$node" "$property" $flags
|
||||
|
||||
if cmp $EXPECT $LOG >/dev/null; then
|
||||
PASS
|
||||
else
|
||||
if [ -z "$QUIET_TEST" ]; then
|
||||
echo "EXPECTED :-:"
|
||||
cat $EXPECT
|
||||
fi
|
||||
FAIL "Results differ from expected"
|
||||
fi
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
subsubnode {
|
||||
compatible = "subsubnode1", "subsubnode";
|
||||
placeholder = "this is a placeholder string", "string2";
|
||||
prop-int = <0xdeadbeef>;
|
||||
};
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ int main(int argc, char *argv[])
|
|||
void *fdt;
|
||||
const char *p;
|
||||
int len, multilen;
|
||||
int n1, n2;
|
||||
int n1, n2, n3, n4;
|
||||
|
||||
test_init(argc, argv);
|
||||
fdt = load_blob_arg(argc, argv);
|
||||
|
@ -92,6 +92,16 @@ int main(int argc, char *argv[])
|
|||
if ((!streq(p, "/node1") || !streq(p + strlen("/node1") + 1, "/node2")))
|
||||
FAIL("multiref has wrong value");
|
||||
|
||||
/* Check reference to nested nodes with common prefix */
|
||||
n3 = fdt_path_offset(fdt, "/foo/baz");
|
||||
if (n3 < 0)
|
||||
FAIL("fdt_path_offset(/foo/baz): %s", fdt_strerror(n3));
|
||||
n4 = fdt_path_offset(fdt, "/foobar/baz");
|
||||
if (n4 < 0)
|
||||
FAIL("fdt_path_offset(/foobar/baz): %s", fdt_strerror(n4));
|
||||
check_ref(fdt, n3, "/foobar/baz");
|
||||
check_ref(fdt, n4, "/foo/baz");
|
||||
|
||||
check_rref(fdt);
|
||||
|
||||
PASS();
|
||||
|
|
|
@ -12,4 +12,17 @@
|
|||
ref = &{/node1}; /* reference after target */
|
||||
lref = &n1;
|
||||
};
|
||||
/* Check references to nested nodes with common prefix */
|
||||
foobar {
|
||||
n3: baz {
|
||||
ref = &{/foo/baz};
|
||||
lref = &n4;
|
||||
};
|
||||
};
|
||||
foo {
|
||||
n4: baz {
|
||||
ref = &{/foobar/baz};
|
||||
lref = &n3;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
288
tests/pylibfdt_tests.py
Normal file
288
tests/pylibfdt_tests.py
Normal file
|
@ -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()
|
|
@ -157,7 +157,15 @@ run_fdtdump_test() {
|
|||
file="$1"
|
||||
shorten_echo fdtdump-runtest.sh "$file"
|
||||
printf ": "
|
||||
base_run_test sh fdtdump-runtest.sh "$file"
|
||||
base_run_test sh fdtdump-runtest.sh "$file" 2>/dev/null
|
||||
}
|
||||
|
||||
run_fdtoverlay_test() {
|
||||
expect="$1"
|
||||
shift
|
||||
shorten_echo fdtoverlay-runtest.sh "$expect" "$@"
|
||||
printf ": "
|
||||
base_run_test sh fdtoverlay-runtest.sh "$expect" "$@"
|
||||
}
|
||||
|
||||
BAD_FIXUP_TREES="bad_index \
|
||||
|
@ -420,7 +428,7 @@ dtc_tests () {
|
|||
run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts
|
||||
run_test path-references dtc_path-references.test.dtb
|
||||
|
||||
run_test phandle_format dtc_references.test.dtb both
|
||||
run_test phandle_format dtc_references.test.dtb epapr
|
||||
for f in legacy epapr both; do
|
||||
run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb references.dts
|
||||
run_test phandle_format dtc_references.test.$f.dtb $f
|
||||
|
@ -540,6 +548,8 @@ dtc_tests () {
|
|||
check_tests obsolete-chosen-interrupt-controller.dts obsolete_chosen_interrupt_controller
|
||||
check_tests reg-without-unit-addr.dts unit_address_vs_reg
|
||||
check_tests unit-addr-without-reg.dts unit_address_vs_reg
|
||||
check_tests unit-addr-leading-0x.dts unit_address_format
|
||||
check_tests unit-addr-leading-0s.dts unit_address_format
|
||||
run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb
|
||||
run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb
|
||||
run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb
|
||||
|
@ -769,6 +779,40 @@ fdtdump_tests () {
|
|||
run_fdtdump_test fdtdump.dts
|
||||
}
|
||||
|
||||
fdtoverlay_tests() {
|
||||
base=overlay_base.dts
|
||||
basedtb=overlay_base.fdoverlay.test.dtb
|
||||
overlay=overlay_overlay_manual_fixups.dts
|
||||
overlaydtb=overlay_overlay_manual_fixups.fdoverlay.test.dtb
|
||||
targetdtb=target.fdoverlay.test.dtb
|
||||
|
||||
run_dtc_test -@ -I dts -O dtb -o $basedtb $base
|
||||
run_dtc_test -@ -I dts -O dtb -o $overlaydtb $overlay
|
||||
|
||||
# test that the new property is installed
|
||||
run_fdtoverlay_test foobar "/test-node" "test-str-property" "-ts" ${basedtb} ${targetdtb} ${overlaydtb}
|
||||
}
|
||||
|
||||
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")
|
||||
|
@ -787,7 +831,12 @@ 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 fdtoverlay"
|
||||
|
||||
# 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
|
||||
|
@ -816,6 +865,12 @@ for set in $TESTSETS; do
|
|||
"fdtdump")
|
||||
fdtdump_tests
|
||||
;;
|
||||
"pylibfdt")
|
||||
pylibfdt_tests
|
||||
;;
|
||||
"fdtoverlay")
|
||||
fdtoverlay_tests
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
subsubnode {
|
||||
compatible = "subsubnode1", "subsubnode";
|
||||
placeholder = "this is a placeholder string", "string2";
|
||||
prop-int = <0xdeadbeef>;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
subsubnode {
|
||||
compatible = "subsubnode1", "subsubnode";
|
||||
placeholder = "this is a placeholder string", "string2";
|
||||
prop-int = <0xdeadbeef>;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ DTC=../dtc
|
|||
DTGET=../fdtget
|
||||
DTPUT=../fdtput
|
||||
FDTDUMP=../fdtdump
|
||||
FDTOVERLAY=../fdtoverlay
|
||||
|
||||
verbose_run () {
|
||||
if [ -z "$QUIET_TEST" ]; then
|
||||
|
|
|
@ -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:
|
||||
|
|
12
tests/unit-addr-leading-0s.dts
Normal file
12
tests/unit-addr-leading-0s.dts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
bus {
|
||||
node@001 {
|
||||
reg = <1 0>;
|
||||
};
|
||||
};
|
||||
};
|
12
tests/unit-addr-leading-0x.dts
Normal file
12
tests/unit-addr-leading-0x.dts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
bus {
|
||||
node@0x1 {
|
||||
reg = <1 0>;
|
||||
};
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue