Merge "target: msm8909: add serial number support to  NAND device"
diff --git a/AndroidBoot.mk b/AndroidBoot.mk
index eab4f85..8697f7d 100644
--- a/AndroidBoot.mk
+++ b/AndroidBoot.mk
@@ -51,6 +51,12 @@
   VERIFIED_BOOT_2 := VERIFIED_BOOT_2=0
 endif
 
+ifeq ($(BOARD_DTBO_NOT_SUPPORTED),true)
+  TARGET_DTBO_NOT_SUPPORTED := TARGET_DTBO_NOT_SUPPORTED=1
+else
+  TARGET_DTBO_NOT_SUPPORTED := TARGET_DTBO_NOT_SUPPORTED=0
+endif
+
 ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
  TARGET_USE_SYSTEM_AS_ROOT_IMAGE := TARGET_USE_SYSTEM_AS_ROOT_IMAGE=1
 else
@@ -119,7 +125,7 @@
 # ELF binary for ABOOT
 TARGET_ABOOT_ELF := $(PRODUCT_OUT)/aboot.elf
 $(TARGET_ABOOT_ELF): ABOOT_CLEAN | $(ABOOT_OUT)
-	$(MAKE) -C $(LK_PATH) TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=$(CROOT_DIR)/$(ABOOT_OUT) $(BOOTLOADER_PLATFORM) $(EMMC_BOOT) $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(VERIFIED_BOOT_2) $(ENABLE_DISPLAY) $(ENABLE_KASLRSEED) $(ENABLE_BOOTDEVICE_MOUNT) $(DEVICE_STATUS) $(BUILD_VARIANT) $(BOARD_NAME) $(ENABLE_VB_ATTEST) $(OSVERSION_IN_BOOTIMAGE) $(QSEECOM_SECAPP_REGION_2MB) $(TARGET_USE_SYSTEM_AS_ROOT_IMAGE)
+	$(MAKE) -C $(LK_PATH) TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=$(CROOT_DIR)/$(ABOOT_OUT) $(BOOTLOADER_PLATFORM) $(EMMC_BOOT) $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(VERIFIED_BOOT_2) $(TARGET_DTBO_NOT_SUPPORTED) $(ENABLE_DISPLAY) $(ENABLE_KASLRSEED) $(ENABLE_BOOTDEVICE_MOUNT) $(DEVICE_STATUS) $(BUILD_VARIANT) $(BOARD_NAME) $(ENABLE_VB_ATTEST) $(OSVERSION_IN_BOOTIMAGE) $(QSEECOM_SECAPP_REGION_2MB) $(TARGET_USE_SYSTEM_AS_ROOT_IMAGE)
 
 # NAND variant output
 TARGET_NAND_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn
@@ -148,7 +154,7 @@
 
 # Top level for eMMC variant targets
 $(TARGET_EMMC_BOOTLOADER): emmc_appsbootldr_clean | $(EMMC_BOOTLOADER_OUT) $(INSTALLED_KEYSTOREIMAGE_TARGET)
-	$(MAKE) -C $(LK_PATH) TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=$(CROOT_DIR)/$(EMMC_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) EMMC_BOOT=1 $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(VERIFIED_BOOT_2) $(ENABLE_DISPLAY) $(ENABLE_KASLRSEED) $(ENABLE_BOOTDEVICE_MOUNT) $(DEVICE_STATUS) $(BUILD_VARIANT) $(BOARD_NAME) $(ENABLE_VB_ATTEST) $(OSVERSION_IN_BOOTIMAGE) $(ENABLE_BG_SUPPORT) $(QSEECOM_SECAPP_REGION_2MB) $(TARGET_USE_SYSTEM_AS_ROOT_IMAGE)
+	$(MAKE) -C $(LK_PATH) TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=$(CROOT_DIR)/$(EMMC_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) EMMC_BOOT=1 $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(VERIFIED_BOOT_2) $(TARGET_DTBO_NOT_SUPPORTED) $(ENABLE_DISPLAY) $(ENABLE_KASLRSEED) $(ENABLE_BOOTDEVICE_MOUNT) $(DEVICE_STATUS) $(BUILD_VARIANT) $(BOARD_NAME) $(ENABLE_VB_ATTEST) $(OSVERSION_IN_BOOTIMAGE) $(ENABLE_BG_SUPPORT) $(QSEECOM_SECAPP_REGION_2MB) $(TARGET_USE_SYSTEM_AS_ROOT_IMAGE)
 
 # Keep build NAND & eMMC as default for targets still using TARGET_BOOTLOADER
 TARGET_BOOTLOADER := $(PRODUCT_OUT)/EMMCBOOT.MBN
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 62cc67a..930621e 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -248,6 +248,9 @@
 static uint32_t dt_size = 0;
 static char *vbcmdline;
 static bootinfo info = {0};
+static void *recovery_dtbo_buf = NULL;
+static uint32_t recovery_dtbo_size = 0;
+
 /* Assuming unauthorized kernel image by default */
 static int auth_kernel_img = 0;
 static device_info device = {DEVICE_MAGIC,0,0,0,0,{0},{0},{0},1,{0},0,{0}};
@@ -345,7 +348,7 @@
 extern int fastboot_trigger(void);
 #endif
 
-static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr, bool is_arm64)
+static void update_ker_tags_rdisk_addr(boot_img_hdr *hdr, bool is_arm64)
 {
 	/* overwrite the destination of specified for the project */
 #ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
@@ -370,6 +373,50 @@
 	memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
 	*ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
 }
