diff --git a/core/fdt.c b/core/fdt.c
index 7abebba..c92dac8 100644
--- a/core/fdt.c
+++ b/core/fdt.c
@@ -27,7 +27,6 @@
 #include <ccan/str/str.h>
 
 static int fdt_error;
-static void *fdt;
 
 #undef DEBUG_FDT
 
@@ -44,12 +43,12 @@ static void __save_err(int err, const char *str)
 
 #define save_err(...) __save_err(__VA_ARGS__, #__VA_ARGS__)
 
-static void dt_property_cell(const char *name, u32 cell)
+static void dt_property_cell(void *fdt, const char *name, u32 cell)
 {
 	save_err(fdt_property_cell(fdt, name, cell));
 }
 
-static void dt_begin_node(const char *name, uint32_t phandle)
+static void dt_begin_node(void *fdt, const char *name, uint32_t phandle)
 {
 	save_err(fdt_begin_node(fdt, name));
 
@@ -57,23 +56,23 @@ static void dt_begin_node(const char *name, uint32_t phandle)
 	 * We add both the new style "phandle" and the legacy
 	 * "linux,phandle" properties
 	 */
-	dt_property_cell("linux,phandle", phandle);
-	dt_property_cell("phandle", phandle);
+	dt_property_cell(fdt, "linux,phandle", phandle);
+	dt_property_cell(fdt, "phandle", phandle);
 }
 
-static void dt_property(const char *name, const void *val, size_t size)
+static void dt_property(void *fdt, const char *name, const void *val, size_t size)
 {
 	save_err(fdt_property(fdt, name, val, size));
 }
 
-static void dt_end_node(void)
+static void dt_end_node(void *fdt)
 {
 	save_err(fdt_end_node(fdt));
 }
 
-static void dump_fdt(void)
-{
 #ifdef DEBUG_FDT
+static void dump_fdt(void *fdt)
+{
 	int i, off, depth, err;
 
 	printf("Device tree %u@%p\n", fdt_totalsize(fdt), fdt);
@@ -110,35 +109,47 @@ static void dump_fdt(void)
 		}
 		printf("name: %s [%u]\n", name, off);
 	}
-#endif
 }
+#else
+#define dump_fdt(x...)
+#endif
 
