diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 00ddb3b05d..70bcdc449d 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -14,6 +14,7 @@
 #include <xen/guest_access.h>
 #include <xen/iocap.h>
 #include <xen/acpi.h>
+#include <xen/vmap.h>
 #include <xen/warning.h>
 #include <acpi/actables.h>
 #include <asm/device.h>
@@ -1706,6 +1707,102 @@ static int __init make_vpl011_uart_node(const struct domain *d, void *fdt)
 }
 #endif
 
+static int __init handle_properties(struct domain *d, void *fdt, const void *pfdt, int nodeoff,
+                                    u32 address_cells, u32 size_cells)
+{
+    int propoff, nameoff, r;
+    const struct fdt_property *prop;
+
+    for ( propoff = fdt_first_property_offset(pfdt, nodeoff);
+          propoff >= 0;
+          propoff = fdt_next_property_offset(pfdt, propoff) )
+    {
+
+        if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) )
+            return -FDT_ERR_INTERNAL;
+
+        nameoff = fdt32_to_cpu(prop->nameoff);
+        r = fdt_property(fdt, fdt_string(pfdt, nameoff),
+                         prop->data, fdt32_to_cpu(prop->len));
+        if ( r )
+            return r;
+    }
+
+    /* FDT_ERR_NOTFOUND => There is no more properties for this node */
+    return ( propoff != -FDT_ERR_NOTFOUND ) ? propoff : 0;
+}
+
+static int __init scan_pt_node(const void *pfdt,
+                               int nodeoff, const char *name, int depth,
+                               u32 address_cells, u32 size_cells,
+                               void *data)
+{
+    int rc;
+    int i, num;
+    struct kernel_info *kinfo = data;
+    void *fdt = kinfo->fdt;
+    int depth_next = depth;
+    int node_next;
+
+    /* no need to parse initial node */
+    if ( !depth )
+        return 0;
+
+    rc = fdt_begin_node(fdt, fdt_get_name(pfdt, nodeoff, NULL));
+    if ( rc )
+        return rc;
+
+    rc = handle_properties(kinfo->d, fdt, pfdt, nodeoff,
+                           address_cells, size_cells);
+    if ( rc )
+        return rc;
+
+    node_next = fdt_next_node(pfdt, nodeoff, &depth_next);
+
+    /*
+     * If the next node is a sibling, then we need to call
+     * fdt_end_node once. If the next node is one level up, we need to
+     * call it twice: once for us and the second time for our parent.
+     * Both these two conditions are expressed together by depth -
+     * depth_next + 1.
+     *
+     * If we reached the end of the device tree fragment, then it is
+     * easy: we need to call fdt_end_node once for every level of depth
+     * to close all open nodes.
+     */
+    if ( depth_next < 0 )
+        num = depth;
+    else
+        num = depth - depth_next + 1;
+
+    for ( i = 0; i < num; i++ )
+    {
+        rc = fdt_end_node(fdt);
+        if ( rc )
+            return rc;
+    }
+
+    return 0;
+}
+
+static int __init domain_handle_dtb_bootmodule(struct domain *d,
+                                               struct kernel_info *kinfo)
+{
+    void *pfdt;
+    int res;
+
+    pfdt = ioremap_cache(kinfo->dtb_bootmodule->start,
+            kinfo->dtb_bootmodule->size);
+    if ( pfdt == NULL )
+        return -EFAULT;
+
+    res = device_tree_for_each_node(pfdt, scan_pt_node, kinfo);
+
+    iounmap(pfdt);
+
+    return res;
+}
+
 /*
  * The max size for DT is 2MB. However, the generated DT is small, 4KB
  * are enough for now, but we might have to increase it in the future.
@@ -1777,6 +1874,12 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
             goto err;
     }
 
+    if ( kinfo->dtb_bootmodule ) {
+        ret = domain_handle_dtb_bootmodule(d, kinfo);
+        if ( ret )
+            return ret;
+    }
+
     ret = fdt_end_node(kinfo->fdt);
     if ( ret < 0 )
         goto err;
diff --git a/xen/include/asm-arm/kernel.h b/xen/include/asm-arm/kernel.h
index 33f3e72b11..720dec4071 100644
--- a/xen/include/asm-arm/kernel.h
+++ b/xen/include/asm-arm/kernel.h
@@ -28,7 +28,7 @@ struct kernel_info {
     paddr_t gnttab_size;
 
     /* boot blob load addresses */
-    const struct bootmodule *kernel_bootmodule, *initrd_bootmodule;
+    const struct bootmodule *kernel_bootmodule, *initrd_bootmodule, *dtb_bootmodule;
     const char* cmdline;
     paddr_t dtb_paddr;
     paddr_t initrd_paddr;
