diff options
78 files changed, 3140 insertions, 435 deletions
| diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 2f073501f82b..72403ac325c0 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -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 @@ -10,7 +10,7 @@  #  VERSION = 1  PATCHLEVEL = 4 -SUBLEVEL = 3 +SUBLEVEL = 6  EXTRAVERSION =  LOCAL_VERSION =  CONFIG_LOCALVERSION = @@ -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 python2 >/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 $@ diff --git a/Makefile.utils b/Makefile.utils index 48ece494b1c4..e0289229e6a5 100644 --- a/Makefile.utils +++ b/Makefile.utils @@ -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) @@ -7,6 +7,83 @@ 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. + + +Tests +----- + +Test files are kept in the tests/ directory. Use 'make check' to build and run +all tests. + +If you want to adjust a test file, be aware that tree_tree1.dts is compiled +and checked against a binary tree from assembler macros in trees.S. So +if you change that file you must change tree.S also. + +  Mailing list  ------------  The following list is for discussion about dtc and libfdt implementation @@ -53,31 +53,27 @@ struct check {  	struct check **prereq;  }; -#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...)	       \ -	static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \ -	static struct check _nm = { \ -		.name = #_nm, \ -		.fn = (_fn), \ -		.data = (_d), \ -		.warn = (_w), \ -		.error = (_e), \ +#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...)	       \ +	static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \ +	static struct check nm_ = { \ +		.name = #nm_, \ +		.fn = (fn_), \ +		.data = (d_), \ +		.warn = (w_), \ +		.error = (e_), \  		.status = UNCHECKED, \ -		.num_prereqs = ARRAY_SIZE(_nm##_prereqs), \ -		.prereq = _nm##_prereqs, \ +		.num_prereqs = ARRAY_SIZE(nm_##_prereqs), \ +		.prereq = nm_##_prereqs, \  	}; -#define WARNING(_nm, _fn, _d, ...) \ -	CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__) -#define ERROR(_nm, _fn, _d, ...) \ -	CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__) -#define CHECK(_nm, _fn, _d, ...) \ -	CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) - -#ifdef __GNUC__ -static inline void check_msg(struct check *c, struct dt_info *dti, -			     const char *fmt, ...) __attribute__((format (printf, 3, 4))); -#endif -static inline void check_msg(struct check *c, struct dt_info *dti, -			     const char *fmt, ...) +#define WARNING(nm_, fn_, d_, ...) \ +	CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__) +#define ERROR(nm_, fn_, d_, ...) \ +	CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__) +#define CHECK(nm_, fn_, d_, ...) \ +	CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__) + +static inline void  PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti, +					   const char *fmt, ...)  {  	va_list ap;  	va_start(ap, fmt); @@ -183,6 +179,36 @@ static void check_is_string(struct check *c, struct dt_info *dti,  #define ERROR_IF_NOT_STRING(nm, propname) \  	ERROR(nm, check_is_string, (propname)) +static void check_is_string_list(struct check *c, struct dt_info *dti, +				 struct node *node) +{ +	int rem, l; +	struct property *prop; +	char *propname = c->data; +	char *str; + +	prop = get_property(node, propname); +	if (!prop) +		return; /* Not present, assumed ok */ + +	str = prop->val.val; +	rem = prop->val.len; +	while (rem > 0) { +		l = strnlen(str, rem); +		if (l == rem) { +			FAIL(c, dti, "\"%s\" property in %s is not a string list", +			     propname, node->fullpath); +			break; +		} +		rem -= l + 1; +		str += l + 1; +	} +} +#define WARNING_IF_NOT_STRING_LIST(nm, propname) \ +	WARNING(nm, check_is_string_list, (propname)) +#define ERROR_IF_NOT_STRING_LIST(nm, propname) \ +	ERROR(nm, check_is_string_list, (propname)) +  static void check_is_cell(struct check *c, struct dt_info *dti,  			  struct node *node)  { @@ -538,13 +564,13 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,  					FAIL(c, dti, "Reference to non-existent node or "  							"label \"%s\"\n", m->ref);  				else /* mark the entry as unresolved */ -					*((cell_t *)(prop->val.val + m->offset)) = +					*((fdt32_t *)(prop->val.val + m->offset)) =  						cpu_to_fdt32(0xffffffff);  				continue;  			}  			phandle = get_node_phandle(dt, refnode); -			*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); +			*((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);  		}  	}  } @@ -590,6 +616,47 @@ WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");  WARNING_IF_NOT_STRING(device_type_is_string, "device_type");  WARNING_IF_NOT_STRING(model_is_string, "model");  WARNING_IF_NOT_STRING(status_is_string, "status"); +WARNING_IF_NOT_STRING(label_is_string, "label"); + +WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible"); + +static void check_names_is_string_list(struct check *c, struct dt_info *dti, +				       struct node *node) +{ +	struct property *prop; + +	for_each_property(node, prop) { +		const char *s = strrchr(prop->name, '-'); +		if (!s || !streq(s, "-names")) +			continue; + +		c->data = prop->name; +		check_is_string_list(c, dti, node); +	} +} +WARNING(names_is_string_list, check_names_is_string_list, NULL); + +static void check_alias_paths(struct check *c, struct dt_info *dti, +				    struct node *node) +{ +	struct property *prop; + +	if (!streq(node->name, "aliases")) +		return; + +	for_each_property(node, prop) { +		if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) { +			FAIL(c, dti, "aliases property '%s' is not a valid node (%s)", +			     prop->name, prop->val.val); +			continue; +		} +		if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name)) +			FAIL(c, dti, "aliases property name '%s' is not valid", +			     prop->name); + +	} +} +WARNING(alias_paths, check_alias_paths, NULL);  static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,  				  struct node *node) @@ -685,6 +752,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 (!strprefixeq(node->name, node->basenamelen, "pci") && +	    !strprefixeq(node->name, node->basenamelen, "pcie")) +		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 (strprefixeq(str, end - str, compat)) +			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   */ @@ -713,6 +1003,31 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,  WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,  	&addr_size_cells); +static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti, +					      struct node *node) +{ +	struct property *prop; +	struct node *child; +	bool has_reg = false; + +	if (!node->parent || node->addr_cells < 0 || node->size_cells < 0) +		return; + +	if (get_property(node, "ranges") || !node->children) +		return; + +	for_each_child(node, child) { +		prop = get_property(child, "reg"); +		if (prop) +			has_reg = true; +	} + +	if (!has_reg) +		FAIL(c, dti, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property in %s", +		     node->fullpath); +} +WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); +  static void check_obsolete_chosen_interrupt_controller(struct check *c,  						       struct dt_info *dti,  						       struct node *node) @@ -737,6 +1052,324 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,  WARNING(obsolete_chosen_interrupt_controller,  	check_obsolete_chosen_interrupt_controller, NULL); +static void check_chosen_node_is_root(struct check *c, struct dt_info *dti, +				      struct node *node) +{ +	if (!streq(node->name, "chosen")) +		return; + +	if (node->parent != dti->dt) +		FAIL(c, dti, "chosen node '%s' must be at root node", +		     node->fullpath); +} +WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL); + +static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti, +				       struct node *node) +{ +	struct property *prop; + +	if (!streq(node->name, "chosen")) +		return; + +	prop = get_property(node, "bootargs"); +	if (!prop) +		return; + +	c->data = prop->name; +	check_is_string(c, dti, node); +} +WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL); + +static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti, +					  struct node *node) +{ +	struct property *prop; + +	if (!streq(node->name, "chosen")) +		return; + +	prop = get_property(node, "stdout-path"); +	if (!prop) { +		prop = get_property(node, "linux,stdout-path"); +		if (!prop) +			return; +		FAIL(c, dti, "Use 'stdout-path' instead of 'linux,stdout-path'"); +	} + +	c->data = prop->name; +	check_is_string(c, dti, node); +} +WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL); + +struct provider { +	const char *prop_name; +	const char *cell_name; +	bool optional; +}; + +static void check_property_phandle_args(struct check *c, +					  struct dt_info *dti, +				          struct node *node, +				          struct property *prop, +				          const struct provider *provider) +{ +	struct node *root = dti->dt; +	int cell, cellsize = 0; + +	if (prop->val.len % sizeof(cell_t)) { +		FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", +		     prop->name, prop->val.len, sizeof(cell_t), node->fullpath); +		return; +	} + +	for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) { +		struct node *provider_node; +		struct property *cellprop; +		int phandle; + +		phandle = propval_cell_n(prop, cell); +		/* +		 * Some bindings use a cell value 0 or -1 to skip over optional +		 * entries when each index position has a specific definition. +		 */ +		if (phandle == 0 || phandle == -1) { +			/* Give up if this is an overlay with external references */ +			if (dti->dtsflags & DTSF_PLUGIN) +				break; + +			cellsize = 0; +			continue; +		} + +		/* If we have markers, verify the current cell is a phandle */ +		if (prop->val.markers) { +			struct marker *m = prop->val.markers; +			for_each_marker_of_type(m, REF_PHANDLE) { +				if (m->offset == (cell * sizeof(cell_t))) +					break; +			} +			if (!m) +				FAIL(c, dti, "Property '%s', cell %d is not a phandle reference in %s", +				     prop->name, cell, node->fullpath); +		} + +		provider_node = get_node_by_phandle(root, phandle); +		if (!provider_node) { +			FAIL(c, dti, "Could not get phandle node for %s:%s(cell %d)", +			     node->fullpath, prop->name, cell); +			break; +		} + +		cellprop = get_property(provider_node, provider->cell_name); +		if (cellprop) { +			cellsize = propval_cell(cellprop); +		} else if (provider->optional) { +			cellsize = 0; +		} else { +			FAIL(c, dti, "Missing property '%s' in node %s or bad phandle (referred from %s:%s[%d])", +			     provider->cell_name, +			     provider_node->fullpath, +			     node->fullpath, prop->name, cell); +			break; +		} + +		if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) { +			FAIL(c, dti, "%s property size (%d) too small for cell size %d in %s", +			     prop->name, prop->val.len, cellsize, node->fullpath); +		} +	} +} + +static void check_provider_cells_property(struct check *c, +					  struct dt_info *dti, +				          struct node *node) +{ +	struct provider *provider = c->data; +	struct property *prop; + +	prop = get_property(node, provider->prop_name); +	if (!prop) +		return; + +	check_property_phandle_args(c, dti, node, prop, provider); +} +#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \ +	static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \ +	WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references); + +WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true); +WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells"); + +static bool prop_is_gpio(struct property *prop) +{ +	char *str; + +	/* +	 * *-gpios and *-gpio can appear in property names, +	 * so skip over any false matches (only one known ATM) +	 */ +	if (strstr(prop->name, "nr-gpio")) +		return false; + +	str = strrchr(prop->name, '-'); +	if (str) +		str++; +	else +		str = prop->name; +	if (!(streq(str, "gpios") || streq(str, "gpio"))) +		return false; + +	return true; +} + +static void check_gpios_property(struct check *c, +					  struct dt_info *dti, +				          struct node *node) +{ +	struct property *prop; + +	/* Skip GPIO hog nodes which have 'gpios' property */ +	if (get_property(node, "gpio-hog")) +		return; + +	for_each_property(node, prop) { +		struct provider provider; + +		if (!prop_is_gpio(prop)) +			continue; + +		provider.prop_name = prop->name; +		provider.cell_name = "#gpio-cells"; +		provider.optional = false; +		check_property_phandle_args(c, dti, node, prop, &provider); +	} + +} +WARNING(gpios_property, check_gpios_property, NULL, &phandle_references); + +static void check_deprecated_gpio_property(struct check *c, +					   struct dt_info *dti, +				           struct node *node) +{ +	struct property *prop; + +	for_each_property(node, prop) { +		char *str; + +		if (!prop_is_gpio(prop)) +			continue; + +		str = strstr(prop->name, "gpio"); +		if (!streq(str, "gpio")) +			continue; + +		FAIL(c, dti, "'[*-]gpio' is deprecated, use '[*-]gpios' instead for %s:%s", +		     node->fullpath, prop->name); +	} + +} +CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL); + +static bool node_is_interrupt_provider(struct node *node) +{ +	struct property *prop; + +	prop = get_property(node, "interrupt-controller"); +	if (prop) +		return true; + +	prop = get_property(node, "interrupt-map"); +	if (prop) +		return true; + +	return false; +} +static void check_interrupts_property(struct check *c, +				      struct dt_info *dti, +				      struct node *node) +{ +	struct node *root = dti->dt; +	struct node *irq_node = NULL, *parent = node; +	struct property *irq_prop, *prop = NULL; +	int irq_cells, phandle; + +	irq_prop = get_property(node, "interrupts"); +	if (!irq_prop) +		return; + +	if (irq_prop->val.len % sizeof(cell_t)) +		FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", +		     irq_prop->name, irq_prop->val.len, sizeof(cell_t), +		     node->fullpath); + +	while (parent && !prop) { +		if (parent != node && node_is_interrupt_provider(parent)) { +			irq_node = parent; +			break; +		} + +		prop = get_property(parent, "interrupt-parent"); +		if (prop) { +			phandle = propval_cell(prop); +			/* Give up if this is an overlay with external references */ +			if ((phandle == 0 || phandle == -1) && +			    (dti->dtsflags & DTSF_PLUGIN)) +					return; + +			irq_node = get_node_by_phandle(root, phandle); +			if (!irq_node) { +				FAIL(c, dti, "Bad interrupt-parent phandle for %s", +				     node->fullpath); +				return; +			} +			if (!node_is_interrupt_provider(irq_node)) +				FAIL(c, dti, +				     "Missing interrupt-controller or interrupt-map property in %s", +				     irq_node->fullpath); + +			break; +		} + +		parent = parent->parent; +	} + +	if (!irq_node) { +		FAIL(c, dti, "Missing interrupt-parent for %s", node->fullpath); +		return; +	} + +	prop = get_property(irq_node, "#interrupt-cells"); +	if (!prop) { +		FAIL(c, dti, "Missing #interrupt-cells in interrupt-parent %s", +		     irq_node->fullpath); +		return; +	} + +	irq_cells = propval_cell(prop); +	if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) { +		FAIL(c, dti, +		     "interrupts size is (%d), expected multiple of %d in %s", +		     irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)), +		     node->fullpath); +	} +} +WARNING(interrupts_property, check_interrupts_property, &phandle_references); +  static struct check *check_table[] = {  	&duplicate_node_names, &duplicate_property_names,  	&node_name_chars, &node_name_format, &property_name_chars, @@ -749,6 +1382,9 @@ static struct check *check_table[] = {  	&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,  	&device_type_is_string, &model_is_string, &status_is_string, +	&label_is_string, + +	&compatible_is_string_list, &names_is_string_list,  	&property_name_chars_strict,  	&node_name_chars_strict, @@ -756,9 +1392,42 @@ 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, +	&avoid_unnecessary_addr_size,  	&obsolete_chosen_interrupt_controller, +	&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, + +	&clocks_property, +	&cooling_device_property, +	&dmas_property, +	&hwlocks_property, +	&interrupts_extended_property, +	&io_channels_property, +	&iommus_property, +	&mboxes_property, +	&msi_parent_property, +	&mux_controls_property, +	&phys_property, +	&power_domains_property, +	&pwms_property, +	&resets_property, +	&sound_dai_property, +	&thermal_sensors_property, + +	&deprecated_gpio_property, +	&gpios_property, +	&interrupts_property, + +	&alias_paths,  	&always_fail,  }; diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index aa32dc8cf81b..d6d68cdcaa8e 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -49,7 +49,7 @@ static int saw_hyphen; /* = 0 */  static unsigned long long last_val;  static char *last_name; /* = NULL */ -const struct { +static const struct {  	const char *pattern;  	int obase, width;  } guess_table[] = { @@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)  struct data data_append_integer(struct data d, uint64_t value, int bits)  {  	uint8_t value_8; -	uint16_t value_16; -	uint32_t value_32; -	uint64_t value_64; +	fdt16_t value_16; +	fdt32_t value_32; +	fdt64_t value_64;  	switch (bits) {  	case 8: @@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)  	}  } -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) +struct data data_append_re(struct data d, uint64_t address, uint64_t size)  { -	struct fdt_reserve_entry bere; +	struct fdt_reserve_entry re; -	bere.address = cpu_to_fdt64(re->address); -	bere.size = cpu_to_fdt64(re->size); +	re.address = cpu_to_fdt64(address); +	re.size = cpu_to_fdt64(size); -	return data_append_data(d, &bere, sizeof(bere)); +	return data_append_data(d, &re, sizeof(re));  }  struct data data_append_cell(struct data d, cell_t word) diff --git a/dtc-lexer.l b/dtc-lexer.l index 52bed7b74940..fd825ebba69c 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -62,12 +62,7 @@ static int dts_version = 1;  static void push_input_file(const char *filename);  static bool pop_input_file(void); -#ifdef __GNUC__ -static void lexical_error(const char *fmt, ...) -	__attribute__((format (printf, 1, 2))); -#else -static void lexical_error(const char *fmt, ...); -#endif +static void PRINTF(1, 2) lexical_error(const char *fmt, ...);  %} diff --git a/dtc-parser.y b/dtc-parser.y index ca3f5003427c..44af170abfea 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -166,7 +166,17 @@ devicetree:  		{  			$$ = merge_nodes($1, $3);  		} - +	| DT_REF nodedef +		{ +			/* +			 * We rely on the rule being always: +			 *   versioninfo plugindecl memreserves devicetree +			 * so $-1 is what we want (plugindecl) +			 */ +			if (!($<flags>-1 & DTSF_PLUGIN)) +				ERROR(&@2, "Label or path %s not found", $1); +			$$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); +		}  	| devicetree DT_LABEL DT_REF nodedef  		{  			struct node *target = get_node_by_ref($1, $3); @@ -182,10 +192,19 @@ devicetree:  		{  			struct node *target = get_node_by_ref($1, $2); -			if (target) +			if (target) {  				merge_nodes(target, $3); -			else -				ERROR(&@2, "Label or path %s not found", $2); +			} else { +				/* +				 * We rely on the rule being always: +				 *   versioninfo plugindecl memreserves devicetree +				 * so $-1 is what we want (plugindecl) +				 */ +				if ($<flags>-1 & DTSF_PLUGIN) +					add_orphan_node($1, $3, $2); +				else +					ERROR(&@2, "Label or path %s not found", $2); +			}  			$$ = $1;  		}  	| devicetree DT_DEL_NODE DT_REF ';' @@ -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 */ @@ -59,8 +59,6 @@ static void fill_fullpaths(struct node *tree, const char *prefix)  }  /* Usage related data. */ -#define FDT_VERSION(version)	_FDT_VERSION(version) -#define _FDT_VERSION(version)	#version  static const char usage_synopsis[] = "dtc [options] <input file>";  static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";  static struct option const usage_long_opts[] = { @@ -98,7 +96,7 @@ static const char * const usage_opts_help[] = {  	 "\t\tdts - device tree source text\n"  	 "\t\tdtb - device tree blob\n"  	 "\t\tasm - assembler source", -	"\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)", +	"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",  	"\n\tOutput dependency file",  	"\n\tMake space for <number> reserve map entries (for dtb and asm output)",  	"\n\tMake the blob at least <bytes> long (extra space)", @@ -138,7 +136,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)  static const char *guess_input_format(const char *fname, const char *fallback)  {  	struct stat statbuf; -	uint32_t magic; +	fdt32_t magic;  	FILE *f;  	if (stat(fname, &statbuf) != 0) @@ -159,8 +157,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)  	}  	fclose(f); -	magic = fdt32_to_cpu(magic); -	if (magic == FDT_MAGIC) +	if (fdt32_to_cpu(magic) == FDT_MAGIC)  		return "dtb";  	return guess_type_by_name(fname, fallback); @@ -320,13 +317,14 @@ int main(int argc, char *argv[])  		dti->boot_cpuid_phys = cmdline_boot_cpuid;  	fill_fullpaths(dti->dt, ""); -	process_checks(force, dti);  	/* on a plugin, generate by default */  	if (dti->dtsflags & DTSF_PLUGIN) {  		generate_fixups = 1;  	} +	process_checks(force, dti); +  	if (auto_label_aliases)  		generate_label_tree(dti, "aliases", false); @@ -1,5 +1,5 @@ -#ifndef _DTC_H -#define _DTC_H +#ifndef DTC_H +#define DTC_H  /*   * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005. @@ -31,6 +31,7 @@  #include <ctype.h>  #include <errno.h>  #include <unistd.h> +#include <inttypes.h>  #include <libfdt_env.h>  #include <fdt.h> @@ -43,7 +44,6 @@  #define debug(...)  #endif -  #define DEFAULT_FDT_VERSION	17  /* @@ -67,7 +67,8 @@ typedef uint32_t cell_t;  #define streq(a, b)	(strcmp((a), (b)) == 0) -#define strneq(a, b, n)	(strncmp((a), (b), (n)) == 0) +#define strstarts(s, prefix)	(strncmp((s), (prefix), strlen(prefix)) == 0) +#define strprefixeq(a, n, b)	(strlen(b) == (n) && (memcmp(a, b, n) == 0))  #define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1)) @@ -114,7 +115,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,  struct data data_merge(struct data d1, struct data d2);  struct data data_append_cell(struct data d, cell_t word);  struct data data_append_integer(struct data d, uint64_t word, int bits); -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); +struct data data_append_re(struct data d, uint64_t address, uint64_t size);  struct data data_append_addr(struct data d, uint64_t addr);  struct data data_append_byte(struct data d, uint8_t byte);  struct data data_append_zeroes(struct data d, int len); @@ -136,6 +137,10 @@ struct label {  	struct label *next;  }; +struct bus_type { +	const char *name; +}; +  struct property {  	bool deleted;  	char *name; @@ -162,6 +167,7 @@ struct node {  	int addr_cells, size_cells;  	struct label *labels; +	const struct bus_type *bus;  };  #define for_each_label_withdel(l0, l) \ @@ -198,6 +204,7 @@ struct node *build_node_delete(void);  struct node *name_node(struct node *node, char *name);  struct node *chain_node(struct node *first, struct node *list);  struct node *merge_nodes(struct node *old_node, struct node *new_node); +struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);  void add_property(struct node *node, struct property *prop);  void delete_property_by_name(struct node *node, char *name); @@ -211,6 +218,7 @@ void append_to_property(struct node *node,  const char *get_unitname(struct node *node);  struct property *get_property(struct node *node, const char *propname);  cell_t propval_cell(struct property *prop); +cell_t propval_cell_n(struct property *prop, int n);  struct property *get_property_by_label(struct node *tree, const char *label,  				       struct node **node);  struct marker *get_marker_label(struct node *tree, const char *label, @@ -227,7 +235,7 @@ uint32_t guess_boot_cpuid(struct node *tree);  /* Boot info (tree plus memreserve information */  struct reserve_info { -	struct fdt_reserve_entry re; +	uint64_t address, size;  	struct reserve_info *next; @@ -282,4 +290,4 @@ struct dt_info *dt_from_source(const char *f);  struct dt_info *dt_from_fs(const char *dirname); -#endif /* _DTC_H */ +#endif /* DTC_H */ diff --git a/fdtdump.c b/fdtdump.c index 194e9d62c6c5..fa3b56130e0d 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -20,7 +20,7 @@  #define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))  #define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a)))) -#define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4))) +#define GET_CELL(p)	(p += 4, *((const fdt32_t *)(p-4)))  static const char *tagname(uint32_t tag)  { @@ -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 @@ -54,6 +54,37 @@ static void report_error(const char *where, int err)  }  /** + * Shows a list of cells in the requested format + * + * @param disp		Display information / options + * @param data		Data to display + * @param len		Maximum length of buffer + * @param size		Data size to use for display (e.g. 4 for 32-bit) + * @return 0 if ok, -1 on error + */ +static int show_cell_list(struct display_info *disp, const char *data, int len, +			  int size) +{ +	const uint8_t *p = (const uint8_t *)data; +	char fmt[3]; +	int value; +	int i; + +	fmt[0] = '%'; +	fmt[1] = disp->type ? disp->type : 'd'; +	fmt[2] = '\0'; +	for (i = 0; i < len; i += size, p += size) { +		if (i) +			printf(" "); +		value = size == 4 ? fdt32_to_cpu(*(const fdt32_t *)p) : +			size == 2 ? (*p << 8) | p[1] : *p; +		printf(fmt, value); +	} + +	return 0; +} + +/**   * Displays data of a given length according to selected options   *   * If a specific data type is provided in disp, then this is used. Otherwise @@ -66,12 +97,9 @@ static void report_error(const char *where, int err)   */  static int show_data(struct display_info *disp, const char *data, int len)  { -	int i, size; -	const uint8_t *p = (const uint8_t *)data; +	int size;  	const char *s; -	int value;  	int is_string; -	char fmt[3];  	/* no data, don't print */  	if (len == 0) @@ -99,17 +127,8 @@ static int show_data(struct display_info *disp, const char *data, int len)  				"selected data size\n");  		return -1;  	} -	fmt[0] = '%'; -	fmt[1] = disp->type ? disp->type : 'd'; -	fmt[2] = '\0'; -	for (i = 0; i < len; i += size, p += size) { -		if (i) -			printf(" "); -		value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) : -			size == 2 ? (*p << 8) | p[1] : *p; -		printf(fmt, value); -	} -	return 0; + +	return show_cell_list(disp, data, len, size);  }  /** @@ -245,7 +264,7 @@ static int show_data_for_item(const void *blob, struct display_info *disp,   * @param filename	Filename of blob file   * @param arg		List of arguments to process   * @param arg_count	Number of arguments - * @param return 0 if ok, -ve on error + * @return 0 if ok, -ve on error   */  static int do_fdtget(struct display_info *disp, const char *filename,  		     char **arg, int arg_count, int args_per_step) diff --git a/fdtoverlay.c b/fdtoverlay.c new file mode 100644 index 000000000000..62a942d80dda --- /dev/null +++ b/fdtoverlay.c @@ -0,0 +1,175 @@ +/* + * 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 <inttypes.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; +	} +	if (fdt_totalsize(blob) > blob_len) { +		fprintf(stderr, + "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n", +			(unsigned long)blob_len, fdt_totalsize(blob)); +		goto out_err; +	} +	ret = 0; + +	/* allocate blob pointer array */ +	ovblob = malloc(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(ovblob); +	} +	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; +} @@ -67,7 +67,7 @@ static void report_error(const char *name, int namelen, int err)   * @param arg		List of arguments from command line   * @param arg_count	Number of arguments (may be 0)   * @param valuep	Returns buffer containing value - * @param *value_len	Returns length of value encoded + * @param value_len	Returns length of value encoded   */  static int encode_value(struct display_info *disp, char **arg, int arg_count,  			char **valuep, int *value_len) @@ -107,7 +107,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,  			if (disp->verbose)  				fprintf(stderr, "\tstring: '%s'\n", ptr);  		} else { -			int *iptr = (int *)ptr; +			fdt32_t *iptr = (fdt32_t *)ptr;  			sscanf(*arg, fmt, &ival);  			if (len == 4)  				*iptr = cpu_to_fdt32(ival); @@ -130,7 +130,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,  #define ALIGN(x)		(((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1)) -static char *_realloc_fdt(char *fdt, int delta) +static char *realloc_fdt(char *fdt, int delta)  {  	int new_sz = fdt_totalsize(fdt) + delta;  	fdt = xrealloc(fdt, new_sz); @@ -144,7 +144,7 @@ static char *realloc_node(char *fdt, const char *name)  	/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */  	delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)  			+ FDT_TAGSIZE; -	return _realloc_fdt(fdt, delta); +	return realloc_fdt(fdt, delta);  }  static char *realloc_property(char *fdt, int nodeoffset, @@ -161,7 +161,7 @@ static char *realloc_property(char *fdt, int nodeoffset,  		/* actual value in off_struct */  		delta += ALIGN(newlen) - ALIGN(oldlen); -	return _realloc_fdt(fdt, delta); +	return realloc_fdt(fdt, delta);  }  static int store_key_value(char **blob, const char *node_name, diff --git a/flattree.c b/flattree.c index ebac548b3fa8..8d268fb785db 100644 --- a/flattree.c +++ b/flattree.c @@ -49,7 +49,7 @@ static struct version_info {  struct emitter {  	void (*cell)(void *, cell_t); -	void (*string)(void *, char *, int); +	void (*string)(void *, const char *, int);  	void (*align)(void *, int);  	void (*data)(void *, struct data);  	void (*beginnode)(void *, struct label *labels); @@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)  	*dtbuf = data_append_cell(*dtbuf, val);  } -static void bin_emit_string(void *e, char *str, int len) +static void bin_emit_string(void *e, const char *str, int len)  {  	struct data *dtbuf = e; @@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)  		(val >> 8) & 0xff, val & 0xff);  } -static void asm_emit_string(void *e, char *str, int len) +static void asm_emit_string(void *e, const char *str, int len)  {  	FILE *f = e; -	char c = 0; -	if (len != 0) { -		/* XXX: ewww */ -		c = str[len]; -		str[len] = '\0'; -	} - -	fprintf(f, "\t.string\t\"%s\"\n", str); - -	if (len != 0) { -		str[len] = c; -	} +	if (len != 0) +		fprintf(f, "\t.string\t\"%.*s\"\n", len, str); +	else +		fprintf(f, "\t.string\t\"%s\"\n", str);  }  static void asm_emit_align(void *e, int a) @@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d)  		emit_offset_label(f, m->ref, m->offset);  	while ((d.len - off) >= sizeof(uint32_t)) { -		asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off)))); +		asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));  		off += sizeof(uint32_t);  	} @@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,  {  	struct reserve_info *re;  	struct data d = empty_data; -	static struct fdt_reserve_entry null_re = {0,0};  	int    j;  	for (re = reservelist; re; re = re->next) { -		d = data_append_re(d, &re->re); +		d = data_append_re(d, re->address, re->size);  	}  	/*  	 * Add additional reserved slots if the user asked for them.  	 */  	for (j = 0; j < reservenum; j++) { -		d = data_append_re(d, &null_re); +		d = data_append_re(d, 0, 0);  	}  	return d; @@ -544,11 +535,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)  			fprintf(f, "\t.globl\t%s\n", l->label);  			fprintf(f, "%s:\n", l->label);  		} -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));  		ASM_EMIT_BELONG(f, "0x%08x", -				(unsigned int)(re->re.address & 0xffffffff)); -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff)); +				(unsigned int)(re->address & 0xffffffff)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));  	}  	for (i = 0; i < reservenum; i++) {  		fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); @@ -609,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)  static uint32_t flat_read_word(struct inbuf *inb)  { -	uint32_t val; +	fdt32_t val;  	assert(((inb->ptr - inb->base) % sizeof(val)) == 0); @@ -718,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)  	 * First pass, count entries.  	 */  	while (1) { +		uint64_t address, size; +  		flat_read_chunk(inb, &re, sizeof(re)); -		re.address  = fdt64_to_cpu(re.address); -		re.size = fdt64_to_cpu(re.size); -		if (re.size == 0) +		address  = fdt64_to_cpu(re.address); +		size = fdt64_to_cpu(re.size); +		if (size == 0)  			break; -		new = build_reserve_entry(re.address, re.size); +		new = build_reserve_entry(address, size);  		reservelist = add_reserve_entry(reservelist, new);  	} @@ -738,7 +731,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)  	plen = strlen(ppath); -	if (!strneq(ppath, cpath, plen)) +	if (!strstarts(cpath, ppath))  		die("Path \"%s\" is not valid as a child of \"%s\"\n",  		    cpath, ppath); @@ -817,6 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,  struct dt_info *dt_from_blob(const char *fname)  {  	FILE *f; +	fdt32_t magic_buf, totalsize_buf;  	uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;  	uint32_t off_dt, off_str, off_mem_rsvmap;  	int rc; @@ -833,7 +827,7 @@ struct dt_info *dt_from_blob(const char *fname)  	f = srcfile_relative_open(fname, NULL); -	rc = fread(&magic, sizeof(magic), 1, f); +	rc = fread(&magic_buf, sizeof(magic_buf), 1, f);  	if (ferror(f))  		die("Error reading DT blob magic number: %s\n",  		    strerror(errno)); @@ -844,11 +838,11 @@ struct dt_info *dt_from_blob(const char *fname)  			die("Mysterious short read reading magic number\n");  	} -	magic = fdt32_to_cpu(magic); +	magic = fdt32_to_cpu(magic_buf);  	if (magic != FDT_MAGIC)  		die("Blob has incorrect magic number\n"); -	rc = fread(&totalsize, sizeof(totalsize), 1, f); +	rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);  	if (ferror(f))  		die("Error reading DT blob size: %s\n", strerror(errno));  	if (rc < 1) { @@ -858,7 +852,7 @@ struct dt_info *dt_from_blob(const char *fname)  			die("Mysterious short read reading blob size\n");  	} -	totalsize = fdt32_to_cpu(totalsize); +	totalsize = fdt32_to_cpu(totalsize_buf);  	if (totalsize < FDT_V1_SIZE)  		die("DT blob size (%d) is too small\n", totalsize); diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 22286a1aaeaf..fd132367362e 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -88,7 +88,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)  		    || ((offset + len) > fdt_size_dt_struct(fdt)))  			return NULL; -	return _fdt_offset_ptr(fdt, offset); +	return fdt_offset_ptr_(fdt, offset);  }  uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) @@ -141,7 +141,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)  	return tag;  } -int _fdt_check_node_offset(const void *fdt, int offset) +int fdt_check_node_offset_(const void *fdt, int offset)  {  	if ((offset < 0) || (offset % FDT_TAGSIZE)  	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) @@ -150,7 +150,7 @@ int _fdt_check_node_offset(const void *fdt, int offset)  	return offset;  } -int _fdt_check_prop_offset(const void *fdt, int offset) +int fdt_check_prop_offset_(const void *fdt, int offset)  {  	if ((offset < 0) || (offset % FDT_TAGSIZE)  	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) @@ -165,7 +165,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth)  	uint32_t tag;  	if (offset >= 0) -		if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) +		if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)  			return nextoffset;  	do { @@ -227,7 +227,7 @@ int fdt_next_subnode(const void *fdt, int offset)  	return offset;  } -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)  {  	int len = strlen(s) + 1;  	const char *last = strtab + tabsize - len; diff --git a/libfdt/fdt.h b/libfdt/fdt.h index 526aedb51556..74961f9026d1 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -1,5 +1,5 @@ -#ifndef _FDT_H -#define _FDT_H +#ifndef FDT_H +#define FDT_H  /*   * libfdt - Flat Device Tree manipulation   * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -108,4 +108,4 @@ struct fdt_property {  #define FDT_V16_SIZE	FDT_V3_SIZE  #define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(fdt32_t)) -#endif /* _FDT_H */ +#endif /* FDT_H */ diff --git a/libfdt/fdt_empty_tree.c b/libfdt/fdt_empty_tree.c index f72d13b1d19c..f2ae9b77c285 100644 --- a/libfdt/fdt_empty_tree.c +++ b/libfdt/fdt_empty_tree.c @@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)  	return fdt_open_into(buf, buf, bufsize);  } - diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 56cb70ed4445..bd81241e6658 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -21,14 +21,14 @@   */  static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)  { -	const uint32_t *val; +	const fdt32_t *val;  	int len;  	val = fdt_getprop(fdto, fragment, "target", &len);  	if (!val)  		return 0; -	if ((len != sizeof(*val)) || (*val == (uint32_t)-1)) +	if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))  		return (uint32_t)-1;  	return fdt32_to_cpu(*val); @@ -39,6 +39,7 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)   * @fdt: Base device tree blob   * @fdto: Device tree overlay blob   * @fragment: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL)   *   * overlay_get_target() retrieves the target offset in the base   * device tree of a fragment, no matter how the actual targetting is @@ -49,37 +50,47 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)   *      Negative error code on error   */  static int overlay_get_target(const void *fdt, const void *fdto, -			      int fragment) +			      int fragment, char const **pathp)  {  	uint32_t phandle; -	const char *path; -	int path_len; +	const char *path = NULL; +	int path_len = 0, ret;  	/* Try first to do a phandle based lookup */  	phandle = overlay_get_target_phandle(fdto, fragment);  	if (phandle == (uint32_t)-1)  		return -FDT_ERR_BADPHANDLE; -	if (phandle) -		return fdt_node_offset_by_phandle(fdt, phandle); +	/* no phandle, try path */ +	if (!phandle) { +		/* And then a path based lookup */ +		path = fdt_getprop(fdto, fragment, "target-path", &path_len); +		if (path) +			ret = fdt_path_offset(fdt, path); +		else +			ret = path_len; +	} else +		ret = fdt_node_offset_by_phandle(fdt, phandle); -	/* And then a path based lookup */ -	path = fdt_getprop(fdto, fragment, "target-path", &path_len); -	if (!path) { -		/* -		 * If we haven't found either a target or a -		 * target-path property in a node that contains a -		 * __overlay__ subnode (we wouldn't be called -		 * otherwise), consider it a improperly written -		 * overlay -		 */ -		if (path_len == -FDT_ERR_NOTFOUND) -			return -FDT_ERR_BADOVERLAY; +	/* +	* If we haven't found either a target or a +	* target-path property in a node that contains a +	* __overlay__ subnode (we wouldn't be called +	* otherwise), consider it a improperly written +	* overlay +	*/ +	if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) +		ret = -FDT_ERR_BADOVERLAY; + +	/* return on error */ +	if (ret < 0) +		return ret; -		return path_len; -	} +	/* return pointer to path (if available) */ +	if (pathp) +		*pathp = path ? path : NULL; -	return fdt_path_offset(fdt, path); +	return ret;  }  /** @@ -99,7 +110,7 @@ static int overlay_get_target(const void *fdt, const void *fdto,  static int overlay_phandle_add_offset(void *fdt, int node,  				      const char *name, uint32_t delta)  { -	const uint32_t *val; +	const fdt32_t *val;  	uint32_t adj_val;  	int len; @@ -210,7 +221,7 @@ static int overlay_update_local_node_references(void *fdto,  	int ret;  	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { -		const uint32_t *fixup_val; +		const fdt32_t *fixup_val;  		const char *tree_val;  		const char *name;  		int fixup_len; @@ -234,7 +245,8 @@ static int overlay_update_local_node_references(void *fdto,  		}  		for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { -			uint32_t adj_val, poffset; +			fdt32_t adj_val; +			uint32_t poffset;  			poffset = fdt32_to_cpu(fixup_val[i]); @@ -246,9 +258,7 @@ static int overlay_update_local_node_references(void *fdto,  			 */  			memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); -			adj_val = fdt32_to_cpu(adj_val); -			adj_val += delta; -			adj_val = cpu_to_fdt32(adj_val); +			adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);  			ret = fdt_setprop_inplace_namelen_partial(fdto,  								  tree_node, @@ -272,7 +282,7 @@ static int overlay_update_local_node_references(void *fdto,  		tree_child = fdt_subnode_offset(fdto, tree_node,  						fixup_child_name); -		if (ret == -FDT_ERR_NOTFOUND) +		if (tree_child == -FDT_ERR_NOTFOUND)  			return -FDT_ERR_BADOVERLAY;  		if (tree_child < 0)  			return tree_child; @@ -356,6 +366,7 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,  {  	const char *symbol_path;  	uint32_t phandle; +	fdt32_t phandle_prop;  	int symbol_off, fixup_off;  	int prop_len; @@ -381,10 +392,11 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,  	if (fixup_off < 0)  		return fixup_off; -	phandle = cpu_to_fdt32(phandle); +	phandle_prop = cpu_to_fdt32(phandle);  	return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,  						   name, name_len, poffset, -						   &phandle, sizeof(phandle)); +						   &phandle_prop, +						   sizeof(phandle_prop));  };  /** @@ -589,7 +601,7 @@ static int overlay_apply_node(void *fdt, int target,   *   * overlay_merge() merges an overlay into its base device tree.   * - * This is the final step in the device tree overlay application + * This is the next to last step in the device tree overlay application   * process, when all the phandles have been adjusted and resolved and   * you just have to merge overlay into the base device tree.   * @@ -617,7 +629,7 @@ static int overlay_merge(void *fdt, void *fdto)  		if (overlay < 0)  			return overlay; -		target = overlay_get_target(fdt, fdto, fragment); +		target = overlay_get_target(fdt, fdto, fragment, NULL);  		if (target < 0)  			return target; @@ -629,6 +641,175 @@ static int overlay_merge(void *fdt, void *fdto)  	return 0;  } +static int get_path_len(const void *fdt, int nodeoffset) +{ +	int len = 0, namelen; +	const char *name; + +	FDT_CHECK_HEADER(fdt); + +	for (;;) { +		name = fdt_get_name(fdt, nodeoffset, &namelen); +		if (!name) +			return namelen; + +		/* root? we're done */ +		if (namelen == 0) +			break; + +		nodeoffset = fdt_parent_offset(fdt, nodeoffset); +		if (nodeoffset < 0) +			return nodeoffset; +		len += namelen + 1; +	} + +	/* in case of root pretend it's "/" */ +	if (len == 0) +		len++; +	return len; +} + +/** + * overlay_symbol_update - Update the symbols of base tree after a merge + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_symbol_update() updates the symbols of the base tree with the + * symbols of the applied overlay + * + * This is the last step in the device tree overlay application + * process, allowing the reference of overlay symbols by subsequent + * overlay operations. + * + * returns: + *      0 on success + *      Negative error code on failure + */ +static int overlay_symbol_update(void *fdt, void *fdto) +{ +	int root_sym, ov_sym, prop, path_len, fragment, target; +	int len, frag_name_len, ret, rel_path_len; +	const char *s, *e; +	const char *path; +	const char *name; +	const char *frag_name; +	const char *rel_path; +	const char *target_path; +	char *buf; +	void *p; + +	ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + +	/* if no overlay symbols exist no problem */ +	if (ov_sym < 0) +		return 0; + +	root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + +	/* it no root symbols exist we should create them */ +	if (root_sym == -FDT_ERR_NOTFOUND) +		root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); + +	/* any error is fatal now */ +	if (root_sym < 0) +		return root_sym; + +	/* iterate over each overlay symbol */ +	fdt_for_each_property_offset(prop, fdto, ov_sym) { +		path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); +		if (!path) +			return path_len; + +		/* verify it's a string property (terminated by a single \0) */ +		if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) +			return -FDT_ERR_BADVALUE; + +		/* keep end marker to avoid strlen() */ +		e = path + path_len; + +		/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */ + +		if (*path != '/') +			return -FDT_ERR_BADVALUE; + +		/* get fragment name first */ +		s = strchr(path + 1, '/'); +		if (!s) +			return -FDT_ERR_BADOVERLAY; + +		frag_name = path + 1; +		frag_name_len = s - path - 1; + +		/* verify format; safe since "s" lies in \0 terminated prop */ +		len = sizeof("/__overlay__/") - 1; +		if ((e - s) < len || memcmp(s, "/__overlay__/", len)) +			return -FDT_ERR_BADOVERLAY; + +		rel_path = s + len; +		rel_path_len = e - rel_path; + +		/* find the fragment index in which the symbol lies */ +		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, +					       frag_name_len); +		/* not found? */ +		if (ret < 0) +			return -FDT_ERR_BADOVERLAY; +		fragment = ret; + +		/* an __overlay__ subnode must exist */ +		ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); +		if (ret < 0) +			return -FDT_ERR_BADOVERLAY; + +		/* get the target of the fragment */ +		ret = overlay_get_target(fdt, fdto, fragment, &target_path); +		if (ret < 0) +			return ret; +		target = ret; + +		/* if we have a target path use */ +		if (!target_path) { +			ret = get_path_len(fdt, target); +			if (ret < 0) +				return ret; +			len = ret; +		} else { +			len = strlen(target_path); +		} + +		ret = fdt_setprop_placeholder(fdt, root_sym, name, +				len + (len > 1) + rel_path_len + 1, &p); +		if (ret < 0) +			return ret; + +		if (!target_path) { +			/* again in case setprop_placeholder changed it */ +			ret = overlay_get_target(fdt, fdto, fragment, &target_path); +			if (ret < 0) +				return ret; +			target = ret; +		} + +		buf = p; +		if (len > 1) { /* target is not root */ +			if (!target_path) { +				ret = fdt_get_path(fdt, target, buf, len + 1); +				if (ret < 0) +					return ret; +			} else +				memcpy(buf, target_path, len + 1); + +		} else +			len--; + +		buf[len] = '/'; +		memcpy(buf + len + 1, rel_path, rel_path_len); +		buf[len + 1 + rel_path_len] = '\0'; +	} + +	return 0; +} +  int fdt_overlay_apply(void *fdt, void *fdto)  {  	uint32_t delta = fdt_get_max_phandle(fdt); @@ -653,6 +834,10 @@ int fdt_overlay_apply(void *fdt, void *fdto)  	if (ret)  		goto err; +	ret = overlay_symbol_update(fdt, fdto); +	if (ret) +		goto err; +  	/*  	 * The overlay has been damaged, erase its magic.  	 */ diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 3d00d2eee0e3..ce17814b2b20 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -55,12 +55,12 @@  #include "libfdt_internal.h" -static int _fdt_nodename_eq(const void *fdt, int offset, +static int fdt_nodename_eq_(const void *fdt, int offset,  			    const char *s, int len)  {  	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); -	if (! p) +	if (!p)  		/* short match */  		return 0; @@ -80,7 +80,7 @@ const char *fdt_string(const void *fdt, int stroffset)  	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;  } -static int _fdt_string_eq(const void *fdt, int stroffset, +static int fdt_string_eq_(const void *fdt, int stroffset,  			  const char *s, int len)  {  	const char *p = fdt_string(fdt, stroffset); @@ -117,8 +117,8 @@ uint32_t fdt_get_max_phandle(const void *fdt)  int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)  {  	FDT_CHECK_HEADER(fdt); -	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); -	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); +	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); +	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);  	return 0;  } @@ -126,12 +126,12 @@ int fdt_num_mem_rsv(const void *fdt)  {  	int i = 0; -	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) +	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)  		i++;  	return i;  } -static int _nextprop(const void *fdt, int offset) +static int nextprop_(const void *fdt, int offset)  {  	uint32_t tag;  	int nextoffset; @@ -166,7 +166,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,  	     (offset >= 0) && (depth >= 0);  	     offset = fdt_next_node(fdt, offset, &depth))  		if ((depth == 1) -		    && _fdt_nodename_eq(fdt, offset, name, namelen)) +		    && fdt_nodename_eq_(fdt, offset, name, namelen))  			return offset;  	if (depth < 0) @@ -232,11 +232,11 @@ int fdt_path_offset(const void *fdt, const char *path)  const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)  { -	const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); +	const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);  	int err;  	if (((err = fdt_check_header(fdt)) != 0) -	    || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) +	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))  			goto fail;  	if (len) @@ -254,18 +254,18 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)  {  	int offset; -	if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) +	if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)  		return offset; -	return _nextprop(fdt, offset); +	return nextprop_(fdt, offset);  }  int fdt_next_property_offset(const void *fdt, int offset)  { -	if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) +	if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)  		return offset; -	return _nextprop(fdt, offset); +	return nextprop_(fdt, offset);  }  const struct fdt_property *fdt_get_property_by_offset(const void *fdt, @@ -275,13 +275,13 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,  	int err;  	const struct fdt_property *prop; -	if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { +	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {  		if (lenp)  			*lenp = err;  		return NULL;  	} -	prop = _fdt_offset_ptr(fdt, offset); +	prop = fdt_offset_ptr_(fdt, offset);  	if (lenp)  		*lenp = fdt32_to_cpu(prop->len); @@ -303,7 +303,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,  			offset = -FDT_ERR_INTERNAL;  			break;  		} -		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), +		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),  				   name, namelen))  			return prop;  	} @@ -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; diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 3fd5847377c9..9b829051e444 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -55,8 +55,8 @@  #include "libfdt_internal.h" -static int _fdt_blocks_misordered(const void *fdt, -			      int mem_rsv_size, int struct_size) +static int fdt_blocks_misordered_(const void *fdt, +				  int mem_rsv_size, int struct_size)  {  	return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))  		|| (fdt_off_dt_struct(fdt) < @@ -67,13 +67,13 @@ static int _fdt_blocks_misordered(const void *fdt,  		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));  } -static int _fdt_rw_check_header(void *fdt) +static int fdt_rw_check_header_(void *fdt)  {  	FDT_CHECK_HEADER(fdt);  	if (fdt_version(fdt) < 17)  		return -FDT_ERR_BADVERSION; -	if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), +	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),  				   fdt_size_dt_struct(fdt)))  		return -FDT_ERR_BADLAYOUT;  	if (fdt_version(fdt) > 17) @@ -84,20 +84,20 @@ static int _fdt_rw_check_header(void *fdt)  #define FDT_RW_CHECK_HEADER(fdt) \  	{ \ -		int __err; \ -		if ((__err = _fdt_rw_check_header(fdt)) != 0) \ -			return __err; \ +		int err_; \ +		if ((err_ = fdt_rw_check_header_(fdt)) != 0) \ +			return err_; \  	} -static inline int _fdt_data_size(void *fdt) +static inline int fdt_data_size_(void *fdt)  {  	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);  } -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) +static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)  {  	char *p = splicepoint; -	char *end = (char *)fdt + _fdt_data_size(fdt); +	char *end = (char *)fdt + fdt_data_size_(fdt);  	if (((p + oldlen) < p) || ((p + oldlen) > end))  		return -FDT_ERR_BADOFFSET; @@ -109,12 +109,12 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)  	return 0;  } -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, +static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,  			       int oldn, int newn)  {  	int delta = (newn - oldn) * sizeof(*p);  	int err; -	err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); +	err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));  	if (err)  		return err;  	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); @@ -122,13 +122,13 @@ static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,  	return 0;  } -static int _fdt_splice_struct(void *fdt, void *p, +static int fdt_splice_struct_(void *fdt, void *p,  			      int oldlen, int newlen)  {  	int delta = newlen - oldlen;  	int err; -	if ((err = _fdt_splice(fdt, p, oldlen, newlen))) +	if ((err = fdt_splice_(fdt, p, oldlen, newlen)))  		return err;  	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); @@ -136,20 +136,20 @@ static int _fdt_splice_struct(void *fdt, void *p,  	return 0;  } -static int _fdt_splice_string(void *fdt, int newlen) +static int fdt_splice_string_(void *fdt, int newlen)  {  	void *p = (char *)fdt  		+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);  	int err; -	if ((err = _fdt_splice(fdt, p, 0, newlen))) +	if ((err = fdt_splice_(fdt, p, 0, newlen)))  		return err;  	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);  	return 0;  } -static int _fdt_find_add_string(void *fdt, const char *s) +static int fdt_find_add_string_(void *fdt, const char *s)  {  	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);  	const char *p; @@ -157,13 +157,13 @@ static int _fdt_find_add_string(void *fdt, const char *s)  	int len = strlen(s) + 1;  	int err; -	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); +	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);  	if (p)  		/* found it */  		return (p - strtab);  	new = strtab + fdt_size_dt_strings(fdt); -	err = _fdt_splice_string(fdt, len); +	err = fdt_splice_string_(fdt, len);  	if (err)  		return err; @@ -178,8 +178,8 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)  	FDT_RW_CHECK_HEADER(fdt); -	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); -	err = _fdt_splice_mem_rsv(fdt, re, 0, 1); +	re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); +	err = fdt_splice_mem_rsv_(fdt, re, 0, 1);  	if (err)  		return err; @@ -190,27 +190,27 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)  int fdt_del_mem_rsv(void *fdt, int n)  { -	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); +	struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);  	FDT_RW_CHECK_HEADER(fdt);  	if (n >= fdt_num_mem_rsv(fdt))  		return -FDT_ERR_NOTFOUND; -	return _fdt_splice_mem_rsv(fdt, re, 1, 0); +	return fdt_splice_mem_rsv_(fdt, re, 1, 0);  } -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, +static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,  				int len, struct fdt_property **prop)  {  	int oldlen;  	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), +	if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),  				      FDT_TAGALIGN(len))))  		return err; @@ -218,7 +218,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,  	return 0;  } -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, +static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,  			     int len, struct fdt_property **prop)  {  	int proplen; @@ -226,17 +226,17 @@ static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,  	int namestroff;  	int err; -	if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) +	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)  		return nextoffset; -	namestroff = _fdt_find_add_string(fdt, name); +	namestroff = fdt_find_add_string_(fdt, name);  	if (namestroff < 0)  		return namestroff; -	*prop = _fdt_offset_ptr_w(fdt, nextoffset); +	*prop = fdt_offset_ptr_w_(fdt, nextoffset);  	proplen = sizeof(**prop) + FDT_TAGALIGN(len); -	err = _fdt_splice_struct(fdt, *prop, 0, proplen); +	err = fdt_splice_struct_(fdt, *prop, 0, proplen);  	if (err)  		return err; @@ -260,7 +260,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)  	newlen = strlen(name); -	err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), +	err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),  				 FDT_TAGALIGN(newlen+1));  	if (err)  		return err; @@ -269,22 +269,36 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)  	return 0;  } -int fdt_setprop(void *fdt, int nodeoffset, const char *name, -		const void *val, int len) +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, +			    int len, void **prop_data)  {  	struct fdt_property *prop;  	int err;  	FDT_RW_CHECK_HEADER(fdt); -	err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); +	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);  	if (err == -FDT_ERR_NOTFOUND) -		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); +		err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); +	if (err) +		return err; + +	*prop_data = prop->data; +	return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, +		const void *val, int len) +{ +	void *prop_data; +	int err; + +	err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);  	if (err)  		return err;  	if (len) -		memcpy(prop->data, val, len); +		memcpy(prop_data, val, len);  	return 0;  } @@ -299,7 +313,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,  	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);  	if (prop) {  		newlen = len + oldlen; -		err = _fdt_splice_struct(fdt, prop->data, +		err = fdt_splice_struct_(fdt, prop->data,  					 FDT_TAGALIGN(oldlen),  					 FDT_TAGALIGN(newlen));  		if (err) @@ -307,7 +321,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,  		prop->len = cpu_to_fdt32(newlen);  		memcpy(prop->data + oldlen, val, len);  	} else { -		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); +		err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);  		if (err)  			return err;  		memcpy(prop->data, val, len); @@ -323,11 +337,11 @@ 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); -	return _fdt_splice_struct(fdt, prop, proplen, 0); +	return fdt_splice_struct_(fdt, prop, proplen, 0);  }  int fdt_add_subnode_namelen(void *fdt, int parentoffset, @@ -355,10 +369,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,  		tag = fdt_next_tag(fdt, offset, &nextoffset);  	} while ((tag == FDT_PROP) || (tag == FDT_NOP)); -	nh = _fdt_offset_ptr_w(fdt, offset); +	nh = fdt_offset_ptr_w_(fdt, offset);  	nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; -	err = _fdt_splice_struct(fdt, nh, 0, nodelen); +	err = fdt_splice_struct_(fdt, nh, 0, nodelen);  	if (err)  		return err; @@ -382,15 +396,15 @@ int fdt_del_node(void *fdt, int nodeoffset)  	FDT_RW_CHECK_HEADER(fdt); -	endoffset = _fdt_node_end_offset(fdt, nodeoffset); +	endoffset = fdt_node_end_offset_(fdt, nodeoffset);  	if (endoffset < 0)  		return endoffset; -	return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), +	return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),  				  endoffset - nodeoffset, 0);  } -static void _fdt_packblocks(const char *old, char *new, +static void fdt_packblocks_(const char *old, char *new,  			    int mem_rsv_size, int struct_size)  {  	int mem_rsv_off, struct_off, strings_off; @@ -436,7 +450,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)  			return struct_size;  	} -	if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { +	if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {  		/* no further work necessary */  		err = fdt_move(fdt, buf, bufsize);  		if (err) @@ -464,7 +478,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)  			return -FDT_ERR_NOSPACE;  	} -	_fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); +	fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);  	memmove(buf, tmp, newsize);  	fdt_set_magic(buf, FDT_MAGIC); @@ -484,8 +498,8 @@ int fdt_pack(void *fdt)  	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)  		* sizeof(struct fdt_reserve_entry); -	_fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); -	fdt_set_totalsize(fdt, _fdt_data_size(fdt)); +	fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); +	fdt_set_totalsize(fdt, fdt_data_size_(fdt));  	return 0;  } diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 6a804859fd0c..6d33cc29d022 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -55,7 +55,7 @@  #include "libfdt_internal.h" -static int _fdt_sw_check_header(void *fdt) +static int fdt_sw_check_header_(void *fdt)  {  	if (fdt_magic(fdt) != FDT_SW_MAGIC)  		return -FDT_ERR_BADMAGIC; @@ -66,11 +66,11 @@ static int _fdt_sw_check_header(void *fdt)  #define FDT_SW_CHECK_HEADER(fdt) \  	{ \  		int err; \ -		if ((err = _fdt_sw_check_header(fdt)) != 0) \ +		if ((err = fdt_sw_check_header_(fdt)) != 0) \  			return err; \  	} -static void *_fdt_grab_space(void *fdt, size_t len) +static void *fdt_grab_space_(void *fdt, size_t len)  {  	int offset = fdt_size_dt_struct(fdt);  	int spaceleft; @@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, size_t len)  		return NULL;  	fdt_set_size_dt_struct(fdt, offset + len); -	return _fdt_offset_ptr_w(fdt, offset); +	return fdt_offset_ptr_w_(fdt, offset);  }  int fdt_create(void *buf, int bufsize) @@ -174,7 +174,7 @@ int fdt_begin_node(void *fdt, const char *name)  	FDT_SW_CHECK_HEADER(fdt); -	nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); +	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));  	if (! nh)  		return -FDT_ERR_NOSPACE; @@ -189,7 +189,7 @@ int fdt_end_node(void *fdt)  	FDT_SW_CHECK_HEADER(fdt); -	en = _fdt_grab_space(fdt, FDT_TAGSIZE); +	en = fdt_grab_space_(fdt, FDT_TAGSIZE);  	if (! en)  		return -FDT_ERR_NOSPACE; @@ -197,7 +197,7 @@ int fdt_end_node(void *fdt)  	return 0;  } -static int _fdt_find_add_string(void *fdt, const char *s) +static int fdt_find_add_string_(void *fdt, const char *s)  {  	char *strtab = (char *)fdt + fdt_totalsize(fdt);  	const char *p; @@ -205,7 +205,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)  	int len = strlen(s) + 1;  	int struct_top, offset; -	p = _fdt_find_string(strtab - strtabsize, strtabsize, s); +	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);  	if (p)  		return p - strtab; @@ -220,25 +220,37 @@ 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;  	FDT_SW_CHECK_HEADER(fdt); -	nameoff = _fdt_find_add_string(fdt, name); +	nameoff = fdt_find_add_string_(fdt, name);  	if (nameoff == 0)  		return -FDT_ERR_NOSPACE; -	prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); +	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));  	if (! prop)  		return -FDT_ERR_NOSPACE;  	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;  } @@ -253,7 +265,7 @@ int fdt_finish(void *fdt)  	FDT_SW_CHECK_HEADER(fdt);  	/* Add terminator */ -	end = _fdt_grab_space(fdt, sizeof(*end)); +	end = fdt_grab_space_(fdt, sizeof(*end));  	if (! end)  		return -FDT_ERR_NOSPACE;  	*end = cpu_to_fdt32(FDT_END); @@ -269,7 +281,7 @@ int fdt_finish(void *fdt)  	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {  		if (tag == FDT_PROP) {  			struct fdt_property *prop = -				_fdt_offset_ptr_w(fdt, offset); +				fdt_offset_ptr_w_(fdt, offset);  			int nameoff;  			nameoff = fdt32_to_cpu(prop->nameoff); diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 6aaab399929c..534c1cbbb2f3 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -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) @@ -93,7 +93,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,  						   val, len);  } -static void _fdt_nop_region(void *start, int len) +static void fdt_nop_region_(void *start, int len)  {  	fdt32_t *p; @@ -107,15 +107,15 @@ 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)); +	fdt_nop_region_(prop, len + sizeof(*prop));  	return 0;  } -int _fdt_node_end_offset(void *fdt, int offset) +int fdt_node_end_offset_(void *fdt, int offset)  {  	int depth = 0; @@ -129,11 +129,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)  {  	int endoffset; -	endoffset = _fdt_node_end_offset(fdt, nodeoffset); +	endoffset = fdt_node_end_offset_(fdt, nodeoffset);  	if (endoffset < 0)  		return endoffset; -	_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), +	fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),  			endoffset - nodeoffset);  	return 0;  } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index ac42e0459524..baa882cfa1df 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1,5 +1,5 @@ -#ifndef _LIBFDT_H -#define _LIBFDT_H +#ifndef LIBFDT_H +#define LIBFDT_H  /*   * libfdt - Flat Device Tree manipulation   * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -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)) @@ -224,23 +225,23 @@ int fdt_next_subnode(const void *fdt, int offset);  #define fdt_size_dt_strings(fdt)	(fdt_get_header(fdt, size_dt_strings))  #define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct)) -#define __fdt_set_hdr(name) \ +#define fdt_set_hdr_(name) \  	static inline void fdt_set_##name(void *fdt, uint32_t val) \  	{ \  		struct fdt_header *fdth = (struct fdt_header *)fdt; \  		fdth->name = cpu_to_fdt32(val); \  	} -__fdt_set_hdr(magic); -__fdt_set_hdr(totalsize); -__fdt_set_hdr(off_dt_struct); -__fdt_set_hdr(off_dt_strings); -__fdt_set_hdr(off_mem_rsvmap); -__fdt_set_hdr(version); -__fdt_set_hdr(last_comp_version); -__fdt_set_hdr(boot_cpuid_phys); -__fdt_set_hdr(size_dt_strings); -__fdt_set_hdr(size_dt_struct); -#undef __fdt_set_hdr +fdt_set_hdr_(magic); +fdt_set_hdr_(totalsize); +fdt_set_hdr_(off_dt_struct); +fdt_set_hdr_(off_dt_strings); +fdt_set_hdr_(off_mem_rsvmap); +fdt_set_hdr_(version); +fdt_set_hdr_(last_comp_version); +fdt_set_hdr_(boot_cpuid_phys); +fdt_set_hdr_(size_dt_strings); +fdt_set_hdr_(size_dt_struct); +#undef fdt_set_hdr_  /**   * fdt_check_header - sanity check a device tree or possible device tree @@ -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); @@ -1416,6 +1449,37 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,  		const void *val, int len);  /** + * fdt_setprop_placeholder - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholer() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to + *		contain the new property value + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, +			    int len, void **prop_data); + +/**   * fdt_setprop_u32 - set a property to a 32-bit integer   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to change @@ -1734,8 +1798,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 @@ -1830,4 +1896,4 @@ int fdt_overlay_apply(void *fdt, void *fdto);  const char *fdt_strerror(int errval); -#endif /* _LIBFDT_H */ +#endif /* LIBFDT_H */ diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 99f936dacc60..bd2474628775 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -1,5 +1,5 @@ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H +#ifndef LIBFDT_ENV_H +#define LIBFDT_ENV_H  /*   * libfdt - Flat Device Tree manipulation   * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -58,16 +58,16 @@  #include <string.h>  #ifdef __CHECKER__ -#define __force __attribute__((force)) -#define __bitwise __attribute__((bitwise)) +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise))  #else -#define __force -#define __bitwise +#define FDT_FORCE +#define FDT_BITWISE  #endif -typedef uint16_t __bitwise fdt16_t; -typedef uint32_t __bitwise fdt32_t; -typedef uint64_t __bitwise fdt64_t; +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t;  #define EXTRACT_BYTE(x, n)	((unsigned long long)((uint8_t *)&x)[n])  #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) @@ -80,33 +80,60 @@ typedef uint64_t __bitwise fdt64_t;  static inline uint16_t fdt16_to_cpu(fdt16_t x)  { -	return (__force uint16_t)CPU_TO_FDT16(x); +	return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);  }  static inline fdt16_t cpu_to_fdt16(uint16_t x)  { -	return (__force fdt16_t)CPU_TO_FDT16(x); +	return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);  }  static inline uint32_t fdt32_to_cpu(fdt32_t x)  { -	return (__force uint32_t)CPU_TO_FDT32(x); +	return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);  }  static inline fdt32_t cpu_to_fdt32(uint32_t x)  { -	return (__force fdt32_t)CPU_TO_FDT32(x); +	return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);  }  static inline uint64_t fdt64_to_cpu(fdt64_t x)  { -	return (__force uint64_t)CPU_TO_FDT64(x); +	return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);  }  static inline fdt64_t cpu_to_fdt64(uint64_t x)  { -	return (__force fdt64_t)CPU_TO_FDT64(x); +	return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);  }  #undef CPU_TO_FDT64  #undef CPU_TO_FDT32  #undef CPU_TO_FDT16  #undef EXTRACT_BYTE -#endif /* _LIBFDT_ENV_H */ +#ifdef __APPLE__ +#include <AvailabilityMacros.h> + +/* strnlen() is not available on Mac OS < 10.7 */ +# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ +                                         MAC_OS_X_VERSION_10_7) + +#define strnlen fdt_strnlen + +/* + * fdt_strnlen: returns the length of a string or max_count - which ever is + * smallest. + * Input 1 string: the string whose size is to be determined + * Input 2 max_count: the maximum value returned by this function + * Output: length of the string or max_count (the smallest of the two) + */ +static inline size_t fdt_strnlen(const char *string, size_t max_count) +{ +    const char *p = memchr(string, 0, max_count); +    return p ? p - string : max_count; +} + +#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < +          MAC_OS_X_VERSION_10_7) */ + +#endif /* __APPLE__ */ + +#endif /* LIBFDT_ENV_H */ diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 02cfa6fb612d..7681e192295b 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -1,5 +1,5 @@ -#ifndef _LIBFDT_INTERNAL_H -#define _LIBFDT_INTERNAL_H +#ifndef LIBFDT_INTERNAL_H +#define LIBFDT_INTERNAL_H  /*   * libfdt - Flat Device Tree manipulation   * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -57,27 +57,27 @@  #define FDT_CHECK_HEADER(fdt) \  	{ \ -		int __err; \ -		if ((__err = fdt_check_header(fdt)) != 0) \ -			return __err; \ +		int err_; \ +		if ((err_ = fdt_check_header(fdt)) != 0) \ +			return err_; \  	} -int _fdt_check_node_offset(const void *fdt, int offset); -int _fdt_check_prop_offset(const void *fdt, int offset); -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); -int _fdt_node_end_offset(void *fdt, int nodeoffset); +int fdt_check_node_offset_(const void *fdt, int offset); +int fdt_check_prop_offset_(const void *fdt, int offset); +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); +int fdt_node_end_offset_(void *fdt, int nodeoffset); -static inline const void *_fdt_offset_ptr(const void *fdt, int offset) +static inline const void *fdt_offset_ptr_(const void *fdt, int offset)  {  	return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;  } -static inline void *_fdt_offset_ptr_w(void *fdt, int offset) +static inline void *fdt_offset_ptr_w_(void *fdt, int offset)  { -	return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); +	return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);  } -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) +static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)  {  	const struct fdt_reserve_entry *rsv_table =  		(const struct fdt_reserve_entry *) @@ -85,11 +85,11 @@ static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int  	return rsv_table + n;  } -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) +static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)  { -	return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); +	return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);  }  #define FDT_SW_MAGIC		(~FDT_MAGIC) -#endif /* _LIBFDT_INTERNAL_H */ +#endif /* LIBFDT_INTERNAL_H */ diff --git a/libfdt/version.lds b/libfdt/version.lds index cff0358f2314..18fb69f70cd8 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -60,6 +60,9 @@ LIBFDT_1.2 {  		fdt_address_cells;  		fdt_size_cells;  		fdt_stringlist_contains; +		fdt_stringlist_count; +		fdt_stringlist_search; +		fdt_stringlist_get;  		fdt_resize;  		fdt_overlay_apply; diff --git a/livetree.c b/livetree.c index 36be9afefd53..57b7db2ed153 100644 --- a/livetree.c +++ b/livetree.c @@ -216,6 +216,29 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)  	return old_node;  } +struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) +{ +	static unsigned int next_orphan_fragment = 0; +	struct node *node; +	struct property *p; +	struct data d = empty_data; +	char *name; + +	d = data_add_marker(d, REF_PHANDLE, ref); +	d = data_append_integer(d, 0xffffffff, 32); + +	p = build_property("target", d); + +	xasprintf(&name, "fragment@%u", +			next_orphan_fragment++); +	name_node(new_node, "__overlay__"); +	node = build_node(p, new_node); +	name_node(node, name); + +	add_child(dt, node); +	return dt; +} +  struct node *chain_node(struct node *first, struct node *list)  {  	assert(first->next_sibling == NULL); @@ -319,8 +342,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)  	memset(new, 0, sizeof(*new)); -	new->re.address = address; -	new->re.size = size; +	new->address = address; +	new->size = size;  	return new;  } @@ -393,7 +416,13 @@ struct property *get_property(struct node *node, const char *propname)  cell_t propval_cell(struct property *prop)  {  	assert(prop->val.len == sizeof(cell_t)); -	return fdt32_to_cpu(*((cell_t *)prop->val.val)); +	return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); +} + +cell_t propval_cell_n(struct property *prop, int n) +{ +	assert(prop->val.len / sizeof(cell_t) >= n); +	return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));  }  struct property *get_property_by_label(struct node *tree, const char *label, @@ -478,7 +507,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) && +		    strprefixeq(path, p - path, child->name))  			return get_node_by_path(child, p+1);  		else if (!p && streq(path, child->name))  			return child; @@ -511,7 +541,10 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)  {  	struct node *child, *node; -	assert((phandle != 0) && (phandle != -1)); +	if ((phandle == 0) || (phandle == -1)) { +		assert(generate_fixups); +		return NULL; +	}  	if (tree->phandle == phandle) {  		if (tree->deleted) @@ -599,13 +632,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)  	a = *((const struct reserve_info * const *)ax);  	b = *((const struct reserve_info * const *)bx); -	if (a->re.address < b->re.address) +	if (a->address < b->address)  		return -1; -	else if (a->re.address > b->re.address) +	else if (a->address > b->address)  		return 1; -	else if (a->re.size < b->re.size) +	else if (a->size < b->size)  		return -1; -	else if (a->re.size > b->re.size) +	else if (a->size > b->size)  		return 1;  	else  		return 0; @@ -902,7 +935,7 @@ static void add_local_fixup_entry(struct dt_info *dti,  		struct node *refnode)  {  	struct node *wn, *nwn;	/* local fixup node, walk node, new */ -	uint32_t value_32; +	fdt32_t value_32;  	char **compp;  	int i, depth; diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt new file mode 100644 index 000000000000..9507d3d44694 --- /dev/null +++ b/pylibfdt/Makefile.pylibfdt @@ -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 diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i new file mode 100644 index 000000000000..415820d7ae88 --- /dev/null +++ b/pylibfdt/libfdt.i @@ -0,0 +1,493 @@ +/* + * 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 + +%include <stdint.i> + +%{ +#define SWIG_FILE_WITH_INIT +#include "libfdt.h" +%} + +%pythoncode %{ + +import struct + +# Error codes, corresponding to FDT_ERR_... in libfdt.h +(NOTFOUND, +        EXISTS, +        NOSPACE, +        BADOFFSET, +        BADPATH, +        BADPHANDLE, +        BADSTATE, +        TRUNCATED, +        BADMAGIC, +        BADVERSION, +        BADSTRUCTURE, +        BADLAYOUT, +        INTERNAL, +        BADNCELLS, +        BADVALUE, +        BADOVERLAY, +        NOPHANDLES) = QUIET_ALL = range(1, 18) +# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions +# altogether. All # functions passed this value will return an error instead +# of raising an exception. + +# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors, +# instead of raising an exception. +QUIET_NOTFOUND = (NOTFOUND,) + + +class FdtException(Exception): +    """An exception caused by an error such as one of the codes above""" +    def __init__(self, err): +        self.err = err + +    def __str__(self): +        return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err)) + +def strerror(fdt_err): +    """Get the string for an error number + +    Args: +        fdt_err: Error number (-ve) + +    Returns: +        String containing the associated error +    """ +    return fdt_strerror(fdt_err) + +def check_err(val, quiet=()): +    """Raise an error if the return value is -ve + +    This is used to check for errors returned by libfdt C functions. + +    Args: +        val: Return value from a libfdt function +        quiet: Errors to ignore (empty to raise on all errors) + +    Returns: +        val if val >= 0 + +    Raises +        FdtException if val < 0 +    """ +    if val < 0: +        if -val not in quiet: +            raise FdtException(val) +    return val + +def check_err_null(val, quiet=()): +    """Raise an error if the return value is NULL + +    This is used to check for a NULL return value from certain libfdt C +    functions + +    Args: +        val: Return value from a libfdt function +        quiet: Errors to ignore (empty to raise on all errors) + +    Returns: +        val if val is a list, None if not + +    Raises +        FdtException if val indicates an error was reported and the error +        is not in @quiet. +    """ +    # Normally a list is returned which contains the data and its length. +    # If we get just an integer error code, it means the function failed. +    if not isinstance(val, list): +        if -val not in quiet: +            raise FdtException(val) +    return val + +class Fdt: +    """Device tree class, supporting all operations + +    The Fdt object is created is created from a device tree binary file, +    e.g. with something like: + +       fdt = Fdt(open("filename.dtb").read()) + +    Operations can then be performed using the methods in this class. Each +    method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). + +    All methods raise an FdtException if an error occurs. To avoid this +    behaviour a 'quiet' parameter is provided for some functions. This +    defaults to empty, but you can pass a list of errors that you expect. +    If one of these errors occurs, the function will return an error number +    (e.g. -NOTFOUND). +    """ +    def __init__(self, data): +        self._fdt = bytearray(data) +        check_err(fdt_check_header(self._fdt)); + +    def subnode_offset(self, parentoffset, name, quiet=()): +        """Get the offset of a named subnode + +        Args: +            parentoffset: Offset of the parent node to check +            name: Name of the required subnode, e.g. 'subnode@1' +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            The node offset of the found node, if any + +        Raises +            FdtException if there is no node with that name, or other error +        """ +        return check_err(fdt_subnode_offset(self._fdt, parentoffset, name), +                         quiet) + +    def path_offset(self, path, quiet=()): +        """Get the offset for a given path + +        Args: +            path: Path to the required node, e.g. '/node@3/subnode@1' +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            Node offset + +        Raises +            FdtException if the path is not valid or not found +        """ +        return check_err(fdt_path_offset(self._fdt, path), quiet) + +    def first_property_offset(self, nodeoffset, quiet=()): +        """Get the offset of the first property in a node offset + +        Args: +            nodeoffset: Offset to the node to check +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            Offset of the first property + +        Raises +            FdtException if the associated node has no properties, or some +                other error occurred +        """ +        return check_err(fdt_first_property_offset(self._fdt, nodeoffset), +                         quiet) + +    def next_property_offset(self, prop_offset, quiet=()): +        """Get the next property in a node + +        Args: +            prop_offset: Offset of the previous property +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            Offset of the next property + +        Raises: +            FdtException if the associated node has no more properties, or +                some other error occurred +        """ +        return check_err(fdt_next_property_offset(self._fdt, prop_offset), +                         quiet) + +    def get_name(self, nodeoffset): +        """Get the name of a node + +        Args: +            nodeoffset: Offset of node to check + +        Returns: +            Node name + +        Raises: +            FdtException on error (e.g. nodeoffset is invalid) +        """ +        return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] + +    def get_property_by_offset(self, prop_offset, quiet=()): +        """Obtains a property that can be examined + +        Args: +            prop_offset: Offset of property (e.g. from first_property_offset()) +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            Property object, or None if not found + +        Raises: +            FdtException on error (e.g. invalid prop_offset or device +            tree format) +        """ +        pdata = check_err_null( +                fdt_get_property_by_offset(self._fdt, prop_offset), quiet) +        if isinstance(pdata, (int)): +            return pdata +        return Property(pdata[0], pdata[1]) + +    def first_subnode(self, nodeoffset, quiet=()): +        """Find the first subnode of a parent node + +        Args: +            nodeoffset: Node offset of parent node +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            The offset of the first subnode, if any + +        Raises: +            FdtException if no subnode found or other error occurs +        """ +        return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) + +    def next_subnode(self, nodeoffset, quiet=()): +        """Find the next subnode + +        Args: +            nodeoffset: Node offset of previous subnode +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            The offset of the next subnode, if any + +        Raises: +            FdtException if no more subnode found or other error occurs +        """ +        return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) + +    def totalsize(self): +        """Return the total size of the device tree + +        Returns: +            Total tree size in bytes +        """ +        return check_err(fdt_totalsize(self._fdt)) + +    def off_dt_struct(self): +        """Return the start of the device tree struct area + +        Returns: +            Start offset of struct area +        """ +        return check_err(fdt_off_dt_struct(self._fdt)) + +    def pack(self, quiet=()): +        """Pack the device tree to remove unused space + +        This adjusts the tree in place. + +        Args: +            quiet: Errors to ignore (empty to raise on all errors) + +        Raises: +            FdtException if any error occurs +        """ +        return check_err(fdt_pack(self._fdt), quiet) + +    def delprop(self, nodeoffset, prop_name): +        """Delete a property from a node + +        Args: +            nodeoffset: Node offset containing property to delete +            prop_name: Name of property to delete + +        Raises: +            FdtError if the property does not exist, or another error occurs +        """ +        return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) + +    def getprop(self, nodeoffset, prop_name, quiet=()): +        """Get a property from a node + +        Args: +            nodeoffset: Node offset containing property to get +            prop_name: Name of property to get +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            Value of property as a bytearray, or -ve error number + +        Raises: +            FdtError if any error occurs (e.g. the property is not found) +        """ +        pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), +                               quiet) +        if isinstance(pdata, (int)): +            return pdata +        return bytearray(pdata[0]) + +    def get_phandle(self, nodeoffset): +        """Get the phandle of a node + +        Args: +            nodeoffset: Node offset to check + +        Returns: +            phandle of node, or 0 if the node has no phandle or another error +            occurs +        """ +        return fdt_get_phandle(self._fdt, nodeoffset) + +    def parent_offset(self, nodeoffset, quiet=()): +        """Get the offset of a node's parent + +        Args: +            nodeoffset: Node offset to check +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            The offset of the parent node, if any + +        Raises: +            FdtException if no parent found or other error occurs +        """ +        return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) + +    def node_offset_by_phandle(self, phandle, quiet=()): +        """Get the offset of a node with the given phandle + +        Args: +            phandle: Phandle to search for +            quiet: Errors to ignore (empty to raise on all errors) + +        Returns: +            The offset of node with that phandle, if any + +        Raises: +            FdtException if no node found or other error occurs +        """ +        return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) + +class Property: +    """Holds a device tree property name and value. + +    This holds a copy of a property taken from the device tree. It does not +    reference the device tree, so if anything changes in the device tree, +    a Property object will remain valid. + +    Properties: +        name: Property name +        value: Proper value as a bytearray +    """ +    def __init__(self, name, value): +        self.name = name +        self.value = value +%} + +%rename(fdt_property) fdt_property_func; + +typedef int fdt32_t; + +%include "libfdt/fdt.h" + +%include "typemaps.i" + +/* Most functions don't change the device tree, so use a const void * */ +%typemap(in) (const void *)(const void *fdt) { +	if (!PyByteArray_Check($input)) { +		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" +			"', argument " "$argnum"" of type '" "$type""'"); +	} +	$1 = (void *)PyByteArray_AsString($input); +        fdt = $1; +        fdt = fdt; /* avoid unused variable warning */ +} + +/* Some functions do change the device tree, so use void * */ +%typemap(in) (void *)(const void *fdt) { +	if (!PyByteArray_Check($input)) { +		SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" +			"', argument " "$argnum"" of type '" "$type""'"); +	} +	$1 = PyByteArray_AsString($input); +        fdt = $1; +        fdt = fdt; /* avoid unused variable warning */ +} + +%typemap(out) (struct fdt_property *) { +	PyObject *buff; + +	if ($1) { +		resultobj = PyString_FromString( +			fdt_string(fdt1, fdt32_to_cpu($1->nameoff))); +		buff = PyByteArray_FromStringAndSize( +			(const char *)($1 + 1), fdt32_to_cpu($1->len)); +		resultobj = SWIG_Python_AppendOutput(resultobj, buff); +	} +} + +%apply int *OUTPUT { int *lenp }; + +/* typemap used for fdt_getprop() */ +%typemap(out) (const void *) { +	if (!$1) +		$result = Py_None; +	else +		$result = Py_BuildValue("s#", $1, *arg4); +} + +/* We have both struct fdt_property and a function fdt_property() */ +%warnfilter(302) fdt_property; + +/* These are macros in the header so have to be redefined here */ +int fdt_magic(const void *fdt); +int fdt_totalsize(const void *fdt); +int fdt_off_dt_struct(const void *fdt); +int fdt_off_dt_strings(const void *fdt); +int fdt_off_mem_rsvmap(const void *fdt); +int fdt_version(const void *fdt); +int fdt_last_comp_version(const void *fdt); +int fdt_boot_cpuid_phys(const void *fdt); +int fdt_size_dt_strings(const void *fdt); +int fdt_size_dt_struct(const void *fdt); + +%include <../libfdt/libfdt.h> diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py new file mode 100755 index 000000000000..1a1e8327122e --- /dev/null +++ b/pylibfdt/setup.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python2 + +""" +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'], +) @@ -17,11 +17,12 @@   *                                                                   USA   */ -#ifndef _SRCPOS_H_ -#define _SRCPOS_H_ +#ifndef SRCPOS_H +#define SRCPOS_H  #include <stdio.h>  #include <stdbool.h> +#include "util.h"  struct srcfile_state {  	FILE *f; @@ -106,13 +107,11 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len);  extern struct srcpos *srcpos_copy(struct srcpos *pos);  extern char *srcpos_string(struct srcpos *pos); -extern void srcpos_verror(struct srcpos *pos, const char *prefix, -			  const char *fmt, va_list va) -	__attribute__((format(printf, 3, 0))); -extern void srcpos_error(struct srcpos *pos, const char *prefix, -			 const char *fmt, ...) -	__attribute__((format(printf, 3, 4))); +extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, +					const char *fmt, va_list va); +extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix, +				      const char *fmt, ...);  extern void srcpos_set_line(char *f, int l); -#endif /* _SRCPOS_H_ */ +#endif /* SRCPOS_H */ diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 3d7a4f82f067..22581359623c 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -72,13 +72,13 @@ tests_clean:  	rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%)  	rm -f $(TESTS_CLEANFILES) -check:	tests ${TESTS_BIN} +check:	tests ${TESTS_BIN} $(TESTS_PYLIBFDT)  	cd $(TESTS_PREFIX); ./run_tests.sh -checkm: tests ${TESTS_BIN} +checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)  	cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ -checkv:	tests ${TESTS_BIN} +checkv:	tests ${TESTS_BIN} $(TESTS_PYLIBFDT)  	cd $(TESTS_PREFIX); ./run_tests.sh -v  ifneq ($(DEPTARGETS),) diff --git a/tests/bad-chosen.dts b/tests/bad-chosen.dts new file mode 100644 index 000000000000..d6f53c68ddd9 --- /dev/null +++ b/tests/bad-chosen.dts @@ -0,0 +1,10 @@ +/dts-v1/; + +/ { +	node2 { +		chosen { +			bootargs = <0xdeadbeef>; +			stdout-path = <1>; +		}; +	}; +}; diff --git a/tests/bad-gpio.dts b/tests/bad-gpio.dts new file mode 100644 index 000000000000..6b77be447b82 --- /dev/null +++ b/tests/bad-gpio.dts @@ -0,0 +1,13 @@ +/dts-v1/; + +/ { +	gpio: gpio-controller { +		#gpio-cells = <3>; +	}; + +	node { +		nr-gpios = <1>; +		foo-gpios = <&gpio>; +		bar-gpio = <&gpio 1 2 3>; +	}; +}; diff --git a/tests/bad-interrupt-cells.dts b/tests/bad-interrupt-cells.dts new file mode 100644 index 000000000000..39fc78fdc11d --- /dev/null +++ b/tests/bad-interrupt-cells.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { +	interrupt-parent = <&intc>; +	intc: interrupt-controller { +		#interrupt-cells = <3>; +	}; + +	node { +		interrupts = <1>; +	}; +}; diff --git a/tests/bad-phandle-cells.dts b/tests/bad-phandle-cells.dts new file mode 100644 index 000000000000..7f7c6a25fd25 --- /dev/null +++ b/tests/bad-phandle-cells.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { +	intc: interrupt-controller { +		#interrupt-cells = <3>; +	}; + +	node { +		interrupts-extended = <&intc>; +	}; +}; diff --git a/tests/bad-string-props.dts b/tests/bad-string-props.dts index 396f82069cf7..6694704a5fc2 100644 --- a/tests/bad-string-props.dts +++ b/tests/bad-string-props.dts @@ -4,4 +4,11 @@  	device_type = <0xdeadbeef>;  	model = <0xdeadbeef>;  	status = <0xdeadbeef>; +	label = <0xdeadbeef>; + +	foobar-names = "foo", <1>; + +	node { +		compatible = "good", <0xdeadbeef>; +	};  }; diff --git a/tests/char_literal.c b/tests/char_literal.c index d7a4773419a0..da1f964d85fa 100644 --- a/tests/char_literal.c +++ b/tests/char_literal.c @@ -31,7 +31,7 @@  int main(int argc, char *argv[])  {  	void *fdt; -	uint32_t expected_cells[5]; +	fdt32_t expected_cells[5];  	expected_cells[0] = cpu_to_fdt32((unsigned char)TEST_CHAR1);  	expected_cells[1] = cpu_to_fdt32((unsigned char)TEST_CHAR2); diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index 12495dea483e..98bf0e712805 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -28,7 +28,7 @@  #include "tests.h"  #include "testdata.h" -int notequal; /* = 0 */ +static int notequal; /* = 0 */  #define MISMATCH(fmt, ...)			\  	do { \ diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c index 20b4356f92f6..baf2ae7826a1 100644 --- a/tests/dtbs_equal_unordered.c +++ b/tests/dtbs_equal_unordered.c @@ -29,7 +29,7 @@  #include "tests.h"  #include "testdata.h" -int notequal; /* = 0 */ +static int notequal; /* = 0 */  #define MISMATCH(fmt, ...)			\  	do { \ @@ -59,14 +59,14 @@ static int mem_rsv_cmp(const void *p1, const void *p2)  	const struct fdt_reserve_entry *re1 = p1;  	const struct fdt_reserve_entry *re2 = p2; -	if (re1->address < re2->address) +	if (fdt64_to_cpu(re1->address) < fdt64_to_cpu(re2->address))  		return -1; -	else if (re1->address > re2->address) +	else if (fdt64_to_cpu(re1->address) > fdt64_to_cpu(re2->address))  		return 1; -	if (re1->size < re2->size) +	if (fdt64_to_cpu(re1->size) < fdt64_to_cpu(re2->size))  		return -1; -	else if (re1->size > re2->size) +	else if (fdt64_to_cpu(re1->size) > fdt64_to_cpu(re2->size))  		return 1;  	return 0; diff --git a/tests/dumptrees.c b/tests/dumptrees.c index a49dbfab1567..87d1c3d8440a 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -29,11 +29,11 @@  #include "testdata.h" -struct { +static struct {  	void *blob;  	const char *filename;  } trees[] = { -#define TREE(name)	{ &_##name, #name ".dtb" } +#define TREE(name)	{ &name, #name ".dtb" }  	TREE(test_tree1),  	TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char),  	TREE(ovf_size_strings), diff --git a/tests/fdtoverlay-runtest.sh b/tests/fdtoverlay-runtest.sh new file mode 100755 index 000000000000..06c1169baad3 --- /dev/null +++ b/tests/fdtoverlay-runtest.sh @@ -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 diff --git a/tests/include7.dts b/tests/include7.dts index 2f6eb890f1fa..ab2c948f0f69 100644 --- a/tests/include7.dts +++ b/tests/include7.dts @@ -5,6 +5,7 @@  		subsubnode {  			compatible = "subsubnode1", "subsubnode"; +			placeholder = "this is a placeholder string", "string2";  			prop-int = <0xdeadbeef>;  		}; diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c index 57e2ff670ded..ed1f967bba25 100644 --- a/tests/integer-expressions.c +++ b/tests/integer-expressions.c @@ -30,7 +30,7 @@  #include "tests.h"  #include "testdata.h" -struct test_expr { +static struct test_expr {  	const char *expr;  	uint32_t result;  } expr_table[] = { @@ -70,7 +70,7 @@ struct test_expr {  int main(int argc, char *argv[])  {  	void *fdt; -	const uint32_t *res; +	const fdt32_t *res;  	int reslen;  	int i; diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c index 4bdf09194c8b..486f9c69e2b8 100644 --- a/tests/node_check_compatible.c +++ b/tests/node_check_compatible.c @@ -45,6 +45,23 @@ static void check_compatible(const void *fdt, const char *path,  		FAIL("%s is not compatible with \"%s\"", path, compat);  } +static void check_not_compatible(const void *fdt, const char *path, +				 const char *compat) +{ +	int offset, err; + +	offset = fdt_path_offset(fdt, path); +	if (offset < 0) +		FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset)); + +	err = fdt_node_check_compatible(fdt, offset, compat); +	if (err < 0) +		FAIL("fdt_node_check_compatible(%s): %s", path, +		     fdt_strerror(err)); +	if (err == 0) +		FAIL("%s is incorrectly compatible with \"%s\"", path, compat); +} +  int main(int argc, char *argv[])  {  	void *fdt; @@ -55,8 +72,10 @@ int main(int argc, char *argv[])  	check_compatible(fdt, "/", "test_tree1");  	check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode1");  	check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode"); +	check_not_compatible(fdt, "/subnode@1/subsubnode", "subsubnode2");  	check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode2");  	check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode"); +	check_not_compatible(fdt, "/subnode@2/subsubnode", "subsubnode1");  	PASS();  } diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c index 9212a4efeffc..286f1e7aa15c 100644 --- a/tests/node_offset_by_prop_value.c +++ b/tests/node_offset_by_prop_value.c @@ -69,7 +69,7 @@ static void check_search_str(void *fdt, const char *propname,  #define check_search_cell(fdt, propname, propval, ...) \  	{ \ -		uint32_t val = cpu_to_fdt32(propval); \ +		fdt32_t val = cpu_to_fdt32(propval); \  		check_search((fdt), (propname), &val, sizeof(val), \  			     ##__VA_ARGS__); \  	} diff --git a/tests/nopulate.c b/tests/nopulate.c index cd79872bc4a9..94ce8adbb98a 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -45,7 +45,7 @@ static int nopulate_struct(char *buf, const char *fdt)  		       nextoffset - offset);  		p += nextoffset - offset; -		*((uint32_t *)p) = cpu_to_fdt32(FDT_NOP); +		*((fdt32_t *)p) = cpu_to_fdt32(FDT_NOP);  		p += FDT_TAGSIZE;  	} while (tag != FDT_END); diff --git a/tests/path-references.c b/tests/path-references.c index c8d25fb85fdd..5e332e8f32ca 100644 --- a/tests/path-references.c +++ b/tests/path-references.c @@ -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(); diff --git a/tests/path-references.dts b/tests/path-references.dts index b00fd79061fa..8c66d8057bbd 100644 --- a/tests/path-references.dts +++ b/tests/path-references.dts @@ -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; +		}; +	};  }; diff --git a/tests/pci-bridge-bad1.dts b/tests/pci-bridge-bad1.dts new file mode 100644 index 000000000000..17aac04aec5d --- /dev/null +++ b/tests/pci-bridge-bad1.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { +	compatible = "example,pci-bridge-ok"; +	#address-cells = < 2 >; +	#size-cells = < 2 >; +	abadname@0 { +		device_type = "pci"; +		compatible = "example,pci-bridge"; +		#address-cells = < 3 >; +		#size-cells = < 2 >; +		reg = <0 0 0 0x1000>; +		bus-range = <0 0xff>; +		ranges = <0 0 0 0 0 0 0x10000>; +	}; +}; diff --git a/tests/pci-bridge-bad2.dts b/tests/pci-bridge-bad2.dts new file mode 100644 index 000000000000..a7e5c054ac41 --- /dev/null +++ b/tests/pci-bridge-bad2.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { +	compatible = "example,pci-bridge-ok"; +	#address-cells = < 2 >; +	#size-cells = < 2 >; +	p@0 { +		device_type = "pci"; +		compatible = "example,pci-bridge"; +		#address-cells = < 3 >; +		#size-cells = < 2 >; +		reg = <0 0 0 0x1000>; +		bus-range = <0 0xff>; +		ranges = <0 0 0 0 0 0 0x10000>; +	}; +}; diff --git a/tests/pci-bridge-ok.dts b/tests/pci-bridge-ok.dts new file mode 100644 index 000000000000..02e32e01a982 --- /dev/null +++ b/tests/pci-bridge-ok.dts @@ -0,0 +1,25 @@ +/dts-v1/; + +/ { +	compatible = "example,pci-bridge-ok"; +	#address-cells = < 2 >; +	#size-cells = < 2 >; +	pci@0 { +		device_type = "pci"; +		compatible = "example,pci-bridge"; +		#address-cells = < 3 >; +		#size-cells = < 2 >; +		reg = <0 0 0 0x1000>; +		bus-range = <0 0xff>; +		ranges = <0 0 0 0 0 0 0x10000>; +	}; +	pcie@10000000000 { +		device_type = "pci"; +		compatible = "example,pcie-bridge"; +		#address-cells = < 3 >; +		#size-cells = < 2 >; +		reg = <0x10 0x00000000 0 0x1000>; +		bus-range = <0 0xff>; +		ranges = <0 0 0 0 0 0 0x10000>; +	}; +}; diff --git a/tests/property_iterate.c b/tests/property_iterate.c index 0f3959cb8c22..b5cedbeef399 100644 --- a/tests/property_iterate.c +++ b/tests/property_iterate.c @@ -33,7 +33,7 @@  static void test_node(void *fdt, int parent_offset)  { -	fdt32_t properties; +	uint32_t properties;  	const fdt32_t *prop;  	int offset, property;  	int count; @@ -48,7 +48,7 @@ static void test_node(void *fdt, int parent_offset)  		FAIL("Missing/invalid test-properties property at '%s'",  		     fdt_get_name(fdt, parent_offset, NULL));  	} -	properties = cpu_to_fdt32(*prop); +	properties = fdt32_to_cpu(*prop);  	count = 0;  	offset = fdt_first_subnode(fdt, parent_offset); diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py new file mode 100644 index 000000000000..95d911aebbd7 --- /dev/null +++ b/tests/pylibfdt_tests.py @@ -0,0 +1,334 @@ +# 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.insert(0, '../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.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 testSubnodeOffset(self): +        """check that we can locate a subnode by name""" +        node1 = self.fdt.path_offset('/subnode@1') +        self.assertEquals(self.fdt.subnode_offset(0, 'subnode@1'), node1) + +        with self.assertRaises(FdtException) as e: +            self.fdt.subnode_offset(0, 'missing') +        self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + +        node2 = self.fdt.path_offset('/subnode@1/subsubnode') +        self.assertEquals(self.fdt.subnode_offset(node1, 'subsubnode'), node2) + +    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)) + +    def testIntegers(self): +        """Check that integers can be passed and returned""" +        self.assertEquals(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0)) +        node2 = self.fdt.path_offset('/subnode@2') +        self.assertEquals(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2)) + +    def testGetPhandle(self): +        """Test for the get_phandle() method""" +        self.assertEquals(0, self.fdt.get_phandle(0)) +        node2 = self.fdt.path_offset('/subnode@2') +        self.assertEquals(0x2000, self.fdt.get_phandle(node2)) + +    def testParentOffset(self): +        """Test for the parent_offset() method""" +        self.assertEquals(-libfdt.NOTFOUND, +                          self.fdt.parent_offset(0, QUIET_NOTFOUND)) +        with self.assertRaises(FdtException) as e: +            self.fdt.parent_offset(0) +        self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + +        node1 = self.fdt.path_offset('/subnode@2') +        self.assertEquals(0, self.fdt.parent_offset(node1)) +        node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') +        self.assertEquals(node1, self.fdt.parent_offset(node2)) + +    def testNodeOffsetByPhandle(self): +        """Test for the node_offset_by_phandle() method""" +        self.assertEquals(-libfdt.NOTFOUND, +                          self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND)) +        node1 = self.fdt.path_offset('/subnode@2') +        self.assertEquals(node1, self.fdt.node_offset_by_phandle(0x2000)) +        node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') +        self.assertEquals(node2, self.fdt.node_offset_by_phandle(0x2001)) + + +if __name__ == "__main__": +    unittest.main() diff --git a/tests/references.c b/tests/references.c index 46662fc0faa7..cab70f6579af 100644 --- a/tests/references.c +++ b/tests/references.c @@ -29,7 +29,7 @@  static void check_ref(const void *fdt, int node, uint32_t checkref)  { -	const uint32_t *p; +	const fdt32_t *p;  	uint32_t ref;  	int len; @@ -58,7 +58,7 @@ static void check_ref(const void *fdt, int node, uint32_t checkref)  static void check_rref(const void *fdt)  { -	const uint32_t *p; +	const fdt32_t *p;  	uint32_t ref;  	int len; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index ed489dbdd269..3fa7c0a7fc98 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -6,6 +6,11 @@ if [ -z "$CC" ]; then      CC=gcc  fi +# stat differs between platforms +if [ -z "$STATSZ" ]; then +	STATSZ="stat -c %s" +fi +  export QUIET_TEST=1  STOP_ON_FAIL=0 @@ -114,7 +119,7 @@ run_wrap_error_test () {  # $2: align base  check_align () {      shorten_echo "check_align $@:	" -    local size=$(stat -c %s "$1") +    local size=$($STATSZ "$1")      local align="$2"      (  	if [ $(($size % $align)) -eq 0 ] ;then @@ -157,7 +162,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 \ @@ -197,6 +210,12 @@ libfdt_overlay_tests () {      run_test overlay overlay_base_manual_symbols.test.dtb overlay_overlay_manual_fixups.test.dtb +    # test simplified plugin syntax +    run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb overlay_overlay_simple.dts + +    # verify non-generation of local fixups +    run_test check_path overlay_overlay_simple.dtb not-exists "/__local_fixups__" +      # Bad fixup tests      for test in $BAD_FIXUP_TREES; do  	tree="overlay_bad_fixup_$test" @@ -420,7 +439,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 @@ -532,7 +551,10 @@ dtc_tests () {      check_tests bad-name-property.dts name_properties      check_tests bad-ncells.dts address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -    check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string +    check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string label_is_string compatible_is_string_list names_is_string_list +    check_tests bad-chosen.dts chosen_node_is_root +    check_tests bad-chosen.dts chosen_node_bootargs +    check_tests bad-chosen.dts chosen_node_stdout_path      check_tests bad-reg-ranges.dts reg_format ranges_format      check_tests bad-empty-ranges.dts ranges_format      check_tests reg-ranges-root.dts reg_format ranges_format @@ -540,6 +562,12 @@ 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 +    check_tests bad-phandle-cells.dts interrupts_extended_property +    check_tests bad-gpio.dts gpios_property +    run_sh_test dtc-checkfails.sh deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb bad-gpio.dts +    check_tests bad-interrupt-cells.dts interrupts_property      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 @@ -554,6 +582,10 @@ dtc_tests () {      run_test check_path test_tree1.dtb exists "/subnode@1"      run_test check_path test_tree1.dtb not-exists "/subnode@10" +    check_tests pci-bridge-ok.dts -n pci_bridge +    check_tests pci-bridge-bad1.dts pci_bridge +    check_tests pci-bridge-bad2.dts pci_bridge +      # Check warning options      run_sh_test dtc-checkfails.sh address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb bad-ncells.dts      run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts @@ -690,7 +722,7 @@ fdtput_tests () {      text=lorem.txt      # Allow just enough space for $text -    run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts +    run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts      # run_fdtput_test <expected-result> <file> <node> <property> <flags> <value>      run_fdtput_test "a_model" $dtb / model -ts "a_model" @@ -709,7 +741,7 @@ fdtput_tests () {      run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)"      # Start again with a fresh dtb -    run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts +    run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts      # Node creation      run_wrap_error_test $DTPUT $dtb -c /baldrick sod @@ -737,7 +769,7 @@ fdtput_tests () {      run_wrap_test $DTPUT $dtb -cp /chosen/son      # Start again with a fresh dtb -    run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts +    run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts      # Node delete      run_wrap_test $DTPUT $dtb -c /chosen/node1 /chosen/node2 /chosen/node3 @@ -769,6 +801,55 @@ 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} + +    stacked_base=stacked_overlay_base.dts +    stacked_basedtb=stacked_overlay_base.fdtoverlay.test.dtb +    stacked_bar=stacked_overlay_bar.dts +    stacked_bardtb=stacked_overlay_bar.fdtoverlay.test.dtb +    stacked_baz=stacked_overlay_baz.dts +    stacked_bazdtb=stacked_overlay_baz.fdtoverlay.test.dtb +    stacked_targetdtb=stacked_overlay_target.fdtoverlay.test.dtb + +    run_dtc_test -@ -I dts -O dtb -o $stacked_basedtb $stacked_base +    run_dtc_test -@ -I dts -O dtb -o $stacked_bardtb $stacked_bar +    run_dtc_test -@ -I dts -O dtb -o $stacked_bazdtb $stacked_baz + +    # test that baz correctly inserted the property +    run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb} +} + +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 +868,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 +902,12 @@ for set in $TESTSETS; do  	"fdtdump")  	    fdtdump_tests  	    ;; +	"pylibfdt") +	    pylibfdt_tests +	    ;; +        "fdtoverlay") +	    fdtoverlay_tests +	    ;;      esac  done @@ -830,3 +922,4 @@ fi  echo "* Strange test result:	$tot_strange"  echo "**********" +[ "$tot_tests" -eq "$tot_pass" ] || exit 1 diff --git a/tests/sized_cells.c b/tests/sized_cells.c index 94da03b8a077..0b2b8dc56626 100644 --- a/tests/sized_cells.c +++ b/tests/sized_cells.c @@ -54,9 +54,9 @@ int main(int argc, char *argv[])  				 TEST_CHAR4,  				 TEST_CHAR5,  				 TEST_VALUE_1 >> 24}; -	uint16_t expected_16[6]; -	uint32_t expected_32[6]; -	uint64_t expected_64[6]; +	fdt16_t expected_16[6]; +	fdt32_t expected_32[6]; +	fdt64_t expected_64[6];  	int i;  	for (i = 0; i < 5; ++i) { diff --git a/tests/stacked_overlay_bar.dts b/tests/stacked_overlay_bar.dts new file mode 100644 index 000000000000..c64639952f4c --- /dev/null +++ b/tests/stacked_overlay_bar.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; +/ { +	fragment@1 { +		target = <&foo>; +		__overlay__ { +			overlay-1-property; +			bar: barnode { +				bar-property = "bar"; +			}; +		}; +	}; +}; diff --git a/tests/stacked_overlay_base.dts b/tests/stacked_overlay_base.dts new file mode 100644 index 000000000000..29164230d6f6 --- /dev/null +++ b/tests/stacked_overlay_base.dts @@ -0,0 +1,6 @@ +/dts-v1/; +/ { +	foo: foonode { +		foo-property = "foo"; +	}; +}; diff --git a/tests/stacked_overlay_baz.dts b/tests/stacked_overlay_baz.dts new file mode 100644 index 000000000000..a52f0cc600e3 --- /dev/null +++ b/tests/stacked_overlay_baz.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; +/ { +	fragment@1 { +		target = <&bar>; +		__overlay__ { +			overlay-2-property; +			baz: baznode { +				baz-property = "baz"; +			}; +		}; +	}; +}; diff --git a/tests/stringlist.c b/tests/stringlist.c index a9d3e73920ca..23cfece021dd 100644 --- a/tests/stringlist.c +++ b/tests/stringlist.c @@ -60,10 +60,11 @@ static void check_expected_failure(const void *fdt, const char *path,  		FAIL("empty string not found in #address-cells: %d\n", err);  	/* -	 * fdt_get_string() can successfully extract strings from non-string -	 * properties. This is because it doesn't necessarily parse the whole -	 * property value, which would be necessary for it to determine if a -	 * valid string or string list is present. +	 * fdt_getprop_string() can successfully extract strings from +	 * non-string properties. This is because it doesn't +	 * necessarily parse the whole property value, which would be +	 * necessary for it to determine if a valid string or string +	 * list is present.  	 */  } diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c index 0fb5c901ebd7..7be5706eeb30 100644 --- a/tests/subnode_iterate.c +++ b/tests/subnode_iterate.c @@ -33,7 +33,7 @@  static void test_node(void *fdt, int parent_offset)  { -	fdt32_t subnodes; +	uint32_t subnodes;  	const fdt32_t *prop;  	int offset;  	int count; @@ -45,7 +45,7 @@ static void test_node(void *fdt, int parent_offset)  		FAIL("Missing/invalid subnodes property at '%s'",  		     fdt_get_name(fdt, parent_offset, NULL));  	} -	subnodes = cpu_to_fdt32(*prop); +	subnodes = fdt32_to_cpu(*prop);  	count = 0;  	fdt_for_each_subnode(offset, fdt, parent_offset) diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 6d4c53102967..386b05f6f720 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -42,14 +42,14 @@ static void realloc_fdt(void **fdt, size_t *size, bool created)  	switch (alloc_mode) {  	case FIXED:  		if (!(*fdt)) -			fdt = xmalloc(*size); +			*fdt = xmalloc(*size);  		else  			FAIL("Ran out of space");  		return;  	case RESIZE:  		if (!(*fdt)) { -			fdt = xmalloc(SPACE); +			*fdt = xmalloc(SPACE);  		} else if (*size < SPACE) {  			*size += 1;  			fdt_resize(*fdt, *fdt, *size); @@ -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); @@ -108,6 +111,8 @@ int main(int argc, char *argv[])  				CONFIG("Bad allocation mode \"%s\" specified",  				       argv[1]);  		} +	} else { +		CONFIG("sw_tree1 <dtb file> [<allocation mode>]");  	}  	fdt = xmalloc(size); @@ -135,6 +140,8 @@ int main(int argc, char *argv[])  	CHECK(fdt_begin_node(fdt, "subsubnode"));  	CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode",  			   23)); +	CHECK(fdt_property_placeholder(fdt, "placeholder", place_len, &place)); +	memcpy(place, place_str, place_len);  	CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));  	CHECK(fdt_end_node(fdt));  	CHECK(fdt_begin_node(fdt, "ss1")); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 67ecfd0ea28f..77ea3256947b 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -18,6 +18,7 @@  		subsubnode {  			compatible = "subsubnode1", "subsubnode"; +			placeholder = "this is a placeholder string", "string2";  			prop-int = <0xdeadbeef>;  		}; diff --git a/tests/test_tree1_label_noderef.dts b/tests/test_tree1_label_noderef.dts index b2b194c6df64..cfe5946f8462 100644 --- a/tests/test_tree1_label_noderef.dts +++ b/tests/test_tree1_label_noderef.dts @@ -18,6 +18,7 @@  		subsubnode {  			compatible = "subsubnode1", "subsubnode"; +			placeholder = "this is a placeholder string", "string2";  			prop-int = <0xdeadbeef>;  		}; diff --git a/tests/testdata.h b/tests/testdata.h index 3588778ad159..c30f0c8a7698 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -4,15 +4,25 @@  #define ASM_CONST_LL(x)	(x##ULL)  #endif -#define TEST_ADDR_1	ASM_CONST_LL(0xdeadbeef00000000) -#define TEST_SIZE_1	ASM_CONST_LL(0x100000) -#define TEST_ADDR_2	ASM_CONST_LL(123456789) -#define TEST_SIZE_2	ASM_CONST_LL(010000) +#define TEST_ADDR_1H	ASM_CONST_LL(0xdeadbeef) +#define TEST_ADDR_1L	ASM_CONST_LL(0x00000000) +#define TEST_ADDR_1	((TEST_ADDR_1H << 32) | TEST_ADDR_1L) +#define TEST_SIZE_1H	ASM_CONST_LL(0x00000000) +#define TEST_SIZE_1L	ASM_CONST_LL(0x00100000) +#define TEST_SIZE_1	((TEST_SIZE_1H << 32) | TEST_SIZE_1L) +#define TEST_ADDR_2H	ASM_CONST_LL(0) +#define TEST_ADDR_2L	ASM_CONST_LL(123456789) +#define TEST_ADDR_2	((TEST_ADDR_2H << 32) | TEST_ADDR_2L) +#define TEST_SIZE_2H	ASM_CONST_LL(0) +#define TEST_SIZE_2L	ASM_CONST_LL(010000) +#define TEST_SIZE_2	((TEST_SIZE_2H << 32) | TEST_SIZE_2L)  #define TEST_VALUE_1	0xdeadbeef  #define TEST_VALUE_2	123456789 -#define TEST_VALUE64_1	ASM_CONST_LL(0xdeadbeef01abcdef) +#define TEST_VALUE64_1H	ASM_CONST_LL(0xdeadbeef) +#define TEST_VALUE64_1L	ASM_CONST_LL(0x01abcdef) +#define TEST_VALUE64_1	((TEST_VALUE64_1H << 32) | TEST_VALUE64_1L)  #define PHANDLE_1	0x2000  #define PHANDLE_2	0x2001 @@ -31,10 +41,10 @@  #define TEST_CHAR5	'\xff'  #ifndef __ASSEMBLY__ -extern struct fdt_header _test_tree1; -extern struct fdt_header _truncated_property; -extern struct fdt_header _bad_node_char; -extern struct fdt_header _bad_node_format; -extern struct fdt_header _bad_prop_char; -extern struct fdt_header _ovf_size_strings; +extern struct fdt_header test_tree1; +extern struct fdt_header truncated_property; +extern struct fdt_header bad_node_char; +extern struct fdt_header bad_node_format; +extern struct fdt_header bad_prop_char; +extern struct fdt_header ovf_size_strings;  #endif /* ! __ASSEMBLY */ diff --git a/tests/tests.h b/tests/tests.h index 56a843cd25d8..df38b773cc37 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -1,5 +1,5 @@ -#ifndef _TESTS_H -#define _TESTS_H +#ifndef TESTS_H +#define TESTS_H  /*   * libfdt - Flat Device Tree manipulation   *	Testcase definitions @@ -99,7 +99,7 @@ void check_property(void *fdt, int nodeoffset, const char *name,  		    int len, const void *val);  #define check_property_cell(fdt, nodeoffset, name, val) \  	({ \ -		uint32_t x = cpu_to_fdt32(val);			      \ +		fdt32_t x = cpu_to_fdt32(val);			      \  		check_property(fdt, nodeoffset, name, sizeof(x), &x); \  	}) @@ -108,12 +108,12 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name,  			  int len, const void *val);  #define check_getprop_cell(fdt, nodeoffset, name, val) \  	({ \ -		uint32_t x = cpu_to_fdt32(val);			     \ +		fdt32_t x = cpu_to_fdt32(val);			     \  		check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \  	})  #define check_getprop_64(fdt, nodeoffset, name, val) \  	({ \ -		uint64_t x = cpu_to_fdt64(val);			     \ +		fdt64_t x = cpu_to_fdt64(val);			     \  		check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \  	})  #define check_getprop_string(fdt, nodeoffset, name, s) \ @@ -126,4 +126,4 @@ void *open_blob_rw(void *blob);  #include "util.h" -#endif /* _TESTS_H */ +#endif /* TESTS_H */ diff --git a/tests/tests.sh b/tests/tests.sh index 818fd09c2ff0..8dda6e105635 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -22,6 +22,7 @@ DTC=../dtc  DTGET=../fdtget  DTPUT=../fdtput  FDTDUMP=../fdtdump +FDTOVERLAY=../fdtoverlay  verbose_run () {      if [ -z "$QUIET_TEST" ]; then diff --git a/tests/trees.S b/tests/trees.S index 3d24aa2dcbc8..6898cf97320c 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -7,20 +7,9 @@  	.byte	((val) >> 8) & 0xff ; \  	.byte	(val) & 0xff	; -#define FDTQUAD(val) \ -	.byte	((val) >> 56) & 0xff ; \ -	.byte	((val) >> 48) & 0xff ; \ -	.byte	((val) >> 40) & 0xff ; \ -	.byte	((val) >> 32) & 0xff ; \ -	.byte	((val) >> 24) & 0xff ; \ -	.byte	((val) >> 16) & 0xff ; \ -	.byte	((val) >> 8) & 0xff ; \ -	.byte	(val) & 0xff	; -  #define TREE_HDR(tree) \  	.balign	8		; \ -	.globl	_##tree		; \ -_##tree:	\ +	.globl	tree		; \  tree:	\  	FDTLONG(FDT_MAGIC)	; \  	FDTLONG(tree##_end - tree) ; \ @@ -33,14 +22,16 @@ tree:	\  	FDTLONG(tree##_strings_end - tree##_strings) ; \  	FDTLONG(tree##_struct_end - tree##_struct) ; -#define RSVMAP_ENTRY(addr, len) \ -	FDTQUAD(addr)		; \ -	FDTQUAD(len)		; \ +#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \ +	FDTLONG(addrh)		; \ +	FDTLONG(addrl)		; \ +	FDTLONG(lenh)		; \ +	FDTLONG(lenl)  #define EMPTY_RSVMAP(tree) \  	.balign	8		; \  tree##_rsvmap:			; \ -	RSVMAP_ENTRY(0, 0) \ +	RSVMAP_ENTRY(0, 0, 0, 0) \  tree##_rsvmap_end:		;  #define PROPHDR(tree, name, len) \ @@ -52,9 +43,10 @@ tree##_rsvmap_end:		;  	PROPHDR(tree, name, 4) \  	FDTLONG(val)		; -#define PROP_INT64(tree, name, val) \ +#define PROP_INT64(tree, name, valh, vall) \  	PROPHDR(tree, name, 8) \ -	FDTQUAD(val)		; +	FDTLONG(valh)		; \ +	FDTLONG(vall)		;  #define PROP_STR(tree, name, str) \  	PROPHDR(tree, name, 55f - 54f) \ @@ -81,16 +73,16 @@ tree##_##name:			; \  	.balign	8  test_tree1_rsvmap: -	RSVMAP_ENTRY(TEST_ADDR_1, TEST_SIZE_1) -	RSVMAP_ENTRY(TEST_ADDR_2, TEST_SIZE_2) -	RSVMAP_ENTRY(0, 0) +	RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L) +	RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L) +	RSVMAP_ENTRY(0, 0, 0, 0)  test_tree1_rsvmap_end:  test_tree1_struct:  	BEGIN_NODE("")  	PROP_STR(test_tree1, compatible, "test_tree1")  	PROP_INT(test_tree1, prop_int, TEST_VALUE_1) -	PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1) +	PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L)  	PROP_STR(test_tree1, prop_str, TEST_STRING_1)  	PROP_INT(test_tree1, address_cells, 1)  	PROP_INT(test_tree1, size_cells, 0) @@ -102,6 +94,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 +134,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: @@ -213,8 +207,7 @@ bad_prop_char_end:  	/* overflow_size_strings */  	.balign	8 -	.globl	_ovf_size_strings -_ovf_size_strings: +	.globl	ovf_size_strings  ovf_size_strings:  	FDTLONG(FDT_MAGIC)  	FDTLONG(ovf_size_strings_end - ovf_size_strings) diff --git a/tests/truncated_property.c b/tests/truncated_property.c index f820d99e3f5d..71619bbce2a9 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -30,7 +30,7 @@  int main(int argc, char *argv[])  { -	void *fdt = &_truncated_property; +	void *fdt = &truncated_property;  	const void *prop;  	int len; diff --git a/tests/unit-addr-leading-0s.dts b/tests/unit-addr-leading-0s.dts new file mode 100644 index 000000000000..cc017e9431a2 --- /dev/null +++ b/tests/unit-addr-leading-0s.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { +	#address-cells = <1>; +	#size-cells = <1>; + +	bus { +		node@001 { +			reg = <1 0>; +		}; +	}; +}; diff --git a/tests/unit-addr-leading-0x.dts b/tests/unit-addr-leading-0x.dts new file mode 100644 index 000000000000..74f19678c98c --- /dev/null +++ b/tests/unit-addr-leading-0x.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { +	#address-cells = <1>; +	#size-cells = <1>; + +	bus { +		node@0x1 { +			reg = <1 0>; +		}; +	}; +}; diff --git a/tests/value-labels.c b/tests/value-labels.c index dcf20593d5c1..8aced74e28e7 100644 --- a/tests/value-labels.c +++ b/tests/value-labels.c @@ -36,13 +36,13 @@ struct val_label {  	int propoff;  }; -struct val_label labels1[] = { +static struct val_label labels1[] = {  	{ "start1", 0 },  	{ "mid1", 2 },  	{ "end1", -1 },  }; -struct val_label labels2[] = { +static struct val_label labels2[] = {  	{ "start2", 0 },  	{ "innerstart2", 0 },  	{ "innermid2", 4 }, @@ -50,7 +50,7 @@ struct val_label labels2[] = {  	{ "end2", -1 },  }; -struct val_label labels3[] = { +static struct val_label labels3[] = {  	{ "start3", 0 },  	{ "innerstart3", 0 },  	{ "innermid3", 1 }, diff --git a/treesource.c b/treesource.c index c9d8967969f9..2461a3d068a0 100644 --- a/treesource.c +++ b/treesource.c @@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)  static void write_propval_cells(FILE *f, struct data val)  {  	void *propend = val.val + val.len; -	cell_t *cp = (cell_t *)val.val; +	fdt32_t *cp = (fdt32_t *)val.val;  	struct marker *m = val.markers;  	fprintf(f, "<"); @@ -275,8 +275,8 @@ void dt_to_source(FILE *f, struct dt_info *dti)  		for_each_label(re->labels, l)  			fprintf(f, "%s: ", l->label);  		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", -			(unsigned long long)re->re.address, -			(unsigned long long)re->re.size); +			(unsigned long long)re->address, +			(unsigned long long)re->size);  	}  	write_tree_source_node(f, dti->dt, 0); @@ -396,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)  		} while (s < data + len);  	} else if ((len % 4) == 0) { -		const uint32_t *cell = (const uint32_t *)data; +		const fdt32_t *cell = (const fdt32_t *)data;  		printf(" = <");  		for (i = 0, len /= 4; i < len; i++) @@ -412,15 +412,16 @@ void utilfdt_print_data(const char *data, int len)  	}  } -void util_version(void) +void NORETURN util_version(void)  {  	printf("Version: %s\n", DTC_VERSION);  	exit(0);  } -void util_usage(const char *errmsg, const char *synopsis, -		const char *short_opts, struct option const long_opts[], -		const char * const opts_help[]) +void NORETURN util_usage(const char *errmsg, const char *synopsis, +			 const char *short_opts, +			 struct option const long_opts[], +			 const char * const opts_help[])  {  	FILE *fp = errmsg ? stderr : stdout;  	const char a_arg[] = "<arg>"; @@ -1,5 +1,5 @@ -#ifndef _UTIL_H -#define _UTIL_H +#ifndef UTIL_H +#define UTIL_H  #include <stdarg.h>  #include <stdbool.h> @@ -25,15 +25,20 @@   *                                                                   USA   */ -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -  #ifdef __GNUC__ -static inline void -__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) -die(const char *str, ...) +#define PRINTF(i, j)	__attribute__((format (printf, i, j))) +#define NORETURN	__attribute__((noreturn))  #else -static inline void die(const char *str, ...) +#define PRINTF(i, j) +#define NORETURN  #endif + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define stringify(s)	stringify_(s) +#define stringify_(s)	#s + +static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)  {  	va_list ap; @@ -66,12 +71,7 @@ static inline void *xrealloc(void *p, size_t len)  extern char *xstrdup(const char *s); -#ifdef __GNUC__ -extern int __attribute__((format (printf, 2, 3))) -xasprintf(char **strp, const char *fmt, ...); -#else -extern int xasprintf(char **strp, const char *fmt, ...); -#endif +extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);  extern char *join_path(const char *path, const char *name);  /** @@ -200,7 +200,7 @@ void utilfdt_print_data(const char *data, int len);  /**   * Show source version and exit   */ -void util_version(void) __attribute__((noreturn)); +void NORETURN util_version(void);  /**   * Show usage and exit @@ -214,9 +214,10 @@ void util_version(void) __attribute__((noreturn));   * @param long_opts	The structure of long options   * @param opts_help	An array of help strings (should align with long_opts)   */ -void util_usage(const char *errmsg, const char *synopsis, -		const char *short_opts, struct option const long_opts[], -		const char * const opts_help[]) __attribute__((noreturn)); +void NORETURN util_usage(const char *errmsg, const char *synopsis, +			 const char *short_opts, +			 struct option const long_opts[], +			 const char * const opts_help[]);  /**   * Show usage and exit @@ -262,4 +263,4 @@ void util_usage(const char *errmsg, const char *synopsis,  	case 'V': util_version(); \  	case '?': usage("unknown option"); -#endif /* _UTIL_H */ +#endif /* UTIL_H */ | 