+#ifdef VERIFIED_BOOT_2
+void load_vbmeta_image(void **vbmeta_image_buf, uint32_t *vbmeta_image_sz)
+{
+	int index = 0;
+	char *vbm_img_buf = NULL;
+	unsigned long long ptn = 0;
+	unsigned long long ptn_size = 0;
+
+	/* Immediately return if dtbo is not supported */
+	index = partition_get_index("vbmeta");
+	ptn = partition_get_offset(index);
+	if(!ptn)
+	{
+		dprintf(CRITICAL, "ERROR: vbmeta partition not found.\n");
+		return;
+	}
+
+	ptn_size = partition_get_size(index);
+	if (ptn_size > MAX_SUPPORTED_VBMETA_IMG_BUF)
+	{
+		dprintf(CRITICAL, "ERROR: vbmeta parition size is greater than supported.\n");
+		return;
+	}
+
+	vbm_img_buf = (char *)memalign(CACHE_LINE, ROUNDUP((uint32_t)ptn_size, CACHE_LINE));
+	if (!vbm_img_buf)
+	{
+		dprintf(CRITICAL, "ERROR: vbmeta unable to locate buffer\n");
+		return;
+	}
+
+	mmc_set_lun(partition_get_lun(index));
+	if (mmc_read(ptn, (uint32_t *)vbm_img_buf, (uint32_t)ptn_size))
+	{
+		dprintf(CRITICAL, "ERROR: vbmeta read failure\n");
+		free(vbm_img_buf);
+		return;
+	}
+
+	*vbmeta_image_buf = vbm_img_buf;
+	*vbmeta_image_sz = (uint32_t)ptn_size;
+	return;
+}
+#endif
 
 #if CHECK_BAT_VOLTAGE
 void update_battery_status(void)
@@ -1175,20 +1222,23 @@
 
 BUF_DMA_ALIGN(buf, BOOT_IMG_MAX_PAGE_SIZE); //Equal to max-supported pagesize
 
