diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c
index 5cc1658dbde61996156741da52eddaf5044f0f52..3230d859b034ef86b5a57980d8df20089c2164a7 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c
@@ -21,28 +21,173 @@
 #include <linux/types.h>
 #include <linux/byteorder/generic.h>
 #include <linux/slab.h>
+#include <linux/libfdt.h>
 #include <linux/of_fdt.h>
 
 #include "mtdsplit.h"
 
-struct fdt_header {
-	uint32_t magic;			 /* magic word FDT_MAGIC */
-	uint32_t totalsize;		 /* total size of DT block */
-	uint32_t off_dt_struct;		 /* offset to structure */
-	uint32_t off_dt_strings;	 /* offset to strings */
-	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
-	uint32_t version;		 /* format version */
-	uint32_t last_comp_version;	 /* last compatible version */
-
-	/* version 2 fields below */
-	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
-					    booting on */
-	/* version 3 fields below */
-	uint32_t size_dt_strings;	 /* size of the strings block */
-
-	/* version 17 fields below */
-	uint32_t size_dt_struct;	 /* size of the structure block */
-};
+// string macros from git://git.denx.de/u-boot.git/include/image.h
+
+#define FIT_IMAGES_PATH         "/images"
+#define FIT_DATA_PROP           "data"
+#define FIT_DATA_POSITION_PROP  "data-position"
+#define FIT_DATA_OFFSET_PROP    "data-offset"
+#define FIT_DATA_SIZE_PROP      "data-size"
+
+// functions from git://git.denx.de/u-boot.git/common/image-fit.c
+
+/**
+ * fit_image_get_data - get data property and its size for a given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @data: double pointer to void, will hold data property's data address
+ * @size: pointer to size_t, will hold data property's data size
+ *
+ * fit_image_get_data() finds data property in a given component image node.
+ * If the property is found its data start address and size are returned to
+ * the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+static int fit_image_get_data(const void *fit, int noffset,
+		const void **data, size_t *size)
+{
+	int len;
+
+	*data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
+	if (*data == NULL) {
+		*size = 0;
+		return -1;
+	}
+
+	*size = len;
+	return 0;
+}
+
+
+/**
+ * Get 'data-offset' property from a given image node.
+ *
+ * @fit: pointer to the FIT image header
+ * @noffset: component image node offset
+ * @data_offset: holds the data-offset property
+ *
+ * returns:
+ *     0, on success
+ *     -ENOENT if the property could not be found
+ */
+static int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset)
+{
+	const fdt32_t *val;
+
+	val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL);
+	if (!val)
+		return -ENOENT;
+
+	*data_offset = fdt32_to_cpu(*val);
+
+	return 0;
+}
+
+/**
+ * Get 'data-position' property from a given image node.
+ *
+ * @fit: pointer to the FIT image header
+ * @noffset: component image node offset
+ * @data_position: holds the data-position property
+ *
+ * returns:
+ *     0, on success
+ *     -ENOENT if the property could not be found
+ */
+static int fit_image_get_data_position(const void *fit, int noffset,
+				int *data_position)
+{
+	const fdt32_t *val;
+
+	val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL);
+	if (!val)
+		return -ENOENT;
+
+	*data_position = fdt32_to_cpu(*val);
+
+	return 0;
+}
+
+/**
+ * Get 'data-size' property from a given image node.
+ *
+ * @fit: pointer to the FIT image header
+ * @noffset: component image node offset
+ * @data_size: holds the data-size property
+ *
+ * returns:
+ *     0, on success
+ *     -ENOENT if the property could not be found
+ */
+static int fit_image_get_data_size(const void *fit, int noffset, int *data_size)
+{
+	const fdt32_t *val;
+
+	val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL);
+	if (!val)
+		return -ENOENT;
+
+	*data_size = fdt32_to_cpu(*val);
+
+	return 0;
+}
+
+/**
+ * fit_image_get_data_and_size - get data and its size including
+ *				 both embedded and external data
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @data: double pointer to void, will hold data property's data address
+ * @size: pointer to size_t, will hold data property's data size
+ *
+ * fit_image_get_data_and_size() finds data and its size including
+ * both embedded and external data. If the property is found
+ * its data start address and size are returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     otherwise, on failure
+ */
+static int fit_image_get_data_and_size(const void *fit, int noffset,
+				const void **data, size_t *size)
+{
+	bool external_data = false;
+	int offset;
+	int len;
+	int ret;
+
+	if (!fit_image_get_data_position(fit, noffset, &offset)) {
+		external_data = true;
+	} else if (!fit_image_get_data_offset(fit, noffset, &offset)) {
+		external_data = true;
+		/*
+		 * For FIT with external data, figure out where
+		 * the external images start. This is the base
+		 * for the data-offset properties in each image.
+		 */
+		offset += ((fdt_totalsize(fit) + 3) & ~3);
+	}
+
+	if (external_data) {
+		ret = fit_image_get_data_size(fit, noffset, &len);
+		if (!ret) {
+			*data = fit + offset;
+			*size = len;
+		}
+	} else {
+		ret = fit_image_get_data(fit, noffset, data, size);
+	}
+
+	return ret;
+}
 
 static int
 mtdsplit_fit_parse(struct mtd_info *mtd,
@@ -56,8 +201,11 @@ mtdsplit_fit_parse(struct mtd_info *mtd,
 	size_t offset;
 	size_t fit_offset, fit_size;
 	size_t rootfs_offset, rootfs_size;
+	size_t data_size, img_total, max_size = 0;
 	struct mtd_partition *parts;
-	int ret;
+	int ret, ndepth, noffset, images_noffset;
+	const void *img_data;
+	void *fit;
 
 	of_property_read_string(np, "openwrt,cmdline-match", &cmdline_match);
 	if (cmdline_match && !strstr(saved_command_line, cmdline_match))
@@ -99,31 +247,87 @@ mtdsplit_fit_parse(struct mtd_info *mtd,
 		return -ENODEV;
 	}
 
-	/* Search for the rootfs partition after the FIT image */
-	ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size, mtd->size,
-				   &rootfs_offset, NULL);
-	if (ret) {
-		pr_info("no rootfs found after FIT image in \"%s\"\n",
-			mtd->name);
-		return ret;
-	}
+	/*
+	 * Classic uImage.FIT has all data embedded into the FDT
+	 * data structure. Hence the total size of the image equals
+	 * the total size of the FDT structure.
+	 * Modern uImage.FIT may have only references to data in FDT,
+	 * hence we need to parse FDT structure to find the end of the
+	 * last external data refernced.
+	 */
+	if (fit_size > 0x1000) {
+		/* Search for the rootfs partition after the FIT image */
+		ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size, mtd->size,
+					   &rootfs_offset, NULL);
+		if (ret) {
+			pr_info("no rootfs found after FIT image in \"%s\"\n",
+				mtd->name);
+			return ret;
+		}
+
+		rootfs_size = mtd->size - rootfs_offset;
+
+		parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL);
+		if (!parts)
+			return -ENOMEM;
+
+		parts[0].name = KERNEL_PART_NAME;
+		parts[0].offset = fit_offset;
+		parts[0].size = mtd_rounddown_to_eb(fit_size, mtd) + mtd->erasesize;
+
+		parts[1].name = ROOTFS_PART_NAME;
+		parts[1].offset = rootfs_offset;
+		parts[1].size = rootfs_size;
+
+		*pparts = parts;
+
+		return 2;
+	} else {
+		/* Search for rootfs_data after FIT external data */
+		fit = kzalloc(fit_size, GFP_KERNEL);
+		ret = mtd_read(mtd, offset, fit_size, &retlen, fit);
+		if (ret) {
+			pr_err("read error in \"%s\" at offset 0x%llx\n",
+			       mtd->name, (unsigned long long) offset);
+			return ret;
+		}
+
+		images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+		if (images_noffset < 0) {
+			pr_err("Can't find images parent node '%s' (%s)\n",
+			FIT_IMAGES_PATH, fdt_strerror(images_noffset));
+			return -ENODEV;
+		}
 
-	rootfs_size = mtd->size - rootfs_offset;
+		for (ndepth = 0,
+		     noffset = fdt_next_node(fit, images_noffset, &ndepth);
+		     (noffset >= 0) && (ndepth > 0);
+		     noffset = fdt_next_node(fit, noffset, &ndepth)) {
+			if (ndepth == 1) {
+				ret = fit_image_get_data_and_size(fit, noffset, &img_data, &data_size);
+				if (ret)
+					return 0;
 
-	parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL);
-	if (!parts)
-		return -ENOMEM;
+				img_total = data_size + (img_data - fit);
 
-	parts[0].name = KERNEL_PART_NAME;
-	parts[0].offset = fit_offset;
-	parts[0].size = mtd_rounddown_to_eb(fit_size, mtd) + mtd->erasesize;
+				max_size = (max_size > img_total) ? max_size : img_total;
+			}
+		}
+
+		parts = kzalloc(sizeof(*parts), GFP_KERNEL);
+		if (!parts)
+			return -ENOMEM;
+
+		parts[0].name = ROOTFS_SPLIT_NAME;
+		parts[0].offset = fit_offset + mtd_rounddown_to_eb(max_size, mtd) + mtd->erasesize;
+		parts[0].size = mtd->size - parts[0].offset;
 
-	parts[1].name = ROOTFS_PART_NAME;
-	parts[1].offset = rootfs_offset;
-	parts[1].size = rootfs_size;
+		*pparts = parts;
 
-	*pparts = parts;
-	return 2;
+		kfree(fit);
+
+		return 1;
+	}
 }
 
 static const struct of_device_id mtdsplit_fit_of_match_table[] = {