Merge "aboot: improve appended device tree support"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 9a45feb..55e8aeb 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -106,8 +106,6 @@
 /* Assuming unauthorized kernel image by default */
 static int auth_kernel_img = 0;
 
-static uint32_t app_dev_tree = 0;
-
 static device_info device = {DEVICE_MAGIC, 0, 0};
 
 static struct udc_device surf_udc_device = {
@@ -466,7 +464,6 @@
 	unsigned offset = 0;
 	unsigned long long ptn = 0;
 	const char *cmdline;
-	void *tags;
 	int index = INVALID_PTN;
 
 	unsigned char *image_addr = 0;
@@ -611,15 +608,18 @@
 			/* Read device device tree in the "tags_add */
 			memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry_ptr->offset, dt_entry_ptr->size);
 		} else {
-				/*
-				 * Look for appended device tree if DTB is not found in boot image
-				 * If found load the kernel & boot up
-				 */
-				app_dev_tree = dev_tree_appended((void*) hdr->kernel_addr);
-				if (!app_dev_tree) {
-					dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
-					return -1;
-				}
+			/*
+			 * If appended dev tree is found, update the atags with
+			 * memory address to the DTB appended location on RAM.
+			 * Else update with the atags address in the kernel header
+			 */
+			void *dtb;
+			dtb = dev_tree_appended((void*) hdr->kernel_addr,
+						(void *)hdr->tags_addr);
+			if (!dtb) {
+				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+				return -1;
+			}
 		}
 		#endif
 		/* Make sure everything from scratch address is read before next step!*/
@@ -705,15 +705,18 @@
 				return -1;
 			}
 		} else {
-				/*
-				 * Look for appended device tree if DTB is not found in boot image
-				 * If found load the kernel & boot up
-				 */
-				app_dev_tree = dev_tree_appended((void*) hdr->kernel_addr);
-				if (!app_dev_tree) {
-					dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
-					return -1;
-				}
+			/*
+			 * If appended dev tree is found, update the atags with
+			 * memory address to the DTB appended location on RAM.
+			 * Else update with the atags address in the kernel header
+			 */
+			void *dtb;
+			dtb = dev_tree_appended((void*) hdr->kernel_addr,
+						(void *)hdr->tags_addr);
+			if (!dtb) {
+				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+				return -1;
+			}
 		}
 		#endif
 	}
@@ -726,17 +729,7 @@
 		cmdline = DEFAULT_CMDLINE;
 	}
 
-	/*
-	 * If appended dev tree is found, update the atags with
-	 * memory address to the DTB appended location on RAM.
-	 * Else update with the atags address in the kernel header
-	 */
-	if (app_dev_tree)
-		tags = (void *)app_dev_tree;
-	else
-		tags = (void *)hdr->tags_addr;
-
-	boot_linux((void *)hdr->kernel_addr, (unsigned *)tags,
+	boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
 		   (const char *)cmdline, board_machtype(),
 		   (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
 
@@ -1188,12 +1181,14 @@
 				dt_entry_ptr->size);
 	} else {
 		/*
-		 * Look for appended device tree if DTB is not found in boot image
-		 * If found load the kernel & boot up
+		 * If appended dev tree is found, update the atags with
+		 * memory address to the DTB appended location on RAM.
+		 * Else update with the atags address in the kernel header
 		 */
-		memmove((void*) hdr->kernel_addr, boot_image_start + page_size, hdr->kernel_size);
-		app_dev_tree = dev_tree_appended((void*) hdr->kernel_addr);
-		if (!app_dev_tree) {
+		void *dtb;
+		dtb = dev_tree_appended((void *)hdr->kernel_addr,
+					(void *)hdr->tags_addr);
+		if (!dtb) {
 			dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
 			return -1;
 		}
@@ -1210,7 +1205,6 @@
 	unsigned ramdisk_actual;
 	struct boot_img_hdr *hdr;
 	char *ptr = ((char*) data);
-	void *tags;
 
 	if (sz < sizeof(hdr)) {
 		fastboot_fail("invalid bootimage header");
@@ -1241,6 +1235,9 @@
 		return;
 	}
 
+	memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
+	memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
+
 #if DEVICE_TREE
 	/* find correct dtb and copy it to right location */
 	if(copy_dtb(data))
@@ -1253,20 +1250,7 @@
 	fastboot_okay("");
 	udc_stop();
 
-	memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
-	memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
-
-	/*
-	 * If appended dev tree is found, update the atags with
-	 * memory address to the DTB appended location on RAM.
-	 * Else update with the atags address in the kernel header
-	 */
-	if (app_dev_tree)
-		tags = (void *)app_dev_tree;
-	else
-		tags = (void *)hdr->tags_addr;
-
-	boot_linux((void*) hdr->kernel_addr, (void*) tags,
+	boot_linux((void*) hdr->kernel_addr, (void*) hdr->tags_addr,
 		   (const char*) hdr->cmdline, board_machtype(),
 		   (void*) hdr->ramdisk_addr, hdr->ramdisk_size);
 }
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 6a06a12..bb3bf64 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -40,25 +40,37 @@
 extern uint32_t target_dev_tree_mem(void *fdt, uint32_t memory_node_offset);
 
 /*
- * Argument:     Start address of the kernel loaded in RAM
+ * Will relocate the DTB to the tags addr if the device tree is found and return
+ * its address
+ *
+ * Arguments:    kernel - Start address of the kernel loaded in RAM
+ *               tags - Start address of the tags loaded in RAM
  * Return Value: DTB address : If appended device tree is found
- *               '0'         : Otherwise
+ *               'NULL'         : Otherwise
  */
-uint32_t dev_tree_appended(void *kernel)
+void *dev_tree_appended(void *kernel, void *tags)
 {
 	uint32_t app_dtb_offset = 0;
 	uint32_t dtb_magic = 0;
-	uint32_t dtb = 0;
 
 	memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
 	memcpy((void*) &dtb_magic, (void*) (kernel + app_dtb_offset), sizeof(uint32_t));
 
 	if (dtb_magic == DTB_MAGIC) {
+		void *dtb;
+		int rc;
+
 		dprintf(INFO, "Found Appeneded Flattened Device tree\n");
-		dtb = (uint32_t) (kernel + app_dtb_offset);
+		dtb = kernel + app_dtb_offset;
+		rc = fdt_open_into(dtb, tags, fdt_totalsize(dtb) + DTB_PAD_SIZE);
+		if (rc == 0) {
+			/* clear out the old DTB magic so kernel doesn't find it */
+			*((uint32_t *)dtb) = 0;
+			return tags;
+		}
 	}
 
-	return dtb;
+	return NULL;
 }
 
 /* Function to return the pointer to the start of the correct device tree
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 389ab49..a27fafd 100644
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -40,6 +40,8 @@
 #define DTB_MAGIC               0xedfe0dd0
 #define DTB_OFFSET              0x2C
 
+#define DTB_PAD_SIZE            1024
+
 struct dt_entry
 {
 	uint32_t platform_id;
@@ -65,5 +67,5 @@
 struct dt_entry * dev_tree_get_entry_ptr(struct dt_table *);
 int update_device_tree(void *, const char *, void *, unsigned);
 int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint32_t size, uint32_t addr);
-uint32_t dev_tree_appended(void *);
+void *dev_tree_appended(void *kernel, void *tags);
 #endif