-int getimage(const bootinfo *info, void **image_buffer, uint32_t *imgsize,
-                    char *imgname)
+int getimage(void **image_buffer, uint32_t *imgsize,
+                    const char *imgname)
 {
-	if (info == NULL || image_buffer == NULL || imgsize == NULL ||
+	uint32_t loadedindex;
+	if (image_buffer == NULL || imgsize == NULL ||
 	    imgname == NULL) {
 		dprintf(CRITICAL, "getimage: invalid parameters\n");
 		return -1;
 	}
-
-	for (uint32_t loadedindex = 0; loadedindex < info->num_loaded_images; loadedindex++) {
-		if (!strncmp(info->images[loadedindex].name, imgname,
+	for (loadedindex = 0; loadedindex < info.num_loaded_images; loadedindex++) {
+		if (!strncmp(info.images[loadedindex].name, imgname,
 		                  strlen(imgname))) {
-			*image_buffer = info->images[loadedindex].image_buffer;
-			*imgsize = info->images[loadedindex].imgsize;
+			*image_buffer = info.images[loadedindex].image_buffer;
+			*imgsize = info.images[loadedindex].imgsize;
+			dprintf(SPEW, "getimage(): Loaded image [%s|%d]\n",
+						info.images[loadedindex].name,
+						info.images[loadedindex].imgsize);
 			return 0;
 		}
 	}
@@ -1309,22 +1359,6 @@
 #endif
 }
 
-int get_boot_image_info(void **image_buffer, uint32_t *imgsize,char *imgname)
-{
-    if (image_buffer == NULL || imgsize == NULL || imgname == NULL) {
-        dprintf(CRITICAL, "get_boot_image_info: invalid parameters\n");
-        return -1;
-    }
-
-    if (!strncmp(info.images[0].name, imgname,
-                strlen(imgname))) {
-        *image_buffer = info.images[0].image_buffer;
-        *imgsize = info.images[0].imgsize;
-        return 0;
-    }
-    return -1;
-}
-
 static bool check_format_bit()
 {
 	bool ret = false;
@@ -1394,10 +1428,18 @@
 	}
 }
 
+/* Function to return recovery appended dtbo buffer info */
+void get_recovery_dtbo_info(uint32_t *dtbo_size, void **dtbo_buf)
+{
+	*dtbo_size = recovery_dtbo_size;
+	*dtbo_buf = recovery_dtbo_buf;
+	return;
+}
+
 int boot_linux_from_mmc(void)
 {
-	struct boot_img_hdr *hdr = (void*) buf;
-	struct boot_img_hdr *uhdr;
+	boot_img_hdr *hdr = (void*) buf;
+	boot_img_hdr *uhdr;
 	unsigned offset = 0;
 	int rcode;
 	unsigned long long ptn = 0;
@@ -1417,9 +1459,14 @@
 	unsigned char *kernel_start_addr = NULL;
 	unsigned int kernel_size = 0;
 	unsigned int patched_kernel_hdr_size = 0;
+	uint64_t image_size = 0;
 	int rc;
 #if VERIFIED_BOOT_2
 	int status;
+	void *dtbo_image_buf = NULL;
+	uint32_t dtbo_image_sz = 0;
+	void *vbmeta_image_buf = NULL;
+	uint32_t vbmeta_image_sz = 0;
 #endif
 	char *ptn_name = NULL;
 #if DEVICE_TREE
@@ -1447,7 +1494,7 @@
 			boot_into_ffbm = true;
 	} else
 		boot_into_ffbm = false;
-	uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
+	uhdr = (boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
 	if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
 		dprintf(INFO, "Unified boot method!\n");
 		hdr = uhdr;
@@ -1464,7 +1511,8 @@
 
 	index = partition_get_index(ptn_name);
 	ptn = partition_get_offset(index);
-	if(ptn == 0) {
+	image_size = partition_get_size(index);
+	if(ptn == 0 || image_size == 0) {
 		dprintf(CRITICAL, "ERROR: No %s partition found\n", ptn_name);
 		return -1;
 	}
@@ -1506,6 +1554,8 @@
 #ifndef OSVERSION_IN_BOOTIMAGE
 	dt_size = hdr->dt_size;
 #endif
+	dprintf(INFO, "BootImage Header: %d\n", hdr->header_version);
+
 	dt_actual = ROUND_TO_PAGE(dt_size, page_mask);
 	if (UINT_MAX < ((uint64_t)kernel_actual + (uint64_t)ramdisk_actual+ (uint64_t)second_actual + (uint64_t)dt_actual + page_size)) {
 		dprintf(CRITICAL, "Integer overflow detected in bootimage header fields at %u in %s\n",__LINE__,__FILE__);
@@ -1520,6 +1570,63 @@
 	imagesize_actual = (page_size + kernel_actual + ramdisk_actual + second_actual);
 #endif
 
+#ifdef OSVERSION_IN_BOOTIMAGE
+	/* If header version is ONE and booting into recovery,
+		dtbo is appended with recovery image.
+		Doing following:
+			* Validating the recovery offset and size.
+			* Extracting recovery dtbo to be used as dtbo.
+	*/
+	if (boot_into_recovery &&
+		hdr->header_version == BOOT_HEADER_VERSION_ONE)
+	{
+		struct boot_img_hdr_v1 *hdr1 =
+			(struct boot_img_hdr_v1 *) (image_addr + sizeof(boot_img_hdr));
+
+		if ((hdr1->header_size !=
+				sizeof(struct boot_img_hdr_v1) + sizeof(boot_img_hdr)))
+		{
+			dprintf(CRITICAL, "Invalid boot image header: %d\n", hdr1->header_size);
+			return -1;
+		}
+
+		if (UINT_MAX < (hdr1->recovery_dtbo_offset + hdr1->recovery_dtbo_size)) {
+			dprintf(CRITICAL,
+				"Integer overflow detected in recovery image header fields at %u in %s\n",__LINE__,__FILE__);
+			return -1;
+		}
+
+		if (hdr1->recovery_dtbo_size > MAX_SUPPORTED_DTBO_IMG_BUF) {
+			dprintf(CRITICAL, "Recovery Dtbo Size too big %x, Allowed size %x\n", hdr1->recovery_dtbo_size,
+				MAX_SUPPORTED_DTBO_IMG_BUF);
+			return -1;
+		}
+
+		if (UINT_MAX < ((uint64_t)imagesize_actual + recovery_dtbo_size))
+		{
+			dprintf(CRITICAL, "Integer overflow detected in recoveryimage header fields at %u in %s\n",__LINE__,__FILE__);
+			return -1;
+		}
+
+		if (hdr1->recovery_dtbo_offset + recovery_dtbo_size > image_size)
+		{
+			dprintf(CRITICAL, "Invalid recovery dtbo: Recovery Dtbo Offset=0x%llx,"
+				" Recovery Dtbo Size=0x%x, Image Size=0x%llx\n",
+				hdr1->recovery_dtbo_offset, recovery_dtbo_size, image_size);
+			return -1;
+		}
+
+		recovery_dtbo_buf = (void *)(hdr1->recovery_dtbo_offset + image_addr);
+		recovery_dtbo_size = hdr1->recovery_dtbo_size;
+		imagesize_actual += recovery_dtbo_size;
+
+		dprintf(SPEW, "Header version: %d\n", hdr->header_version);
+		dprintf(SPEW, "Recovery Dtbo Size 0x%x\n", recovery_dtbo_size);
+		dprintf(SPEW, "Recovery Dtbo Offset 0x%llx\n", hdr1->recovery_dtbo_offset);
+
+	}
+#endif
+
 #if VERIFIED_BOOT
 	boot_verifier_init();
 #endif
@@ -1598,11 +1705,37 @@
 		return -1;
 	}
 
+	/* load and validate dtbo partition */
+	load_validate_dtbo_image(&dtbo_image_buf, &dtbo_image_sz);
+
+	/* load vbmeta partition */
+	load_vbmeta_image(&vbmeta_image_buf, &vbmeta_image_sz);
+
 	memset(&info, 0, sizeof(bootinfo));
-	info.images[0].image_buffer = image_addr;
-	info.images[0].imgsize = imagesize_actual;
-	info.images[0].name = "boot";
-	info.num_loaded_images = 0;
+
+	/* Pass loaded boot image passed */
+	info.images[IMG_BOOT].image_buffer = image_addr;
+	info.images[IMG_BOOT].imgsize = imagesize_actual;
+	info.images[IMG_BOOT].name = ptn_name;
+	++info.num_loaded_images;
+
+	/* Pass loaded dtbo image */
+	if (dtbo_image_buf != NULL) {
+		info.images[IMG_DTBO].image_buffer = dtbo_image_buf;
+		info.images[IMG_DTBO].imgsize = dtbo_image_sz;
+		info.images[IMG_DTBO].name = "dtbo";
+		++info.num_loaded_images;
+	}
+
+	/* Pass loaded vbmeta image */
+	if (vbmeta_image_buf != NULL) {
+		info.images[IMG_VBMETA].image_buffer = vbmeta_image_buf;
+		info.images[IMG_VBMETA].imgsize = vbmeta_image_sz;
+		info.images[IMG_VBMETA].name = "vbmeta";
+		++info.num_loaded_images;
+	}
+
+	info.header_version = hdr->header_version;
 	info.multi_slot_boot = partition_multislot_is_supported();
 	info.bootreason_alarm = boot_reason_alarm;
 	info.bootinto_recovery = boot_into_recovery;
@@ -1611,6 +1744,10 @@
 		return -1;
 
 	vbcmdline = info.vbcmdline;
+
+	/* Free the buffer allocated to vbmeta post verification */
+	free(vbmeta_image_buf);
+	--info.num_loaded_images;
 #else
 	/* Change the condition a little bit to include the test framework support.
 	 * We would never reach this point if device is in fastboot mode, even if we did
@@ -1693,6 +1830,10 @@
 	{
 		out_addr = (unsigned char *)(image_addr + imagesize_actual + page_size);
 		out_avai_len = target_get_max_flash_size() - imagesize_actual - page_size;
+#if VERIFIED_BOOT_2
+		if (dtbo_image_sz)
+			out_avai_len -= DTBO_IMG_BUF;
+#endif
 		dprintf(INFO, "decompressing kernel image: start\n");
 		rc = decompress((unsigned char *)(image_addr + page_size),
 				hdr->kernel_size, out_addr, out_avai_len,
@@ -1875,7 +2016,7 @@
 
 int boot_linux_from_flash(void)
 {
-	struct boot_img_hdr *hdr = (void*) buf;
+	boot_img_hdr *hdr = (void*) buf;
 	struct ptentry *ptn;
 	struct ptable *ptable;
 	unsigned offset = 0;
@@ -1898,7 +2039,7 @@
 #endif
 
 	if (target_is_emmc_boot()) {
-		hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
+		hdr = (boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
 		if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
 			dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
 			return -1;
@@ -2683,7 +2824,7 @@
 	unsigned char *best_match_dt_addr = NULL;
 	int rc;
 
-	struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
+	boot_img_hdr *hdr = (boot_img_hdr *) (boot_image_start);
 
 #ifndef OSVERSION_IN_BOOTIMAGE
 	dt_size = hdr->dt_size;
@@ -2771,7 +2912,7 @@
 	unsigned second_actual;
 	uint32_t image_actual;
 	uint32_t dt_actual = 0;
-	struct boot_img_hdr *hdr = NULL;
+	boot_img_hdr *hdr = NULL;
 	struct kernel64_hdr *kptr = NULL;
 	char *ptr = ((char*) data);
 	int ret = 0;
@@ -2809,7 +2950,7 @@
 		goto boot_failed;
 	}
 
-	hdr = (struct boot_img_hdr *)data;
+	hdr = (boot_img_hdr *)data;
 
 	/* ensure commandline is terminated */
 	hdr->cmdline[BOOT_ARGS_SIZE-1] = 0;
@@ -3210,7 +3351,10 @@
 	fs_signature_type ret = NO_FS;
 	int index;
 	unsigned long long ptn;
-	char *sb_buffer = memalign(CACHE_LINE, mmc_blocksize);
+	char *buffer = memalign(CACHE_LINE, mmc_blocksize);
+	uint32_t sb_blk_offset = 0;
+	char *sb_buffer = buffer;
+
 	if (!sb_buffer)
 	{
 		dprintf(CRITICAL, "ERROR: Failed to allocate buffer for superblock\n");
@@ -3225,21 +3369,24 @@
 	}
 	ptn = partition_get_offset(index);
 	mmc_set_lun(partition_get_lun(index));
-	if(mmc_read(ptn + FS_SUPERBLOCK_OFFSET,
+	sb_blk_offset = (FS_SUPERBLOCK_OFFSET/mmc_blocksize);
+
+	if(mmc_read(ptn + (sb_blk_offset * mmc_blocksize),
 				(void *)sb_buffer, mmc_blocksize))
 	{
 		dprintf(CRITICAL, "ERROR: Failed to read Superblock\n");
 		goto out;
 	}
 
-	if (*((uint16 *)(&sb_buffer[EXT_MAGIC_OFFSET_SB]))
-									== (uint16)EXT_MAGIC)
+	if (sb_blk_offset == 0)
+		sb_buffer += FS_SUPERBLOCK_OFFSET;
+
+	if (*((uint16 *)(&sb_buffer[EXT_MAGIC_OFFSET_SB])) == (uint16)EXT_MAGIC)
 	{
 		dprintf(SPEW, "%s() Found EXT FS\n", arg);
 		ret = EXT_FS_SIGNATURE;
 	}
-	else if (*((uint32 *)(&sb_buffer[F2FS_MAGIC_OFFSET_SB]))
-										== F2FS_MAGIC)
+	else if (*((uint32 *)(&sb_buffer[F2FS_MAGIC_OFFSET_SB])) == F2FS_MAGIC)
 	{
 		dprintf(SPEW, "%s() Found F2FS FS\n", arg);
 		ret = EXT_F2FS_SIGNATURE;
@@ -3252,8 +3399,8 @@
 	}
 
 out:
-	if(sb_buffer)
-		free(sb_buffer);
+	if(buffer)
+		free(buffer);
 	return ret;
 }
 
diff --git a/app/aboot/bootimg.h b/app/aboot/bootimg.h
index 7dfbef8..a07db93 100644
--- a/app/aboot/bootimg.h
+++ b/app/aboot/bootimg.h
@@ -31,16 +31,19 @@
 #ifndef _BOOT_IMAGE_H_
 #define _BOOT_IMAGE_H_
 
-typedef struct boot_img_hdr boot_img_hdr;
-
 #define BOOT_MAGIC "ANDROID!"
 #define BOOT_MAGIC_SIZE 8
 #define BOOT_NAME_SIZE  16
 #define BOOT_ARGS_SIZE  512
 #define BOOT_IMG_MAX_PAGE_SIZE 4096
+#define BOOT_EXTRA_ARGS_SIZE 1024
 
-struct boot_img_hdr
-{
+#define BOOT_HEADER_VERSION_ZERO 0
+/* Struct def for boot image header
+  * Bootloader expects the structure of boot_img_hdr with header version
+  * BOOT_HEADER_VERSION_ZERO to be as follows:
+  */
+struct boot_img_hdr_v0 {
     unsigned char magic[BOOT_MAGIC_SIZE];
 
     unsigned kernel_size;  /* size in bytes */
@@ -55,7 +58,7 @@
     unsigned tags_addr;    /* physical addr for kernel tags */
     unsigned page_size;    /* flash page size we assume */
 #if OSVERSION_IN_BOOTIMAGE
-    uint32_t unused;    /* future expansion: should be 0 */
+    uint32_t header_version; /* version for the boot image header */
     uint32_t os_version; /* version << 11 | patch_level */
 #else
     unsigned dt_size;      /* device_tree in bytes */
@@ -66,7 +69,24 @@
     unsigned char cmdline[BOOT_ARGS_SIZE];
 
     unsigned id[8]; /* timestamp / checksum / sha1 / etc */
-};
+
+    /* Supplemental command line data; kept here to maintain
+        * binary compatibility with older versions of mkbootimg
+        */
+    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
+} __attribute__((packed));
+
+/*
+ * It is expected that callers would explicitly specify which version of the
+ * boot image header they need to use.
+ */
+typedef struct boot_img_hdr_v0 boot_img_hdr;
+
+/**
+ * Offset of recovery DTBO length in a boot image header of version V1 or
+ * above.
+  */
+#define BOOT_IMAGE_HEADER_V1_RECOVERY_DTBO_SIZE_OFFSET sizeof (boot_img_hdr)
 
 /*
 ** +-----------------+ 
@@ -78,13 +98,9 @@
 ** +-----------------+
 ** | second stage    | o pages
 ** +-----------------+
-** | device tree     | p pages
-** +-----------------+
-**
 ** n = (kernel_size + page_size - 1) / page_size
 ** m = (ramdisk_size + page_size - 1) / page_size
 ** o = (second_size + page_size - 1) / page_size
-** p = (dt_size + page_size - 1) / page_size
 ** 0. all entities are page_size aligned in flash
 ** 1. kernel and ramdisk are required (size != 0)
 ** 2. second is optional (second_size == 0 -> no second)
@@ -97,6 +113,47 @@
 **    else: jump to kernel_addr
 */
 
+#define BOOT_HEADER_VERSION_ONE 1
+
+struct boot_img_hdr_v1 {
+    uint32_t recovery_dtbo_size;   /* size in bytes for recovery DTBO image */
+    uint64_t recovery_dtbo_offset; /* physical load addr */
+    uint32_t header_size;
+} __attribute__((packed));
+
+/* When the boot image header has a version of BOOT_HEADER_VERSION_ONE,
+ * the structure of the boot image is as follows:
+ *
+ * +-----------------+
+ * | boot header     | 1 page
+ * +-----------------+
+ * | kernel          | n pages
+ * +-----------------+
+ * | ramdisk         | m pages
+ * +-----------------+
+ * | second stage    | o pages
+ * +-----------------+
+ * | recovery dtbo   | p pages
+ * +-----------------+
+ * n = (kernel_size + page_size - 1) / page_size
+ * m = (ramdisk_size + page_size - 1) / page_size
+ * o = (second_size + page_size - 1) / page_size
+ * p = (recovery_dtbo_size + page_size - 1) / page_size
+ *
+ * 0. all entities are page_size aligned in flash
+ * 1. kernel and ramdisk are required (size != 0)
+ * 2. recovery_dtbo is required for recovery.img
+ *    in non-A/B devices(recovery_dtbo_size != 0)
+ * 3. second is optional (second_size == 0 -> no second)
+ * 4. load each element (kernel, ramdisk, second, recovery_dtbo) at
+ *    the specified physical address (kernel_addr, etc)
+ * 5. prepare tags at tag_addr.  kernel_args[] is
+ *    appended to the kernel commandline in the tags.
+ * 6. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+ * 7. if second_size != 0: jump to second_addr
+ *    else: jump to kernel_addr
+ */
+
 boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
                         void *ramdisk, unsigned ramdisk_size,
                         void *second, unsigned second_size,
diff --git a/include/target.h b/include/target.h
index 4cc2812..0a0e545 100644
--- a/include/target.h
+++ b/include/target.h
@@ -108,6 +108,7 @@
 int target_get_qmp_regsize();
 uint32_t target_ddr_cfg_reg();
 
+bool is_target_support_dtbo(void);
 bool target_is_pmi_enabled(void);
 #if PON_VIB_SUPPORT
 void get_vibration_type();
diff --git a/makefile b/makefile
index b2d40a6..f6da064 100644
--- a/makefile
+++ b/makefile
@@ -127,6 +127,10 @@
   DEFINES += _SIGNED_KERNEL=1
 endif
 
+ifeq ($(TARGET_DTBO_NOT_SUPPORTED),1)
+  DEFINES += TARGET_DTBO_NOT_SUPPORTED=1
+endif
+
 ifeq ($(OSVERSION_IN_BOOTIMAGE),1)
  DEFINES += OSVERSION_IN_BOOTIMAGE=1
 endif
diff --git a/platform/msm8952/platform.c b/platform/msm8952/platform.c
index 184f5e2..e865b30 100644
--- a/platform/msm8952/platform.c
+++ b/platform/msm8952/platform.c
@@ -214,6 +214,7 @@
 		case MSM8217:
 		case MSM8617:
 		case APQ8017:
+		case QM215:
 			ret = 1;
 			break;
 		default:
diff --git a/platform/msm_shared/avb/VerifiedBoot.c b/platform/msm_shared/avb/VerifiedBoot.c
index 4150f9a..585d6a9 100644
--- a/platform/msm_shared/avb/VerifiedBoot.c
+++ b/platform/msm_shared/avb/VerifiedBoot.c
@@ -38,12 +38,22 @@
 #include <platform/timer.h>
 #include "verifiedboot.h"
 #include <err.h>
+#include <target.h>
 
 #ifndef DTB_PAD_SIZE
 #define DTB_PAD_SIZE            2048
 #endif
 #define INTERMEDIATE_DIGEST_LENGTH	64
 #define MAX_PART_NAME_SIZE		10
+#define MAX_NUM_REQ_PARTITION	8
+#define BOOT_HEADER_VERSION_ZERO	0
+
+char *avb_verify_partition_name[] = {
+	"boot",
+	"dtbo",
+	"vbmeta",
+	"recovery"
+};
 
 #ifndef MDTP_SUPPORT
 int mdtp_activated(bool * activated)
@@ -337,6 +347,17 @@
 	"aboot",
 };
 
+VOID AddRequestedPartition(CHAR8 **requestedpartititon, UINT32 index)
+{
+	UINTN i;
+	for (i = 0; i < MAX_NUM_REQ_PARTITION; i++) {
+		if (requestedpartititon[i] == NULL){
+			requestedpartititon[i] = avb_verify_partition_name[index];
+			break;
+		}
+	}
+}
+
 static EFI_STATUS load_image_and_authVB2(bootinfo *Info)
 {
 	EFI_STATUS Status = EFI_SUCCESS;
@@ -349,10 +370,10 @@
 	CHAR8 *SlotSuffix = NULL;
 	BOOLEAN AllowVerificationError = !is_device_locked();
 	BOOLEAN VerityEnforcing = is_verity_enforcing();
-	const CHAR8 *RequestedPartitionMission[] = {"boot", "dtbo", NULL};
-	const CHAR8 *RequestedPartitionRecovery[] = {"recovery", "dtbo", NULL};
+	CHAR8 *RequestedPartitionAll[MAX_NUM_REQ_PARTITION] = {NULL};
 	const CHAR8 **RequestedPartition = NULL;
 	UINTN NumRequestedPartition = 0;
+	UINT32 HeaderVersion = 0;
 	UINT32 ImageHdrSize = 0;
 	UINT32 imgsizeActual = 0;
 	VOID *image_buffer = NULL;
@@ -363,6 +384,7 @@
 	AvbHashtreeErrorMode VerityFlags = AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
 	device_info DevInfo_vb;
 
+	HeaderVersion = Info->header_version;
 	Info->boot_state = RED;
 	GUARD(VBCommonInit(Info));
 
@@ -395,27 +417,30 @@
 	}
 
 	if(!Info->multi_slot_boot && Info->bootinto_recovery) {
-		RequestedPartition = RequestedPartitionRecovery;
-	NumRequestedPartition = ARRAY_SIZE (RequestedPartitionRecovery) - 1;
-	if (Info->num_loaded_images) {
-	/* fastboot boot option, skip Index 0, as boot image already
-	 * loaded */
-	RequestedPartition = &RequestedPartitionRecovery[1];
-	}
+		AddRequestedPartition(RequestedPartitionAll, IMG_RECOVERY);
+		NumRequestedPartition += 1;
+		/* Add dtbo validation if target supports dtbo image generation and
+		dtbo is not included in recovery i.e. HEADER VERSION is 0 */
+		if (is_target_support_dtbo() && HeaderVersion == BOOT_HEADER_VERSION_ZERO) {
+			AddRequestedPartition(RequestedPartitionAll, IMG_DTBO);
+			NumRequestedPartition += 1;
+		}
 	} else {
-	RequestedPartition = RequestedPartitionMission;
-        NumRequestedPartition = ARRAY_SIZE(RequestedPartitionMission) - 1;
-        if (Info->num_loaded_images) {
-                /* fastboot boot option, skip Index 0, as boot image already
-                 * loaded */
-                RequestedPartition = &RequestedPartitionMission[1];
+		AddRequestedPartition(RequestedPartitionAll, IMG_BOOT);
+		NumRequestedPartition += 1;
+		if (is_target_support_dtbo()) {
+			AddRequestedPartition(RequestedPartitionAll, IMG_DTBO);
+			NumRequestedPartition += 1;
 		}
 	}
+
+	RequestedPartition = (const CHAR8 **)RequestedPartitionAll;
 	if (Info->num_loaded_images) {
+		/* fastboot boot option, skip Index 0, boot image already loaded */
+		RequestedPartition = (const CHAR8 **)&RequestedPartitionAll[1];
 		NumRequestedPartition--;
 	}
 
-	// FIXME: is this correct?
 	VerityFlags = VerityEnforcing ?
 				AVB_HASHTREE_ERROR_MODE_RESTART :
 				AVB_HASHTREE_ERROR_MODE_EIO;
@@ -494,7 +519,7 @@
 	Info->vb_data = (VOID *)VBData;
 
 	ImageHdrSize = get_page_size();
-	GUARD_OUT(getimage(Info, &image_buffer, &imgsize,(!Info->multi_slot_boot && Info->bootinto_recovery) ? "recovery" : "boot") );
+	GUARD_OUT(getimage(&image_buffer, &imgsize,(!Info->multi_slot_boot && Info->bootinto_recovery) ? "recovery" : "boot") );
 
 	Status = check_img_header(image_buffer, ImageHdrSize, &imgsizeActual);
 	if (Status != EFI_SUCCESS) {
diff --git a/platform/msm_shared/avb/libavb/avb_ops.c b/platform/msm_shared/avb/libavb/avb_ops.c
index ebb84c7..4c1b81c 100644
--- a/platform/msm_shared/avb/libavb/avb_ops.c
+++ b/platform/msm_shared/avb/libavb/avb_ops.c
@@ -176,12 +176,12 @@
 	}
 	*OutNumRead = 0;
 
-	if (!strncmp(Partition,"boot",strlen("boot"))) {
-		/* API returns previously loaded Boot Image buffer address and size */
-		get_boot_image_info(Buffer, OutNumRead, "boot");
+	if (!getimage(Buffer, OutNumRead, Partition)) {
+		/* API returns previously loaded Images buffer address and size */
+		dprintf(SPEW, "DEBUG: %s already loadded \n", Partition);
 		return AVB_IO_RESULT_OK;
 	}
-
+	dprintf(SPEW, "%s Loading image\n", Partition);
 	index = partition_get_index(Partition);
 	ptn = partition_get_offset(index);
 
diff --git a/platform/msm_shared/avb/libavb/avb_slot_verify.c b/platform/msm_shared/avb/libavb/avb_slot_verify.c
index d709635..b279e22 100644
--- a/platform/msm_shared/avb/libavb/avb_slot_verify.c
+++ b/platform/msm_shared/avb/libavb/avb_slot_verify.c
@@ -158,20 +158,17 @@
     }
   }
 
-  image_buf = (uint8_t *)target_get_scratch_address()+0x02000000;
+  if (!strncmp(part_name, "boot", strlen("boot"))) {
+      image_size = hash_desc.image_size;
+  }
+
+  io_ret = ops->read_from_partition(
+            ops, part_name, 0 /* offset */, image_size, &image_buf, &part_num_read);
+
   if (image_buf == NULL) {
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     goto out;
   }
-
-  if (!strncmp(part_name, "boot", strlen("boot"))) {
-      image_size = hash_desc.image_size;
-      io_ret = ops->read_from_partition(
-              ops, part_name, 0 /* offset */, image_size, &image_buf, &part_num_read);
-  }  else {
-      io_ret = ops->read_from_partition(
-              ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
-  }
   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     goto out;
@@ -180,7 +177,7 @@
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     goto out;
   }
-  if (part_num_read != image_size) {
+  if (part_num_read < image_size) {
     avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     goto out;
@@ -470,18 +467,17 @@
     vbmeta_size = footer.vbmeta_size;
   }
 
-  vbmeta_buf = (uint8_t *)target_get_scratch_address() + 0x06000000;
+  io_ret = ops->read_from_partition(ops,
+                                    full_partition_name,
+                                    vbmeta_offset,
+                                    vbmeta_size,
+                                    &vbmeta_buf,
+                                    &vbmeta_num_read);
   if (vbmeta_buf == NULL) {
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     goto out;
   }
 
-  io_ret = ops->read_from_partition(ops,
-                                    full_partition_name,
-                                    vbmeta_offset,
-                                    vbmeta_size,
-                                    vbmeta_buf,
-                                    &vbmeta_num_read);
   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     goto out;
diff --git a/platform/msm_shared/boot_verifier.c b/platform/msm_shared/boot_verifier.c
index ced0fac..b81f3f2 100644
--- a/platform/msm_shared/boot_verifier.c
+++ b/platform/msm_shared/boot_verifier.c
@@ -421,7 +421,7 @@
 		ASSERT(0);
 	}
 
-	if (version_rsp.major_version > 0x2)
+	if (version_rsp.major_version >= 0x2)
 	{
 		bs_req = malloc(sizeof(km_set_boot_state_req_t) + sizeof(km_boot_state_t));
 		ASSERT(bs_req);
@@ -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 2b146cc..6a99514 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -63,13 +63,6 @@
 static void *final_dtb_hdr = NULL;
 static event_t dtbo_event;
 
-typedef enum dtbo_error
-{
-	DTBO_ERROR = 0,
-	DTBO_NOT_SUPPORTED = 1,
-	DTBO_SUCCESS = 2
-}dtbo_error;
-
 dtbo_error ret = DTBO_SUCCESS;
 
 struct dt_entry_v1
@@ -170,81 +163,103 @@
  * Function to validate dtbo image.
  * return: TRUE or FALSE.
  */
-dtbo_error load_validate_dtbo_image(void **dtbo_buf)
+dtbo_error load_validate_dtbo_image(void **dtbo_buf, uint32_t *dtbo_image_sz)
 {
 	uint64_t dtbo_total_size = 0;
-	void *dtbo_image_buf = NULL;
+	static void *dtbo_image_buf = NULL;
 	unsigned int dtbo_image_buf_size;
 	unsigned int dtbo_partition_size;
-	unsigned long long ptn, ptn_size, boot_img_sz;
+	unsigned long long ptn, boot_img_sz;
 	int index = INVALID_PTN;
 	int page_size = mmc_page_size();
 	struct dtbo_table_hdr *dtbo_table_header = NULL;
 	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;
 
-	/* Immediately return if dtbo is not supported */
-	index = partition_get_index("dtbo");
-	if (index == INVALID_PTN)
-	{
-		ret = DTBO_NOT_SUPPORTED;
+	/* If dtbo loaded skip loading */
+	if (dtbo_loaded)
 		goto out;
-	}
 
-	ptn = partition_get_offset(index);
-	if(!ptn)
-	{
-		dprintf(CRITICAL, "ERROR: dtbo parition failed to get offset. \n");
-		ret = DTBO_ERROR;
-		goto out;
-	}
+	get_recovery_dtbo_info(&recovery_dtbo_size, &recovery_appended_dtbo);
 
-	ptn_size = partition_get_size(index);
-	if (ptn_size > DTBO_IMG_BUF)
-	{
-		dprintf(CRITICAL, "ERROR: dtbo parition size is greater than supported.\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");
 
-/*
-	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;
-	}
+		/* Immediately return if dtbo is not supported */
+		if (index == INVALID_PTN)
+		{
+			ret = DTBO_NOT_SUPPORTED;
+			goto out;
+		}
 
-	mmc_set_lun(partition_get_lun(index));
-	dtbo_image_buf = target_get_scratch_address() + boot_img_sz; /* read dtbo after boot.img */
-	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 = partition_get_offset(index);
+		if(!ptn)
+		{
+			dprintf(CRITICAL, "ERROR: dtbo parition failed to get offset. \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;
+		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;
+		}
+
+		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 */
@@ -310,7 +325,17 @@
 	}
 
 out:
-	*dtbo_buf = dtbo_image_buf;
+	if (ret == DTBO_SUCCESS)
+	{
+		*dtbo_buf = dtbo_image_buf;
+		*dtbo_image_sz = (uint32_t)ptn_size;
+		dtbo_loaded = true;
+	}
+	else
+	{
+		*dtbo_buf = NULL;
+		*dtbo_image_sz = 0;
+	}
 	return ret;
 }
 
@@ -1037,9 +1062,10 @@
 					uint32_t dtb_offset, void *tags)
 {
 	void *dtbo_image_buf = NULL;
+	uint32_t dtbo_image_sz = 0;
 
 	bs_set_timestamp(BS_DTB_OVERLAY_START);
-	ret = load_validate_dtbo_image(&dtbo_image_buf);
+	ret = load_validate_dtbo_image(&dtbo_image_buf, &dtbo_image_sz);
 	if (ret == DTBO_SUCCESS)
 	{
 		final_dtb_hdr = soc_dtb = get_soc_dtb(kernel,
diff --git a/platform/msm_shared/include/boot_device.h b/platform/msm_shared/include/boot_device.h
index 8fe4463..2e2a02f 100644
--- a/platform/msm_shared/include/boot_device.h
+++ b/platform/msm_shared/include/boot_device.h
@@ -78,12 +78,19 @@
 	char *vbcmdline;
 	uint32_t vbcmdline_len;
 	uint32_t vbcmdline_filled_len;
+	uint32_t header_version;
 	void *vb_data;
 } bootinfo;
 
-int getimage(const bootinfo *Info, void **image_buffer, uint32_t *imgsize,
-                    char *imgname);
+typedef enum {
+	IMG_BOOT = 0,
+	IMG_DTBO,
+	IMG_VBMETA,
+	IMG_RECOVERY,
+	IMG_MAX
+} img_type;
 
+int getimage(void **image_buffer, uint32_t *imgsize, const char *imgname);
 void platform_read_boot_config();
 uint32_t platform_get_boot_dev();
 uint32_t platform_boot_dev_isemmc();
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 6c06b44..1d8dd07 100644
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -58,7 +58,9 @@
 #define PMIC_SHIFT_IDX            (2)
 #define PLATFORM_SUBTYPE_SHIFT_ID (0x18)
 #define FOUNDRY_ID_MASK           (0x00ff0000)
-#define DTBO_IMG_BUF             (8388608) /* 8MB 8 * 1024 * 1024 */
+#define MAX_SUPPORTED_DTBO_IMG_BUF (8388608)  /* 8MB   8 * 1024 * 1024 */
+#define DTBO_IMG_BUF               (10485760) /* 10MB 10 * 1024 * 1024 */
+#define MAX_SUPPORTED_VBMETA_IMG_BUF (65536)  /* 64 KB 64 * 1024 */
 /*
  * For DTB V1: The DTB entries would be of the format
  * qcom,msm-id = <msm8974, CDP, rev_1>; (3 * sizeof(uint32_t))
@@ -239,6 +241,15 @@
 	uint32_t custom[DTBO_CUSTOM_MAX];    //optional, must zero if unused
 };
 
+typedef enum dtbo_error
+{
+	DTBO_ERROR = 0,
+	DTBO_NOT_SUPPORTED = 1,
+	DTBO_SUCCESS = 2
+}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);
diff --git a/platform/msm_shared/mdp3.c b/platform/msm_shared/mdp3.c
index b9169c1..5333656 100644
--- a/platform/msm_shared/mdp3.c
+++ b/platform/msm_shared/mdp3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2017-2018, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -152,6 +152,7 @@
 	writel(0x00ABCDEF, MDP_DSI_VIDEO_BORDER_CLR);
 	writel(0x00000000, MDP_DSI_VIDEO_HSYNC_SKEW);
 	writel(0x00000000, MDP_DSI_VIDEO_CTL_POLARITY);
+	writel(0x70000000, MDP_DSI_VIDEO_TEST_CTL);
 	// end of cmd mdp
 
 	return 0;
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index f32d935..d862e0b 100644
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -473,7 +473,8 @@
 	SDM429 = 354,
 	SDM439 = 353,
 	SDA429 = 364,
-	SDA439 = 363
+	SDA439 = 363,
+	QM215 = 386
 };
 
 enum platform {
diff --git a/project/msm8909.mk b/project/msm8909.mk
index cbf4b47..5c563c3 100644
--- a/project/msm8909.mk
+++ b/project/msm8909.mk
@@ -19,6 +19,15 @@
 DEFINES += DISPLAY_SPLASH_SCREEN=1
 endif
 
+ifeq ($(VERIFIED_BOOT_2),1)
+ENABLE_SECAPP_LOADER := 1
+ENABLE_RPMB_SUPPORT := 1
+ifneq (,$(findstring DISPLAY_SPLASH_SCREEN,$(DEFINES)))
+#enable fbcon display menu
+ENABLE_FBCON_DISPLAY_MSG := 1
+endif
+endif
+
 ifeq ($(VERIFIED_BOOT),1)
 ENABLE_SECAPP_LOADER := 1
 ENABLE_RPMB_SUPPORT := 1
diff --git a/target/init.c b/target/init.c
index 2358438..7d7b0b8 100644
--- a/target/init.c
+++ b/target/init.c
@@ -485,6 +485,15 @@
 
 }
 
+bool is_target_support_dtbo(void)
+{
+#if TARGET_DTBO_NOT_SUPPORTED
+  return false;
+#else
+  return true;
+#endif
+}
+
 #if CHECK_BAT_VOLTAGE
 /* Return battery voltage */
 uint32_t target_get_battery_voltage()
diff --git a/target/msm8909/init.c b/target/msm8909/init.c
index 1211daf..b6a51e5 100644
--- a/target/msm8909/init.c
+++ b/target/msm8909/init.c
@@ -331,7 +331,7 @@
 {
 	uint32_t base_addr;
 	uint8_t slot;
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	int ret = 0;
 #endif
 	dprintf(INFO, "target_init()\n");
@@ -390,7 +390,7 @@
 	if (target_use_signed_kernel())
 		target_crypto_init_params();
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if (VB_M <= target_get_vb_version())
 	{
 		clock_ce_enable(CE1_INSTANCE);
@@ -711,7 +711,7 @@
 	if (target_is_ssd_enabled())
 		clock_ce_disable(CE1_INSTANCE);
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if(VB_M <= target_get_vb_version())
 	{
 		if (is_sec_app_loaded())