Merge "target: msm8953: Add PMI8950 poweroff sequence support"
diff --git a/AndroidBoot.mk b/AndroidBoot.mk
index 5f31a90..fe3608f 100644
--- a/AndroidBoot.mk
+++ b/AndroidBoot.mk
@@ -39,6 +39,18 @@
   VERIFIED_BOOT := VERIFIED_BOOT=0
 endif
 
+ifeq ($(TARGET_WEAR_SUPPORT_KM3),true)
+  QSEECOM_SECAPP_REGION_2MB := QSEECOM_SECAPP_REGION_2MB=1
+else
+  QSEECOM_SECAPP_REGION_2MB := QSEECOM_SECAPP_REGION_2MB=0
+endif
+
+ifeq ($(BOARD_AVB_ENABLE),true)
+  VERIFIED_BOOT_2 := VERIFIED_BOOT_2=1
+else
+  VERIFIED_BOOT_2 := VERIFIED_BOOT_2=0
+endif
+
 ifeq ($(EARLY_MOUNT_SUPPORT),true)
   ENABLE_BOOTDEVICE_MOUNT := ENABLE_BOOTDEVICE_MOUNT=1
 else
@@ -101,7 +113,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) $(ENABLE_DISPLAY) $(ENABLE_KASLRSEED) $(ENABLE_BOOTDEVICE_MOUNT) $(DEVICE_STATUS) $(BUILD_VARIANT) $(BOARD_NAME) $(ENABLE_VB_ATTEST) $(OSVERSION_IN_BOOTIMAGE)
+	$(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)
 
 # NAND variant output
 TARGET_NAND_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn
@@ -130,7 +142,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) $(ENABLE_DISPLAY) $(ENABLE_KASLRSEED) $(ENABLE_BOOTDEVICE_MOUNT) $(DEVICE_STATUS) $(BUILD_VARIANT) $(BOARD_NAME) $(ENABLE_VB_ATTEST) $(OSVERSION_IN_BOOTIMAGE) $(ENABLE_BG_SUPPORT)
+	$(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)
 
 # 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
old mode 100755
new mode 100644
index 80336bd..11d64c4
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -49,6 +49,7 @@
 #include <mmc.h>
 #include <partition_parser.h>
 #include <ab_partition_parser.h>
+#include <verifiedboot.h>
 #include <platform.h>
 #include <crypto_hash.h>
 #include <malloc.h>
@@ -112,6 +113,7 @@
 static void publish_getvar_multislot_vars();
 /* fastboot command function pointer */
 typedef void (*fastboot_cmd_fn) (const char *, void *, unsigned);
+bool get_perm_attr_status();
 
 struct fastboot_cmd_desc {
 	char * name;
@@ -134,7 +136,7 @@
 #endif
 
 #define MAX_TAGS_SIZE   1024
-
+#define PLL_CODES_OFFSET 4096
 /* make 4096 as default size to ensure EFS,EXT4's erasing */
 #define DEFAULT_ERASE_SIZE  4096
 #define MAX_PANEL_BUF_SIZE 196
@@ -169,8 +171,9 @@
 static const char *battchg_pause = " androidboot.mode=charger";
 static const char *auth_kernel = " androidboot.authorized_kernel=true";
 static const char *secondary_gpt_enable = " gpt";
+#ifdef MDTP_SUPPORT
 static const char *mdtp_activated_flag = " mdtp";
-
+#endif
 static const char *baseband_apq     = " androidboot.baseband=apq";
 static const char *baseband_msm     = " androidboot.baseband=msm";
 static const char *baseband_csfb    = " androidboot.baseband=csfb";
@@ -185,7 +188,11 @@
 static const char *baseband_apq_nowgr   = " androidboot.baseband=baseband_apq_nowgr";
 static const char *androidboot_slot_suffix = " androidboot.slot_suffix=";
 static const char *skip_ramfs = " skip_initramfs";
+#ifdef INIT_BIN_LE
+static const char *sys_path_cmdline = " rootwait ro init="INIT_BIN_LE;
+#else
 static const char *sys_path_cmdline = " rootwait ro init=/init";
+#endif
 
 #if VERITY_LE
 static const char *verity_dev = " root=/dev/dm-0";
@@ -231,10 +238,12 @@
 static bool devinfo_present = true;
 bool boot_into_fastboot = false;
 static uint32_t dt_size = 0;
-
+static char *vbcmdline;
+static bootinfo info = {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};
+static device_info device = {DEVICE_MAGIC,0,0,0,0,{0},{0},{0},1,{0},0,{0}};
+
 static bool is_allow_unlock = 0;
 
 static char frp_ptns[2][8] = {"config","frp"};
@@ -276,6 +285,22 @@
 /*
  * Update the part_type_known for known paritions types.
  */
+#define RAW_STR "raw"
+#define EXT_STR "ext4"
+#define F2FS_STR "f2fs"
+
+#define FS_SUPERBLOCK_OFFSET    0x400
+#define EXT_MAGIC    0xEF53
+#define EXT_MAGIC_OFFSET_SB   0x38
+#define F2FS_MAGIC   0xF2F52010  // F2FS Magic Number
+#define F2FS_MAGIC_OFFSET_SB 0x0
+
+typedef enum fs_signature_type {
+	EXT_FS_SIGNATURE = 1,
+	EXT_F2FS_SIGNATURE = 2,
+	NO_FS = -1
+} fs_signature_type;
+
 struct getvar_partition_info part_info[NUM_PARTITIONS];
 struct getvar_partition_info part_type_known[] =
 {
@@ -355,7 +380,9 @@
 	bool gpt_exists = partition_gpt_exists();
 	int have_target_boot_params = 0;
 	char *boot_dev_buf = NULL;
+#ifdef MDTP_SUPPORT
     	bool is_mdtp_activated = 0;
+#endif
 	int current_active_slot = INVALID;
 	int system_ptn_index = -1;
 	unsigned int lun = 0;
@@ -418,12 +445,20 @@
 	}
 #endif
 
+
+	if (vbcmdline != NULL) {
+		dprintf(DEBUG, "UpdateCmdLine vbcmdline present len %d\n",
+						strlen(vbcmdline));
+		cmdline_len += strlen(vbcmdline);
+	}
+
 	if (boot_into_recovery && gpt_exists)
 		cmdline_len += strlen(secondary_gpt_enable);
 
+#ifdef MDTP_SUPPORT
 	if(is_mdtp_activated)
 		cmdline_len += strlen(mdtp_activated_flag);
-
+#endif
 	if (boot_into_ffbm) {
 		cmdline_len += strlen(androidboot_mode);
 
@@ -555,7 +590,9 @@
 		}
 
 		cmdline_len += strlen(sys_path_cmdline);
+#ifndef VERIFIED_BOOT_2
 		cmdline_len += strlen(syspath_buf);
+#endif
 		if (!boot_into_recovery)
 			cmdline_len += strlen(skip_ramfs);
 	}
@@ -621,6 +658,13 @@
 			while ((*dst++ = *src++));
 		}
 #endif
+
+		if (vbcmdline != NULL) {
+			src = vbcmdline;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		}
+
 		src = usb_sn_cmdline;
 		if (have_cmdline) --dst;
 		have_cmdline = 1;
@@ -640,13 +684,13 @@
 			if (have_cmdline) --dst;
 			while ((*dst++ = *src++));
 		}
-
+#ifdef MDTP_SUPPORT
 		if (is_mdtp_activated) {
 			src = mdtp_activated_flag;
 			if (have_cmdline) --dst;
 			while ((*dst++ = *src++));
 		}
-
+#endif
 		if (boot_into_ffbm) {
 			src = androidboot_mode;
 			if (have_cmdline) --dst;
@@ -781,9 +825,11 @@
 				--dst;
 				while ((*dst++ = *src++));
 
+#ifndef VERIFIED_BOOT_2
 				src = syspath_buf;
 				--dst;
 				while ((*dst++ = *src++));
+#endif
 		}
 
 #if TARGET_CMDLINE_SUPPORT
@@ -938,11 +984,8 @@
 	generate_atags(tags, final_cmdline, ramdisk, ramdisk_size);
 #endif
 
-	if (final_cmdline)
-		free(final_cmdline);
-
 #if VERIFIED_BOOT
-	if (VB_M <= target_get_vb_version())
+	if (VB_M == target_get_vb_version())
 	{
 		if (device.verity_mode == 0) {
 #if FBCON_DISPLAY_MSG
@@ -980,6 +1023,9 @@
 
 	/* Perform target specific cleanup */
 	target_uninit();
+	free_verified_boot_resource(&info);
+	if (final_cmdline)
+		free(final_cmdline);
 
 	dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d), tags/device tree @ %p\n",
 		entry, ramdisk, ramdisk_size, (void *)tags_phys);
@@ -1050,6 +1096,26 @@
 
 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)
+{
+	if (info == NULL || 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,
+		                  strlen(imgname))) {
+			*image_buffer = info->images[loadedindex].image_buffer;
+			*imgsize = info->images[loadedindex].imgsize;
+			return 0;
+		}
+	}
+	return -1;
+}
+
 static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
 {
 	int ret;
@@ -1068,15 +1134,18 @@
 	dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
 
 #if VERIFIED_BOOT
-	char *ptn_name = NULL;
-	if (boot_into_recovery &&
+	uint32_t bootstate;
+	if(boot_into_recovery &&
 		(!partition_multislot_is_supported()))
-		ptn_name = "/recovery";
+	{
+		ret = boot_verify_image((unsigned char *)bootimg_addr,
+				bootimg_size, "/recovery", &bootstate);
+	}
 	else
-		ptn_name = "/boot";
-
-	ret = boot_verify_image((unsigned char *)bootimg_addr,
-				bootimg_size, ptn_name);
+	{
+		ret = boot_verify_image((unsigned char *)bootimg_addr,
+				bootimg_size, "/boot", &bootstate);
+	}
 	boot_verify_print_state();
 #else
 	ret = image_verify((unsigned char *)bootimg_addr,
@@ -1161,6 +1230,22 @@
 #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;
@@ -1254,6 +1339,9 @@
 	unsigned int kernel_size = 0;
 	unsigned int patched_kernel_hdr_size = 0;
 	int rc;
+#if VERIFIED_BOOT_2
+	int status;
+#endif
 	char *ptn_name = NULL;
 #if DEVICE_TREE
 	struct dt_table *table;
@@ -1416,7 +1504,35 @@
 		(int) target_use_signed_kernel(),
 		device.is_unlocked,
 		device.is_tampered);
+#if VERIFIED_BOOT_2
+	offset = imagesize_actual;
+	if (check_aboot_addr_range_overlap((uintptr_t)image_addr + offset, page_size))
+	{
+		dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
+		return -1;
+	}
 
+	/* Read signature */
+	if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
+		return -1;
+	}
+
+	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;
+	info.multi_slot_boot = partition_multislot_is_supported();
+	info.bootreason_alarm = boot_reason_alarm;
+	info.bootinto_recovery = boot_into_recovery;
+	status = load_image_and_auth(&info);
+	if(status)
+		return -1;
+
+	vbcmdline = info.vbcmdline;
+#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
 	 * that means we are in test mode, so execute kernel authentication part for the
@@ -1464,6 +1580,7 @@
 		}
 #endif /* MDTP_SUPPORT */
 	}
+#endif
 
 #if VERIFIED_BOOT
 	if((boot_verify_get_state() == ORANGE) && (!boot_into_ffbm))
@@ -1480,7 +1597,7 @@
 #endif
 
 #if VERIFIED_BOOT
-	if (VB_M <= target_get_vb_version())
+	if (VB_M == target_get_vb_version())
 	{
 		/* set boot and system versions. */
 		set_os_version((unsigned char *)image_addr);
@@ -1691,11 +1808,12 @@
 	unsigned second_actual = 0;
 
 #if DEVICE_TREE
-	struct dt_table *table;
+	struct dt_table *table = NULL;
 	struct dt_entry dt_entry;
 	unsigned dt_table_offset;
 	uint32_t dt_actual;
-	uint32_t dt_hdr_size;
+	uint32_t dt_hdr_size = 0;
+	uint32_t dtb_offset = 0;
 	unsigned int dtb_size = 0;
 	unsigned char *best_match_dt_addr = NULL;
 #endif
@@ -1870,7 +1988,6 @@
 		/* Second image loading not implemented. */
 		ASSERT(0);
 	}
-
 	/* Move kernel and ramdisk to correct address */
 	memmove((void*) hdr->kernel_addr, (char*) (image_addr + page_size), hdr->kernel_size);
 	memmove((void*) hdr->ramdisk_addr, (char*) (image_addr + page_size + kernel_actual), hdr->ramdisk_size);
@@ -1922,7 +2039,27 @@
 		best_match_dt_addr = (unsigned char *)table + dt_entry.offset;
 		dtb_size = dt_entry.size;
 		memmove((void *)hdr->tags_addr, (char *)best_match_dt_addr, dtb_size);
-	}
+
+	} else {
+		/* Validate the tags_addr */
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual) ||
+	        check_ddr_addr_range_bound(hdr->tags_addr, kernel_actual))
+		{
+			dprintf(CRITICAL, "Device tree addresses are not valid.\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 = NULL;
+		dtb = dev_tree_appended((void*)(image_addr + page_size ),hdr->kernel_size, dtb_offset, (void *)hdr->tags_addr);
+		if (!dtb) {
+			dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+			return -1;
+		}
+         }
 #endif
 	if(target_use_signed_kernel() && (!device.is_unlocked))
 	{
@@ -1935,7 +2072,6 @@
 		set_tamper_flag(device.is_tampered);
 #endif
 	}
-
 continue_boot:
 
 	/* TODO: create/pass atags to kernel */
@@ -2224,6 +2360,80 @@
 	}
 }
 
+int read_rollback_index(uint32_t loc, uint64_t *roll_back_index)
+{
+        if (!devinfo_present) {
+                dprintf(CRITICAL, "DeviceInfo not initalized \n");
+                return -EINVAL;
+        }
+        if (loc >= ARRAY_SIZE(device.rollback_index)) {
+                dprintf(CRITICAL, "%s() Loc out of range index: %d, array len: %d\n",
+                                __func__, loc, ARRAY_SIZE(device.rollback_index));
+                ASSERT(0);
+        }
+
+        *roll_back_index = device.rollback_index[loc];
+        return 0;
+}
+
+int write_rollback_index(uint32_t loc, uint64_t roll_back_index)
+{
+        if (!devinfo_present) {
+                dprintf(CRITICAL, "DeviceInfo not initalized \n");
+                return -EINVAL;
+        }
+        if (loc >= ARRAY_SIZE(device.rollback_index)) {
+                dprintf(CRITICAL, "%s() Loc out of range index: %d, array len: %d\n",
+                                __func__, loc, ARRAY_SIZE(device.rollback_index));
+                ASSERT(0);
+        }
+
+        device.rollback_index[loc] = roll_back_index;
+        write_device_info(&device);
+        return 0;
+}
+
+int store_userkey(uint8_t *user_key, uint32_t user_key_size)
+{
+        if (!devinfo_present) {
+                dprintf(CRITICAL, "DeviceInfo not initalized \n");
+                return -EINVAL;
+        }
+
+        if (user_key_size > ARRAY_SIZE(device.user_public_key)) {
+                dprintf(CRITICAL, "StoreUserKey, UserKeySize too large!\n");
+                return -ENODEV;
+        }
+
+        memcpy(device.user_public_key, user_key, user_key_size);
+        device.user_public_key_length = user_key_size;
+        write_device_info(&device);
+        return 0;
+}
+
+int erase_userkey()
+{
+        if (!devinfo_present) {
+                dprintf(CRITICAL, "DeviceInfo not initalized \n");
+                return -EINVAL;
+        }
+        memset(device.user_public_key, 0, ARRAY_SIZE(device.user_public_key));
+        device.user_public_key_length = 0;
+        write_device_info(&device);
+        return 0;
+}
+
+int get_userkey(uint8_t **user_key, uint32_t *user_key_size)
+{
+        if (!devinfo_present) {
+                dprintf(CRITICAL, "DeviceInfo not initalized \n");
+                return -EINVAL;
+        }
+        *user_key = device.user_public_key;
+        *user_key_size = device.user_public_key_length;
+        return 0;
+}
+
 void read_device_info(device_info *dev)
 {
 	if(target_is_emmc_boot())
@@ -2253,20 +2463,20 @@
 			memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
 			if (is_secure_boot_enable()) {
 				info->is_unlocked = 0;
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 				if (VB_M <= target_get_vb_version())
 					info->is_unlock_critical = 0;
 #endif
 			} else {
 				info->is_unlocked = 1;
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 				if (VB_M <= target_get_vb_version())
 					info->is_unlock_critical = 1;
 #endif
 			}
 			info->is_tampered = 0;
 			info->charger_screen_enabled = 0;
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 			if (VB_M <= target_get_vb_version())
 				info->verity_mode = 1; //enforcing by default
 #endif
@@ -2307,7 +2517,7 @@
 {
 	if (type == UNLOCK)
 		device.is_unlocked = status;
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	else if (VB_M <= target_get_vb_version() &&
 			type == UNLOCK_CRITICAL)
 			device.is_unlock_critical = status;
@@ -2323,7 +2533,7 @@
 	/* check device unlock status if it is as expected */
 	if (type == UNLOCK)
 		is_unlocked = device.is_unlocked;
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if(VB_M <= target_get_vb_version() &&
 		type == UNLOCK_CRITICAL)
 	{
@@ -2386,9 +2596,9 @@
 {
 	uint32 dt_image_offset = 0;
 	uint32_t n;
-	struct dt_table *table;
+	struct dt_table *table = NULL;
 	struct dt_entry dt_entry;
-	uint32_t dt_hdr_size;
+	uint32_t dt_hdr_size = 0;
 	unsigned int compressed_size = 0;
 	unsigned int dtb_size = 0;
 	unsigned int out_avai_len = 0;
@@ -2479,16 +2689,11 @@
 
 void cmd_boot(const char *arg, void *data, unsigned sz)
 {
-#ifdef MDTP_SUPPORT
-	static bool is_mdtp_activated = 0;
-#endif /* MDTP_SUPPORT */
 	unsigned kernel_actual;
 	unsigned ramdisk_actual;
 	unsigned second_actual;
 	uint32_t image_actual;
 	uint32_t dt_actual = 0;
-	uint32_t sig_actual = 0;
-	uint32_t sig_size = 0;
 	struct boot_img_hdr *hdr = NULL;
 	struct kernel64_hdr *kptr = NULL;
 	char *ptr = ((char*) data);
@@ -2501,13 +2706,20 @@
 	unsigned char *kernel_start_addr = NULL;
 	unsigned int kernel_size = 0;
 	unsigned int scratch_offset = 0;
+#if !VERIFIED_BOOT_2
+	uint32_t sig_actual = 0;
+	uint32_t sig_size = 0;
+#ifdef MDTP_SUPPORT
+        static bool is_mdtp_activated = 0;
+#endif /* MDTP_SUPPORT */
+#endif
 
 #if FBCON_DISPLAY_MSG
 	/* Exit keys' detection thread firstly */
 	exit_menu_keys_detection();
 #endif
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if(target_build_variant_user() && !device.is_unlocked)
 	{
 		fastboot_fail("unlock device to use this command");
@@ -2550,15 +2762,27 @@
 		fastboot_fail("bootimage header fields are invalid");
 		goto boot_failed;
 	}
+#if VERIFIED_BOOT_2
+	memset(&info, 0, sizeof(bootinfo));
+	info.images[0].image_buffer = data;
+	info.images[0].imgsize = image_actual;
+	info.images[0].name = "boot";
+	info.num_loaded_images = 1;
+	info.multi_slot_boot = partition_multislot_is_supported();
+	if (load_image_and_auth(&info))
+		goto boot_failed;
+	vbcmdline = info.vbcmdline;
+#else
 	sig_size = sz - image_actual;
 
 	if (target_use_signed_kernel() && (!device.is_unlocked)) {
+		unsigned chk;
 		/* Calculate the signature length from boot image */
 		sig_actual = read_der_message_length(
 				(unsigned char*)(data + image_actual), sig_size);
-		image_actual = ADD_OF(image_actual, sig_actual);
+		chk = ADD_OF(image_actual, sig_actual);
 
-		if (image_actual > sz) {
+		if (chk > sz) {
 			fastboot_fail("bootimage header fields are invalid");
 			goto boot_failed;
 		}
@@ -2571,7 +2795,7 @@
 	/* Handle overflow if the input image size is greater than
 	 * boot image buffer can hold
 	 */
-	if ((target_get_max_flash_size() - (image_actual - sig_actual)) < page_size)
+	if ((target_get_max_flash_size() - page_size) < image_actual)
 	{
 		fastboot_fail("booimage: size is greater than boot image buffer can hold");
 		goto boot_failed;
@@ -2584,7 +2808,7 @@
 		/* Pass size excluding signature size, otherwise we would try to
 		 * access signature beyond its length
 		 */
-		verify_signed_bootimg((uint32_t)data, (image_actual - sig_actual));
+		verify_signed_bootimg((uint32_t)data, image_actual);
 	}
 #ifdef MDTP_SUPPORT
 	else
@@ -2609,9 +2833,10 @@
 		goto boot_failed;
 	}
 #endif /* MDTP_SUPPORT */
+#endif /* VERIFIED_BOOT_2 else */
 
 #if VERIFIED_BOOT
-	if (VB_M <= target_get_vb_version())
+	if (VB_M == target_get_vb_version())
 	{
 		/* set boot and system versions. */
 		set_os_version((unsigned char *)data);
@@ -2751,6 +2976,16 @@
 		return;
 	}
 
+	if (!strncmp(arg, "avb_custom_key", strlen("avb_custom_key"))) {
+		dprintf(INFO, "erasing avb_custom_key\n");
+		if (erase_userkey()) {
+			fastboot_fail("Erasing avb_custom_key failed");
+		} else {
+			fastboot_okay("");
+		}
+		return;
+	}
+
 	if (flash_erase(ptn)) {
 		fastboot_fail("failed to erase partition");
 		return;
@@ -2790,6 +3025,15 @@
 	lun = partition_get_lun(index);
 	mmc_set_lun(lun);
 
+	if (!strncmp(arg, "avb_custom_key", strlen("avb_custom_key"))) {
+		dprintf(INFO, "erasing avb_custom_key\n");
+		if (erase_userkey()) {
+			fastboot_fail("Erasing avb_custom_key failed");
+		} else {
+			fastboot_okay("");
+		}
+		return;
+	}
 	if (platform_boot_dev_isemmc())
 	{
 		if (mmc_erase_card(ptn, size)) {
@@ -2824,7 +3068,7 @@
 			free(footer);
 		}
 	}
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if (VB_M <= target_get_vb_version() &&
 		!(strncmp(arg, "userdata", 8)) &&
 		send_delete_keys_to_tz())
@@ -2835,7 +3079,7 @@
 
 void cmd_erase(const char *arg, void *data, unsigned sz)
 {
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if (target_build_variant_user())
 	{
 		if(!device.is_unlocked)
@@ -2881,6 +3125,99 @@
 	return;
 }
 
+/* Function to check partition type of a partition*/
+static fs_signature_type
+check_partition_fs_signature(const char *arg)
+{
+	fs_signature_type ret = NO_FS;
+	int index;
+	unsigned long long ptn;
+	char *sb_buffer = malloc(mmc_blocksize);
+	if (!sb_buffer)
+	{
+		dprintf(CRITICAL, "ERROR: Failed to allocate buffer for superblock\n");
+		goto out;
+	}
+
+	/* Read super block */
+	if ((index = partition_get_index(arg)) < 0)
+	{
+		dprintf(CRITICAL, "ERROR: %s() doesn't exsit\n", arg);
+		goto out;
+	}
+	ptn = partition_get_offset(index);
+	mmc_set_lun(partition_get_lun(index));
+	if(mmc_read(ptn + FS_SUPERBLOCK_OFFSET,
+				(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)
+	{
+		dprintf(SPEW, "%s() Found EXT FS\n", arg);
+		ret = EXT_FS_SIGNATURE;
+	}
+	else if (*((uint32 *)(&sb_buffer[F2FS_MAGIC_OFFSET_SB]))
+										== F2FS_MAGIC)
+	{
+		dprintf(SPEW, "%s() Found F2FS FS\n", arg);
+		ret = EXT_F2FS_SIGNATURE;
+	}
+	else
+	{
+		dprintf(SPEW, "%s() Reverting to default 0x%x\n",
+				arg, *((uint16 *)(&sb_buffer[EXT_MAGIC_OFFSET_SB])));
+		ret = NO_FS;
+	}
+
+out:
+	if(sb_buffer)
+		free(sb_buffer);
+	return ret;
+}
+
+/* Function to get partition type */
+static void get_partition_type(const char *arg, char *response)
+{
+	uint n = 0;
+	fs_signature_type fs_signature;
+
+	if (arg == NULL ||
+		response == NULL)
+	{
+		dprintf(CRITICAL, "Invalid input parameter\n");
+		return;
+	}
+
+	/* By default copy raw to response */
+	strlcpy(response, RAW_STR, MAX_RSP_SIZE);
+
+	/* Mark partiton type for known paritions only */
+	for (n=0; n < ARRAY_SIZE(part_type_known); n++)
+	{
+		if (!strncmp(part_type_known[n].part_name, arg, strlen(arg)))
+		{
+			/* Check partition for FS signature */
+			fs_signature = check_partition_fs_signature(arg);
+			switch (fs_signature)
+			{
+				case EXT_FS_SIGNATURE:
+					strlcpy(response, EXT_STR, MAX_RSP_SIZE);
+					break;
+				case EXT_F2FS_SIGNATURE:
+					strlcpy(response, F2FS_STR, MAX_RSP_SIZE);
+					break;
+				case NO_FS:
+					strlcpy(response, part_type_known[n].type_response, MAX_RSP_SIZE);
+			}
+		}
+	}
+	return;
+}
+
 /*
  * Publish the partition type & size info
  * fastboot getvar will publish the required information.
@@ -2889,7 +3226,7 @@
  */
 static void publish_getvar_partition_info(struct getvar_partition_info *info, uint8_t num_parts)
 {
-	uint8_t i,n;
+	uint8_t i;
 	static bool published = false;
 	struct partition_entry *ptn_entry =
 				partition_get_partition_entries();
@@ -2900,21 +3237,8 @@
 		strlcat(info[i].getvar_size, "partition-size:", MAX_GET_VAR_NAME_SIZE);
 		strlcat(info[i].getvar_type, "partition-type:", MAX_GET_VAR_NAME_SIZE);
 
-		/* Mark partiton type for known paritions only */
-		for (n=0; n < ARRAY_SIZE(part_type_known); n++)
-		{
-			if (!strncmp(part_type_known[n].part_name, info[i].part_name,
-					strlen(part_type_known[n].part_name)))
-			{
-				strlcat(info[i].type_response,
-						part_type_known[n].type_response,
-						MAX_RSP_SIZE);
-				break;
-			}
-		}
-
+		get_partition_type(info[i].part_name, info[i].type_response);
 		get_partition_size(info[i].part_name, info[i].size_response);
-
 		if (strlcat(info[i].getvar_size, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
 		{
 			dprintf(CRITICAL, "partition size name truncated\n");
@@ -3081,7 +3405,7 @@
 	 * which with "any" name other than bootloader. Because it maybe
 	 * a meta package of all partitions.
 	 */
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if (target_build_variant_user()) {
 		if (!device.is_unlocked) {
 			fastboot_fail("Device is locked, meta image flashing is not allowed");
@@ -3484,7 +3808,7 @@
 	}
 #endif /* SSD_ENABLE */
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if (target_build_variant_user())
 	{
 		/* if device is locked:
@@ -3508,6 +3832,15 @@
 		}
 	}
 #endif
+	if (!strncmp(arg, "avb_custom_key", strlen("avb_custom_key"))) {
+		dprintf(INFO, "flashing avb_custom_key\n");
+		if (store_userkey(data, sz)) {
+			fastboot_fail("Flashing avb_custom_key failed");
+		} else {
+			fastboot_okay("");
+		}
+		return;
+	}
 
 	sparse_header = (sparse_header_t *) data;
 	meta_header = (meta_header_t *) data;
@@ -3582,6 +3915,16 @@
 		return;
 	}
 
+	if (!strncmp(arg, "avb_custom_key", strlen("avb_custom_key"))) {
+		dprintf(INFO, "flashing avb_custom_key\n");
+		if (store_userkey(data, sz)) {
+			fastboot_fail("Flashing avb_custom_key failed");
+		} else {
+			fastboot_okay("");
+		}
+		return;
+	}
+
 	if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
 		if((sz > BOOT_MAGIC_SIZE) && (!memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE))) {
 			dprintf(INFO, "Verified the BOOT_MAGIC in image header  \n");
@@ -3864,7 +4207,7 @@
 	fastboot_info(response);
 	snprintf(response, sizeof(response), "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
 	fastboot_info(response);
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 	if (VB_M <= target_get_vb_version())
 	{
 		snprintf(response, sizeof(response), "\tDevice critical unlocked: %s",
@@ -4029,7 +4372,7 @@
 
 	base = (uint8_t *) fb_display->base;
 
-	if (mmc_read(ptn, (uint32_t *)(base + LOGO_IMG_OFFSET), blocksize)) {
+	if (mmc_read(ptn + PLL_CODES_OFFSET, (uint32_t *)(base + LOGO_IMG_OFFSET), blocksize)) {
 		dprintf(CRITICAL, "ERROR: Cannot read splash image header\n");
 		return -1;
 	}
@@ -4061,7 +4404,7 @@
 				return -1;
 			}
 
-			if (mmc_read(ptn + blocksize, (uint32_t *)(base + blocksize), readsize)) {
+			if (mmc_read(ptn + PLL_CODES_OFFSET + blocksize, (uint32_t *)(base + blocksize), readsize)) {
 				dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
 				return -1;
 			}
@@ -4078,13 +4421,13 @@
 			readsize =  ROUNDUP((realsize + LOGO_IMG_HEADER_SIZE), blocksize) - blocksize;
 
 			if (blocksize == LOGO_IMG_HEADER_SIZE) { /* read the content directly */
-				if (mmc_read((ptn + LOGO_IMG_HEADER_SIZE), (uint32_t *)base, readsize)) {
+				if (mmc_read((ptn + PLL_CODES_OFFSET + LOGO_IMG_HEADER_SIZE), (uint32_t *)base, readsize)) {
 					fbcon_clear();
 					dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
 					return -1;
 				}
 			} else {
-				if (mmc_read(ptn + blocksize ,
+				if (mmc_read(ptn + PLL_CODES_OFFSET + blocksize ,
 						(uint32_t *)(base + LOGO_IMG_OFFSET + blocksize), readsize)) {
 					dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
 					return -1;
@@ -4206,11 +4549,21 @@
 	return;
 }
 
+bool is_device_locked_critical()
+{
+        return device.is_unlock_critical ? false:true;
+}
+
 bool is_device_locked()
 {
 	return device.is_unlocked ? false:true;
 }
 
+bool is_verity_enforcing()
+{
+        return device.verity_mode ? true:false;
+}
+
 /* register commands and variables for fastboot */
 void aboot_fastboot_register_commands(void)
 {
diff --git a/app/aboot/devinfo.h b/app/aboot/devinfo.h
index ed43f43..f7b02b4 100644
--- a/app/aboot/devinfo.h
+++ b/app/aboot/devinfo.h
@@ -36,6 +36,9 @@
 #define DEVICE_MAGIC_SIZE 13
 #define MAX_PANEL_ID_LEN 64
 #define MAX_VERSION_LEN  64
+#define MAX_VB_PARTITIONS 32
+#define MAX_USER_KEY_SIZE 2048
+#define SHA256_DIGEST_LENGTH 32
 
 enum unlock_type {
 	UNLOCK = 0,
@@ -53,5 +56,8 @@
 	char bootloader_version[MAX_VERSION_LEN];
 	char radio_version[MAX_VERSION_LEN];
 	bool verity_mode; // 1 = enforcing, 0 = logging
+	uint64_t rollback_index[MAX_VB_PARTITIONS];
+	uint32_t user_public_key_length;
+	uint8_t user_public_key[MAX_USER_KEY_SIZE];
 };
 #endif
diff --git a/app/aboot/mdtp.c b/app/aboot/mdtp.c
index 05f7998..bb806ca 100644
--- a/app/aboot/mdtp.c
+++ b/app/aboot/mdtp.c
@@ -478,6 +478,7 @@
 	bool restore_to_orange = false;
 	unsigned long long ptn = 0;
 	int index = INVALID_PTN;
+	uint32_t bootstate;
 
 	/* If image was already verified in aboot, return its status */
 	if (ext_partition->integrity_state == MDTP_PARTITION_STATE_INVALID)
@@ -538,7 +539,8 @@
 		/* 4) Verify the image using its signature. */
 		ret = boot_verify_image((unsigned char *)ext_partition->image_addr,
 								ext_partition->image_size,
-								ext_partition->partition == MDTP_PARTITION_BOOT ? "/boot" : "/recovery");
+								ext_partition->partition == MDTP_PARTITION_BOOT ? "/boot" : "/recovery",
+								&bootstate);
 		break;
 
 	default:
diff --git a/dev/gcdb/display/include/panel_hx8399c_fhd_pluse_video.h b/dev/gcdb/display/include/panel_hx8399c_fhd_pluse_video.h
index 9331755..2915fe2 100644
--- a/dev/gcdb/display/include/panel_hx8399c_fhd_pluse_video.h
+++ b/dev/gcdb/display/include/panel_hx8399c_fhd_pluse_video.h
@@ -47,7 +47,7 @@
 /* Panel resolution                                                          */
 /*---------------------------------------------------------------------------*/
 static struct panel_resolution hx8399c_fhd_pluse_video_panel_res = {
-	1080, 2160, 24, 24, 16, 0, 36, 40, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	1080, 2160, 42, 42, 10, 0, 10, 15, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 /*---------------------------------------------------------------------------*/
@@ -71,11 +71,10 @@
 };
 
 static char hx8399c_fhd_pluse_video_on_cmd2[] = {
-	0x10, 0x00, 0x39, 0xC0,
-	0xB1, 0x02, 0x04, 0x74,
-	0x94, 0x01, 0x32, 0x33,
-	0x11, 0x11, 0xE6, 0x5D,
-	0x56, 0x73, 0x02, 0x02,
+	0x0C, 0x00, 0x39, 0xC0,
+	0xB1, 0x02, 0x04, 0x72,
+	0x92, 0x01, 0x32, 0xAA,
+	0x11, 0x11, 0x52, 0x57,
 };
 
 static char hx8399c_fhd_pluse_video_on_cmd3[] = {
@@ -89,23 +88,23 @@
 static char hx8399c_fhd_pluse_video_on_cmd4[] = {
 	0x2D, 0x00, 0x39, 0xC0,
 	0xB4, 0x00, 0xFF, 0x59,
-	0x59, 0x0C, 0xAC, 0x00,
-	0x00, 0x0C, 0x00, 0x07,
-	0x0A, 0x00, 0x28, 0x07,
-	0x08, 0x0C, 0x21, 0x03,
-	0x00, 0x00, 0x00, 0xAE,
-	0x87, 0x59, 0x59, 0x0C,
-	0xAC, 0x00, 0x00, 0x0C,
-	0x00, 0x07, 0x0A, 0x00,
-	0x28, 0x07, 0x08, 0x0C,
-	0x01, 0x00, 0x00, 0xAE,
+	0x59, 0x01, 0xAB, 0x00,
+	0x00, 0x09, 0x00, 0x03,
+	0x05, 0x00, 0x28, 0x03,
+	0x0B, 0x0D, 0x21, 0x03,
+	0x02, 0x00, 0x0C, 0xA3,
+	0x80, 0x59, 0x59, 0x02,
+	0xAB, 0x00, 0x00, 0x09,
+	0x00, 0x03, 0x05, 0x00,
+	0x28, 0x03, 0x0B, 0x0D,
+	0x02, 0x00, 0x0C, 0xA3,
 	0x01, 0xFF, 0xFF, 0xFF,
 };
 
 static char hx8399c_fhd_pluse_video_on_cmd5[] = {
 	0x22, 0x00, 0x39, 0xC0,
-	0xD3, 0x00, 0x00, 0x01,
-	0x01, 0x00, 0x00, 0x10,
+	0xD3, 0x00, 0x0C, 0x03,
+	0x03, 0x00, 0x00, 0x10,
 	0x10, 0x00, 0x00, 0x03,
 	0x00, 0x03, 0x00, 0x08,
 	0x78, 0x08, 0x78, 0x00,
@@ -162,9 +161,9 @@
 
 static char hx8399c_fhd_pluse_video_on_cmd11[] = {
 	0x11, 0x00, 0x39, 0xC0,
-	0xD8, 0x82, 0xEA, 0xAA,
-	0xAA, 0x82, 0xEA, 0xAA,
-	0xAA, 0x82, 0xEA, 0xAA,
+	0xD8, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x82, 0xEA, 0xAA,
 	0xAA, 0x82, 0xEA, 0xAA,
 	0xAA, 0xFF, 0xFF, 0xFF,
 };
@@ -188,20 +187,20 @@
 
 static char hx8399c_fhd_pluse_video_on_cmd15[] = {
 	0x37, 0x00, 0x39, 0xC0,
-	0xE0, 0x08, 0x2A, 0x39,
-	0x35, 0x74, 0x7C, 0x87,
-	0x7F, 0x84, 0x8A, 0x8E,
-	0x91, 0x93, 0x96, 0x9B,
-	0x9C, 0x9E, 0xA5, 0xA6,
-	0xAE, 0xA1, 0xAF, 0xB2,
-	0x5C, 0x58, 0x63, 0x74,
-	0x08, 0x2A, 0x39, 0x35,
-	0x74, 0x7C, 0x87, 0x7F,
-	0x84, 0x8A, 0x8E, 0x91,
-	0x93, 0x96, 0x9B, 0x9C,
-	0x9E, 0xA5, 0xA6, 0xAE,
-	0xA1, 0xAF, 0xB2, 0x5C,
-	0x58, 0x63, 0x74, 0xFF,
+	0xE0, 0x01, 0x21, 0x31,
+	0x2D, 0x66, 0x6F, 0x7B,
+	0x75, 0x7A, 0x81, 0x86,
+	0x89, 0x8C, 0x90, 0x95,
+	0x97, 0x9A, 0xA1, 0xA2,
+	0xAA, 0x9E, 0xAD, 0xB0,
+	0x5B, 0x57, 0x63, 0x7A,
+	0x01, 0x21, 0x31, 0x2D,
+	0x66, 0x6F, 0x7B, 0x75,
+	0x7A, 0x81, 0x86, 0x89,
+	0x9C, 0x90, 0x95, 0x97,
+	0x9A, 0xA1, 0xA2, 0xAA,
+	0x9E, 0xAD, 0xB0, 0x5B,
+	0x57, 0x63, 0x7A, 0xFF,
 };
 
 static char hx8399c_fhd_pluse_video_on_cmd16[] = {
@@ -215,28 +214,17 @@
 };
 
 static char hx8399c_fhd_pluse_video_on_cmd18[] = {
-	0x06, 0x00, 0x39, 0xC0,
-	0xC7, 0x00, 0x08, 0x00,
-	0x01, 0x08, 0xFF, 0x00,
-};
-
-static char hx8399c_fhd_pluse_video_on_cmd19[] = {
-	0x03, 0x00, 0x39, 0xC0,
-	0xC0, 0x25, 0x5A, 0xFF,
-};
-
-static char hx8399c_fhd_pluse_video_on_cmd20[] = {
 	0x11, 0x00, 0x05, 0x80,
 };
 
-static char hx8399c_fhd_pluse_video_on_cmd21[] = {
+static char hx8399c_fhd_pluse_video_on_cmd19[] = {
 	0x29, 0x00, 0x05, 0x80,
 };
 
 static struct mipi_dsi_cmd hx8399c_fhd_pluse_video_on_command[] = {
 	{0x08, hx8399c_fhd_pluse_video_on_cmd0, 0x00},
 	{0x08, hx8399c_fhd_pluse_video_on_cmd1, 0x00},
-	{0x14, hx8399c_fhd_pluse_video_on_cmd2, 0x00},
+	{0x10, hx8399c_fhd_pluse_video_on_cmd2, 0x00},
 	{0x14, hx8399c_fhd_pluse_video_on_cmd3, 0x00},
 	{0x34, hx8399c_fhd_pluse_video_on_cmd4, 0x00},
 	{0x28, hx8399c_fhd_pluse_video_on_cmd5, 0x05},
@@ -252,13 +240,11 @@
 	{0x3C, hx8399c_fhd_pluse_video_on_cmd15, 0x05},
 	{0x08, hx8399c_fhd_pluse_video_on_cmd16, 0x00},
 	{0x08, hx8399c_fhd_pluse_video_on_cmd17, 0x00},
-	{0x0C, hx8399c_fhd_pluse_video_on_cmd18, 0x00},
-	{0x08, hx8399c_fhd_pluse_video_on_cmd19, 0x00},
-	{0x04, hx8399c_fhd_pluse_video_on_cmd20, 0x78},
-	{0x04, hx8399c_fhd_pluse_video_on_cmd21, 0x14}
+	{0x04, hx8399c_fhd_pluse_video_on_cmd18, 0x78},
+	{0x04, hx8399c_fhd_pluse_video_on_cmd19, 0x14}
 };
 
-#define HX8399C_FHD_PLUSE_VIDEO_ON_COMMAND 22
+#define HX8399C_FHD_PLUSE_VIDEO_ON_COMMAND 20
 
 
 static char hx8399c_fhd_pluse_videooff_cmd0[] = {
@@ -271,7 +257,7 @@
 
 static struct mipi_dsi_cmd hx8399c_fhd_pluse_video_off_command[] = {
 	{0x4, hx8399c_fhd_pluse_videooff_cmd0, 0x32},
-	{0x4, hx8399c_fhd_pluse_videooff_cmd1, 0x78}
+	{0x4, hx8399c_fhd_pluse_videooff_cmd1, 0x96}
 };
 
 #define HX8399C_FHD_PLUSE_VIDEO_OFF_COMMAND 2
diff --git a/dev/gcdb/display/include/panel_st7789v2_qvga_spi_cmd.h b/dev/gcdb/display/include/panel_st7789v2_qvga_spi_cmd.h
index 869f536..614e21a 100644
--- a/dev/gcdb/display/include/panel_st7789v2_qvga_spi_cmd.h
+++ b/dev/gcdb/display/include/panel_st7789v2_qvga_spi_cmd.h
@@ -157,13 +157,14 @@
 	{0x0F, st7789v2_qvga_cmd_on_cmd12, 0x00, 0},
 	{0x0F, st7789v2_qvga_cmd_on_cmd13, 0x00, 0},
 	{0x01, st7789v2_qvga_cmd_on_cmd14, 0x00, 0},
-	{0x01, st7789v2_qvga_cmd_on_cmd15, 0x78, 0},
-	{0x05, st7789v2_qvga_cmd_on_cmd16, 0x00, 0},
-	{0x05, st7789v2_qvga_cmd_on_cmd17, 0x00, 0},
 	{0x01, st7789v2_qvga_cmd_on_cmd18, 0x00, 0},
+	{0x01, st7789v2_qvga_cmd_on_cmd15, 0x78, 1},
+	{0x05, st7789v2_qvga_cmd_on_cmd16, 0x00, 1},
+	{0x05, st7789v2_qvga_cmd_on_cmd17, 0x00, 1},
+	{0x01, st7789v2_qvga_cmd_on_cmd18, 0x00, 1},
 };
 
-#define ST7789v2_QVGA_CMD_ON_COMMAND 19
+#define ST7789v2_QVGA_CMD_ON_COMMAND 20
 
 
 static char st7789v2_qvga_cmdoff_cmd0[] = {
diff --git a/include/err.h b/include/err.h
index 265c19c..b4e9c5a 100644
--- a/include/err.h
+++ b/include/err.h
@@ -51,5 +51,11 @@
 #define ERR_RECURSE_TOO_DEEP -23
 #define ERR_NOT_SUPPORTED -24
 #define ERR_TOO_BIG -25
+#define EIO 5      /* I/O error */
+#define ENOMEM 12  /* Out of memory */
+#define EACCES 13  /* Permission denied */
+#define ENODEV 19  /* No such device */
+#define EINVAL 22  /* Invalid argument */
+
 
 #endif
diff --git a/include/platform.h b/include/platform.h
index 55fd39e..cd55d7e 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2008 Travis Geiselbrecht
  *
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files
@@ -71,6 +71,8 @@
 int platform_is_msm8952();
 int platform_is_msm8953();
 int platform_is_msm8956();
+int platform_is_sdm429();
+int platform_is_sdm439();
 uint32_t platform_is_msm8976_v_1_1();
 uint32_t platform_get_tz_app_add();
 uint32_t platform_get_tz_app_size();
@@ -92,4 +94,14 @@
 bool platform_is_mdm9206();
 int is_vb_le_enabled();
 void* get_rpmb_snd_rcv_buff();
+int LoadImage(char *Pname, void **ImgBuf, uint32_t *ImgSzActual);
+void boot_verifier_init();
+uint32_t get_page_size();
+int read_rollback_index(uint32_t loc, uint64_t *roll_back_index);
+int write_rollback_index(uint32_t loc, uint64_t roll_back_index);
+int get_userkey(uint8_t **user_key, uint32_t *user_key_size);
+int erase_userkey();
+int store_userkey(uint8_t *user_key, uint32_t user_key_size);
+bool is_device_locked_critical();
+bool is_verity_enforcing();
 #endif
diff --git a/include/target.h b/include/target.h
index 7b92dfb..2151f05 100644
--- a/include/target.h
+++ b/include/target.h
@@ -33,6 +33,7 @@
 {
 	VB_L = 1,
 	VB_M = 2,
+	VB_AVB2 = 4,
 };
 
 /* Target helper functions exposed to USB driver */
diff --git a/makefile b/makefile
index a1b091e..df6e89b 100644
--- a/makefile
+++ b/makefile
@@ -50,7 +50,7 @@
 endif
 
 INCLUDES := -I$(BUILDDIR) -Iinclude
-CFLAGS := -O2 -g -fno-builtin -finline -W -Wall -Wno-multichar -Wno-unused-parameter -Wno-unused-function -include $(CONFIGHEADER)
+CFLAGS := -O2 -g -fno-builtin -finline -W -Wall -Wno-multichar -Wno-unused-parameter -Wno-unused-function $(LKLE_CFLAGS) -include $(CONFIGHEADER)
 #CFLAGS += -Werror
 ifeq ($(EMMC_BOOT),1)
   CFLAGS += -D_EMMC_BOOT=1
@@ -122,6 +122,10 @@
     DEFINES += DEFAULT_UNLOCK=1
   endif
 endif
+ifeq ($(VERIFIED_BOOT_2),1)
+  DEFINES += VERIFIED_BOOT_2=1
+  DEFINES += _SIGNED_KERNEL=1
+endif
 
 ifeq ($(OSVERSION_IN_BOOTIMAGE),1)
  DEFINES += OSVERSION_IN_BOOTIMAGE=1
diff --git a/platform/msm8909/include/platform/iomap.h b/platform/msm8909/include/platform/iomap.h
index f860274..55312e4 100755
--- a/platform/msm8909/include/platform/iomap.h
+++ b/platform/msm8909/include/platform/iomap.h
@@ -211,8 +211,13 @@
 #define RPMB_SND_RCV_BUF_SZ         0x1
 
 /* QSEECOM: Secure app region notification */
-#define APP_REGION_ADDR 0x87b00000
-#define APP_REGION_SIZE 0x100000
+#if QSEECOM_SECAPP_REGION_2MB
+  #define APP_REGION_ADDR 0x87a00000
+  #define APP_REGION_SIZE 0x200000
+#else
+  #define APP_REGION_ADDR 0x87b00000
+  #define APP_REGION_SIZE 0x100000
+#endif
 
 
 /* MDSS */
diff --git a/platform/msm8952/msm8952-clock.c b/platform/msm8952/msm8952-clock.c
index d6c029f..3d2b85c 100644
--- a/platform/msm8952/msm8952-clock.c
+++ b/platform/msm8952/msm8952-clock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, 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
@@ -650,7 +650,8 @@
 			msm8976_v_1_1_sdcc_clock_modify();
 	}
 
-	if (platform_is_msm8937() || platform_is_msm8917())
+	if (platform_is_msm8937() || platform_is_msm8917() ||
+		platform_is_sdm429() || platform_is_sdm439())
 		msm8937_clock_override();
 
 	clk_init(msm_clocks_8952, ARRAY_SIZE(msm_clocks_8952));
diff --git a/platform/msm8952/platform.c b/platform/msm8952/platform.c
index 11501c2..cd771de 100644
--- a/platform/msm8952/platform.c
+++ b/platform/msm8952/platform.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, 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
@@ -260,6 +260,41 @@
 	return ret;
 }
 
+int platform_is_sdm429()
+{
+	uint32_t platform = board_platform_id();
+	uint32_t ret = 0;
+
+	switch(platform)
+	{
+	case SDM429:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+	};
+
+	return ret;
+}
+
+int platform_is_sdm439()
+{
+	uint32_t platform = board_platform_id();
+	uint32_t ret = 0;
+
+	switch(platform)
+	{
+	case SDM439:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+	};
+
+	return ret;
+}
+
+
 int platform_is_msm8956()
 {
 	uint32_t platform = board_platform_id();
@@ -282,7 +317,8 @@
 
 uint32_t platform_get_tz_app_add()
 {
-	if(platform_is_msm8937() || platform_is_msm8917())
+	if(platform_is_msm8937() || platform_is_msm8917() ||
+		platform_is_sdm429() || platform_is_sdm439())
 		return APP_REGION_ADDR_8937;
 	else
 		return APP_REGION_ADDR_8952;
@@ -290,7 +326,8 @@
 
 uint32_t platform_get_tz_app_size()
 {
-	if(platform_is_msm8937() || platform_is_msm8917())
+	if(platform_is_msm8937() || platform_is_msm8917() ||
+		platform_is_sdm429() || platform_is_sdm439())
 		return APP_REGION_SIZE_8937;
 	else
 		return APP_REGION_SIZE_8952;
@@ -298,7 +335,7 @@
 
 uint32_t platform_get_apcs_ipc_base()
 {
-	if(platform_is_msm8917())
+	if(platform_is_msm8917() || platform_is_sdm429())
 		return APCS_ALIAS1_IPC_INTERRUPT_1;
 	else
 		return APCS_ALIAS0_IPC_INTERRUPT_2;
diff --git a/platform/msm_shared/avb/OEMPublicKey.h b/platform/msm_shared/avb/OEMPublicKey.h
new file mode 100644
index 0000000..6825696
--- /dev/null
+++ b/platform/msm_shared/avb/OEMPublicKey.h
@@ -0,0 +1,124 @@
+/* Copyright (c) 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ *  with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __OEM_PUBLIC_KEY_H__
+#define __OEM_PUBLIC_KEY_H__
+
+/**
+ * Internal builds use TestKeyRSA4096Public
+ * OEM should replace this Array with public key used to sign boot.img
+ * avbtool extract_public_key  --key KEY --output OUTPUT
+ */
+static const char OEMPublicKey[] = {
+    0x00, 0x00, 0x10, 0x00, 0x55, 0xd9, 0x04, 0xad, 0xd8, 0x04, 0xaf, 0xe3,
+    0xd3, 0x84, 0x6c, 0x7e, 0x0d, 0x89, 0x3d, 0xc2, 0x8c, 0xd3, 0x12, 0x55,
+    0xe9, 0x62, 0xc9, 0xf1, 0x0f, 0x5e, 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c,
+    0x2c, 0x65, 0x4a, 0x94, 0xb5, 0x16, 0x2b, 0x00, 0xbb, 0x06, 0xef, 0x13,
+    0x07, 0x53, 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
+    0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0x0f, 0xf7, 0x3a,
+    0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad, 0xac, 0x35, 0xda, 0x3b,
+    0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3, 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b,
+    0x6c, 0x5a, 0x27, 0xd7, 0x96, 0x06, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa,
+    0x30, 0xb4, 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
+    0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x09, 0x77, 0xab, 0x97, 0x93, 0xeb, 0x44,
+    0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb, 0x23, 0x0c, 0x47, 0x71,
+    0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47, 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2,
+    0x2a, 0x9a, 0xb0, 0x4c, 0x01, 0x0c, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed,
+    0x6e, 0x8b, 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
+    0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x07, 0xee, 0x79,
+    0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd, 0xc4, 0xbc, 0xc2, 0x11,
+    0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27, 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e,
+    0xca, 0xdc, 0x57, 0x2f, 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf,
+    0x66, 0xa7, 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
+    0xd5, 0x09, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9, 0x79, 0x80,
+    0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3, 0x31, 0x11, 0xf9, 0xf6,
+    0x02, 0x63, 0x2a, 0x1a, 0x2d, 0xd1, 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd,
+    0xbd, 0xf7, 0x4d, 0xc0, 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3,
+    0x27, 0x2d, 0xe5, 0xc9, 0x66, 0x0e, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
+    0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59, 0xd8, 0x79,
+    0x45, 0xff, 0x03, 0x4c, 0x26, 0xa2, 0x00, 0x5a, 0x8e, 0xc2, 0x51, 0xa1,
+    0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81, 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d,
+    0x05, 0xe9, 0xad, 0x0f, 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27,
+    0xda, 0x7c, 0x5d, 0xe4, 0xfa, 0x04, 0xd3, 0x05, 0x0b, 0xba, 0x3a, 0xb2,
+    0x49, 0x45, 0x2f, 0x47, 0xc7, 0x0d, 0x41, 0x3f, 0x97, 0x80, 0x4d, 0x3f,
+    0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf, 0x48, 0x22, 0x12, 0x45,
+    0x2e, 0xf5, 0x0f, 0x87, 0x92, 0xe2, 0x84, 0x01, 0xf9, 0x12, 0x0f, 0x14,
+    0x15, 0x24, 0xce, 0x89, 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15,
+    0xea, 0xbe, 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
+    0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed, 0x53, 0x66,
+    0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0x0d, 0x83, 0xc9, 0xe8, 0x6b,
+    0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a, 0x66, 0xae, 0x8c, 0x97, 0xd7, 0x0d,
+    0x6c, 0x49, 0xc7, 0xf5, 0xc4, 0x92, 0x31, 0x8b, 0x09, 0xee, 0x33, 0xda,
+    0xa9, 0x37, 0xb6, 0x49, 0x18, 0xf8, 0x0e, 0x60, 0x45, 0xc8, 0x33, 0x91,
+    0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6, 0xca, 0x61,
+    0xf9, 0x2f, 0xe0, 0xbf, 0x05, 0x30, 0x52, 0x5a, 0x12, 0x1c, 0x00, 0xa7,
+    0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95, 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e,
+    0x5e, 0xdd, 0x00, 0xdb, 0x0d, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7,
+    0x43, 0xf7, 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
+    0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e, 0x83, 0x6a,
+    0x0a, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc, 0x8c, 0xde, 0x39, 0xd1,
+    0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64, 0xe0, 0x0a, 0xcb, 0x0b, 0xb8, 0x5a,
+    0x7c, 0xc3, 0x0b, 0xe6, 0xbe, 0xfe, 0x8b, 0x0f, 0x7d, 0x34, 0x8e, 0x02,
+    0x66, 0x74, 0x01, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x08, 0x2f, 0x3f,
+    0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12, 0x0c, 0x00,
+    0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2, 0x5f, 0x32, 0x65, 0xc9,
+    0x9c, 0xbe, 0xd6, 0x0a, 0x13, 0x87, 0x3c, 0x2a, 0x45, 0x47, 0x0c, 0xca,
+    0x42, 0x82, 0xfa, 0x89, 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6,
+    0x23, 0xa5, 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
+    0xa1, 0x0b, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6, 0x4a, 0x63,
+    0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6, 0x2f, 0xbb, 0xf8, 0xb2,
+    0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25, 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49,
+    0x0b, 0xf6, 0x8a, 0xbe, 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x04, 0x17,
+    0x75, 0xf1, 0xf3, 0x03, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
+    0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x04, 0xd4, 0xb4, 0x21,
+    0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2, 0x7d, 0x13, 0x0e, 0xaf,
+    0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81, 0x84, 0x8d, 0x09, 0xa0, 0x6a, 0xc1,
+    0xbb, 0xd9, 0xf5, 0x86, 0xac, 0xbd, 0x75, 0x61, 0x09, 0xe6, 0x8c, 0x3d,
+    0x77, 0xb2, 0xed, 0x30, 0x20, 0xe4, 0x00, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
+    0x00, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec, 0x38, 0xbc,
+    0xe5, 0x1b, 0xb4, 0x06, 0x23, 0x31, 0x71, 0x1c, 0x49, 0xcd, 0x76, 0x4a,
+    0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b, 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15,
+    0x0f, 0x37, 0x39, 0xf6, 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce,
+    0x1b, 0x16, 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
+    0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x05, 0x8e, 0xb7,
+    0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48, 0x19, 0x10, 0x9c, 0x04,
+    0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f, 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26,
+    0x19, 0x1d, 0xd1, 0x2c, 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x06, 0xa6, 0xb2,
+    0x41, 0xcc, 0x0a, 0x27, 0x96, 0x09, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
+    0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2, 0x74, 0xf2,
+    0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0x0b, 0x70, 0x43, 0x3d, 0xb1,
+    0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7, 0x19, 0xbc, 0x63, 0x0b, 0xfd, 0x4d,
+    0x88, 0xfe, 0x67, 0xac, 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6,
+    0x1e, 0x25, 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x01,
+    0x3f, 0x71, 0x55, 0x0e, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea, 0xe5, 0xb5,
+    0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1, 0x5f, 0x53, 0x91, 0xad,
+    0x05, 0xde, 0x20, 0xe7, 0x51, 0xda, 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee,
+    0x42, 0x65, 0x70, 0x13, 0x0b, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca,
+    0x5f, 0xf5, 0x1d, 0x70, 0x4b, 0x6c, 0x06, 0x74, 0xec, 0xb5, 0x2e, 0x77,
+    0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac, 0xd8, 0x7e};
+
+#endif /* __OEM_PUBLIC_KEY_H__ */
diff --git a/platform/msm_shared/avb/VerifiedBoot.c b/platform/msm_shared/avb/VerifiedBoot.c
new file mode 100644
index 0000000..a23e15d
--- /dev/null
+++ b/platform/msm_shared/avb/VerifiedBoot.c
@@ -0,0 +1,792 @@
+/* Copyright (c) 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ *  with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "libavb/libavb.h"
+#include <malloc.h>
+
+#include <boot_verifier.h>
+#include <ab_partition_parser.h>
+#include <partition_parser.h>
+#include <recovery.h>
+#include <display_menu.h>
+#include <../../../app/aboot/mdtp.h>
+#include <platform/timer.h>
+#include "verifiedboot.h"
+#include <err.h>
+
+#ifndef DTB_PAD_SIZE
+#define DTB_PAD_SIZE            2048
+#endif
+#define INTERMEDIATE_DIGEST_LENGTH	64
+#define MAX_PART_NAME_SIZE		10
+
+#ifndef MDTP_SUPPORT
+int mdtp_activated(bool * activated)
+{
+	return 0;
+}
+void mdtp_fwlock_verify_lock(mdtp_ext_partition_verification_t *ext_partition)
+{
+	return;
+}
+#endif
+
+static const CHAR8 *VerifiedState = " androidboot.verifiedbootstate=";
+static const CHAR8 *KeymasterLoadState = " androidboot.keymaster=1";
+static const CHAR8 *Space = " ";
+#if !VERIFIED_BOOT_2
+static const CHAR8 *VerityMode = " androidboot.veritymode=";
+static struct verified_boot_verity_mode VbVm[] =
+{
+	{FALSE, "logging"},
+	{TRUE, "enforcing"},
+};
+#endif
+
+static struct verified_boot_state_name VbSn[] =
+{
+	{GREEN, "green"},
+	{ORANGE, "orange"},
+	{YELLOW, "yellow"},
+	{RED, "red"},
+};
+
+struct boolean_string
+{
+	BOOLEAN value;
+	CHAR8 *name;
+};
+
+static struct boolean_string BooleanString[] =
+{
+	{FALSE, "false"},
+	{TRUE, "true"}
+};
+
+
+typedef struct {
+	AvbOps *Ops;
+	AvbSlotVerifyData *SlotData;
+} VB2Data;
+
+UINT32 GetAVBVersion()
+{
+#if VERIFIED_BOOT_2
+	return 2;
+#elif VERIFIED_BOOT
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+BOOLEAN VerifiedBootEnabled()
+{
+	return (GetAVBVersion() > NO_AVB);
+}
+
+static int GetCurrentSlotSuffix(Slot *CurrentSlot)
+{
+	if (!partition_multislot_is_supported())
+		return ERR_INVALID_ARGS;
+
+	strncpy(CurrentSlot->Suffix,
+			SUFFIX_SLOT(partition_find_active_slot()),
+			MAX_SLOT_SUFFIX_SZ);
+	return 0;
+}
+
+static int check_img_header(void *ImageHdrBuffer, uint32_t ImageHdrSize, uint32_t *imgsizeActual)
+{
+    /* These checks are already done before calling auth remove from here */
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
+	boot_verifier_init();
+#endif
+	return 0;
+}
+
+static int GetActiveSlot(Slot *ActiveSlot)
+{
+	if (!partition_multislot_is_supported())
+		return ERR_INVALID_ARGS;
+	int idx = partition_find_active_slot();
+	if (idx != INVALID)
+	{
+		strncpy(ActiveSlot->Suffix,
+			SUFFIX_SLOT(partition_find_active_slot()),
+			MAX_SLOT_SUFFIX_SZ);
+		return 0;
+	}
+	return ERR_NOT_FOUND;
+}
+
+static int FindBootableSlot(Slot *BootableSlot)
+{
+   int Status = 0;
+
+   if (BootableSlot == NULL) {
+       dprintf(CRITICAL,"FindBootableSlot: input parameter invalid\n");
+       return -ERR_INVALID_ARGS;
+   }
+
+   Status = GetActiveSlot(BootableSlot);
+   if (Status != 0) {
+       /* clear bootable slot */
+       BootableSlot->Suffix[0] = '\0';
+   }
+   return Status;
+}
+
+bool IsSuffixEmpty(Slot *CheckSlot)
+{
+	if (CheckSlot == NULL) {
+		return TRUE;
+	}
+
+	if (strlen((char *)CheckSlot->Suffix) == 0) {
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static int HandleActiveSlotUnbootable()
+{
+   int curr_slot;
+   curr_slot = partition_find_active_slot();
+   partition_deactivate_slot(curr_slot);
+   partition_find_boot_slot();
+
+   // should not reach here
+   return ERROR;
+}
+
+/*
+ * Returns length = 0 when there is failure.
+ */
+uint32_t GetSystemPath(char **SysPath)
+{
+	INT32 Index;
+	UINT32 Lun;
+	CHAR8 PartitionName[MAX_GPT_NAME_SIZE];
+	Slot CurSlot;
+	CHAR8 LunCharMapping[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
+
+	if (GetCurrentSlotSuffix(&CurSlot))
+		return 0;
+
+	*SysPath = malloc(sizeof(char) * MAX_PATH_SIZE);
+	if (!*SysPath) {
+		dprintf(CRITICAL, "Failed to allocated memory for System path query\n");
+		return 0;
+	}
+
+	strncpy(PartitionName, "system", strlen("system") + 1);
+	strncat(PartitionName, CurSlot.Suffix, MAX_GPT_NAME_SIZE - 1);
+
+	Index = partition_get_index(PartitionName);
+	if (Index == INVALID_PTN || Index >= NUM_PARTITIONS) {
+		dprintf(CRITICAL, "System partition does not exit\n");
+		free(*SysPath);
+		return 0;
+	}
+
+	Lun = partition_get_lun(Index);
+	if (platform_boot_dev_isemmc()) {
+		snprintf(*SysPath, MAX_PATH_SIZE, " root=/dev/mmcblk0p%d",
+				Index + 1);
+	} else {
+		snprintf(*SysPath, MAX_PATH_SIZE, " root=/dev/sd%c%d",
+				LunCharMapping[Lun],
+				partition_get_index_in_lun(PartitionName, Lun));
+	}
+
+	dprintf(DEBUG, "System Path - %s \n", *SysPath);
+
+	return strlen(*SysPath);
+}
+
+static EFI_STATUS Appendvbcmdline(bootinfo *Info, const CHAR8 *Src)
+{
+	INT32 SrcLen = strlen(Src);
+	CHAR8 *Dst = (CHAR8 *)Info->vbcmdline + Info->vbcmdline_filled_len;
+
+	strlcat(Dst, Src, SrcLen);
+	Info->vbcmdline_filled_len += SrcLen;
+
+	return EFI_SUCCESS;
+}
+
+static EFI_STATUS AppendVBCommonCmdLine(bootinfo *Info)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+
+	if (GetAVBVersion() >= AVB_1) {
+		GUARD(Appendvbcmdline(Info, VerifiedState));
+		GUARD(Appendvbcmdline(Info, VbSn[Info->boot_state].name));
+	}
+	GUARD(Appendvbcmdline(Info, KeymasterLoadState));
+	GUARD(Appendvbcmdline(Info, Space));
+	return EFI_SUCCESS;
+}
+
+static EFI_STATUS VBCommonInit(bootinfo *Info)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+
+	Info->boot_state = RED;
+
+	// FIXME: Add boot call
+	/* allocate VB command line*/
+	Info->vbcmdline = malloc(2*DTB_PAD_SIZE);
+	if (Info->vbcmdline == NULL) {
+		dprintf(CRITICAL, "VB CmdLine allocation failed!\n");
+		Status = EFI_OUT_OF_RESOURCES;
+		return Status;
+	}
+	Info->vbcmdline_len = 2*DTB_PAD_SIZE;
+	Info->vbcmdline_filled_len = 0;
+	Info->vbcmdline[Info->vbcmdline_filled_len] = '\0';
+
+	return Status;
+}
+
+#if VERIFIED_BOOT_2
+/* Disable for VB 2.0 as this path is never taken */
+static EFI_STATUS LoadImageNoAuth(bootinfo *Info)
+{
+	return ERROR;
+}
+static EFI_STATUS load_image_and_authVB1(bootinfo *Info)
+{
+	return ERROR;
+}
+#else
+static EFI_STATUS LoadImageNoAuth(bootinfo *Info)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+
+	if (Info->images[0].image_buffer != NULL && Info->images[0].imgsize > 0) {
+		/* fastboot boot option image already loaded */
+		return Status;
+	}
+
+	Status = LoadImage(Info->pname, (VOID **)&(Info->images[0].image_buffer),
+	                   (UINT32 *)&(Info->images[0].imgsize));
+	if (Status != EFI_SUCCESS) {
+		dprintf(CRITICAL,
+		       "ERROR: Failed to load image from partition: %d\n", Status);
+		return EFI_LOAD_ERROR;
+	}
+	Info->num_loaded_images = 1;
+	Info->images[0].name = malloc(strlen(Info->pname) + 1);
+	strncpy(Info->images[0].name, Info->pname, strlen(Info->pname)); //FIXME
+	return Status;
+}
+
+static EFI_STATUS load_image_and_authVB1(bootinfo *Info)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+	CHAR8 StrPname[MAX_GPT_NAME_SIZE];
+	CHAR8 Pname[MAX_GPT_NAME_SIZE];
+	CHAR8 *SystemPath = NULL;
+	UINT32 SystemPathLen = 0;
+	device_info DevInfo_vb;
+
+	GUARD(VBCommonInit(Info));
+	GUARD(LoadImageNoAuth(Info));
+	boot_verifier_init();
+
+	// FIXME: INIT devinfo()
+	DevInfo_vb.is_unlocked = !is_device_locked();
+	DevInfo_vb.is_unlock_critical = !is_device_locked_critical();
+
+	strncpy(StrPname, "/", strlen("/"));
+	strncpy(Pname, Info->pname, strlen(Info->pname));
+	if (Info->multi_slot_boot) {
+		strncat(StrPname, Pname,
+	              strlen(Pname) - (MAX_SLOT_SUFFIX_SZ - 1));
+	} else {
+		strncat(StrPname, Pname, strlen(Pname));
+	}
+
+	Status = boot_verify_image((UINT8 *)Info->images[0].image_buffer,
+	                                Info->images[0].imgsize,
+					StrPname,
+	                                &Info->boot_state);
+	if (Status != EFI_SUCCESS || Info->boot_state == BOOT_STATE_MAX) {
+		dprintf(CRITICAL, "VBVerifyImage failed with: %d\n", Status);
+		return Status;
+	}
+
+	set_os_version((unsigned char *)Info->images[0].image_buffer);
+	if(!send_rot_command((uint32_t)DevInfo_vb.is_unlocked))
+		return EFI_LOAD_ERROR;
+
+	SystemPathLen = GetSystemPath(&SystemPath);
+	if (SystemPathLen == 0 || SystemPath == NULL) {
+		dprintf(CRITICAL, "GetSystemPath failed!\n");
+		return EFI_LOAD_ERROR;
+	}
+	GUARD(AppendVBCommonCmdLine(Info));
+	GUARD(Appendvbcmdline(Info, VerityMode));
+	GUARD(Appendvbcmdline(Info, VbVm[is_verity_enforcing()].name));
+	GUARD(Appendvbcmdline(Info, SystemPath));
+
+	Info->vb_data = NULL;
+	return Status;
+}
+#endif
+
+static BOOLEAN ResultShouldContinue(AvbSlotVerifyResult Result)
+{
+	switch (Result) {
+	case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+	case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+	case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+	case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+        case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+		return FALSE;
+
+	case AVB_SLOT_VERIFY_RESULT_OK:
+	case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+	case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+	case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+char *pname[] = {
+	"sbl1",
+	"rpm",
+	"tz",
+	"aboot",
+};
+
+static EFI_STATUS load_image_and_authVB2(bootinfo *Info)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+	AvbSlotVerifyResult Result;
+	AvbSlotVerifyData *SlotData = NULL;
+	VB2Data *VBData = NULL;
+	AvbOpsUserData *UserData = NULL;
+	AvbOps *Ops = NULL;
+	CHAR8 Pname[MAX_GPT_NAME_SIZE] = {0};
+	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};
+	const CHAR8 **RequestedPartition = NULL;
+	UINTN NumRequestedPartition = 0;
+	UINT32 ImageHdrSize = 0;
+	UINT32 imgsizeActual = 0;
+	VOID *image_buffer = NULL;
+	UINT32 imgsize = 0;
+        AvbSlotVerifyFlags VerifyFlags = AllowVerificationError ?
+           AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR :
+           AVB_SLOT_VERIFY_FLAGS_NONE;
+	AvbHashtreeErrorMode VerityFlags = AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
+	device_info DevInfo_vb;
+
+	Info->boot_state = RED;
+	GUARD(VBCommonInit(Info));
+
+	UserData = avb_calloc(sizeof(AvbOpsUserData));
+	if (UserData == NULL) {
+		dprintf(CRITICAL,
+		       "ERROR: Failed to allocate AvbOpsUserData\n");
+		Status = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	Ops = AvbOpsNew(UserData);
+	if (Ops == NULL) {
+		dprintf(CRITICAL, "ERROR: Failed to allocate AvbOps\n");
+		Status = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	if(Info->multi_slot_boot) {
+	strncpy(Pname, Info->pname, strlen(Info->pname));
+	if ((MAX_SLOT_SUFFIX_SZ + 1) > strlen(Pname)) {
+		dprintf(CRITICAL, "ERROR: Can not determine slot suffix\n");
+		Status = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	SlotSuffix = &Pname[strlen(Pname) - MAX_SLOT_SUFFIX_SZ + 1];
+	} else {
+		 SlotSuffix = "\0";
+	}
+
+	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];
+	}
+	} 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];
+		}
+	}
+	if (Info->num_loaded_images) {
+		NumRequestedPartition--;
+	}
+
+	// FIXME: is this correct?
+	VerityFlags = VerityEnforcing ?
+				AVB_HASHTREE_ERROR_MODE_RESTART :
+				AVB_HASHTREE_ERROR_MODE_EIO;
+
+	Result = avb_slot_verify(Ops, RequestedPartition, SlotSuffix,
+				VerifyFlags, VerityFlags,
+				&SlotData);
+
+	if (AllowVerificationError && ResultShouldContinue(Result)) {
+		dprintf(CRITICAL, "State: Unlocked, AvbSlotVerify returned "
+		                    "%s, continue boot\n",
+		       avb_slot_verify_result_to_string(Result));
+	} else if (Result != AVB_SLOT_VERIFY_RESULT_OK) {
+		dprintf(CRITICAL,
+		       "ERROR: Device State %s, AvbSlotVerify returned %s\n",
+		       AllowVerificationError ? "Unlocked" : "Locked",
+		       avb_slot_verify_result_to_string(Result));
+		Status = EFI_LOAD_ERROR;
+		Info->boot_state = RED;
+		goto out;
+	}
+
+	for (UINTN ReqIndex = 0; ReqIndex < NumRequestedPartition; ReqIndex++) {
+		dprintf(DEBUG, "Requested Partition: %s\n",
+		       RequestedPartition[ReqIndex]);
+		for (UINTN loadedindex = 0;
+		     loadedindex < SlotData->num_loaded_partitions; loadedindex++) {
+			dprintf(DEBUG, "Loaded Partition: %s\n",
+			       SlotData->loaded_partitions[loadedindex].partition_name);
+			if (!strncmp((const char *)
+			            RequestedPartition[ReqIndex],
+			            SlotData->loaded_partitions[loadedindex].partition_name,
+			            strlen(SlotData->loaded_partitions[loadedindex]
+			                                .partition_name))) {
+				if (Info->num_loaded_images >= ARRAY_SIZE(Info->images)) {
+					dprintf(CRITICAL, "NumLoadedPartition"
+					                    "(%d) too large "
+					                    "max images(%d)\n",
+					       Info->num_loaded_images,
+					       ARRAY_SIZE(Info->images));
+					Status = EFI_LOAD_ERROR;
+					Info->boot_state = RED;
+					goto out;
+				}
+				Info->images[Info->num_loaded_images].name =
+				        SlotData->loaded_partitions[loadedindex].partition_name;
+				Info->images[Info->num_loaded_images].image_buffer =
+				        SlotData->loaded_partitions[loadedindex].data;
+				Info->images[Info->num_loaded_images].imgsize =
+				        SlotData->loaded_partitions[loadedindex].data_size;
+				Info->num_loaded_images++;
+				break;
+			}
+		}
+	}
+
+	if (Info->num_loaded_images < NumRequestedPartition) {
+		dprintf(CRITICAL, "ERROR: AvbSlotVerify slot data: num of loaded partitions %d, requested %lu\n",Info->num_loaded_images, NumRequestedPartition);
+		Status = EFI_LOAD_ERROR;
+		goto out;
+	}
+
+	dprintf(DEBUG, "Total loaded partition %d\n", Info->num_loaded_images);
+
+	VBData = (VB2Data *)avb_calloc(sizeof(VB2Data));
+	if (VBData == NULL) {
+		dprintf(CRITICAL, "ERROR: Failed to allocate VB2Data\n");
+		Status = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	VBData->Ops = Ops;
+	VBData->SlotData = SlotData;
+	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") );
+
+	Status = check_img_header(image_buffer, ImageHdrSize, &imgsizeActual);
+	if (Status != EFI_SUCCESS) {
+		dprintf(CRITICAL, "Invalid boot image header:%d\n", Status);
+		goto out;
+	}
+
+	if (imgsizeActual > imgsize) {
+		Status = EFI_BUFFER_TOO_SMALL;
+		dprintf(CRITICAL,
+		       "Boot size in vbmeta less than actual boot image size "
+		       "flash corresponding vbmeta.img\n");
+		goto out;
+	}
+	if (AllowVerificationError) {
+		Info->boot_state = ORANGE;
+	} else {
+		if (UserData->IsUserKey) {
+			Info->boot_state = YELLOW;
+		} else {
+			Info->boot_state = GREEN;
+		}
+	}
+
+	/* command line */
+	GUARD_OUT(AppendVBCommonCmdLine(Info));
+	GUARD_OUT(Appendvbcmdline(Info, SlotData->cmdline));
+	DevInfo_vb.is_unlocked = !is_device_locked();
+	set_os_version((unsigned char *)Info->images[0].image_buffer);
+	if(!send_rot_command((uint32_t)DevInfo_vb.is_unlocked))
+		return EFI_LOAD_ERROR;
+	dprintf(INFO, "VB2: Authenticate complete! boot state is: %s\n",
+	       VbSn[Info->boot_state].name);
+
+out:
+	if (Status != EFI_SUCCESS) {
+		if (SlotData != NULL) {
+			avb_slot_verify_data_free(SlotData);
+		}
+		if (Ops != NULL) {
+			AvbOpsFree(Ops);
+		}
+		if (UserData != NULL) {
+			avb_free(UserData);
+		}
+		if (VBData != NULL) {
+			avb_free(VBData);
+		}
+		Info->boot_state = RED;
+		if(Info->multi_slot_boot) {
+		HandleActiveSlotUnbootable();
+		/* HandleActiveSlotUnbootable should have swapped slots and
+		* reboot the device. If no bootable slot found, enter fastboot */
+			dprintf(CRITICAL, "No bootable slots found enter fastboot mode\n");
+		 } else {
+			dprintf(CRITICAL, "Non Multi-slot: Unbootable entering fastboot mode\n");
+		}
+
+		}
+
+	dprintf(CRITICAL, "VB2: boot state: %s(%d)\n",
+	       VbSn[Info->boot_state].name, Info->boot_state);
+	return Status;
+}
+
+static EFI_STATUS DisplayVerifiedBootScreen(bootinfo *Info)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+	CHAR8 ffbm_mode_string[FFBM_MODE_BUF_SIZE] = {'\0'};
+
+	if (GetAVBVersion() < AVB_1) {
+		return EFI_SUCCESS;
+	}
+
+	if (!strncmp(Info->pname, "boot", strlen("boot"))) {
+		Status = get_ffbm(ffbm_mode_string, FFBM_MODE_BUF_SIZE);
+		if (Status != EFI_SUCCESS) {
+			dprintf(DEBUG,
+			       "No Ffbm cookie found, ignore: %d\n", Status);
+			ffbm_mode_string[0] = '\0';
+		}
+	}
+
+	dprintf(DEBUG, "Boot State is : %d\n", Info->boot_state);
+	switch (Info->boot_state)
+        {
+		case RED:
+			display_bootverify_menu(DISPLAY_MENU_RED);
+			//if (Status != EFI_SUCCESS) {
+				dprintf(INFO, "Your device is corrupt. It can't be trusted and will not boot." \
+					"\nYour device will shutdown in 30s\n");
+			//}
+			udelay(30000000);
+			shutdown_device();
+			break;
+		case YELLOW:
+			display_bootverify_menu(DISPLAY_MENU_YELLOW);
+			//if (Status == EFI_SUCCESS) {
+				wait_for_users_action();
+			//} else {
+				dprintf(INFO, "Your device has loaded a different operating system." \
+					"\nWait for 5 seconds before proceeding\n");
+				udelay(5000000);
+			//}
+			break;
+		case ORANGE:
+			if (ffbm_mode_string[0] != '\0' && !target_build_variant_user()) {
+				dprintf(DEBUG, "Device will boot into FFBM mode\n");
+			} else {
+				display_bootverify_menu(DISPLAY_MENU_ORANGE);
+				if (Status == EFI_SUCCESS) {
+					wait_for_users_action();
+				} else {
+					dprintf(INFO, "Device is unlocked, Skipping boot verification\n");
+					udelay(5000000);
+				}
+			}
+			break;
+		default:
+			break;
+	}
+	return EFI_SUCCESS;
+}
+
+EFI_STATUS load_image_and_auth(bootinfo *Info)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+	BOOLEAN MdtpActive = FALSE;
+	UINT32 AVBVersion = NO_AVB;
+	mdtp_ext_partition_verification_t ext_partition;
+
+	if (Info == NULL) {
+		dprintf(CRITICAL, "Invalid parameter Info\n");
+		return EFI_INVALID_PARAMETER;
+	}
+
+	if (!Info->multi_slot_boot) {
+		if (Info->bootinto_recovery) {
+			dprintf(INFO, "Booting Into Recovery Mode\n");
+			strncpy(Info->pname, "recovery", strlen("recovery"));
+		} else {
+			dprintf(INFO, "Booting Into Mission Mode\n");
+			strncpy(Info->pname, "boot", strlen("boot"));
+		}
+	} else {
+		Slot CurrentSlot = {{0}};
+
+		GUARD(FindBootableSlot(&CurrentSlot));
+		if (IsSuffixEmpty(&CurrentSlot)) {
+			dprintf(CRITICAL, "No bootable slot\n");
+			return EFI_LOAD_ERROR;
+		}
+		strncpy(Info->pname, "boot", strlen("boot"));
+		strncat(Info->pname, CurrentSlot.Suffix, strlen(CurrentSlot.Suffix));
+	}
+
+	dprintf(DEBUG, "MultiSlot %s, partition name %s\n",
+	       BooleanString[Info->multi_slot_boot].name, Info->pname);
+
+	Status = mdtp_activated(&MdtpActive);
+	if (Status) {
+		dprintf(CRITICAL,
+			       "Failed to get activation state for MDTP, "
+			       "Status=%d."
+			       " Considering MDTP as active and continuing \n",
+			       Status);
+		if (Status != -1)
+			MdtpActive = TRUE;
+	}
+
+	AVBVersion = GetAVBVersion();
+	dprintf(DEBUG, "AVB version %d\n", AVBVersion);
+
+	/* Load and Authenticate */
+	switch (AVBVersion) {
+	case NO_AVB:
+		return LoadImageNoAuth(Info);
+		break;
+	case AVB_1:
+		Status = load_image_and_authVB1(Info);
+		break;
+	case AVB_2:
+		Status = load_image_and_authVB2(Info);
+		break;
+	default:
+		dprintf(CRITICAL, "Unsupported AVB version %d\n", AVBVersion);
+		Status = EFI_UNSUPPORTED;
+	}
+
+	// if MDTP is active Display Recovery UI
+	if (Status != EFI_SUCCESS && MdtpActive && !target_use_signed_kernel()) {
+		//FIXME: Hard coded to BOOT
+		ext_partition.partition = Info->bootinto_recovery ? MDTP_PARTITION_RECOVERY : MDTP_PARTITION_BOOT;
+		ext_partition.integrity_state = MDTP_PARTITION_STATE_UNSET;
+		ext_partition.page_size = get_page_size();
+		ext_partition.image_addr = (uint32)Info->images[0].image_buffer;
+		ext_partition.image_size = Info->images[0].imgsize;
+		ext_partition.sig_avail = FALSE;
+		mdtp_fwlock_verify_lock(&ext_partition);
+	}
+
+	if (!is_device_locked() && Status != EFI_SUCCESS) {
+		dprintf(CRITICAL, "load_image_and_auth failed %d\n", Status);
+		return Status;
+	}
+
+	DisplayVerifiedBootScreen(Info);
+
+	return Status;
+}
+
+#if VERIFIED_BOOT_2
+VOID free_verified_boot_resource(bootinfo *Info)
+{
+	dprintf(DEBUG, "free_verified_boot_resource\n");
+
+	if (Info == NULL) {
+		return;
+	}
+
+	VB2Data *VBData = Info->vb_data;
+	if (VBData != NULL) {
+		AvbOps *Ops = VBData->Ops;
+		if (Ops != NULL) {
+			if (Ops->user_data != NULL) {
+				avb_free(Ops->user_data);
+			}
+			AvbOpsFree(Ops);
+		}
+
+		AvbSlotVerifyData *SlotData = VBData->SlotData;
+		if (SlotData != NULL) {
+			avb_slot_verify_data_free(SlotData);
+		}
+		avb_free(VBData);
+	}
+
+	if (Info->vbcmdline != NULL) {
+		free(Info->vbcmdline);
+	}
+	return;
+}
+#else
+VOID free_verified_boot_resource(bootinfo *Info)
+{
+	return;
+}
+#endif
diff --git a/platform/msm_shared/avb/libavb/avb_chain_partition_descriptor.c b/platform/msm_shared/avb/libavb/avb_chain_partition_descriptor.c
new file mode 100644
index 0000000..3f14232
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_chain_partition_descriptor.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_chain_partition_descriptor.h"
+#include "avb_util.h"
+
+bool avb_chain_partition_descriptor_validate_and_byteswap(
+    const AvbChainPartitionDescriptor* src, AvbChainPartitionDescriptor* dest) {
+  uint64_t expected_size;
+
+  avb_memcpy(dest, src, sizeof(AvbChainPartitionDescriptor));
+
+  if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+                                            (AvbDescriptor*)dest))
+    return false;
+
+  if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) {
+    avb_error("Invalid tag for chain partition descriptor.\n");
+    return false;
+  }
+
+  dest->rollback_index_location = avb_be32toh(dest->rollback_index_location);
+  dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+  dest->public_key_len = avb_be32toh(dest->public_key_len);
+
+  if (dest->rollback_index_location < 1) {
+    avb_error("Invalid rollback index location value.\n");
+    return false;
+  }
+
+  /* Check that partition_name and public_key are fully contained. */
+  expected_size = sizeof(AvbChainPartitionDescriptor) - sizeof(AvbDescriptor);
+  if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+      !avb_safe_add_to(&expected_size, dest->public_key_len)) {
+    avb_error("Overflow while adding up sizes.\n");
+    return false;
+  }
+  if (expected_size > dest->parent_descriptor.num_bytes_following) {
+    avb_error("Descriptor payload size overflow.\n");
+    return false;
+  }
+  return true;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_chain_partition_descriptor.h b/platform/msm_shared/avb/libavb/avb_chain_partition_descriptor.h
new file mode 100644
index 0000000..f2c9250
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_chain_partition_descriptor.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_CHAIN_PARTITION_DESCRIPTOR_H_
+#define AVB_CHAIN_PARTITION_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A descriptor containing a pointer to signed integrity data stored
+ * on another partition. The descriptor contains the partition name in
+ * question (without the A/B suffix), the public key used to sign the
+ * integrity data, and rollback index location to use for rollback
+ * protection.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded) and |public_key_len| bytes of the
+ * public key.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ */
+typedef struct AvbChainPartitionDescriptor {
+  AvbDescriptor parent_descriptor;
+  uint32_t rollback_index_location;
+  uint32_t partition_name_len;
+  uint32_t public_key_len;
+  uint8_t reserved[64];
+} AVB_ATTR_PACKED AvbChainPartitionDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_chain_partition_descriptor_validate_and_byteswap(
+    const AvbChainPartitionDescriptor* src,
+    AvbChainPartitionDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_CHAIN_PARTITION_DESCRIPTOR_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_crc32.c b/platform/msm_shared/avb/libavb/avb_crc32.c
new file mode 100644
index 0000000..7d4cb09
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_crc32.c
@@ -0,0 +1,114 @@
+/*-
+ *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
+ *  code or tables extracted from it, as desired without restriction.
+ */
+
+/*
+ *  First, the polynomial itself and its table of feedback terms.  The
+ *  polynomial is
+ *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ *
+ *  Note that we take it "backwards" and put the highest-order term in
+ *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
+ *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
+ *  the MSB being 1
+ *
+ *  Note that the usual hardware shift register implementation, which
+ *  is what we're using (we're merely optimizing it by doing eight-bit
+ *  chunks at a time) shifts bits into the lowest-order term.  In our
+ *  implementation, that means shifting towards the right.  Why do we
+ *  do it this way?  Because the calculated CRC must be transmitted in
+ *  order from highest-order term to lowest-order term.  UARTs transmit
+ *  characters in order from LSB to MSB.  By storing the CRC this way
+ *  we hand it to the UART in the order low-byte to high-byte; the UART
+ *  sends each low-bit to hight-bit; and the result is transmission bit
+ *  by bit from highest- to lowest-order term without requiring any bit
+ *  shuffling on our part.  Reception works similarly
+ *
+ *  The feedback terms table consists of 256, 32-bit entries.  Notes
+ *
+ *      The table can be generated at runtime if desired; code to do so
+ *      is shown later.  It might not be obvious, but the feedback
+ *      terms simply represent the results of eight shift/xor opera
+ *      tions for all combinations of data and CRC register values
+ *
+ *      The values must be right-shifted by eight bits by the "updcrc
+ *      logic; the shift must be unsigned (bring in zeroes).  On some
+ *      hardware you could probably optimize the shift in assembler by
+ *      using byte-swap instructions
+ *      polynomial $edb88320
+ *
+ *
+ * CRC32 code derived from work by Gary S. Brown.
+ */
+
+#include "avb_sysdeps.h"
+#include "avb_util.h"
+
+/* Code taken from FreeBSD 8 */
+
+static uint32_t iavb_crc32_tab[] = {
+    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+    0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+    0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+    0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+    0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+    0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+    0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+    0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+    0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+    0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+    0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+    0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+    0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+    0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+    0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+    0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
+
+/*
+ * A function that calculates the CRC-32 based on the table above is
+ * given below for documentation purposes. An equivalent implementation
+ * of this function that's actually used in the kernel can be found
+ * in sys/libkern.h, where it can be inlined.
+ */
+
+static uint32_t iavb_crc32(uint32_t crc_in, const uint8_t* buf, int size) {
+  const uint8_t* p = buf;
+  uint32_t crc;
+
+  crc = crc_in ^ ~0U;
+  while (size--)
+    crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+  return crc ^ ~0U;
+}
+
+uint32_t avb_crc32(const uint8_t* buf, size_t size) {
+  return iavb_crc32(0, buf, size);
+}
diff --git a/platform/msm_shared/avb/libavb/avb_crypto.c b/platform/msm_shared/avb/libavb/avb_crypto.c
new file mode 100644
index 0000000..0e8899c
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_crypto.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_crypto.h"
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+
+/* NOTE: The PKC1-v1.5 padding is a blob of binary DER of ASN.1 and is
+ * obtained from section 5.2.2 of RFC 4880.
+ */
+
+static const uint8_t
+    padding_RSA2048_SHA256[AVB_RSA2048_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+        0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+        0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+    padding_RSA4096_SHA256[AVB_RSA4096_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+        0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+        0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+    padding_RSA8192_SHA256[AVB_RSA8192_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+        0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+        0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+    padding_RSA2048_SHA512[AVB_RSA2048_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+        0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+        0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+
+static const uint8_t
+    padding_RSA4096_SHA512[AVB_RSA4096_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+        0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
+        0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+        0x05, 0x00, 0x04, 0x40};
+
+static const uint8_t
+    padding_RSA8192_SHA512[AVB_RSA8192_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+        0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+        0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+
+static AvbAlgorithmData algorithm_data[_AVB_ALGORITHM_NUM_TYPES] = {
+    /* AVB_ALGORITHM_TYPE_NONE */
+    {.padding = NULL, .padding_len = 0, .hash_len = 0},
+    /* AVB_ALGORITHM_TYPE_SHA256_RSA2048 */
+    {.padding = padding_RSA2048_SHA256,
+     .padding_len = sizeof(padding_RSA2048_SHA256),
+     .hash_len = AVB_SHA256_DIGEST_SIZE},
+    /* AVB_ALGORITHM_TYPE_SHA256_RSA4096 */
+    {.padding = padding_RSA4096_SHA256,
+     .padding_len = sizeof(padding_RSA4096_SHA256),
+     .hash_len = AVB_SHA256_DIGEST_SIZE},
+    /* AVB_ALGORITHM_TYPE_SHA256_RSA8192 */
+    {.padding = padding_RSA8192_SHA256,
+     .padding_len = sizeof(padding_RSA8192_SHA256),
+     .hash_len = AVB_SHA256_DIGEST_SIZE},
+    /* AVB_ALGORITHM_TYPE_SHA512_RSA2048 */
+    {.padding = padding_RSA2048_SHA512,
+     .padding_len = sizeof(padding_RSA2048_SHA512),
+     .hash_len = AVB_SHA512_DIGEST_SIZE},
+    /* AVB_ALGORITHM_TYPE_SHA512_RSA4096 */
+    {.padding = padding_RSA4096_SHA512,
+     .padding_len = sizeof(padding_RSA4096_SHA512),
+     .hash_len = AVB_SHA512_DIGEST_SIZE},
+    /* AVB_ALGORITHM_TYPE_SHA512_RSA8192 */
+    {.padding = padding_RSA8192_SHA512,
+     .padding_len = sizeof(padding_RSA8192_SHA512),
+     .hash_len = AVB_SHA512_DIGEST_SIZE},
+};
+
+const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm) {
+  if (algorithm < _AVB_ALGORITHM_NUM_TYPES) {
+    return &algorithm_data[algorithm];
+  }
+  return NULL;
+}
+
+bool avb_rsa_public_key_header_validate_and_byteswap(
+    const AvbRSAPublicKeyHeader* src, AvbRSAPublicKeyHeader* dest) {
+  avb_memcpy(dest, src, sizeof(AvbRSAPublicKeyHeader));
+
+  dest->key_num_bits = avb_be32toh(dest->key_num_bits);
+  dest->n0inv = avb_be32toh(dest->n0inv);
+
+  return true;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_crypto.h b/platform/msm_shared/avb/libavb/avb_crypto.h
new file mode 100644
index 0000000..7e8d7e2
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_crypto.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_CRYPTO_H_
+#define AVB_CRYPTO_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Size of a RSA-2048 signature. */
+#define AVB_RSA2048_NUM_BYTES 256
+
+/* Size of a RSA-4096 signature. */
+#define AVB_RSA4096_NUM_BYTES 512
+
+/* Size of a RSA-8192 signature. */
+#define AVB_RSA8192_NUM_BYTES 1024
+
+/* Size in bytes of a SHA-256 digest. */
+#define AVB_SHA256_DIGEST_SIZE 32
+
+/* Size in bytes of a SHA-512 digest. */
+#define AVB_SHA512_DIGEST_SIZE 64
+
+/* Algorithms that can be used in the vbmeta image for
+ * verification. An algorithm consists of a hash type and a signature
+ * type.
+ *
+ * The data used to calculate the hash is the three blocks mentioned
+ * in the documentation for |AvbVBMetaImageHeader| except for the data
+ * in the "Authentication data" block.
+ *
+ * For signatures with RSA keys, PKCS v1.5 padding is used. The public
+ * key data is stored in the auxiliary data block, see
+ * |AvbRSAPublicKeyHeader| for the serialization format.
+ *
+ * Each algorithm type is described below:
+ *
+ * AVB_ALGORITHM_TYPE_NONE: There is no hash, no signature of the
+ * data, and no public key. The data cannot be verified. The fields
+ * |hash_size|, |signature_size|, and |public_key_size| must be zero.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA2048: The hash function used is
+ * SHA-256, resulting in 32 bytes of hash digest data. This hash is
+ * signed with a 2048-bit RSA key. The field |hash_size| must be 32,
+ * |signature_size| must be 256, and the public key data must have
+ * |key_num_bits| set to 2048.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA4096: Like above, but only with
+ * a 4096-bit RSA key and |signature_size| set to 512.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA8192: Like above, but only with
+ * a 8192-bit RSA key and |signature_size| set to 1024.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA2048: The hash function used is
+ * SHA-512, resulting in 64 bytes of hash digest data. This hash is
+ * signed with a 2048-bit RSA key. The field |hash_size| must be 64,
+ * |signature_size| must be 256, and the public key data must have
+ * |key_num_bits| set to 2048.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA4096: Like above, but only with
+ * a 4096-bit RSA key and |signature_size| set to 512.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA8192: Like above, but only with
+ * a 8192-bit RSA key and |signature_size| set to 1024.
+ */
+typedef enum {
+  AVB_ALGORITHM_TYPE_NONE,
+  AVB_ALGORITHM_TYPE_SHA256_RSA2048,
+  AVB_ALGORITHM_TYPE_SHA256_RSA4096,
+  AVB_ALGORITHM_TYPE_SHA256_RSA8192,
+  AVB_ALGORITHM_TYPE_SHA512_RSA2048,
+  AVB_ALGORITHM_TYPE_SHA512_RSA4096,
+  AVB_ALGORITHM_TYPE_SHA512_RSA8192,
+  _AVB_ALGORITHM_NUM_TYPES
+} AvbAlgorithmType;
+
+/* Holds algorithm-specific data. The |padding| is needed by avb_rsa_verify. */
+typedef struct {
+  const uint8_t* padding;
+  size_t padding_len;
+  size_t hash_len;
+} AvbAlgorithmData;
+
+/* Provides algorithm-specific data for a given |algorithm|. Returns NULL if
+ * |algorithm| is invalid.
+ */
+const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm)
+    AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* The header for a serialized RSA public key.
+ *
+ * The size of the key is given by |key_num_bits|, for example 2048
+ * for a RSA-2048 key. By definition, a RSA public key is the pair (n,
+ * e) where |n| is the modulus (which can be represented in
+ * |key_num_bits| bits) and |e| is the public exponent. The exponent
+ * is not stored since it's assumed to always be 65537.
+ *
+ * To optimize verification, the key block includes two precomputed
+ * values, |n0inv| (fits in 32 bits) and |rr| and can always be
+ * represented in |key_num_bits|.
+
+ * The value |n0inv| is the value -1/n[0] (mod 2^32). The value |rr|
+ * is (2^key_num_bits)^2 (mod n).
+ *
+ * Following this header is |key_num_bits| bits of |n|, then
+ * |key_num_bits| bits of |rr|. Both values are stored with most
+ * significant bit first. Each serialized number takes up
+ * |key_num_bits|/8 bytes.
+ *
+ * All fields in this struct are stored in network byte order when
+ * serialized.  To generate a copy with fields swapped to native byte
+ * order, use the function avb_rsa_public_key_header_validate_and_byteswap().
+ *
+ * The avb_rsa_verify() function expects a key in this serialized
+ * format.
+ *
+ * The 'avbtool extract_public_key' command can be used to generate a
+ * serialized RSA public key.
+ */
+typedef struct AvbRSAPublicKeyHeader {
+  uint32_t key_num_bits;
+  uint32_t n0inv;
+} AVB_ATTR_PACKED AvbRSAPublicKeyHeader;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ */
+bool avb_rsa_public_key_header_validate_and_byteswap(
+    const AvbRSAPublicKeyHeader* src,
+    AvbRSAPublicKeyHeader* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_CRYPTO_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_descriptor.c b/platform/msm_shared/avb/libavb/avb_descriptor.c
new file mode 100644
index 0000000..4f8e925
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_descriptor.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_descriptor.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+
+bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
+                                          AvbDescriptor* dest) {
+  dest->tag = avb_be64toh(src->tag);
+  dest->num_bytes_following = avb_be64toh(src->num_bytes_following);
+
+  if ((dest->num_bytes_following & 0x07) != 0) {
+    avb_error("Descriptor size is not divisible by 8.\n");
+    return false;
+  }
+  return true;
+}
+
+bool avb_descriptor_foreach(const uint8_t* image_data,
+                            size_t image_size,
+                            AvbDescriptorForeachFunc foreach_func,
+                            void* user_data) {
+  const AvbVBMetaImageHeader* header = NULL;
+  bool ret = false;
+  const uint8_t* image_end;
+  const uint8_t* desc_start;
+  const uint8_t* desc_end;
+  const uint8_t* p;
+
+  if (image_data == NULL) {
+    avb_error("image_data is NULL\n.");
+    goto out;
+  }
+
+  if (foreach_func == NULL) {
+    avb_error("foreach_func is NULL\n.");
+    goto out;
+  }
+
+  if (image_size < sizeof(AvbVBMetaImageHeader)) {
+    avb_error("Length is smaller than header.\n");
+    goto out;
+  }
+
+  /* Ensure magic is correct. */
+  if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+    avb_error("Magic is incorrect.\n");
+    goto out;
+  }
+
+  /* Careful, not byteswapped - also ensure it's aligned properly. */
+  avb_assert_aligned(image_data);
+  header = (const AvbVBMetaImageHeader*)image_data;
+  image_end = image_data + image_size;
+
+  desc_start = image_data + sizeof(AvbVBMetaImageHeader) +
+               avb_be64toh(header->authentication_data_block_size) +
+               avb_be64toh(header->descriptors_offset);
+
+  desc_end = desc_start + avb_be64toh(header->descriptors_size);
+
+  if (desc_start < image_data || desc_start > image_end ||
+      desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
+    avb_error("Descriptors not inside passed-in data.\n");
+    goto out;
+  }
+
+  for (p = desc_start; p < desc_end;) {
+    const AvbDescriptor* dh = (const AvbDescriptor*)p;
+    avb_assert_aligned(dh);
+    uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
+    uint64_t nb_total = sizeof(AvbDescriptor) + nb_following;
+
+    if ((nb_total & 7) != 0) {
+      avb_error("Invalid descriptor length.\n");
+      goto out;
+    }
+
+    if (nb_total + p < desc_start || nb_total + p > desc_end) {
+      avb_error("Invalid data in descriptors array.\n");
+      goto out;
+    }
+
+    if (foreach_func(dh, user_data) == 0) {
+      goto out;
+    }
+
+    p += nb_total;
+  }
+
+  ret = true;
+
+out:
+  return ret;
+}
+
+static bool count_descriptors(const AvbDescriptor* descriptor,
+                              void* user_data) {
+  size_t* num_descriptors = user_data;
+  *num_descriptors += 1;
+  return true;
+}
+
+typedef struct {
+  size_t descriptor_number;
+  const AvbDescriptor** descriptors;
+} SetDescriptorData;
+
+static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
+  SetDescriptorData* data = user_data;
+  data->descriptors[data->descriptor_number++] = descriptor;
+  return true;
+}
+
+const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
+                                             size_t image_size,
+                                             size_t* out_num_descriptors) {
+  size_t num_descriptors = 0;
+  SetDescriptorData data;
+
+  avb_descriptor_foreach(
+      image_data, image_size, count_descriptors, &num_descriptors);
+
+  data.descriptor_number = 0;
+  data.descriptors =
+      avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
+  if (data.descriptors == NULL) {
+    return NULL;
+  }
+  avb_descriptor_foreach(image_data, image_size, set_descriptors, &data);
+  avb_assert(data.descriptor_number == num_descriptors);
+
+  if (out_num_descriptors != NULL) {
+    *out_num_descriptors = num_descriptors;
+  }
+
+  return data.descriptors;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_descriptor.h b/platform/msm_shared/avb/libavb/avb_descriptor.h
new file mode 100644
index 0000000..5d0f0c6
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_descriptor.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_DESCRIPTOR_H_
+#define AVB_DESCRIPTOR_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Well-known descriptor tags.
+ *
+ * AVB_DESCRIPTOR_TAG_PROPERTY: see |AvbPropertyDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_HASHTREE: see |AvbHashtreeDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_HASH: see |AvbHashDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: see |AvbKernelCmdlineDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: see |AvbChainPartitionDescriptor| struct.
+ */
+typedef enum {
+  AVB_DESCRIPTOR_TAG_PROPERTY,
+  AVB_DESCRIPTOR_TAG_HASHTREE,
+  AVB_DESCRIPTOR_TAG_HASH,
+  AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
+  AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
+} AvbDescriptorTag;
+
+/* The header for a serialized descriptor.
+ *
+ * A descriptor always have two fields, a |tag| (denoting its type,
+ * see the |AvbDescriptorTag| enumeration) and the size of the bytes
+ * following, |num_bytes_following|.
+ *
+ * For padding, |num_bytes_following| is always a multiple of 8.
+ */
+typedef struct AvbDescriptor {
+  uint64_t tag;
+  uint64_t num_bytes_following;
+} AVB_ATTR_PACKED AvbDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_descriptor_validate_and_byteswap(
+    const AvbDescriptor* src, AvbDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Signature for callback function used in avb_descriptor_foreach().
+ * The passed in descriptor is given by |descriptor| and the
+ * |user_data| passed to avb_descriptor_foreach() function is in
+ * |user_data|. Return true to continue iterating, false to stop
+ * iterating.
+ *
+ * Note that |descriptor| points into the image passed to
+ * avb_descriptor_foreach() - all fields need to be byteswapped!
+ */
+typedef bool AvbDescriptorForeachFunc(const AvbDescriptor* descriptor,
+                                      void* user_data);
+
+/* Convenience function to iterate over all descriptors in an vbmeta
+ * image.
+ *
+ * The function given by |foreach_func| will be called for each
+ * descriptor. The given function should return true to continue
+ * iterating, false to stop.
+ *
+ * The |user_data| parameter will be passed to |foreach_func|.
+ *
+ * Returns false if the iteration was short-circuited, that is if
+ * an invocation of |foreach_func| returned false.
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a known
+ * good public key. Additionally, |image_data| must be word-aligned.
+ */
+bool avb_descriptor_foreach(const uint8_t* image_data,
+                            size_t image_size,
+                            AvbDescriptorForeachFunc foreach_func,
+                            void* user_data);
+
+/* Gets all descriptors in a vbmeta image.
+ *
+ * The return value is a NULL-pointer terminated array of
+ * AvbDescriptor pointers. Free with avb_free() when you are done with
+ * it. If |out_num_descriptors| is non-NULL, the number of descriptors
+ * will be returned there.
+ *
+ * Note that each AvbDescriptor pointer in the array points into
+ * |image_data| - all fields need to be byteswapped!
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a known
+ * good public key. Additionally, |image_data| must be word-aligned.
+ */
+const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
+                                             size_t image_size,
+                                             size_t* out_num_descriptors)
+    AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_DESCRIPTOR_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_footer.c b/platform/msm_shared/avb/libavb/avb_footer.c
new file mode 100644
index 0000000..b8b8211
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_footer.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_footer.h"
+#include "avb_util.h"
+
+bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest) {
+  avb_memcpy(dest, src, sizeof(AvbFooter));
+
+  dest->version_major = avb_be32toh(dest->version_major);
+  dest->version_minor = avb_be32toh(dest->version_minor);
+
+  dest->original_image_size = avb_be64toh(dest->original_image_size);
+  dest->vbmeta_offset = avb_be64toh(dest->vbmeta_offset);
+  dest->vbmeta_size = avb_be64toh(dest->vbmeta_size);
+
+  /* Check that magic is correct. */
+  if (avb_safe_memcmp(dest->magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) !=
+      0) {
+    avb_error("Footer magic is incorrect.\n");
+    return false;
+  }
+
+  /* Ensure we don't attempt to access any fields if the footer major
+   * version is not supported.
+   */
+  if (dest->version_major > AVB_FOOTER_VERSION_MAJOR) {
+    avb_error("No support for footer version.\n");
+    return false;
+  }
+
+  return true;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_footer.h b/platform/msm_shared/avb/libavb/avb_footer.h
new file mode 100644
index 0000000..e84826f
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_footer.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_FOOTER_H_
+#define AVB_FOOTER_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Magic for the footer. */
+#define AVB_FOOTER_MAGIC "AVBf"
+#define AVB_FOOTER_MAGIC_LEN 4
+
+/* Size of the footer. */
+#define AVB_FOOTER_SIZE 64
+
+/* The current footer version used - keep in sync with avbtool. */
+#define AVB_FOOTER_VERSION_MAJOR 1
+#define AVB_FOOTER_VERSION_MINOR 0
+
+/* The struct used as a footer used on partitions, used to find the
+ * AvbVBMetaImageHeader struct. This struct is always stored at the
+ * end of a partition.
+ */
+typedef struct AvbFooter {
+  /*   0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
+  uint8_t magic[AVB_FOOTER_MAGIC_LEN];
+  /*   4: The major version of the footer struct. */
+  uint32_t version_major;
+  /*   8: The minor version of the footer struct. */
+  uint32_t version_minor;
+
+  /*  12: The original size of the image on the partition. */
+  uint64_t original_image_size;
+
+  /*  20: The offset of the |AvbVBMetaImageHeader| struct. */
+  uint64_t vbmeta_offset;
+
+  /*  28: The size of the vbmeta block (header + auth + aux blocks). */
+  uint64_t vbmeta_size;
+
+  /*  36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
+   * must be set to zeroes.
+   */
+  uint8_t reserved[28];
+} AVB_ATTR_PACKED AvbFooter;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ */
+bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest)
+    AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_FOOTER_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_hash_descriptor.c b/platform/msm_shared/avb/libavb/avb_hash_descriptor.c
new file mode 100644
index 0000000..2e427de
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_hash_descriptor.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_hash_descriptor.h"
+#include "avb_util.h"
+
+bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
+                                               AvbHashDescriptor* dest) {
+  uint64_t expected_size;
+
+  avb_memcpy(dest, src, sizeof(AvbHashDescriptor));
+
+  if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+                                            (AvbDescriptor*)dest))
+    return false;
+
+  if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASH) {
+    avb_error("Invalid tag for hash descriptor.\n");
+    return false;
+  }
+
+  dest->image_size = avb_be64toh(dest->image_size);
+  dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+  dest->salt_len = avb_be32toh(dest->salt_len);
+  dest->digest_len = avb_be32toh(dest->digest_len);
+
+  /* Check that partition_name, salt, and digest are fully contained. */
+  expected_size = sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor);
+  if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+      !avb_safe_add_to(&expected_size, dest->salt_len) ||
+      !avb_safe_add_to(&expected_size, dest->digest_len)) {
+    avb_error("Overflow while adding up sizes.\n");
+    return false;
+  }
+  if (expected_size > dest->parent_descriptor.num_bytes_following) {
+    avb_error("Descriptor payload size overflow.\n");
+    return false;
+  }
+  return true;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_hash_descriptor.h b/platform/msm_shared/avb/libavb/avb_hash_descriptor.h
new file mode 100644
index 0000000..2668118
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_hash_descriptor.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_HASH_DESCRIPTOR_H_
+#define AVB_HASH_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A descriptor containing information about hash for an image.
+ *
+ * This descriptor is typically used for boot partitions to verify the
+ * entire kernel+initramfs image before executing it.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
+ * |digest_len| bytes of the digest.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ */
+typedef struct AvbHashDescriptor {
+  AvbDescriptor parent_descriptor;
+  uint64_t image_size;
+  uint8_t hash_algorithm[32];
+  uint32_t partition_name_len;
+  uint32_t salt_len;
+  uint32_t digest_len;
+  uint8_t reserved[64];
+} AVB_ATTR_PACKED AvbHashDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
+                                               AvbHashDescriptor* dest)
+    AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_HASH_DESCRIPTOR_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_hashtree_descriptor.c b/platform/msm_shared/avb/libavb/avb_hashtree_descriptor.c
new file mode 100644
index 0000000..b961e47
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_hashtree_descriptor.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_hashtree_descriptor.h"
+#include "avb_util.h"
+
+bool avb_hashtree_descriptor_validate_and_byteswap(
+    const AvbHashtreeDescriptor* src, AvbHashtreeDescriptor* dest) {
+  uint64_t expected_size;
+
+  avb_memcpy(dest, src, sizeof(AvbHashtreeDescriptor));
+
+  if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+                                            (AvbDescriptor*)dest))
+    return false;
+
+  if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASHTREE) {
+    avb_error("Invalid tag for hashtree descriptor.\n");
+    return false;
+  }
+
+  dest->dm_verity_version = avb_be32toh(dest->dm_verity_version);
+  dest->image_size = avb_be64toh(dest->image_size);
+  dest->tree_offset = avb_be64toh(dest->tree_offset);
+  dest->tree_size = avb_be64toh(dest->tree_size);
+  dest->data_block_size = avb_be32toh(dest->data_block_size);
+  dest->hash_block_size = avb_be32toh(dest->hash_block_size);
+  dest->fec_num_roots = avb_be32toh(dest->fec_num_roots);
+  dest->fec_offset = avb_be64toh(dest->fec_offset);
+  dest->fec_size = avb_be64toh(dest->fec_size);
+  dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+  dest->salt_len = avb_be32toh(dest->salt_len);
+  dest->root_digest_len = avb_be32toh(dest->root_digest_len);
+
+  /* Check that partition_name, salt, and root_digest are fully contained. */
+  expected_size = sizeof(AvbHashtreeDescriptor) - sizeof(AvbDescriptor);
+  if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+      !avb_safe_add_to(&expected_size, dest->salt_len) ||
+      !avb_safe_add_to(&expected_size, dest->root_digest_len)) {
+    avb_error("Overflow while adding up sizes.\n");
+    return false;
+  }
+  if (expected_size > dest->parent_descriptor.num_bytes_following) {
+    avb_error("Descriptor payload size overflow.\n");
+    return false;
+  }
+  return true;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_hashtree_descriptor.h b/platform/msm_shared/avb/libavb/avb_hashtree_descriptor.h
new file mode 100644
index 0000000..a5aafbf
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_hashtree_descriptor.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_HASHTREE_DESCRIPTOR_H_
+#define AVB_HASHTREE_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A descriptor containing information about a dm-verity hashtree.
+ *
+ * Hash-trees are used to verify large partitions typically containing
+ * file systems. See
+ * https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
+ * information about dm-verity.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
+ * |root_digest_len| bytes of the root digest.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ */
+typedef struct AvbHashtreeDescriptor {
+  AvbDescriptor parent_descriptor;
+  uint32_t dm_verity_version;
+  uint64_t image_size;
+  uint64_t tree_offset;
+  uint64_t tree_size;
+  uint32_t data_block_size;
+  uint32_t hash_block_size;
+  uint32_t fec_num_roots;
+  uint64_t fec_offset;
+  uint64_t fec_size;
+  uint8_t hash_algorithm[32];
+  uint32_t partition_name_len;
+  uint32_t salt_len;
+  uint32_t root_digest_len;
+  uint8_t reserved[64];
+} AVB_ATTR_PACKED AvbHashtreeDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_hashtree_descriptor_validate_and_byteswap(
+    const AvbHashtreeDescriptor* src,
+    AvbHashtreeDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_HASHTREE_DESCRIPTOR_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_kernel_cmdline_descriptor.c b/platform/msm_shared/avb/libavb/avb_kernel_cmdline_descriptor.c
new file mode 100644
index 0000000..67521f2
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_kernel_cmdline_descriptor.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_util.h"
+
+bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
+    const AvbKernelCmdlineDescriptor* src, AvbKernelCmdlineDescriptor* dest) {
+  uint64_t expected_size;
+
+  avb_memcpy(dest, src, sizeof(AvbKernelCmdlineDescriptor));
+
+  if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+                                            (AvbDescriptor*)dest))
+    return false;
+
+  if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) {
+    avb_error("Invalid tag for kernel cmdline descriptor.\n");
+    return false;
+  }
+
+  dest->flags = avb_be32toh(dest->flags);
+  dest->kernel_cmdline_length = avb_be32toh(dest->kernel_cmdline_length);
+
+  /* Check that kernel_cmdline is fully contained. */
+  expected_size = sizeof(AvbKernelCmdlineDescriptor) - sizeof(AvbDescriptor);
+  if (!avb_safe_add_to(&expected_size, dest->kernel_cmdline_length)) {
+    avb_error("Overflow while adding up sizes.\n");
+    return false;
+  }
+  if (expected_size > dest->parent_descriptor.num_bytes_following) {
+    avb_error("Descriptor payload size overflow.\n");
+    return false;
+  }
+
+  return true;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_kernel_cmdline_descriptor.h b/platform/msm_shared/avb/libavb/avb_kernel_cmdline_descriptor.h
new file mode 100644
index 0000000..6908b3b
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_kernel_cmdline_descriptor.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
+#define AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flags for kernel command-line descriptors.
+ *
+ * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED: The
+ * cmdline will only be applied if hashtree verification is not
+ * disabled (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
+ *
+ * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED: The cmdline
+ * will only be applied if hashtree verification is disabled
+ * (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
+ */
+typedef enum {
+  AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED = (1 << 0),
+  AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED = (1 << 1)
+} AvbKernelCmdlineFlags;
+
+/* A descriptor containing information to be appended to the kernel
+ * command-line.
+ *
+ * The |flags| field contains flags from the AvbKernelCmdlineFlags
+ * enumeration.
+ *
+ * Following this struct are |kernel_cmdline_len| bytes with the
+ * kernel command-line (UTF-8 encoded).
+ */
+typedef struct AvbKernelCmdlineDescriptor {
+  AvbDescriptor parent_descriptor;
+  uint32_t flags;
+  uint32_t kernel_cmdline_length;
+} AVB_ATTR_PACKED AvbKernelCmdlineDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
+    const AvbKernelCmdlineDescriptor* src,
+    AvbKernelCmdlineDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_KERNEL_CMDLINE_DESCRIPTOR_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_ops.c b/platform/msm_shared/avb/libavb/avb_ops.c
new file mode 100644
index 0000000..97aa79b
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_ops.c
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Copyright (c) 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ *  with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "../OEMPublicKey.h"
+#include "avb_sysdeps.h"
+#include "libavb.h"
+#include <platform.h>
+#include <err.h>
+#include <ab_partition_parser.h>
+#include <partition_parser.h>
+
+struct partition_entry *PtnEntries;
+
+bool IsCurrentSlotSuccessful()
+{
+   struct ab_slot_info slot_info[AB_SUPPORTED_SLOTS];
+   int slot_idx =INVALID;
+
+   slot_idx = partition_find_active_slot();
+   if(slot_idx == INVALID)
+   {
+	   dprintf(CRITICAL,
+	           "IsCurrentSlotSuccessful: no active slots found!\n");
+	   return FALSE;
+	}
+   partition_fill_slot_meta(slot_info);
+   if(!strncmp(slot_info[slot_idx].slot_is_succesful_rsp,"yes",strlen("yes")))
+       return TRUE;
+
+   return FALSE;
+}
+
+static struct partition_entry *Getpartition_entry(const char *Partition)
+{
+	int32_t Index = partition_get_index(Partition);
+	struct partition_entry *partition_entries =
+				partition_get_partition_entries();
+	if (partition_entries == NULL) {
+                dprintf(CRITICAL, "Getpartition_entry: No partition entry found\n");
+                return NULL;
+        }
+
+	PtnEntries = partition_entries;
+
+	if (Index == INVALID_PTN) {
+		dprintf(CRITICAL, "Getpartition_entry: No partition entry for "
+		           "%s, invalid index\n", Partition);
+		return NULL;
+	}
+	return &PtnEntries[Index];
+}
+
+int get_unique_guid(const char *Partition, char *unique_guid)
+{
+        struct partition_entry *gp = Getpartition_entry(Partition);
+	if(gp == NULL)
+	{
+		dprintf(CRITICAL, "Partition entry not found\n");
+                return -1;
+
+	}
+        if (!unique_guid)
+                return -1;
+
+        memcpy(unique_guid, gp->unique_partition_guid, UNIQUE_PARTITION_GUID_SIZE);
+
+        return 0;
+}
+
+static struct partition_entry *GetBootpartition_entry(Slot *BootSlot)
+{
+	int32_t Index = INVALID_PTN;
+	struct partition_entry *partition_entries =
+				partition_get_partition_entries();
+	if( BootSlot == NULL)
+        {
+                dprintf(INFO, "No bootable slot found \n");
+                return NULL;
+
+        }
+	if( partition_entries == NULL)
+	{
+		dprintf(INFO, "No partition entry found \n");
+                return NULL;
+
+	}
+	PtnEntries = partition_entries;
+
+	if (strncmp("_a", (const char *)BootSlot->Suffix, strlen((const char *)BootSlot->Suffix)) == 0) {
+		Index = partition_get_index("boot_a");
+	} else if (strncmp("_b", (const char *)BootSlot->Suffix, strlen((const char *)BootSlot->Suffix)) == 0) {
+		Index = partition_get_index("boot_b");
+	} else {
+		dprintf(CRITICAL, "GetBootpartition_entry: No boot partition "
+		                    "entry for slot %s\n", (char *)BootSlot->Suffix);
+		return NULL;
+	}
+
+	if (Index == INVALID_PTN) {
+		dprintf(CRITICAL,
+		       "GetBootpartition_entry: No boot partition entry "
+		       "for slot %s, invalid index\n", (char *)BootSlot->Suffix);
+		return NULL;
+	}
+	return &PtnEntries[Index];
+}
+
+AvbIOResult AvbReadFromPartition(AvbOps *Ops, const char *Partition, int64_t ReadOffset,
+                     size_t NumBytes, void *Buffer, size_t *OutNumRead)
+{
+	AvbIOResult Result = AVB_IO_RESULT_OK;
+	EFI_STATUS Status = EFI_SUCCESS;
+	VOID *Page = NULL;
+	UINT32 Offset = 0;
+	UINTN ptn = 0;
+	UINT32 PageSize = 0;
+	UINT32 StartBlock = 0;
+	UINT32 LastBlock = 0;
+	UINT32 FullBlock = 0;
+	UINTN StartPageReadSize = 0;
+	int index = INVALID_PTN;
+
+	if (Partition == NULL || Buffer == NULL || OutNumRead == NULL || NumBytes <= 0) {
+		dprintf(CRITICAL, "bad input paramaters\n");
+		Result = AVB_IO_RESULT_ERROR_IO;
+		goto out;
+	}
+	*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");
+		return AVB_IO_RESULT_OK;
+	}
+
+	index = partition_get_index(Partition);
+	ptn = partition_get_offset(index);
+
+	if (ReadOffset < 0) {
+		if ((-ReadOffset) > ptn) {
+			dprintf(CRITICAL,
+			       "Negative Offset outside range.\n");
+			Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+			goto out;
+		}
+		Offset = ptn - (-ReadOffset);
+		dprintf(DEBUG,
+		       "negative Offset (%lld) converted to (%u) \n", ReadOffset, Offset);
+	} else {
+		// check int64_t to UINT32 converstion?
+		Offset = ReadOffset;
+	}
+
+	if (Offset > ptn) {
+		dprintf(CRITICAL, "Offset outside range.\n");
+		Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+		goto out;
+	}
+
+	if (NumBytes > ptn - Offset) {
+		NumBytes = ptn - Offset;
+	}
+
+	dprintf(CRITICAL,
+	       "read from %s, 0x%x bytes at Offset 0x%x, partition size %lu\n",
+	       Partition, NumBytes, Offset, ptn);
+
+	/* |NumBytes| and or |Offset| can be unaligned to block size/page size.
+	 */
+	//PageSize = mmc_get_device_blocksize();
+	PageSize = get_page_size();
+	Page = avb_malloc(PageSize);
+	if (Page == NULL) {
+		dprintf(CRITICAL, "Allocate for partial read failed!");
+		Result = AVB_IO_RESULT_ERROR_OOM;
+		goto out;
+	}
+
+	StartBlock = Offset / PageSize;
+	LastBlock = (NumBytes + Offset) / PageSize;
+	FullBlock = StartBlock;
+	StartPageReadSize = 0;
+
+	if (Offset % PageSize != 0) {
+		/* Offset not aligned to PageSize*/
+		UINT32 StartPageReadOffset = Offset - (StartBlock * PageSize);
+
+		if (StartBlock == LastBlock) {
+			/* Offset & Offset + NumBytes are in same block */
+			StartPageReadSize = NumBytes;
+		} else {
+			StartPageReadSize = PageSize - StartPageReadOffset;
+			FullBlock++;
+		}
+
+		dprintf(DEBUG,
+		       "StartBlock 0x%x, ReadOffset 0x%x, read_size 0x%lx\n",
+		       StartBlock, StartPageReadOffset, StartPageReadSize);
+		if (StartPageReadSize <= 0 || StartPageReadOffset >= PageSize ||
+		    StartPageReadSize > PageSize - StartPageReadOffset ||
+		    StartPageReadSize > NumBytes) {
+			dprintf(CRITICAL,
+			       "StartBlock 0x%x, ReadOffset 0x%x, read_size "
+			       "0x%lx outside range.\n",
+			       StartBlock, StartPageReadOffset, StartPageReadSize);
+			Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+			goto out;
+		}
+
+		Status = mmc_read(ptn, Page, PageSize);
+		if (Status == EFI_SUCCESS) {
+			avb_memcpy(Buffer, Page + StartPageReadOffset, StartPageReadSize);
+			*OutNumRead += StartPageReadSize;
+		} else {
+			*OutNumRead = 0;
+			dprintf(CRITICAL, "ReadBlocks failed %d\n", Status);
+			goto out;
+		}
+	}
+
+	if (*OutNumRead < NumBytes && (NumBytes + Offset) % PageSize != 0) {
+		/* NumBytes + Offset not aligned to PageSize*/
+		/* Offset for last block is always zero, start at Page boundary
+		 */
+		UINT32 LastPageReadOffset = 0;
+		UINTN ReadOffset2 = (LastBlock * PageSize);
+		UINTN LastPageReadSize = (Offset + NumBytes) - ReadOffset2;
+
+		dprintf(DEBUG,
+		       "LastBlock 0x%x, ReadOffset 0x%x, read_size 0x%lx\n",
+		       LastBlock, LastPageReadOffset, LastPageReadSize);
+
+		if (LastPageReadSize <= 0 || LastPageReadSize >= PageSize ||
+		    LastPageReadSize > (NumBytes - *OutNumRead)) {
+			dprintf(CRITICAL,
+			       "LastBlock 0x%x, ReadOffset 0x%x, read_size "
+			       "0x%lx outside range.\n",
+			       LastBlock, LastPageReadOffset, LastPageReadSize);
+			Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+			goto out;
+		}
+
+		Status = mmc_read(ptn + ReadOffset2, Page, PageSize);
+		if (Status == EFI_SUCCESS) {
+			avb_memcpy(Buffer + (NumBytes - LastPageReadSize), Page,
+			           LastPageReadSize);
+			*OutNumRead += LastPageReadSize;
+		} else {
+			*OutNumRead = 0;
+			dprintf(CRITICAL, "ReadBlocks failed %d\n", Status);
+			goto out;
+		}
+	}
+
+	if (*OutNumRead < NumBytes) {
+		/* full block reads */
+		UINTN FillPageReadSize = NumBytes - *OutNumRead;
+
+		if ((FillPageReadSize % PageSize) != 0 ||
+		    (NumBytes - StartPageReadSize) < FillPageReadSize) {
+			dprintf(CRITICAL,
+			       "FullBlock 0x%x, ReadOffset 0x%x, read_size "
+			       "0x%lx outside range.\n",
+			       FullBlock, 0, FillPageReadSize);
+			Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+			goto out;
+		}
+			dprintf(SPEW,
+			       "FullBlock 0x%x, ReadOffset 0x%x, read_size "
+			       "0x%lx outside range. StartPageReadSize %#lx PageSize %d ptn %#lx Buffer %p\n",
+			       FullBlock, 0, FillPageReadSize, StartPageReadSize, PageSize, ptn, Buffer);
+		Status = mmc_read(ptn + FullBlock * PageSize, Buffer + StartPageReadSize,
+					FillPageReadSize);
+		if (Status == EFI_SUCCESS) {
+			*OutNumRead += FillPageReadSize;
+		} else {
+			*OutNumRead = 0;
+			dprintf(CRITICAL, "ReadBlocks failed %d\n", Status);
+			goto out;
+		}
+	}
+out:
+	if (Page != NULL) {
+		avb_free(Page);
+	}
+
+	return Result;
+}
+
+AvbIOResult AvbWriteToPartition(AvbOps *Ops, const char *Partition, int64_t Offset,
+                                size_t NumBytes, const void *Buffer)
+{
+	/* unsupported api */
+	return AVB_IO_RESULT_ERROR_IO;
+}
+
+AvbIOResult
+AvbValidateVbmetaPublicKey(AvbOps *Ops, const uint8_t *PublicKeyData,
+                           size_t PublicKeyLength, const uint8_t *PublicKeyMetadata,
+                           size_t PublicKeyMetadataLength, bool *OutIsTrusted)
+{
+	UINT8 *UserKeyBuffer = NULL;
+	UINT32 UserKeyLength = 0;
+	EFI_STATUS Status = EFI_SUCCESS;
+	AvbOpsUserData *UserData = NULL;
+
+	dprintf(DEBUG, "ValidateVbmetaPublicKey PublicKeyLength %d, "
+	                      "PublicKeyMetadataLength %d\n",
+	       PublicKeyLength, PublicKeyMetadataLength);
+
+	if (Ops == NULL || OutIsTrusted == NULL || PublicKeyData == NULL) {
+		dprintf(CRITICAL, "Invalid parameters\n");
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+
+	Status = get_userkey(&UserKeyBuffer, &UserKeyLength);
+	if (Status != EFI_SUCCESS) {
+		dprintf(CRITICAL, "get_userkey failed\n");
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+
+	UserData = (AvbOpsUserData *)Ops->user_data;
+	UserData->IsUserKey = FALSE;
+
+	if (PublicKeyLength == UserKeyLength &&
+	    memcmp(PublicKeyData, UserKeyBuffer, PublicKeyLength) == 0) {
+		*OutIsTrusted = true;
+		UserData->IsUserKey = TRUE;
+	} else if (PublicKeyLength == ARRAY_SIZE(OEMPublicKey) &&
+	           memcmp(PublicKeyData, OEMPublicKey, PublicKeyLength) == 0) {
+		*OutIsTrusted = true;
+	} else {
+		*OutIsTrusted = false;
+		memset(UserData->PublicKey, 0, ARRAY_SIZE(UserData->PublicKey));
+		UserData->PublicKeyLen = 0;
+	}
+
+	if (*OutIsTrusted == true) {
+		if (PublicKeyLength > ARRAY_SIZE(UserData->PublicKey)) {
+			dprintf(CRITICAL, "ValidateVbmetaPublicKey: "
+			                    "public key length too large %d\n",
+			       PublicKeyLength);
+			return AVB_IO_RESULT_ERROR_OOM;
+		}
+		memcpy(UserData->PublicKey, PublicKeyData, PublicKeyLength);
+		UserData->PublicKeyLen = PublicKeyLength;
+	}
+	dprintf(DEBUG,
+	       "ValidateVbmetaPublicKey OutIsTrusted %d, UserKey %d\n",
+	       *OutIsTrusted, UserData->IsUserKey);
+	return AVB_IO_RESULT_OK;
+}
+
+
+AvbIOResult AvbReadRollbackIndex(AvbOps *Ops, size_t RollbackIndexLocation,
+                                 uint64_t *OutRollbackIndex)
+{
+
+	EFI_STATUS Status = read_rollback_index(RollbackIndexLocation, OutRollbackIndex);
+
+	if (Status != EFI_SUCCESS) {
+		dprintf(CRITICAL, "ReadRollbackIndex failed! %d\n", Status);
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+	dprintf(DEBUG,
+	       "ReadRollbackIndex Location %zu, RollbackIndex %llu\n",
+	       RollbackIndexLocation, *OutRollbackIndex);
+	return AVB_IO_RESULT_OK;
+}
+
+AvbIOResult
+AvbWriteRollbackIndex(AvbOps *Ops, size_t RollbackIndexLocation, uint64_t RollbackIndex)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+
+	dprintf(DEBUG,
+	       "WriteRollbackIndex Location %zu, RollbackIndex %llu\n",
+	       RollbackIndexLocation, RollbackIndex);
+	/* Update rollback if the current slot is successful */
+	if (IsCurrentSlotSuccessful()) {
+		dprintf(INFO,
+		       "Updating rollback index %llu, for location %zu\n",
+		       RollbackIndex, RollbackIndexLocation);
+		Status = write_rollback_index(RollbackIndexLocation, RollbackIndex);
+		if (Status != EFI_SUCCESS) {
+			dprintf(CRITICAL, "ReadRollbackIndex failed! %d\n", Status);
+			return AVB_IO_RESULT_ERROR_IO;
+		}
+	} else {
+		dprintf(INFO, "Not updating rollback index as current "
+		                   "slot is not successful\n");
+	}
+	return AVB_IO_RESULT_OK;
+}
+
+AvbIOResult AvbReadIsDeviceUnlocked(AvbOps *Ops, bool *OutIsUnlocked)
+{
+	if (OutIsUnlocked == NULL) {
+		dprintf(CRITICAL, "bad input paramaters\n");
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+	*OutIsUnlocked = !is_device_locked();
+	return AVB_IO_RESULT_OK;
+}
+
+static VOID GuidToHex(CHAR8 *Buf, EFI_GUID *Guid)
+{
+	CHAR8 HexDigits[17] = "0123456789abcdef";
+
+	Buf[0] = HexDigits[(Guid->Data1 >> 28) & 0x0f];
+	Buf[1] = HexDigits[(Guid->Data1 >> 24) & 0x0f];
+	Buf[2] = HexDigits[(Guid->Data1 >> 20) & 0x0f];
+	Buf[3] = HexDigits[(Guid->Data1 >> 16) & 0x0f];
+	Buf[4] = HexDigits[(Guid->Data1 >> 12) & 0x0f];
+	Buf[5] = HexDigits[(Guid->Data1 >> 8) & 0x0f];
+	Buf[6] = HexDigits[(Guid->Data1 >> 4) & 0x0f];
+	Buf[7] = HexDigits[(Guid->Data1 >> 0) & 0x0f];
+	Buf[8] = '-';
+	Buf[9] = HexDigits[(Guid->Data2 >> 12) & 0x0f];
+	Buf[10] = HexDigits[(Guid->Data2 >> 8) & 0x0f];
+	Buf[11] = HexDigits[(Guid->Data2 >> 4) & 0x0f];
+	Buf[12] = HexDigits[(Guid->Data2 >> 0) & 0x0f];
+	Buf[13] = '-';
+	Buf[14] = HexDigits[(Guid->Data3 >> 12) & 0x0f];
+	Buf[15] = HexDigits[(Guid->Data3 >> 8) & 0x0f];
+	Buf[16] = HexDigits[(Guid->Data3 >> 4) & 0x0f];
+	Buf[17] = HexDigits[(Guid->Data3 >> 0) & 0x0f];
+	Buf[18] = '-';
+	Buf[19] = HexDigits[(Guid->Data4[0] >> 4) & 0x0f];
+	Buf[20] = HexDigits[(Guid->Data4[0] >> 0) & 0x0f];
+	Buf[21] = HexDigits[(Guid->Data4[1] >> 4) & 0x0f];
+	Buf[22] = HexDigits[(Guid->Data4[1] >> 0) & 0x0f];
+	Buf[23] = '-';
+	Buf[24] = HexDigits[(Guid->Data4[2] >> 4) & 0x0f];
+	Buf[25] = HexDigits[(Guid->Data4[2] >> 0) & 0x0f];
+	Buf[26] = HexDigits[(Guid->Data4[3] >> 4) & 0x0f];
+	Buf[27] = HexDigits[(Guid->Data4[3] >> 0) & 0x0f];
+	Buf[28] = HexDigits[(Guid->Data4[4] >> 4) & 0x0f];
+	Buf[29] = HexDigits[(Guid->Data4[4] >> 0) & 0x0f];
+	Buf[30] = HexDigits[(Guid->Data4[5] >> 4) & 0x0f];
+	Buf[31] = HexDigits[(Guid->Data4[5] >> 0) & 0x0f];
+	Buf[32] = HexDigits[(Guid->Data4[6] >> 4) & 0x0f];
+	Buf[33] = HexDigits[(Guid->Data4[6] >> 0) & 0x0f];
+	Buf[34] = HexDigits[(Guid->Data4[7] >> 4) & 0x0f];
+	Buf[35] = HexDigits[(Guid->Data4[7] >> 0) & 0x0f];
+	Buf[36] = '\0';
+}
+
+AvbIOResult AvbGetUniqueGuidForPartition(AvbOps *Ops, const char *PartitionName,
+                                         char *GuidBuf, size_t GuidBufSize)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+	char unique_partition_guid[UNIQUE_PARTITION_GUID_SIZE];
+	CHAR16 UnicodePartition[MAX_GPT_NAME_SIZE] = {0};
+
+	Status = get_unique_guid(PartitionName, unique_partition_guid);
+	if (Status) {
+		dprintf(CRITICAL,
+		       "get_unique_guid: No partition entry for %s\n",
+		       PartitionName);
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+
+	if ((strlen(PartitionName) + 1) > ARRAY_SIZE(UnicodePartition)) {
+		dprintf(CRITICAL, "AvbGetUniqueGuidForPartition: Partition "
+		                    "%s, name too large\n",
+		       PartitionName);
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+
+	GuidToHex(GuidBuf, (EFI_GUID *)unique_partition_guid);
+	dprintf(DEBUG, "%s uuid: %s\n", PartitionName, GuidBuf);
+
+	return AVB_IO_RESULT_OK;
+}
+
+AvbIOResult AvbGetSizeOfPartition(AvbOps *Ops, const char *Partition, uint64_t *OutSizeNumBytes)
+{
+	AvbIOResult Result = AVB_IO_RESULT_OK;
+	int index;
+
+	if (Ops == NULL || Partition == NULL || OutSizeNumBytes == NULL) {
+		dprintf(CRITICAL,
+		       "AvbGetSizeOfPartition invalid parameter pointers\n");
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+
+	index = partition_get_index(Partition);
+	*OutSizeNumBytes = (uint64_t)partition_get_size(index);
+	if (*OutSizeNumBytes == 0)
+		return AVB_IO_RESULT_ERROR_IO;
+
+	return Result;
+}
+
+AvbOps *AvbOpsNew(VOID *UserData)
+{
+	AvbOps *Ops = avb_calloc(sizeof(AvbOps));
+	if (Ops == NULL) {
+		dprintf(CRITICAL, "Error allocating memory for AvbOps.\n");
+		goto out;
+	}
+
+	Ops->user_data = UserData;
+	Ops->read_from_partition = AvbReadFromPartition;
+	Ops->write_to_partition = AvbWriteToPartition;
+	Ops->validate_vbmeta_public_key = AvbValidateVbmetaPublicKey;
+	Ops->read_rollback_index = AvbReadRollbackIndex;
+	Ops->write_rollback_index = AvbWriteRollbackIndex;
+	Ops->read_is_device_unlocked = AvbReadIsDeviceUnlocked;
+	Ops->get_unique_guid_for_partition = AvbGetUniqueGuidForPartition;
+	Ops->get_size_of_partition = AvbGetSizeOfPartition;
+
+out:
+	return Ops;
+}
+
+VOID AvbOpsFree(AvbOps *Ops)
+{
+	if (Ops != NULL) {
+		avb_free(Ops);
+	}
+}
diff --git a/platform/msm_shared/avb/libavb/avb_ops.h b/platform/msm_shared/avb/libavb/avb_ops.h
new file mode 100644
index 0000000..15c7b22
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_ops.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_OPS_H_
+#define AVB_OPS_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return codes used for I/O operations.
+ *
+ * AVB_IO_RESULT_OK is returned if the requested operation was
+ * successful.
+ *
+ * AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk
+ * or other subsystem) encountered an I/O error.
+ *
+ * AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory.
+ *
+ * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested
+ * partition does not exist.
+ *
+ * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
+ * range of bytes requested to be read or written is outside the range
+ * of the partition.
+ */
+typedef enum {
+  AVB_IO_RESULT_OK,
+  AVB_IO_RESULT_ERROR_OOM,
+  AVB_IO_RESULT_ERROR_IO,
+  AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
+  AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION
+} AvbIOResult;
+
+struct AvbOps;
+typedef struct AvbOps AvbOps;
+
+typedef struct {
+        uint32_t  Data1;
+        uint16_t  Data2;
+        uint16_t  Data3;
+        uint8_t   Data4[8];
+} EFI_GUID;
+
+/* Forward-declaration of operations in libavb_ab. */
+struct AvbABOps;
+
+/* Forward-declaration of operations in libavb_atx. */
+struct AvbAtxOps;
+
+/* High-level operations/functions/methods that are platform
+ * dependent.
+ *
+ * Operations may be added in the future so when implementing it
+ * always make sure to zero out sizeof(AvbOps) bytes of the struct to
+ * ensure that unimplemented operations are set to NULL.
+ */
+struct AvbOps {
+  /* This pointer can be used by the application/bootloader using
+   * libavb and is typically used in each operation to get a pointer
+   * to platform-specific resources. It cannot be used by libraries.
+   */
+  void* user_data;
+
+  /* If libavb_ab is used, this should point to the
+   * AvbABOps. Otherwise it must be set to NULL.
+   */
+  struct AvbABOps* ab_ops;
+
+  /* If libavb_atx is used, this should point to the
+   * AvbAtxOps. Otherwise it must be set to NULL.
+   */
+  struct AvbAtxOps* atx_ops;
+
+  /* Reads |num_bytes| from offset |offset| from partition with name
+   * |partition| (NUL-terminated UTF-8 string). If |offset| is
+   * negative, its absolute value should be interpreted as the number
+   * of bytes from the end of the partition.
+   *
+   * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
+   * there is no partition with the given name,
+   * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
+   * |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
+   * there was an I/O error from the underlying I/O subsystem.  If the
+   * operation succeeds as requested AVB_IO_RESULT_OK is returned and
+   * the data is available in |buffer|.
+   *
+   * The only time partial I/O may occur is if reading beyond the end
+   * of the partition. In this case the value returned in
+   * |out_num_read| may be smaller than |num_bytes|.
+   */
+  AvbIOResult (*read_from_partition)(AvbOps* ops,
+                                     const char* partition,
+                                     int64_t offset,
+                                     size_t num_bytes,
+                                     void* buffer,
+                                     size_t* out_num_read);
+
+  /* Writes |num_bytes| from |bffer| at offset |offset| to partition
+   * with name |partition| (NUL-terminated UTF-8 string). If |offset|
+   * is negative, its absolute value should be interpreted as the
+   * number of bytes from the end of the partition.
+   *
+   * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
+   * there is no partition with the given name,
+   * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
+   * byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
+   * if there was an I/O error from the underlying I/O subsystem.  If
+   * the operation succeeds as requested AVB_IO_RESULT_OK is
+   * returned.
+   *
+   * This function never does any partial I/O, it either transfers all
+   * of the requested bytes or returns an error.
+   */
+  AvbIOResult (*write_to_partition)(AvbOps* ops,
+                                    const char* partition,
+                                    int64_t offset,
+                                    size_t num_bytes,
+                                    const void* buffer);
+
+  /* Checks if the given public key used to sign the 'vbmeta'
+   * partition is trusted. Boot loaders typically compare this with
+   * embedded key material generated with 'avbtool
+   * extract_public_key'.
+   *
+   * The public key is in the array pointed to by |public_key_data|
+   * and is of |public_key_length| bytes.
+   *
+   * If there is no public key metadata (set with the avbtool option
+   * --public_key_metadata) then |public_key_metadata| will be set to
+   * NULL. Otherwise this field points to the data which is
+   * |public_key_metadata_length| bytes long.
+   *
+   * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
+   * true if trusted or false if untrusted.
+   */
+  AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
+                                            const uint8_t* public_key_data,
+                                            size_t public_key_length,
+                                            const uint8_t* public_key_metadata,
+                                            size_t public_key_metadata_length,
+                                            bool* out_is_trusted);
+
+  /* Gets the rollback index corresponding to the location given by
+   * |rollback_index_location|. The value is returned in
+   * |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
+   * index was retrieved, otherwise an error code.
+   *
+   * A device may have a limited amount of rollback index locations (say,
+   * one or four) so may error out if |rollback_index_location| exceeds
+   * this number.
+   */
+  AvbIOResult (*read_rollback_index)(AvbOps* ops,
+                                     size_t rollback_index_location,
+                                     uint64_t* out_rollback_index);
+
+  /* Sets the rollback index corresponding to the location given by
+   * |rollback_index_location| to |rollback_index|. Returns
+   * AVB_IO_RESULT_OK if the rollback index was set, otherwise an
+   * error code.
+   *
+   * A device may have a limited amount of rollback index locations (say,
+   * one or four) so may error out if |rollback_index_location| exceeds
+   * this number.
+   */
+  AvbIOResult (*write_rollback_index)(AvbOps* ops,
+                                      size_t rollback_index_location,
+                                      uint64_t rollback_index);
+
+  /* Gets whether the device is unlocked. The value is returned in
+   * |out_is_unlocked| (true if unlocked, false otherwise). Returns
+   * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
+   * code.
+   */
+  AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
+
+  /* Gets the unique partition GUID for a partition with name in
+   * |partition| (NUL-terminated UTF-8 string). The GUID is copied as
+   * a string into |guid_buf| of size |guid_buf_size| and will be NUL
+   * terminated. The string must be lower-case and properly
+   * hyphenated. For example:
+   *
+   *  527c1c6d-6361-4593-8842-3c78fcd39219
+   *
+   * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+   */
+  AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
+                                               const char* partition,
+                                               char* guid_buf,
+                                               size_t guid_buf_size);
+
+  /* Gets the size of a partition with the name in |partition|
+   * (NUL-terminated UTF-8 string). Returns the value in
+   * |out_size_num_bytes|.
+   *
+   * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+   */
+  AvbIOResult (*get_size_of_partition)(AvbOps* ops,
+                                       const char* partition,
+                                       uint64_t* out_size_num_bytes);
+};
+
+typedef struct {
+    BOOLEAN IsUserKey;
+    UINTN PublicKeyLen;
+    CHAR8 PublicKey[MAX_USER_KEY_SIZE];
+} AvbOpsUserData;
+
+AvbOps *AvbOpsNew(VOID *UserData);
+
+VOID AvbOpsFree(AvbOps *Ops);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_OPS_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_property_descriptor.c b/platform/msm_shared/avb/libavb/avb_property_descriptor.c
new file mode 100644
index 0000000..7eba2c0
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_property_descriptor.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_property_descriptor.h"
+#include "avb_util.h"
+
+bool avb_property_descriptor_validate_and_byteswap(
+    const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
+  uint64_t expected_size;
+
+  avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));
+
+  if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+                                            (AvbDescriptor*)dest))
+    return false;
+
+  if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
+    avb_error("Invalid tag for property descriptor.\n");
+    return false;
+  }
+
+  dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
+  dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);
+
+  /* Check that key and value are fully contained. */
+  expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
+  if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
+      !avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
+    avb_error("Overflow while adding up sizes.\n");
+    return false;
+  }
+  if (expected_size > dest->parent_descriptor.num_bytes_following) {
+    avb_error("Descriptor payload size overflow.\n");
+    return false;
+  }
+
+  return true;
+}
+
+typedef struct {
+  const char* key;
+  size_t key_size;
+  const char* ret_value;
+  size_t ret_value_size;
+} PropertyIteratorData;
+
+static bool property_lookup_desc_foreach(const AvbDescriptor* header,
+                                         void* user_data) {
+  PropertyIteratorData* data = (PropertyIteratorData*)user_data;
+  AvbPropertyDescriptor prop_desc;
+  const uint8_t* p;
+  bool ret = true;
+
+  if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
+    goto out;
+  }
+
+  if (!avb_property_descriptor_validate_and_byteswap(
+          (const AvbPropertyDescriptor*)header, &prop_desc)) {
+    goto out;
+  }
+
+  p = (const uint8_t*)header;
+  if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
+    avb_error("No terminating NUL byte in key.\n");
+    goto out;
+  }
+
+  if (data->key_size == prop_desc.key_num_bytes) {
+    if (avb_memcmp(p + sizeof(AvbPropertyDescriptor),
+                   data->key,
+                   data->key_size) == 0) {
+      data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
+                                      prop_desc.key_num_bytes + 1);
+      data->ret_value_size = prop_desc.value_num_bytes;
+      /* Stop iterating. */
+      ret = false;
+      goto out;
+    }
+  }
+
+out:
+  return ret;
+}
+
+const char* avb_property_lookup(const uint8_t* image_data,
+                                size_t image_size,
+                                const char* key,
+                                size_t key_size,
+                                size_t* out_value_size) {
+  PropertyIteratorData data;
+
+  if (key_size == 0) {
+    key_size = avb_strlen(key);
+  }
+
+  data.key = key;
+  data.key_size = key_size;
+
+  if (avb_descriptor_foreach(
+          image_data, image_size, property_lookup_desc_foreach, &data) == 0) {
+    if (out_value_size != NULL) {
+      *out_value_size = data.ret_value_size;
+    }
+    return data.ret_value;
+  }
+
+  if (out_value_size != NULL) {
+    *out_value_size = 0;
+  }
+  return NULL;
+}
+
+bool avb_property_lookup_uint64(const uint8_t* image_data,
+                                size_t image_size,
+                                const char* key,
+                                size_t key_size,
+                                uint64_t* out_value) {
+  const char* value;
+  bool ret = false;
+  uint64_t parsed_val;
+  int base;
+  int n;
+
+  value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
+  if (value == NULL) {
+    goto out;
+  }
+
+  base = 10;
+  if (avb_memcmp(value, "0x", 2) == 0) {
+    base = 16;
+    value += 2;
+  }
+
+  parsed_val = 0;
+  for (n = 0; value[n] != '\0'; n++) {
+    int c = value[n];
+    int digit;
+
+    parsed_val *= base;
+
+    if (c >= '0' && c <= '9') {
+      digit = c - '0';
+    } else if (base == 16 && c >= 'a' && c <= 'f') {
+      digit = c - 'a' + 10;
+    } else if (base == 16 && c >= 'A' && c <= 'F') {
+      digit = c - 'A' + 10;
+    } else {
+      avb_error("Invalid digit.\n");
+      goto out;
+    }
+
+    parsed_val += digit;
+  }
+
+  ret = true;
+  if (out_value != NULL) {
+    *out_value = parsed_val;
+  }
+
+out:
+  return ret;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_property_descriptor.h b/platform/msm_shared/avb/libavb/avb_property_descriptor.h
new file mode 100644
index 0000000..a2fef69
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_property_descriptor.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_PROPERTY_DESCRIPTOR_H_
+#define AVB_PROPERTY_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A descriptor for properties (free-form key/value pairs).
+ *
+ * Following this struct are |key_num_bytes| bytes of key data,
+ * followed by a NUL byte, then |value_num_bytes| bytes of value data,
+ * followed by a NUL byte and then enough padding to make the combined
+ * size a multiple of 8.
+ */
+typedef struct AvbPropertyDescriptor {
+  AvbDescriptor parent_descriptor;
+  uint64_t key_num_bytes;
+  uint64_t value_num_bytes;
+} AVB_ATTR_PACKED AvbPropertyDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_property_descriptor_validate_and_byteswap(
+    const AvbPropertyDescriptor* src,
+    AvbPropertyDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Convenience function for looking up the value for a property with
+ * name |key| in a vbmeta image. If |key_size| is 0, |key| must be
+ * NUL-terminated.
+ *
+ * The |image_data| parameter must be a pointer to a vbmeta image of
+ * size |image_size|.
+ *
+ * This function returns a pointer to the value inside the passed-in
+ * image or NULL if not found. Note that the value is always
+ * guaranteed to be followed by a NUL byte.
+ *
+ * If the value was found and |out_value_size| is not NULL, the size
+ * of the value is returned there.
+ *
+ * This function is O(n) in number of descriptors so if you need to
+ * look up a lot of values, you may want to build a more efficient
+ * lookup-table by manually walking all descriptors using
+ * avb_descriptor_foreach().
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a
+ * known good public key.
+ */
+const char* avb_property_lookup(const uint8_t* image_data,
+                                size_t image_size,
+                                const char* key,
+                                size_t key_size,
+                                size_t* out_value_size)
+    AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Like avb_property_lookup() but parses the intial portions of the
+ * value as an unsigned 64-bit integer. Both decimal and hexadecimal
+ * representations (e.g. "0x2a") are supported. Returns false on
+ * failure and true on success. On success, the parsed value is
+ * returned in |out_value|.
+ */
+bool avb_property_lookup_uint64(const uint8_t* image_data,
+                                size_t image_size,
+                                const char* key,
+                                size_t key_size,
+                                uint64_t* out_value)
+    AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_PROPERTY_DESCRIPTOR_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_rsa.c b/platform/msm_shared/avb/libavb/avb_rsa.c
new file mode 100644
index 0000000..f4cb322
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_rsa.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Implementation of RSA signature verification which uses a pre-processed
+ * key for computation. The code extends libmincrypt RSA verification code to
+ * support multiple RSA key lengths and hash digest algorithms.
+ */
+
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+
+typedef struct IAvbKey {
+  unsigned int len; /* Length of n[] in number of uint32_t */
+  uint32_t n0inv;   /* -1 / n[0] mod 2^32 */
+  uint32_t* n;      /* modulus as array (host-byte order) */
+  uint32_t* rr;     /* R^2 as array (host-byte order) */
+} IAvbKey;
+
+static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
+  AvbRSAPublicKeyHeader h;
+  IAvbKey* key = NULL;
+  size_t expected_length;
+  unsigned int i;
+  const uint8_t* n;
+  const uint8_t* rr;
+
+  if (!avb_rsa_public_key_header_validate_and_byteswap(
+          (const AvbRSAPublicKeyHeader*)data, &h)) {
+    avb_error("Invalid key.\n");
+    goto fail;
+  }
+
+  if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
+        h.key_num_bits == 8192)) {
+    avb_error("Unexpected key length.\n");
+    goto fail;
+  }
+
+  expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
+  if (length != expected_length) {
+    avb_error("Key does not match expected length.\n");
+    goto fail;
+  }
+
+  n = data + sizeof(AvbRSAPublicKeyHeader);
+  rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;
+
+  /* Store n and rr following the key header so we only have to do one
+   * allocation.
+   */
+  key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
+  if (key == NULL) {
+    goto fail;
+  }
+
+  key->len = h.key_num_bits / 32;
+  key->n0inv = h.n0inv;
+  key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
+  key->rr = key->n + key->len;
+
+  /* Crypto-code below (modpowF4() and friends) expects the key in
+   * little-endian format (rather than the format we're storing the
+   * key in), so convert it.
+   */
+  for (i = 0; i < key->len; i++) {
+    key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
+    key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
+  }
+  return key;
+
+fail:
+  if (key != NULL) {
+    avb_free(key);
+  }
+  return NULL;
+}
+
+static void iavb_free_parsed_key(IAvbKey* key) {
+  avb_free(key);
+}
+
+/* a[] -= mod */
+static void subM(const IAvbKey* key, uint32_t* a) {
+  int64_t A = 0;
+  uint32_t i;
+  for (i = 0; i < key->len; ++i) {
+    A += (uint64_t)a[i] - key->n[i];
+    a[i] = (uint32_t)A;
+    A >>= 32;
+  }
+}
+
+/* return a[] >= mod */
+static int geM(const IAvbKey* key, uint32_t* a) {
+  uint32_t i;
+  for (i = key->len; i;) {
+    --i;
+    if (a[i] < key->n[i]) {
+      return 0;
+    }
+    if (a[i] > key->n[i]) {
+      return 1;
+    }
+  }
+  return 1; /* equal */
+}
+
+/* montgomery c[] += a * b[] / R % mod */
+static void montMulAdd(const IAvbKey* key,
+                       uint32_t* c,
+                       const uint32_t a,
+                       const uint32_t* b) {
+  uint64_t A = (uint64_t)a * b[0] + c[0];
+  uint32_t d0 = (uint32_t)A * key->n0inv;
+  uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
+  uint32_t i;
+
+  for (i = 1; i < key->len; ++i) {
+    A = (A >> 32) + (uint64_t)a * b[i] + c[i];
+    B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
+    c[i - 1] = (uint32_t)B;
+  }
+
+  A = (A >> 32) + (B >> 32);
+
+  c[i - 1] = (uint32_t)A;
+
+  if (A >> 32) {
+    subM(key, c);
+  }
+}
+
+/* montgomery c[] = a[] * b[] / R % mod */
+static void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
+  uint32_t i;
+  for (i = 0; i < key->len; ++i) {
+    c[i] = 0;
+  }
+  for (i = 0; i < key->len; ++i) {
+    montMulAdd(key, c, a[i], b);
+  }
+}
+
+/* In-place public exponentiation. (65537}
+ * Input and output big-endian byte array in inout.
+ */
+static void modpowF4(const IAvbKey* key, uint8_t* inout) {
+  uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+  uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+  uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+  if (a == NULL || aR == NULL || aaR == NULL) {
+    goto out;
+  }
+
+  uint32_t* aaa = aaR; /* Re-use location. */
+  int i;
+
+  /* Convert from big endian byte array to little endian word array. */
+  for (i = 0; i < (int)key->len; ++i) {
+    uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
+                   (inout[((key->len - 1 - i) * 4) + 1] << 16) |
+                   (inout[((key->len - 1 - i) * 4) + 2] << 8) |
+                   (inout[((key->len - 1 - i) * 4) + 3] << 0);
+    a[i] = tmp;
+  }
+
+  montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M   */
+  for (i = 0; i < 16; i += 2) {
+    montMul(key, aaR, aR, aR);  /* aaR = aR * aR / R mod M */
+    montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
+  }
+  montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
+
+  /* Make sure aaa < mod; aaa is at most 1x mod too large. */
+  if (geM(key, aaa)) {
+    subM(key, aaa);
+  }
+
+  /* Convert to bigendian byte array */
+  for (i = (int)key->len - 1; i >= 0; --i) {
+    uint32_t tmp = aaa[i];
+    *inout++ = (uint8_t)(tmp >> 24);
+    *inout++ = (uint8_t)(tmp >> 16);
+    *inout++ = (uint8_t)(tmp >> 8);
+    *inout++ = (uint8_t)(tmp >> 0);
+  }
+
+out:
+  if (a != NULL) {
+    avb_free(a);
+  }
+  if (aR != NULL) {
+    avb_free(aR);
+  }
+  if (aaR != NULL) {
+    avb_free(aaR);
+  }
+}
+
+/* Verify a RSA PKCS1.5 signature against an expected hash.
+ * Returns false on failure, true on success.
+ */
+bool avb_rsa_verify(const uint8_t* key,
+                    size_t key_num_bytes,
+                    const uint8_t* sig,
+                    size_t sig_num_bytes,
+                    const uint8_t* hash,
+                    size_t hash_num_bytes,
+                    const uint8_t* padding,
+                    size_t padding_num_bytes) {
+  uint8_t* buf = NULL;
+  IAvbKey* parsed_key = NULL;
+  bool success = false;
+
+  if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
+    avb_error("Invalid input.\n");
+    goto out;
+  }
+
+  parsed_key = iavb_parse_key_data(key, key_num_bytes);
+  if (parsed_key == NULL) {
+    avb_error("Error parsing key.\n");
+    goto out;
+  }
+
+  if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
+    avb_error("Signature length does not match key length.\n");
+    goto out;
+  }
+
+  if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
+    avb_error("Padding length does not match hash and signature lengths.\n");
+    goto out;
+  }
+
+  buf = (uint8_t*)avb_malloc(sig_num_bytes);
+  if (buf == NULL) {
+    avb_error("Error allocating memory.\n");
+    goto out;
+  }
+  avb_memcpy(buf, sig, sig_num_bytes);
+
+  modpowF4(parsed_key, buf);
+
+  /* Check padding bytes.
+   *
+   * Even though there are probably no timing issues here, we use
+   * avb_safe_memcmp() just to be on the safe side.
+   */
+  if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
+    avb_error("Padding check failed.\n");
+    goto out;
+  }
+
+  /* Check hash. */
+  if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
+    avb_error("Hash check failed.\n");
+    goto out;
+  }
+
+  success = true;
+
+out:
+  if (parsed_key != NULL) {
+    iavb_free_parsed_key(parsed_key);
+  }
+  if (buf != NULL) {
+    avb_free(buf);
+  }
+  return success;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_rsa.h b/platform/msm_shared/avb/libavb/avb_rsa.h
new file mode 100644
index 0000000..c2dcf47
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_rsa.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_rsa.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_RSA_H_
+#define AVB_RSA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_sysdeps.h"
+
+/* Using the key given by |key|, verify a RSA signature |sig| of
+ * length |sig_num_bytes| against an expected |hash| of length
+ * |hash_num_bytes|. The padding to expect must be passed in using
+ * |padding| of length |padding_num_bytes|.
+ *
+ * The data in |key| must match the format defined in
+ * |AvbRSAPublicKeyHeader|, including the two large numbers
+ * following. The |key_num_bytes| must be the size of the entire
+ * serialized key.
+ *
+ * Returns false if verification fails, true otherwise.
+ */
+bool avb_rsa_verify(const uint8_t* key,
+                    size_t key_num_bytes,
+                    const uint8_t* sig,
+                    size_t sig_num_bytes,
+                    const uint8_t* hash,
+                    size_t hash_num_bytes,
+                    const uint8_t* padding,
+                    size_t padding_num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_RSA_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_sha.h b/platform/msm_shared/avb/libavb/avb_sha.h
new file mode 100644
index 0000000..c5a6a4c
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_sha.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_sha.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_SHA_H_
+#define AVB_SHA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_sysdeps.h"
+
+/* Block size in bytes of a SHA-256 digest. */
+#define AVB_SHA256_BLOCK_SIZE 64
+
+
+/* Block size in bytes of a SHA-512 digest. */
+#define AVB_SHA512_BLOCK_SIZE 128
+
+/* Data structure used for SHA-256. */
+typedef struct {
+  uint32_t h[8];
+  uint32_t tot_len;
+  uint32_t len;
+  uint8_t block[2 * AVB_SHA256_BLOCK_SIZE];
+  uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */
+} AvbSHA256Ctx;
+
+/* Data structure used for SHA-512. */
+typedef struct {
+  uint64_t h[8];
+  uint32_t tot_len;
+  uint32_t len;
+  uint8_t block[2 * AVB_SHA512_BLOCK_SIZE];
+  uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */
+} AvbSHA512Ctx;
+
+/* Initializes the SHA-256 context. */
+void avb_sha256_init(AvbSHA256Ctx* ctx);
+
+/* Updates the SHA-256 context with |len| bytes from |data|. */
+void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len);
+
+/* Returns the SHA-256 digest. */
+uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Initializes the SHA-512 context. */
+void avb_sha512_init(AvbSHA512Ctx* ctx);
+
+/* Updates the SHA-512 context with |len| bytes from |data|. */
+void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len);
+
+/* Returns the SHA-512 digest. */
+uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SHA_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_sha256.c b/platform/msm_shared/avb/libavb/avb_sha256.c
new file mode 100644
index 0000000..cdd143a
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_sha256.c
@@ -0,0 +1,390 @@
+/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
+ * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
+ */
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date:  04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "avb_sha.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define UNPACK32(x, str)                 \
+  {                                      \
+    *((str) + 3) = (uint8_t)((x));       \
+    *((str) + 2) = (uint8_t)((x) >> 8);  \
+    *((str) + 1) = (uint8_t)((x) >> 16); \
+    *((str) + 0) = (uint8_t)((x) >> 24); \
+  }
+
+#define PACK32(str, x)                                                    \
+  {                                                                       \
+    *(x) = ((uint32_t) * ((str) + 3)) | ((uint32_t) * ((str) + 2) << 8) | \
+           ((uint32_t) * ((str) + 1) << 16) |                             \
+           ((uint32_t) * ((str) + 0) << 24);                              \
+  }
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+  { w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16]; }
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j)                               \
+  {                                                                         \
+    t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + \
+         w[j];                                                              \
+    t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);                       \
+    wv[d] += t1;                                                            \
+    wv[h] = t1 + t2;                                                        \
+  }
+
+static const uint32_t sha256_h0[8] = {0x6a09e667,
+                                      0xbb67ae85,
+                                      0x3c6ef372,
+                                      0xa54ff53a,
+                                      0x510e527f,
+                                      0x9b05688c,
+                                      0x1f83d9ab,
+                                      0x5be0cd19};
+
+static const uint32_t sha256_k[64] = {
+    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+    0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+    0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+    0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+    0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+    0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
+
+/* SHA-256 implementation */
+void avb_sha256_init(AvbSHA256Ctx* ctx) {
+#ifndef UNROLL_LOOPS
+  int i;
+  for (i = 0; i < 8; i++) {
+    ctx->h[i] = sha256_h0[i];
+  }
+#else
+  ctx->h[0] = sha256_h0[0];
+  ctx->h[1] = sha256_h0[1];
+  ctx->h[2] = sha256_h0[2];
+  ctx->h[3] = sha256_h0[3];
+  ctx->h[4] = sha256_h0[4];
+  ctx->h[5] = sha256_h0[5];
+  ctx->h[6] = sha256_h0[6];
+  ctx->h[7] = sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+  ctx->len = 0;
+  ctx->tot_len = 0;
+}
+
+static void SHA256_transform(AvbSHA256Ctx* ctx,
+                             const uint8_t* message,
+                             unsigned int block_nb) {
+  uint32_t w[64];
+  uint32_t wv[8];
+  uint32_t t1, t2;
+  const unsigned char* sub_block;
+  int i;
+
+#ifndef UNROLL_LOOPS
+  int j;
+#endif
+
+  for (i = 0; i < (int)block_nb; i++) {
+    sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+    for (j = 0; j < 16; j++) {
+      PACK32(&sub_block[j << 2], &w[j]);
+    }
+
+    for (j = 16; j < 64; j++) {
+      SHA256_SCR(j);
+    }
+
+    for (j = 0; j < 8; j++) {
+      wv[j] = ctx->h[j];
+    }
+
+    for (j = 0; j < 64; j++) {
+      t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] +
+           w[j];
+      t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+      wv[7] = wv[6];
+      wv[6] = wv[5];
+      wv[5] = wv[4];
+      wv[4] = wv[3] + t1;
+      wv[3] = wv[2];
+      wv[2] = wv[1];
+      wv[1] = wv[0];
+      wv[0] = t1 + t2;
+    }
+
+    for (j = 0; j < 8; j++) {
+      ctx->h[j] += wv[j];
+    }
+#else
+    PACK32(&sub_block[0], &w[0]);
+    PACK32(&sub_block[4], &w[1]);
+    PACK32(&sub_block[8], &w[2]);
+    PACK32(&sub_block[12], &w[3]);
+    PACK32(&sub_block[16], &w[4]);
+    PACK32(&sub_block[20], &w[5]);
+    PACK32(&sub_block[24], &w[6]);
+    PACK32(&sub_block[28], &w[7]);
+    PACK32(&sub_block[32], &w[8]);
+    PACK32(&sub_block[36], &w[9]);
+    PACK32(&sub_block[40], &w[10]);
+    PACK32(&sub_block[44], &w[11]);
+    PACK32(&sub_block[48], &w[12]);
+    PACK32(&sub_block[52], &w[13]);
+    PACK32(&sub_block[56], &w[14]);
+    PACK32(&sub_block[60], &w[15]);
+
+    SHA256_SCR(16);
+    SHA256_SCR(17);
+    SHA256_SCR(18);
+    SHA256_SCR(19);
+    SHA256_SCR(20);
+    SHA256_SCR(21);
+    SHA256_SCR(22);
+    SHA256_SCR(23);
+    SHA256_SCR(24);
+    SHA256_SCR(25);
+    SHA256_SCR(26);
+    SHA256_SCR(27);
+    SHA256_SCR(28);
+    SHA256_SCR(29);
+    SHA256_SCR(30);
+    SHA256_SCR(31);
+    SHA256_SCR(32);
+    SHA256_SCR(33);
+    SHA256_SCR(34);
+    SHA256_SCR(35);
+    SHA256_SCR(36);
+    SHA256_SCR(37);
+    SHA256_SCR(38);
+    SHA256_SCR(39);
+    SHA256_SCR(40);
+    SHA256_SCR(41);
+    SHA256_SCR(42);
+    SHA256_SCR(43);
+    SHA256_SCR(44);
+    SHA256_SCR(45);
+    SHA256_SCR(46);
+    SHA256_SCR(47);
+    SHA256_SCR(48);
+    SHA256_SCR(49);
+    SHA256_SCR(50);
+    SHA256_SCR(51);
+    SHA256_SCR(52);
+    SHA256_SCR(53);
+    SHA256_SCR(54);
+    SHA256_SCR(55);
+    SHA256_SCR(56);
+    SHA256_SCR(57);
+    SHA256_SCR(58);
+    SHA256_SCR(59);
+    SHA256_SCR(60);
+    SHA256_SCR(61);
+    SHA256_SCR(62);
+    SHA256_SCR(63);
+
+    wv[0] = ctx->h[0];
+    wv[1] = ctx->h[1];
+    wv[2] = ctx->h[2];
+    wv[3] = ctx->h[3];
+    wv[4] = ctx->h[4];
+    wv[5] = ctx->h[5];
+    wv[6] = ctx->h[6];
+    wv[7] = ctx->h[7];
+
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
+    SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
+    SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
+    SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
+    SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
+    SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
+    SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61);
+    SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62);
+    SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63);
+
+    ctx->h[0] += wv[0];
+    ctx->h[1] += wv[1];
+    ctx->h[2] += wv[2];
+    ctx->h[3] += wv[3];
+    ctx->h[4] += wv[4];
+    ctx->h[5] += wv[5];
+    ctx->h[6] += wv[6];
+    ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+  }
+}
+
+void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len) {
+  unsigned int block_nb;
+  unsigned int new_len, rem_len, tmp_len;
+  const uint8_t* shifted_data;
+
+  tmp_len = AVB_SHA256_BLOCK_SIZE - ctx->len;
+  rem_len = len < tmp_len ? len : tmp_len;
+
+  avb_memcpy(&ctx->block[ctx->len], data, rem_len);
+
+  if (ctx->len + len < AVB_SHA256_BLOCK_SIZE) {
+    ctx->len += len;
+    return;
+  }
+
+  new_len = len - rem_len;
+  block_nb = new_len / AVB_SHA256_BLOCK_SIZE;
+
+  shifted_data = data + rem_len;
+
+  SHA256_transform(ctx, ctx->block, 1);
+  SHA256_transform(ctx, shifted_data, block_nb);
+
+  rem_len = new_len % AVB_SHA256_BLOCK_SIZE;
+
+  avb_memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len);
+
+  ctx->len = rem_len;
+  ctx->tot_len += (block_nb + 1) << 6;
+}
+
+uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) {
+  unsigned int block_nb;
+  unsigned int pm_len;
+  unsigned int len_b;
+#ifndef UNROLL_LOOPS
+  int i;
+#endif
+
+  block_nb =
+      (1 + ((AVB_SHA256_BLOCK_SIZE - 9) < (ctx->len % AVB_SHA256_BLOCK_SIZE)));
+
+  len_b = (ctx->tot_len + ctx->len) << 3;
+  pm_len = block_nb << 6;
+
+  avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+  ctx->block[ctx->len] = 0x80;
+  UNPACK32(len_b, ctx->block + pm_len - 4);
+
+  SHA256_transform(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+  for (i = 0; i < 8; i++) {
+    UNPACK32(ctx->h[i], &ctx->buf[i << 2]);
+  }
+#else
+  UNPACK32(ctx->h[0], &ctx->buf[0]);
+  UNPACK32(ctx->h[1], &ctx->buf[4]);
+  UNPACK32(ctx->h[2], &ctx->buf[8]);
+  UNPACK32(ctx->h[3], &ctx->buf[12]);
+  UNPACK32(ctx->h[4], &ctx->buf[16]);
+  UNPACK32(ctx->h[5], &ctx->buf[20]);
+  UNPACK32(ctx->h[6], &ctx->buf[24]);
+  UNPACK32(ctx->h[7], &ctx->buf[28]);
+#endif /* !UNROLL_LOOPS */
+
+  return ctx->buf;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_sha512.c b/platform/msm_shared/avb/libavb/avb_sha512.c
new file mode 100644
index 0000000..8df6319
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_sha512.c
@@ -0,0 +1,388 @@
+/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
+ * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
+ */
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date:  04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "avb_sha.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
+#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
+
+#define UNPACK32(x, str)                 \
+  {                                      \
+    *((str) + 3) = (uint8_t)((x));       \
+    *((str) + 2) = (uint8_t)((x) >> 8);  \
+    *((str) + 1) = (uint8_t)((x) >> 16); \
+    *((str) + 0) = (uint8_t)((x) >> 24); \
+  }
+
+#define UNPACK64(x, str)                         \
+  {                                              \
+    *((str) + 7) = (uint8_t)x;                   \
+    *((str) + 6) = (uint8_t)((uint64_t)x >> 8);  \
+    *((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
+    *((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
+    *((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
+    *((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
+    *((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
+    *((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
+  }
+
+#define PACK64(str, x)                                                        \
+  {                                                                           \
+    *(x) =                                                                    \
+        ((uint64_t) * ((str) + 7)) | ((uint64_t) * ((str) + 6) << 8) |        \
+        ((uint64_t) * ((str) + 5) << 16) | ((uint64_t) * ((str) + 4) << 24) | \
+        ((uint64_t) * ((str) + 3) << 32) | ((uint64_t) * ((str) + 2) << 40) | \
+        ((uint64_t) * ((str) + 1) << 48) | ((uint64_t) * ((str) + 0) << 56);  \
+  }
+
+/* Macros used for loops unrolling */
+
+#define SHA512_SCR(i) \
+  { w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16]; }
+
+#define SHA512_EXP(a, b, c, d, e, f, g, h, j)                               \
+  {                                                                         \
+    t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha512_k[j] + \
+         w[j];                                                              \
+    t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);                       \
+    wv[d] += t1;                                                            \
+    wv[h] = t1 + t2;                                                        \
+  }
+
+static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL,
+                                      0xbb67ae8584caa73bULL,
+                                      0x3c6ef372fe94f82bULL,
+                                      0xa54ff53a5f1d36f1ULL,
+                                      0x510e527fade682d1ULL,
+                                      0x9b05688c2b3e6c1fULL,
+                                      0x1f83d9abfb41bd6bULL,
+                                      0x5be0cd19137e2179ULL};
+
+static const uint64_t sha512_k[80] = {
+    0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+    0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+    0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+    0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+    0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+    0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+    0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+    0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+    0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+    0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+    0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+    0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+    0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+    0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+    0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+    0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+    0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+    0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+    0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+    0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+    0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+    0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+    0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+    0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+    0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+    0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+    0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
+
+/* SHA-512 implementation */
+
+void avb_sha512_init(AvbSHA512Ctx* ctx) {
+#ifdef UNROLL_LOOPS_SHA512
+  ctx->h[0] = sha512_h0[0];
+  ctx->h[1] = sha512_h0[1];
+  ctx->h[2] = sha512_h0[2];
+  ctx->h[3] = sha512_h0[3];
+  ctx->h[4] = sha512_h0[4];
+  ctx->h[5] = sha512_h0[5];
+  ctx->h[6] = sha512_h0[6];
+  ctx->h[7] = sha512_h0[7];
+#else
+  int i;
+
+  for (i = 0; i < 8; i++)
+    ctx->h[i] = sha512_h0[i];
+#endif /* UNROLL_LOOPS_SHA512 */
+
+  ctx->len = 0;
+  ctx->tot_len = 0;
+}
+
+static void SHA512_transform(AvbSHA512Ctx* ctx,
+                             const uint8_t* message,
+                             unsigned int block_nb) {
+  uint64_t w[80];
+  uint64_t wv[8];
+  uint64_t t1, t2;
+  const uint8_t* sub_block;
+  int i, j;
+
+  for (i = 0; i < (int)block_nb; i++) {
+    sub_block = message + (i << 7);
+
+#ifdef UNROLL_LOOPS_SHA512
+    PACK64(&sub_block[0], &w[0]);
+    PACK64(&sub_block[8], &w[1]);
+    PACK64(&sub_block[16], &w[2]);
+    PACK64(&sub_block[24], &w[3]);
+    PACK64(&sub_block[32], &w[4]);
+    PACK64(&sub_block[40], &w[5]);
+    PACK64(&sub_block[48], &w[6]);
+    PACK64(&sub_block[56], &w[7]);
+    PACK64(&sub_block[64], &w[8]);
+    PACK64(&sub_block[72], &w[9]);
+    PACK64(&sub_block[80], &w[10]);
+    PACK64(&sub_block[88], &w[11]);
+    PACK64(&sub_block[96], &w[12]);
+    PACK64(&sub_block[104], &w[13]);
+    PACK64(&sub_block[112], &w[14]);
+    PACK64(&sub_block[120], &w[15]);
+
+    SHA512_SCR(16);
+    SHA512_SCR(17);
+    SHA512_SCR(18);
+    SHA512_SCR(19);
+    SHA512_SCR(20);
+    SHA512_SCR(21);
+    SHA512_SCR(22);
+    SHA512_SCR(23);
+    SHA512_SCR(24);
+    SHA512_SCR(25);
+    SHA512_SCR(26);
+    SHA512_SCR(27);
+    SHA512_SCR(28);
+    SHA512_SCR(29);
+    SHA512_SCR(30);
+    SHA512_SCR(31);
+    SHA512_SCR(32);
+    SHA512_SCR(33);
+    SHA512_SCR(34);
+    SHA512_SCR(35);
+    SHA512_SCR(36);
+    SHA512_SCR(37);
+    SHA512_SCR(38);
+    SHA512_SCR(39);
+    SHA512_SCR(40);
+    SHA512_SCR(41);
+    SHA512_SCR(42);
+    SHA512_SCR(43);
+    SHA512_SCR(44);
+    SHA512_SCR(45);
+    SHA512_SCR(46);
+    SHA512_SCR(47);
+    SHA512_SCR(48);
+    SHA512_SCR(49);
+    SHA512_SCR(50);
+    SHA512_SCR(51);
+    SHA512_SCR(52);
+    SHA512_SCR(53);
+    SHA512_SCR(54);
+    SHA512_SCR(55);
+    SHA512_SCR(56);
+    SHA512_SCR(57);
+    SHA512_SCR(58);
+    SHA512_SCR(59);
+    SHA512_SCR(60);
+    SHA512_SCR(61);
+    SHA512_SCR(62);
+    SHA512_SCR(63);
+    SHA512_SCR(64);
+    SHA512_SCR(65);
+    SHA512_SCR(66);
+    SHA512_SCR(67);
+    SHA512_SCR(68);
+    SHA512_SCR(69);
+    SHA512_SCR(70);
+    SHA512_SCR(71);
+    SHA512_SCR(72);
+    SHA512_SCR(73);
+    SHA512_SCR(74);
+    SHA512_SCR(75);
+    SHA512_SCR(76);
+    SHA512_SCR(77);
+    SHA512_SCR(78);
+    SHA512_SCR(79);
+
+    wv[0] = ctx->h[0];
+    wv[1] = ctx->h[1];
+    wv[2] = ctx->h[2];
+    wv[3] = ctx->h[3];
+    wv[4] = ctx->h[4];
+    wv[5] = ctx->h[5];
+    wv[6] = ctx->h[6];
+    wv[7] = ctx->h[7];
+
+    j = 0;
+
+    do {
+      SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
+      j++;
+      SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
+      j++;
+      SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
+      j++;
+      SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
+      j++;
+      SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
+      j++;
+      SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
+      j++;
+      SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
+      j++;
+      SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
+      j++;
+    } while (j < 80);
+
+    ctx->h[0] += wv[0];
+    ctx->h[1] += wv[1];
+    ctx->h[2] += wv[2];
+    ctx->h[3] += wv[3];
+    ctx->h[4] += wv[4];
+    ctx->h[5] += wv[5];
+    ctx->h[6] += wv[6];
+    ctx->h[7] += wv[7];
+#else
+    for (j = 0; j < 16; j++) {
+      PACK64(&sub_block[j << 3], &w[j]);
+    }
+
+    for (j = 16; j < 80; j++) {
+      SHA512_SCR(j);
+    }
+
+    for (j = 0; j < 8; j++) {
+      wv[j] = ctx->h[j];
+    }
+
+    for (j = 0; j < 80; j++) {
+      t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] +
+           w[j];
+      t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+      wv[7] = wv[6];
+      wv[6] = wv[5];
+      wv[5] = wv[4];
+      wv[4] = wv[3] + t1;
+      wv[3] = wv[2];
+      wv[2] = wv[1];
+      wv[1] = wv[0];
+      wv[0] = t1 + t2;
+    }
+
+    for (j = 0; j < 8; j++)
+      ctx->h[j] += wv[j];
+#endif /* UNROLL_LOOPS_SHA512 */
+  }
+}
+
+void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len) {
+  unsigned int block_nb;
+  unsigned int new_len, rem_len, tmp_len;
+  const uint8_t* shifted_data;
+
+  tmp_len = AVB_SHA512_BLOCK_SIZE - ctx->len;
+  rem_len = len < tmp_len ? len : tmp_len;
+
+  avb_memcpy(&ctx->block[ctx->len], data, rem_len);
+
+  if (ctx->len + len < AVB_SHA512_BLOCK_SIZE) {
+    ctx->len += len;
+    return;
+  }
+
+  new_len = len - rem_len;
+  block_nb = new_len / AVB_SHA512_BLOCK_SIZE;
+
+  shifted_data = data + rem_len;
+
+  SHA512_transform(ctx, ctx->block, 1);
+  SHA512_transform(ctx, shifted_data, block_nb);
+
+  rem_len = new_len % AVB_SHA512_BLOCK_SIZE;
+
+  avb_memcpy(ctx->block, &shifted_data[block_nb << 7], rem_len);
+
+  ctx->len = rem_len;
+  ctx->tot_len += (block_nb + 1) << 7;
+}
+
+uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) {
+  unsigned int block_nb;
+  unsigned int pm_len;
+  unsigned int len_b;
+
+#ifndef UNROLL_LOOPS_SHA512
+  int i;
+#endif
+
+  block_nb =
+      1 + ((AVB_SHA512_BLOCK_SIZE - 17) < (ctx->len % AVB_SHA512_BLOCK_SIZE));
+
+  len_b = (ctx->tot_len + ctx->len) << 3;
+  pm_len = block_nb << 7;
+
+  avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+  ctx->block[ctx->len] = 0x80;
+  UNPACK32(len_b, ctx->block + pm_len - 4);
+
+  SHA512_transform(ctx, ctx->block, block_nb);
+
+#ifdef UNROLL_LOOPS_SHA512
+  UNPACK64(ctx->h[0], &ctx->buf[0]);
+  UNPACK64(ctx->h[1], &ctx->buf[8]);
+  UNPACK64(ctx->h[2], &ctx->buf[16]);
+  UNPACK64(ctx->h[3], &ctx->buf[24]);
+  UNPACK64(ctx->h[4], &ctx->buf[32]);
+  UNPACK64(ctx->h[5], &ctx->buf[40]);
+  UNPACK64(ctx->h[6], &ctx->buf[48]);
+  UNPACK64(ctx->h[7], &ctx->buf[56]);
+#else
+  for (i = 0; i < 8; i++)
+    UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
+#endif /* UNROLL_LOOPS_SHA512 */
+
+  return ctx->buf;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_slot_verify.c b/platform/msm_shared/avb/libavb/avb_slot_verify.c
new file mode 100644
index 0000000..0594fab
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_slot_verify.c
@@ -0,0 +1,1487 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_slot_verify.h"
+#include "avb_chain_partition_descriptor.h"
+#include "avb_footer.h"
+#include "avb_hash_descriptor.h"
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+#include "avb_version.h"
+
+/* Maximum allow length (in bytes) of a partition name, including
+ * ab_suffix.
+ */
+#define PART_NAME_MAX_SIZE 32
+
+/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
+#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
+
+/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
+#define MAX_NUMBER_OF_VBMETA_IMAGES 32
+
+/* Maximum size of a vbmeta image - 64 KiB. */
+#define VBMETA_MAX_SIZE (64 * 1024)
+
+/* Helper function to see if we should continue with verification in
+ * allow_verification_error=true mode if something goes wrong. See the
+ * comments for the avb_slot_verify() function for more information.
+ */
+static inline bool result_should_continue(AvbSlotVerifyResult result) {
+  switch (result) {
+    case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+    case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+    case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+      return false;
+
+    case AVB_SLOT_VERIFY_RESULT_OK:
+    case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+    case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+    case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+      return true;
+  }
+
+  return false;
+}
+
+static AvbSlotVerifyResult load_and_verify_hash_partition(
+    AvbOps* ops,
+    const char* const* requested_partitions,
+    const char* ab_suffix,
+    bool allow_verification_error,
+    const AvbDescriptor* descriptor,
+    AvbSlotVerifyData* slot_data) {
+  AvbHashDescriptor hash_desc;
+  const uint8_t* desc_partition_name = NULL;
+  const uint8_t* desc_salt;
+  const uint8_t* desc_digest;
+  char part_name[PART_NAME_MAX_SIZE];
+  AvbSlotVerifyResult ret;
+  AvbIOResult io_ret;
+  uint8_t* image_buf = NULL;
+  size_t part_num_read;
+  uint8_t* digest = NULL;
+  size_t digest_len;
+  const char* found = NULL;
+  uint64_t image_size;
+
+  if (!avb_hash_descriptor_validate_and_byteswap(
+          (const AvbHashDescriptor*)descriptor, &hash_desc)) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+  desc_partition_name =
+      ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
+  desc_salt = desc_partition_name + hash_desc.partition_name_len;
+  desc_digest = desc_salt + hash_desc.salt_len;
+
+  if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
+    avb_error("Partition name is not valid UTF-8.\n");
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+
+  /* Don't bother loading or validating unless the partition was
+   * requested in the first place.
+   */
+  found = avb_strv_find_str(requested_partitions,
+                            (const char*)desc_partition_name,
+                            hash_desc.partition_name_len);
+  if (found == NULL) {
+    ret = AVB_SLOT_VERIFY_RESULT_OK;
+    goto out;
+  }
+
+  if (!avb_str_concat(part_name,
+                      sizeof part_name,
+                      (const char*)desc_partition_name,
+                      hash_desc.partition_name_len,
+                      ab_suffix,
+                      avb_strlen(ab_suffix))) {
+    avb_error("Partition name and suffix does not fit.\n");
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+
+  /* If we're allowing verification errors then hash_desc.image_size
+   * may no longer match what's in the partition... so in this case
+   * just load the entire partition.
+   *
+   * For example, this can happen if a developer does 'fastboot flash
+   * boot /path/to/new/and/bigger/boot.img'. We want this to work
+   * since it's such a common workflow.
+   */
+  image_size = hash_desc.image_size;
+  if (allow_verification_error) {
+    if (ops->get_size_of_partition == NULL) {
+      avb_errorv(part_name,
+                 ": The get_size_of_partition() operation is "
+                 "not implemented so we may not load the entire partition. "
+                 "Please implement.",
+                 NULL);
+    } else {
+      io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
+      if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+        goto out;
+      } else if (io_ret != AVB_IO_RESULT_OK) {
+        avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+        goto out;
+      }
+      avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+    }
+  }
+
+  image_buf = (uint8_t *)target_get_scratch_address()+0x02000000;
+  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;
+  } else if (io_ret != AVB_IO_RESULT_OK) {
+    avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+    goto out;
+  }
+  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;
+  }
+
+  if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
+    uint32_t complete_len = hash_desc.salt_len + hash_desc.image_size;
+    uint8_t *complete_buf = (uint8_t *)target_get_scratch_address()+0x08000000;
+    digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
+    avb_memcpy(complete_buf, desc_salt, hash_desc.salt_len);
+    avb_memcpy(complete_buf + hash_desc.salt_len, image_buf, hash_desc.image_size);
+    hash_find(complete_buf, complete_len, digest, CRYPTO_AUTH_ALG_SHA256);
+    digest_len = AVB_SHA256_DIGEST_SIZE;
+  } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
+    AvbSHA512Ctx sha512_ctx;
+    uint8_t *dig;
+    digest = avb_malloc(AVB_SHA512_DIGEST_SIZE);
+    avb_sha512_init(&sha512_ctx);
+    avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
+    avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
+    dig = avb_sha512_final(&sha512_ctx);
+    digest_len = AVB_SHA512_DIGEST_SIZE;
+    avb_memcpy(digest, dig, AVB_SHA512_DIGEST_SIZE);
+  } else {
+    avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+
+  if (digest_len != hash_desc.digest_len) {
+    avb_errorv(
+        part_name, ": Digest in descriptor not of expected size.\n", NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+
+  if (avb_safe_memcmp(digest, desc_digest, digest_len) != 0) {
+    avb_errorv(part_name,
+               ": Hash of data does not match digest in descriptor.\n",
+               NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+    goto out;
+  }
+
+  ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+  if (digest)
+    avb_free(digest);
+  /* If it worked and something was loaded, copy to slot_data. */
+  if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
+      image_buf != NULL) {
+    AvbPartitionData* loaded_partition;
+    if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
+      avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto fail;
+    }
+    loaded_partition =
+        &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
+    loaded_partition->partition_name = avb_strdup(found);
+    loaded_partition->data_size = image_size;
+    loaded_partition->data = image_buf;
+    image_buf = NULL;
+  }
+
+fail:
+  //remove avb_free() as memory allocated from scratch region
+  return ret;
+}
+
+static AvbSlotVerifyResult load_requested_partitions(
+    AvbOps* ops,
+    const char* const* requested_partitions,
+    const char* ab_suffix,
+    AvbSlotVerifyData* slot_data) {
+  AvbSlotVerifyResult ret;
+  uint8_t* image_buf = NULL;
+  size_t n;
+
+  if (ops->get_size_of_partition == NULL) {
+    avb_error("get_size_of_partition() not implemented.\n");
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+    goto out;
+  }
+
+  for (n = 0; requested_partitions[n] != NULL; n++) {
+    char part_name[PART_NAME_MAX_SIZE];
+    AvbIOResult io_ret;
+    uint64_t image_size;
+    size_t part_num_read;
+    AvbPartitionData* loaded_partition;
+
+    if (!avb_str_concat(part_name,
+                        sizeof part_name,
+                        requested_partitions[n],
+                        avb_strlen(requested_partitions[n]),
+                        ab_suffix,
+                        avb_strlen(ab_suffix))) {
+      avb_error("Partition name and suffix does not fit.\n");
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+      goto out;
+    }
+
+    io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
+    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto out;
+    } else if (io_ret != AVB_IO_RESULT_OK) {
+      avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+      goto out;
+    }
+    avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+
+    image_buf = avb_malloc(image_size);
+    if (image_buf == NULL) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto out;
+    }
+
+    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;
+    } else if (io_ret != AVB_IO_RESULT_OK) {
+      avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+      goto out;
+    }
+    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;
+    }
+
+    /* Move to slot_data. */
+    if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
+      avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto out;
+    }
+    loaded_partition =
+        &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
+    loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
+    if (loaded_partition->partition_name == NULL) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto out;
+    }
+    loaded_partition->data_size = image_size;
+    loaded_partition->data = image_buf;
+    image_buf = NULL;
+  }
+
+  ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+  if (image_buf != NULL) {
+    avb_free(image_buf);
+  }
+  return ret;
+}
+
+static AvbSlotVerifyResult load_and_verify_vbmeta(
+    AvbOps* ops,
+    const char* const* requested_partitions,
+    const char* ab_suffix,
+    bool allow_verification_error,
+    AvbVBMetaImageFlags toplevel_vbmeta_flags,
+    int rollback_index_location,
+    const char* partition_name,
+    size_t partition_name_len,
+    const uint8_t* expected_public_key,
+    size_t expected_public_key_length,
+    AvbSlotVerifyData* slot_data,
+    AvbAlgorithmType* out_algorithm_type) {
+  char full_partition_name[PART_NAME_MAX_SIZE];
+  AvbSlotVerifyResult ret;
+  AvbIOResult io_ret;
+  size_t vbmeta_offset;
+  size_t vbmeta_size;
+  uint8_t* vbmeta_buf = NULL;
+  size_t vbmeta_num_read;
+  AvbVBMetaVerifyResult vbmeta_ret;
+  const uint8_t* pk_data;
+  size_t pk_len;
+  AvbVBMetaImageHeader vbmeta_header;
+  uint64_t stored_rollback_index;
+  const AvbDescriptor** descriptors = NULL;
+  size_t num_descriptors;
+  size_t n;
+  bool is_main_vbmeta;
+  bool is_vbmeta_partition;
+  AvbVBMetaData* vbmeta_image_data = NULL;
+
+  ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+  avb_assert(slot_data != NULL);
+
+  /* Since we allow top-level vbmeta in 'boot', use
+   * rollback_index_location to determine whether we're the main
+   * vbmeta struct.
+   */
+  is_main_vbmeta = (rollback_index_location == 0);
+  is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
+
+  if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
+    avb_error("Partition name is not valid UTF-8.\n");
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+
+  /* Construct full partition name. */
+  if (!avb_str_concat(full_partition_name,
+                      sizeof full_partition_name,
+                      partition_name,
+                      partition_name_len,
+                      ab_suffix,
+                      avb_strlen(ab_suffix))) {
+    avb_error("Partition name and suffix does not fit.\n");
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+
+  avb_debugv("Loading vbmeta struct from partition '",
+             full_partition_name,
+             "'.\n",
+             NULL);
+
+  /* If we're loading from the main vbmeta partition, the vbmeta
+   * struct is in the beginning. Otherwise we have to locate it via a
+   * footer.
+   */
+  if (is_vbmeta_partition) {
+    vbmeta_offset = 0;
+    vbmeta_size = VBMETA_MAX_SIZE;
+  } else {
+    uint8_t footer_buf[AVB_FOOTER_SIZE];
+    size_t footer_num_read;
+    AvbFooter footer;
+
+    io_ret = ops->read_from_partition(ops,
+                                      full_partition_name,
+                                      -AVB_FOOTER_SIZE,
+                                      AVB_FOOTER_SIZE,
+                                      footer_buf,
+                                      &footer_num_read);
+    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto out;
+    } else if (io_ret != AVB_IO_RESULT_OK) {
+      avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+      goto out;
+    }
+    avb_assert(footer_num_read == AVB_FOOTER_SIZE);
+
+    if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
+                                          &footer)) {
+      avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+      goto out;
+    }
+
+    /* Basic footer sanity check since the data is untrusted. */
+    if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
+      avb_errorv(
+          full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+      goto out;
+    }
+
+    vbmeta_offset = footer.vbmeta_offset;
+    vbmeta_size = footer.vbmeta_size;
+  }
+
+  vbmeta_buf = (uint8_t *)target_get_scratch_address() + 0x06000000;
+  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;
+  } else if (io_ret != AVB_IO_RESULT_OK) {
+    /* If we're looking for 'vbmeta' but there is no such partition,
+     * go try to get it from the boot partition instead.
+     */
+    if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
+        is_vbmeta_partition) {
+      avb_debugv(full_partition_name,
+                 ": No such partition. Trying 'boot' instead.\n",
+                 NULL);
+      ret = load_and_verify_vbmeta(ops,
+                                   requested_partitions,
+                                   ab_suffix,
+                                   allow_verification_error,
+                                   0 /* toplevel_vbmeta_flags */,
+                                   0 /* rollback_index_location */,
+                                   "boot",
+                                   avb_strlen("boot"),
+                                   NULL /* expected_public_key */,
+                                   0 /* expected_public_key_length */,
+                                   slot_data,
+                                   out_algorithm_type);
+      goto out;
+    } else {
+      avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+      goto out;
+    }
+  }
+  avb_assert(vbmeta_num_read <= vbmeta_size);
+
+  /* Check if the image is properly signed and get the public key used
+   * to sign the image.
+   */
+  vbmeta_ret =
+      avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
+  switch (vbmeta_ret) {
+    case AVB_VBMETA_VERIFY_RESULT_OK:
+      avb_assert(pk_data != NULL && pk_len > 0);
+      break;
+
+    case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
+    case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
+    case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+      avb_errorv(full_partition_name,
+                 ": Error verifying vbmeta image: ",
+                 avb_vbmeta_verify_result_to_string(vbmeta_ret),
+                 "\n",
+                 NULL);
+      if (!allow_verification_error) {
+        goto out;
+      }
+      break;
+
+    case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
+      /* No way to continue this case. */
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+      avb_errorv(full_partition_name,
+                 ": Error verifying vbmeta image: invalid vbmeta header\n",
+                 NULL);
+      goto out;
+
+    case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
+      /* No way to continue this case. */
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
+      avb_errorv(full_partition_name,
+                 ": Error verifying vbmeta image: unsupported AVB version\n",
+                 NULL);
+      goto out;
+  }
+
+  /* Byteswap the header. */
+  avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
+                                             &vbmeta_header);
+
+  /* If we're the toplevel, assign flags so they'll be passed down. */
+  if (is_main_vbmeta) {
+    toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
+  } else {
+    if (vbmeta_header.flags != 0) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+      avb_errorv(full_partition_name,
+                 ": chained vbmeta image has non-zero flags\n",
+                 NULL);
+      goto out;
+    }
+  }
+
+  /* Check if key used to make signature matches what is expected. */
+  if (pk_data != NULL) {
+    if (expected_public_key != NULL) {
+      avb_assert(!is_main_vbmeta);
+      if (expected_public_key_length != pk_len ||
+          avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
+        avb_errorv(full_partition_name,
+                   ": Public key used to sign data does not match key in chain "
+                   "partition descriptor.\n",
+                   NULL);
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
+        if (!allow_verification_error) {
+          goto out;
+        }
+      }
+    } else {
+      bool key_is_trusted = false;
+      const uint8_t* pk_metadata = NULL;
+      size_t pk_metadata_len = 0;
+
+      if (vbmeta_header.public_key_metadata_size > 0) {
+        pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
+                      vbmeta_header.authentication_data_block_size +
+                      vbmeta_header.public_key_metadata_offset;
+        pk_metadata_len = vbmeta_header.public_key_metadata_size;
+      }
+
+      avb_assert(is_main_vbmeta);
+      io_ret = ops->validate_vbmeta_public_key(
+          ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
+      if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+        goto out;
+      } else if (io_ret != AVB_IO_RESULT_OK) {
+        avb_errorv(full_partition_name,
+                   ": Error while checking public key used to sign data.\n",
+                   NULL);
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+        goto out;
+      }
+      if (!key_is_trusted) {
+        avb_errorv(full_partition_name,
+                   ": Public key used to sign data rejected.\n",
+                   NULL);
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
+        if (!allow_verification_error) {
+          goto out;
+        }
+      }
+    }
+  }
+
+  /* Check rollback index. */
+  io_ret = ops->read_rollback_index(
+      ops, rollback_index_location, &stored_rollback_index);
+  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto out;
+  } else if (io_ret != AVB_IO_RESULT_OK) {
+    avb_errorv(full_partition_name,
+               ": Error getting rollback index for location.\n",
+               NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+    goto out;
+  }
+  if (vbmeta_header.rollback_index < stored_rollback_index) {
+    avb_errorv(
+        full_partition_name,
+        ": Image rollback index is less than the stored rollback index.\n",
+        NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
+    if (!allow_verification_error) {
+      goto out;
+    }
+  }
+
+  /* Copy vbmeta to vbmeta_images before recursing. */
+  if (is_main_vbmeta) {
+    avb_assert(slot_data->num_vbmeta_images == 0);
+  } else {
+    avb_assert(slot_data->num_vbmeta_images > 0);
+  }
+  if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
+    avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto out;
+  }
+  vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
+  vbmeta_image_data->partition_name = avb_strdup(partition_name);
+  vbmeta_image_data->vbmeta_data = vbmeta_buf;
+  /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
+   * and this includes data past the end of the image. Pass the
+   * actual size of the vbmeta image. Also, no need to use
+   * avb_safe_add() since the header has already been verified.
+   */
+  vbmeta_image_data->vbmeta_size =
+      sizeof(AvbVBMetaImageHeader) +
+      vbmeta_header.authentication_data_block_size +
+      vbmeta_header.auxiliary_data_block_size;
+  vbmeta_image_data->verify_result = vbmeta_ret;
+
+  /* If verification has been disabled by setting a bit in the image,
+   * we're done... except that we need to load the entirety of the
+   * requested partitions.
+   */
+  if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
+    AvbSlotVerifyResult sub_ret;
+    avb_debugv(
+        full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
+    /* If load_requested_partitions() fail it is always a fatal
+     * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
+     * than recoverable (e.g. one where result_should_continue()
+     * returns true) and we want to convey that error.
+     */
+    sub_ret = load_requested_partitions(
+        ops, requested_partitions, ab_suffix, slot_data);
+    if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+      ret = sub_ret;
+    }
+    goto out;
+  }
+
+  /* Now go through all descriptors and take the appropriate action:
+   *
+   * - hash descriptor: Load data from partition, calculate hash, and
+   *   checks that it matches what's in the hash descriptor.
+   *
+   * - hashtree descriptor: Do nothing since verification happens
+   *   on-the-fly from within the OS.
+   *
+   * - chained partition descriptor: Load the footer, load the vbmeta
+   *   image, verify vbmeta image (includes rollback checks, hash
+   *   checks, bail on chained partitions).
+   */
+  descriptors =
+      avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
+  for (n = 0; n < num_descriptors; n++) {
+    AvbDescriptor desc;
+
+    if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
+      avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+      goto out;
+    }
+
+    switch (desc.tag) {
+      case AVB_DESCRIPTOR_TAG_HASH: {
+        AvbSlotVerifyResult sub_ret;
+        sub_ret = load_and_verify_hash_partition(ops,
+                                                 requested_partitions,
+                                                 ab_suffix,
+                                                 allow_verification_error,
+                                                 descriptors[n],
+                                                 slot_data);
+        if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+          ret = sub_ret;
+          if (!allow_verification_error || !result_should_continue(ret)) {
+            goto out;
+          }
+        }
+      } break;
+
+      case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
+        AvbSlotVerifyResult sub_ret;
+        AvbChainPartitionDescriptor chain_desc;
+        const uint8_t* chain_partition_name;
+        const uint8_t* chain_public_key;
+
+        /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
+        if (!is_main_vbmeta) {
+          avb_errorv(full_partition_name,
+                     ": Encountered chain descriptor not in main image.\n",
+                     NULL);
+          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+          goto out;
+        }
+
+        if (!avb_chain_partition_descriptor_validate_and_byteswap(
+                (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
+          avb_errorv(full_partition_name,
+                     ": Chain partition descriptor is invalid.\n",
+                     NULL);
+          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+          goto out;
+        }
+
+        if (chain_desc.rollback_index_location == 0) {
+          avb_errorv(full_partition_name,
+                     ": Chain partition has invalid "
+                     "rollback_index_location field.\n",
+                     NULL);
+          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+          goto out;
+        }
+
+        chain_partition_name = ((const uint8_t*)descriptors[n]) +
+                               sizeof(AvbChainPartitionDescriptor);
+        chain_public_key = chain_partition_name + chain_desc.partition_name_len;
+
+        sub_ret = load_and_verify_vbmeta(ops,
+                                         requested_partitions,
+                                         ab_suffix,
+                                         allow_verification_error,
+                                         toplevel_vbmeta_flags,
+                                         chain_desc.rollback_index_location,
+                                         (const char*)chain_partition_name,
+                                         chain_desc.partition_name_len,
+                                         chain_public_key,
+                                         chain_desc.public_key_len,
+                                         slot_data,
+                                         NULL /* out_algorithm_type */);
+        if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+          ret = sub_ret;
+          if (!result_should_continue(ret)) {
+            goto out;
+          }
+        }
+      } break;
+
+      case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
+        const uint8_t* kernel_cmdline;
+        AvbKernelCmdlineDescriptor kernel_cmdline_desc;
+        bool apply_cmdline;
+
+        if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
+                (AvbKernelCmdlineDescriptor*)descriptors[n],
+                &kernel_cmdline_desc)) {
+          avb_errorv(full_partition_name,
+                     ": Kernel cmdline descriptor is invalid.\n",
+                     NULL);
+          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+          goto out;
+        }
+
+        kernel_cmdline = ((const uint8_t*)descriptors[n]) +
+                         sizeof(AvbKernelCmdlineDescriptor);
+
+        if (!avb_validate_utf8(kernel_cmdline,
+                               kernel_cmdline_desc.kernel_cmdline_length)) {
+          avb_errorv(full_partition_name,
+                     ": Kernel cmdline is not valid UTF-8.\n",
+                     NULL);
+          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+          goto out;
+        }
+
+        /* Compare the flags for top-level VBMeta struct with flags in
+         * the command-line descriptor so command-line snippets only
+         * intended for a certain mode (dm-verity enabled/disabled)
+         * are skipped if applicable.
+         */
+        apply_cmdline = true;
+        if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
+          if (kernel_cmdline_desc.flags &
+              AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
+            apply_cmdline = false;
+          }
+        } else {
+          if (kernel_cmdline_desc.flags &
+              AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
+            apply_cmdline = false;
+          }
+        }
+
+        if (apply_cmdline) {
+          if (slot_data->cmdline == NULL) {
+            slot_data->cmdline =
+                avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
+            if (slot_data->cmdline == NULL) {
+              ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+              goto out;
+            }
+            avb_memcpy(slot_data->cmdline,
+                       kernel_cmdline,
+                       kernel_cmdline_desc.kernel_cmdline_length);
+          } else {
+            /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
+            size_t orig_size = avb_strlen(slot_data->cmdline);
+            size_t new_size =
+                orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
+            char* new_cmdline = avb_calloc(new_size);
+            if (new_cmdline == NULL) {
+              ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+              goto out;
+            }
+            avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
+            new_cmdline[orig_size] = ' ';
+            avb_memcpy(new_cmdline + orig_size + 1,
+                       kernel_cmdline,
+                       kernel_cmdline_desc.kernel_cmdline_length);
+            avb_free(slot_data->cmdline);
+            slot_data->cmdline = new_cmdline;
+          }
+        }
+      } break;
+
+      /* Explicit fall-through */
+      case AVB_DESCRIPTOR_TAG_PROPERTY:
+      case AVB_DESCRIPTOR_TAG_HASHTREE:
+        /* Do nothing. */
+        break;
+    }
+  }
+
+  if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
+    avb_errorv(
+        full_partition_name, ": Invalid rollback_index_location.\n", NULL);
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+    goto out;
+  }
+
+  slot_data->rollback_indexes[rollback_index_location] =
+      vbmeta_header.rollback_index;
+
+  if (out_algorithm_type != NULL) {
+    *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
+  }
+
+out:
+  /* If |vbmeta_image_data| isn't NULL it means that it adopted
+   * |vbmeta_buf| so in that case don't free it here.
+   */
+
+  /* remove avb_free() as memory allocated from scratch region */
+
+  if (descriptors != NULL) {
+    avb_free(descriptors);
+  }
+  return ret;
+}
+
+#define NUM_GUIDS 3
+
+/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
+ * values. Returns NULL on OOM, otherwise the cmdline with values
+ * replaced.
+ */
+static char* sub_cmdline(AvbOps* ops,
+                         const char* cmdline,
+                         const char* ab_suffix,
+                         bool using_boot_for_vbmeta) {
+  const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
+  const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
+                                        "$(ANDROID_BOOT_PARTUUID)",
+                                        "$(ANDROID_VBMETA_PARTUUID)"};
+  char* ret = NULL;
+  AvbIOResult io_ret;
+
+  /* Special-case for when the top-level vbmeta struct is in the boot
+   * partition.
+   */
+  if (using_boot_for_vbmeta) {
+    part_name_str[2] = "boot";
+  }
+
+  /* Replace unique partition GUIDs */
+  for (size_t n = 0; n < NUM_GUIDS; n++) {
+    char part_name[PART_NAME_MAX_SIZE];
+    char guid_buf[37];
+
+    if (!avb_str_concat(part_name,
+                        sizeof part_name,
+                        part_name_str[n],
+                        avb_strlen(part_name_str[n]),
+                        ab_suffix,
+                        avb_strlen(ab_suffix))) {
+      avb_error("Partition name and suffix does not fit.\n");
+      goto fail;
+    }
+
+    io_ret = ops->get_unique_guid_for_partition(
+        ops, part_name, guid_buf, sizeof guid_buf);
+    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+      return NULL;
+    } else if (io_ret != AVB_IO_RESULT_OK) {
+      avb_error("Error getting unique GUID for partition.\n");
+      goto fail;
+    }
+
+    if (ret == NULL) {
+      ret = avb_replace(cmdline, replace_str[n], guid_buf);
+    } else {
+      char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
+      avb_free(ret);
+      ret = new_ret;
+    }
+    if (ret == NULL) {
+      goto fail;
+    }
+  }
+
+  return ret;
+
+fail:
+  if (ret != NULL) {
+    avb_free(ret);
+  }
+  return NULL;
+}
+
+static int cmdline_append_option(AvbSlotVerifyData* slot_data,
+                                 const char* key,
+                                 const char* value) {
+  size_t offset, key_len, value_len;
+  char* new_cmdline;
+
+  key_len = avb_strlen(key);
+  value_len = avb_strlen(value);
+
+  offset = 0;
+  if (slot_data->cmdline != NULL) {
+    offset = avb_strlen(slot_data->cmdline);
+    if (offset > 0) {
+      offset += 1;
+    }
+  }
+
+  new_cmdline = avb_calloc(offset + key_len + value_len + 2);
+  if (new_cmdline == NULL) {
+    return 0;
+  }
+  if (offset > 0) {
+    avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
+    new_cmdline[offset - 1] = ' ';
+  }
+  avb_memcpy(new_cmdline + offset, key, key_len);
+  new_cmdline[offset + key_len] = '=';
+  avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
+  if (slot_data->cmdline != NULL) {
+    avb_free(slot_data->cmdline);
+  }
+  slot_data->cmdline = new_cmdline;
+
+  return 1;
+}
+
+#define AVB_MAX_DIGITS_UINT64 32
+
+/* Writes |value| to |digits| in base 10 followed by a NUL byte.
+ * Returns number of characters written excluding the NUL byte.
+ */
+static size_t uint64_to_base10(uint64_t value,
+                               char digits[AVB_MAX_DIGITS_UINT64]) {
+  char rev_digits[AVB_MAX_DIGITS_UINT64];
+  size_t n, num_digits;
+
+  for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
+    rev_digits[num_digits++] = (value % 10) + '0';
+    value /= 10;
+    if (value == 0) {
+      break;
+    }
+  }
+
+  for (n = 0; n < num_digits; n++) {
+    digits[n] = rev_digits[num_digits - 1 - n];
+  }
+  digits[n] = '\0';
+  return n;
+}
+
+static int cmdline_append_version(AvbSlotVerifyData* slot_data,
+                                  const char* key,
+                                  uint64_t major_version,
+                                  uint64_t minor_version) {
+  char major_digits[AVB_MAX_DIGITS_UINT64];
+  char minor_digits[AVB_MAX_DIGITS_UINT64];
+  char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
+  size_t num_major_digits, num_minor_digits;
+
+  num_major_digits = uint64_to_base10(major_version, major_digits);
+  num_minor_digits = uint64_to_base10(minor_version, minor_digits);
+  avb_memcpy(combined, major_digits, num_major_digits);
+  combined[num_major_digits] = '.';
+  avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
+  combined[num_major_digits + 1 + num_minor_digits] = '\0';
+
+  return cmdline_append_option(slot_data, key, combined);
+}
+
+static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
+                                        const char* key,
+                                        uint64_t value) {
+  char digits[AVB_MAX_DIGITS_UINT64];
+  uint64_to_base10(value, digits);
+  return cmdline_append_option(slot_data, key, digits);
+}
+
+static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
+                              const char* key,
+                              const uint8_t* data,
+                              size_t data_len) {
+  char hex_digits[17] = "0123456789abcdef";
+  char* hex_data;
+  int ret;
+  size_t n;
+
+  hex_data = avb_malloc(data_len * 2 + 1);
+  if (hex_data == NULL) {
+    return 0;
+  }
+
+  for (n = 0; n < data_len; n++) {
+    hex_data[n * 2] = hex_digits[data[n] >> 4];
+    hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
+  }
+  hex_data[n * 2] = '\0';
+
+  ret = cmdline_append_option(slot_data, key, hex_data);
+  avb_free(hex_data);
+  return ret;
+}
+
+static AvbSlotVerifyResult append_options(
+    AvbOps* ops,
+    AvbSlotVerifyData* slot_data,
+    AvbVBMetaImageHeader* toplevel_vbmeta,
+    AvbAlgorithmType algorithm_type,
+    AvbHashtreeErrorMode hashtree_error_mode) {
+  AvbSlotVerifyResult ret;
+  const char* verity_mode = NULL;
+  bool is_device_unlocked;
+  AvbIOResult io_ret;
+
+  /* Add androidboot.vbmeta.device option. */
+  if (!cmdline_append_option(slot_data,
+                             "androidboot.vbmeta.device",
+                             "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto out;
+  }
+
+  /* Add androidboot.vbmeta.avb_version option. */
+  if (!cmdline_append_version(slot_data,
+                              "androidboot.vbmeta.avb_version",
+                              AVB_VERSION_MAJOR,
+                              AVB_VERSION_MINOR)) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto out;
+  }
+
+  /* Set androidboot.avb.device_state to "locked" or "unlocked". */
+  io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
+  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto out;
+  } else if (io_ret != AVB_IO_RESULT_OK) {
+    avb_error("Error getting device state.\n");
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+    goto out;
+  }
+  if (!cmdline_append_option(slot_data,
+                             "androidboot.vbmeta.device_state",
+                             is_device_unlocked ? "unlocked" : "locked")) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto out;
+  }
+
+  /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
+   * function as is used to sign vbmeta.
+   */
+  switch (algorithm_type) {
+    /* Explicit fallthrough. */
+    case AVB_ALGORITHM_TYPE_NONE:
+    case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
+    case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
+    case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
+      size_t n, prev_sz = 0, total_size = 0;
+      uint8_t* digest = NULL;
+      uint8_t* tbuf = NULL;
+
+      digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
+      for (n = 0; n < slot_data->num_vbmeta_images; n++) {
+        total_size += slot_data->vbmeta_images[n].vbmeta_size;
+      }
+      tbuf = avb_malloc(total_size);
+
+      for (n = 0; n < slot_data->num_vbmeta_images; n++) {
+        avb_memcpy(tbuf + prev_sz, slot_data->vbmeta_images[n].vbmeta_data,
+                                   slot_data->vbmeta_images[n].vbmeta_size);
+        prev_sz = slot_data->vbmeta_images[n].vbmeta_size;
+      }
+      hash_find((unsigned char *)tbuf, total_size, digest, CRYPTO_AUTH_ALG_SHA256);
+      avb_free(tbuf);
+
+      if (!cmdline_append_option(
+              slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
+          !cmdline_append_uint64_base10(
+              slot_data, "androidboot.vbmeta.size", total_size) ||
+          !cmdline_append_hex(slot_data,
+                              "androidboot.vbmeta.digest",
+                              digest,
+                              AVB_SHA256_DIGEST_SIZE)) {
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+        if (digest)
+          avb_free(digest);
+        goto out;
+      }
+      if (digest)
+        avb_free(digest);
+    } break;
+    /* Explicit fallthrough. */
+    case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
+    case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
+    case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
+      AvbSHA512Ctx ctx;
+      size_t n, total_size = 0;
+      avb_sha512_init(&ctx);
+      for (n = 0; n < slot_data->num_vbmeta_images; n++) {
+        avb_sha512_update(&ctx,
+                          slot_data->vbmeta_images[n].vbmeta_data,
+                          slot_data->vbmeta_images[n].vbmeta_size);
+        total_size += slot_data->vbmeta_images[n].vbmeta_size;
+      }
+      if (!cmdline_append_option(
+              slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
+          !cmdline_append_uint64_base10(
+              slot_data, "androidboot.vbmeta.size", total_size) ||
+          !cmdline_append_hex(slot_data,
+                              "androidboot.vbmeta.digest",
+                              avb_sha512_final(&ctx),
+                              AVB_SHA512_DIGEST_SIZE)) {
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+        goto out;
+      }
+    } break;
+    case _AVB_ALGORITHM_NUM_TYPES:
+      avb_assert_not_reached();
+      break;
+  }
+
+  /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
+  if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
+    verity_mode = "disabled";
+  } else {
+    const char* dm_verity_mode = NULL;
+    char* new_ret;
+
+    switch (hashtree_error_mode) {
+      case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
+        if (!cmdline_append_option(
+                slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
+          ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+          goto out;
+        }
+        verity_mode = "enforcing";
+        dm_verity_mode = "restart_on_corruption";
+        break;
+      case AVB_HASHTREE_ERROR_MODE_RESTART:
+        verity_mode = "enforcing";
+        dm_verity_mode = "restart_on_corruption";
+        break;
+      case AVB_HASHTREE_ERROR_MODE_EIO:
+        verity_mode = "eio";
+        /* For now there's no option to specify the EIO mode. So
+         * just use 'ignore_zero_blocks' since that's already set
+         * and dm-verity-target.c supports specifying this multiple
+         * times.
+         */
+        dm_verity_mode = "ignore_zero_blocks";
+        break;
+      case AVB_HASHTREE_ERROR_MODE_LOGGING:
+        verity_mode = "logging";
+        dm_verity_mode = "ignore_corruption";
+        break;
+    }
+    new_ret = avb_replace(
+        slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
+    avb_free(slot_data->cmdline);
+    slot_data->cmdline = new_ret;
+    if (slot_data->cmdline == NULL) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto out;
+    }
+  }
+  if (!cmdline_append_option(
+          slot_data, "androidboot.veritymode", verity_mode)) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto out;
+  }
+
+  ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+
+  return ret;
+}
+
+AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
+                                    const char* const* requested_partitions,
+                                    const char* ab_suffix,
+                                    AvbSlotVerifyFlags flags,
+                                    AvbHashtreeErrorMode hashtree_error_mode,
+                                    AvbSlotVerifyData** out_data) {
+  AvbSlotVerifyResult ret;
+  AvbSlotVerifyData* slot_data = NULL;
+  AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
+  bool using_boot_for_vbmeta = false;
+  AvbVBMetaImageHeader toplevel_vbmeta;
+  bool allow_verification_error =
+      (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
+
+  /* Fail early if we're missing the AvbOps needed for slot verification.
+   *
+   * For now, handle get_size_of_partition() not being implemented. In
+   * a later release we may change that.
+   */
+  avb_assert(ops->read_is_device_unlocked != NULL);
+  avb_assert(ops->read_from_partition != NULL);
+  avb_assert(ops->validate_vbmeta_public_key != NULL);
+  avb_assert(ops->read_rollback_index != NULL);
+  avb_assert(ops->get_unique_guid_for_partition != NULL);
+  /* avb_assert(ops->get_size_of_partition != NULL); */
+
+  if (out_data != NULL) {
+    *out_data = NULL;
+  }
+
+  /* Allowing dm-verity errors defeats the purpose of verified boot so
+   * only allow this if set up to allow verification errors
+   * (e.g. typically only UNLOCKED mode).
+   */
+  if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
+      !allow_verification_error) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+    goto fail;
+  }
+
+  slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
+  if (slot_data == NULL) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto fail;
+  }
+  slot_data->vbmeta_images =
+      avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
+  if (slot_data->vbmeta_images == NULL) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto fail;
+  }
+  slot_data->loaded_partitions =
+      avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
+  if (slot_data->loaded_partitions == NULL) {
+    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+    goto fail;
+  }
+
+  ret = load_and_verify_vbmeta(ops,
+                               requested_partitions,
+                               ab_suffix,
+                               allow_verification_error,
+                               0 /* toplevel_vbmeta_flags */,
+                               0 /* rollback_index_location */,
+                               "vbmeta",
+                               avb_strlen("vbmeta"),
+                               NULL /* expected_public_key */,
+                               0 /* expected_public_key_length */,
+                               slot_data,
+                               &algorithm_type);
+  if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+    goto fail;
+  }
+
+  /* If things check out, mangle the kernel command-line as needed. */
+  if (result_should_continue(ret)) {
+    if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
+      avb_assert(
+          avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
+      using_boot_for_vbmeta = true;
+    }
+
+    /* Byteswap top-level vbmeta header since we'll need it below. */
+    avb_vbmeta_image_header_to_host_byte_order(
+        (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
+        &toplevel_vbmeta);
+
+    /* Fill in |ab_suffix| field. */
+    slot_data->ab_suffix = avb_strdup(ab_suffix);
+    if (slot_data->ab_suffix == NULL) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto fail;
+    }
+
+    /* If verification is disabled, we are done ... we specifically
+     * don't want to add any androidboot.* options since verification
+     * is disabled.
+     */
+    if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
+      /* Since verification is disabled we didn't process any
+       * descriptors and thus there's no cmdline... so set root= such
+       * that the system partition is mounted.
+       */
+      avb_assert(slot_data->cmdline == NULL);
+      slot_data->cmdline =
+          avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
+      if (slot_data->cmdline == NULL) {
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+        goto fail;
+      }
+    } else {
+      /* Add options - any failure in append_options() is either an
+       * I/O or OOM error.
+       */
+      AvbSlotVerifyResult sub_ret = append_options(ops,
+                                                   slot_data,
+                                                   &toplevel_vbmeta,
+                                                   algorithm_type,
+                                                   hashtree_error_mode);
+      if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+        ret = sub_ret;
+        goto fail;
+      }
+    }
+
+    /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
+    if (slot_data->cmdline != NULL) {
+      char* new_cmdline;
+      new_cmdline = sub_cmdline(
+          ops, slot_data->cmdline, ab_suffix, using_boot_for_vbmeta);
+      if (new_cmdline == NULL) {
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+        goto fail;
+      }
+      avb_free(slot_data->cmdline);
+      slot_data->cmdline = new_cmdline;
+    }
+
+    if (out_data != NULL) {
+      *out_data = slot_data;
+    } else {
+      avb_slot_verify_data_free(slot_data);
+    }
+  }
+
+  if (!allow_verification_error) {
+    avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
+  }
+
+  return ret;
+
+fail:
+  if (slot_data != NULL) {
+    avb_slot_verify_data_free(slot_data);
+  }
+  return ret;
+}
+
+void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
+  if (data->ab_suffix != NULL) {
+    avb_free(data->ab_suffix);
+  }
+  if (data->cmdline != NULL) {
+    avb_free(data->cmdline);
+  }
+  if (data->vbmeta_images != NULL) {
+    size_t n;
+    for (n = 0; n < data->num_vbmeta_images; n++) {
+      AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
+      if (vbmeta_image->partition_name != NULL) {
+        avb_free(vbmeta_image->partition_name);
+      }
+      if (vbmeta_image->vbmeta_data != NULL) {
+        vbmeta_image->vbmeta_data = NULL;
+      }
+    }
+    avb_free(data->vbmeta_images);
+  }
+  if (data->loaded_partitions != NULL) {
+    size_t n;
+    for (n = 0; n < data->num_loaded_partitions; n++) {
+      AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
+      if (loaded_partition->partition_name != NULL) {
+        avb_free(loaded_partition->partition_name);
+      }
+      if (loaded_partition->data != NULL) {
+         if (data->num_loaded_partitions == 1)
+           loaded_partition->data = NULL;
+      }
+    }
+    avb_free(data->loaded_partitions);
+  }
+  avb_free(data);
+}
+
+const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
+  const char* ret = NULL;
+
+  switch (result) {
+    case AVB_SLOT_VERIFY_RESULT_OK:
+      ret = "OK";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+      ret = "ERROR_OOM";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+      ret = "ERROR_IO";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+      ret = "ERROR_VERIFICATION";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+      ret = "ERROR_ROLLBACK_INDEX";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+      ret = "ERROR_PUBLIC_KEY_REJECTED";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+      ret = "ERROR_INVALID_METADATA";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+      ret = "ERROR_UNSUPPORTED_VERSION";
+      break;
+    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+      ret = "ERROR_INVALID_ARGUMENT";
+      break;
+      /* Do not add a 'default:' case here because of -Wswitch. */
+  }
+
+  if (ret == NULL) {
+    avb_error("Unknown AvbSlotVerifyResult value.\n");
+    ret = "(unknown)";
+  }
+
+  return ret;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_slot_verify.h b/platform/msm_shared/avb/libavb/avb_slot_verify.h
new file mode 100644
index 0000000..d8de8fb
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_slot_verify.h
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_SLOT_VERIFY_H_
+#define AVB_SLOT_VERIFY_H_
+
+#include "avb_ops.h"
+#include "avb_vbmeta_image.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return codes used in avb_slot_verify(), see that function for
+ * documentation for each field.
+ *
+ * Use avb_slot_verify_result_to_string() to get a textual
+ * representation usable for error/debug output.
+ */
+typedef enum {
+  AVB_SLOT_VERIFY_RESULT_OK,
+  AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
+  AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+  AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
+  AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
+  AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
+  AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
+  AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
+  AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
+} AvbSlotVerifyResult;
+
+/* Various error handling modes for when verification fails using a
+ * hashtree at runtime inside the HLOS.
+ *
+ * AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
+ * will invalidate the current slot and restart.
+ *
+ * AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
+ *
+ * AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
+ * returned to applications.
+ *
+ * AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
+ * and corrupt data may be returned to applications. This mode should
+ * be used ONLY for diagnostics and debugging. It cannot be used
+ * unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
+ * used.
+ */
+typedef enum {
+  AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+  AVB_HASHTREE_ERROR_MODE_RESTART,
+  AVB_HASHTREE_ERROR_MODE_EIO,
+  AVB_HASHTREE_ERROR_MODE_LOGGING
+} AvbHashtreeErrorMode;
+
+/* Flags that influence how avb_slot_verify() works.
+ *
+ * If AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is NOT set then
+ * avb_slot_verify() will bail out as soon as an error is encountered
+ * and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
+ * returned.
+ *
+ * Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
+ * avb_slot_verify() will continue verification efforts and |out_data|
+ * is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
+ * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
+ * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
+ * undefined which error is returned if more than one distinct error
+ * is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
+ * returned if, and only if, there are no errors. This mode is needed
+ * to boot valid but unverified slots when the device is unlocked.
+ *
+ * Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
+ * contents loaded from |requested_partition| will be the contents of
+ * the entire partition instead of just the size specified in the hash
+ * descriptor.
+ */
+typedef enum {
+  AVB_SLOT_VERIFY_FLAGS_NONE = 0,
+  AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0)
+} AvbSlotVerifyFlags;
+
+/* Get a textual representation of |result|. */
+const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
+
+/* Maximum number of rollback index locations supported. */
+#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS 32
+
+/* AvbPartitionData contains data loaded from partitions when using
+ * avb_slot_verify(). The |partition_name| field contains the name of
+ * the partition (without A/B suffix), |data| points to the loaded
+ * data which is |data_size| bytes long.
+ *
+ * Note that this is strictly less than the partition size - it's only
+ * the image stored there, not the entire partition nor any of the
+ * metadata.
+ */
+typedef struct {
+  char* partition_name;
+  uint8_t* data;
+  size_t data_size;
+} AvbPartitionData;
+
+/* AvbVBMetaData contains a vbmeta struct loaded from a partition when
+ * using avb_slot_verify(). The |partition_name| field contains the
+ * name of the partition (without A/B suffix), |vbmeta_data| points to
+ * the loaded data which is |vbmeta_size| bytes long.
+ *
+ * The |verify_result| field contains the result of
+ * avb_vbmeta_image_verify() on the data. This is guaranteed to be
+ * AVB_VBMETA_VERIFY_RESULT_OK for all vbmeta images if
+ * avb_slot_verify() returns AVB_SLOT_VERIFY_RESULT_OK.
+ *
+ * You can use avb_descriptor_get_all(), avb_descriptor_foreach(), and
+ * avb_vbmeta_image_header_to_host_byte_order() with this data.
+ */
+typedef struct {
+  char* partition_name;
+  uint8_t* vbmeta_data;
+  size_t vbmeta_size;
+  AvbVBMetaVerifyResult verify_result;
+} AvbVBMetaData;
+
+/* AvbSlotVerifyData contains data needed to boot a particular slot
+ * and is returned by avb_slot_verify() if partitions in a slot are
+ * successfully verified.
+ *
+ * All data pointed to by this struct - including data in each item in
+ * the |partitions| array - will be freed when the
+ * avb_slot_verify_data_free() function is called.
+ *
+ * The |ab_suffix| field is the copy of the of |ab_suffix| field
+ * passed to avb_slot_verify(). It is the A/B suffix of the slot. This
+ * value includes the leading underscore - typical values are "" (if
+ * no slots are in use), "_a" (for the first slot), and "_b" (for the
+ * second slot).
+ *
+ * The VBMeta images that were checked are available in the
+ * |vbmeta_images| field. The field |num_vbmeta_images| contains the
+ * number of elements in this array. The first element -
+ * vbmeta_images[0] - is guaranteed to be from the partition with the
+ * top-level vbmeta struct. This is usually the "vbmeta" partition in
+ * the requested slot but if there is no "vbmeta" partition it can
+ * also be the "boot" partition.
+ *
+ * The partitions loaded and verified from from the slot are
+ * accessible in the |loaded_partitions| array. The field
+ * |num_loaded_partitions| contains the number of elements in this
+ * array. The order of partitions in this array may not necessarily be
+ * the same order as in the passed-in |requested_partitions| array.
+ *
+ * Rollback indexes for the verified slot are stored in the
+ * |rollback_indexes| field. Note that avb_slot_verify() will NEVER
+ * modify stored_rollback_index[n] locations e.g. it will never use
+ * the write_rollback_index() AvbOps operation. Instead it is the job
+ * of the caller of avb_slot_verify() to do this based on e.g. A/B
+ * policy and other factors. See libavb_ab/avb_ab_flow.c for an
+ * example of how to do this.
+ *
+ * The |cmdline| field is a NUL-terminated string in UTF-8 resulting
+ * from concatenating all |AvbKernelCmdlineDescriptor| and then
+ * performing proper substitution of the variables
+ * $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
+ * $(ANDROID_VBMETA_PARTUUID) using the
+ * get_unique_guid_for_partition() operation in |AvbOps|. Additionally
+ * $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
+ * option depending on the value of |hashtree_error_mode|.
+ *
+ * Additionally, the |cmdline| field will have the following kernel
+ * command-line options set (unless verification is disabled, see
+ * below):
+ *
+ *   androidboot.veritymode: This is set to 'disabled' if the
+ *   AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
+ *   vbmeta struct. Otherwise it is set to 'enforcing' if the
+ *   passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
+ *   or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
+ *   set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
+ *   AVB_HASHTREE_ERROR_MODE_LOGGING.
+ *
+ *   androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
+ *   if hashtree validation isn't disabled and the passed-in hashtree
+ *   error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
+ *
+ *   androidboot.vbmeta.device_state: set to "locked" or "unlocked"
+ *   depending on the result of the result of AvbOps's
+ *   read_is_unlocked() function.
+ *
+ *   androidboot.vbmeta.{hash_alg, size, digest}: Will be set to
+ *   the digest of all images in |vbmeta_images|.
+ *
+ *   androidboot.vbmeta.device: This is set to the value
+ *   PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
+ *   will end up pointing to the vbmeta partition for the verified
+ *   slot. If there is no vbmeta partition it will point to the boot
+ *   partition of the verified slot.
+ *
+ *   androidboot.vbmeta.avb_version: This is set to the decimal value
+ *   of AVB_VERSION_MAJOR followed by a dot followed by the decimal
+ *   value of AVB_VERSION_MINOR, for example "1.0" or "1.4". This
+ *   version number represents the vbmeta file format version
+ *   supported by libavb copy used in the boot loader. This is not
+ *   necessarily the same version number of the on-disk metadata for
+ *   the slot that was verified.
+ *
+ * Note that androidboot.slot_suffix is not set in the |cmdline| field
+ * in |AvbSlotVerifyData| - you will have to set this yourself.
+ *
+ * If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
+ * in the top-level vbmeta struct then only the top-level vbmeta
+ * struct is verified and descriptors will not processed. The return
+ * value will be set accordingly (if this flag is set via 'avbctl
+ * disable-verification' then the return value will be
+ * |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
+ * |AvbSlotVerifyData| is returned. Additionally all partitions in the
+ * |requested_partitions| are loaded and the |cmdline| field is set to
+ * "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
+ * appropriate system partition is substituted in. Note that none of
+ * the androidboot.* options mentioned above will be set.
+ *
+ * This struct may grow in the future without it being considered an
+ * ABI break.
+ */
+typedef struct {
+  char* ab_suffix;
+  AvbVBMetaData* vbmeta_images;
+  size_t num_vbmeta_images;
+  AvbPartitionData* loaded_partitions;
+  size_t num_loaded_partitions;
+  char* cmdline;
+  uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
+} AvbSlotVerifyData;
+
+/* Frees a |AvbSlotVerifyData| including all data it points to. */
+void avb_slot_verify_data_free(AvbSlotVerifyData* data);
+
+/* Performs a full verification of the slot identified by |ab_suffix|
+ * and load and verify the contents of the partitions whose name is in
+ * the NULL-terminated string array |requested_partitions| (each
+ * partition must use hash verification). If not using A/B, pass an
+ * empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
+ * must include the leading underscore, for example "_a" should be
+ * used to refer to the first slot.
+ *
+ * Typically the |requested_partitions| array only contains a single
+ * item for the boot partition, 'boot'.
+ *
+ * Verification includes loading and verifying data from the 'vbmeta',
+ * the requested hash partitions, and possibly other partitions (with
+ * |ab_suffix| appended), inspecting rollback indexes, and checking if
+ * the public key used to sign the data is acceptable. The functions
+ * in |ops| will be used to do this.
+ *
+ * If |out_data| is not NULL, it will be set to a newly allocated
+ * |AvbSlotVerifyData| struct containing all the data needed to
+ * actually boot the slot. This data structure should be freed with
+ * avb_slot_verify_data_free() when you are done with it. See below
+ * for when this is returned.
+ *
+ * The |flags| parameter is used to influence the semantics of
+ * avb_slot_verify() - for example the
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
+ * ignore verification errors which is something needed in the
+ * UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
+ *
+ * The |hashtree_error_mode| parameter should be set to the desired
+ * error handling mode when hashtree validation fails inside the
+ * HLOS. This value isn't used by libavb per se - it is forwarded to
+ * the HLOS through the androidboot.veritymode and
+ * androidboot.vbmeta.invalidate_on_error cmdline parameters. See the
+ * AvbHashtreeErrorMode enumeration for details.
+ *
+ * Also note that |out_data| is never set if
+ * AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+ * or AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned.
+ *
+ * AVB_SLOT_VERIFY_RESULT_OK is returned if everything is verified
+ * correctly and all public keys are accepted.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED is returned if
+ * everything is verified correctly out but one or more public keys
+ * are not accepted. This includes the case where integrity data is
+ * not signed.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_OOM is returned if unable to
+ * allocate memory.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_IO is returned if an I/O error
+ * occurred while trying to load data or get a rollback index.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION is returned if the data
+ * did not verify, e.g. the digest didn't match or signature checks
+ * failed.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned if a
+ * rollback index was less than its stored value.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned if some
+ * of the metadata is invalid or inconsistent.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION is returned if
+ * some of the metadata requires a newer version of libavb than what
+ * is in use.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned if the
+ * caller passed invalid parameters, for example trying to use
+ * AVB_HASHTREE_ERROR_MODE_LOGGING without
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
+ */
+AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
+                                    const char* const* requested_partitions,
+                                    const char* ab_suffix,
+                                    AvbSlotVerifyFlags flags,
+                                    AvbHashtreeErrorMode hashtree_error_mode,
+                                    AvbSlotVerifyData** out_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SLOT_VERIFY_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_sysdeps.c b/platform/msm_shared/avb/libavb/avb_sysdeps.c
new file mode 100644
index 0000000..15c9d58
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_sysdeps.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Copyright (c) 2017, 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ *  with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "avb_sysdeps.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <target.h>
+#include <malloc.h>
+
+int avb_memcmp(const void *src1, const void *src2, size_t n)
+{
+	return memcmp(src1, src2, n);
+}
+
+void *avb_memcpy(void *dest, const void *src, size_t n)
+{
+	return memcpy(dest, src, n);
+}
+
+void *avb_memset(void *dest, const int c, size_t n)
+{
+	return memset(dest, c, n);
+}
+
+int avb_strcmp(const char *s1, const char *s2)
+{
+	return strcmp(s1, s2);
+}
+
+size_t avb_strlen(const char *str)
+{
+	return strlen(str);
+}
+
+void avb_abort(void)
+{
+	dprintf(INFO, "avb_abort!");
+	shutdown_device();
+}
+
+void avb_print(const char *message)
+{
+	dprintf(INFO, message);
+}
+
+void avb_printv(const char *message, ...)
+{
+	va_list ap;
+	const char *m;
+
+	va_start(ap, message);
+	for (m = message; m != NULL; m = va_arg(ap, const char *)) {
+		avb_print(m);
+	}
+	va_end(ap);
+	return;
+}
+
+void *avb_malloc_(size_t size)
+{
+	return malloc(size);
+}
+
+void avb_free(void *ptr)
+{
+	free(ptr);
+}
diff --git a/platform/msm_shared/avb/libavb/avb_sysdeps.h b/platform/msm_shared/avb/libavb/avb_sysdeps.h
new file mode 100644
index 0000000..55e3e19
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_sysdeps.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_SYSDEPS_H_
+#define AVB_SYSDEPS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Change these includes to match your platform to bring in the
+ * equivalent types available in a normal C runtime. At least things
+ * like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
+ * must be present.
+ */
+#include <stddef.h>
+#include <stdint.h>
+#include <verifiedboot.h>
+#include <crypto_hash.h>
+
+/* If you don't have gcc or clang, these attribute macros may need to
+ * be adjusted.
+ */
+#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#define AVB_ATTR_PACKED __attribute__((packed))
+#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
+#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
+
+/* Size in bytes used for alignment. */
+#ifdef __LP64__
+#define AVB_ALIGNMENT_SIZE 8
+#else
+#define AVB_ALIGNMENT_SIZE 4
+#endif
+
+/* Compare |n| bytes in |src1| and |src2|.
+ *
+ * Returns an integer less than, equal to, or greater than zero if the
+ * first |n| bytes of |src1| is found, respectively, to be less than,
+ * to match, or be greater than the first |n| bytes of |src2|. */
+int avb_memcmp(const void* src1,
+               const void* src2,
+               size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Compare two strings.
+ *
+ * Return an integer less than, equal to, or greater than zero if |s1|
+ * is found, respectively, to be less than, to match, or be greater
+ * than |s2|.
+ */
+int avb_strcmp(const char* s1, const char* s2);
+
+/* Copy |n| bytes from |src| to |dest|. */
+void* avb_memcpy(void* dest, const void* src, size_t n);
+
+/* Set |n| bytes starting at |s| to |c|.  Returns |dest|. */
+void* avb_memset(void* dest, const int c, size_t n);
+
+/* Prints out a message. The string passed must be a NUL-terminated
+ * UTF-8 string.
+ */
+void avb_print(const char* message);
+
+/* Prints out a vector of strings. Each argument must point to a
+ * NUL-terminated UTF-8 string and NULL should be the last argument.
+ */
+void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
+
+/* Aborts the program or reboots the device. */
+void avb_abort(void);
+
+/* Allocates |size| bytes. Returns NULL if no memory is available,
+ * otherwise a pointer to the allocated memory.
+ *
+ * The memory is not initialized.
+ *
+ * The pointer returned is guaranteed to be word-aligned.
+ *
+ * The memory should be freed with avb_free() when you are done with it.
+ */
+void* avb_malloc_(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Frees memory previously allocated with avb_malloc(). */
+void avb_free(void* ptr);
+
+/* Returns the lenght of |str|, excluding the terminating NUL-byte. */
+size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SYSDEPS_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_sysdeps_posix.c b/platform/msm_shared/avb/libavb/avb_sysdeps_posix.c
new file mode 100644
index 0000000..b538811
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_sysdeps_posix.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <endian.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avb_sysdeps.h"
+
+int avb_memcmp(const void* src1, const void* src2, size_t n) {
+  return memcmp(src1, src2, n);
+}
+
+void* avb_memcpy(void* dest, const void* src, size_t n) {
+  return memcpy(dest, src, n);
+}
+
+void* avb_memset(void* dest, const int c, size_t n) {
+  return memset(dest, c, n);
+}
+
+int avb_strcmp(const char* s1, const char* s2) {
+  return strcmp(s1, s2);
+}
+
+size_t avb_strlen(const char* str) {
+  return strlen(str);
+}
+
+void avb_abort(void) {
+  dprintf(INFO, "avb_abort!");
+  ASSERT(0);
+}
+
+void avb_print(const char* message) {
+  dprintf(DEBUG, "%s", message);
+}
+
+void avb_printv(const char* message, ...) {
+  va_list ap;
+  const char* m;
+
+  va_start(ap, message);
+  for (m = message; m != NULL; m = va_arg(ap, const char*)) {
+    dprintf(DEBUG, "%s", m);
+  }
+  va_end(ap);
+}
+
+void* avb_malloc_(size_t size) {
+  return malloc(size);
+}
+
+void avb_free(void* ptr) {
+  free(ptr);
+  ptr = NULL;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_util.c b/platform/msm_shared/avb/libavb/avb_util.c
new file mode 100644
index 0000000..43662b4
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_util.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_util.h"
+
+#include <stdarg.h>
+
+uint32_t avb_be32toh(uint32_t in) {
+  uint8_t* d = (uint8_t*)&in;
+  uint32_t ret;
+  ret = ((uint32_t)d[0]) << 24;
+  ret |= ((uint32_t)d[1]) << 16;
+  ret |= ((uint32_t)d[2]) << 8;
+  ret |= ((uint32_t)d[3]);
+  return ret;
+}
+
+uint64_t avb_be64toh(uint64_t in) {
+  uint8_t* d = (uint8_t*)&in;
+  uint64_t ret;
+  ret = ((uint64_t)d[0]) << 56;
+  ret |= ((uint64_t)d[1]) << 48;
+  ret |= ((uint64_t)d[2]) << 40;
+  ret |= ((uint64_t)d[3]) << 32;
+  ret |= ((uint64_t)d[4]) << 24;
+  ret |= ((uint64_t)d[5]) << 16;
+  ret |= ((uint64_t)d[6]) << 8;
+  ret |= ((uint64_t)d[7]);
+  return ret;
+}
+
+/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
+uint32_t avb_htobe32(uint32_t in) {
+  union {
+    uint32_t word;
+    uint8_t bytes[4];
+  } ret;
+  ret.bytes[0] = (in >> 24) & 0xff;
+  ret.bytes[1] = (in >> 16) & 0xff;
+  ret.bytes[2] = (in >> 8) & 0xff;
+  ret.bytes[3] = in & 0xff;
+  return ret.word;
+}
+
+/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+uint64_t avb_htobe64(uint64_t in) {
+  union {
+    uint64_t word;
+    uint8_t bytes[8];
+  } ret;
+  ret.bytes[0] = (in >> 56) & 0xff;
+  ret.bytes[1] = (in >> 48) & 0xff;
+  ret.bytes[2] = (in >> 40) & 0xff;
+  ret.bytes[3] = (in >> 32) & 0xff;
+  ret.bytes[4] = (in >> 24) & 0xff;
+  ret.bytes[5] = (in >> 16) & 0xff;
+  ret.bytes[6] = (in >> 8) & 0xff;
+  ret.bytes[7] = in & 0xff;
+  return ret.word;
+}
+
+int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
+  const unsigned char* us1 = s1;
+  const unsigned char* us2 = s2;
+  int result = 0;
+
+  if (0 == n) {
+    return 0;
+  }
+
+  /*
+   * Code snippet without data-dependent branch due to Nate Lawson
+   * (nate@root.org) of Root Labs.
+   */
+  while (n--) {
+    result |= *us1++ ^ *us2++;
+  }
+
+  return result != 0;
+}
+
+bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
+  uint64_t original_value;
+
+  avb_assert(value != NULL);
+
+  original_value = *value;
+
+  *value += value_to_add;
+  if (*value < original_value) {
+    avb_error("Overflow when adding values.\n");
+    return false;
+  }
+
+  return true;
+}
+
+bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
+  uint64_t dummy;
+  if (out_result == NULL) {
+    out_result = &dummy;
+  }
+  *out_result = a;
+  return avb_safe_add_to(out_result, b);
+}
+
+bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
+  size_t n;
+  unsigned int num_cc;
+
+  for (n = 0, num_cc = 0; n < num_bytes; n++) {
+    uint8_t c = data[n];
+
+    if (num_cc > 0) {
+      if ((c & (0x80 | 0x40)) == 0x80) {
+        /* 10xx xxxx */
+      } else {
+        goto fail;
+      }
+      num_cc--;
+    } else {
+      if (c < 0x80) {
+        num_cc = 0;
+      } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
+        /* 110x xxxx */
+        num_cc = 1;
+      } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
+        /* 1110 xxxx */
+        num_cc = 2;
+      } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
+                 (0x80 | 0x40 | 0x20 | 0x10)) {
+        /* 1111 0xxx */
+        num_cc = 3;
+      } else {
+        goto fail;
+      }
+    }
+  }
+
+  if (num_cc != 0) {
+    goto fail;
+  }
+
+  return true;
+
+fail:
+  return false;
+}
+
+bool avb_str_concat(char* buf,
+                    size_t buf_size,
+                    const char* str1,
+                    size_t str1_len,
+                    const char* str2,
+                    size_t str2_len) {
+  uint64_t combined_len;
+
+  if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
+    avb_error("Overflow when adding string sizes.\n");
+    return false;
+  }
+
+  if (combined_len > buf_size - 1) {
+    avb_error("Insufficient buffer space.\n");
+    return false;
+  }
+
+  avb_memcpy(buf, str1, str1_len);
+  avb_memcpy(buf + str1_len, str2, str2_len);
+  buf[combined_len] = '\0';
+
+  return true;
+}
+
+void* avb_malloc(size_t size) {
+  void* ret = avb_malloc_(size);
+  if (ret == NULL) {
+    avb_error("Failed to allocate memory.\n");
+    return NULL;
+  }
+  return ret;
+}
+
+void* avb_calloc(size_t size) {
+  void* ret = avb_malloc(size);
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  avb_memset(ret, '\0', size);
+  return ret;
+}
+
+char* avb_strdup(const char* str) {
+  size_t len = avb_strlen(str);
+  char* ret = avb_malloc(len + 1);
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  avb_memcpy(ret, str, len);
+  ret[len] = '\0';
+
+  return ret;
+}
+
+const char* avb_strstr(const char* haystack, const char* needle) {
+  size_t n, m;
+
+  /* Look through |haystack| and check if the first character of
+   * |needle| matches. If so, check the rest of |needle|.
+   */
+  for (n = 0; haystack[n] != '\0'; n++) {
+    if (haystack[n] != needle[0]) {
+      continue;
+    }
+
+    for (m = 1;; m++) {
+      if (needle[m] == '\0') {
+        return haystack + n;
+      }
+
+      if (haystack[n + m] != needle[m]) {
+        break;
+      }
+    }
+  }
+
+  return NULL;
+}
+
+const char* avb_strv_find_str(const char* const* strings,
+                              const char* str,
+                              size_t str_size) {
+  size_t n;
+  for (n = 0; strings[n] != NULL; n++) {
+    if (avb_strlen(strings[n]) == str_size &&
+        avb_memcmp(strings[n], str, str_size) == 0) {
+      return strings[n];
+    }
+  }
+  return NULL;
+}
+
+char* avb_replace(const char* str, const char* search, const char* replace) {
+  char* ret = NULL;
+  size_t ret_len = 0;
+  size_t search_len, replace_len;
+  const char* str_after_last_replace;
+
+  search_len = avb_strlen(search);
+  replace_len = avb_strlen(replace);
+
+  str_after_last_replace = str;
+  while (*str != '\0') {
+    const char* s;
+    size_t num_before;
+    size_t num_new;
+
+    s = avb_strstr(str, search);
+    if (s == NULL) {
+      break;
+    }
+
+    num_before = s - str;
+
+    if (ret == NULL) {
+      num_new = num_before + replace_len + 1;
+      ret = avb_malloc(num_new);
+      if (ret == NULL) {
+        goto out;
+      }
+      avb_memcpy(ret, str, num_before);
+      avb_memcpy(ret + num_before, replace, replace_len);
+      ret[num_new - 1] = '\0';
+      ret_len = num_new - 1;
+    } else {
+      char* new_str;
+      num_new = ret_len + num_before + replace_len + 1;
+      new_str = avb_malloc(num_new);
+      if (ret == NULL) {
+        goto out;
+      }
+      avb_memcpy(new_str, ret, ret_len);
+      avb_memcpy(new_str + ret_len, str, num_before);
+      avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
+      new_str[num_new - 1] = '\0';
+      avb_free(ret);
+      ret = new_str;
+      ret_len = num_new - 1;
+    }
+
+    str = s + search_len;
+    str_after_last_replace = str;
+  }
+
+  if (ret == NULL) {
+    ret = avb_strdup(str_after_last_replace);
+    if (ret == NULL) {
+      goto out;
+    }
+  } else {
+    size_t num_remaining = avb_strlen(str_after_last_replace);
+    size_t num_new = ret_len + num_remaining + 1;
+    char* new_str = avb_malloc(num_new);
+    if (ret == NULL) {
+      goto out;
+    }
+    avb_memcpy(new_str, ret, ret_len);
+    avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
+    new_str[num_new - 1] = '\0';
+    avb_free(ret);
+    ret = new_str;
+    ret_len = num_new - 1;
+  }
+
+out:
+  return ret;
+}
+
+/* We only support a limited amount of strings in avb_strdupv(). */
+#define AVB_STRDUPV_MAX_NUM_STRINGS 32
+
+char* avb_strdupv(const char* str, ...) {
+  va_list ap;
+  const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
+  size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
+  size_t num_strings, n;
+  uint64_t total_length;
+  char *ret = NULL, *dest;
+
+  num_strings = 0;
+  total_length = 0;
+  va_start(ap, str);
+  do {
+    size_t str_len = avb_strlen(str);
+    strings[num_strings] = str;
+    lengths[num_strings] = str_len;
+    if (!avb_safe_add_to(&total_length, str_len)) {
+      avb_fatal("Overflow while determining total length.\n");
+      break;
+    }
+    num_strings++;
+    if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
+      avb_fatal("Too many strings passed.\n");
+      break;
+    }
+    str = va_arg(ap, const char*);
+  } while (str != NULL);
+  va_end(ap);
+
+  ret = avb_malloc(total_length + 1);
+  if (ret == NULL) {
+    goto out;
+  }
+
+  dest = ret;
+  for (n = 0; n < num_strings; n++) {
+    avb_memcpy(dest, strings[n], lengths[n]);
+    dest += lengths[n];
+  }
+  *dest = '\0';
+  avb_assert(dest == ret + total_length);
+
+out:
+  return ret;
+}
+
+const char* avb_basename(const char* str) {
+  int64_t n;
+  size_t len;
+
+  len = avb_strlen(str);
+  if (len >= 2) {
+    for (n = len - 2; n >= 0; n--) {
+      if (str[n] == '/') {
+        return str + n + 1;
+      }
+    }
+  }
+  return str;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_util.h b/platform/msm_shared/avb/libavb/avb_util.h
new file mode 100644
index 0000000..07c3258
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_util.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_UTIL_H_
+#define AVB_UTIL_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AVB_STRINGIFY(x) #x
+#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
+
+#ifdef AVB_ENABLE_DEBUG
+/* Aborts the program if |expr| is false.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_assert(expr)                     \
+  do {                                       \
+    if (!(expr)) {                           \
+      avb_fatal("assert fail: " #expr "\n"); \
+    }                                        \
+  } while (0)
+#else
+#define avb_assert(expr)
+#endif
+
+/* Aborts the program if reached.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#ifdef AVB_ENABLE_DEBUG
+#define avb_assert_not_reached()         \
+  do {                                   \
+    avb_fatal("assert_not_reached()\n"); \
+  } while (0)
+#else
+#define avb_assert_not_reached()
+#endif
+
+/* Aborts the program if |addr| is not word-aligned.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_assert_aligned(addr) \
+  avb_assert((((uintptr_t)addr) & (AVB_ALIGNMENT_SIZE - 1)) == 0)
+
+#ifdef AVB_ENABLE_DEBUG
+/* Print functions, used for diagnostics.
+ *
+ * These have no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_debug(message)              \
+  do {                                  \
+    avb_printv(avb_basename(__FILE__),  \
+               ":",                     \
+               AVB_TO_STRING(__LINE__), \
+               ": DEBUG: ",             \
+               message,                 \
+               NULL);                   \
+  } while (0)
+#define avb_debugv(message, ...)        \
+  do {                                  \
+    avb_printv(avb_basename(__FILE__),  \
+               ":",                     \
+               AVB_TO_STRING(__LINE__), \
+               ": DEBUG: ",             \
+               message,                 \
+               ##__VA_ARGS__);          \
+  } while (0)
+#else
+#define avb_debug(message)
+#define avb_debugv(message, ...)
+#endif
+
+/* Prints out a message. This is typically used if a runtime-error
+ * occurs.
+ */
+#define avb_error(message)              \
+  do {                                  \
+    avb_printv(avb_basename(__FILE__),  \
+               ":",                     \
+               AVB_TO_STRING(__LINE__), \
+               ": ERROR: ",             \
+               message,                 \
+               NULL);                   \
+  } while (0)
+#define avb_errorv(message, ...)        \
+  do {                                  \
+    avb_printv(avb_basename(__FILE__),  \
+               ":",                     \
+               AVB_TO_STRING(__LINE__), \
+               ": ERROR: ",             \
+               message,                 \
+               ##__VA_ARGS__);          \
+  } while (0)
+
+/* Prints out a message and calls avb_abort().
+ */
+#define avb_fatal(message)              \
+  do {                                  \
+    avb_printv(avb_basename(__FILE__),  \
+               ":",                     \
+               AVB_TO_STRING(__LINE__), \
+               ": FATAL: ",             \
+               message,                 \
+               NULL);                   \
+    avb_abort();                        \
+  } while (0)
+#define avb_fatalv(message, ...)        \
+  do {                                  \
+    avb_printv(avb_basename(__FILE__),  \
+               ":",                     \
+               AVB_TO_STRING(__LINE__), \
+               ": FATAL: ",             \
+               message,                 \
+               ##__VA_ARGS__);          \
+    avb_abort();                        \
+  } while (0)
+
+/* Converts a 32-bit unsigned integer from big-endian to host byte order. */
+uint32_t avb_be32toh(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Converts a 64-bit unsigned integer from big-endian to host byte order. */
+uint64_t avb_be64toh(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
+uint32_t avb_htobe32(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+uint64_t avb_htobe64(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Compare |n| bytes starting at |s1| with |s2| and return 0 if they
+ * match, 1 if they don't.  Returns 0 if |n|==0, since no bytes
+ * mismatched.
+ *
+ * Time taken to perform the comparison is only dependent on |n| and
+ * not on the relationship of the match between |s1| and |s2|.
+ *
+ * Note that unlike avb_memcmp(), this only indicates inequality, not
+ * whether |s1| is less than or greater than |s2|.
+ */
+int avb_safe_memcmp(const void* s1,
+                    const void* s2,
+                    size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Adds |value_to_add| to |value| with overflow protection.
+ *
+ * Returns false if the addition overflows, true otherwise. In either
+ * case, |value| is always modified.
+ */
+bool avb_safe_add_to(uint64_t* value,
+                     uint64_t value_to_add) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Adds |a| and |b| with overflow protection, returning the value in
+ * |out_result|.
+ *
+ * It's permissible to pass NULL for |out_result| if you just want to
+ * check that the addition would not overflow.
+ *
+ * Returns false if the addition overflows, true otherwise.
+ */
+bool avb_safe_add(uint64_t* out_result,
+                  uint64_t a,
+                  uint64_t b) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Checks if |num_bytes| data at |data| is a valid UTF-8
+ * string. Returns true if valid UTF-8, false otherwise.
+ */
+bool avb_validate_utf8(const uint8_t* data,
+                       size_t num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Concatenates |str1| (of |str1_len| bytes) and |str2| (of |str2_len|
+ * bytes) and puts the result in |buf| which holds |buf_size|
+ * bytes. The result is also guaranteed to be NUL terminated. Fail if
+ * there is not enough room in |buf| for the resulting string plus
+ * terminating NUL byte.
+ *
+ * Returns true if the operation succeeds, false otherwise.
+ */
+bool avb_str_concat(char* buf,
+                    size_t buf_size,
+                    const char* str1,
+                    size_t str1_len,
+                    const char* str2,
+                    size_t str2_len);
+
+/* Like avb_malloc_() but prints a error using avb_error() if memory
+ * allocation fails.
+ */
+void* avb_malloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Like avb_malloc() but sets the memory with zeroes. */
+void* avb_calloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Duplicates a NUL-terminated string. Returns NULL on OOM. */
+char* avb_strdup(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Duplicates a NULL-terminated array of NUL-terminated strings by
+ * concatenating them. The returned string will be
+ * NUL-terminated. Returns NULL on OOM.
+ */
+char* avb_strdupv(const char* str,
+                  ...) AVB_ATTR_WARN_UNUSED_RESULT AVB_ATTR_SENTINEL;
+
+/* Finds the first occurrence of |needle| in the string |haystack|
+ * where both strings are NUL-terminated strings. The terminating NUL
+ * bytes are not compared.
+ *
+ * Returns NULL if not found, otherwise points into |haystack| for the
+ * first occurrence of |needle|.
+ */
+const char* avb_strstr(const char* haystack,
+                       const char* needle) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Finds the first occurrence of |str| in the NULL-terminated string
+ * array |strings|. Each element in |strings| must be
+ * NUL-terminated. The string given by |str| need not be
+ * NUL-terminated but its size must be given in |str_size|.
+ *
+ * Returns NULL if not found, otherwise points into |strings| for the
+ * first occurrence of |str|.
+ */
+const char* avb_strv_find_str(const char* const* strings,
+                              const char* str,
+                              size_t str_size);
+
+/* Replaces all occurrences of |search| with |replace| in |str|.
+ *
+ * Returns a newly allocated string or NULL if out of memory.
+ */
+char* avb_replace(const char* str,
+                  const char* search,
+                  const char* replace) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Calculates the CRC-32 for data in |buf| of size |buf_size|. */
+uint32_t avb_crc32(const uint8_t* buf, size_t buf_size);
+
+/* Returns the basename of |str|. This is defined as the last path
+ * component, assuming the normal POSIX separator '/'. If there are no
+ * separators, returns |str|.
+ */
+const char* avb_basename(const char* str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_UTIL_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_vbmeta_image.c b/platform/msm_shared/avb/libavb/avb_vbmeta_image.c
new file mode 100644
index 0000000..b95d8b6
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_vbmeta_image.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_vbmeta_image.h"
+#include "avb_crypto.h"
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_version.h"
+
+AvbVBMetaVerifyResult avb_vbmeta_image_verify(
+    const uint8_t* data,
+    size_t length,
+    const uint8_t** out_public_key_data,
+    size_t* out_public_key_length) {
+  AvbVBMetaVerifyResult ret;
+  AvbVBMetaImageHeader h;
+  uint8_t* computed_hash = NULL;
+  uint8_t *comp_hash = NULL;
+  const AvbAlgorithmData* algorithm;
+  AvbSHA512Ctx sha512_ctx;
+  const uint8_t* header_block;
+  const uint8_t* authentication_block;
+  const uint8_t* auxiliary_block;
+  int verification_result;
+  uint32_t total_len;
+  uint8_t *tbuf;
+
+  ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
+
+  if (out_public_key_data != NULL) {
+    *out_public_key_data = NULL;
+  }
+  if (out_public_key_length != NULL) {
+    *out_public_key_length = 0;
+  }
+
+  /* Ensure magic is correct. */
+  if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+    avb_error("Magic is incorrect.\n");
+    goto out;
+  }
+
+  /* Before we byteswap, ensure length is long enough. */
+  if (length < sizeof(AvbVBMetaImageHeader)) {
+    avb_error("Length is smaller than header.\n");
+    goto out;
+  }
+  avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
+                                             &h);
+
+  /* Ensure we don't attempt to access any fields if we do not meet
+   * the specified minimum version of libavb.
+   */
+  if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
+      (h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
+    avb_error("Mismatch between image version and libavb version.\n");
+    ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
+    goto out;
+  }
+
+  /* Ensure |release_string| ends with a NUL byte. */
+  if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
+    avb_error("Release string does not end with a NUL byte.\n");
+    goto out;
+  }
+
+  /* Ensure inner block sizes are multiple of 64. */
+  if ((h.authentication_data_block_size & 0x3f) != 0 ||
+      (h.auxiliary_data_block_size & 0x3f) != 0) {
+    avb_error("Block size is not a multiple of 64.\n");
+    goto out;
+  }
+
+  /* Ensure block sizes all add up to at most |length|. */
+  uint64_t block_total = sizeof(AvbVBMetaImageHeader);
+  if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
+      !avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
+    avb_error("Overflow while computing size of boot image.\n");
+    goto out;
+  }
+  if (block_total > length) {
+    avb_error("Block sizes add up to more than given length.\n");
+    goto out;
+  }
+
+  uintptr_t data_ptr = (uintptr_t)data;
+  /* Ensure passed in memory doesn't wrap. */
+  if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
+    avb_error("Boot image location and length mismatch.\n");
+    goto out;
+  }
+
+  /* Ensure hash and signature are entirely in the Authentication data block. */
+  uint64_t hash_end;
+  if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
+      hash_end > h.authentication_data_block_size) {
+    avb_error("Hash is not entirely in its block.\n");
+    goto out;
+  }
+  uint64_t signature_end;
+  if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
+      signature_end > h.authentication_data_block_size) {
+    avb_error("Signature is not entirely in its block.\n");
+    goto out;
+  }
+
+  /* Ensure public key is entirely in the Auxiliary data block. */
+  uint64_t pubkey_end;
+  if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
+      pubkey_end > h.auxiliary_data_block_size) {
+    avb_error("Public key is not entirely in its block.\n");
+    goto out;
+  }
+
+  /* Ensure public key metadata (if set) is entirely in the Auxiliary
+   * data block. */
+  if (h.public_key_metadata_size > 0) {
+    uint64_t pubkey_md_end;
+    if (!avb_safe_add(&pubkey_md_end,
+                      h.public_key_metadata_offset,
+                      h.public_key_metadata_size) ||
+        pubkey_md_end > h.auxiliary_data_block_size) {
+      avb_error("Public key metadata is not entirely in its block.\n");
+      goto out;
+    }
+  }
+
+  /* Bail early if there's no hash or signature. */
+  if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
+    ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
+    goto out;
+  }
+
+  /* Ensure algorithm field is supported. */
+  algorithm = avb_get_algorithm_data(h.algorithm_type);
+  if (!algorithm) {
+    avb_error("Invalid or unknown algorithm.\n");
+    goto out;
+  }
+
+  /* Bail if the embedded hash size doesn't match the chosen algorithm. */
+  if (h.hash_size != algorithm->hash_len) {
+    avb_error("Embedded hash has wrong size.\n");
+    goto out;
+  }
+
+  /* No overflow checks needed from here-on after since all block
+   * sizes and offsets have been verified above.
+   */
+
+  header_block = data;
+  authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
+  auxiliary_block = authentication_block + h.authentication_data_block_size;
+
+  switch (h.algorithm_type) {
+    /* Explicit fall-through: */
+    case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
+    case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
+    case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
+      total_len = sizeof(AvbVBMetaImageHeader) + h.auxiliary_data_block_size;
+      tbuf = avb_malloc_(total_len);
+      computed_hash = avb_malloc_(AVB_SHA256_DIGEST_SIZE);
+      avb_memcpy(tbuf, header_block, sizeof(AvbVBMetaImageHeader));
+      avb_memcpy(tbuf + sizeof(AvbVBMetaImageHeader), auxiliary_block, h.auxiliary_data_block_size);
+      hash_find(tbuf, total_len, computed_hash, CRYPTO_AUTH_ALG_SHA256);
+      avb_free(tbuf);
+      break;
+    /* Explicit fall-through: */
+    case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
+    case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
+    case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
+      computed_hash = avb_malloc(AVB_SHA512_DIGEST_SIZE);
+      avb_sha512_init(&sha512_ctx);
+      avb_sha512_update(
+          &sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
+      avb_sha512_update(
+          &sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
+      comp_hash = avb_sha512_final(&sha512_ctx);
+      avb_memcpy(computed_hash, comp_hash, AVB_SHA512_DIGEST_SIZE);
+      break;
+    default:
+      avb_error("Unknown algorithm.\n");
+      goto out;
+  }
+
+  if (avb_safe_memcmp(authentication_block + h.hash_offset,
+                      computed_hash,
+                      h.hash_size) != 0) {
+    avb_error("Hash does not match!\n");
+    ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
+    goto out;
+  }
+
+  verification_result =
+      avb_rsa_verify(auxiliary_block + h.public_key_offset,
+                     h.public_key_size,
+                     authentication_block + h.signature_offset,
+                     h.signature_size,
+                     authentication_block + h.hash_offset,
+                     h.hash_size,
+                     algorithm->padding,
+                     algorithm->padding_len);
+
+  if (verification_result == 0) {
+    ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
+    goto out;
+  }
+
+  if (h.public_key_size > 0) {
+    if (out_public_key_data != NULL) {
+      *out_public_key_data = auxiliary_block + h.public_key_offset;
+    }
+    if (out_public_key_length != NULL) {
+      *out_public_key_length = h.public_key_size;
+    }
+  }
+
+  ret = AVB_VBMETA_VERIFY_RESULT_OK;
+
+out:
+  if (computed_hash)
+    avb_free(computed_hash);
+  return ret;
+}
+
+void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
+                                                AvbVBMetaImageHeader* dest) {
+  avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
+
+  dest->required_libavb_version_major =
+      avb_be32toh(dest->required_libavb_version_major);
+  dest->required_libavb_version_minor =
+      avb_be32toh(dest->required_libavb_version_minor);
+
+  dest->authentication_data_block_size =
+      avb_be64toh(dest->authentication_data_block_size);
+  dest->auxiliary_data_block_size =
+      avb_be64toh(dest->auxiliary_data_block_size);
+
+  dest->algorithm_type = avb_be32toh(dest->algorithm_type);
+
+  dest->hash_offset = avb_be64toh(dest->hash_offset);
+  dest->hash_size = avb_be64toh(dest->hash_size);
+
+  dest->signature_offset = avb_be64toh(dest->signature_offset);
+  dest->signature_size = avb_be64toh(dest->signature_size);
+
+  dest->public_key_offset = avb_be64toh(dest->public_key_offset);
+  dest->public_key_size = avb_be64toh(dest->public_key_size);
+
+  dest->public_key_metadata_offset =
+      avb_be64toh(dest->public_key_metadata_offset);
+  dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
+
+  dest->descriptors_offset = avb_be64toh(dest->descriptors_offset);
+  dest->descriptors_size = avb_be64toh(dest->descriptors_size);
+
+  dest->rollback_index = avb_be64toh(dest->rollback_index);
+  dest->flags = avb_be32toh(dest->flags);
+}
+
+const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
+  const char* ret = NULL;
+
+  switch (result) {
+    case AVB_VBMETA_VERIFY_RESULT_OK:
+      ret = "OK";
+      break;
+    case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
+      ret = "OK_NOT_SIGNED";
+      break;
+    case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
+      ret = "INVALID_VBMETA_HEADER";
+      break;
+    case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
+      ret = "UNSUPPORTED_VERSION";
+      break;
+    case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
+      ret = "HASH_MISMATCH";
+      break;
+    case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
+      ret = "SIGNATURE_MISMATCH";
+      break;
+      /* Do not add a 'default:' case here because of -Wswitch. */
+  }
+
+  if (ret == NULL) {
+    avb_error("Unknown AvbVBMetaVerifyResult value.\n");
+    ret = "(unknown)";
+  }
+
+  return ret;
+}
diff --git a/platform/msm_shared/avb/libavb/avb_vbmeta_image.h b/platform/msm_shared/avb/libavb/avb_vbmeta_image.h
new file mode 100644
index 0000000..d0c9f15
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_vbmeta_image.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_VBMETA_IMAGE_H_
+#define AVB_VBMETA_IMAGE_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_descriptor.h"
+
+/* Size of the vbmeta image header. */
+#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
+
+/* Magic for the vbmeta image header. */
+#define AVB_MAGIC "AVB0"
+#define AVB_MAGIC_LEN 4
+
+/* Maximum size of the release string including the terminating NUL byte. */
+#define AVB_RELEASE_STRING_SIZE 48
+
+/* Flags for the vbmeta image.
+ *
+ * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED: If this flag is set,
+ * hashtree image verification will be disabled.
+ *
+ * AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set,
+ * verification will be disabled and descriptors will not be parsed.
+ */
+typedef enum {
+  AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),
+  AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)
+} AvbVBMetaImageFlags;
+
+/* Binary format for header of the vbmeta image.
+ *
+ * The vbmeta image consists of three blocks:
+ *
+ *  +-----------------------------------------+
+ *  | Header data - fixed size                |
+ *  +-----------------------------------------+
+ *  | Authentication data - variable size     |
+ *  +-----------------------------------------+
+ *  | Auxiliary data - variable size          |
+ *  +-----------------------------------------+
+ *
+ * The "Header data" block is described by this struct and is always
+ * |AVB_VBMETA_IMAGE_HEADER_SIZE| bytes long.
+ *
+ * The "Authentication data" block is |authentication_data_block_size|
+ * bytes long and contains the hash and signature used to authenticate
+ * the vbmeta image. The type of the hash and signature is defined by
+ * the |algorithm_type| field.
+ *
+ * The "Auxiliary data" is |auxiliary_data_block_size| bytes long and
+ * contains the auxiliary data including the public key used to make
+ * the signature and descriptors.
+ *
+ * The public key is at offset |public_key_offset| with size
+ * |public_key_size| in this block. The size of the public key data is
+ * defined by the |algorithm_type| field. The format of the public key
+ * data is described in the |AvbRSAPublicKeyHeader| struct.
+ *
+ * The descriptors starts at |descriptors_offset| from the beginning
+ * of the "Auxiliary Data" block and take up |descriptors_size|
+ * bytes. Each descriptor is stored as a |AvbDescriptor| with tag and
+ * number of bytes following. The number of descriptors can be
+ * determined by walking this data until |descriptors_size| is
+ * exhausted.
+ *
+ * The size of each of the "Authentication data" and "Auxiliary data"
+ * blocks must be divisible by 64. This is to ensure proper alignment.
+ *
+ * Descriptors are free-form blocks stored in a part of the vbmeta
+ * image subject to the same integrity checks as the rest of the
+ * image. See the documentation for |AvbDescriptor| for well-known
+ * descriptors. See avb_descriptor_foreach() for a convenience
+ * function to iterate over descriptors.
+ *
+ * This struct is versioned, see the |required_libavb_version_major|
+ * and |required_libavb_version_minor| fields. This represents the
+ * minimum version of libavb required to verify the header and depends
+ * on the features (e.g. algorithms, descriptors) used. Note that this
+ * may be 1.0 even if generated by an avbtool from 1.4 but where no
+ * features introduced after 1.0 has been used. See the "Versioning
+ * and compatibility" section in the README.md file for more details.
+ *
+ * All fields are stored in network byte order when serialized. To
+ * generate a copy with fields swapped to native byte order, use the
+ * function avb_vbmeta_image_header_to_host_byte_order().
+ *
+ * Before reading and/or using any of this data, you MUST verify it
+ * using avb_vbmeta_image_verify() and reject it unless it's signed by
+ * a known good public key.
+ */
+typedef struct AvbVBMetaImageHeader {
+  /*   0: Four bytes equal to "AVB0" (AVB_MAGIC). */
+  uint8_t magic[AVB_MAGIC_LEN];
+
+  /*   4: The major version of libavb required for this header. */
+  uint32_t required_libavb_version_major;
+  /*   8: The minor version of libavb required for this header. */
+  uint32_t required_libavb_version_minor;
+
+  /*  12: The size of the signature block. */
+  uint64_t authentication_data_block_size;
+  /*  20: The size of the auxiliary data block. */
+  uint64_t auxiliary_data_block_size;
+
+  /*  28: The verification algorithm used, see |AvbAlgorithmType| enum. */
+  uint32_t algorithm_type;
+
+  /*  32: Offset into the "Authentication data" block of hash data. */
+  uint64_t hash_offset;
+  /*  40: Length of the hash data. */
+  uint64_t hash_size;
+
+  /*  48: Offset into the "Authentication data" block of signature data. */
+  uint64_t signature_offset;
+  /*  56: Length of the signature data. */
+  uint64_t signature_size;
+
+  /*  64: Offset into the "Auxiliary data" block of public key data. */
+  uint64_t public_key_offset;
+  /*  72: Length of the public key data. */
+  uint64_t public_key_size;
+
+  /*  80: Offset into the "Auxiliary data" block of public key metadata. */
+  uint64_t public_key_metadata_offset;
+  /*  88: Length of the public key metadata. Must be set to zero if there
+   *  is no public key metadata.
+   */
+  uint64_t public_key_metadata_size;
+
+  /*  96: Offset into the "Auxiliary data" block of descriptor data. */
+  uint64_t descriptors_offset;
+  /* 104: Length of descriptor data. */
+  uint64_t descriptors_size;
+
+  /* 112: The rollback index which can be used to prevent rollback to
+   *  older versions.
+   */
+  uint64_t rollback_index;
+
+  /* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
+   * set to zero if the vbmeta image is not a top-level image.
+   */
+  uint32_t flags;
+
+  /* 124: Reserved to ensure |release_string| start on a 16-byte
+   * boundary. Must be set to zeroes.
+   */
+  uint8_t reserved0[4];
+
+  /* 128: The release string from avbtool, e.g. "avbtool 1.0.0" or
+   * "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL
+   * terminated. Applications must not make assumptions about how this
+   * string is formatted.
+   */
+  uint8_t release_string[AVB_RELEASE_STRING_SIZE];
+
+  /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
+   * bytes. This must be set to zeroes.
+   */
+  uint8_t reserved[80];
+} AVB_ATTR_PACKED AvbVBMetaImageHeader;
+
+/* Copies |src| to |dest|, byte-swapping fields in the process.
+ *
+ * Make sure you've verified |src| using avb_vbmeta_image_verify()
+ * before accessing the data and/or using this function.
+ */
+void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
+                                                AvbVBMetaImageHeader* dest);
+
+/* Return codes used in avb_vbmeta_image_verify().
+ *
+ * AVB_VBMETA_VERIFY_RESULT_OK is returned if the vbmeta image header
+ * is valid, the hash is correct and the signature is correct. Keep in
+ * mind that you still need to check that you know the public key used
+ * to sign the image, see avb_vbmeta_image_verify() for details.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED is returned if the vbmeta
+ * image header is valid but there is no signature or hash.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER is returned if the
+ * header of the vbmeta image is invalid, for example, invalid magic
+ * or inconsistent data.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION is returned if a) the
+ * vbmeta image requires a minimum version of libavb which exceeds the
+ * version of libavb used; or b) the vbmeta image major version
+ * differs from the major version of libavb in use.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH is returned if the hash
+ * stored in the "Authentication data" block does not match the
+ * calculated hash.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH is returned if the
+ * signature stored in the "Authentication data" block is invalid or
+ * doesn't match the public key stored in the vbmeta image.
+ */
+typedef enum {
+  AVB_VBMETA_VERIFY_RESULT_OK,
+  AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED,
+  AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
+  AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION,
+  AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
+  AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH,
+} AvbVBMetaVerifyResult;
+
+/* Get a textual representation of |result|. */
+const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result);
+
+/* Checks that vbmeta image at |data| of size |length| is a valid
+ * vbmeta image. The complete contents of the vbmeta image must be
+ * passed in. It's fine if |length| is bigger than the actual image,
+ * typically callers of this function will load the entire contents of
+ * the 'vbmeta_a' or 'vbmeta_b' partition and pass in its length (for
+ * example, 1 MiB).
+ *
+ * See the |AvbVBMetaImageHeader| struct for information about the
+ * three blocks (header, authentication, auxiliary) that make up a
+ * vbmeta image.
+ *
+ * If the function returns |AVB_VBMETA_VERIFY_RESULT_OK| and
+ * |out_public_key_data| is non-NULL, it will be set to point inside
+ * |data| for where the serialized public key data is stored and
+ * |out_public_key_length|, if non-NULL, will be set to the length of
+ * the public key data. If there is no public key in the metadata then
+ * |out_public_key_data| is set to NULL.
+ *
+ * See the |AvbVBMetaVerifyResult| enum for possible return values.
+ *
+ * VERY IMPORTANT:
+ *
+ *   1. Even if |AVB_VBMETA_VERIFY_RESULT_OK| is returned, you still
+ *      need to check that the public key embedded in the image
+ *      matches a known key! You can use 'avbtool extract_public_key'
+ *      to extract the key (at build time, then store it along your
+ *      code) and compare it to what is returned in
+ *      |out_public_key_data|.
+ *
+ *   2. You need to check the |rollback_index| field against a stored
+ *      value in NVRAM and reject the vbmeta image if the value in
+ *      NVRAM is bigger than |rollback_index|. You must also update
+ *      the value stored in NVRAM to the smallest value of
+ *      |rollback_index| field from boot images in all bootable and
+ *      authentic slots marked as GOOD.
+ *
+ * This is a low-level function to only verify the vbmeta data - you
+ * are likely looking for avb_slot_verify() instead for verifying
+ * integrity data for a whole set of partitions.
+ */
+AvbVBMetaVerifyResult avb_vbmeta_image_verify(
+    const uint8_t* data,
+    size_t length,
+    const uint8_t** out_public_key_data,
+    size_t* out_public_key_length) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_VBMETA_IMAGE_H_ */
diff --git a/platform/msm_shared/avb/libavb/avb_version.c b/platform/msm_shared/avb/libavb/avb_version.c
new file mode 100644
index 0000000..31f5fa6
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_version.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_version.h"
+
+#define AVB_QUOTE(str) #str
+#define AVB_EXPAND_AND_QUOTE(str) AVB_QUOTE(str)
+
+/* Keep in sync with get_release_string() in avbtool. */
+const char* avb_version_string(void) {
+  return AVB_EXPAND_AND_QUOTE(AVB_VERSION_MAJOR) "." AVB_EXPAND_AND_QUOTE(
+      AVB_VERSION_MINOR) "." AVB_EXPAND_AND_QUOTE(AVB_VERSION_SUB);
+}
diff --git a/platform/msm_shared/avb/libavb/avb_version.h b/platform/msm_shared/avb/libavb/avb_version.h
new file mode 100644
index 0000000..9d92970
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/avb_version.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_VERSION_H_
+#define AVB_VERSION_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The version number of AVB - keep in sync with avbtool. */
+#define AVB_VERSION_MAJOR 1
+#define AVB_VERSION_MINOR 0
+#define AVB_VERSION_SUB 0
+
+/* Returns a NUL-terminated string for the libavb version in use.  The
+ * returned string usually looks like "%d.%d.%d". Applications must
+ * not make assumptions about the content of this string.
+ *
+ * Boot loaders should display this string in debug/diagnostics output
+ * to aid with debugging.
+ *
+ * This is similar to the string put in the |release_string| string
+ * field in the VBMeta struct by avbtool.
+ */
+const char* avb_version_string(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_VERSION_H_ */
diff --git a/platform/msm_shared/avb/libavb/libavb.h b/platform/msm_shared/avb/libavb/libavb.h
new file mode 100644
index 0000000..d511584
--- /dev/null
+++ b/platform/msm_shared/avb/libavb/libavb.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef LIBAVB_H_
+#define LIBAVB_H_
+
+/* The AVB_INSIDE_LIBAVB_H preprocessor symbol is used to enforce
+ * library users to include only this file. All public interfaces, and
+ * only public interfaces, must be included here.
+ */
+
+#define AVB_INSIDE_LIBAVB_H
+#include "avb_chain_partition_descriptor.h"
+#include "avb_crypto.h"
+#include "avb_descriptor.h"
+#include "avb_footer.h"
+#include "avb_hash_descriptor.h"
+#include "avb_hashtree_descriptor.h"
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_ops.h"
+#include "avb_property_descriptor.h"
+#include "avb_slot_verify.h"
+#include "avb_sysdeps.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+#include "avb_version.h"
+#undef AVB_INSIDE_LIBAVB_H
+
+#endif /* LIBAVB_H_ */
diff --git a/platform/msm_shared/avb/rules.mk b/platform/msm_shared/avb/rules.mk
new file mode 100644
index 0000000..6795e1d
--- /dev/null
+++ b/platform/msm_shared/avb/rules.mk
@@ -0,0 +1,25 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+INCLUDES += -I$(LK_TOP_DIR)/include -I$(LK_TOP_DIR)/app/aboot -I$(LK_TOP_DIR)/platform/msm_shared -I$(LK_TOP_DIR)/platform/msm_shared/avb -I$(LK_TOP_DIR)/platform/msm_shared/include \
+
+CFLAGS += -DAVB_COMPILATION
+
+OBJS += $(LOCAL_DIR)/libavb/avb_chain_partition_descriptor.o \
+		$(LOCAL_DIR)/libavb/avb_crc32.o \
+		$(LOCAL_DIR)/libavb/avb_crypto.o \
+		$(LOCAL_DIR)/libavb/avb_descriptor.o \
+		$(LOCAL_DIR)/libavb/avb_footer.o \
+		$(LOCAL_DIR)/libavb/avb_hash_descriptor.o \
+		$(LOCAL_DIR)/libavb/avb_hashtree_descriptor.o \
+		$(LOCAL_DIR)/libavb/avb_kernel_cmdline_descriptor.o \
+		$(LOCAL_DIR)/libavb/avb_property_descriptor.o \
+		$(LOCAL_DIR)/libavb/avb_ops.o \
+		$(LOCAL_DIR)/libavb/avb_rsa.o \
+		$(LOCAL_DIR)/libavb/avb_sha256.o \
+		$(LOCAL_DIR)/libavb/avb_sha512.o \
+		$(LOCAL_DIR)/libavb/avb_slot_verify.o \
+		$(LOCAL_DIR)/libavb/avb_sysdeps_posix.o \
+		$(LOCAL_DIR)/libavb/avb_vbmeta_image.o \
+		$(LOCAL_DIR)/libavb/avb_util.o \
+		$(LOCAL_DIR)/libavb/avb_version.o \
+		$(LOCAL_DIR)/VerifiedBoot.o \
diff --git a/platform/msm_shared/boot_verifier.c b/platform/msm_shared/boot_verifier.c
index 76e8a50..95feec5 100644
--- a/platform/msm_shared/boot_verifier.c
+++ b/platform/msm_shared/boot_verifier.c
@@ -459,7 +459,7 @@
 	uint32_t boot_device_state = boot_verify_get_state();
 	int app_handle = 0;
 	uint32_t len_oem_rsa = 0, len_from_cert = 0;
-	km_set_rot_req_t *read_req;
+	km_set_rot_req_t *read_req = NULL;
 	km_set_rot_rsp_t read_rsp;
 	app_handle = get_secapp_handle();
 	int n = 0, e = 0;
@@ -587,7 +587,8 @@
 	return fp;
 }
 
-bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname)
+bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname,
+			uint32_t *bootstate)
 {
 	bool ret = false;
 	X509 *cert = NULL;
@@ -646,6 +647,10 @@
 
 	if(sig != NULL)
 		VERIFIED_BOOT_SIG_free(sig);
+	*bootstate = dev_boot_state;
+	if(bootstate == NULL)
+		goto verify_image_error;
+
 verify_image_error:
 	free(signature);
 	return ret;
diff --git a/platform/msm_shared/display.c b/platform/msm_shared/display.c
index cf4db48..780ecfc 100644
--- a/platform/msm_shared/display.c
+++ b/platform/msm_shared/display.c
@@ -257,6 +257,9 @@
 		ret = mdss_spi_on(pinfo, &(panel->fb));
 		if (ret)
 			goto msm_display_on_out;
+		ret = mdss_spi_cmd_post_on(pinfo);
+		if (ret)
+			goto msm_display_on_out;
 		break;
 #endif
 #ifdef DISPLAY_TYPE_QPIC
diff --git a/platform/msm_shared/display_menu.c b/platform/msm_shared/display_menu.c
index 8b74c9a..c9a58a8 100644
--- a/platform/msm_shared/display_menu.c
+++ b/platform/msm_shared/display_menu.c
@@ -78,7 +78,7 @@
 static bool is_thread_start = false;
 static struct select_msg_info msg_info;
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 struct boot_verify_info {
 	int msg_type;
 	const char *warning_msg;
@@ -248,7 +248,7 @@
 	unlock_msg_info->info.option_index= 2;
 }
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 /* msg_lock need to be holded when call this function. */
 void display_bootverify_menu_renew(struct select_msg_info *msg_info, int type)
 {
@@ -525,7 +525,7 @@
 	display_menu_thread_start(fastboot_menu_msg_info);
 }
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 void display_bootverify_menu(int type)
 {
 	struct select_msg_info *bootverify_menu_msg_info;
diff --git a/platform/msm_shared/include/ab_partition_parser.h b/platform/msm_shared/include/ab_partition_parser.h
index 34520ac..607a412 100644
--- a/platform/msm_shared/include/ab_partition_parser.h
+++ b/platform/msm_shared/include/ab_partition_parser.h
@@ -27,11 +27,18 @@
  *
  */
 #include <fastboot.h>
+#include <err.h>
 
 extern const char *suffix_slot[];
 extern const char *suffix_delimiter;
 
 #define SUFFIX_SLOT(part_slot) suffix_slot[(part_slot)]
+#define MAX_SLOT_SUFFIX_SZ      3
+#define BOOT_DEV_NAME_SIZE_MAX 10
+
+typedef struct {
+	char Suffix[MAX_SLOT_SUFFIX_SZ];
+}Slot;
 #define SET_BIT(p,n) ((p) |= ((uint64_t)0x1 << (n)))
 #define CLR_BIT(p,n) ((p) &= (~(((uint64_t)0x1) << (n))))
 
diff --git a/platform/msm_shared/include/boot_device.h b/platform/msm_shared/include/boot_device.h
index 7d2451a..8fe4463 100644
--- a/platform/msm_shared/include/boot_device.h
+++ b/platform/msm_shared/include/boot_device.h
@@ -55,10 +55,40 @@
 };
 #endif
 
+#define MAX_NUMBER_OF_LOADED_IMAGES 32
+#ifndef MAX_GPT_NAME_SIZE
+#define MAX_GPT_NAME_SIZE 72
+#endif
+
+typedef struct {
+	char *name;
+	void *image_buffer;
+	uint32_t imgsize;
+} imagedata;
+
+typedef struct bootinfo {
+	int multi_slot_boot;
+	bool bootinto_recovery;
+	bool bootreason_alarm;
+	char pname[MAX_GPT_NAME_SIZE];
+	char bootable_slot[MAX_GPT_NAME_SIZE];
+	imagedata images[MAX_NUMBER_OF_LOADED_IMAGES];
+	uint32_t num_loaded_images;
+	uint32_t boot_state;
+	char *vbcmdline;
+	uint32_t vbcmdline_len;
+	uint32_t vbcmdline_filled_len;
+	void *vb_data;
+} bootinfo;
+
+int getimage(const bootinfo *Info, void **image_buffer, uint32_t *imgsize,
+                    char *imgname);
+
 void platform_read_boot_config();
 uint32_t platform_get_boot_dev();
 uint32_t platform_boot_dev_isemmc();
 void platform_boot_dev_cmdline(char *buf);
+int get_boot_image_info(void **image_buffer, uint32_t *imgsize,char *imgname);
 
 void *target_mmc_device();
 #endif
diff --git a/platform/msm_shared/include/boot_verifier.h b/platform/msm_shared/include/boot_verifier.h
index 1f74d0b..9bf34b6 100644
--- a/platform/msm_shared/include/boot_verifier.h
+++ b/platform/msm_shared/include/boot_verifier.h
@@ -136,6 +136,7 @@
 	ORANGE,
 	YELLOW,
 	RED,
+	BOOT_STATE_MAX = (uint32_t)0xFFFFFFFF,
 };
 
 struct verified_boot_verity_mode
@@ -164,7 +165,7 @@
 /* Function to initialize keystore */
 uint32_t boot_verify_keystore_init();
 /* Function to verify boot/recovery image */
-bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname);
+bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname, uint32_t *bs);
 /* Function to send event to boot state machine */
 void boot_verify_send_event(uint32_t event);
 /* Read current boot state */
diff --git a/platform/msm_shared/include/mdp4.h b/platform/msm_shared/include/mdp4.h
index 8bbb3a7..b27e363 100644
--- a/platform/msm_shared/include/mdp4.h
+++ b/platform/msm_shared/include/mdp4.h
@@ -128,4 +128,5 @@
 int mdss_spi_init(void);
 int mdss_spi_panel_init(struct msm_panel_info *pinfo);
 int mdss_spi_on(struct msm_panel_info *pinfo, struct fbcon_config *fb);
+int mdss_spi_cmd_post_on(struct msm_panel_info *pinfo);
 #endif
diff --git a/platform/msm_shared/include/verifiedboot.h b/platform/msm_shared/include/verifiedboot.h
new file mode 100644
index 0000000..9e16982
--- /dev/null
+++ b/platform/msm_shared/include/verifiedboot.h
@@ -0,0 +1,170 @@
+/* Copyright (c) 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ *  with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __VERIFIEDBOOT_H__
+#define __VERIFIEDBOOT_H__
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <mmc.h>
+#include <platform.h>
+#include <devinfo.h>
+#include <meta_format.h>
+#include <boot_device.h>
+#include <boot_verifier.h>
+#include <target.h>
+
+typedef enum {
+	NO_AVB	= 0,
+	AVB_1,
+	AVB_2,
+	AVB_LE
+} avb_versions;
+
+#define VB_SHA256_SIZE  32
+#define LE_BOOTIMG_SIG_SIZE 256
+#define abort() ASSERT(false);
+#define MAX_PATH_SIZE 64
+
+#define EFIERR(_a)		(-1 * (_a))
+
+#define EFI_SUCCESS               0
+#define EFI_LOAD_ERROR            EFIERR (1)
+#define EFI_INVALID_PARAMETER     EFIERR (2)
+#define EFI_UNSUPPORTED           EFIERR (3)
+#define EFI_BAD_BUFFER_SIZE       EFIERR (4)
+#define EFI_BUFFER_TOO_SMALL      EFIERR (5)
+#define EFI_NOT_READY             EFIERR (6)
+#define EFI_DEVICE_ERROR          EFIERR (7)
+#define EFI_WRITE_PROTECTED       EFIERR (8)
+#define EFI_OUT_OF_RESOURCES      EFIERR (9)
+#define EFI_VOLUME_CORRUPTED      EFIERR (10)
+#define EFI_VOLUME_FULL           EFIERR (11)
+#define EFI_NO_MEDIA              EFIERR (12)
+#define EFI_MEDIA_CHANGED         EFIERR (13)
+#define EFI_NOT_FOUND             EFIERR (14)
+#define EFI_ACCESS_DENIED         EFIERR (15)
+#define EFI_NO_RESPONSE           EFIERR (16)
+#define EFI_NO_MAPPING            EFIERR (17)
+#define EFI_TIMEOUT               EFIERR (18)
+#define EFI_NOT_STARTED           EFIERR (19)
+#define EFI_ALREADY_STARTED       EFIERR (20)
+#define EFI_ABORTED               EFIERR (21)
+#define EFI_ICMP_ERROR            EFIERR (22)
+
+#define EFI_TFTP_ERROR            EFIERR (23)
+#define EFI_PROTOCOL_ERROR        EFIERR (24)
+#define EFI_INCOMPATIBLE_VERSION  EFIERR (25)
+#define EFI_SECURITY_VIOLATION    EFIERR (26)
+#define EFI_CRC_ERROR             EFIERR (27)
+#define EFI_END_OF_MEDIA          EFIERR (28)
+#define EFI_END_OF_FILE           EFIERR (31)
+#define EFI_INVALID_LANGUAGE      EFIERR (32)
+
+#define EFI_WARN_UNKNOWN_GLYPH    EFIWARN (1)
+#define EFI_WARN_DELETE_FAILURE   EFIWARN (2)
+#define EFI_WARN_WRITE_FAILURE    EFIWARN (3)
+#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN (4)
+
+typedef int       EFI_STATUS;
+typedef bool      BOOLEAN;
+typedef char      CHAR8;
+typedef int16_t   CHAR16;
+typedef void      VOID;
+typedef uint8_t   UINT8;
+typedef uint16_t  UINT16;
+typedef uint32_t  UINT32;
+typedef uint64_t  UINT64;
+typedef int16_t   INT16;
+typedef int32_t   INT32;
+typedef int64_t   INT64;
+typedef uintptr_t UINTN;
+
+typedef enum {
+	VB_UNDEFINED_HASH	= 0,
+	VB_SHA1,
+	VB_SHA256,
+	VB_UNSUPPORTED_HASH,
+	VB_RESERVED_HASH	= 0x7fffffff /* force to 32 bits */
+} vb_hash;
+
+#define GUARD(code)                                                            \
+    do {                                                                       \
+        Status = (code);                                                       \
+        if (Status != EFI_SUCCESS) {                                           \
+            dprintf(CRITICAL, "Err: line:%d %s() status: %d\n", __LINE__,      \
+                   __FUNCTION__, Status);                                      \
+            return Status;                                                     \
+        }                                                                      \
+    } while (0)
+
+#define GUARD_OUT(code)                                                        \
+    do {                                                                       \
+        Status = (code);                                                       \
+        if (Status != EFI_SUCCESS) {                                           \
+            dprintf(CRITICAL, "Err: line:%d %s() status: %d\n", __LINE__,      \
+                   __FUNCTION__, Status);                                      \
+            goto out;                                                          \
+        }                                                                      \
+    } while (0)
+
+/* forward declare bootinfo */
+typedef struct bootinfo bootinfo;
+
+BOOLEAN VerifiedBootEnabled();
+
+/**
+ * @return  0 - AVB disabled
+ *          1 - VB 1.0
+ *          2 - VB 2.0
+ *          3 - LE VB
+ */
+UINT32 GetAVBVersion();
+
+/**
+ * Authenticates and loads boot image in
+ * Info->Images on EFI_SUCCESS.
+ * Also provides Verified Boot command
+ * arguments (if any) in Info->vbcmdline
+ *
+ * @return EFI_STATUS
+ */
+int load_image_and_auth(bootinfo *Info);
+
+/**
+ *  Free resources/memory allocated by
+ *  verified boot, image_buffer, vbcmdline
+ *  VBData...
+ *
+ * @return VOID
+ */
+void free_verified_boot_resource(bootinfo *Info);
+
+#endif /* __VERIFIEDBOOT_H__ */
diff --git a/platform/msm_shared/mdss_spi.c b/platform/msm_shared/mdss_spi.c
index 4819478..4cd5d4b 100644
--- a/platform/msm_shared/mdss_spi.c
+++ b/platform/msm_shared/mdss_spi.c
@@ -171,3 +171,32 @@
 
 	return ret;
 }
+
+int mdss_spi_cmd_post_on(struct msm_panel_info *pinfo)
+{
+	int cmd_count = 0;
+	char *payload;
+
+	if (!dev) {
+		dprintf(CRITICAL, "SPI has not been initialized\n");
+		return -ENODEV;
+	}
+
+	while (cmd_count < pinfo->spi.num_of_panel_cmds) {
+		if (pinfo->spi.panel_cmds[cmd_count].cmds_post_tg){
+			payload = pinfo->spi.panel_cmds[cmd_count].payload;
+			mdss_spi_write_cmd(payload);
+			if (pinfo->spi.panel_cmds[cmd_count].size > 1)
+				mdss_spi_write_data(payload + 1,
+					pinfo->spi.panel_cmds[cmd_count].size
+						- 1);
+
+			if (pinfo->spi.panel_cmds[cmd_count].wait)
+				mdelay(pinfo->spi.panel_cmds[cmd_count].wait);
+		}
+
+		cmd_count ++;
+	}
+
+	return SUCCESS;
+}
diff --git a/platform/msm_shared/mmc_wrapper.c b/platform/msm_shared/mmc_wrapper.c
index 495767a..f25a633 100755
--- a/platform/msm_shared/mmc_wrapper.c
+++ b/platform/msm_shared/mmc_wrapper.c
@@ -675,6 +675,7 @@
 		 */
 		if (partition_read_only(index) && size < card->wp_grp_size)
 		{
+			dprintf(CRITICAL, "WARNING: Size of partition is less than 1 Write Protect GRP size\n");
 			/* Write protect api takes the size in bytes, convert size to bytes */
 			size = card->wp_grp_size * block_size;
 		}
diff --git a/platform/msm_shared/qseecom_lk.c b/platform/msm_shared/qseecom_lk.c
index 717c2a5..d385fd5 100644
--- a/platform/msm_shared/qseecom_lk.c
+++ b/platform/msm_shared/qseecom_lk.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015,2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -47,7 +47,7 @@
 #define MAX_SCM_ARGS 10
 #define N_EXT_SCM_ARGS 7
 #define FIRST_EXT_ARG_IDX 3
-
+#define MAX_TA_PARTITION_SIZE 0x00100000
 #define N_REGISTER_ARGS (MAX_SCM_ARGS - N_EXT_SCM_ARGS + 1)
 
 #define QSEE_LOG_BUF_SIZE (4096)
@@ -551,7 +551,7 @@
 	int index = INVALID_PTN;
 	unsigned long long ptn = 0;
 	unsigned long long size = 0;
-	unsigned long long rounded_size = 0;
+	unsigned long rounded_size = 0;
 	void *buf = NULL;
 	void *req = NULL;
 	struct qseecom_load_app_ireq load_req = {0};
@@ -569,8 +569,8 @@
 	mmc_set_lun(lun);
 
 	size = partition_get_size(index);
-	if ((ULLONG_MAX - PAGE_SIZE + 1) < size) {
-		dprintf(CRITICAL, "Integer overflow detected in rounding up the partition size!");
+	if (MAX_TA_PARTITION_SIZE < size) {
+		dprintf(CRITICAL, "Invalid TA partition size!");
 		ret = GENERIC_ERROR;
 		goto err;
 	}
@@ -626,7 +626,7 @@
 	int index = INVALID_PTN;
 	unsigned long long ptn = 0;
 	unsigned long long size = 0;
-	unsigned long long rounded_size = 0;
+	unsigned  long rounded_size = 0;
 	void *buf = NULL;
 	void *req = NULL;
 	struct qseecom_load_app_ireq load_req = {0};
@@ -640,8 +640,8 @@
 	mmc_set_lun(lun);
 
 	size = partition_get_size(index);
-	if ((ULLONG_MAX - PAGE_SIZE + 1) < size) {
-		dprintf(CRITICAL, "Integer overflow detected in rounding up the partition size!");
+	if (MAX_TA_PARTITION_SIZE < size) {
+		dprintf(CRITICAL, "Invalid cmnlib partition size!");
 		ret = GENERIC_ERROR;
 		goto err;
 	}
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index f8460ff..82c7d88 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -698,3 +698,8 @@
 ifeq ($(ENABLE_RPMB_SUPPORT), 1)
 include platform/msm_shared/rpmb/rules.mk
 endif
+
+ifeq ($(VERIFIED_BOOT_2), 1)
+OBJS += platform/msm_shared/boot_verifier.o
+endif
+include platform/msm_shared/avb/rules.mk
diff --git a/platform/msm_shared/scm.c b/platform/msm_shared/scm.c
index 6b4af41..bd32e2c 100644
--- a/platform/msm_shared/scm.c
+++ b/platform/msm_shared/scm.c
@@ -37,6 +37,8 @@
 #include <dload_util.h>
 #include <platform/iomap.h>
 #include <board.h>
+#include <qseecomi_lk.h>
+#include <qseecom_lk_api.h>
 #include "scm.h"
 
 #pragma GCC optimize ("O0")
@@ -1282,12 +1284,15 @@
 	}
 
 	if (!ret) {
-		/* Check for secure device: Bit#0 = 0, Bit#1 = 0 Bit#2 = 0 , Bit#5 = 0 , Bit#6 = 1 */
+		/* Check for secure device: Bit#0 = 0, Bit#1 = 0 Bit#2 = 0 , Bit#5 = 0 */
+		/* Check Bit#6 = 1 only for TZ.BF.4.0 */
         	if (!CHECK_BIT(resp[0], SECBOOT_FUSE_BIT) && !CHECK_BIT(resp[0], SECBOOT_FUSE_SHK_BIT) &&
         		!CHECK_BIT(resp[0], SECBOOT_FUSE_DEBUG_DISABLED_BIT) &&
-        		!CHECK_BIT(resp[0], SECBOOT_FUSE_RPMB_ENABLED_BIT) &&
-        		CHECK_BIT(resp[0], SECBOOT_FUSE_DEBUG_RE_ENABLED_BIT)) {
-        		secure_boot_enabled = true;
+                        !CHECK_BIT(resp[0], SECBOOT_FUSE_RPMB_ENABLED_BIT)) {
+                        if ((qseecom_get_version() < QSEE_VERSION_40))
+	                        secure_boot_enabled = true;
+                        else if (CHECK_BIT(resp[0], SECBOOT_FUSE_DEBUG_RE_ENABLED_BIT))
+	                        secure_boot_enabled = true;
         	}
 		/* Bit 2 - DEBUG_DISABLE_CHECK */
 		if (CHECK_BIT(resp[0], SECBOOT_FUSE_DEBUG_DISABLED_BIT))
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index c8a3e48..7f0095b 100644
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -469,7 +469,9 @@
 	MDM9206 = 322,
 	SDA450 = 351,
 	SDM632 = 349,
-	SDA632 = 350
+	SDA632 = 350,
+	SDM429 = 354,
+	SDM439 = 353
 };
 
 enum platform {
diff --git a/project/msm8909.mk b/project/msm8909.mk
index 07815f2..30cf2d9 100644
--- a/project/msm8909.mk
+++ b/project/msm8909.mk
@@ -109,5 +109,10 @@
 DEFINES += FBCON_DISPLAY_MSG=1
 endif
 
+#Increase TZ apps region to 2 MB due to KM 3.0 support
+ifeq ($(QSEECOM_SECAPP_REGION_2MB),1)
+ DEFINES += QSEECOM_SECAPP_REGION_2MB=1
+endif
+
 #enable battery voltage check
 DEFINES += CHECK_BAT_VOLTAGE=1
diff --git a/project/msm8952.mk b/project/msm8952.mk
index ee9063c..d40dfa1 100644
--- a/project/msm8952.mk
+++ b/project/msm8952.mk
@@ -14,6 +14,10 @@
 
 EMMC_BOOT := 1
 
+ifeq ($(ENABLE_DISPLAY),1)
+DEFINES += ENABLE_DISPLAY=1
+DEFINES += DISPLAY_SPLASH_SCREEN=1
+endif
 
 ifeq ($(VERIFIED_BOOT),1)
 ENABLE_MDTP_SUPPORT := 1
@@ -115,3 +119,7 @@
 
 #enable battery voltage check
 DEFINES += CHECK_BAT_VOLTAGE=1
+
+#Use PON register for reboot reason
+ENABLE_REBOOT_MODULE := 1
+DEFINES += USE_PON_REBOOT_REG=1
diff --git a/project/msm8953.mk b/project/msm8953.mk
index 039e60e..f9a9644 100644
--- a/project/msm8953.mk
+++ b/project/msm8953.mk
@@ -19,15 +19,23 @@
 DEFINES += DISPLAY_SPLASH_SCREEN=1
 endif
 
-ifeq ($(VERIFIED_BOOT),1)
 ENABLE_SECAPP_LOADER := 1
 ENABLE_RPMB_SUPPORT := 1
+
+ifeq ($(VERIFIED_BOOT),1)
 ifneq (,$(findstring DISPLAY_SPLASH_SCREEN,$(DEFINES)))
 #enable fbcon display menu
 ENABLE_FBCON_DISPLAY_MSG := 1
 endif
 endif
 
+ifeq ($(VERIFIED_BOOT_2),1)
+ifneq (,$(findstring DISPLAY_SPLASH_SCREEN,$(DEFINES)))
+#enable fbcon display menu
+  ENABLE_FBCON_DISPLAY_MSG := 1
+endif
+endif
+
 ENABLE_SMD_SUPPORT := 1
 ENABLE_PWM_SUPPORT := true
 
@@ -127,4 +135,4 @@
 ENABLE_REBOOT_MODULE := 1
 
 #Use PON register for reboot reason
-DEFINES += USE_PON_REBOOT_REG=1
\ No newline at end of file
+DEFINES += USE_PON_REBOOT_REG=1
diff --git a/target/init.c b/target/init.c
index e8189cc..5ec4ab6 100644
--- a/target/init.c
+++ b/target/init.c
@@ -43,7 +43,7 @@
 #include <pm_fg_adc_usr.h>
 #endif
 
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 #include <partition_parser.h>
 #include <ab_partition_parser.h>
 #endif
@@ -62,10 +62,9 @@
 #define BATT_VOLTAGE_NUMR		122070
 #define QGAUGE_VOLTAGE_NUMR		194637
 #define BATT_VOLTAGE_DENR		1000
-
-#if VERIFIED_BOOT
+#define INVALID  -1
 static int vb_version = INVALID;
-#endif
+
 /*
  * default implementations of these routines, if the target code
  * chooses not to implement.
@@ -291,6 +290,8 @@
 		case SDA450:
 		case SDM632:
 		case SDA632:
+		case SDM429:
+		case SDM439:
 		/* SDCC HC DDR CONFIG has shifted by 4 bytes for these platform */
 			ret += 4;
 			break;
@@ -299,8 +300,7 @@
 	}
 	return ret;
 }
-
-#if VERIFIED_BOOT
+#if VERIFIED_BOOT || VERIFIED_BOOT_2
 int target_get_vb_version()
 {
 	if (vb_version == INVALID)
@@ -315,6 +315,11 @@
 	}
 	return vb_version;
 }
+#else
+int target_get_vb_version()
+{
+	return vb_version;
+}
 #endif
 
 #if VERIFIED_BOOT_LE
@@ -371,6 +376,8 @@
 		case SDA450:
 		case SDM632:
 		case SDA632:
+		case SDM429:
+		case SDM439:
 			config->vib_type = VIB_LRA_TYPE;
 			config->hap_rate_cfg1 = QPNP_HAP_RATE_CFG1_41;
 			config->hap_rate_cfg2 = QPNP_HAP_RATE_CFG2_03;
diff --git a/target/mdm9607/init.c b/target/mdm9607/init.c
index 40776f7..51172fd 100644
--- a/target/mdm9607/init.c
+++ b/target/mdm9607/init.c
@@ -97,6 +97,11 @@
 #define CE_ARRAY_SIZE           20
 #define SUB_TYPE_SKUT           0x0A
 
+__WEAK unsigned int qseecom_get_version()
+{
+        return 0;
+}
+
 struct qpic_nand_init_config config;
 
 void update_ptable_names(void)
diff --git a/target/msm8909/init.c b/target/msm8909/init.c
index 4a5a3db..7ebf174 100644
--- a/target/msm8909/init.c
+++ b/target/msm8909/init.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -81,6 +81,9 @@
 #define CE_ARRAY_SIZE           20
 #define SUB_TYPE_SKUT           0x0A
 
+/* Fastboot switch GPIO for Intrinsic board. */
+#define USB_SW_GPIO_INTRINSIC_SOM 3
+
 extern void smem_ptable_init(void);
 extern void smem_add_modem_partitions(struct ptable *flash_ptable);
 void target_sdc_init();
@@ -735,6 +738,9 @@
 /* Do any target specific intialization needed before entering fastboot mode */
 void target_fastboot_init(void)
 {
+	uint32_t hw_id = board_hardware_id();
+	uint32_t platform_subtype = board_hardware_subtype();
+
 	/* Set the BOOT_DONE flag in PM8916 */
 	pm8x41_set_boot_done();
 
@@ -742,6 +748,26 @@
 		clock_ce_enable(CE1_INSTANCE);
 		target_load_ssd_keystore();
 	}
+
+	if ((HW_PLATFORM_MTP == hw_id) &&
+		(HW_PLATFORM_SUBTYPE_INTRINSIC_SOM == platform_subtype))
+	{
+		dprintf(SPEW, "Enabling PMIC GPIO for USB detection\n");
+
+		struct pm8x41_gpio usbgpio_param = {
+			.direction = PM_GPIO_DIR_OUT,
+			.vin_sel = 0,
+			.out_strength = PM_GPIO_OUT_DRIVE_MED,
+			.function = PM_GPIO_FUNC_HIGH,
+			.pull = PM_GPIO_PULLDOWN_10,
+			.inv_int_pol = PM_GPIO_INVERT,
+		};
+
+		pm8x41_gpio_config(USB_SW_GPIO_INTRINSIC_SOM, &usbgpio_param);
+		pm8x41_gpio_set(USB_SW_GPIO_INTRINSIC_SOM, 0);
+	}
+
+	return;
 }
 
 int set_download_mode(enum reboot_reason mode)
diff --git a/target/msm8909/oem_panel.c b/target/msm8909/oem_panel.c
index 064539c..deb6024 100644
--- a/target/msm8909/oem_panel.c
+++ b/target/msm8909/oem_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -472,6 +472,7 @@
 			struct mdss_dsi_phy_ctrl *phy_db)
 {
 	uint32_t hw_id = board_hardware_id();
+	uint32_t platform_type = board_platform_id();
 	uint32_t platform_subtype = board_hardware_subtype();
 	int32_t panel_override_id;
 
@@ -499,7 +500,20 @@
 		case HW_PLATFORM_SUBTYPE_8909_PM660_V1:
 		case HW_PLATFORM_SUBTYPE_8909_PM660:
 		case HW_PLATFORM_SUBTYPE_8909_COMPAL_ALPHA:
-			panel_id = AUO_390P_CMD_PANEL;
+			if ((platform_type == MSM8909W) ||
+				(platform_type == APQ8009W))
+				panel_id = AUO_390P_CMD_PANEL;
+			break;
+		case HW_PLATFORM_SUBTYPE_SWOC_TP_CIRC:
+		case HW_PLATFORM_SUBTYPE_SWOC_NOWGR_CIRC:
+			if ((platform_type == MSM8909W) ||
+				(platform_type == APQ8009W))
+				panel_id = AUO_400P_CMD_PANEL;
+			break;
+		case HW_PLATFORM_SUBTYPE_SWOC_WEAR:
+			if ((platform_type == MSM8909W) ||
+				(platform_type == APQ8009W))
+				panel_id = AUO_CX_QVGA_CMD_PANEL;
 			break;
 		default:
 			panel_id = HX8394D_720P_VIDEO_PANEL;
diff --git a/target/msm8952/init.c b/target/msm8952/init.c
index 6773dfa..a7c3469 100644
--- a/target/msm8952/init.c
+++ b/target/msm8952/init.c
@@ -192,7 +192,8 @@
 
 	if(platform_is_msm8956())
 		vol_up_gpio = TLMM_VOL_UP_BTN_GPIO_8956;
-	else if(platform_is_msm8937() || platform_is_msm8917())
+	else if(platform_is_msm8937() || platform_is_msm8917() ||
+		    platform_is_sdm429() || platform_is_sdm439())
 		vol_up_gpio = TLMM_VOL_UP_BTN_GPIO_8937;
 	else
 		vol_up_gpio = TLMM_VOL_UP_BTN_GPIO;
@@ -279,28 +280,6 @@
 		keys_post_event(KEY_VOLUMEUP, 1);
 }
 
-/* Configure PMIC and Drop PS_HOLD for shutdown */
-void shutdown_device()
-{
-	dprintf(CRITICAL, "Going down for shutdown.\n");
-
-	/* Configure PMIC for shutdown */
-	if (target_get_pmic() == PMIC_IS_PMI632)
-		pmi632_reset_configure(PON_PSHOLD_SHUTDOWN);
-	else
-		pm8x41_reset_configure(PON_PSHOLD_SHUTDOWN);
-
-	/* Drop PS_HOLD for MSM */
-	writel(0x00, MPM2_MPM_PS_HOLD);
-
-	mdelay(5000);
-
-	dprintf(CRITICAL, "shutdown failed\n");
-
-	ASSERT(0);
-}
-
-
 void target_init(void)
 {
 	dprintf(INFO, "target_init()\n");
@@ -309,7 +288,8 @@
 
 	if(target_is_pmi_enabled())
 	{
-		if(platform_is_msm8937() || platform_is_msm8917())
+		if(platform_is_msm8937() || platform_is_msm8917() ||
+		   platform_is_sdm429() || platform_is_sdm439())
 		{
 			uint8_t pmi_rev = 0;
 			uint32_t pmi_type = 0;
@@ -427,6 +407,8 @@
 	case MSM8920:
 	case MSM8217:
 	case MSM8617:
+	case SDM429:
+	case SDM439:
 		board->baseband = BASEBAND_MSM;
 		break;
 	case APQ8052:
@@ -447,32 +429,6 @@
 	return board_baseband();
 }
 
-unsigned check_reboot_mode(void)
-{
-	uint32_t restart_reason = 0;
-
-	/* Read reboot reason and scrub it */
-	restart_reason = readl(RESTART_REASON_ADDR);
-	writel(0x00, RESTART_REASON_ADDR);
-
-	return restart_reason;
-}
-
-unsigned check_hard_reboot_mode(void)
-{
-	uint8_t hard_restart_reason = 0;
-	uint8_t value = 0;
-
-	/* Read reboot reason and scrub it
-	  * Bit-5, bit-6 and bit-7 of SOFT_RB_SPARE for hard reset reason
-	  */
-	value = pm8x41_reg_read(PON_SOFT_RB_SPARE);
-	hard_restart_reason = value >> 5;
-	pm8x41_reg_write(PON_SOFT_RB_SPARE, value & 0x1f);
-
-	return hard_restart_reason;
-}
-
 int set_download_mode(enum reboot_reason mode)
 {
 	int ret = 0;
@@ -488,69 +444,6 @@
 	return _emmc_recovery_init();
 }
 
-void reboot_device(unsigned reboot_reason)
-{
-	uint8_t reset_type = 0;
-	uint32_t ret = 0;
-
-	/* Set cookie for dload mode */
-	if(set_download_mode(reboot_reason)) {
-		dprintf(CRITICAL, "HALT: set_download_mode not supported\n");
-		return;
-	}
-
-	writel(reboot_reason, RESTART_REASON_ADDR);
-
-	/* For Reboot-bootloader and Dload cases do a warm reset
-	 * For Reboot cases do a hard reset
-	 */
-	if((reboot_reason == FASTBOOT_MODE) || (reboot_reason == NORMAL_DLOAD) ||
-		(reboot_reason == EMERGENCY_DLOAD) || (reboot_reason == RECOVERY_MODE))
-		reset_type = PON_PSHOLD_WARM_RESET;
-	else
-		reset_type = PON_PSHOLD_HARD_RESET;
-
-	if (target_get_pmic() == PMIC_IS_PMI632)
-	{
-		pmi632_reset_configure(reset_type);
-	}
-	else
-	{
-		if(target_is_pmi_enabled())
-			pm8994_reset_configure(reset_type);
-		else
-			pm8x41_reset_configure(reset_type);
-	}
-
-	ret = scm_halt_pmic_arbiter();
-	if (ret)
-		dprintf(CRITICAL , "Failed to halt pmic arbiter: %d\n", ret);
-
-	/* Drop PS_HOLD for MSM */
-	writel(0x00, MPM2_MPM_PS_HOLD);
-
-	mdelay(5000);
-
-	dprintf(CRITICAL, "Rebooting failed\n");
-}
-
-#if USER_FORCE_RESET_SUPPORT
-/* Return 1 if it is a force resin triggered by user. */
-uint32_t is_user_force_reset(void)
-{
-	uint8_t poff_reason1 = pm8x41_get_pon_poff_reason1();
-	uint8_t poff_reason2 = pm8x41_get_pon_poff_reason2();
-
-	dprintf(SPEW, "poff_reason1: %d\n", poff_reason1);
-	dprintf(SPEW, "poff_reason2: %d\n", poff_reason2);
-	if (pm8x41_get_is_cold_boot() && (poff_reason1 == KPDPWR_AND_RESIN ||
-							poff_reason2 == STAGE3))
-		return 1;
-	else
-		return 0;
-}
-#endif
-
 unsigned target_pause_for_battery_charge(void)
 {
 	uint32_t pmic = target_get_pmic();
@@ -842,3 +735,20 @@
 		return PMIC_IS_UNKNOWN;
 	}
 }
+
+void pmic_reset_configure(uint8_t reset_type)
+{
+	uint32_t pmi_type;
+
+	pmi_type = target_get_pmic();
+	if (pmi_type == PMIC_IS_PMI632) {
+		pmi632_reset_configure(reset_type);
+	} else {
+		if(target_is_pmi_enabled()) {
+			pm8994_reset_configure(reset_type);
+		} else {
+			pm8x41_reset_configure(reset_type);
+		}
+	}
+}
+
diff --git a/target/msm8952/rules.mk b/target/msm8952/rules.mk
index d86ea01..ccc7e92 100644
--- a/target/msm8952/rules.mk
+++ b/target/msm8952/rules.mk
@@ -18,10 +18,6 @@
 SCRATCH_SIZE     := 511
 SCRATCH_SIZE_512 := 234
 
-ifeq ($(ENABLE_DISPLAY),1)
-DEFINES += ENABLE_DISPLAY=1
-DEFINES += DISPLAY_SPLASH_SCREEN=1
-endif
 DEFINES += DISPLAY_TYPE_MIPI=1
 DEFINES += DISPLAY_TYPE_DSI6G=1
 
diff --git a/target/msm8952/target_display.c b/target/msm8952/target_display.c
index 2f27fda..65d8222 100644
--- a/target/msm8952/target_display.c
+++ b/target/msm8952/target_display.c
@@ -593,10 +593,11 @@
 	bool ret = true;
 	struct oem_panel_data oem = mdss_dsi_get_oem_data();
 	uint32_t platform_subtype = board_hardware_subtype();
+	uint32_t platform = board_platform_id();
 
 	/* default to hdmi for apq iot */
-	if ((HW_PLATFORM_SUBTYPE_SAP == platform_subtype) ||
-		(HW_PLATFORM_SUBTYPE_SAP_NOPMI == platform_subtype)) {
+	if ((APQ8017 == platform) && ((HW_PLATFORM_SUBTYPE_SAP == platform_subtype) ||
+		(HW_PLATFORM_SUBTYPE_SAP_NOPMI == platform_subtype))) {
 		if (!strcmp(oem.panel, "")) {
 			if (buf_size < (prefix_string_len +
 				strlen(HDMI_ADV_PANEL_STRING))) {
@@ -646,6 +647,7 @@
 	int32_t ret = 0;
 	uint32_t panel_loop = 0;
 	uint32_t platform_subtype = board_hardware_subtype();
+	uint32_t platform = board_platform_id();
 
 	set_panel_cmd_string(panel_name);
 	oem = mdss_dsi_get_oem_data();
@@ -659,8 +661,8 @@
 		oem.cont_splash = false;
 	}
 
-	if ((HW_PLATFORM_SUBTYPE_SAP == platform_subtype) ||
-		(HW_PLATFORM_SUBTYPE_SAP_NOPMI == platform_subtype)) {
+	if ((APQ8017 == platform) && ((HW_PLATFORM_SUBTYPE_SAP == platform_subtype) ||
+		(HW_PLATFORM_SUBTYPE_SAP_NOPMI == platform_subtype))) {
 		dprintf(INFO, "%s: Platform subtype %d\n",
 			__func__, platform_subtype);
 		return;
diff --git a/target/msm8953/include/target/display.h b/target/msm8953/include/target/display.h
index 07b3f26..a70edf1 100755
--- a/target/msm8953/include/target/display.h
+++ b/target/msm8953/include/target/display.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, 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
@@ -66,7 +66,7 @@
 /*---------------------------------------------------------------------------*/
 #define DISPLAY_CMDLINE_PREFIX " mdss_mdp.panel="
 
-#define MIPI_FB_ADDR 0x90100000
+#define MIPI_FB_ADDR 0x90000000
 
 #define MIPI_HSYNC_PULSE_WIDTH       12
 #define MIPI_HSYNC_BACK_PORCH_DCLK   32
diff --git a/target/msm8953/init.c b/target/msm8953/init.c
index 33f4c79..075bf09 100644
--- a/target/msm8953/init.c
+++ b/target/msm8953/init.c
@@ -377,7 +377,6 @@
 	if (target_use_signed_kernel())
 		target_crypto_init_params();
 
-#if VERIFIED_BOOT
 	if (VB_M <= target_get_vb_version())
 	{
 		clock_ce_enable(CE1_INSTANCE);
@@ -411,7 +410,6 @@
 			ASSERT(0);
 		}
 	}
-#endif
 
 #if SMD_SUPPORT
 	rpm_smd_init();
@@ -517,6 +515,10 @@
 
 void target_uninit(void)
 {
+#if PON_VIB_SUPPORT
+	if(target_is_pmi_enabled())
+		turn_off_vib_early();
+#endif
 	mmc_put_card_to_sleep(dev);
 	sdhci_mode_disable(&dev->host);
 	if (crypto_initialized())
@@ -525,7 +527,6 @@
 	if (target_is_ssd_enabled())
 		clock_ce_disable(CE1_INSTANCE);
 
-#if VERIFIED_BOOT
 	if (VB_M <= target_get_vb_version())
 	{
 		if (is_sec_app_loaded())
@@ -545,7 +546,6 @@
 
 		clock_ce_disable(CE1_INSTANCE);
 	}
-#endif
 
 #if SMD_SUPPORT
 	rpm_smd_uninit();
diff --git a/target/target_display.c b/target/target_display.c
index d32e90d..ff0bff8 100644
--- a/target/target_display.c
+++ b/target/target_display.c
@@ -146,3 +146,8 @@
 {
 	return 0;
 }
+
+__WEAK int mdss_spi_cmd_post_on(struct msm_panel_info *pinfo)
+{
+	return 0;
+}