ipq806x: Added support for compressed dtb images

This commit lays a foundation for packing multiple dtb
images in a single itb image, by supporting compressed dtb
images. This is basically to support all boards across
different soc versions in a single itb image.
The plan is to compress the dtb images, so as to save flash space.

Change-Id: Iba81e311cfda55696209cf99c81e062980629871
Signed-off-by: Gokul Sriram Palanisamy <gpalan@codeaurora.org>
diff --git a/common/bootm.c b/common/bootm.c
index 58936ca..9c8d28a 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -334,6 +334,11 @@
 	*load_end = load;
 	print_decomp_msg(comp, type, load == image_start);
 
+#if defined(CONFIG_DTB_COMPRESSION)
+	if(type == IH_TYPE_FLATDT)
+		unc_len = CONFIG_DTB_LOAD_MAXLEN;
+#endif
+
 	/*
 	 * Load the image to the right place, decompressing if needed. After
 	 * this, image_len will be set to the number of uncompressed bytes
@@ -413,8 +418,8 @@
 }
 
 #ifndef USE_HOSTCC
-static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
-			 int boot_progress)
+int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
+		  int boot_progress)
 {
 	image_info_t os = images->os;
 	ulong load = os.load;
@@ -437,8 +442,10 @@
 	}
 	flush_cache(load, (*load_end - load) * sizeof(ulong));
 
-	debug("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end);
-	bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
+	debug("   %s loaded at 0x%08lx, end = 0x%08lx\n",
+	      genimg_get_type_name(os.type), load, *load_end);
+	if (os.type == IH_TYPE_KERNEL)
+		bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
 
 	no_overlap = (os.comp == IH_COMP_NONE && load == image_start);
 
diff --git a/common/image-fit.c b/common/image-fit.c
index c531ee7..fb66c46 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1569,6 +1569,10 @@
 	uint8_t os;
 	const char *prop_name;
 	int ret;
+#if defined(CONFIG_DTB_COMPRESSION)
+	bootm_headers_t fdt = {0};
+#endif
+	uint8_t comp_type = IH_COMP_NONE;
 
 	fit = map_sysmem(addr, 0);
 	fit_uname = fit_unamep ? *fit_unamep : NULL;
@@ -1650,11 +1654,13 @@
 		return -ENOEXEC;
 	}
 #endif
+#if !defined(CONFIG_DTB_COMPRESSION)
 	if (image_type == IH_TYPE_FLATDT &&
 	    !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
 		puts("FDT image is compressed");
 		return -EPROTONOSUPPORT;
 	}
+#endif
 
 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
 	type_ok = fit_image_check_type(fit, noffset, image_type) ||
@@ -1691,10 +1697,30 @@
 	}
 	len = (ulong)size;
 
-	/* verify that image data is a proper FDT blob */
-	if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
-		puts("Subimage data is not a FDT");
-		return -ENOEXEC;
+#if defined(CONFIG_DTB_COMPRESSION)
+	if (!fit_image_get_comp(fit, noffset, &comp_type)
+				&& (comp_type != IH_COMP_NONE)) {
+		printf("   %s %s image found\n",
+		       genimg_get_comp_name(comp_type), prop_name);
+		if (fit_image_get_load(fit, noffset,
+				       &load) != 0) {
+			printf("ERROR: load address not found for "
+			       "compressed %s..\n", prop_name);
+			return -EFAULT;
+		} else {
+			fdt.os.comp = comp_type;
+			fdt.os.type = IH_TYPE_FLATDT;
+			printf("   %s load address is: 0x%08x\n", prop_name,
+			       (unsigned int)load);
+		}
+	}
+#endif
+	if (comp_type == IH_COMP_NONE) {
+		/* verify that image data is a proper FDT blob */
+		if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
+			puts("Subimage data is not a FDT");
+			return -ENOEXEC;
+		}
 	}
 
 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
@@ -1722,7 +1748,6 @@
 	} else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
 		ulong image_start, image_end;
 		ulong load_end;
-		void *dst;
 
 		/*
 		 * move image data to the load address,
@@ -1741,8 +1766,27 @@
 		printf("   Loading %s from 0x%08lx to 0x%08lx\n",
 		       prop_name, data, load);
 
-		dst = map_sysmem(load, len);
+#if defined(CONFIG_DTB_COMPRESSION)
+		if (comp_type != IH_COMP_NONE) {
+			fdt.os.image_start = (ulong)data;
+			fdt.os.image_len = len;
+			fdt.os.load = load;
+			if (!bootm_load_os(&fdt, &load_end, 1)) {
+				/*
+				 * verify that uncompressed image
+				 * data is a proper FDT blob
+				 * */
+				if (fdt_check_header((char *)load) != 0) {
+					printf("Error: Uncompresed FIT Subimage"
+					       " data is not a %s", prop_name);
+					return -ENOEXEC;
+				}
+			}
+		}
+#else
+		void *dst = map_sysmem(load, len);
 		memmove(dst, buf, len);
+#endif
 		data = load;
 	}
 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
diff --git a/include/image.h b/include/image.h
index c34c230..61ad3a8 100644
--- a/include/image.h
+++ b/include/image.h
@@ -917,6 +917,9 @@
 int calculate_hash(const void *data, int data_len, const char *algo,
 			uint8_t *value, int *value_len);
 
+int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
+		  int boot_progress);
+
 /*
  * At present we only support signing on the host, and verification on the
  * device