platform: msm_shared: Change to parse recovery image for dtbo selection.

The recovery partition must be self-sufficient and cannot depend
on other partitions. While booting into recovery, the bootloader
must load the DTBO image that is compatible with the recovery image.
Change check the header version for appended DTBO, and extracts
appended dtbo in case booting into recovery mode.

Change-Id: Idfb0e0113d72c0fb40b346a6281b259c00a40d05
diff --git a/platform/msm_shared/boot_verifier.c b/platform/msm_shared/boot_verifier.c
index ced0fac..e547d81 100644
--- a/platform/msm_shared/boot_verifier.c
+++ b/platform/msm_shared/boot_verifier.c
@@ -782,11 +782,11 @@
 #if OSVERSION_IN_BOOTIMAGE
 void set_os_version(unsigned char* img_addr)
 {
-	struct boot_img_hdr *img_hdr = NULL;
+	boot_img_hdr *img_hdr = NULL;
 
 	/* Extract the os version and patch level */
 	if (img_addr) {
-		img_hdr = (struct boot_img_hdr *)img_addr;
+		img_hdr = (boot_img_hdr *)img_addr;
 		boot_state_info.system_version = (img_hdr->os_version & 0xFFFFF800) >> 11;
 		boot_state_info.system_security_level = (img_hdr->os_version & 0x7FF);
 	} else {
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 12d39b3..6a99514 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -176,77 +176,90 @@
 	dtbo_error ret = DTBO_SUCCESS;
 	static bool dtbo_loaded = false;
 	static unsigned long long ptn_size = 0;
+	uint32_t recovery_dtbo_size = 0;
+	void *recovery_appended_dtbo = NULL;
 
 	/* If dtbo loaded skip loading */
 	if (dtbo_loaded)
 		goto out;
 
-	/* Immediately return if dtbo is not supported */
-	index = partition_get_index("dtbo");
-	if (index == INVALID_PTN)
-	{
-		ret = DTBO_NOT_SUPPORTED;
-		goto out;
-	}
+	get_recovery_dtbo_info(&recovery_dtbo_size, &recovery_appended_dtbo);
 
-	ptn = partition_get_offset(index);
-	if(!ptn)
-	{
-		dprintf(CRITICAL, "ERROR: dtbo parition failed to get offset. \n");
-		ret = DTBO_ERROR;
-		goto out;
-	}
+	/* Intialize dtbo for recovery header v1 */
+	if (recovery_dtbo_size && recovery_appended_dtbo) {
+		dtbo_image_buf = recovery_appended_dtbo;
+		dtbo_partition_size = recovery_dtbo_size;
+		ptn_size = recovery_dtbo_size;
+	} else {
+		index = partition_get_index("dtbo");
 
-	ptn_size = partition_get_size(index);
-	if (ptn_size > MAX_SUPPORTED_DTBO_IMG_BUF)
-	{
-		dprintf(CRITICAL, "ERROR: dtbo parition size is greater than supported.\n");
-		ret = DTBO_ERROR;
-		goto out;
-	}
 
-/*
-	Read dtbo image into scratch region after kernel image.
-	dtbo_image_buf_size = total_scratch_region_size - boot_img_sz
-*/
-	boot_img_sz = partition_get_size(partition_get_index("boot"));
-	if (!boot_img_sz)
-	{
-		dprintf(CRITICAL, "ERROR: Unable to get boot partition size\n");
-		ret = DTBO_NOT_SUPPORTED;
-		goto out;
-	}
+		/* Immediately return if dtbo is not supported */
+		if (index == INVALID_PTN)
+		{
+			ret = DTBO_NOT_SUPPORTED;
+			goto out;
+		}
 
-	dtbo_image_buf_size = target_get_max_flash_size() - boot_img_sz;
-	dtbo_partition_size = ptn_size + ADDR_ALIGNMENT;
-	dtbo_partition_size = ROUND_TO_PAGE(dtbo_partition_size, (page_size - 1)); /* Maximum dtbo size possible */
-	if (dtbo_partition_size == UINT_MAX ||
-		dtbo_image_buf_size < dtbo_partition_size)
-	{
-		dprintf(CRITICAL, "ERROR: Invalid DTBO partition size\n");
-		ret = DTBO_NOT_SUPPORTED;
-		goto out;
-	}
+		ptn = partition_get_offset(index);
+		if(!ptn)
+		{
+			dprintf(CRITICAL, "ERROR: dtbo parition failed to get offset. \n");
+			ret = DTBO_ERROR;
+			goto out;
+		}
 
-	mmc_set_lun(partition_get_lun(index));
-	/* read dtbo at last 10MB of scratch */
-	dtbo_image_buf = target_get_scratch_address() +
-				(target_get_max_flash_size() - DTBO_IMG_BUF);
-	dtbo_image_buf =
-		(void *)ROUND_TO_PAGE((addr_t)dtbo_image_buf, (ADDR_ALIGNMENT-1) );
-	if(dtbo_image_buf == (void *)UINT_MAX)
-	{
-		dprintf(CRITICAL, "ERROR: Invalid DTBO image buf addr\n");
-		ret = DTBO_NOT_SUPPORTED;
-		goto out;
-	}
+		ptn_size = partition_get_size(index);
+		if (ptn_size > MAX_SUPPORTED_DTBO_IMG_BUF)
+		{
+			dprintf(CRITICAL, "ERROR: dtbo parition size is greater than supported.\n");
+			ret = DTBO_ERROR;
+			goto out;
+		}
 
-	/* Read dtbo partition with header */
-	if (mmc_read(ptn, (uint32_t *)(dtbo_image_buf), dtbo_partition_size))
-	{
-		dprintf(CRITICAL, "ERROR: dtbo partition mmc read failure \n");
-		ret = DTBO_ERROR;
-		goto out;
+		/*
+		Read dtbo image into scratch region after kernel image.
+		dtbo_image_buf_size = total_scratch_region_size - boot_img_sz
+		*/
+		boot_img_sz = partition_get_size(partition_get_index("boot"));
+		if (!boot_img_sz)
+		{
+			dprintf(CRITICAL, "ERROR: Unable to get boot partition size\n");
+			ret = DTBO_NOT_SUPPORTED;
+			goto out;
+		}
+
+		dtbo_image_buf_size = target_get_max_flash_size() - boot_img_sz;
+		dtbo_partition_size = ptn_size + ADDR_ALIGNMENT;
+		dtbo_partition_size = ROUND_TO_PAGE(dtbo_partition_size, (page_size - 1)); /* Maximum dtbo size possible */
+		if (dtbo_partition_size == UINT_MAX ||
+			dtbo_image_buf_size < dtbo_partition_size)
+		{
+			dprintf(CRITICAL, "ERROR: Invalid DTBO partition size\n");
+			ret = DTBO_NOT_SUPPORTED;
+			goto out;
+		}
+
+		mmc_set_lun(partition_get_lun(index));
+		/* read dtbo at last 10MB of scratch */
+		dtbo_image_buf = target_get_scratch_address() +
+					(target_get_max_flash_size() - DTBO_IMG_BUF);
+		dtbo_image_buf =
+			(void *)ROUND_TO_PAGE((addr_t)dtbo_image_buf, (ADDR_ALIGNMENT-1) );
+		if(dtbo_image_buf == (void *)UINT_MAX)
+		{
+			dprintf(CRITICAL, "ERROR: Invalid DTBO image buf addr\n");
+			ret = DTBO_NOT_SUPPORTED;
+			goto out;
+		}
+
+		/* Read dtbo partition with header */
+		if (mmc_read(ptn, (uint32_t *)(dtbo_image_buf), dtbo_partition_size))
+		{
+			dprintf(CRITICAL, "ERROR: dtbo partition mmc read failure \n");
+			ret = DTBO_ERROR;
+			goto out;
+		}
 	}
 
 	/* validate the dtbo image, before reading complete image */
diff --git a/platform/msm_shared/include/boot_device.h b/platform/msm_shared/include/boot_device.h
index 4eb172c..2e2a02f 100644
--- a/platform/msm_shared/include/boot_device.h
+++ b/platform/msm_shared/include/boot_device.h
@@ -78,6 +78,7 @@
 	char *vbcmdline;
 	uint32_t vbcmdline_len;
 	uint32_t vbcmdline_filled_len;
+	uint32_t header_version;
 	void *vb_data;
 } bootinfo;
 
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index a9ea7a6..1d8dd07 100644
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -249,6 +249,7 @@
 }dtbo_error;
 
 dtbo_error load_validate_dtbo_image(void **dtbo_img, uint32_t *dtbo_img_size);
+void get_recovery_dtbo_info(uint32_t *dtbo_size, void **dtbo_buf);
 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 *fdt, const char *, void *, unsigned);