Merge "app: aboot: Allow dynamic detection of device tree header size."
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 74c81b1..c9f763e 100755
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -624,6 +624,7 @@
 	struct dt_entry dt_entry;
 	unsigned dt_table_offset;
 	uint32_t dt_actual;
+	uint32_t dt_hdr_size;
 #endif
 	if (!boot_into_recovery) {
 		memset(ffbm_mode_string, '\0', sizeof(ffbm_mode_string));
@@ -773,15 +774,14 @@
 
 		#if DEVICE_TREE
 		if(hdr->dt_size) {
-			table = (struct dt_table*) dt_buf;
 			dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
+			table = (struct dt_table*) dt_table_offset;
 
-			memmove((void *) dt_buf, (char *)dt_table_offset, page_size);
-
-			if (dev_tree_validate(table, hdr->page_size) != 0) {
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 				return -1;
 			}
+
 			/* Find index of device tree within device tree table */
 			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
 				dprintf(CRITICAL, "ERROR: Device Tree Blob cannot be found\n");
@@ -852,18 +852,28 @@
 
 		#if DEVICE_TREE
 		if(hdr->dt_size != 0) {
-			/* Read the device tree table into buffer */
+			/* Read the first page of device tree table into buffer */
 			if(mmc_read(ptn + offset,(unsigned int *) dt_buf, page_size)) {
 				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
 				return -1;
 			}
 			table = (struct dt_table*) dt_buf;
 
-			if (dev_tree_validate(table, hdr->page_size) != 0) {
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 				return -1;
 			}
 
+			table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
+			if (!table)
+				return -1;
+
+			/* Read the entire device tree table into buffer */
+			if(mmc_read(ptn + offset,(unsigned int *) table, dt_hdr_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+
 			/* Find index of device tree within device tree table */
 			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
 				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
@@ -935,6 +945,7 @@
 	struct dt_table *table;
 	struct dt_entry dt_entry;
 	uint32_t dt_actual;
+	uint32_t dt_hdr_size;
 #endif
 
 	if (target_is_emmc_boot()) {
@@ -1126,11 +1137,22 @@
 
 			table = (struct dt_table*) dt_buf;
 
-			if (dev_tree_validate(table, hdr->page_size) != 0) {
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 				return -1;
 			}
 
+			table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
+			if (!table)
+				return -1;
+
+			/* Read the entire device tree table into buffer */
+			if(flash_read(ptn, offset, (void *)table, dt_hdr_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+
+
 			/* Find index of device tree within device tree table */
 			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
 				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
@@ -1335,6 +1357,7 @@
 	uint32_t n;
 	struct dt_table *table;
 	struct dt_entry dt_entry;
+	uint32_t dt_hdr_size;
 
 	struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
 
@@ -1358,7 +1381,7 @@
 		/* offset now point to start of dt.img */
 		table = (struct dt_table*)(boot_image_start + dt_image_offset);
 
-		if (dev_tree_validate(table, hdr->page_size) != 0) {
+		if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 			dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 			return -1;
 		}
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 4e1d44f..7ff5a82 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -197,9 +197,10 @@
 }
 
 /* Returns 0 if the device tree is valid. */
-int dev_tree_validate(struct dt_table *table, unsigned int page_size)
+int dev_tree_validate(struct dt_table *table, unsigned int page_size, uint32_t *dt_hdr_size)
 {
 	int dt_entry_size;
+	uint32_t hdr_size;
 
 	/* Validate the device tree table header */
 	if(table->magic != DEV_TREE_MAGIC) {
@@ -217,8 +218,11 @@
 		return -1;
 	}
 
-	/* Restriction that the device tree entry table should be less than a page*/
-	ASSERT(((table->num_entries * dt_entry_size)+ DEV_TREE_HEADER_SIZE) < page_size);
+	hdr_size = table->num_entries * dt_entry_size + DEV_TREE_HEADER_SIZE;
+	/* Roundup to page_size. */
+	hdr_size = ROUNDUP(hdr_size, page_size);
+
+	*dt_hdr_size = hdr_size;
 
 	return 0;
 }
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 2a8ee01..b88a47d 100644
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -66,7 +66,7 @@
 	DT_OP_FAILURE = -1,
 };
 
-int dev_tree_validate(struct dt_table *table, unsigned int page_size);
+int dev_tree_validate(struct dt_table *table, unsigned int page_size, uint32_t *dt_hdr_size);
 int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info);
 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);