-static void flatten_dt_node(const struct dt_node *root)
+static void dt_flatten_properties(void *fdt, const struct dt_node *dn)
 {
-	const struct dt_node *i;
-	const struct dt_property *p;
+	struct dt_property *p;
 
-#ifdef DEBUG_FDT
-	printf("FDT: node: %s\n", root->name);
-#endif
-
-	list_for_each(&root->properties, p, list) {
+	list_for_each(&dn->properties, p, list) {
 		if (strstarts(p->name, DT_PRIVATE))
 			continue;
 #ifdef DEBUG_FDT
 		printf("FDT:   prop: %s size: %ld\n", p->name, p->len);
 #endif
-		dt_property(p->name, p->prop, p->len);
+		dt_property(fdt, p->name, p->prop, p->len);
 	}
+}
 
-	list_for_each(&root->children, i, list) {
-		dt_begin_node(i->name, i->phandle);
-		flatten_dt_node(i);
-		dt_end_node();
+static void dt_flatten_node(void *fdt, const struct dt_node *dn, bool inclusive)
+{
+	const struct dt_node *child;
+
+#ifdef DEBUG_FDT
+	printf("FDT: node: %s\n", dn->name);
+#endif
+
+	if (inclusive) {
+		dt_begin_node(fdt, dn->name, dn->phandle);
+		dt_flatten_properties(fdt, dn);
 	}
+
+	list_for_each(&dn->children, child, list)
+		dt_flatten_node(fdt, child, true);
+
+	/* Note that we have open ending pattern */
+	if (inclusive)
+		dt_end_node(fdt);
 }
 
-static void create_dtb_reservemap(const struct dt_node *root)
+static void create_dtb_reservemap(void *fdt, const struct dt_node *root)
 {
 	uint64_t base, size;
 	const uint64_t *ranges;
@@ -160,38 +171,61 @@ static void create_dtb_reservemap(const struct dt_node *root)
 	save_err(fdt_finish_reservemap(fdt));
 }
 
-void *create_dtb(const struct dt_node *root)
+static int __create_dtb(const struct dt_node *root, size_t len,
+			bool inclusive, void **pblob)
 {
-	size_t len = DEVICE_TREE_MAX_SIZE;
-	uint32_t old_last_phandle = last_phandle;
+	void *fdt;
 
-	do {
-		if (fdt)
-			free(fdt);
-		last_phandle = old_last_phandle;
-		fdt_error = 0;
-		fdt = malloc(len);
-		if (!fdt) {
-			prerror("dtb: could not malloc %lu\n", (long)len);
-			return NULL;
-		}
+	/* Clear cached error */
+	fdt_error = 0;
 
-		fdt_create(fdt, len);
+	/* Allocate memory chunk */
+	fdt = malloc(len);
+	if (!fdt) {
+		*pblob = NULL;
+		prerror("dtb: cannot alloc %lu\n", (long)len);
+		return 0;
+	}
 
-		create_dtb_reservemap(root);
+	/* FDT header */
+	fdt_create(fdt, len);
 
-		/* Open root node */
-		dt_begin_node(root->name, root->phandle);
+	/* Reserved memory chunks */
+	if (root == dt_root && inclusive)
+		create_dtb_reservemap(fdt, root);
 
-		/* Unflatten our live tree */
-		flatten_dt_node(root);
+	/* Unflatten our live tree */
+	dt_flatten_node(fdt, root, inclusive);
 
-		/* Close root node */
-		dt_end_node();
+	save_err(fdt_finish(fdt));
+	if (fdt_error) {
+		free(fdt);
+		return fdt_error;
+	}
 
-		save_err(fdt_finish(fdt));
+	*pblob = fdt;
+	return 0;
+}
 
-		if (!fdt_error)
+void *create_dtb(const struct dt_node *root, size_t *size, bool inclusive)
+{
+	size_t len;
+	uint32_t old_last_phandle = last_phandle;
+	void *fdt = NULL;
+	int ret;
+
+	/* Get the initial length */
+	if (size) {
+		len = *size;
+		*size = 0;
+	} else {
+		len = DEVICE_TREE_MAX_SIZE;
+	}
+
+	do {
+		last_phandle = old_last_phandle;
+		ret = __create_dtb(root, len, inclusive, &fdt);
+		if (!ret)
 			break;
 
 		len *= 2;
@@ -203,5 +237,8 @@ void *create_dtb(const struct dt_node *root)
 		prerror("dtb: error %s\n", fdt_strerror(fdt_error));
 		return NULL;
 	}
+
+	if (size)
+		*size = len;
 	return fdt;
 }
diff --git a/core/init.c b/core/init.c
index 445272a..2836ae3 100644
--- a/core/init.c
+++ b/core/init.c
@@ -414,7 +414,7 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
 	op_display(OP_LOG, OP_MOD_INIT, 0x000B);
 
 	/* Create the device tree blob to boot OS. */
-	fdt = create_dtb(dt_root);
+	fdt = create_dtb(dt_root, NULL, true);
 	if (!fdt) {
 		op_display(OP_FATAL, OP_MOD_INIT, 2);
 		abort();
diff --git a/include/device_tree.h b/include/device_tree.h
index d04f20a..a32821c 100644
--- a/include/device_tree.h
+++ b/include/device_tree.h
@@ -18,11 +18,6 @@
 #define __DEVICE_TREE_H
 #include <stdint.h>
 
-/* Note: Device tree creation has no locks. It's assumed to be done
- * by a single processor in a non racy way
- */
-void *create_dtb(const struct dt_node *root);
-
 /* Helpers to cache errors in fdt; use this instead of fdt_* */
 uint32_t dt_begin_node(const char *name); /* returns phandle */
 void dt_property_string(const char *name, const char *value);
diff --git a/include/skiboot.h b/include/skiboot.h
index fc5bc1d..19b77b3 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -235,7 +235,7 @@ extern void prd_occ_reset(uint32_t proc);
 extern void prd_init(void);
 
 /* Flatten device-tree */
-extern void *create_dtb(const struct dt_node *root);
+void *create_dtb(const struct dt_node *root, size_t *size, bool inclusive);
 
 /* SLW reinit function for switching core settings */
 extern int64_t slw_reinit(uint64_t flags);
