diff --git a/.cirrus.yml b/.cirrus.yml
index c270a09..d2dc34e 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,9 +1,9 @@
 env:
   CIRRUS_CLONE_DEPTH: 1
 
-freebsd_12_task:
+freebsd_13_task:
   freebsd_instance:
-    image: freebsd-12-1-release-amd64
+    image: freebsd-13-0-release-amd64
   install_script:
     pkg install -y bison gmake pkgconf
   build_script:
diff --git a/.gitignore b/.gitignore
index 8e332d8..416fa05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,7 @@ lex.yy.c
 # cscope files
 cscope.*
 ncscope.*
+
+.eggs/
+build/
+dist/
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index 97e53b9..cf4b253 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -712,7 +712,7 @@ The syntax of the fdtget command is:
 
 where options are:
 
-    <type>    s=string, i=int, u=unsigned, x=hex
+    <type>    s=string, i=int, u=unsigned, x=hex, r=raw
         Optional modifier prefix:
             hh or b=byte, h=2 byte, l=4 byte (default)
 
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..0eee931
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
+
+global-exclude *
+include README
+include GPL
+include BSD-2-Clause
+include setup.py
+include pylibfdt/libfdt.i
+include libfdt/libfdt.h
+include libfdt/fdt.h
+include libfdt/libfdt_env.h
diff --git a/Makefile b/Makefile
index ea8c659..ee77115 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ CONFIG_LOCALVERSION =
 ASSUME_MASK ?= 0
 
 CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
-WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
+WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
 	-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
 CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
 
diff --git a/README b/README
index d9bf850..a48312a 100644
--- a/README
+++ b/README
@@ -48,18 +48,24 @@ If you add new features, please check code coverage:
     # Open 'htmlcov/index.html' in your browser
 
 
-To install the library via the normal setup.py method, use:
+The library can be installed with pip from a local source tree:
 
-    ./pylibfdt/setup.py install [--prefix=/path/to/install_dir]
+    pip install . [--user|--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.
+Or directly from a remote git repo:
+
+    pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main
+
+The install depends on libfdt shared library being installed on the host system
+first. Generally, using --user or --prefix is not necessary and pip will use the
+default location for the Python installation which varies if the user is root or
+not.
+
+You can also install everything via make if you like, but pip is recommended.
 
 To install both libfdt and pylibfdt you can use:
 
-    make install [SETUP_PREFIX=/path/to/install_dir] \
-            [PREFIX=/path/to/install_dir]
+    make install [PREFIX=/path/to/install_dir]
 
 To disable building the python library, even if swig and Python are available,
 use:
@@ -71,6 +77,15 @@ More work remains to support all of libfdt, including access to numeric
 values.
 
 
+Adding a new function to libfdt.h
+---------------------------------
+
+The shared library uses libfdt/version.lds to list the exported functions, so
+add your new function there. Check that your function works with pylibfdt. If
+it cannot be supported, put the declaration in libfdt.h behind #ifndef SWIG so
+that swig ignores it.
+
+
 Tests
 -----
 
diff --git a/checks.c b/checks.c
index e6c7c3e..9f31d26 100644
--- a/checks.c
+++ b/checks.c
@@ -312,7 +312,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
 static void check_node_name_chars(struct check *c, struct dt_info *dti,
 				  struct node *node)
 {
-	int n = strspn(node->name, c->data);
+	size_t n = strspn(node->name, c->data);
 
 	if (n < strlen(node->name))
 		FAIL(c, dti, node, "Bad character '%c' in node name",
@@ -386,7 +386,7 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
 	struct property *prop;
 
 	for_each_property(node, prop) {
-		int n = strspn(prop->name, c->data);
+		size_t n = strspn(prop->name, c->data);
 
 		if (n < strlen(prop->name))
 			FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
@@ -403,7 +403,7 @@ static void check_property_name_chars_strict(struct check *c,
 
 	for_each_property(node, prop) {
 		const char *name = prop->name;
-		int n = strspn(name, c->data);
+		size_t n = strspn(name, c->data);
 
 		if (n == strlen(prop->name))
 			continue;
@@ -520,7 +520,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
 
 	phandle = propval_cell(prop);
 
-	if ((phandle == 0) || (phandle == -1)) {
+	if (!phandle_is_valid(phandle)) {
 		FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
 		     phandle, prop->name);
 		return 0;
@@ -579,7 +579,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
 	if (!prop)
 		return; /* No name property, that's fine */
 
-	if ((prop->val.len != node->basenamelen+1)
+	if ((prop->val.len != node->basenamelen + 1U)
 	    || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
 		FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
 		     " of base node name)", prop->val.val);
@@ -892,7 +892,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
 	} else {
 		cells = (cell_t *)prop->val.val;
 		min_bus = fdt32_to_cpu(cells[0]);
-		max_bus = fdt32_to_cpu(cells[0]);
+		max_bus = fdt32_to_cpu(cells[1]);
 	}
 	if ((bus_num < min_bus) || (bus_num > max_bus))
 		FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
@@ -1382,13 +1382,13 @@ struct provider {
 };
 
 static void check_property_phandle_args(struct check *c,
-					  struct dt_info *dti,
-				          struct node *node,
-				          struct property *prop,
-				          const struct provider *provider)
+					struct dt_info *dti,
+					struct node *node,
+					struct property *prop,
+					const struct provider *provider)
 {
 	struct node *root = dti->dt;
-	int cell, cellsize = 0;
+	unsigned int cell, cellsize = 0;
 
 	if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
 		FAIL_PROP(c, dti, node, prop,
@@ -1400,14 +1400,15 @@ static void check_property_phandle_args(struct check *c,
 	for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
 		struct node *provider_node;
 		struct property *cellprop;
-		int phandle;
+		cell_t phandle;
+		unsigned int expected;
 
 		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) {
+		if (!phandle_is_valid(phandle)) {
 			/* Give up if this is an overlay with external references */
 			if (dti->dtsflags & DTSF_PLUGIN)
 				break;
@@ -1450,10 +1451,12 @@ static void check_property_phandle_args(struct check *c,
 			break;
 		}
 
-		if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
+		expected = (cell + cellsize + 1) * sizeof(cell_t);
+		if ((expected <= cell) || prop->val.len < expected) {
 			FAIL_PROP(c, dti, node, prop,
-				  "property size (%d) too small for cell size %d",
+				  "property size (%d) too small for cell size %u",
 				  prop->val.len, cellsize);
+			break;
 		}
 	}
 }
@@ -1573,21 +1576,106 @@ static void check_interrupt_provider(struct check *c,
 				     struct node *node)
 {
 	struct property *prop;
+	bool irq_provider = node_is_interrupt_provider(node);
 
-	if (!node_is_interrupt_provider(node))
+	prop = get_property(node, "#interrupt-cells");
+	if (irq_provider && !prop) {
+		FAIL(c, dti, node,
+		     "Missing '#interrupt-cells' in interrupt provider");
 		return;
+	}
 
-	prop = get_property(node, "#interrupt-cells");
-	if (!prop)
+	if (!irq_provider && prop) {
 		FAIL(c, dti, node,
-		     "Missing #interrupt-cells in interrupt provider");
+		     "'#interrupt-cells' found, but node is not an interrupt provider");
+		return;
+	}
+}
+WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
 
-	prop = get_property(node, "#address-cells");
-	if (!prop)
+static void check_interrupt_map(struct check *c,
+				struct dt_info *dti,
+				struct node *node)
+{
+	struct node *root = dti->dt;
+	struct property *prop, *irq_map_prop;
+	size_t cellsize, cell, map_cells;
+
+	irq_map_prop = get_property(node, "interrupt-map");
+	if (!irq_map_prop)
+		return;
+
+	if (node->addr_cells < 0) {
 		FAIL(c, dti, node,
-		     "Missing #address-cells in interrupt provider");
+		     "Missing '#address-cells' in interrupt-map provider");
+		return;
+	}
+	cellsize = node_addr_cells(node);
+	cellsize += propval_cell(get_property(node, "#interrupt-cells"));
+
+	prop = get_property(node, "interrupt-map-mask");
+	if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
+		FAIL_PROP(c, dti, node, prop,
+			  "property size (%d) is invalid, expected %zu",
+			  prop->val.len, cellsize * sizeof(cell_t));
+
+	if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
+		FAIL_PROP(c, dti, node, irq_map_prop,
+			  "property size (%d) is invalid, expected multiple of %zu",
+			  irq_map_prop->val.len, sizeof(cell_t));
+		return;
+	}
+
+	map_cells = irq_map_prop->val.len / sizeof(cell_t);
+	for (cell = 0; cell < map_cells; ) {
+		struct node *provider_node;
+		struct property *cellprop;
+		int phandle;
+		size_t parent_cellsize;
+
+		if ((cell + cellsize) >= map_cells) {
+			FAIL_PROP(c, dti, node, irq_map_prop,
+				  "property size (%d) too small, expected > %zu",
+				  irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
+			break;
+		}
+		cell += cellsize;
+
+		phandle = propval_cell_n(irq_map_prop, cell);
+		if (!phandle_is_valid(phandle)) {
+			/* Give up if this is an overlay with external references */
+			if (!(dti->dtsflags & DTSF_PLUGIN))
+				FAIL_PROP(c, dti, node, irq_map_prop,
+					  "Cell %zu is not a phandle(%d)",
+					  cell, phandle);
+			break;
+		}
+
+		provider_node = get_node_by_phandle(root, phandle);
+		if (!provider_node) {
+			FAIL_PROP(c, dti, node, irq_map_prop,
+				  "Could not get phandle(%d) node for (cell %zu)",
+				  phandle, cell);
+			break;
+		}
+
+		cellprop = get_property(provider_node, "#interrupt-cells");
+		if (cellprop) {
+			parent_cellsize = propval_cell(cellprop);
+		} else {
+			FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
+			     provider_node->fullpath, cell);
+			break;
+		}
+
+		cellprop = get_property(provider_node, "#address-cells");
+		if (cellprop)
+			parent_cellsize += propval_cell(cellprop);
+
+		cell += 1 + parent_cellsize;
+	}
 }
-WARNING(interrupt_provider, check_interrupt_provider, NULL);
+WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
 
 static void check_interrupts_property(struct check *c,
 				      struct dt_info *dti,
@@ -1596,7 +1684,7 @@ static void check_interrupts_property(struct check *c,
 	struct node *root = dti->dt;
 	struct node *irq_node = NULL, *parent = node;
 	struct property *irq_prop, *prop = NULL;
-	int irq_cells, phandle;
+	cell_t irq_cells, phandle;
 
 	irq_prop = get_property(node, "interrupts");
 	if (!irq_prop)
@@ -1615,7 +1703,7 @@ static void check_interrupts_property(struct check *c,
 		prop = get_property(parent, "interrupt-parent");
 		if (prop) {
 			phandle = propval_cell(prop);
-			if ((phandle == 0) || (phandle == -1)) {
+			if (!phandle_is_valid(phandle)) {
 				/* Give up if this is an overlay with
 				 * external references */
 				if (dti->dtsflags & DTSF_PLUGIN)
@@ -1762,7 +1850,7 @@ WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
 static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
 					struct node *endpoint)
 {
-	int phandle;
+	cell_t phandle;
 	struct node *node;
 	struct property *prop;
 
@@ -1772,7 +1860,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
 
 	phandle = propval_cell(prop);
 	/* Give up if this is an overlay with external references */
-	if (phandle == 0 || phandle == -1)
+	if (!phandle_is_valid(phandle))
 		return NULL;
 
 	node = get_node_by_phandle(dti->dt, phandle);
@@ -1887,6 +1975,7 @@ static struct check *check_table[] = {
 	&gpios_property,
 	&interrupts_property,
 	&interrupt_provider,
+	&interrupt_map,
 
 	&alias_paths,
 
@@ -1910,7 +1999,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
 
 static void disable_warning_error(struct check *c, bool warn, bool error)
 {
-	int i;
+	unsigned int i;
 
 	/* Lowering level, also lower it for things this is the prereq
 	 * for */
@@ -1931,7 +2020,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
 
 void parse_checks_option(bool warn, bool error, const char *arg)
 {
-	int i;
+	unsigned int i;
 	const char *name = arg;
 	bool enable = true;
 
@@ -1958,7 +2047,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
 
 void process_checks(bool force, struct dt_info *dti)
 {
-	int i;
+	unsigned int i;
 	int error = 0;
 
 	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 5568b4a..de60a70 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -200,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
 			return DT_LABEL_REF;
 		}
 
-<*>"&{/"{PATHCHAR}*\}	{	/* new-style path reference */
+<*>"&{"{PATHCHAR}*\}	{	/* new-style path reference */
 			yytext[yyleng-1] = '\0';
 			DPRINT("Ref: %s\n", yytext+2);
 			yylval.labelref = xstrdup(yytext+2);
diff --git a/dtc-parser.y b/dtc-parser.y
index a0316a3..46457d4 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -23,6 +23,12 @@ extern void yyerror(char const *s);
 
 extern struct dt_info *parser_output;
 extern bool treesource_error;
+
+static bool is_ref_relative(const char *ref)
+{
+	return ref[0] != '/' && strchr(&ref[1], '/');
+}
+
 %}
 
 %union {
@@ -169,6 +175,8 @@ devicetree:
 			 */
 			if (!($<flags>-1 & DTSF_PLUGIN))
 				ERROR(&@2, "Label or path %s not found", $1);
+			else if (is_ref_relative($1))
+				ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
 			$$ = add_orphan_node(
 					name_node(build_node(NULL, NULL, NULL),
 						  ""),
@@ -178,6 +186,9 @@ devicetree:
 		{
 			struct node *target = get_node_by_ref($1, $3);
 
+			if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
+				ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
+
 			if (target) {
 				add_label(&target->labels, $2);
 				merge_nodes(target, $4);
@@ -193,6 +204,8 @@ devicetree:
 			 * so $-1 is what we want (plugindecl)
 			 */
 			if ($<flags>-1 & DTSF_PLUGIN) {
+				if (is_ref_relative($2))
+					ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
 				add_orphan_node($1, $3, $2);
 			} else {
 				struct node *target = get_node_by_ref($1, $2);
diff --git a/dtc.c b/dtc.c
index 3962d3f..bc786c5 100644
--- a/dtc.c
+++ b/dtc.c
@@ -12,7 +12,7 @@
  * Command line options
  */
 int quiet;		/* Level of quietness */
-int reservenum;		/* Number of memory reservation slots */
+unsigned 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 */
@@ -197,7 +197,7 @@ int main(int argc, char *argv[])
 			depname = optarg;
 			break;
 		case 'R':
-			reservenum = strtol(optarg, NULL, 0);
+			reservenum = strtoul(optarg, NULL, 0);
 			break;
 		case 'S':
 			minsize = strtol(optarg, NULL, 0);
diff --git a/dtc.h b/dtc.h
index 6296361..0a1f549 100644
--- a/dtc.h
+++ b/dtc.h
@@ -35,7 +35,7 @@
  * Command line options
  */
 extern int quiet;		/* Level of quietness */
-extern int reservenum;		/* Number of memory reservation slots */
+extern unsigned int reservenum;	/* Number of memory reservation slots */
 extern int minsize;		/* Minimum blob size */
 extern int padsize;		/* Additional padding to blob */
 extern int alignsize;		/* Additional padding to blob accroding to the alignsize */
@@ -51,6 +51,11 @@ extern int annotate;		/* annotate .dts with input source location */
 
 typedef uint32_t cell_t;
 
+static inline bool phandle_is_valid(cell_t phandle)
+{
+	return phandle != 0 && phandle != ~0U;
+}
+
 static inline uint16_t dtb_ld16(const void *p)
 {
 	const uint8_t *bp = (const uint8_t *)p;
@@ -111,6 +116,12 @@ enum markertype {
 	TYPE_UINT64,
 	TYPE_STRING,
 };
+
+static inline bool is_type_marker(enum markertype type)
+{
+	return type >= TYPE_UINT8;
+}
+
 extern const char *markername(enum markertype markertype);
 
 struct  marker {
@@ -135,7 +146,22 @@ struct data {
 	for_each_marker(m) \
 		if ((m)->type == (t))
 
-size_t type_marker_length(struct marker *m);
+static inline struct marker *next_type_marker(struct marker *m)
+{
+	for_each_marker(m)
+		if (is_type_marker(m->type))
+			break;
+	return m;
+}
+
+static inline size_t type_marker_length(struct marker *m)
+{
+	struct marker *next = next_type_marker(m->next);
+
+	if (next)
+		return next->offset - m->offset;
+	return 0;
+}
 
 void data_free(struct data d);
 
diff --git a/fdtdump.c b/fdtdump.c
index d9fb374..d424869 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -18,10 +18,10 @@
 #include "util.h"
 
 #define FDT_MAGIC_SIZE	4
-#define MAX_VERSION 17
+#define MAX_VERSION 17U
 
 #define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))
-#define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
+#define PALIGN(p, a)	((void *)(ALIGN((uintptr_t)(p), (a))))
 #define GET_CELL(p)	(p += 4, *((const fdt32_t *)(p-4)))
 
 static const char *tagname(uint32_t tag)
@@ -163,7 +163,7 @@ static const char * const usage_opts_help[] = {
 	USAGE_COMMON_OPTS_HELP
 };
 
-static bool valid_header(char *p, off_t len)
+static bool valid_header(char *p, size_t len)
 {
 	if (len < sizeof(struct fdt_header) ||
 	    fdt_magic(p) != FDT_MAGIC ||
@@ -235,7 +235,7 @@ int main(int argc, char *argv[])
 			}
 			++p;
 		}
-		if (!p || endp - p < sizeof(struct fdt_header))
+		if (!p || (size_t)(endp - p) < sizeof(struct fdt_header))
 			die("%s: could not locate fdt magic\n", file);
 		printf("%s: found fdt at offset %#tx\n", file, p - buf);
 		buf = p;
diff --git a/fdtget.c b/fdtget.c
index 777582e..dd70985 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -62,8 +62,14 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
 	for (i = 0; i < len; i += size, p += size) {
 		if (i)
 			printf(" ");
-		value = size == 4 ? fdt32_ld((const fdt32_t *)p) :
-			size == 2 ? (*p << 8) | p[1] : *p;
+		switch (size) {
+		case 4: value = fdt32_ld((const fdt32_t *)p); break;
+		case 2: value = fdt16_ld((const fdt16_t *)p); break;
+		case 1:
+		default:
+			value = *p;
+			break;
+		}
 		printf(fmt, value);
 	}
 
@@ -91,6 +97,11 @@ static int show_data(struct display_info *disp, const char *data, int len)
 	if (len == 0)
 		return 0;
 
+	if (disp->type == 'r') {
+		fwrite(data, 1, len, stdout);
+		return 0;
+	}
+
 	is_string = (disp->type) == 's' ||
 		(!disp->type && util_is_printable_string(data, len));
 	if (is_string) {
diff --git a/fdtput.c b/fdtput.c
index 428745a..c2fecf4 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -433,6 +433,8 @@ int main(int argc, char *argv[])
 			if (utilfdt_decode_type(optarg, &disp.type,
 					&disp.size))
 				usage("Invalid type string");
+			if (disp.type == 'r')
+				usage("Unsupported raw data type");
 			break;
 
 		case 'v':
diff --git a/flattree.c b/flattree.c
index 4659afb..95e43d3 100644
--- a/flattree.c
+++ b/flattree.c
@@ -124,7 +124,8 @@ static void asm_emit_cell(void *e, cell_t val)
 {
 	FILE *f = e;
 
-	fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
+	fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
+		"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
 		(val >> 24) & 0xff, (val >> 16) & 0xff,
 		(val >> 8) & 0xff, val & 0xff);
 }
@@ -134,9 +135,9 @@ static void asm_emit_string(void *e, const char *str, int len)
 	FILE *f = e;
 
 	if (len != 0)
-		fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
+		fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
 	else
-		fprintf(f, "\t.string\t\"%s\"\n", str);
+		fprintf(f, "\t.asciz\t\"%s\"\n", str);
 }
 
 static void asm_emit_align(void *e, int a)
@@ -295,7 +296,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
 {
 	struct reserve_info *re;
 	struct data d = empty_data;
-	int    j;
+	unsigned int j;
 
 	for (re = reservelist; re; re = re->next) {
 		d = data_append_re(d, re->address, re->size);
@@ -438,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
 
 	while (p < (strbuf.val + strbuf.len)) {
 		len = strlen(p);
-		fprintf(f, "\t.string \"%s\"\n", p);
+		fprintf(f, "\t.asciz \"%s\"\n", p);
 		p += len+1;
 	}
 }
diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c
index 9a82cd0..c40ba09 100644
--- a/libfdt/fdt_addresses.c
+++ b/libfdt/fdt_addresses.c
@@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
 	/* check validity of address */
 	prop = data;
 	if (addr_cells == 1) {
-		if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+		if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
 			return -FDT_ERR_BADVALUE;
 
 		fdt32_st(prop, (uint32_t)addr);
diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c
index d217e79..5c0c398 100644
--- a/libfdt/fdt_overlay.c
+++ b/libfdt/fdt_overlay.c
@@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
 	return fdt32_to_cpu(*val);
 }
 
-/**
- * overlay_get_target - retrieves the offset of a fragment's target
- * @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 targeting is
- * done (through a phandle or a path)
- *
- * returns:
- *      the targeted node offset in the base device tree
- *      Negative error code on error
- */
-static int overlay_get_target(const void *fdt, const void *fdto,
-			      int fragment, char const **pathp)
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+			      int fragment_offset, char const **pathp)
 {
 	uint32_t phandle;
 	const char *path = NULL;
 	int path_len = 0, ret;
 
 	/* Try first to do a phandle based lookup */
-	phandle = overlay_get_target_phandle(fdto, fragment);
+	phandle = overlay_get_target_phandle(fdto, fragment_offset);
 	if (phandle == (uint32_t)-1)
 		return -FDT_ERR_BADPHANDLE;
 
 	/* no phandle, try path */
 	if (!phandle) {
 		/* And then a path based lookup */
-		path = fdt_getprop(fdto, fragment, "target-path", &path_len);
+		path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
 		if (path)
 			ret = fdt_path_offset(fdt, path);
 		else
@@ -636,7 +621,7 @@ static int overlay_merge(void *fdt, void *fdto)
 		if (overlay < 0)
 			return overlay;
 
-		target = overlay_get_target(fdt, fdto, fragment, NULL);
+		target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
 		if (target < 0)
 			return target;
 
@@ -779,7 +764,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
 			return -FDT_ERR_BADOVERLAY;
 
 		/* get the target of the fragment */
-		ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+		ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
 		if (ret < 0)
 			return ret;
 		target = ret;
@@ -801,7 +786,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
 
 		if (!target_path) {
 			/* again in case setprop_placeholder changed it */
-			ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+			ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
 			if (ret < 0)
 				return ret;
 			target = ret;
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index 17584da..9f6c551 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -481,12 +481,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
 		if (!can_assume(VALID_INPUT)) {
 			name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
 					      &namelen);
+			*namep = name;
 			if (!name) {
 				if (lenp)
 					*lenp = namelen;
 				return NULL;
 			}
-			*namep = name;
 		} else {
 			*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
 		}
diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c
index b435693..d852b77 100644
--- a/libfdt/fdt_strerror.c
+++ b/libfdt/fdt_strerror.c
@@ -39,6 +39,7 @@ static struct fdt_errtabent fdt_errtable[] = {
 	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
 	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
 	FDT_ERRTABENT(FDT_ERR_BADFLAGS),
+	FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
 };
 #define FDT_ERRTABSIZE	((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
 
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 73467f7..a7f432c 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -131,6 +131,13 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
  * to work even with unaligned pointers on platforms (such as ARMv5) that don't
  * like unaligned loads and stores.
  */
+static inline uint16_t fdt16_ld(const fdt16_t *p)
+{
+	const uint8_t *bp = (const uint8_t *)p;
+
+	return ((uint16_t)bp[0] << 8) | bp[1];
+}
+
 static inline uint32_t fdt32_ld(const fdt32_t *p)
 {
 	const uint8_t *bp = (const uint8_t *)p;
@@ -2109,6 +2116,24 @@ int fdt_del_node(void *fdt, int nodeoffset);
  */
 int fdt_overlay_apply(void *fdt, void *fdto);
 
+/**
+ * fdt_overlay_target_offset - retrieves the offset of a fragment's target
+ * @fdt: Base device tree blob
+ * @fdto: Device tree overlay blob
+ * @fragment_offset: node offset of the fragment in the overlay
+ * @pathp: pointer which receives the path of the target (or NULL)
+ *
+ * fdt_overlay_target_offset() retrieves the target offset in the base
+ * device tree of a fragment, no matter how the actual targeting is
+ * done (through a phandle or a path)
+ *
+ * returns:
+ *      the targeted node offset in the base device tree
+ *      Negative error code on error
+ */
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+			      int fragment_offset, char const **pathp);
+
 /**********************************************************************/
 /* Debugging / informational functions                                */
 /**********************************************************************/
diff --git a/libfdt/meson.build b/libfdt/meson.build
index 0307ffb..71f29b6 100644
--- a/libfdt/meson.build
+++ b/libfdt/meson.build
@@ -24,6 +24,11 @@ libfdt = library(
   install: true,
 )
 
+libfdt_a = static_library(
+  'fdt', sources,
+  install: true,
+)
+
 libfdt_inc = include_directories('.')
 
 libfdt_dep = declare_dependency(
diff --git a/libfdt/version.lds b/libfdt/version.lds
index 7ab85f1..cbce5d4 100644
--- a/libfdt/version.lds
+++ b/libfdt/version.lds
@@ -77,6 +77,7 @@ LIBFDT_1.2 {
 		fdt_appendprop_addrrange;
 		fdt_setprop_inplace_namelen_partial;
 		fdt_create_with_flags;
+		fdt_overlay_target_offset;
 	local:
 		*;
 };
diff --git a/livetree.c b/livetree.c
index 7eacd02..169462d 100644
--- a/livetree.c
+++ b/livetree.c
@@ -526,7 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
 	p = strchr(path, '/');
 
 	for_each_child(tree, child) {
-		if (p && strprefixeq(path, p - path, child->name))
+		if (p && strprefixeq(path, (size_t)(p - path), child->name))
 			return get_node_by_path(child, p+1);
 		else if (!p && streq(path, child->name))
 			return child;
@@ -559,7 +559,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
 {
 	struct node *child, *node;
 
-	if ((phandle == 0) || (phandle == -1)) {
+	if (!phandle_is_valid(phandle)) {
 		assert(generate_fixups);
 		return NULL;
 	}
@@ -581,12 +581,39 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
 
 struct node *get_node_by_ref(struct node *tree, const char *ref)
 {
+	struct node *target = tree;
+	const char *label = NULL, *path = NULL;
+
 	if (streq(ref, "/"))
 		return tree;
-	else if (ref[0] == '/')
-		return get_node_by_path(tree, ref);
+
+	if (ref[0] == '/')
+		path = ref;
 	else
-		return get_node_by_label(tree, ref);
+		label = ref;
+
+	if (label) {
+		const char *slash = strchr(label, '/');
+		char *buf = NULL;
+
+		if (slash) {
+			buf = xstrndup(label, slash - label);
+			label = buf;
+			path = slash + 1;
+		}
+
+		target = get_node_by_label(tree, label);
+
+		free(buf);
+
+		if (!target)
+			return NULL;
+	}
+
+	if (path)
+		target = get_node_by_path(target, path);
+
+	return target;
 }
 
 cell_t get_node_phandle(struct node *root, struct node *node)
@@ -594,7 +621,7 @@ cell_t get_node_phandle(struct node *root, struct node *node)
 	static cell_t phandle = 1; /* FIXME: ick, static local */
 	struct data d = empty_data;
 
-	if ((node->phandle != 0) && (node->phandle != -1))
+	if (phandle_is_valid(node->phandle))
 		return node->phandle;
 
 	while (get_node_by_phandle(root, phandle))
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
index 1b5f236..82f565e 100644
--- a/pylibfdt/Makefile.pylibfdt
+++ b/pylibfdt/Makefile.pylibfdt
@@ -9,14 +9,13 @@ PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%)
 PYLIBFDT_CLEANDIRS_L = build __pycache__
 PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%)
 
-SETUP = $(PYLIBFDT_dir)/setup.py
-SETUPFLAGS = --top-builddir .
+SETUP = ./setup.py
 
 ifndef V
 SETUPFLAGS += --quiet
 endif
 
-$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE)
+$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP)
 	@$(VECHO) PYMOD $@
 	$(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_dir)
 
diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i
index 51ee801..f9f7e7e 100644
--- a/pylibfdt/libfdt.i
+++ b/pylibfdt/libfdt.i
@@ -443,6 +443,29 @@ class FdtRo(object):
         """
         return fdt_get_alias(self._fdt, name)
 
+    def get_path(self, nodeoffset, quiet=()):
+        """Get the full path of a node
+
+        Args:
+            nodeoffset: Node offset to check
+
+        Returns:
+            Full path to the node
+
+        Raises:
+            FdtException if an error occurs
+        """
+        size = 1024
+        while True:
+            ret, path = fdt_get_path(self._fdt, nodeoffset, size)
+            if ret == -NOSPACE:
+                size = size * 2
+                continue
+            err = check_err(ret, quiet)
+            if err:
+                return err
+            return path
+
     def parent_offset(self, nodeoffset, quiet=()):
         """Get the offset of a node's parent
 
@@ -716,6 +739,21 @@ class Property(bytearray):
     def as_int64(self):
         return self.as_cell('q')
 
+    def as_list(self, fmt):
+        return list(map(lambda x: x[0], struct.iter_unpack('>' + fmt, self)))
+
+    def as_uint32_list(self):
+        return self.as_list('L')
+
+    def as_int32_list(self):
+        return self.as_list('l')
+
+    def as_uint64_list(self):
+        return self.as_list('Q')
+
+    def as_int64_list(self):
+        return self.as_list('q')
+
     def as_str(self):
         """Unicode is supported by decoding from UTF-8"""
         if self[-1] != 0:
@@ -724,6 +762,13 @@ class Property(bytearray):
             raise ValueError('Property contains embedded nul characters')
         return self[:-1].decode('utf-8')
 
+    def as_stringlist(self):
+        """Unicode is supported by decoding from UTF-8"""
+        if self[-1] != 0:
+            raise ValueError('Property lacks nul termination')
+        parts = self[:-1].split(b'\x00')
+        return list(map(lambda x: x.decode('utf-8'), parts))
+
 
 class FdtSw(FdtRo):
     """Software interface to create a device tree from scratch
@@ -1040,14 +1085,16 @@ typedef uint32_t fdt32_t;
 
 /* typemap used for fdt_getprop() */
 %typemap(out) (const void *) {
-	if (!$1)
+	if (!$1) {
 		$result = Py_None;
-	else
+		Py_INCREF($result);
+	} else {
         %#if PY_VERSION_HEX >= 0x03000000
-            $result = Py_BuildValue("y#", $1, *arg4);
+            $result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4);
         %#else
-            $result = Py_BuildValue("s#", $1, *arg4);
+            $result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4);
         %#endif
+    }
 }
 
 /* typemap used for fdt_setprop() */
@@ -1091,6 +1138,11 @@ typedef uint32_t fdt32_t;
         }
 }
 
+%include "cstring.i"
+
+%cstring_output_maxsize(char *buf, int buflen);
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
 /* We have both struct fdt_property and a function fdt_property() */
 %warnfilter(302) fdt_property;
 
diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build
index 088f249..f684cbb 100644
--- a/pylibfdt/meson.build
+++ b/pylibfdt/meson.build
@@ -1,11 +1,10 @@
-setup_py = find_program('setup.py')
-setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.current_build_dir() / '..']
+setup_py = find_program('../setup.py')
+setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.project_build_root()]
 
 custom_target(
   'pylibfdt',
   input: 'libfdt.i',
   output: '_libfdt.so',
-  depends: version_gen_h,
   command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()],
   build_by_default: true,
 )
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
deleted file mode 100755
index ef40f15..0000000
--- a/pylibfdt/setup.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
-
-# While Python 3 is the default, it's also possible to invoke
-# this setup.py script with Python 2.
-
-"""
-setup.py file for SWIG libfdt
-Copyright (C) 2017 Google, Inc.
-Written by Simon Glass <sjg@chromium.org>
-"""
-
-from distutils.core import setup, Extension
-import os
-import re
-import sys
-
-
-VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$'
-
-
-def get_top_builddir():
-    if '--top-builddir' in sys.argv:
-        index = sys.argv.index('--top-builddir')
-        sys.argv.pop(index)
-        return sys.argv.pop(index)
-    else:
-        return os.getcwd()
-
-
-srcdir = os.path.dirname(os.path.abspath(sys.argv[0]))
-top_builddir = get_top_builddir()
-
-
-def get_version():
-    version_file = os.path.join(top_builddir, 'version_gen.h')
-    f = open(version_file, 'rt')
-    m = re.match(VERSION_PATTERN, f.readline())
-    return m.group(1)
-
-
-libfdt_module = Extension(
-    '_libfdt',
-    sources=[os.path.join(srcdir, 'libfdt.i')],
-    include_dirs=[os.path.join(srcdir, '../libfdt')],
-    libraries=['fdt'],
-    library_dirs=[os.path.join(top_builddir, 'libfdt')],
-    swig_opts=['-I' + os.path.join(srcdir, '../libfdt')],
-)
-
-setup(
-    name='libfdt',
-    version=get_version(),
-    author='Simon Glass <sjg@chromium.org>',
-    description='Python binding for libfdt',
-    ext_modules=[libfdt_module],
-    package_dir={'': srcdir},
-    py_modules=['libfdt'],
-)
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..a8e54a3
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
+
+# While Python 3 is the default, it's also possible to invoke
+# this setup.py script with Python 2.
+
+"""
+setup.py file for SWIG libfdt
+Copyright (C) 2017 Google, Inc.
+Written by Simon Glass <sjg@chromium.org>
+"""
+
+from setuptools import setup, Extension
+from setuptools.command.build_py import build_py as _build_py
+
+import os
+import re
+import sys
+
+srcdir = os.path.dirname(__file__)
+
+with open(os.path.join(srcdir, "README"), "r") as fh:
+    long_description = fh.read()
+
+def get_top_builddir():
+    if '--top-builddir' in sys.argv:
+        index = sys.argv.index('--top-builddir')
+        sys.argv.pop(index)
+        return sys.argv.pop(index)
+    else:
+        return srcdir
+
+top_builddir = get_top_builddir()
+
+libfdt_module = Extension(
+    '_libfdt',
+    sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')],
+    define_macros=[('PY_SSIZE_T_CLEAN', None)],
+    include_dirs=[os.path.join(srcdir, 'libfdt')],
+    libraries=['fdt'],
+    library_dirs=[os.path.join(top_builddir, 'libfdt')],
+    swig_opts=['-I' + os.path.join(srcdir, 'libfdt')],
+)
+
+class build_py(_build_py):
+    def run(self):
+        self.run_command("build_ext")
+        return super().run()
+
+setup(
+    name='libfdt',
+    use_scm_version={
+        "root": srcdir,
+    },
+    cmdclass = {'build_py' : build_py},
+    setup_requires = ['setuptools_scm'],
+    author='Simon Glass',
+    author_email='sjg@chromium.org',
+    description='Python binding for libfdt',
+    ext_modules=[libfdt_module],
+    package_dir={'': os.path.join(srcdir, 'pylibfdt')},
+    py_modules=['libfdt'],
+
+    long_description=long_description,
+    long_description_content_type="text/plain",
+    url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git",
+    license="BSD",
+    license_files=["GPL", "BSD-2-Clause"],
+
+    classifiers=[
+        "Programming Language :: Python :: 3",
+        "License :: OSI Approved :: BSD License",
+        "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)",
+        "Operating System :: OS Independent",
+    ],
+
+)
diff --git a/tests/.gitignore b/tests/.gitignore
index d3f1434..03bdde2 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -54,6 +54,7 @@ tmp.*
 /property_iterate
 /propname_escapes
 /references
+/relref_merge
 /root_node
 /rw_tree1
 /rw_oom
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 2b47627..2f78952 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -18,7 +18,7 @@ LIB_TESTS_L = get_mem_rsv \
 	open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
 	appendprop1 appendprop2 propname_escapes \
 	string_escapes references path-references phandle_format \
-	boot-cpuid incbin \
+	boot-cpuid incbin relref_merge \
 	extra-terminating-null \
 	dtbs_equal_ordered \
 	dtb_reverse dtbs_equal_unordered \
diff --git a/tests/bad-interrupt-map-mask.dts b/tests/bad-interrupt-map-mask.dts
new file mode 100644
index 0000000..10eaffd
--- /dev/null
+++ b/tests/bad-interrupt-map-mask.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+
+/ {
+	interrupt-parent = <&intc>;
+	intc: interrupt-controller {
+		#interrupt-cells = <3>;
+		interrupt-controller;
+	};
+
+	node {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-map = <1 &intc 1 2 3>;
+		interrupt-map-mask = <0 0>;
+
+		child {
+			interrupts = <1>;
+		};
+	};
+};
diff --git a/tests/bad-interrupt-map-parent.dts b/tests/bad-interrupt-map-parent.dts
new file mode 100644
index 0000000..fe88ce2
--- /dev/null
+++ b/tests/bad-interrupt-map-parent.dts
@@ -0,0 +1,17 @@
+/dts-v1/;
+
+/ {
+	interrupt-parent = <&intc>;
+	intc: interrupt-controller {
+	};
+
+	node {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-map = <1 &intc 1 2 3>;
+
+		child {
+			interrupts = <1>;
+		};
+	};
+};
diff --git a/tests/bad-interrupt-map.dts b/tests/bad-interrupt-map.dts
new file mode 100644
index 0000000..6df8f93
--- /dev/null
+++ b/tests/bad-interrupt-map.dts
@@ -0,0 +1,19 @@
+/dts-v1/;
+
+/ {
+	interrupt-parent = <&intc>;
+	intc: interrupt-controller {
+		#interrupt-cells = <3>;
+		interrupt-controller;
+	};
+
+	node {
+		/* Missing #address-cells = <0>; */
+		#interrupt-cells = <1>;
+		interrupt-map = <1 &intc 1 2 3>;
+
+		child {
+			interrupts = <1>;
+		};
+	};
+};
diff --git a/tests/base01.asm b/tests/base01.asm
index 266e446..63f2eca 100644
--- a/tests/base01.asm
+++ b/tests/base01.asm
@@ -32,7 +32,7 @@ _dt_reserve_map:
 dt_struct_start:
 _dt_struct_start:
 	.long	OF_DT_BEGIN_NODE
-	.string	""
+	.asciz	""
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0xa
@@ -58,7 +58,7 @@ _dt_struct_start:
 	.long	0x2
 	.balign	4
 	.long	OF_DT_BEGIN_NODE
-	.string	"memory@0"
+	.asciz	"memory@0"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0x7
@@ -77,7 +77,7 @@ _dt_struct_start:
 	.balign	4
 	.long	OF_DT_END_NODE
 	.long	OF_DT_BEGIN_NODE
-	.string	"cpus"
+	.asciz	"cpus"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0x4
@@ -151,22 +151,22 @@ _dt_struct_end:
 	.globl	dt_strings_start
 dt_strings_start:
 _dt_strings_start:
-	.string "model"
-	.string "compatible"
-	.string "#address-cells"
-	.string "#size-cells"
-	.string "device_type"
-	.string "reg"
-	.string "d10"
-	.string "d23"
-	.string "b101"
-	.string "o17"
-	.string "hd00d"
-	.string "stuff"
-	.string "bad-d-1"
-	.string "bad-d-2"
-	.string "bad-o-1"
-	.string "bad-o-2"
+	.asciz	"model"
+	.asciz	"compatible"
+	.asciz	"#address-cells"
+	.asciz	"#size-cells"
+	.asciz	"device_type"
+	.asciz	"reg"
+	.asciz	"d10"
+	.asciz	"d23"
+	.asciz	"b101"
+	.asciz	"o17"
+	.asciz	"hd00d"
+	.asciz	"stuff"
+	.asciz	"bad-d-1"
+	.asciz	"bad-d-2"
+	.asciz	"bad-o-1"
+	.asciz	"bad-o-2"
 	.globl	dt_strings_end
 dt_strings_end:
 _dt_strings_end:
diff --git a/tests/dumptrees.c b/tests/dumptrees.c
index f1e0ea9..08967b3 100644
--- a/tests/dumptrees.c
+++ b/tests/dumptrees.c
@@ -32,7 +32,7 @@ static struct {
 
 int main(int argc, char *argv[])
 {
-	int i;
+	unsigned int i;
 
 	if (argc != 2) {
 	    fprintf(stderr, "Missing output directory argument\n");
diff --git a/tests/fs_tree1.c b/tests/fs_tree1.c
index dff3880..978f6a3 100644
--- a/tests/fs_tree1.c
+++ b/tests/fs_tree1.c
@@ -54,7 +54,7 @@ static void mkfile(const char *name, void *data, size_t len)
 	rc = write(fd, data, len);
 	if (rc < 0)
 		FAIL("write(\"%s\"): %s", name, strerror(errno));
-	if (rc != len)
+	if ((unsigned)rc != len)
 		FAIL("write(\"%s\"): short write", name);
 	
 	rc = close(fd);
diff --git a/tests/get_name.c b/tests/get_name.c
index 5a35103..d20bf30 100644
--- a/tests/get_name.c
+++ b/tests/get_name.c
@@ -34,12 +34,14 @@ static void check_name(void *fdt, const char *path)
 		       offset, getname, len);
 	if (!getname)
 		FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
+	if (len < 0)
+		FAIL("negative name length (%d) for returned node name\n", len);
 
 	if (strcmp(getname, checkname) != 0)
 		FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
 		     path, getname, checkname);
 
-	if (len != strlen(getname))
+	if ((unsigned)len != strlen(getname))
 		FAIL("fdt_get_name(%s) returned length %d instead of %zd",
 		     path, len, strlen(getname));
 
diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c
index 6f33d81..2f164d9 100644
--- a/tests/integer-expressions.c
+++ b/tests/integer-expressions.c
@@ -59,7 +59,7 @@ int main(int argc, char *argv[])
 	void *fdt;
 	const fdt32_t *res;
 	int reslen;
-	int i;
+	unsigned int i;
 
 	test_init(argc, argv);
 
diff --git a/tests/nopulate.c b/tests/nopulate.c
index 2ae1753..e06a0b3 100644
--- a/tests/nopulate.c
+++ b/tests/nopulate.c
@@ -43,7 +43,8 @@ static int nopulate_struct(char *buf, const char *fdt)
 int main(int argc, char *argv[])
 {
 	char *fdt, *fdt2, *buf;
-	int newsize, struct_start, struct_end_old, struct_end_new, delta;
+	int newsize, struct_end_old, struct_end_new, delta;
+	unsigned int struct_start;
 	const char *inname;
 	char outname[PATH_MAX];
 
diff --git a/tests/overlay.c b/tests/overlay.c
index 91afa72..f3dd310 100644
--- a/tests/overlay.c
+++ b/tests/overlay.c
@@ -35,7 +35,11 @@ static int fdt_getprop_u32_by_poffset(void *fdt, const char *path,
 		return node_off;
 
 	val = fdt_getprop(fdt, node_off, name, &len);
-	if (!val || (len < (sizeof(uint32_t) * (poffset + 1))))
+	if (val && len < 0)
+		FAIL("fdt_getprop() returns negative length");
+	if (!val && len < 0)
+		return len;
+	if (!val || ((unsigned)len < (sizeof(uint32_t) * (poffset + 1))))
 		return -FDT_ERR_NOTFOUND;
 
 	*out = fdt32_to_cpu(*(val + poffset));
diff --git a/tests/path-references.c b/tests/path-references.c
index 4db61a5..b914576 100644
--- a/tests/path-references.c
+++ b/tests/path-references.c
@@ -53,7 +53,7 @@ int main(int argc, char *argv[])
 	void *fdt;
 	const char *p;
 	int len, multilen;
-	int n1, n2, n3, n4;
+	int n1, n2, n3, n4, n5;
 
 	test_init(argc, argv);
 	fdt = load_blob_arg(argc, argv);
@@ -89,6 +89,12 @@ int main(int argc, char *argv[])
 	check_ref(fdt, n3, "/foobar/baz");
 	check_ref(fdt, n4, "/foo/baz");
 
+	n5 = fdt_path_offset(fdt, "/bar/baz");
+	if (n5 < 0)
+		FAIL("fdt_path_offset(/bar/baz): %s", fdt_strerror(n5));
+
+	check_ref(fdt, n5, "/bar/baz");
+
 	check_rref(fdt);
 
 	PASS();
diff --git a/tests/path-references.dts b/tests/path-references.dts
index 1fb7d70..dd9ccfc 100644
--- a/tests/path-references.dts
+++ b/tests/path-references.dts
@@ -25,4 +25,13 @@
 			lref = &n3;
 		};
 	};
+	n5: bar {
+		baz {
+		};
+	};
+};
+
+n6: &{n5/baz} {
+	ref = &{n6/};
+	lref = &{n5/baz};
 };
diff --git a/tests/phandle-args-overflow.dts b/tests/phandle-args-overflow.dts
new file mode 100644
index 0000000..8c8c5d7
--- /dev/null
+++ b/tests/phandle-args-overflow.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/*
+ * https://github.com/dgibson/dtc/issues/64
+ *
+ * Certain dtc versions had a bug where this input caused an infinite
+ * loop in check_property_phandle_args().
+ *
+ */
+
+/ {
+    clocks = <&ref &ref>;
+
+    ref: poc {
+        phandle = <1>;
+        #clock-cells = <0xffffffff>;
+    };
+};
diff --git a/tests/phandle_format.c b/tests/phandle_format.c
index d00618f..0febb32 100644
--- a/tests/phandle_format.c
+++ b/tests/phandle_format.c
@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
 		FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
 
 	h4 = fdt_get_phandle(fdt, n4);
-	if ((h4 == 0) || (h4 == -1))
+	if ((h4 == 0) || (h4 == ~0U))
 		FAIL("/node4 has bad phandle 0x%x\n", h4);
 
 	if (phandle_format & PHANDLE_LEGACY)
diff --git a/tests/property_iterate.c b/tests/property_iterate.c
index 9a67f49..0b6af9b 100644
--- a/tests/property_iterate.c
+++ b/tests/property_iterate.c
@@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset)
 	uint32_t properties;
 	const fdt32_t *prop;
 	int offset, property;
-	int count;
+	unsigned int count;
 	int len;
 
 	/*
diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py
index 64b5bd1..68d6aaa 100644
--- a/tests/pylibfdt_tests.py
+++ b/tests/pylibfdt_tests.py
@@ -348,6 +348,19 @@ class PyLibfdtBasicTests(unittest.TestCase):
         self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1'))
         self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1'))
 
+    def testGetPath(self):
+        """Test for the get_path() method"""
+        node = self.fdt.path_offset('/subnode@1')
+        node2 = self.fdt.path_offset('/subnode@1/subsubnode')
+        self.assertEqual("/subnode@1", self.fdt.get_path(node))
+        self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2))
+
+        with self.assertRaises(FdtException) as e:
+            self.fdt.get_path(-1)
+        self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+
+        self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_path(-1, quiet=(libfdt.BADOFFSET,)))
+
     def testParentOffset(self):
         """Test for the parent_offset() method"""
         self.assertEqual(-libfdt.NOTFOUND,
@@ -382,6 +395,25 @@ class PyLibfdtBasicTests(unittest.TestCase):
                           self.get_prop("prop-uint64").as_uint64())
         self.assertEqual(-2, self.get_prop("prop-int64").as_int64())
 
+    def testGetIntListProperties(self):
+        """Test that we can access properties as integer lists"""
+        self.assertEqual([128, -16, -2],
+                         self.get_prop("prop-int32-array").as_int32_list())
+        self.assertEqual([0x1, 0x98765432, 0xdeadbeef],
+                         self.get_prop("prop-uint32-array").as_uint32_list())
+        self.assertEqual([0x100000000, -2],
+                         self.get_prop("prop-int64-array").as_int64_list())
+        self.assertEqual([0x100000000, 0x1],
+                         self.get_prop("prop-uint64-array").as_uint64_list())
+
+    def testGetStringlistProperties(self):
+        """Test that we can access properties as string list"""
+        node = self.fdt.path_offset('/subnode@1/subsubnode')
+        self.assertEqual(["subsubnode1", "subsubnode"],
+                         self.fdt.getprop(node, "compatible").as_stringlist())
+        self.assertEqual(["this is a placeholder string", "string2"],
+                         self.fdt.getprop(node, "placeholder").as_stringlist())
+
     def testReserveMap(self):
         """Test that we can access the memory reserve map"""
         self.assertEqual(2, self.fdt.num_mem_rsv())
diff --git a/tests/references.c b/tests/references.c
index d18e722..cb1daaa 100644
--- a/tests/references.c
+++ b/tests/references.c
@@ -106,7 +106,7 @@ int main(int argc, char *argv[])
 	if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
 		FAIL("/node4 has bad phandle, 0x%x", h4);
 
-	if ((h5 == 0) || (h5 == -1))
+	if ((h5 == 0) || (h5 == ~0U))
 		FAIL("/node5 has bad phandle, 0x%x", h5);
 	if ((h5 == h4) || (h5 == h2) || (h5 == h1))
 		FAIL("/node5 has duplicate phandle, 0x%x", h5);
diff --git a/tests/relref_merge.c b/tests/relref_merge.c
new file mode 100644
index 0000000..5daab2e
--- /dev/null
+++ b/tests/relref_merge.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for label relative child references in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2020 Ahmad Fatoum, Pengutronix.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_exist(void *fdt, const char *path)
+{
+	int sn = fdt_path_offset(fdt, path);
+	if (sn < 0)
+		FAIL("%s expected but not found: %s", path, fdt_strerror(sn));
+}
+
+static void check_doesnt_exist(void *fdt, const char *path)
+{
+	int sn = fdt_path_offset(fdt, path);
+	if (sn >= 0)
+		FAIL("%s found but not expected %d", path, sn);
+}
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_exist(fdt, "/node/subnode1");
+	check_exist(fdt, "/node/keep-me");
+	check_doesnt_exist(fdt, "/node/remove-me");
+
+	check_doesnt_exist(fdt, "/node2");
+	check_doesnt_exist(fdt, "/node/subnode3");
+
+	check_exist(fdt, "/node/subnode4");
+
+	check_exist(fdt, "/node/subnode1/add-me");
+
+	PASS();
+}
diff --git a/tests/relref_merge.dts b/tests/relref_merge.dts
new file mode 100644
index 0000000..d8660eb
--- /dev/null
+++ b/tests/relref_merge.dts
@@ -0,0 +1,40 @@
+/dts-v1/;
+
+/ {
+	node_label: node {
+		keep-me {};
+		remove-me {};
+
+		subnode1 {
+			property-inline1;
+			property-inline2;
+			property-inline3;
+		};
+
+		subnode2 {
+			property-inline1;
+		};
+
+		subnode3 {
+			property-inline1;
+		};
+	};
+
+	node2_label: node2 {
+		property-inline1;
+	};
+};
+/omit-if-no-ref/ &{node_label/subnode1};
+/omit-if-no-ref/ &node2_label;
+/delete-node/ &{node_label/subnode3};
+
+&{node_label/} {
+	/delete-node/ remove-me;
+
+	subnode4 { };
+};
+
+label: &{node_label/subnode1} {
+	selfref = &{node_label/subnode1};
+	add-me { };
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 0e270fe..c78351d 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -513,6 +513,9 @@ libfdt_tests () {
     run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1
     run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb
 
+    ## https://github.com/dgibson/dtc/issues/64
+    check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property
+
     # check full tests
     for good in test_tree1.dtb; do
 	run_test check_full $good
@@ -666,6 +669,9 @@ dtc_tests () {
     tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb
     run_wrap_error_test $DTC -I dts -O dtb -o /dev/null "$SRCDIR/test_label_ref.dts"
 
+    run_dtc_test -I dts -O dtb -o dtc_relref_merge.test.dtb "$SRCDIR/relref_merge.dts"
+    run_test relref_merge dtc_relref_merge.test.dtb
+
     # Check prop/node delete functionality
     run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb "$SRCDIR/test_tree1_delete.dts"
     tree1_tests dtc_tree1_delete.test.dtb
@@ -717,6 +723,9 @@ dtc_tests () {
     run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts"
     check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property
     check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider
+    check_tests "$SRCDIR/bad-interrupt-map.dts" interrupt_map
+    check_tests "$SRCDIR/bad-interrupt-map-parent.dts" interrupt_map
+    check_tests "$SRCDIR/bad-interrupt-map-mask.dts" interrupt_map
     run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_chars -- -I dtb -O dtb bad_node_char.dtb
     run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_format -- -I dtb -O dtb bad_node_format.dtb
     run_sh_test "$SRCDIR/dtc-checkfails.sh" property_name_chars -- -I dtb -O dtb bad_prop_char.dtb
@@ -852,6 +861,8 @@ fdtget_tests () {
     run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
     run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1
     run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob
+    run_fdtget_test "MyBoardName\0MyBoardFamilyName\0" -tr $dtb / compatible
+    run_fdtget_test "\x0a\x0b\x0c\x0d\xde\xea\xad\xbe\xef" -tr $dtb /randomnode blob
 
     # Here the property size is not a multiple of 4 bytes, so it should fail
     run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed
diff --git a/tests/set_name.c b/tests/set_name.c
index a62cb58..5020305 100644
--- a/tests/set_name.c
+++ b/tests/set_name.c
@@ -39,7 +39,11 @@ static void check_set_name(void *fdt, const char *path, const char *newname)
 		FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
 		     path, getname, oldname);
 
-	if (len != strlen(getname))
+	if (len < 0)
+		FAIL("fdt_get_name(%s) returned negative length: %d",
+		     path, len);
+
+	if ((unsigned)len != strlen(getname))
 		FAIL("fdt_get_name(%s) returned length %d instead of %zd",
 		     path, len, strlen(getname));
 
@@ -51,12 +55,14 @@ static void check_set_name(void *fdt, const char *path, const char *newname)
 	getname = fdt_get_name(fdt, offset, &len);
 	if (!getname)
 		FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
+	if (len < 0)
+		FAIL("negative name length (%d) for returned node name\n", len);
 
 	if (strcmp(getname, newname) != 0)
 		FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
 		     path, getname, newname);
 
-	if (len != strlen(getname))
+	if ((unsigned)len != strlen(getname))
 		FAIL("fdt_get_name(%s) returned length %d instead of %zd",
 		     path, len, strlen(getname));
 }
diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c
index 7e1198d..61a0da1 100644
--- a/tests/setprop_inplace.c
+++ b/tests/setprop_inplace.c
@@ -58,7 +58,7 @@ int main(int argc, char *argv[])
 			     TEST_STRING_1);
 
 	verbose_printf("Old string value was \"%s\"\n", strp);
-	xstr = strdup(strp);
+	xstr = xstrdup(strp);
 	xlen = strlen(xstr);
 	for (i = 0; i < xlen; i++)
 		xstr[i] = toupper(xstr[i]);
diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c
index 2dc9b2d..2553a51 100644
--- a/tests/subnode_iterate.c
+++ b/tests/subnode_iterate.c
@@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset)
 	uint32_t subnodes;
 	const fdt32_t *prop;
 	int offset;
-	int count;
+	unsigned int count;
 	int len;
 
 	/* This property indicates the number of subnodes to expect */
diff --git a/tests/test01.asm b/tests/test01.asm
index bbf66c7..73fa603 100644
--- a/tests/test01.asm
+++ b/tests/test01.asm
@@ -44,7 +44,7 @@ _dt_reserve_map:
 dt_struct_start:
 _dt_struct_start:
 	.long	OF_DT_BEGIN_NODE
-	.string	""
+	.asciz	""
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0xc
@@ -76,7 +76,7 @@ _dt_struct_start:
 	.long	0x2
 	.balign	4
 	.long	OF_DT_BEGIN_NODE
-	.string	"cpus"
+	.asciz	"cpus"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0x4
@@ -94,7 +94,7 @@ _dt_struct_start:
 	.long	0x0
 	.balign	4
 	.long	OF_DT_BEGIN_NODE
-	.string	"PowerPC,970@0"
+	.asciz	"PowerPC,970@0"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0xc
@@ -139,7 +139,7 @@ _dt_struct_start:
 	.balign	4
 	.long	OF_DT_END_NODE
 	.long	OF_DT_BEGIN_NODE
-	.string	"PowerPC,970@1"
+	.asciz	"PowerPC,970@1"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0xc
@@ -181,7 +181,7 @@ _dt_struct_start:
 	.long	OF_DT_END_NODE
 	.long	OF_DT_END_NODE
 	.long	OF_DT_BEGIN_NODE
-	.string	"randomnode"
+	.asciz	"randomnode"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0x13
@@ -216,7 +216,7 @@ _dt_struct_start:
 	.balign	4
 	.long	OF_DT_END_NODE
 	.long	OF_DT_BEGIN_NODE
-	.string	"memory@0"
+	.asciz	"memory@0"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0x7
@@ -242,7 +242,7 @@ memreg:
 	.balign	4
 	.long	OF_DT_END_NODE
 	.long	OF_DT_BEGIN_NODE
-	.string	"chosen"
+	.asciz	"chosen"
 	.balign	4
 	.long	OF_DT_PROP
 	.long	0xf
@@ -267,25 +267,25 @@ _dt_struct_end:
 	.globl	dt_strings_start
 dt_strings_start:
 _dt_strings_start:
-	.string "model"
-	.string "compatible"
-	.string "#address-cells"
-	.string "#size-cells"
-	.string "linux,phandle"
-	.string "name"
-	.string "device_type"
-	.string "reg"
-	.string "clock-frequency"
-	.string "timebase-frequency"
-	.string "linux,boot-cpu"
-	.string "i-cache-size"
-	.string "d-cache-size"
-	.string "string"
-	.string "blob"
-	.string "ref"
-	.string "mixed"
-	.string "bootargs"
-	.string "linux,platform"
+	.asciz	"model"
+	.asciz	"compatible"
+	.asciz	"#address-cells"
+	.asciz	"#size-cells"
+	.asciz	"linux,phandle"
+	.asciz	"name"
+	.asciz	"device_type"
+	.asciz	"reg"
+	.asciz	"clock-frequency"
+	.asciz	"timebase-frequency"
+	.asciz	"linux,boot-cpu"
+	.asciz	"i-cache-size"
+	.asciz	"d-cache-size"
+	.asciz	"string"
+	.asciz	"blob"
+	.asciz	"ref"
+	.asciz	"mixed"
+	.asciz	"bootargs"
+	.asciz	"linux,platform"
 	.globl	dt_strings_end
 dt_strings_end:
 _dt_strings_end:
diff --git a/tests/test_props.dts b/tests/test_props.dts
index 7e59bd1..5089023 100644
--- a/tests/test_props.dts
+++ b/tests/test_props.dts
@@ -8,4 +8,8 @@
 	prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>;
 	prop-uint64 = /bits/ 64 <9223372036854775807>;
 	prop-int64 = /bits/ 64 <0xfffffffffffffffe>;
+	prop-int32-array = <128>, <(-16)>, <0xfffffffe>;
+	prop-uint32-array = <0x1>, <0x98765432>, <0xdeadbeef>;
+	prop-int64-array = /bits/ 64 <0x100000000 0xfffffffffffffffe>;
+	prop-uint64-array = /bits/ 64 <0x100000000 0x1>;
 };
diff --git a/tests/tests.h b/tests/tests.h
index 1017366..bf8f23c 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -83,7 +83,7 @@ void cleanup(void);
 void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size);
 
 void check_property(void *fdt, int nodeoffset, const char *name,
-		    int len, const void *val);
+		    unsigned int len, const void *val);
 #define check_property_cell(fdt, nodeoffset, name, val) \
 	({ \
 		fdt32_t x = cpu_to_fdt32(val);			      \
diff --git a/tests/testutils.c b/tests/testutils.c
index 5e494c5..10129c0 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -88,7 +88,7 @@ void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size)
 }
 
 void check_property(void *fdt, int nodeoffset, const char *name,
-		    int len, const void *val)
+		    unsigned int len, const void *val)
 {
 	const struct fdt_property *prop;
 	int retlen, namelen;
@@ -101,6 +101,9 @@ void check_property(void *fdt, int nodeoffset, const char *name,
 	if (! prop)
 		FAIL("Error retrieving \"%s\" pointer: %s", name,
 		     fdt_strerror(retlen));
+	if (retlen < 0)
+		FAIL("negative name length (%d) for returned property\n",
+		     retlen);
 
 	tag = fdt32_to_cpu(prop->tag);
 	nameoff = fdt32_to_cpu(prop->nameoff);
@@ -112,13 +115,16 @@ void check_property(void *fdt, int nodeoffset, const char *name,
 	propname = fdt_get_string(fdt, nameoff, &namelen);
 	if (!propname)
 		FAIL("Couldn't get property name: %s", fdt_strerror(namelen));
-	if (namelen != strlen(propname))
+	if (namelen < 0)
+		FAIL("negative name length (%d) for returned string\n",
+		     namelen);
+	if ((unsigned)namelen != strlen(propname))
 		FAIL("Incorrect prop name length: %d instead of %zd",
 		     namelen, strlen(propname));
 	if (!streq(propname, name))
 		FAIL("Property name mismatch \"%s\" instead of \"%s\"",
 		     propname, name);
-	if (proplen != retlen)
+	if (proplen != (unsigned)retlen)
 		FAIL("Length retrieved for \"%s\" by fdt_get_property()"
 		     " differs from stored length (%d != %d)",
 		     name, retlen, proplen);
diff --git a/tests/trees.S b/tests/trees.S
index 95d599d..d69f7f1 100644
--- a/tests/trees.S
+++ b/tests/trees.S
@@ -1,174 +1,187 @@
 #include <fdt.h>
 #include "testdata.h"
 
-#define FDTLONG(val) \
-	.byte	((val) >> 24) & 0xff ; \
-	.byte	((val) >> 16) & 0xff ; \
-	.byte	((val) >> 8) & 0xff ; \
-	.byte	(val) & 0xff	;
-
-#define TREE_HDR(tree) \
-	.balign	8		; \
-	.globl	tree		; \
-tree:	\
-	FDTLONG(FDT_MAGIC)	; \
-	FDTLONG(tree##_end - tree) ; \
-	FDTLONG(tree##_struct - tree) ; \
-	FDTLONG(tree##_strings - tree) ; \
-	FDTLONG(tree##_rsvmap - tree) ; \
-	FDTLONG(0x11)		; \
-	FDTLONG(0x10)		; \
-	FDTLONG(0)		; \
-	FDTLONG(tree##_strings_end - tree##_strings) ; \
-	FDTLONG(tree##_struct_end - tree##_struct) ;
-
-#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, 0, 0) \
-tree##_rsvmap_end:		;
-
-#define PROPHDR(tree, name, len) \
-	FDTLONG(FDT_PROP)	; \
-	FDTLONG(len)		; \
-	FDTLONG(tree##_##name - tree##_strings) ;
-
-#define PROP_EMPTY(tree, name) \
-	PROPHDR(tree, name, 0)	;
-
-#define PROP_INT(tree, name, val) \
-	PROPHDR(tree, name, 4) \
-	FDTLONG(val)		;
-
-#define PROP_INT64(tree, name, valh, vall) \
-	PROPHDR(tree, name, 8) \
-	FDTLONG(valh)		; \
-	FDTLONG(vall)		;
-
-#define PROP_STR(tree, name, str) \
-	PROPHDR(tree, name, 55f - 54f) \
-54:	\
-	.string	str		; \
-55:	\
-	.balign	4		;
-
-#define BEGIN_NODE(name) \
-	FDTLONG(FDT_BEGIN_NODE)	; \
-	.string	name		; \
-	.balign 4		;
-
-#define END_NODE \
-	FDTLONG(FDT_END_NODE)	;
-
-#define STRING(tree, name, str) \
-tree##_##name:			; \
-	.string	str		;
+	.macro	fdtlong	val
+	.byte	((\val) >> 24) & 0xff
+	.byte	((\val) >> 16) & 0xff
+	.byte	((\val) >> 8) & 0xff
+	.byte	(\val) & 0xff
+	.endm
+
+	.macro	treehdr	tree
+	.balign	8
+	.globl	\tree
+\tree :
+	fdtlong	FDT_MAGIC
+	fdtlong	(\tree\()_end - \tree)
+	fdtlong	(\tree\()_struct - \tree)
+	fdtlong	(\tree\()_strings - \tree)
+	fdtlong	(\tree\()_rsvmap - \tree)
+	fdtlong	0x11
+	fdtlong	0x10
+	fdtlong	0
+	fdtlong	(\tree\()_strings_end - \tree\()_strings)
+	fdtlong	(\tree\()_struct_end - \tree\()_struct)
+	.endm
+
+	.macro	rsvmape	addrh, addrl, lenh, lenl
+	fdtlong	\addrh
+	fdtlong	\addrl
+	fdtlong	\lenh
+	fdtlong	\lenl
+	.endm
+
+	.macro	empty_rsvmap	tree
+	.balign	8
+\tree\()_rsvmap:
+	rsvmape	0, 0, 0, 0
+\tree\()_rsvmap_end:
+	.endm
+
+	.macro prophdr	tree, name, len
+	fdtlong	FDT_PROP
+	fdtlong	\len
+	fdtlong	(\tree\()_\name - \tree\()_strings)
+	.endm
+
+	.macro propnil	tree, name
+	prophdr	\tree, \name, 0
+	.endm
+
+	.macro propu32	tree, name, val
+	prophdr	\tree, \name, 4
+	fdtlong	\val
+	.endm
+
+	.macro propu64	tree, name, valh, vall
+	prophdr	\tree, \name, 8
+	fdtlong	\valh
+	fdtlong	\vall
+	.endm
+
+	.macro propstr	tree, name, str:vararg
+	prophdr	\tree, \name, (55f - 54f)
+54:
+	.asciz	\str
+55:
+	.balign	4
+	.endm
+
+	.macro	beginn	name:vararg
+	fdtlong	FDT_BEGIN_NODE
+	.asciz	\name
+	.balign 4
+	.endm
+
+	.macro	endn
+	fdtlong	FDT_END_NODE
+	.endm
+
+	.macro	string	tree, name, str:vararg
+\tree\()_\name :
+	.asciz	\str
+	.endm
+
 
 	.data
 
-	TREE_HDR(test_tree1)
+	treehdr	test_tree1
 
 	.balign	8
 test_tree1_rsvmap:
-	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)
+	rsvmape	TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
+	rsvmape	TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L
+	rsvmape	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_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)
-
-	BEGIN_NODE("subnode@1")
-	PROP_STR(test_tree1, compatible, "subnode1")
-	PROP_INT(test_tree1, reg, 1)
-	PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
-
-	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
-
-	BEGIN_NODE("ss1")
-	END_NODE
-
-	END_NODE
-
-	BEGIN_NODE("subnode@2")
-	PROP_INT(test_tree1, reg, 2)
-	PROP_INT(test_tree1, linux_phandle, PHANDLE_1)
-	PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
-	PROP_INT(test_tree1, address_cells, 1)
-	PROP_INT(test_tree1, size_cells, 0)
-
-	BEGIN_NODE("subsubnode@0")
-	PROP_INT(test_tree1, reg, 0)
-	PROP_INT(test_tree1, phandle, PHANDLE_2)
-	PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode")
-	PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
-	END_NODE
-
-	BEGIN_NODE("ss2")
-	END_NODE
-
-	END_NODE
-
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	propstr	test_tree1, compatible, "test_tree1"
+	propu32	test_tree1, prop_int, TEST_VALUE_1
+	propu64	test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L
+	propstr	test_tree1, prop_str, TEST_STRING_1
+	propu32 test_tree1, address_cells, 1
+	propu32	test_tree1, size_cells, 0
+
+	beginn	"subnode@1"
+	propstr	test_tree1, compatible, "subnode1"
+	propu32	test_tree1, reg, 1
+	propu32	test_tree1, prop_int, TEST_VALUE_1
+
+	beginn	"subsubnode"
+	propstr	test_tree1, compatible, "subsubnode1\0subsubnode"
+	propstr	test_tree1, placeholder, "this is a placeholder string\0string2"
+	propu32	test_tree1, prop_int, TEST_VALUE_1
+	endn
+
+	beginn	"ss1"
+	endn
+
+	endn
+
+	beginn	"subnode@2"
+	propu32	test_tree1, reg, 2
+	propu32	test_tree1, linux_phandle, PHANDLE_1
+	propu32	test_tree1, prop_int, TEST_VALUE_2
+	propu32	test_tree1, address_cells, 1
+	propu32	test_tree1, size_cells, 0
+
+	beginn	"subsubnode@0"
+	propu32	test_tree1, reg, 0
+	propu32	test_tree1, phandle, PHANDLE_2
+	propstr	test_tree1, compatible, "subsubnode2\0subsubnode"
+	propu32	test_tree1, prop_int, TEST_VALUE_2
+	endn
+
+	beginn	"ss2"
+	endn
+
+	endn
+
+	endn
+	fdtlong	FDT_END
 test_tree1_struct_end:
 
 test_tree1_strings:
-	STRING(test_tree1, compatible, "compatible")
-	STRING(test_tree1, prop_int, "prop-int")
-	STRING(test_tree1, prop_int64, "prop-int64")
-	STRING(test_tree1, prop_str, "prop-str")
-	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")
+	string	test_tree1, compatible, "compatible"
+	string	test_tree1, prop_int, "prop-int"
+	string	test_tree1, prop_int64, "prop-int64"
+	string	test_tree1, prop_str, "prop-str"
+	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:
 test_tree1_end:
 
 
-	TREE_HDR(truncated_property)
-	EMPTY_RSVMAP(truncated_property)
+	treehdr	truncated_property
+	empty_rsvmap	truncated_property
 
 truncated_property_struct:
-	BEGIN_NODE("")
-	PROPHDR(truncated_property, prop_truncated, 4)
+	beginn	""
+	prophdr	truncated_property, prop_truncated, 4
 	/* Oops, no actual property data here */
 truncated_property_struct_end:
 
 truncated_property_strings:
-	STRING(truncated_property, prop_truncated, "truncated")
+	string	truncated_property, prop_truncated, "truncated"
 truncated_property_strings_end:
 
 truncated_property_end:
 
 
-	TREE_HDR(bad_node_char)
-	EMPTY_RSVMAP(bad_node_char)
+	treehdr	bad_node_char
+	empty_rsvmap	bad_node_char
 
 bad_node_char_struct:
-	BEGIN_NODE("")
-	BEGIN_NODE("sub$node")
-	END_NODE
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	beginn	"sub$node"
+	endn
+	endn
+	fdtlong	FDT_END
 bad_node_char_struct_end:
 
 bad_node_char_strings:
@@ -176,15 +189,15 @@ bad_node_char_strings_end:
 bad_node_char_end:
 
 
-	TREE_HDR(bad_node_format)
-	EMPTY_RSVMAP(bad_node_format)
+	treehdr	bad_node_format
+	empty_rsvmap	bad_node_format
 
 bad_node_format_struct:
-	BEGIN_NODE("")
-	BEGIN_NODE("subnode@1@2")
-	END_NODE
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	beginn	"subnode@1@2"
+	endn
+	endn
+	fdtlong	FDT_END
 bad_node_format_struct_end:
 
 bad_node_format_strings:
@@ -192,18 +205,18 @@ bad_node_format_strings_end:
 bad_node_format_end:
 
 
-	TREE_HDR(bad_prop_char)
-	EMPTY_RSVMAP(bad_prop_char)
+	treehdr	bad_prop_char
+	empty_rsvmap	bad_prop_char
 
 bad_prop_char_struct:
-	BEGIN_NODE("")
-	PROP_INT(bad_prop_char, prop, TEST_VALUE_1)
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	propu32	bad_prop_char, prop, TEST_VALUE_1
+	endn
+	fdtlong	FDT_END
 bad_prop_char_struct_end:
 
 bad_prop_char_strings:
-	STRING(bad_prop_char, prop, "prop$erty")
+	string	bad_prop_char, prop, "prop$erty"
 bad_prop_char_strings_end:
 bad_prop_char_end:
 
@@ -212,62 +225,60 @@ bad_prop_char_end:
 	.balign	8
 	.globl	ovf_size_strings
 ovf_size_strings:
-	FDTLONG(FDT_MAGIC)
-	FDTLONG(ovf_size_strings_end - ovf_size_strings)
-	FDTLONG(ovf_size_strings_struct - ovf_size_strings) 
-	FDTLONG(ovf_size_strings_strings - ovf_size_strings)
-	FDTLONG(ovf_size_strings_rsvmap - ovf_size_strings)
-	FDTLONG(0x11)
-	FDTLONG(0x10)
-	FDTLONG(0)
-	FDTLONG(0xffffffff)
-	FDTLONG(ovf_size_strings_struct_end - ovf_size_strings_struct)
-	EMPTY_RSVMAP(ovf_size_strings)
+	fdtlong	FDT_MAGIC
+	fdtlong	(ovf_size_strings_end - ovf_size_strings)
+	fdtlong	(ovf_size_strings_struct - ovf_size_strings)
+	fdtlong	(ovf_size_strings_strings - ovf_size_strings)
+	fdtlong	(ovf_size_strings_rsvmap - ovf_size_strings)
+	fdtlong	0x11
+	fdtlong	0x10
+	fdtlong	0
+	fdtlong	0xffffffff
+	fdtlong	(ovf_size_strings_struct_end - ovf_size_strings_struct)
+	empty_rsvmap	ovf_size_strings
 
 ovf_size_strings_struct:
-	BEGIN_NODE("")
-	PROP_INT(ovf_size_strings, bad_string, 0)
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	propu32	ovf_size_strings, bad_string, 0
+	endn
+	fdtlong	FDT_END
 ovf_size_strings_struct_end:
 
 ovf_size_strings_strings:
-	STRING(ovf_size_strings, x, "x")
+	string	ovf_size_strings, x, "x"
 	ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000
 ovf_size_strings_strings_end:
 ovf_size_strings_end:
 
 
 	/* truncated_string */
-	TREE_HDR(truncated_string)
-	EMPTY_RSVMAP(truncated_string)
+	treehdr	truncated_string
+	empty_rsvmap	truncated_string
 
 truncated_string_struct:
-	BEGIN_NODE("")
-	PROP_EMPTY(truncated_string, good_string)
-	PROP_EMPTY(truncated_string, bad_string)
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	propnil	truncated_string, good_string
+	propnil	truncated_string, bad_string
+	endn
+	fdtlong	FDT_END
 truncated_string_struct_end:
 
 truncated_string_strings:
-	STRING(truncated_string, good_string, "good")
+	string	truncated_string, good_string, "good"
 truncated_string_bad_string:
-	.byte	'b'
-	.byte	'a'
-	.byte	'd'
+	.ascii	"bad"
 	/* NOTE: terminating \0 deliberately missing */
 truncated_string_strings_end:
 truncated_string_end:
 
 
 	/* truncated_memrsv */
-	TREE_HDR(truncated_memrsv)
+	treehdr	truncated_memrsv
 
 truncated_memrsv_struct:
-	BEGIN_NODE("")
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	endn
+	fdtlong	FDT_END
 truncated_memrsv_struct_end:
 
 truncated_memrsv_strings:
@@ -275,22 +286,22 @@ truncated_memrsv_strings_end:
 
 	.balign	8
 truncated_memrsv_rsvmap:
-	RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
+	rsvmape	TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
 truncated_memrsv_rsvmap_end:
 
 truncated_memrsv_end:
 
 
         /* two root nodes */
-        TREE_HDR(two_roots)
-	EMPTY_RSVMAP(two_roots)
+	treehdr	two_roots
+	empty_rsvmap	two_roots
 
 two_roots_struct:
-	BEGIN_NODE("")
-	END_NODE
-	BEGIN_NODE("")
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	""
+	endn
+	beginn	""
+	endn
+	fdtlong	FDT_END
 two_roots_struct_end:
 
 two_roots_strings:
@@ -300,13 +311,13 @@ two_roots_end:
 
 
         /* root node with a non-empty name */
-        TREE_HDR(named_root)
-	EMPTY_RSVMAP(named_root)
+	treehdr	named_root
+	empty_rsvmap	named_root
 
 named_root_struct:
-	BEGIN_NODE("fake")
-	END_NODE
-	FDTLONG(FDT_END)
+	beginn	"fake"
+	endn
+	fdtlong	FDT_END
 named_root_struct_end:
 
 named_root_strings:
diff --git a/tests/type-preservation.dt.yaml b/tests/type-preservation.dt.yaml
index ee8cfde..a0cc64c 100644
--- a/tests/type-preservation.dt.yaml
+++ b/tests/type-preservation.dt.yaml
@@ -13,8 +13,11 @@
     int64: [!u64 [0x200000000]]
     int64-array: [!u64 [0x100000000, 0x0]]
     a-string-with-nulls: ["foo\0bar", "baz"]
+    a-phandle: [[!phandle 0x1]]
+    a-phandle-with-args: [[!phandle 0x1, 0x0, 0x1], [!phandle 0x1, 0x2, 0x3]]
     subsubnode:
       compatible: ["subsubnode1", "subsubnode"]
+      phandle: [[0x1]]
       subsubsubnode:
         compatible: ["subsubsubnode1", [0x1234], "subsubsubnode"]
 ...
diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts
index 3e380ba..921ea21 100644
--- a/tests/type-preservation.dts
+++ b/tests/type-preservation.dts
@@ -16,9 +16,12 @@
 		int64 = /bits/ 64 <0x200000000>;
 		int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:;
 		a-string-with-nulls = "foo\0bar", "baz";
+		a-phandle = <&subsub1>;
+		a-phandle-with-args = <&subsub1 0x00 0x01>, <&subsub1 0x02 0x03>;
 
 		subsub1: subsubnode {
 			compatible = "subsubnode1", "subsubnode";
+			phandle = <0x01>;
 
 			subsubsub1: subsubsubnode {
 				compatible = "subsubsubnode1", <0x1234>, valuea: valueb: "subsubsubnode";
diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c
index c621759..ba6462f 100644
--- a/tests/utilfdt_test.c
+++ b/tests/utilfdt_test.c
@@ -73,6 +73,9 @@ static void check_sizes(char *modifier, int expected_size)
 
 	*ptr = 's';
 	check(fmt, 's', -1);
+
+	*ptr = 'r';
+	check(fmt, 'r', -1);
 }
 
 static void test_utilfdt_decode_type(void)
@@ -90,7 +93,7 @@ static void test_utilfdt_decode_type(void)
 	/* try every other character */
 	checkfail("");
 	for (ch = ' '; ch < 127; ch++) {
-		if (!strchr("iuxs", ch)) {
+		if (!strchr("iuxsr", ch)) {
 			*fmt = ch;
 			fmt[1] = '\0';
 			checkfail(fmt);
diff --git a/treesource.c b/treesource.c
index 061ba8c..33fedee 100644
--- a/treesource.c
+++ b/treesource.c
@@ -124,27 +124,6 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
 	}
 }
 
-static bool has_data_type_information(struct marker *m)
-{
-	return m->type >= TYPE_UINT8;
-}
-
-static struct marker *next_type_marker(struct marker *m)
-{
-	while (m && !has_data_type_information(m))
-		m = m->next;
-	return m;
-}
-
-size_t type_marker_length(struct marker *m)
-{
-	struct marker *next = next_type_marker(m->next);
-
-	if (next)
-		return next->offset - m->offset;
-	return 0;
-}
-
 static const char *delim_start[] = {
 	[TYPE_UINT8] = "[",
 	[TYPE_UINT16] = "/bits/ 16 <",
@@ -229,26 +208,39 @@ static void write_propval(FILE *f, struct property *prop)
 		size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
 		size_t data_len = type_marker_length(m) ? : len - m->offset;
 		const char *p = &prop->val.val[m->offset];
+		struct marker *m_phandle;
 
-		if (has_data_type_information(m)) {
+		if (is_type_marker(m->type)) {
 			emit_type = m->type;
 			fprintf(f, " %s", delim_start[emit_type]);
 		} else if (m->type == LABEL)
 			fprintf(f, " %s:", m->ref);
-		else if (m->offset)
-			fputc(' ', f);
 
-		if (emit_type == TYPE_NONE) {
-			assert(chunk_len == 0);
+		if (emit_type == TYPE_NONE || chunk_len == 0)
 			continue;
-		}
 
 		switch(emit_type) {
 		case TYPE_UINT16:
 			write_propval_int(f, p, chunk_len, 2);
 			break;
 		case TYPE_UINT32:
-			write_propval_int(f, p, chunk_len, 4);
+			m_phandle = prop->val.markers;
+			for_each_marker_of_type(m_phandle, REF_PHANDLE)
+				if (m->offset == m_phandle->offset)
+					break;
+
+			if (m_phandle) {
+				if (m_phandle->ref[0] == '/')
+					fprintf(f, "&{%s}", m_phandle->ref);
+				else
+					fprintf(f, "&%s", m_phandle->ref);
+				if (chunk_len > 4) {
+					fputc(' ', f);
+					write_propval_int(f, p + 4, chunk_len - 4, 4);
+				}
+			} else {
+				write_propval_int(f, p, chunk_len, 4);
+			}
 			break;
 		case TYPE_UINT64:
 			write_propval_int(f, p, chunk_len, 8);
diff --git a/util.c b/util.c
index 40274fb..507f012 100644
--- a/util.c
+++ b/util.c
@@ -33,6 +33,17 @@ char *xstrdup(const char *s)
 	return d;
 }
 
+char *xstrndup(const char *s, size_t n)
+{
+	size_t len = strnlen(s, n) + 1;
+	char *d = xmalloc(len);
+
+	memcpy(d, s, len - 1);
+	d[len - 1] = '\0';
+
+	return d;
+}
+
 int xavsprintf_append(char **strp, const char *fmt, va_list ap)
 {
 	int n, size = 0;	/* start with 128 bytes */
@@ -353,11 +364,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
 	}
 
 	/* we should now have a type */
-	if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+	if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
 		return -1;
 
 	/* convert qualifier (bhL) to byte size */
-	if (*fmt != 's')
+	if (*fmt != 's' && *fmt != 'r')
 		*size = qualifier == 'b' ? 1 :
 				qualifier == 'h' ? 2 :
 				qualifier == 'l' ? 4 : -1;
diff --git a/util.h b/util.h
index c45b2c2..9d38ede 100644
--- a/util.h
+++ b/util.h
@@ -61,6 +61,7 @@ static inline void *xrealloc(void *p, size_t len)
 }
 
 extern char *xstrdup(const char *s);
+extern char *xstrndup(const char *s, size_t len);
 
 extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
 extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
@@ -143,6 +144,7 @@ int utilfdt_write_err(const char *filename, const void *blob);
  *		i	signed integer
  *		u	unsigned integer
  *		x	hex
+ *		r	raw
  *
  * TODO: Implement ll modifier (8 bytes)
  * TODO: Implement o type (octal)
@@ -160,7 +162,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
  */
 
 #define USAGE_TYPE_MSG \
-	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+	"<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
 	"\tOptional modifier prefix:\n" \
 	"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
 
