Merge "platform: msm-shared: Ability to flash only one volume for UBIFS partitions"
diff --git a/AndroidBoot.mk b/AndroidBoot.mk
index b27a1a0..1b336e3 100644
--- a/AndroidBoot.mk
+++ b/AndroidBoot.mk
@@ -20,13 +20,17 @@
 ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
   VERIFIED_BOOT := VERIFIED_BOOT=1
 else
-  VERIFIED_BOOT := VERIFEID_BOOT=0
+  VERIFIED_BOOT := VERIFIED_BOOT=0
 endif
 
 ifneq ($(TARGET_BUILD_VARIANT),user)
   DEVICE_STATUS := DEFAULT_UNLOCK=true
 endif
 
+ifeq ($(TARGET_BUILD_VARIANT),user)
+  BUILD_VARIANT := USER_BUILD_VARIANT=true
+endif
+
 ifeq ($(TARGET_BOARD_PLATFORM),msm8660)
   BOOTLOADER_PLATFORM := msm8660_surf
 endif
@@ -41,7 +45,7 @@
 # ELF binary for ABOOT
 TARGET_ABOOT_ELF := $(PRODUCT_OUT)/aboot.elf
 $(TARGET_ABOOT_ELF): ABOOT_CLEAN | $(ABOOT_OUT)
-	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(ABOOT_OUT) $(BOOTLOADER_PLATFORM) $(EMMC_BOOT) $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS)
+	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(ABOOT_OUT) $(BOOTLOADER_PLATFORM) $(EMMC_BOOT) $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS) $(BUILD_VARIANT)
 
 # NAND variant output
 TARGET_NAND_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn
@@ -70,7 +74,7 @@
 
 # Top level for eMMC variant targets
 $(TARGET_EMMC_BOOTLOADER): emmc_appsbootldr_clean | $(EMMC_BOOTLOADER_OUT) $(INSTALLED_KEYSTOREIMAGE_TARGET)
-	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(EMMC_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) EMMC_BOOT=1 $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS)
+	$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_COMPILE) BOOTLOADER_OUT=../../../$(EMMC_BOOTLOADER_OUT) $(BOOTLOADER_PLATFORM) EMMC_BOOT=1 $(SIGNED_KERNEL) $(VERIFIED_BOOT) $(DEVICE_STATUS) $(BUILD_VARIANT)
 
 # Keep build NAND & eMMC as default for targets still using TARGET_BOOTLOADER
 TARGET_BOOTLOADER := $(PRODUCT_OUT)/EMMCBOOT.MBN
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index ccf95c8..5451150 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -57,6 +57,10 @@
 #include <boot_device.h>
 #include <boot_verifier.h>
 #include <image_verify.h>
+#include <decompress.h>
+#if USE_RPMB_FOR_DEVINFO
+#include <rpmb.h>
+#endif
 
 #if DEVICE_TREE
 #include <libfdt.h>
@@ -68,6 +72,7 @@
 #include "bootimg.h"
 #include "fastboot.h"
 #include "sparse_format.h"
+#include "meta_format.h"
 #include "mmc.h"
 #include "devinfo.h"
 #include "board.h"
@@ -138,6 +143,7 @@
 static const char *battchg_pause = " androidboot.mode=charger";
 static const char *auth_kernel = " androidboot.authorized_kernel=true";
 static const char *secondary_gpt_enable = " gpt";
+static const char *mdtp_activated_flag = " mdtp";
 
 static const char *baseband_apq     = " androidboot.baseband=apq";
 static const char *baseband_msm     = " androidboot.baseband=msm";
@@ -157,11 +163,12 @@
 static bool boot_into_ffbm;
 static char target_boot_params[64];
 static bool boot_reason_alarm;
+static bool devinfo_present = true;
 
 /* Assuming unauthorized kernel image by default */
 static int auth_kernel_img = 0;
 
-static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0, {0}};
+static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0, {0}, {0},{0}};
 
 struct atag_ptbl_entry
 {
@@ -242,6 +249,10 @@
 	bool gpt_exists = partition_gpt_exists();
 	int have_target_boot_params = 0;
 	char *boot_dev_buf = NULL;
+    bool is_mdtp_activated = 0;
+#ifdef MDTP_SUPPORT
+    mdtp_activated(&is_mdtp_activated);
+#endif /* MDTP_SUPPORT */
 
 	if (cmdline && cmdline[0]) {
 		cmdline_len = strlen(cmdline);
@@ -263,6 +274,9 @@
 	if (boot_into_recovery && gpt_exists)
 		cmdline_len += strlen(secondary_gpt_enable);
 
+	if(is_mdtp_activated)
+		cmdline_len += strlen(mdtp_activated_flag);
+
 	if (boot_into_ffbm) {
 		cmdline_len += strlen(androidboot_mode);
 		cmdline_len += strlen(ffbm_mode_string);
@@ -391,6 +405,12 @@
 			while ((*dst++ = *src++));
 		}
 
+		if (is_mdtp_activated) {
+			src = mdtp_activated_flag;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		}
+
 		if (boot_into_ffbm) {
 			src = androidboot_mode;
 			if (have_cmdline) --dst;
@@ -625,7 +645,7 @@
 
 #if VERIFIED_BOOT
 	/* Write protect the device info */
-	if (mmc_write_protect("devinfo", 1))
+	if (target_build_variant_user() && devinfo_present && mmc_write_protect("devinfo", 1))
 	{
 		dprintf(INFO, "Failed to write protect dev info\n");
 		ASSERT(0);
@@ -739,18 +759,6 @@
 	set_tamper_flag(device.is_tampered);
 #endif
 
-	if(device.is_tampered)
-	{
-		write_device_info_mmc(&device);
-	#ifdef TZ_TAMPER_FUSE
-		set_tamper_fuse_cmd();
-	#endif
-	#ifdef ASSERT_ON_TAMPER
-		dprintf(CRITICAL, "Device is tampered. Asserting..\n");
-		ASSERT(0);
-	#endif
-	}
-
 #if VERIFIED_BOOT
 	if(boot_verify_get_state() == RED)
 	{
@@ -768,6 +776,19 @@
 		}
 	}
 #endif
+
+	if(device.is_tampered)
+	{
+		write_device_info_mmc(&device);
+	#ifdef TZ_TAMPER_FUSE
+		set_tamper_fuse_cmd();
+	#endif
+	#ifdef ASSERT_ON_TAMPER
+		dprintf(CRITICAL, "Device is tampered. Asserting..\n");
+		ASSERT(0);
+	#endif
+	}
+
 }
 
 static bool check_format_bit()
@@ -854,6 +875,14 @@
 	unsigned imagesize_actual;
 	unsigned second_actual = 0;
 
+	unsigned int out_len = 0;
+	unsigned int out_avai_len = 0;
+	unsigned char *out_addr = NULL;
+	uint32_t dtb_offset = 0;
+	unsigned char *kernel_start_addr = NULL;
+	unsigned int kernel_size = 0;
+	int rc;
+
 #if DEVICE_TREE
 	struct dt_table *table;
 	struct dt_entry dt_entry;
@@ -861,8 +890,7 @@
 	uint32_t dt_actual;
 	uint32_t dt_hdr_size;
 #endif
-	BUF_DMA_ALIGN(kbuf, BOOT_IMG_MAX_PAGE_SIZE);
-	struct kernel64_hdr *kptr = (void*) kbuf;
+	struct kernel64_hdr *kptr = NULL;
 
 	if (check_format_bit())
 		boot_into_recovery = 1;
@@ -923,45 +951,50 @@
 		page_mask = page_size - 1;
 	}
 
-	/* Read the next page to get kernel Image header
-	 * which lives in the second page for arm64 targets.
-	 */
-
-	if (mmc_read(ptn + page_size, (uint32_t *) kbuf, page_size)) {
-		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
-                return -1;
-	}
-
-	/*
-	 * Update the kernel/ramdisk/tags address if the boot image header
-	 * has default values, these default values come from mkbootimg when
-	 * the boot image is flashed using fastboot flash:raw
-	 */
-	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
-
-	/* Get virtual addresses since the hdr saves physical addresses. */
-	hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
-	hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
-	hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
-
 	kernel_actual  = ROUND_TO_PAGE(hdr->kernel_size,  page_mask);
 	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
 
-	/* Check if the addresses in the header are valid. */
-	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
-		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+	image_addr = (unsigned char *)target_get_scratch_address();
+
+#if DEVICE_TREE
+	dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
+	imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+#else
+	imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
+#endif
+
+#if VERIFIED_BOOT
+	boot_verifier_init();
+#endif
+
+	if (check_aboot_addr_range_overlap((uint32_t) image_addr, imagesize_actual))
 	{
-		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+		dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
 		return -1;
 	}
 
-#ifndef DEVICE_TREE
-	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+	/*
+	 * Update loading flow of bootimage to support compressed/uncompressed
+	 * bootimage on both 64bit and 32bit platform.
+	 * 1. Load bootimage from emmc partition onto DDR.
+	 * 2. Check if bootimage is gzip format. If yes, decompress compressed kernel
+	 * 3. Check kernel header and update kernel load addr for 64bit and 32bit
+	 *    platform accordingly.
+	 * 4. Sanity Check on kernel_addr and ramdisk_addr and copy data.
+	 */
+
+	dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
+	bs_set_timestamp(BS_KERNEL_LOAD_START);
+
+	/* Read image without signature */
+	if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
 	{
-		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
 		return -1;
 	}
-#endif
+
+	dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
+	bs_set_timestamp(BS_KERNEL_LOAD_DONE);
 
 	/* Authenticate Kernel */
 	dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
@@ -969,51 +1002,9 @@
 		device.is_unlocked,
 		device.is_tampered);
 
-#if VERIFIED_BOOT
-	boot_verifier_init();
-#endif
-
 	if(target_use_signed_kernel() && (!device.is_unlocked))
 	{
-		offset = 0;
-
-		image_addr = (unsigned char *)target_get_scratch_address();
-
-#if DEVICE_TREE
-		dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
-
-		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
-		{
-			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-			return -1;
-		}
-#else
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
-
-#endif
-
-		dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_START);
-
-		if (check_aboot_addr_range_overlap((uint32_t)image_addr, imagesize_actual))
-		{
-			dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
-			return -1;
-		}
-
-		/* Read image without signature */
-		if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
-		{
-			dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
-				return -1;
-		}
-
-		dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
-
 		offset = imagesize_actual;
-
 		if (check_aboot_addr_range_overlap((uint32_t)image_addr + offset, page_size))
 		{
 			dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
@@ -1028,147 +1019,120 @@
 		}
 
 		verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
-
-		/* Move kernel, ramdisk and device tree 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);
-
-		#if DEVICE_TREE
-		if(hdr->dt_size) {
-			dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
-			table = (struct dt_table*) dt_table_offset;
-
-			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
-				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
-				return -1;
-			}
-
-			/* Find index of device tree within device tree table */
-			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
-				dprintf(CRITICAL, "ERROR: Device Tree Blob cannot be found\n");
-				return -1;
-			}
-
-			/* Validate and Read device device tree in the "tags_add */
-			if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
-			{
-				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-				return -1;
-			}
-
-			memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
-		} else {
-			/*
-			 * If appended dev tree is found, update the atags with
-			 * memory address to the DTB appended location on RAM.
-			 * Else update with the atags address in the kernel header
-			 */
-			void *dtb;
-			dtb = dev_tree_appended((void*) hdr->kernel_addr,
-						hdr->kernel_size,
-						(void *)hdr->tags_addr);
-			if (!dtb) {
-				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
-				return -1;
-			}
-		}
-		#endif
-	}
-	else
-	{
+	} else {
 		second_actual  = ROUND_TO_PAGE(hdr->second_size,  page_mask);
+		#ifdef TZ_SAVE_KERNEL_HASH
+		aboot_save_boot_hash_mmc((uint32_t) image_addr, imagesize_actual);
+		#endif /* TZ_SAVE_KERNEL_HASH */
+	}
 
-		image_addr = (unsigned char *)target_get_scratch_address();
-#if DEVICE_TREE
-		dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+	/*
+	 * Check if the kernel image is a gzip package. If yes, need to decompress it.
+	 * If not, continue booting.
+	 */
+	if (is_gzip_package((unsigned char *)(image_addr + page_size), hdr->kernel_size))
+	{
+		out_addr = (unsigned char *)(image_addr + imagesize_actual + page_size);
+		out_avai_len = target_get_max_flash_size() - imagesize_actual - page_size;
+		dprintf(INFO, "decompress image start\n");
+		rc = decompress((unsigned char *)(image_addr + page_size),
+				hdr->kernel_size, out_addr, out_avai_len,
+				&dtb_offset, &out_len);
+		if (rc)
+		{
+			dprintf(INFO, "decompress image failed!!!\n");
+			ASSERT(0);
+		}
 
-		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
+		dprintf(INFO, "decompressed image finished.\n");
+		kptr = (struct kernel64_hdr *)out_addr;
+		kernel_start_addr = out_addr;
+		kernel_size = out_len;
+	} else {
+		kptr = (struct kernel64_hdr *)(image_addr + page_size);
+		kernel_start_addr = (unsigned char *)(image_addr + page_size);
+		kernel_size = hdr->kernel_size;
+	}
+
+	/*
+	 * Update the kernel/ramdisk/tags address if the boot image header
+	 * has default values, these default values come from mkbootimg when
+	 * the boot image is flashed using fastboot flash:raw
+	 */
+	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
+
+	/* Get virtual addresses since the hdr saves physical addresses. */
+	hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
+	hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
+	hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
+
+	kernel_size = ROUND_TO_PAGE(kernel_size,  page_mask);
+	/* Check if the addresses in the header are valid. */
+	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_size) ||
+		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+	{
+		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+		return -1;
+	}
+
+#ifndef DEVICE_TREE
+	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+	{
+		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		return -1;
+	}
+#endif
+
+	/* Move kernel, ramdisk and device tree to correct address */
+	memmove((void*) hdr->kernel_addr, kernel_start_addr, kernel_size);
+	memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
+
+	#if DEVICE_TREE
+	if(hdr->dt_size) {
+		dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
+		table = (struct dt_table*) dt_table_offset;
+
+		if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
+			dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
+			return -1;
+		}
+
+		/* Find index of device tree within device tree table */
+		if(dev_tree_get_entry_info(table, &dt_entry) != 0){
+			dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
+			return -1;
+		}
+
+		/* Validate and Read device device tree in the tags_addr */
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
 		{
 			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
 			return -1;
 		}
-#else
-		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
 
-#endif
-		if (check_aboot_addr_range_overlap((uint32_t) image_addr, imagesize_actual))
+		memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
+	} else {
+		/* Validate the tags_addr */
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
 		{
-			dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
+			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
 			return -1;
 		}
-
-		dprintf(INFO, "Loading boot image (%d): start\n",
-				imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_START);
-
-		offset = 0;
-
-		/* Load the entire boot image */
-		if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual)) {
-			dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
-					return -1;
+		/*
+		 * If appended dev tree is found, update the atags with
+		 * memory address to the DTB appended location on RAM.
+		 * Else update with the atags address in the kernel header
+		 */
+		void *dtb;
+		dtb = dev_tree_appended((void*)(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;
 		}
-
-		dprintf(INFO, "Loading boot image (%d): done\n",
-				imagesize_actual);
-		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
-
-		#ifdef TZ_SAVE_KERNEL_HASH
-		aboot_save_boot_hash_mmc((uint32_t) image_addr, imagesize_actual);
-		#endif /* TZ_SAVE_KERNEL_HASH */
-
-		/* Move kernel, ramdisk and device tree 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);
-
-		#if DEVICE_TREE
-		if(hdr->dt_size) {
-			dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
-			table = (struct dt_table*) dt_table_offset;
-
-			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
-				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
-				return -1;
-			}
-
-			/* Find index of device tree within device tree table */
-			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
-				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
-				return -1;
-			}
-
-			/* Validate and Read device device tree in the tags_addr */
-			if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
-			{
-				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-				return -1;
-			}
-
-			memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
-		} else {
-			/* Validate the tags_addr */
-			if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
-			{
-				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
-				return -1;
-			}
-			/*
-			 * If appended dev tree is found, update the atags with
-			 * memory address to the DTB appended location on RAM.
-			 * Else update with the atags address in the kernel header
-			 */
-			void *dtb;
-			dtb = dev_tree_appended((void*) hdr->kernel_addr,
-						kernel_actual,
-						(void *)hdr->tags_addr);
-			if (!dtb) {
-				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
-				return -1;
-			}
-		}
-		#endif
 	}
+	#endif
 
 	if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
 		target_load_ssd_keystore();
@@ -1324,8 +1288,8 @@
 		verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
 
 		/* 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);
+		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);
 #if DEVICE_TREE
 		/* Validate and Read device device tree in the "tags_add */
 		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
@@ -1444,20 +1408,17 @@
 BUF_DMA_ALIGN(info_buf, BOOT_IMG_MAX_PAGE_SIZE);
 void write_device_info_mmc(device_info *dev)
 {
-	struct device_info *info = (void*) info_buf;
 	unsigned long long ptn = 0;
-#if !VERIFIED_BOOT
 	unsigned long long size;
-#endif
 	int index = INVALID_PTN;
 	uint32_t blocksize;
 	uint8_t lun = 0;
+	uint32_t ret = 0;
 
-#if VERIFIED_BOOT
-	index = partition_get_index("devinfo");
-#else
-	index = partition_get_index("aboot");
-#endif
+	if (devinfo_present)
+		index = partition_get_index("devinfo");
+	else
+		index = partition_get_index("aboot");
 
 	ptn = partition_get_offset(index);
 	if(ptn == 0)
@@ -1468,40 +1429,34 @@
 	lun = partition_get_lun(index);
 	mmc_set_lun(lun);
 
-#if !VERIFIED_BOOT
 	size = partition_get_size(index);
-#endif
-
-	memcpy(info, dev, sizeof(device_info));
 
 	blocksize = mmc_get_device_blocksize();
 
-#if VERIFIED_BOOT
-	if(mmc_write(ptn, blocksize, (void *)info_buf))
-#else
-	if(mmc_write((ptn + size - blocksize), blocksize, (void *)info_buf))
-#endif
+	if (devinfo_present)
+		ret = mmc_write(ptn, blocksize, (void *)info_buf);
+	else
+		ret = mmc_write((ptn + size - blocksize), blocksize, (void *)info_buf);
+	if (ret)
 	{
 		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
 		return;
 	}
 }
 
-void read_device_info_mmc(device_info *dev)
+void read_device_info_mmc(struct device_info *info)
 {
-	struct device_info *info = (void*) info_buf;
 	unsigned long long ptn = 0;
-#if !VERIFIED_BOOT
 	unsigned long long size;
-#endif
 	int index = INVALID_PTN;
 	uint32_t blocksize;
+	uint32_t ret  = 0;
 
-#if VERIFIED_BOOT
-	index = partition_get_index("devinfo");
-#else
-	index = partition_get_index("aboot");
-#endif
+	if ((index = partition_get_index("devinfo")) < 0)
+	{
+		devinfo_present = false;
+		index = partition_get_index("aboot");
+	}
 
 	ptn = partition_get_offset(index);
 	if(ptn == 0)
@@ -1511,37 +1466,20 @@
 
 	mmc_set_lun(partition_get_lun(index));
 
-#if !VERIFIED_BOOT
 	size = partition_get_size(index);
-#endif
 
 	blocksize = mmc_get_device_blocksize();
 
-#if VERIFIED_BOOT
-	if(mmc_read(ptn, (void *)info_buf, blocksize))
-#else
-	if(mmc_read((ptn + size - blocksize), (void *)info_buf, blocksize))
-#endif
+	if (devinfo_present)
+		ret = mmc_read(ptn, (void *)info_buf, blocksize);
+	else
+		ret = mmc_read((ptn + size - blocksize), (void *)info_buf, blocksize);
+	if (ret)
 	{
 		dprintf(CRITICAL, "ERROR: Cannot read device info\n");
 		return;
 	}
 
-	if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
-	{
-		memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
-#if DEFAULT_UNLOCK
-		info->is_unlocked = 1;
-#else
-		info->is_unlocked = 0;
-#endif
-		info->is_verified = 0;
-		info->is_tampered = 0;
-		info->charger_screen_enabled = 0;
-
-		write_device_info_mmc(info);
-	}
-	memcpy(dev, info, sizeof(device_info));
 }
 
 void write_device_info_flash(device_info *dev)
@@ -1613,7 +1551,15 @@
 {
 	if(target_is_emmc_boot())
 	{
-		write_device_info_mmc(dev);
+		struct device_info *info = (void*) info_buf;
+		memcpy(info, dev, sizeof(struct device_info));
+
+#if USE_RPMB_FOR_DEVINFO
+		if (is_secure_boot_enable())
+			write_device_info_rpmb((void*) info, mmc_get_device_blocksize());
+#else
+		write_device_info_mmc(info);
+#endif
 	}
 	else
 	{
@@ -1625,7 +1571,32 @@
 {
 	if(target_is_emmc_boot())
 	{
-		read_device_info_mmc(dev);
+		struct device_info *info = (void*) info_buf;
+
+#if USE_RPMB_FOR_DEVINFO
+		if (is_secure_boot_enable())
+			read_device_info_rpmb((void*) info, mmc_get_device_blocksize());
+#else
+		read_device_info_mmc(info);
+#endif
+
+		if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
+		{
+			memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
+			if (is_secure_boot_enable())
+				info->is_unlocked = 0;
+			else
+				info->is_unlocked = 1;
+			info->is_verified = 0;
+			info->is_tampered = 0;
+#if USER_BUILD_VARIANT
+			info->charger_screen_enabled = 1;
+#else
+			info->charger_screen_enabled = 0;
+#endif
+			write_device_info(info);
+		}
+		memcpy(dev, info, sizeof(device_info));
 	}
 	else
 	{
@@ -1659,7 +1630,6 @@
 	struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
 
 	if(hdr->dt_size != 0) {
-
 		/* add kernel offset */
 		dt_image_offset += page_size;
 		n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
@@ -1714,16 +1684,23 @@
 	uint32_t image_actual;
 	uint32_t dt_actual = 0;
 	uint32_t sig_actual = SIGNATURE_SIZE;
-	struct boot_img_hdr *hdr;
-	struct kernel64_hdr *kptr;
+	struct boot_img_hdr *hdr = NULL;
+	struct kernel64_hdr *kptr = NULL;
 	char *ptr = ((char*) data);
 	int ret = 0;
 	uint8_t dtb_copied = 0;
+	unsigned int out_len = 0;
+	unsigned int out_avai_len = 0;
+	unsigned char *out_addr = NULL;
+	uint32_t dtb_offset = 0;
+	unsigned char *kernel_start_addr = NULL;
+	unsigned int kernel_size = 0;
+
 
 #ifdef MDTP_SUPPORT
 	/* Go through Firmware Lock verification before continue with boot process */
 	mdtp_fwlock_verify_lock();
-	fbcon_clear();
+	display_image_on_screen();
 #endif /* MDTP_SUPPORT */
 
 #if VERIFIED_BOOT
@@ -1778,11 +1755,39 @@
 		verify_signed_bootimg((uint32_t)data, (image_actual - sig_actual));
 
 	/*
+	 * Check if the kernel image is a gzip package. If yes, need to decompress it.
+	 * If not, continue booting.
+	 */
+	if (is_gzip_package((unsigned char *)(data + page_size), hdr->kernel_size))
+	{
+		out_addr = (unsigned char *)target_get_scratch_address();
+		out_addr = (unsigned char *)(out_addr + image_actual + page_size);
+		out_avai_len = target_get_max_flash_size() - image_actual - page_size;
+		dprintf(INFO, "decompress image start\n");
+		ret = decompress((unsigned char *)(ptr + page_size),
+				hdr->kernel_size, out_addr, out_avai_len,
+				&dtb_offset, &out_len);
+		if (ret)
+		{
+			dprintf(INFO, "decompress image failed!!!\n");
+			ASSERT(0);
+		}
+
+		dprintf(INFO, "decompressed image finished.\n");
+		kptr = (struct kernel64_hdr *)out_addr;
+		kernel_start_addr = out_addr;
+		kernel_size = out_len;
+	} else {
+		kptr = (struct kernel64_hdr*)((char *)data + page_size);
+		kernel_start_addr = (unsigned char *)((char *)data + page_size);
+		kernel_size = hdr->kernel_size;
+	}
+
+	/*
 	 * Update the kernel/ramdisk/tags address if the boot image header
 	 * has default values, these default values come from mkbootimg when
 	 * the boot image is flashed using fastboot flash:raw
 	 */
-	kptr = (struct kernel64_hdr*)((char*) data + page_size);
 	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
 
 	/* Get virtual addresses since the hdr saves physical addresses. */
@@ -1790,8 +1795,9 @@
 	hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
 	hdr->tags_addr = VA(hdr->tags_addr);
 
+	kernel_size  = ROUND_TO_PAGE(kernel_size,  page_mask);
 	/* Check if the addresses in the header are valid. */
-	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_size) ||
 		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
 	{
 		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
@@ -1813,9 +1819,15 @@
 
 	/* Load ramdisk & kernel */
 	memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
-	memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
+	memmove((void*) hdr->kernel_addr, (char*) (kernel_start_addr), kernel_size);
 
 #if DEVICE_TREE
+	if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
+	{
+		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		return;
+	}
+
 	/*
 	 * If dtb is not found look for appended DTB in the kernel.
 	 * If appended dev tree is found, update the atags with
@@ -1824,7 +1836,8 @@
 	 */
 	if (!dtb_copied) {
 		void *dtb;
-		dtb = dev_tree_appended((void *)hdr->kernel_addr, hdr->kernel_size,
+		dtb = dev_tree_appended((void*)(ptr + page_size),
+					hdr->kernel_size, dtb_offset,
 					(void *)hdr->tags_addr);
 		if (!dtb) {
 			fastboot_fail("dtb not found");
@@ -1833,14 +1846,6 @@
 	}
 #endif
 
-#ifndef DEVICE_TREE
-	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
-	{
-		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
-		return;
-	}
-#endif
-
 	fastboot_okay("");
 	fastboot_stop();
 
@@ -1904,24 +1909,25 @@
 	lun = partition_get_lun(index);
 	mmc_set_lun(lun);
 
-#if MMC_SDHCI_SUPPORT
-	if (mmc_erase_card(ptn, size)) {
-		fastboot_fail("failed to erase partition\n");
-		return;
-	}
-#else
-	BUF_DMA_ALIGN(out, DEFAULT_ERASE_SIZE);
-	size = partition_get_size(index);
-	if (size > DEFAULT_ERASE_SIZE)
-		size = DEFAULT_ERASE_SIZE;
+	if (platform_boot_dev_isemmc())
+	{
+		if (mmc_erase_card(ptn, size)) {
+			fastboot_fail("failed to erase partition\n");
+			return;
+		}
+	} else {
+		BUF_DMA_ALIGN(out, DEFAULT_ERASE_SIZE);
+		size = partition_get_size(index);
+		if (size > DEFAULT_ERASE_SIZE)
+			size = DEFAULT_ERASE_SIZE;
 
-	/* Simple inefficient version of erase. Just writing
-       0 in first several blocks */
-	if (mmc_write(ptn , size, (unsigned int *)out)) {
-		fastboot_fail("failed to erase partition");
-		return;
+		/* Simple inefficient version of erase. Just writing
+	       0 in first several blocks */
+		if (mmc_write(ptn , size, (unsigned int *)out)) {
+			fastboot_fail("failed to erase partition");
+			return;
+		}
 	}
-#endif
 	fastboot_okay("");
 }
 
@@ -2015,6 +2021,47 @@
 	return;
 }
 
+void cmd_flash_meta_img(const char *arg, void *data, unsigned sz)
+{
+	int i, images;
+	meta_header_t *meta_header;
+	img_header_entry_t *img_header_entry;
+
+	meta_header = (meta_header_t*) data;
+	img_header_entry = (img_header_entry_t*) (data+sizeof(meta_header_t));
+
+	images = meta_header->img_hdr_sz / sizeof(img_header_entry_t);
+
+	for (i=0; i<images; i++) {
+
+		if((img_header_entry[i].ptn_name == NULL) ||
+			(img_header_entry[i].start_offset == 0) ||
+			(img_header_entry[i].size == 0))
+			break;
+
+		cmd_flash_mmc_img(img_header_entry[i].ptn_name,
+					(void *) data + img_header_entry[i].start_offset,
+					img_header_entry[i].size);
+	}
+
+	if (!strncmp(arg, "bootloader", strlen("bootloader")))
+	{
+		strlcpy(device.bootloader_version, TARGET(BOARD), MAX_VERSION_LEN);
+		strlcat(device.bootloader_version, "-", MAX_VERSION_LEN);
+		strlcat(device.bootloader_version, meta_header->img_version, MAX_VERSION_LEN);
+	}
+	else
+	{
+		strlcpy(device.radio_version, TARGET(BOARD), MAX_VERSION_LEN);
+		strlcat(device.radio_version, "-", MAX_VERSION_LEN);
+		strlcat(device.radio_version, meta_header->img_version, MAX_VERSION_LEN);
+	}
+
+	write_device_info(&device);
+	fastboot_okay("");
+	return;
+}
+
 void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
 {
 	unsigned int chunk;
@@ -2192,6 +2239,7 @@
 void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
 {
 	sparse_header_t *sparse_header;
+	meta_header_t *meta_header;
 
 #ifdef SSD_ENABLE
 	/* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
@@ -2278,10 +2326,13 @@
 #endif
 
 	sparse_header = (sparse_header_t *) data;
-	if (sparse_header->magic != SPARSE_HEADER_MAGIC)
-		cmd_flash_mmc_img(arg, data, sz);
-	else
+	meta_header = (meta_header_t *) data;
+	if (sparse_header->magic == SPARSE_HEADER_MAGIC)
 		cmd_flash_mmc_sparse_img(arg, data, sz);
+	else if (meta_header->magic == META_HEADER_MAGIC)
+		cmd_flash_meta_img(arg, data, sz);
+	else
+		cmd_flash_mmc_img(arg, data, sz);
 	return;
 }
 
@@ -2377,7 +2428,7 @@
 #ifdef MDTP_SUPPORT
 	/* Go through Firmware Lock verification before continue with boot process */
 	mdtp_fwlock_verify_lock();
-	fbcon_clear();
+	display_image_on_screen();
 #endif /* MDTP_SUPPORT */
 
 	if (target_is_emmc_boot())
@@ -2560,6 +2611,7 @@
 	struct fbimage *logo = NULL;
 	uint32_t blocksize;
 	uint32_t readsize;
+	uint32_t logosize;
 	uint32_t ptn_size;
 
 	index = partition_get_index("splash");
@@ -2576,12 +2628,12 @@
 
 	ptn_size = partition_get_size(index);
 	blocksize = mmc_get_device_blocksize();
-	readsize = ROUNDUP(sizeof(logo->header), blocksize);
+	logosize = ROUNDUP(sizeof(logo->header), blocksize);
 
-	logo = (struct fbimage *)memalign(CACHE_LINE, ROUNDUP(readsize, CACHE_LINE));
+	logo = (struct fbimage *)memalign(CACHE_LINE, ROUNDUP(logosize, CACHE_LINE));
 	ASSERT(logo);
 
-	if (mmc_read(ptn, (uint32_t *) logo, readsize)) {
+	if (mmc_read(ptn, (uint32_t *) logo, logosize)) {
 		dprintf(CRITICAL, "ERROR: Cannot read splash image header\n");
 		goto err;
 	}
@@ -2606,7 +2658,7 @@
 			goto err;
 		}
 
-		if (mmc_read(ptn + sizeof(logo->header),(uint32_t *)base, readsize)) {
+		if (mmc_read(ptn + logosize,(uint32_t *)base, readsize)) {
 			fbcon_clear();
 			dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
 			goto err;
@@ -2752,6 +2804,8 @@
 			device.display_panel);
 	fastboot_publish("display-panel",
 			(const char *) panel_display_mode);
+	fastboot_publish("version-bootloader", (const char *) device.bootloader_version);
+	fastboot_publish("version-baseband", (const char *) device.radio_version);
 }
 
 void aboot_init(const struct app_descriptor *app)
@@ -2778,11 +2832,16 @@
 
 	/* Display splash screen if enabled */
 #if DISPLAY_SPLASH_SCREEN
-	dprintf(SPEW, "Display Init: Start\n");
-	target_display_init(device.display_panel);
-	dprintf(SPEW, "Display Init: Done\n");
+#if NO_ALARM_DISPLAY
+	if (!check_alarm_boot()) {
 #endif
-
+		dprintf(SPEW, "Display Init: Start\n");
+		target_display_init(device.display_panel);
+		dprintf(SPEW, "Display Init: Done\n");
+#if NO_ALARM_DISPLAY
+	}
+#endif
+#endif
 
 	target_serialno((unsigned char *) sn_buf);
 	dprintf(SPEW,"serial number: %s\n",sn_buf);
@@ -2860,7 +2919,7 @@
 #ifdef MDTP_SUPPORT
 			/* Go through Firmware Lock verification before continue with boot process */
 			mdtp_fwlock_verify_lock();
-			fbcon_clear();
+			display_image_on_screen();
 #endif /* MDTP_SUPPORT */
 
 			boot_linux_from_mmc();
diff --git a/app/aboot/devinfo.h b/app/aboot/devinfo.h
index bd78771..7eee69b 100644
--- a/app/aboot/devinfo.h
+++ b/app/aboot/devinfo.h
@@ -1,5 +1,5 @@
 /*
- * * Copyright (c) 2011,2014, The Linux Foundation. All rights reserved.
+ * * Copyright (c) 2011,2014-2015, 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
@@ -35,6 +35,7 @@
 #define DEVICE_MAGIC "ANDROID-BOOT!"
 #define DEVICE_MAGIC_SIZE 13
 #define MAX_PANEL_ID_LEN 64
+#define MAX_VERSION_LEN  64
 
 struct device_info
 {
@@ -44,6 +45,8 @@
 	bool is_verified;
 	bool charger_screen_enabled;
 	char display_panel[MAX_PANEL_ID_LEN];
+	char bootloader_version[MAX_VERSION_LEN];
+	char radio_version[MAX_VERSION_LEN];
 };
 
 #endif
diff --git a/app/aboot/fastboot.c b/app/aboot/fastboot.c
index 9dac985..6f1841f 100644
--- a/app/aboot/fastboot.c
+++ b/app/aboot/fastboot.c
@@ -2,7 +2,7 @@
  * Copyright (c) 2009, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, 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
@@ -428,10 +428,32 @@
 	fastboot_ack("OKAY", info);
 }
 
+static void getvar_all()
+{
+	struct fastboot_var *var;
+	char getvar_all[64];
+
+	for (var = varlist; var; var = var->next)
+	{
+		strlcpy((char *) getvar_all, var->name, sizeof(getvar_all));
+		strlcat((char *) getvar_all, ":", sizeof(getvar_all));
+		strlcat((char *) getvar_all, var->value, sizeof(getvar_all));
+		fastboot_info(getvar_all);
+		memset((void *) getvar_all, '\0', sizeof(getvar_all));
+	}
+	fastboot_okay("");
+}
+
 static void cmd_getvar(const char *arg, void *data, unsigned sz)
 {
 	struct fastboot_var *var;
 
+	if (!strncmp("all", arg, strlen(arg)))
+	{
+		getvar_all();
+		return;
+	}
+
 	for (var = varlist; var; var = var->next) {
 		if (!strcmp(var->name, arg)) {
 			fastboot_okay(var->value);
@@ -456,6 +478,10 @@
 	snprintf((char *)response, MAX_RSP_SIZE, "DATA%08x", len);
 	if (usb_if.usb_write(response, strlen((const char *)response)) < 0)
 		return;
+	/*
+	 * Discard the cache contents before starting the download
+	 */
+	arch_invalidate_cache_range((addr_t) download_base, sz);
 
 	r = usb_if.usb_read(download_base, len);
 	if ((r < 0) || ((unsigned) r != len)) {
diff --git a/app/aboot/mdtp.c b/app/aboot/mdtp.c
index 60b97b0..160f6c8 100644
--- a/app/aboot/mdtp.c
+++ b/app/aboot/mdtp.c
@@ -47,6 +47,7 @@
 static int mdtp_tzbsp_dec_verify_DIP(DIP_t *enc_dip, DIP_t *dec_dip, uint32_t *verified);
 static int mdtp_tzbsp_enc_hash_DIP(DIP_t *dec_dip, DIP_t *enc_dip);
 
+static int is_mdtp_activated = -1;
 /********************************************************************************/
 
 /* Read the DIP from EMMC */
@@ -76,7 +77,7 @@
 		return -1;
 	}
 
-	dprintf(INFO, "mdtp: read_DIP: SUCCESS, read %d bytes\n", actual_partition_size);
+	dprintf(SPEW, "mdtp: read_DIP: SUCCESS, read %d bytes\n", actual_partition_size);
 
 	return 0;
 }
@@ -85,7 +86,6 @@
 static int write_DIP(DIP_t *dip)
 {
 	unsigned long long ptn = 0;
-	uint32_t partition_size;
 	uint32_t block_size = mmc_get_device_blocksize();
 
 	int index = INVALID_PTN;
@@ -94,30 +94,25 @@
 
 	index = partition_get_index("dip");
 	ptn = partition_get_offset(index);
+
 	if(ptn == 0)
 	{
 		return -1;
 	}
 
-	partition_size = partition_get_size(index);
-
-	if(partition_size < size)
-	{
-		dprintf(CRITICAL, "mdtp: write_DIP: ERROR, DIP partition too small\n");
-		return -1;
-	}
-
-	if(mmc_write(ptn, ROUNDUP(size, block_size), (void *)dip))
+	if(mmc_write(ptn, ROUNDUP(sizeof(DIP_t), block_size), (void *)dip))
 	{
 		dprintf(CRITICAL, "mdtp: write_DIP: ERROR, cannot read DIP info\n");
 		return -1;
 	}
 
+	dprintf(SPEW, "mdtp: write_DIP: SUCCESS, write %d bytes\n", ROUNDUP(sizeof(DIP_t), block_size));
+
 	return 0;
 }
 
-/* Provision the DIP by storing the default DIP into the EMMC */
-static void provision_DIP()
+/* Deactivate MDTP by storing the default DIP into the EMMC */
+static void write_deactivated_DIP()
 {
 	DIP_t *enc_dip;
 	DIP_t *dec_dip;
@@ -126,14 +121,14 @@
 	enc_dip = malloc(sizeof(DIP_t));
 	if (enc_dip == NULL)
 	{
-		dprintf(CRITICAL, "mdtp: provision_DIP: ERROR, cannot allocate DIP\n");
+		dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
 		return;
 	}
 
 	dec_dip = malloc(sizeof(DIP_t));
 	if (dec_dip == NULL)
 	{
-		dprintf(CRITICAL, "mdtp: provision_DIP: ERROR, cannot allocate DIP\n");
+		dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot allocate DIP\n");
 		free(enc_dip);
 		return;
 	}
@@ -145,21 +140,14 @@
 	ret = mdtp_tzbsp_enc_hash_DIP(dec_dip, enc_dip);
 	if(ret < 0)
 	{
-		dprintf(CRITICAL, "mdtp: provision_DIP: ERROR, cannot cipher DIP\n");
+		dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot cipher DIP\n");
 		goto out;
 	}
 
 	ret = write_DIP(enc_dip);
 	if(ret < 0)
 	{
-		dprintf(CRITICAL, "mdtp: provision_DIP: ERROR, cannot write DIP\n");
-		goto out;
-	}
-
-	ret = mdtp_tzbsp_set_provisioned_fuse();
-	if(ret < 0)
-	{
-		dprintf(CRITICAL, "mdtp: provision_DIP: ERROR, cannot set DIP_PROVISIONED fuse\n\n");
+		dprintf(CRITICAL, "mdtp: write_deactivated_DIP: ERROR, cannot write DIP\n");
 		goto out;
 	}
 
@@ -178,7 +166,7 @@
 	uint32_t block_size = mmc_get_device_blocksize();
 	uint32_t actual_partition_size = ROUNDUP(size, block_size);
 
-	dprintf(INFO, "mdtp: verify_partition_single_hash: %s, %u\n", name, size);
+	dprintf(SPEW, "mdtp: verify_partition_single_hash: %s, %u\n", name, size);
 
 	ASSERT(name != NULL);
 	ASSERT(hash_table != NULL);
@@ -208,7 +196,7 @@
 		return -1;
 	}
 
-	dprintf(INFO, "verify_partition_single_hash: %s: VERIFIED!\n", name);
+	dprintf(SPEW, "verify_partition_single_hash: %s: VERIFIED!\n", name);
 
 	return 0;
 }
@@ -228,7 +216,7 @@
 	uint32_t bytes_to_read;
 	uint32_t block_num = 0;
 
-	dprintf(INFO, "mdtp: verify_partition_block_hash: %s, %u\n", name, size);
+	dprintf(SPEW, "mdtp: verify_partition_block_hash: %s, %u\n", name, size);
 
 	ASSERT(name != NULL);
 	ASSERT(hash_table != NULL);
@@ -287,7 +275,7 @@
 		force_verify_block += 1;
 	}
 
-	dprintf(INFO, "verify_partition_block_hash: %s: VERIFIED!\n", name);
+	dprintf(SPEW, "verify_partition_block_hash: %s: VERIFIED!\n", name);
 
 	return 0;
 }
@@ -321,6 +309,75 @@
 	return 0;
 }
 
+/* Display the recovery UI to allow the user to enter the PIN and continue boot */
+static int display_recovery_ui(DIP_t *dip)
+{
+	uint32_t pin_length = 0;
+	char entered_pin[MDTP_MAX_PIN_LEN+1] = {0};
+	uint32_t i;
+	uint32_t equal_count = 0, different_count = 0;
+
+	if (dip->mdtp_cfg.enable_local_pin_authentication)
+	{
+		dprintf(SPEW, "mdtp: display_recovery_ui: Local deactivation enabled\n");
+
+		pin_length = strlen(dip->mdtp_cfg.mdtp_pin.mdtp_pin);
+
+		if (pin_length > MDTP_MAX_PIN_LEN || pin_length < MDTP_MIN_PIN_LEN)
+		{
+			dprintf(CRITICAL, "mdtp: display_recovery_ui: Error, invalid PIN length\n");
+			display_error_msg();
+			return -1;
+		}
+
+		// Set entered_pin to initial '0' string + null terminator
+		for (i=0; i<pin_length; i++)
+		{
+			entered_pin[i] = '0';
+		}
+
+		// Allow the user to enter the PIN as many times as he wishes
+		// (with INVALID_PIN_DELAY_MSECONDS after each failed attempt)
+		while (1)
+		{
+		    get_pin_from_user(entered_pin, pin_length);
+
+		    // Go over the entire PIN in any case, to prevent side-channel attacks
+		    for (i=0; i<pin_length; i++)
+		    {
+		        if (dip->mdtp_cfg.mdtp_pin.mdtp_pin[i] == entered_pin[i])
+		            equal_count++;
+		        else
+		            different_count++;
+		    }
+
+		    if (equal_count == pin_length)
+		    {
+		        // Valid PIN - deactivate and continue boot
+		        dprintf(SPEW, "mdtp: display_recovery_ui: valid PIN, continue boot\n");
+		        write_deactivated_DIP();
+		        return 0;
+		    }
+		    else
+		    {
+		        // Invalid PIN - display an appropriate message (which also includes a wait
+		        // for INVALID_PIN_DELAY_MSECONDS), and allow the user to try again
+		        dprintf(CRITICAL, "mdtp: display_recovery_ui: ERROR, invalid PIN\n");
+		        display_invalid_pin_msg();
+
+		        equal_count = 0;
+		        different_count = 0;
+		    }
+		}
+	}
+	else
+	{
+		dprintf(CRITICAL, "mdtp: display_recovery_ui: Local deactivation disabled, unable to display recovery UI\n");
+		display_error_msg();
+		return -1;
+	}
+}
+
 /* Verify all protected partitinons according to the DIP */
 static int verify_all_partitions(DIP_t *dip, verify_result_t *verify_result)
 {
@@ -340,8 +397,6 @@
 	}
 	else if (dip->status == DIP_STATUS_ACTIVATED)
 	{
-		show_checking_msg();
-
 		for(i=0; i<MAX_PARTITIONS; i++)
 		{
 			if(dip->partition_cfg[i].lock_enabled && dip->partition_cfg[i].size)
@@ -361,14 +416,13 @@
 		if (verify_failure)
 		{
 			dprintf(CRITICAL, "mdtp: verify_all_partitions: Failed partition verification\n");
-			show_invalid_msg();
-			return -1;
+			return 0;
 		}
+		is_mdtp_activated = 1;
 
 	}
 
 	*verify_result = VERIFY_OK;
-	show_OK_msg();
 	return 0;
 }
 
@@ -385,14 +439,14 @@
 	enc_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
 	if (enc_dip == NULL)
 	{
-		dprintf(CRITICAL, "mdtp: provision_DIP: ERROR, cannot allocate DIP\n");
+		dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
 		return;
 	}
 
 	dec_dip = malloc(ROUNDUP(sizeof(DIP_t), block_size));
 	if (dec_dip == NULL)
 	{
-		dprintf(CRITICAL, "mdtp: provision_DIP: ERROR, cannot allocate DIP\n");
+		dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot allocate DIP\n");
 		free(enc_dip);
 		return;
 	}
@@ -410,7 +464,7 @@
 	if(ret < 0)
 	{
 		dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, cannot verify DIP\n");
-		show_invalid_msg();
+		display_error_msg();
 		goto out;
 	}
 
@@ -418,7 +472,7 @@
 	if(!verified)
 	{
 		dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted DIP\n");
-		show_invalid_msg();
+		display_error_msg();
 		goto out;
 	}
 
@@ -432,14 +486,15 @@
 
 	if (verify_result == VERIFY_OK)
 	{
-		dprintf(INFO, "mdtp: validate_DIP_and_firmware: Verify OK\n");
+		dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify OK\n");
 	}
 	else if (verify_result  == VERIFY_FAILED)
 	{
 		dprintf(CRITICAL, "mdtp: validate_DIP_and_firmware: ERROR, corrupted firmware\n");
+		display_recovery_ui(dec_dip);
 	} else /* VERIFY_SKIPPED */
 	{
-		dprintf(INFO, "mdtp: validate_DIP_and_firmware: Verify skipped\n");
+		dprintf(SPEW, "mdtp: validate_DIP_and_firmware: Verify skipped\n");
 	}
 
 out:
@@ -459,6 +514,9 @@
 	int ret;
 	bool enabled;
 
+	/* sets the default value of this global to be MDTP not activated */
+	is_mdtp_activated = 0;
+
 	ret = mdtp_fuse_get_enabled(&enabled);
 	if(ret)
 	{
@@ -474,6 +532,18 @@
 
 	return 0;
 }
+/********************************************************************************/
+
+/** Indicates whether the MDTP is currently in ACTIVATED state **/
+int mdtp_activated(bool * activated){
+	if(is_mdtp_activated < 0){
+		/* mdtp_fwlock_verify_lock was not called before, the value is not valid */
+		return is_mdtp_activated;
+	}
+
+	*activated = is_mdtp_activated;
+	return 0;
+}
 
 /********************************************************************************/
 
diff --git a/app/aboot/mdtp.h b/app/aboot/mdtp.h
index 9975899..865c791 100644
--- a/app/aboot/mdtp.h
+++ b/app/aboot/mdtp.h
@@ -34,9 +34,13 @@
 #define MAX_PARTITIONS 3
 #define MAX_PARTITION_NAME_LEN 100
 #define HASH_LEN 32
+#define MDTP_MIN_PIN_LEN 5
 #define MDTP_MAX_PIN_LEN 8
 #define DIP_PADDING 11
 
+#define INITIAL_DELAY_MSECONDS      5000
+#define INVALID_PIN_DELAY_MSECONDS  5000
+
 #define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
 #define MDTP_FWLOCK_BLOCK_SIZE (1024*1024*16)
 #define MDTP_FWLOCK_MAX_FILES (100)
@@ -104,19 +108,71 @@
 	VERIFY_FAILED,
 } verify_result_t;
 
-/* Start Firmware Lock verification process */
+
+/**
+ * mdtp_fwlock_verify_lock
+ *
+ * Start Firmware Lock verification process.
+ *
+ * @return - negative value for an error, 0 for success.
+ */
 int mdtp_fwlock_verify_lock();
 
-/* Return whether the MDTP is currently enabled or disabled in HW */
+/**
+ * mdtp_fuse_get_enabled
+ *
+ * Return whether the MDTP is currently enabled or
+ * disabled in HW.
+ *
+ * @param[out] enabled: set to true if MDTP enabled,
+ * false otherwise.
+ *
+ * @return - negative value for an error, 0 for success.
+ */
 int mdtp_fuse_get_enabled(bool *enabled);
 
-/* Display the "Firmware Valid" screen */
-void show_OK_msg();
+/**
+ * get_pin_from_user
+ *
+ * Display the recovery PIN screen and set received buffer
+ * with the PIN the user has entered.
+ *
+ * @param[out] entered_pin: buffer holding the received PIN.
+ * @param[in]  pin_length:  PIN length (and also entered_pin buffer length).
+ *
+ * @return - None.
+ */
+void get_pin_from_user(char *entered_pin, uint32_t pin_length);
 
-/* Display the "Firmware Invalid" screen */
-void show_invalid_msg();
+/**
+ * display_invalid_pin_msg
+ *
+ * User has entered invalid PIN, display error message and
+ * allow the user to try again.
+ *
+ * @return - None.
+ */
+void display_invalid_pin_msg();
 
-/* Display the "Verifying Firmware" screen */
-void show_checking_msg();
+/**
+ * display_error_msg
+ *
+ * Display error message and stop boot process.
+ *
+ * @return - None.
+ */
+void display_error_msg();
+
+/**
+ * mdtp_activated
+ *
+ * Indicates whether the MDTP is currently in ACTIVATED state.
+ * You must call this function only after calling to mdtp_fwlock_verify_lock();
+ *
+ * @param[out] activated: MDTP is in ACTIVATED state (TRUE/FALSE).
+ *
+ * @return - negative value for an error, 0 for success.
+ */
+int mdtp_activated(bool * activated);
 
 #endif
diff --git a/app/aboot/mdtp_fuse.c b/app/aboot/mdtp_fuse.c
index c4abd19..1487057 100644
--- a/app/aboot/mdtp_fuse.c
+++ b/app/aboot/mdtp_fuse.c
@@ -41,6 +41,8 @@
 #define MAX_METADATA_SIZE       (0x1000)
 #define QFPROM_ADDR_SPACE_RAW   (0)
 
+char metadata_block[MAX_METADATA_SIZE] = {0};
+
 /********************************************************************************/
 
 typedef union
@@ -116,7 +118,6 @@
 {
 	unsigned long long ptn = 0;
 	uint32_t actual_size;
-	char metadata_block[MAX_METADATA_SIZE];
 	int index = INVALID_PTN;
 	uint32_t block_size = mmc_get_device_blocksize();
 
@@ -128,21 +129,21 @@
 		return -1;
 	}
 
-	if (sizeof(metadata_t) > MAX_METADATA_SIZE)
+	actual_size = ROUNDUP(sizeof(metadata_t), block_size);
+
+	if (actual_size > MAX_METADATA_SIZE)
 	{
-		dprintf(CRITICAL, "mdtp: read_metadata: ERROR, meta data size %d too big\n", sizeof(metadata_t));
+		dprintf(CRITICAL, "mdtp: read_metadata: ERROR, meta data size %d too big\n", actual_size);
 		return -1;
 	}
 
-	actual_size = ROUNDUP(MAX_METADATA_SIZE, block_size);
-
 	if(mmc_read(ptn, (void *)metadata_block, actual_size))
 	{
 		dprintf(CRITICAL, "mdtp: read_metadata: ERROR, cannot read mdtp info\n");
 		return -1;
 	}
 
-	memcpy(metadata, metadata_block, sizeof(metadata_t));
+	memscpy((uint8_t*)metadata, sizeof(metadata_t), (uint8_t*)(&(metadata_block[0])), MAX_METADATA_SIZE);
 
 	dprintf(INFO, "mdtp: read_metadata: SUCCESS, read %d bytes\n", actual_size);
 
diff --git a/app/aboot/mdtp_ui.c b/app/aboot/mdtp_ui.c
index 30d70d6..48d899e 100644
--- a/app/aboot/mdtp_ui.c
+++ b/app/aboot/mdtp_ui.c
@@ -32,31 +32,88 @@
 #include <mmc.h>
 #include <partition_parser.h>
 #include <stdlib.h>
+#include <string.h>
 #include "mdtp.h"
 
-#define MDTP_IMAGE_WIDTH 500
-#define MDTP_IMAGE_HEIGHT 800
-#define MDTP_UX_DELAY 1000
-#define MDTP_OK_OFFSET 0x0
-#define MDTP_CHECKING_OFFSET 0x200000
-#define MDTP_INVALID_OFFSET 0x400000
-#define MDTP_RECOVERED_OFFSET 0x600000
+// Image dimensions
+#define MDTP_ERROR_MSG_WIDTH                (1412)
+#define MDTP_ERROR_MSG_HEIGHT               (212)
+#define MDTP_MAIN_TEXT_WIDTH                (1364)
+#define MDTP_MAIN_TEXT_HEIGHT               (288)
+#define MDTP_PIN_DIGIT_WIDTH                (180)
+#define MDTP_PIN_DIGIT_HEIGHT               (180)
+#define MDTP_OK_BUTTON_WIDTH                (644)
+#define MDTP_OK_BUTTON_HEIGHT               (158)
+#define MDTP_DIGITS_INSTRUCTIONS_WIDTH      (1384)
+#define MDTP_DIGITS_INSTRUCTIONS_HEIGHT     (166)
+#define MDTP_PIN_INSTRUCTIONS_WIDTH         (920)
+#define MDTP_PIN_INSTRUCTIONS_HEIGHT        (204)
 
-extern uint32_t target_volume_down(void);
-extern void fbcon_putImage(struct fbimage *fbimg, bool flag);
+// Image offsets
+#define MDTP_ERROR_MSG_OFFSET               (0x1000)
+#define MDTP_INITIAL_DELAY_OFFSET           (0xDD000)
+#define MDTP_ENTER_PIN_OFFSET               (0x1FD000)
+#define MDTP_INVALID_PIN_OFFSET             (0x31D000)
+#define MDTP_PIN_DIGIT_0_OFFSET             (0x43D000)
+#define MDTP_PIN_DIGITS_OFFSET              (0x18000)
+#define MDTP_PIN_SELECTED_DIGIT_0_OFFSET    (MDTP_PIN_DIGIT_0_OFFSET + 10*MDTP_PIN_DIGITS_OFFSET)  // (0x52D000)
+#define MDTP_OK_BUTTON_OFFSET               (0x61D000)
+#define MDTP_SELECTED_OK_BUTTON_OFFSET      (0x668000)
+#define MDTP_DIGITS_INSTRUCTIONS_OFFSET     (0x6B3000)
+#define MDTP_PIN_INSTRUCTIONS_OFFSET        (0x75C000)
+
+// Image releative locations
+#define ERROR_MESSAGE_RELATIVE_Y_LOCATION   (0.18)
+#define MAIN_TEXT_RELATIVE_Y_LOCATION       (0.33)
+#define PIN_RELATIVE_Y_LOCATION             (0.47)
+#define PIN_TEXT_RELATIVE_Y_LOCATION        (0.57)
+#define OK_BUTTON_RELATIVE_Y_LOCATION       (0.75)
+#define OK_TEXT_RELATIVE_Y_LOCATION         (0.82)
+
+#define DIGIT_SPACE                         (12)
+
+#define MDTP_PRESSING_DELAY_MSEC            (400)
+#define MDTP_MAX_IMAGE_SIZE                 (1183000)  //size in bytes, includes some extra bytes since we round up to block size in read
+#define RGB888_BLACK                        (0x000000)
+#define BITS_PER_BYTE                       (8)
+
+
+#define CENTER_IMAGE_ON_X_AXIS(image_width,screen_width)         ((screen_width-image_width)/2)
+
 extern void mdelay(unsigned msecs);
+extern uint32_t target_volume_up();
+extern uint32_t target_volume_down();
 
-static struct fbimage mdtp_header;/* = {0};*/
+struct mdtp_fbimage {
+    uint32_t width;
+    uint32_t height;
+    uint8_t image[MDTP_MAX_IMAGE_SIZE];
+};
 
-/********************************************************************************/
+/*----------------------------------------------------------------------------
+ * Global Variables
+ * -------------------------------------------------------------------------*/
 
-/* Load the "Firmware Valid" image from EMMC */
-static struct fbimage* mdtp_images_mmc_OK()
+static uint32_t g_pin_frames_x_location[MDTP_MAX_PIN_LEN] = {0};
+static uint32_t g_pin_frames_y_location = 0;
+
+static bool g_initial_screen_displayed = false;
+
+static struct mdtp_fbimage g_mdtp_header;
+static struct fbcon_config *fb_config = NULL;
+
+/*----------------------------------------------------------------------------
+ * Local Functions
+ * -------------------------------------------------------------------------*/
+
+/**
+ * Load images from EMMC
+ */
+static struct mdtp_fbimage* mdtp_read_mmc_image(uint32_t offset, uint32_t width, uint32_t height)
 {
 	int index = INVALID_PTN;
 	unsigned long long ptn = 0;
-	struct fbcon_config *fb_display = NULL;
-	struct fbimage *logo = &mdtp_header;
+	struct mdtp_fbimage *logo = &g_mdtp_header;
 	uint32_t block_size = mmc_get_device_blocksize();
 
 	index = partition_get_index("mdtp");
@@ -71,231 +128,475 @@
 		return NULL;
 	}
 
-	fb_display = fbcon_display();
-	if (fb_display)
+	if (fb_config)
 	{
-		uint8_t *base = (uint8_t *) fb_display->base;
-		base += LOGO_IMG_OFFSET;
+		uint8_t *base = logo->image;
 
-		if (mmc_read(ptn, (void*)base, ROUNDUP(MDTP_IMAGE_WIDTH*MDTP_IMAGE_HEIGHT*3, block_size))) {
+		if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*3, block_size))) {
 				fbcon_clear();
 				dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
 				return NULL;
 		}
-		logo->image = base;
+		logo->width = width;
+		logo->height = height;
 	}
 
 	return logo;
 }
 
-/* Load the "Firmware Invalid" image from EMMC */
-static struct fbimage* mdtp_images_mmc_INVALID()
+/**
+ * flush fbcon display
+ *
+ * The function is duplicated from fbcon.c
+ */
+static void fbcon_flush(void)
 {
-	int index = INVALID_PTN;
-	unsigned long long ptn = 0;
-	struct fbcon_config *fb_display = NULL;
-	struct fbimage *logo = &mdtp_header;
-	uint32_t block_size = mmc_get_device_blocksize();
+	if (fb_config->update_start)
+		fb_config->update_start();
+	if (fb_config->update_done)
+		while (!fb_config->update_done());
+}
 
-	index = partition_get_index("mdtp");
-	if (index == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
-		return NULL;
-	}
+/**
+ * Clear complete section on the screen.
+ * The section is of section_height, and is located from the y
+ * coordinate and down.
+ */
+static void fbcon_clear_section(uint32_t y, uint32_t section_height)
+{
+	unsigned image_base;
+	unsigned bytes_per_bpp;
 
-	ptn = partition_get_offset(index);
-	if (ptn == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
-		return NULL;
-	}
-
-	fb_display = fbcon_display();
-	if (fb_display)
+	if (fb_config)
 	{
-		uint8_t *base = (uint8_t *) fb_display->base;
-		base += LOGO_IMG_OFFSET;
+	    image_base = (y *(fb_config->width));
+		bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
 
-		if (mmc_read(ptn+MDTP_INVALID_OFFSET, (void*)base, ROUNDUP(MDTP_IMAGE_WIDTH*MDTP_IMAGE_HEIGHT*3, block_size))) {
-				fbcon_clear();
-				dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
-				return NULL;
-		}
-		logo->image = base;
+		unsigned count = fb_config->width*section_height;
+		memset(fb_config->base + image_base*bytes_per_bpp, RGB888_BLACK, count*bytes_per_bpp);
+
+		fbcon_flush();
 	}
-
-	return logo;
-}
-
-/* Load the "Verifying Firmware" image from EMMC */
-static struct fbimage* mdtp_images_mmc_CHECKING()
-{
-	int index = INVALID_PTN;
-	unsigned long long ptn = 0;
-	struct fbcon_config *fb_display = NULL;
-	struct fbimage *logo = &mdtp_header;
-	uint32_t block_size = mmc_get_device_blocksize();
-
-	index = partition_get_index("mdtp");
-	if (index == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
-		return NULL;
-	}
-
-	ptn = partition_get_offset(index);
-	if (ptn == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
-		return NULL;
-	}
-
-	fb_display = fbcon_display();
-	if (fb_display)
+	else
 	{
-		uint8_t *base = (uint8_t *) fb_display->base;
-		base += LOGO_IMG_OFFSET;
-
-		if (mmc_read(ptn+MDTP_CHECKING_OFFSET, (void*)base, ROUNDUP(MDTP_IMAGE_WIDTH*MDTP_IMAGE_HEIGHT*3, block_size))) {
-				fbcon_clear();
-				dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
-				return NULL;
-		}
-		logo->image = base;
+	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+	    display_error_msg();
 	}
-
-	return logo;
 }
 
-/* Load the "Verifying Firmware" image from EMMC */
-static struct fbimage* mdtp_images_mmc_RECOVERED()
+/**
+ * Put image at a specific (x,y) location on the screen.
+ * Duplicated from fbcon.c, with modifications to allow (x,y) location (instead of a centered image),
+ * and display bmp images properly (order of copying the lines to the screen was reversed)
+ */
+static void fbcon_putImage_in_location(struct mdtp_fbimage *fbimg, uint32_t x, uint32_t y)
 {
-	int index = INVALID_PTN;
-	unsigned long long ptn = 0;
-	struct fbcon_config *fb_display = NULL;
-	struct fbimage *logo = &mdtp_header;
-	uint32_t block_size = mmc_get_device_blocksize();
+    unsigned i = 0;
+    unsigned bytes_per_bpp;
+    unsigned image_base;
+    unsigned width, pitch, height;
+    unsigned char *logo_base = NULL;
 
-	index = partition_get_index("mdtp");
-	if (index == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
-		return NULL;
+    if (!fb_config) {
+		dprintf(CRITICAL,"ERROR: NULL configuration, image cannot be displayed\n");
+		return;
 	}
 
-	ptn = partition_get_offset(index);
-	if (ptn == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
-		return NULL;
+	if(fbimg) {
+		width = pitch = fbimg->width;
+		height = fbimg->height;
+		logo_base = (unsigned char *)fbimg->image;
+	}
+	else {
+	    dprintf(CRITICAL,"ERROR: invalid image struct\n");
+	    return;
 	}
 
-	fb_display = fbcon_display();
-	if (fb_display)
+	bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
+
+#if DISPLAY_TYPE_MIPI
+	if (bytes_per_bpp == 3)
 	{
-		uint8_t *base = (uint8_t *) fb_display->base;
-		base += LOGO_IMG_OFFSET;
+		if (fbimg->width == fb_config->width && fbimg->height == fb_config->height)
+			return;
 
-		if (mmc_read(ptn+MDTP_RECOVERED_OFFSET, (void*)base, ROUNDUP(MDTP_IMAGE_WIDTH*MDTP_IMAGE_HEIGHT*3, block_size))) {
-				fbcon_clear();
-				dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
-				return NULL;
+		if (fbimg->width > fb_config->width || fbimg->height > fb_config->height)
+		{
+		    dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen\n");
+		    return;
 		}
-		logo->image = base;
+
+		image_base = ( (y *(fb_config->width)) + x);
+		for (i = 0; i < height; i++) {
+			memcpy (fb_config->base + ((image_base + (i * (fb_config->width))) * bytes_per_bpp),
+				logo_base + ((height - 1 - i) * pitch * bytes_per_bpp), width * bytes_per_bpp);
+		}
 	}
 
-	return logo;
+	fbcon_flush();
+
+#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
+	if(is_cmd_mode_enabled())
+        mipi_dsi_cmd_mode_trigger();
+#endif
+
+#else
+    if (bytes_per_bpp == 2)
+    {
+        for (i = 0; i < fbimg->width; i++)
+        {
+            memcpy (fb_config->base + ((image_base + (i * (fb_config->width))) * bytes_per_bpp),
+		   fbimg->image + (i * fbimg->height * bytes_per_bpp),
+		   fbimg->height * bytes_per_bpp);
+        }
+    }
+    fbcon_flush();
+#endif
 }
 
-/* Show the "Firmware Valid" image */
-static void display_image_on_screen_OK()
+/**
+ * Display main error message
+ */
+static int display_error_message()
 {
-	struct fbimage *fbimg;
+    struct mdtp_fbimage *fbimg;
 
-	fbcon_clear();
-	fbimg = mdtp_images_mmc_OK();
-	fbimg->header.width = MDTP_IMAGE_WIDTH;
-	fbimg->header.height = MDTP_IMAGE_HEIGHT;
+    fb_config = fbcon_display();
 
-	dprintf(CRITICAL, "display_image_on_screen_OK\n");
-	fbcon_putImage(fbimg, true);
+    if (fb_config)
+	{
+        uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_ERROR_MSG_WIDTH,fb_config->width);
+		uint32_t y = ((fb_config->height)*ERROR_MESSAGE_RELATIVE_Y_LOCATION);
+
+        fbimg = mdtp_read_mmc_image(MDTP_ERROR_MSG_OFFSET, MDTP_ERROR_MSG_WIDTH, MDTP_ERROR_MSG_HEIGHT);
+        if (NULL == fbimg)
+        {
+            dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
+            return -1;
+        }
+
+        fbcon_putImage_in_location(fbimg, x, y);
+
+		return 0;
+	}
+	else
+	{
+	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		return -1;
+	}
 }
 
-/* Show the "Firmware Invalid" image */
-static void display_image_on_screen_INVALID()
+/**
+ * Read from mmc the image in the given offset, of the given width and height.
+ * Then, display the image on the screen in the given (x,y) location.
+ */
+static void display_image(uint32_t offset, uint32_t width, uint32_t height, uint32_t x, uint32_t y)
 {
-	struct fbimage *fbimg;
+    struct mdtp_fbimage *fbimg;
 
-	fbcon_clear();
-	fbimg = mdtp_images_mmc_INVALID();
-	fbimg->header.width = MDTP_IMAGE_WIDTH;
-	fbimg->header.height = MDTP_IMAGE_HEIGHT;
+    if (fb_config)
+    {
+        fbimg = mdtp_read_mmc_image(offset, width, height);
+        if (NULL == fbimg)
+        {
+            dprintf(CRITICAL,"ERROR: failed to read image from mmc\n");
+            display_error_msg();
+        }
 
-	dprintf(CRITICAL, "display_image_on_screen_INVALID\n");
-	fbcon_putImage(fbimg, true);
+        fbcon_putImage_in_location(fbimg, x, y);
+    }
+    else
+    {
+        dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+        display_error_msg();
+    }
 }
 
-/* Show the "Verifying Firmware" image */
-static void display_image_on_screen_CHECKING()
+/**
+ * Display initial delay message
+ */
+static void display_initial_delay()
 {
-	struct fbimage *fbimg;
+    uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
+	uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
 
-	fbcon_clear();
-	fbimg = mdtp_images_mmc_CHECKING();
-	fbimg->header.width = MDTP_IMAGE_WIDTH;
-	fbimg->header.height = MDTP_IMAGE_HEIGHT;
-
-	dprintf(CRITICAL, "display_image_on_screen_CHECKING\n");
-	fbcon_putImage(fbimg, true);
+	display_image(MDTP_INITIAL_DELAY_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
 }
 
-/* Show the "Verifying Firmware" image */
-static void display_image_on_screen_RECOVERED()
+/**
+ * Display "enter PIN" message
+ */
+static void display_enter_pin()
 {
-	struct fbimage *fbimg;
+    uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
+	uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
 
-	fbcon_clear();
-	fbimg = mdtp_images_mmc_RECOVERED();
-	fbimg->header.width = MDTP_IMAGE_WIDTH;
-	fbimg->header.height = MDTP_IMAGE_HEIGHT;
-
-	dprintf(CRITICAL, "display_image_on_screen_RECOVERED\n");
-	fbcon_putImage(fbimg, true);
+	display_image(MDTP_ENTER_PIN_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
 }
 
-/* Display the "Firmware Valid" screen */
-void show_OK_msg()
+/**
+ * Display invalid PIN message
+ */
+static void display_invalid_pin()
 {
-	display_image_on_screen_OK();
-	mdelay(MDTP_UX_DELAY);
+    uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
+	uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
 
-	return;
+	display_image(MDTP_INVALID_PIN_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
 }
 
-/* Display the "Firmware Invalid" screen */
-void show_invalid_msg()
+/**
+ * Clear digits instructions
+ */
+static void display_digits_instructions()
 {
-	display_image_on_screen_INVALID();
+    uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_DIGITS_INSTRUCTIONS_WIDTH,fb_config->width);
+	uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
+
+	display_image(MDTP_DIGITS_INSTRUCTIONS_OFFSET, MDTP_DIGITS_INSTRUCTIONS_WIDTH, MDTP_DIGITS_INSTRUCTIONS_HEIGHT, x, y);
+}
+
+/**
+ * Clear digits instructions
+ */
+static void clear_digits_instructions()
+{
+    uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
+
+    fbcon_clear_section(y, MDTP_DIGITS_INSTRUCTIONS_HEIGHT);
+}
+
+/**
+ * Display a digit as un-selected.
+ */
+static void display_digit(uint32_t x, uint32_t y, uint32_t digit)
+{
+    display_image(MDTP_PIN_DIGIT_0_OFFSET + digit*MDTP_PIN_DIGITS_OFFSET,
+            MDTP_PIN_DIGIT_WIDTH, MDTP_PIN_DIGIT_HEIGHT, x, y);
+}
+
+/**
+ * Display a digit as selected.
+ */
+static void display_selected_digit(uint32_t x, uint32_t y, uint32_t digit)
+{
+    display_image(MDTP_PIN_SELECTED_DIGIT_0_OFFSET + digit*MDTP_PIN_DIGITS_OFFSET,
+			MDTP_PIN_DIGIT_WIDTH, MDTP_PIN_DIGIT_HEIGHT, x, y);
+}
+
+/**
+ * Display OK button as un-selected.
+ */
+static void display_ok_button()
+{
+    uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(MDTP_OK_BUTTON_WIDTH,fb_config->width);
+	uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
+
+	display_image(MDTP_OK_BUTTON_OFFSET, MDTP_OK_BUTTON_WIDTH, MDTP_OK_BUTTON_HEIGHT, ok_x, ok_y);
+}
+
+/**
+ * Display OK button as selected.
+ */
+static void display_selected_ok_button()
+{
+    uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(MDTP_OK_BUTTON_WIDTH,fb_config->width);
+	uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
+
+	display_image(MDTP_SELECTED_OK_BUTTON_OFFSET, MDTP_OK_BUTTON_WIDTH, MDTP_OK_BUTTON_HEIGHT,  ok_x, ok_y);
+}
+
+/**
+ * Display the instructions for the OK button.
+ */
+static void display_pin_instructions()
+{
+    uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_PIN_INSTRUCTIONS_WIDTH,fb_config->width);
+	uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
+
+	display_image(MDTP_PIN_INSTRUCTIONS_OFFSET, MDTP_PIN_INSTRUCTIONS_WIDTH, MDTP_PIN_INSTRUCTIONS_HEIGHT, x, y);
+}
+
+/**
+ * Clear the instructions for the OK button.
+ */
+static void clear_pin_message()
+{
+    uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
+
+	fbcon_clear_section(y, MDTP_PIN_INSTRUCTIONS_HEIGHT);
+}
+
+/**
+ * Display the basic layout of the screen (done only once).
+ */
+static void display_initial_screen(uint32_t pin_length)
+{
+    if (g_initial_screen_displayed == true)
+		return;
+
+    fb_config = fbcon_display();
+
+    if (fb_config)
+	{
+		fbcon_clear();
+
+		if (display_error_message())
+		    display_error_msg();
+		display_initial_delay();
+
+		mdelay(INITIAL_DELAY_MSECONDS);
+
+		g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION);
+
+		uint32_t total_pin_length = pin_length*MDTP_PIN_DIGIT_WIDTH + DIGIT_SPACE*(pin_length - 1);
+		uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
+
+		for (int i=0; i<(int)pin_length; i++)
+		{
+			g_pin_frames_x_location[i] = complete_pin_centered + i*(DIGIT_SPACE+MDTP_PIN_DIGIT_WIDTH);
+		}
+
+		for (int i=0; i<(int)pin_length; i++)
+		{
+			display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
+		}
+
+		display_ok_button();
+
+		g_initial_screen_displayed = true;
+	}
+	else
+	{
+	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+	    display_error_msg();
+		return;
+	}
+}
+
+/**
+ * Display the recovery PIN screen and set received buffer
+ * with the PIN the user has entered.
+ * The entered PIN will be validated by the calling function.
+ */
+static void display_get_pin_interface(char *entered_pin, uint32_t pin_length)
+{
+	uint32_t previous_position = 0, current_position = 0;
+
+	display_initial_screen(pin_length);
+	display_enter_pin();
+
+	// Convert ascii to digits
+	for (uint32_t i=0; i<pin_length; i++)
+	{
+		entered_pin[i] -= '0';
+	}
+	display_selected_digit(g_pin_frames_x_location[0], g_pin_frames_y_location, entered_pin[0]);
+	display_digits_instructions();
 
 	while (1)
 	{
-		if(target_volume_down())
+		if (target_volume_up())
 		{
-			display_image_on_screen_RECOVERED();
-			mdelay(MDTP_UX_DELAY);
-			break;
+			// current position is the OK button
+			if (current_position == pin_length)
+			{
+				// Convert digits to ascii and
+				// validate entered PIN in the calling function
+				for (uint32_t i=0; i<pin_length; i++)
+				{
+					entered_pin[i] += '0';
+				}
+				return;
+			}
+
+			// current position is a PIN slot
+			entered_pin[current_position] = (entered_pin[current_position]+1) % 10;
+			display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
+			mdelay(MDTP_PRESSING_DELAY_MSEC);
+		}
+		if (target_volume_down())
+		{
+			previous_position = current_position;
+			current_position = (current_position+1) % (pin_length+1);
+
+			// previous position was the OK button
+			if (previous_position == pin_length)
+			{
+				clear_pin_message();
+				display_ok_button();
+
+				display_digits_instructions();
+				display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
+
+			}
+
+			// current position is the OK button
+			else if (current_position == pin_length)
+			{
+				display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
+				clear_digits_instructions();
+
+				display_selected_ok_button();
+				display_pin_instructions();
+			}
+
+			// both the previous and the current positions are PIN slots
+			else
+			{
+				display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
+
+				display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
+			}
+
+			mdelay(MDTP_PRESSING_DELAY_MSEC);
 		}
 	}
+}
+
+/*----------------------------------------------------------------------------
+ * External Functions
+ * -------------------------------------------------------------------------*/
+
+/**
+ * Display the recovery PIN screen and set received buffer
+ * with the PIN the user has entered.
+ */
+void get_pin_from_user(char *entered_pin, uint32_t pin_length)
+{
+	display_get_pin_interface(entered_pin, pin_length);
 
 	return;
 }
 
-/* Display the "Verifying Firmware" screen */
-void show_checking_msg()
+/**
+ * User has entered invalid PIN, display error message and
+ * allow the user to try again.
+ */
+void display_invalid_pin_msg()
 {
-	display_image_on_screen_CHECKING();
-	return;
+    clear_pin_message();
+    display_ok_button();
+
+    display_invalid_pin();
+
+    mdelay(INVALID_PIN_DELAY_MSECONDS);
 }
 
-/* Display the "Verifying Firmware" screen */
-void show_recovered_msg()
+/**
+ *  Display error message and stop boot process.
+ */
+void display_error_msg()
 {
-	display_image_on_screen_RECOVERED();
-	return;
+    fbcon_clear();
+	display_error_message();   // No point in checking the return value here
+
+	// Invalid state. Nothing to be done but contacting the OEM.
+	// Stop boot process.
+	dprintf(CRITICAL,"ERROR: blocking boot process\n");
+	while(1)
+	{
+
+	}
 }
 
diff --git a/app/aboot/meta_format.h b/app/aboot/meta_format.h
new file mode 100644
index 0000000..7bf6812
--- /dev/null
+++ b/app/aboot/meta_format.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 _META_FORMAT_H_
+#define _META_FORMAT_H_
+
+#define META_HEADER_MAGIC  0xce1ad63c
+#define MAX_GPT_NAME_SIZE  72
+typedef unsigned int u32;
+typedef unsigned short int u16;
+
+typedef struct meta_header {
+  u32       magic;		    /* 0xce1ad63c */
+  u16       major_version;	/* (0x1) - reject images with higher major versions */
+  u16       minor_version;	/* (0x0) - allow images with higer minor versions */
+  char 	    img_version[64]; /* Top level version for images in this meta */
+  u16	    meta_hdr_sz;    /* size of this header */
+  u16	    img_hdr_sz;     /* size of img_header_entry list */
+} meta_header_t;
+
+typedef struct img_header_entry {
+  char      ptn_name[MAX_GPT_NAME_SIZE];
+  u32       start_offset;
+  u32       size;
+} img_header_entry_t;
+
+#endif
diff --git a/app/aboot/rules.mk b/app/aboot/rules.mk
index 95a8865..7774788 100644
--- a/app/aboot/rules.mk
+++ b/app/aboot/rules.mk
@@ -1,9 +1,11 @@
 LOCAL_DIR := $(GET_LOCAL_DIR)
 
-INCLUDES += -I$(LK_TOP_DIR)/platform/msm_shared/include
+INCLUDES += -I$(LK_TOP_DIR)/platform/msm_shared/include -I$(LK_TOP_DIR)/lib/zlib_inflate
 
 DEFINES += ASSERT_ON_TAMPER=1
 
+MODULES += lib/zlib_inflate
+
 OBJS += \
 	$(LOCAL_DIR)/aboot.o \
 	$(LOCAL_DIR)/fastboot.o \
diff --git a/app/rpmbtests/qseecom_lk_test.c b/app/rpmbtests/qseecom_lk_test.c
new file mode 100644
index 0000000..0bfcb9b
--- /dev/null
+++ b/app/rpmbtests/qseecom_lk_test.c
@@ -0,0 +1,358 @@
+/* Copyright (c) 2015, 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 <partition_parser.h>
+#include <qseecom_lk.h>
+#include <scm.h>
+
+//#include "qseecom_legacy.h"
+#include "qseecom_lk_api.h"
+#include <debug.h>
+#include <kernel/mutex.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <arch/defines.h>
+#include <string.h>
+
+/* commands supported from sample client */
+#define CLIENT_CMD0_GET_VERSION             0
+#define CLIENT_CMD1_BASIC_DATA              1
+#define CLIENT_CMD2_REGISTER_SB_PTR         2
+#define CLIENT_CMD3_RUN_CRYTPO_TEST         3
+#define CLIENT_CMD4_RUN_CRYTPO_PERF         4
+#define CLIENT_CMD5_RUN_SFS_TEST            5
+#define CLIENT_CMD6_RUN_BUF_ALIGNMENT_TEST  6
+#define CLIENT_CMD7_RUN_CRYPTO_RSA_TEST     7
+#define CLIENT_CMD8_RUN_RSA_PERF_TEST       8
+#define CLIENT_CMD9_RUN_CMNLIB_TEST         9
+#define CLIENT_CMD10_RUN_CORE_TEST          10
+#define CLIENT_CMD11_RUN_SECURECHANNEL_TEST 11
+#define CLIENT_CMD12_RUN_SERVICES_TEST      12
+#define CLIENT_CMD13_RUN_MISC_TEST          13
+#define CLIENT_CMD17_RUN_STORAGE_TEST       17
+#define CLIENT_APPSBL_QSEECOM_RUN_LISTENER_FRAMEWORK_TEST_1       50
+
+#define __64KB__ 0x10000
+#define __32KB__ 0x8000
+#define __16KB__ 0x4000
+#define __8KB__ 0x2000
+#define __4KB__ 0x1000
+#define __2KB__ 0x800
+#define __1KB__ 0x400
+
+#define LISTENER_TEST_SERVICE			0x100
+
+struct qsc_send_cmd {
+     unsigned int cmd_id;
+     unsigned int data;
+     unsigned int data2;
+     unsigned int len;
+     unsigned int start_pkt;
+     unsigned int end_pkt;
+     unsigned int test_buf_size;
+};
+
+struct qsc_send_cmd_rsp {
+  unsigned int data;
+  int status;
+};
+
+
+int listener_test_cmd_handler (void* buf, uint32_t size)
+{
+	uint32 *req = 0;
+	uint32 rsp = 0;
+
+	if ((!buf) || (size < 4)) {
+		dprintf(CRITICAL, "Invalid listener cmd handler inputs\n");
+		return -1;
+	}
+
+	req = (uint32 *)buf;
+	if (*req == (100 * 100)) {
+		dprintf(CRITICAL, "Listener Success\n");
+		rsp = *req * 100;
+		dprintf(CRITICAL, "rsp = %u\n", rsp);
+		memcpy (buf, &rsp, sizeof(uint32));
+		return 0;
+	} else {
+		dprintf(CRITICAL, "Listener Failure, req:%u\n", *req);
+		rsp = 0;
+		memcpy (buf, &rsp, sizeof(uint32));
+		return 0;
+	}
+}
+
+static struct qseecom_listener_services listeners[] = {
+		{
+			.service_name = "Listener Test service",
+			.id = LISTENER_TEST_SERVICE,
+			.sb_size = (20 * 1024),
+			.service_cmd_handler = listener_test_cmd_handler,
+		},
+};
+
+int qsc_run_get_version(char *appname, uint32_t iterations)
+{
+	struct qsc_send_cmd send_cmd;
+	struct qsc_send_cmd_rsp msgrsp={0};	/* response data sent from QSEE */
+	uint32_t i = 0, ret = 0, err = -1;
+
+	dprintf(CRITICAL, "%s:Get_version\n", __func__);
+
+	dprintf(CRITICAL, "(This may take a few minutes please wait....)\n");
+	/* Start the application */
+	for  (i = 0;  i < iterations;  i++) {
+		dprintf(CRITICAL, "iteration %d\n", i);
+		ret = qseecom_start_app(appname);
+		if (ret <= 0) {
+			dprintf(CRITICAL, "Start app: fail: ret:%d\n", ret);
+			err = -1;
+			goto err_ret;
+		}
+		dprintf(CRITICAL, "apphandle %u\n", ret);
+		ret = qseecom_start_app(appname);
+		if (ret <= 0) {
+			dprintf(CRITICAL, "Start app: fail: ret:%d\n", ret);
+			err = -1;
+			goto err_ret_shutdown;
+		}
+		dprintf(CRITICAL, "apphandle %u\n", ret);
+		send_cmd.cmd_id = CLIENT_CMD0_GET_VERSION;
+		err = qseecom_send_command(ret, &send_cmd, sizeof(struct qsc_send_cmd), &msgrsp, sizeof(struct qsc_send_cmd_rsp));
+		if (err) {
+			dprintf(CRITICAL, "Send app: fail\n");
+			goto err_ret_shutdown;
+		}
+		dprintf(ALWAYS, "The version of %s is: %u\n", appname, msgrsp.data);
+		/* Shutdown the application */
+		dprintf(ALWAYS, "Shutting down %s\n", appname);
+		err = qseecom_shutdown_app(ret);
+		if (err) {
+			dprintf(CRITICAL, "Failed to shutdown app: %d\n",err);
+			goto err_ret;
+		}
+		dprintf(ALWAYS, "Shutting down %s\n", appname);
+		err = qseecom_shutdown_app(ret);
+		if (err) {
+			dprintf(CRITICAL, "Failed to shutdown app: %d\n",err);
+			goto err_ret;
+		}
+
+    }
+err_ret_shutdown:
+	if (err) {
+		if (qseecom_shutdown_app(ret))
+			dprintf(CRITICAL, "Failed to shutdown app: %d\n",err);
+	}
+err_ret:
+	if (err)
+		dprintf(CRITICAL, "Test %u failed with error %d, shutting down %s\n", CLIENT_CMD0_GET_VERSION, err, appname);
+	else
+		dprintf(CRITICAL, "Test %u passed for iterations %u executing %s\n", CLIENT_CMD0_GET_VERSION, iterations, appname);
+	return err;
+}
+
+
+int qsc_run_start_stop_app_basic_test(char *appname, uint32_t iterations)
+{
+	uint32_t i = 0;
+	int ret = 0;			/* return value */
+	int err = 0;			/* return value */
+	struct qsc_send_cmd send_cmd = {0};
+	struct qsc_send_cmd_rsp msgrsp={0};	/* response data sent from QSEE */
+
+	dprintf(CRITICAL, "%s:Basic_start_stop_test\n", __func__);
+
+	dprintf(CRITICAL, "(This may take a few minutes please wait....)\n");
+	/* Start the application */
+    for  (i = 0;  i < iterations;  i++) {
+		dprintf(CRITICAL, "iteration %d\n", i);
+		ret = qseecom_start_app(appname);
+		if (ret <= 0) {
+			dprintf(CRITICAL, "Start app: fail: ret:%d\n", ret);
+			err = -1;
+			goto err_ret;
+		}
+		/* Send data using send command to QSEE application */
+		send_cmd.cmd_id = CLIENT_CMD1_BASIC_DATA;
+		send_cmd.start_pkt = 0;
+		send_cmd.end_pkt = 0;
+		send_cmd.test_buf_size = 0;
+		send_cmd.data = 100;
+		err = qseecom_send_command(ret, &send_cmd, sizeof(struct qsc_send_cmd), &msgrsp, sizeof(struct qsc_send_cmd_rsp));
+		if (err) {
+			dprintf(CRITICAL, "Send app: fail\n");
+			goto err_ret_shutdown;
+		}
+		if (((msgrsp.data)/100) != 10) {
+			dprintf(CRITICAL, "App Comm Error:%u\n", msgrsp.data);
+			err = -1;
+			goto err_ret_shutdown;
+		}
+		dprintf(CRITICAL, "msg.rsp:%u\n", msgrsp.data);
+		/* Shutdown the application */
+		err = qseecom_shutdown_app(ret);
+		if (err) {
+			dprintf(CRITICAL, "Failed to shutdown app: %d\n",err);
+			goto err_ret;
+		}
+    }
+err_ret_shutdown:
+    if (err) {
+		if (qseecom_shutdown_app(ret))
+			dprintf(CRITICAL, "Failed to shutdown app: %d\n",err);
+    }
+err_ret:
+	if (err)
+		dprintf(CRITICAL, "Test %u failed with error %d, shutting down %s\n", CLIENT_CMD0_GET_VERSION, err, appname);
+	else
+		dprintf(CRITICAL, "Test %u passed for iterations %u executing %s\n", CLIENT_CMD0_GET_VERSION, iterations, appname);
+		return err;
+}
+
+
+
+int qsc_run_start_stop_app_listener_test(char *appname, uint32_t iterations)
+{
+	uint32_t i = 0;
+	int ret = 0;			/* return value */
+	int err = 0;			/* return value */
+	struct qsc_send_cmd send_cmd;
+	struct qsc_send_cmd_rsp msgrsp={0};	/* response data sent from QSEE */
+
+	dprintf(CRITICAL, "%s:qsc_run_start_stop_app_listener_test\n", __func__);
+
+	dprintf(CRITICAL, "(This may take a few minutes please wait....)\n");
+
+	ret = qseecom_register_listener(&listeners[0]);
+	if (ret < 0) {
+		dprintf(CRITICAL, "Reg Listener: fail: ret:%d\n", ret);
+		err = -1;
+		goto err_ret;
+	}
+	/* Start the application */
+    for  (i = 0;  i < iterations;  i++) {
+		dprintf(CRITICAL, "iteration %d\n", i);
+		ret = qseecom_start_app(appname);
+		if (ret <= 0) {
+			dprintf(CRITICAL, "Start app: fail: ret:%d\n", ret);
+			err = -1;
+			goto err_dereg;
+		}
+		/* Send data using send command to QSEE application */
+		send_cmd.cmd_id = CLIENT_APPSBL_QSEECOM_RUN_LISTENER_FRAMEWORK_TEST_1;
+		send_cmd.start_pkt = 0;
+		send_cmd.end_pkt = 0;
+		send_cmd.test_buf_size = 0;
+		send_cmd.data = 100;
+		err = qseecom_send_command(ret, &send_cmd, sizeof(struct qsc_send_cmd), &msgrsp, sizeof(struct qsc_send_cmd_rsp));
+		if (err) {
+			dprintf(CRITICAL, "Send app: fail\n");
+			goto err_ret_shutdown;
+		}
+		if (((msgrsp.data)/100) != 10) {
+			dprintf(CRITICAL, "App Comm Error:%u Status:%d\n", msgrsp.data, msgrsp.status);
+			err = -1;
+			goto err_ret_shutdown;
+		}
+		/* Shutdown the application */
+		err = qseecom_shutdown_app(ret);
+		if (err) {
+			dprintf(CRITICAL, "Failed to shutdown app: %d\n",err);
+			goto err_dereg;
+		}
+    }
+
+err_ret_shutdown:
+	if (err) {
+	   	if (qseecom_shutdown_app(ret))
+	   		dprintf(CRITICAL, "Failed to shutdown app: %d\n",err);
+	}
+err_dereg:
+	ret = qseecom_deregister_listener(listeners[0].id);
+	if (ret < 0) {
+		dprintf(CRITICAL, "DeReg Listener: fail: ret:%d\n", ret);
+		err = -1;
+	}
+err_ret:
+	if (err)
+		dprintf(CRITICAL, "Test %u failed with error %d, shutting down %s\n", CLIENT_CMD0_GET_VERSION, err, appname);
+	else
+		dprintf(CRITICAL, "Test %u passed for iterations %u executing %s\n", CLIENT_CMD0_GET_VERSION, iterations, appname);
+	return err;
+}
+
+int qseecom_test_cmd_handler(const char *arg) {
+	char *token = NULL;
+	char * appname = NULL;
+	uint32_t test = 0;
+	uint32_t iterations = 0;
+
+	token = strtok((char *)arg, " ");
+	if (!token) {
+		dprintf(CRITICAL, "Appname not provided, error\n");
+		return -1;
+	}
+	appname = token;
+
+	token = strtok(NULL, " ");
+	if (!token) {
+		dprintf(CRITICAL, "Test not provided, error\n");
+		return -1;
+	}
+	test = atoi(token);
+
+	token = strtok(NULL, " ");
+	if (token)
+		iterations = atoi(token);
+	else
+		dprintf(CRITICAL, "iterations not provided\n");
+
+	switch (test) {
+		case CLIENT_CMD0_GET_VERSION:
+		{
+			qsc_run_get_version(appname, iterations);
+			break;
+		}
+		case CLIENT_CMD1_BASIC_DATA:
+		{
+			qsc_run_start_stop_app_basic_test(appname, iterations);
+			break;
+		}
+
+		case CLIENT_APPSBL_QSEECOM_RUN_LISTENER_FRAMEWORK_TEST_1:
+		{
+			qsc_run_start_stop_app_listener_test(appname, iterations);
+			break;
+		}
+	}
+	dprintf(CRITICAL, "test:%u iterations:%u\n", test, iterations);
+	return 0;
+}
+
diff --git a/app/rpmbtests/rules.mk b/app/rpmbtests/rules.mk
index b59dee9..f43c488 100644
--- a/app/rpmbtests/rules.mk
+++ b/app/rpmbtests/rules.mk
@@ -5,4 +5,5 @@
 DEFINES += ASSERT_ON_TAMPER=1
 
 OBJS += \
-	$(LOCAL_DIR)/ufs_rpmb.o
+	$(LOCAL_DIR)/ufs_rpmb.o \
+	$(LOCAL_DIR)/qseecom_lk_test.o
diff --git a/app/rpmbtests/ufs_rpmb.c b/app/rpmbtests/ufs_rpmb.c
index 7342a82..d951933 100644
--- a/app/rpmbtests/ufs_rpmb.c
+++ b/app/rpmbtests/ufs_rpmb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015 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
@@ -99,9 +99,11 @@
 	}
 	memset(&data_frame, 0, sizeof(data_frame));
 	memset(&result_frame, 0, sizeof(result_frame));
-	data_frame.address = BE16(address);
-	data_frame.blockcount = BE16(rpmb_num_blocks);
-	data_frame.requestresponse = BE16(AUTH_READ);
+	data_frame.address[0] = (address & 0xff00) >> 8;
+	data_frame.address[1] = address & 0x00ff;
+	data_frame.blockcount[0] = (rpmb_num_blocks & 0xff00) >> 8;
+	data_frame.blockcount[1] = rpmb_num_blocks & 0x00ff;
+	data_frame.requestresponse[1] = AUTH_READ;
 	for(i = 0 ; i < 16; i++)
 	{
 		data_frame.nonce[i] = (rand() % 256) + 1;
diff --git a/arch/arm/cache-ops.S b/arch/arm/cache-ops.S
index 22d9a2b..cfcbaa4 100644
--- a/arch/arm/cache-ops.S
+++ b/arch/arm/cache-ops.S
@@ -328,6 +328,7 @@
 
 	/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
 FUNCTION(arch_clean_invalidate_cache_range)
+	dsb
 	add 	r2, r0, r1					// Calculate the end address
 	bic 	r0,#(CACHE_LINE-1)			// Align start with cache line
 0:
diff --git a/dev/fbcon/fbcon.c b/dev/fbcon/fbcon.c
index e95036e..ce79a3e 100644
--- a/dev/fbcon/fbcon.c
+++ b/dev/fbcon/fbcon.c
@@ -2,7 +2,7 @@
  * Copyright (c) 2008, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2015, 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
@@ -35,6 +35,7 @@
 #include <splash.h>
 #include <platform.h>
 #include <string.h>
+#include <arch/ops.h>
 
 #include "font5x12.h"
 
@@ -300,6 +301,8 @@
 			memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
 				logo_base + (i * pitch * bytes_per_bpp), width * bytes_per_bpp);
 		}
+		/* Flush the contents to memory before giving the data to dma */
+		arch_clean_invalidate_cache_range((addr_t) config->base, (total_x * total_y * bytes_per_bpp));
 	}
 
 	fbcon_flush();
@@ -323,6 +326,8 @@
 				(header->height * bytes_per_bpp));
 		}
 	}
+	/* Flush the contents to memory before giving the data to dma */
+	arch_clean_invalidate_cache_range((addr_t) config->base, (total_x * total_y * bytes_per_bpp));
 	fbcon_flush();
 #endif
 }
diff --git a/dev/gcdb/display/gcdb_display.c b/dev/gcdb/display/gcdb_display.c
index 8e521b1..4a49b1b 100755
--- a/dev/gcdb/display/gcdb_display.c
+++ b/dev/gcdb/display/gcdb_display.c
@@ -210,6 +210,8 @@
 		goto splash_err;
 	}
 
+	mmc_set_lun(partition_get_lun(index));
+
 	blocksize = mmc_get_device_blocksize();
 	if (blocksize == 0) {
 		dprintf(CRITICAL, "ERROR:splash Partition invalid blocksize\n");
@@ -269,6 +271,8 @@
 		goto store_err;
 	}
 
+	mmc_set_lun(partition_get_lun(index));
+
 	ret = mmc_write(ptn, sizeof(uint32_t), &pinfo->dfps);
 	if (ret)
 		dprintf(CRITICAL, "mmc write failed!\n");
diff --git a/dev/gcdb/display/include/panel_auo_qvga_cmd.h b/dev/gcdb/display/include/panel_auo_qvga_cmd.h
new file mode 100644
index 0000000..4215108
--- /dev/null
+++ b/dev/gcdb/display/include/panel_auo_qvga_cmd.h
@@ -0,0 +1,310 @@
+/* Copyright (c) 2015, 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 BY THE COPYRIGHT HOLDERS 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
+ * 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 _PANEL_AUO_QVGA_CMD_H_
+#define _PANEL_AUO_QVGA_CMD_H_
+/*---------------------------------------------------------------------------*/
+/* HEADER files                                                              */
+/*---------------------------------------------------------------------------*/
+#include "panel.h"
+
+/*---------------------------------------------------------------------------*/
+/* Panel configuration                                                       */
+/*---------------------------------------------------------------------------*/
+static struct panel_config auo_qvga_cmd_panel_data = {
+	"qcom,mdss_dsi_auo_qvga_cmd", "dsi:0:", "qcom,mdss-dsi-panel",
+	10, 1, "DISPLAY_1", 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ""
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel resolution                                                          */
+/*---------------------------------------------------------------------------*/
+static struct panel_resolution auo_qvga_cmd_panel_res = {
+	320, 320, 4, 4, 4, 0, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel color information                                                   */
+/*---------------------------------------------------------------------------*/
+static struct color_info auo_qvga_cmd_color = {
+	24, 0, 0xff, 0, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel on/off command information                                          */
+/*---------------------------------------------------------------------------*/
+static char auo_qvga_cmd_on_cmd0[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x00, 0xFF, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd1[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xBD, 0x01, 0x90, 0x14,
+	0x14, 0x00, 0xFF, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd2[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xBE, 0x01, 0x90, 0x14,
+	0x14, 0x01, 0xFF, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd3[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xBF, 0x01, 0x90, 0x14,
+	0x14, 0x00, 0xFF, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd4[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xBB, 0x07, 0x07, 0x07,
+};
+
+static char auo_qvga_cmd_on_cmd5[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0xC7, 0x40, 0xFF, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd6[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x02, 0xFF, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd7[] = {
+	0x03, 0x00, 0x39, 0xC0,
+	0xFE, 0x08, 0x50, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd8[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xC3, 0xF2, 0x95, 0x04,
+};
+
+static char auo_qvga_cmd_on_cmd9[] = {
+	0x04, 0x00, 0x15, 0x80,
+};
+
+static char auo_qvga_cmd_on_cmd10[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x01, 0xFF, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd11[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB0, 0x03, 0x03, 0x03,
+};
+
+static char auo_qvga_cmd_on_cmd12[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB1, 0x05, 0x05, 0x05,
+};
+
+static char auo_qvga_cmd_on_cmd13[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB2, 0x01, 0x01, 0x01,
+};
+
+static char auo_qvga_cmd_on_cmd14[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB4, 0x07, 0x07, 0x07,
+};
+
+static char auo_qvga_cmd_on_cmd15[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB5, 0x03, 0x03, 0x03,
+};
+
+static char auo_qvga_cmd_on_cmd16[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB6, 0x53, 0x53, 0x53,
+};
+
+static char auo_qvga_cmd_on_cmd17[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB7, 0x33, 0x33, 0x33,
+};
+
+static char auo_qvga_cmd_on_cmd18[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB8, 0x23, 0x23, 0x23,
+};
+
+static char auo_qvga_cmd_on_cmd19[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xB9, 0x03, 0x03, 0x03,
+};
+
+static char auo_qvga_cmd_on_cmd20[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xBA, 0x03, 0x03, 0x03,
+};
+
+static char auo_qvga_cmd_on_cmd21[] = {
+	0x04, 0x00, 0x39, 0xC0,
+	0xBE, 0x32, 0x30, 0x70,
+};
+
+static char auo_qvga_cmd_on_cmd22[] = {
+	0x08, 0x00, 0x39, 0xC0,
+	0xCF, 0xFF, 0xD4, 0x95,
+	0xEF, 0x4F, 0x00, 0x04,
+};
+
+static char auo_qvga_cmd_on_cmd23[] = {
+	0x35, 0x01, 0x15, 0x80,
+};
+
+static char auo_qvga_cmd_on_cmd24[] = {
+	0x36, 0x01, 0x15, 0x80,
+};
+
+static char auo_qvga_cmd_on_cmd25[] = {
+	0xC0, 0x20, 0x15, 0x80,
+};
+
+static char auo_qvga_cmd_on_cmd26[] = {
+	0x07, 0x00, 0x39, 0xC0,
+	0xC2, 0x17, 0x17, 0x17,
+	0x17, 0x17, 0x0B, 0xFF,
+};
+
+static char auo_qvga_cmd_on_cmd27[] = {
+	0x00, 0x00, 0x32, 0x80,
+};
+
+static char auo_qvga_cmd_on_cmd28[] = {
+	0x11, 0x00, 0x05, 0x80,
+};
+
+static char auo_qvga_cmd_on_cmd29[] = {
+	0x29, 0x00, 0x05, 0x80,
+};
+
+static struct mipi_dsi_cmd auo_qvga_cmd_on_command[] = {
+	{0xc, auo_qvga_cmd_on_cmd0, 0x00},
+	{0xc, auo_qvga_cmd_on_cmd1, 0x00},
+	{0xc, auo_qvga_cmd_on_cmd2, 0x00},
+	{0xc, auo_qvga_cmd_on_cmd3, 0x10},
+	{0x8, auo_qvga_cmd_on_cmd4, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd5, 0x00},
+	{0xc, auo_qvga_cmd_on_cmd6, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd7, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd8, 0x00},
+	{0x4, auo_qvga_cmd_on_cmd9, 0x00},
+	{0xc, auo_qvga_cmd_on_cmd10, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd11, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd12, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd13, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd14, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd15, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd16, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd17, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd18, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd19, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd20, 0x00},
+	{0x8, auo_qvga_cmd_on_cmd21, 0x00},
+	{0xc, auo_qvga_cmd_on_cmd22, 0x00},
+	{0x4, auo_qvga_cmd_on_cmd23, 0x00},
+	{0x4, auo_qvga_cmd_on_cmd24, 0x00},
+	{0x4, auo_qvga_cmd_on_cmd25, 0x00},
+	{0xc, auo_qvga_cmd_on_cmd26, 0x00},
+	{0x4, auo_qvga_cmd_on_cmd27, 0x00},
+	{0x4, auo_qvga_cmd_on_cmd28, 0xFF},
+	{0x4, auo_qvga_cmd_on_cmd29, 0x00}
+};
+
+#define auo_QVGA_CMD_ON_COMMAND 30
+
+static char auo_qvga_cmdoff_cmd0[] = {
+	0x28, 0x00, 0x05, 0x80
+};
+
+static char auo_qvga_cmdoff_cmd1[] = {
+	0x10, 0x00, 0x05, 0x80
+};
+
+static struct mipi_dsi_cmd auo_qvga_cmd_off_command[] = {
+	{0x4, auo_qvga_cmdoff_cmd0, 0x32},
+	{0x4, auo_qvga_cmdoff_cmd1, 0x78}
+};
+
+#define auo_QVGA_CMD_OFF_COMMAND 2
+
+static struct command_state auo_qvga_cmd_state = {
+	0, 1
+};
+
+/*---------------------------------------------------------------------------*/
+/* Command mode panel information                                            */
+/*---------------------------------------------------------------------------*/
+static struct commandpanel_info auo_qvga_cmd_command_panel = {
+	1, 1, 1, 0, 0, 0x2c, 0, 0, 0, 1, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Video mode panel information                                              */
+/*---------------------------------------------------------------------------*/
+static struct videopanel_info auo_qvga_cmd_video_panel = {
+	1, 0, 0, 0, 1, 1, 2, 0, 0x9
+};
+
+/*---------------------------------------------------------------------------*/
+/* Lane configuration                                                        */
+/*---------------------------------------------------------------------------*/
+static struct lane_configuration auo_qvga_cmd_lane_config = {
+	1, 0, 1, 0, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel timing                                                              */
+/*---------------------------------------------------------------------------*/
+static const uint32_t auo_qvga_cmd_timings[] = {
+	0x5F, 0x12, 0x0A, 0x00, 0x32, 0x34, 0x10, 0x16, 0x0F, 0x03, 0x04, 0x00
+};
+
+static struct panel_timing auo_qvga_cmd_timing_info = {
+	0, 4, 0x05, 0x15
+};
+
+static struct panel_reset_sequence auo_qvga_cmd_panel_reset_seq = {
+	{ 1, 0, 1, }, { 20, 20, 20, }, 2
+};
+
+/*---------------------------------------------------------------------------*/
+/* Backlight setting                                                         */
+/*---------------------------------------------------------------------------*/
+static struct backlight auo_qvga_cmd_backlight = {
+	2, 1, 255, 100, 1, "PMIC_8941"
+};
+
+#endif /*_PANEL_AUO_QVGA_CMD_H_*/
diff --git a/dev/gcdb/display/include/panel_hx8394d_720p_video.h b/dev/gcdb/display/include/panel_hx8394d_720p_video.h
index 3ab32f8..ac4806f 100644
--- a/dev/gcdb/display/include/panel_hx8394d_720p_video.h
+++ b/dev/gcdb/display/include/panel_hx8394d_720p_video.h
@@ -283,6 +283,6 @@
   1, 1, 4095, 100, 1, "PMIC_8941"
 };
 
-#define HX8394D_720P_VIDEO_SIGNATURE 0xFFFF
+#define HX8394D_720P_VIDEO_SIGNATURE 0xa0087
 
 #endif /*_HX8394D_720P_VIDEO_H_*/
diff --git a/dev/gcdb/display/include/panel_hx8394d_qhd_video.h b/dev/gcdb/display/include/panel_hx8394d_qhd_video.h
index 82d3b41..c04fccb 100644
--- a/dev/gcdb/display/include/panel_hx8394d_qhd_video.h
+++ b/dev/gcdb/display/include/panel_hx8394d_qhd_video.h
@@ -207,6 +207,21 @@
 };
 #define HX8394D_QHD_VIDEO_ON_COMMAND 16
 
+static char hx8394d_qhd_video_off_cmd0[] = {
+	0x28, 0x00, 0x05, 0x80
+};
+
+static char hx8394d_qhd_video_off_cmd1[] = {
+	0x10, 0x00, 0x05, 0x80
+};
+
+static struct mipi_dsi_cmd hx8394d_qhd_video_off_command[] = {
+	{0x4, hx8394d_qhd_video_off_cmd0, 0x32},
+	{0x4, hx8394d_qhd_video_off_cmd1, 0x78}
+};
+
+#define HX8394D_QHD_VIDEO_OFF_COMMAND 2
+
 static struct command_state hx8394d_qhd_video_state = {
 	0, 1
 };
diff --git a/dev/gcdb/display/include/panel_ili9806e_fwvga_video.h b/dev/gcdb/display/include/panel_ili9806e_fwvga_video.h
index c4941c5..1055c3c 100644
--- a/dev/gcdb/display/include/panel_ili9806e_fwvga_video.h
+++ b/dev/gcdb/display/include/panel_ili9806e_fwvga_video.h
@@ -87,12 +87,12 @@
 
 static char ili9806e_fwvga_video_on_cmd4[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x31, 0x00, 0xFF, 0xFF,
+	0x31, 0x02, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd5[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x40, 0x16, 0xFF, 0xFF,
+	0x40, 0x1A, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd6[] = {
@@ -107,22 +107,22 @@
 
 static char ili9806e_fwvga_video_on_cmd8[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x43, 0x89, 0xFF, 0xFF,
+	0x43, 0x09, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd9[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x44, 0x06, 0xFF, 0xFF,
+	0x44, 0x09, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd10[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x50, 0x80, 0xFF, 0xFF,
+	0x50, 0x78, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd11[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x51, 0x80, 0xFF, 0xFF,
+	0x51, 0x78, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd12[] = {
@@ -132,497 +132,2791 @@
 
 static char ili9806e_fwvga_video_on_cmd13[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x53, 0x43, 0xFF, 0xFF,
+	0x53, 0x2B, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd14[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x60, 0x07, 0xFF, 0xFF,
+	0x57, 0x50, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd15[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x61, 0x00, 0xFF, 0xFF,
+	0x60, 0x07, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd16[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x62, 0x07, 0xFF, 0xFF,
+	0x61, 0x00, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd17[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x63, 0x00, 0xFF, 0xFF,
+	0x62, 0x08, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd18[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA0, 0x00, 0xFF, 0xFF,
+	0x63, 0x00, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd19[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA1, 0x01, 0xFF, 0xFF,
+	0xA0, 0x00, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd20[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA2, 0x0A, 0xFF, 0xFF,
+	0xA1, 0x06, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd21[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA3, 0x10, 0xFF, 0xFF,
+	0xA2, 0x10, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd22[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA4, 0x0B, 0xFF, 0xFF,
+	0xA3, 0x11, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd23[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA5, 0x1C, 0xFF, 0xFF,
+	0xA4, 0x08, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd24[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA6, 0x0B, 0xFF, 0xFF,
+	0xA5, 0x1A, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd25[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA7, 0x09, 0xFF, 0xFF,
+	0xA6, 0x09, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd26[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA8, 0x05, 0xFF, 0xFF,
+	0xA7, 0x08, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd27[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xA9, 0x0B, 0xFF, 0xFF,
+	0xA8, 0x05, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd28[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xAA, 0x07, 0xFF, 0xFF,
+	0xA9, 0x0A, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd29[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xAB, 0x06, 0xFF, 0xFF,
+	0xAA, 0x04, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd30[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xAC, 0x0E, 0xFF, 0xFF,
+	0xAB, 0x08, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd31[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xAD, 0x29, 0xFF, 0xFF,
+	0xAC, 0x10, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd32[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xAE, 0x25, 0xFF, 0xFF,
+	0xAD, 0x38, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd33[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xAF, 0x00, 0xFF, 0xFF,
+	0xAE, 0x34, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd34[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC0, 0x00, 0xFF, 0xFF,
+	0xAF, 0x00, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd35[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC1, 0x02, 0xFF, 0xFF,
+	0xC0, 0x00, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd36[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC2, 0x07, 0xFF, 0xFF,
+	0xC1, 0x07, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd37[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC3, 0x0C, 0xFF, 0xFF,
+	0xC2, 0x15, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd38[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC4, 0x06, 0xFF, 0xFF,
+	0xC3, 0x11, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd39[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC5, 0x18, 0xFF, 0xFF,
+	0xC4, 0x0A, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd40[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC6, 0x0B, 0xFF, 0xFF,
+	0xC5, 0x18, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd41[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC7, 0x0A, 0xFF, 0xFF,
+	0xC6, 0x08, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd42[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC8, 0x02, 0xFF, 0xFF,
+	0xC7, 0x07, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd43[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xC9, 0x06, 0xFF, 0xFF,
+	0xC8, 0x03, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd44[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xCA, 0x03, 0xFF, 0xFF,
+	0xC9, 0x08, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd45[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xCB, 0x03, 0xFF, 0xFF,
+	0xCA, 0x07, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd46[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xCC, 0x0B, 0xFF, 0xFF,
+	0xCB, 0x05, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd47[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xCD, 0x2A, 0xFF, 0xFF,
+	0xCC, 0x0C, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd48[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xCE, 0x25, 0xFF, 0xFF,
+	0xCD, 0x1E, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd49[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0xCF, 0x00, 0xFF, 0xFF,
+	0xCE, 0x1A, 0xFF, 0xFF,
 };
 
 static char ili9806e_fwvga_video_on_cmd50[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0xCF, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd51[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xFF, 0xFF, 0x98, 0x06,
+	0x04, 0x02, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd52[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x40, 0x01, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd53[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x00, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd54[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x01, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd55[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x02, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd56[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x03, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd57[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x04, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd58[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x05, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd59[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x06, 0x09, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd60[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x07, 0x19, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd61[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x08, 0x19, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd62[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x09, 0x19, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd63[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0A, 0x19, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd64[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0B, 0x19, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd65[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0C, 0x1C, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd66[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0D, 0x1C, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd67[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0E, 0x1C, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd68[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0F, 0x1C, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd69[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x10, 0x1D, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd70[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x11, 0x1D, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd71[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x12, 0x1D, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd72[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x13, 0x1D, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd73[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x14, 0x1D, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd74[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x15, 0x3E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd75[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x16, 0x3E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd76[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x17, 0x3E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd77[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x18, 0x3E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd78[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x19, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd79[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1A, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd80[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1B, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd81[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1C, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd82[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1D, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd83[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1E, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd84[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1F, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd85[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x20, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd86[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x21, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd87[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x22, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd88[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x23, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd89[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x24, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd90[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x25, 0x4E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd91[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x26, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd92[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x27, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd93[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x28, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd94[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x29, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd95[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2A, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd96[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2B, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd97[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2C, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd98[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2D, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd99[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2E, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd100[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2F, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd101[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x30, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd102[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x31, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd103[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x32, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd104[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x33, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd105[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x34, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd106[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x35, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd107[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x36, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd108[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x37, 0x5E, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd109[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x38, 0x5C, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd110[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x39, 0x4C, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd111[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3A, 0x4C, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd112[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3B, 0x3B, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd113[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3C, 0x3B, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd114[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3D, 0x2A, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd115[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3E, 0x10, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd116[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd117[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xFF, 0xFF, 0x98, 0x06,
+	0x04, 0x03, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd118[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x00, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd119[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x01, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd120[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x02, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd121[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x03, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd122[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x04, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd123[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x05, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd124[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x06, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd125[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x07, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd126[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x08, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd127[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x09, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd128[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd129[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd130[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd131[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd132[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd133[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd134[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x10, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd135[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x11, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd136[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x12, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd137[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x13, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd138[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x14, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd139[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x15, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd140[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x16, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd141[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x17, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd142[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x18, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd143[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x19, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd144[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd145[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd146[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd147[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd148[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd149[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd150[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x20, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd151[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x21, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd152[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x22, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd153[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x23, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd154[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x24, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd155[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x25, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd156[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x26, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd157[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x27, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd158[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x28, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd159[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x29, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd160[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd161[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd162[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd163[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd164[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd165[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd166[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x30, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd167[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x31, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd168[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x32, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd169[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x33, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd170[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x34, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd171[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x35, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd172[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x36, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd173[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x37, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd174[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x38, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd175[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x39, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd176[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd177[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd178[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd179[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd180[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd181[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd182[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x40, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd183[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x41, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd184[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x42, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd185[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x43, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd186[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x44, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd187[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x45, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd188[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x46, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd189[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x47, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd190[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x48, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd191[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x49, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd192[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd193[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd194[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd195[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd196[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd197[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd198[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x50, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd199[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x51, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd200[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x52, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd201[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x53, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd202[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x54, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd203[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x55, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd204[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x56, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd205[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x57, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd206[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x58, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd207[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x59, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd208[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd209[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd210[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd211[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd212[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd213[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd214[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x60, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd215[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x61, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd216[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x62, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd217[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x63, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd218[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x64, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd219[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x65, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd220[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x66, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd221[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x67, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd222[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x68, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd223[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x69, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd224[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd225[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd226[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd227[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd228[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd229[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd230[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x70, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd231[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x71, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd232[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x72, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd233[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x73, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd234[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x74, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd235[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x75, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd236[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x76, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd237[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x77, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd238[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x78, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd239[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x79, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd240[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd241[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd242[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd243[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd244[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd245[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd246[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xFF, 0xFF, 0x98, 0x06,
+	0x04, 0x04, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd247[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x00, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd248[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x01, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd249[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x02, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd250[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x03, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd251[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x04, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd252[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x05, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd253[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x06, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd254[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x07, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd255[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x08, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd256[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x09, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd257[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd258[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd259[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd260[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd261[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd262[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd263[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x10, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd264[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x11, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd265[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x12, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd266[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x13, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd267[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x14, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd268[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x15, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd269[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x16, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd270[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x17, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd271[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x18, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd272[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x19, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd273[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd274[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd275[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd276[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd277[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd278[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd279[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x20, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd280[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x21, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd281[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x22, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd282[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x23, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd283[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x24, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd284[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x25, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd285[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x26, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd286[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x27, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd287[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x28, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd288[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x29, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd289[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd290[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd291[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd292[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd293[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd294[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd295[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x30, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd296[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x31, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd297[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x32, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd298[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x33, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd299[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x34, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd300[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x35, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd301[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x36, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd302[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x37, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd303[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x38, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd304[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x39, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd305[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd306[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd307[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd308[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd309[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd310[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd311[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x40, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd312[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x41, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd313[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x42, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd314[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x43, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd315[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x44, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd316[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x45, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd317[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x46, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd318[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x47, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd319[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x48, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd320[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x49, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd321[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd322[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd323[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd324[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd325[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd326[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd327[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x50, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd328[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x51, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd329[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x52, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd330[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x53, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd331[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x54, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd332[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x55, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd333[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x56, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd334[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x57, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd335[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x58, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd336[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x59, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd337[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd338[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd339[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd340[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd341[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd342[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd343[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x60, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd344[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x61, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd345[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x62, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd346[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x63, 0x10, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd347[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x64, 0x10, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd348[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x65, 0x20, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd349[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x66, 0x10, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd350[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x67, 0x10, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd351[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x68, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd352[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x69, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd353[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd354[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd355[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd356[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd357[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd358[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd359[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x70, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd360[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x71, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd361[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x72, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd362[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x73, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd363[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x74, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd364[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x75, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd365[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x76, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd366[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x77, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd367[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x78, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd368[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x79, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd369[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd370[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd371[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd372[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd373[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd374[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd375[] = {
+	0x06, 0x00, 0x39, 0xC0,
+	0xFF, 0xFF, 0x98, 0x06,
+	0x04, 0x04, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd376[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x00, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd377[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x01, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd378[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x02, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd379[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x03, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd380[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x04, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd381[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x05, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd382[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x06, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd383[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x07, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd384[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x08, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd385[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x09, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd386[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd387[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd388[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd389[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd390[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd391[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x0F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd392[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x10, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd393[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x11, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd394[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x12, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd395[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x13, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd396[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x14, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd397[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x15, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd398[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x16, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd399[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x17, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd400[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x18, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd401[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x19, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd402[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd403[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd404[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd405[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd406[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd407[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x1F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd408[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x20, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd409[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x21, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd410[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x22, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd411[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x23, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd412[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x24, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd413[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x25, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd414[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x26, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd415[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x27, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd416[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x28, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd417[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x29, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd418[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd419[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd420[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd421[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd422[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd423[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x2F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd424[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x30, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd425[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x31, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd426[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x32, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd427[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x33, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd428[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x34, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd429[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x35, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd430[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x36, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd431[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x37, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd432[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x38, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd433[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x39, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd434[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd435[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd436[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd437[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd438[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd439[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x3F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd440[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x40, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd441[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x41, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd442[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x42, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd443[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x43, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd444[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x44, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd445[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x45, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd446[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x46, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd447[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x47, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd448[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x48, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd449[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x49, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd450[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd451[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd452[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd453[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd454[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd455[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x4F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd456[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x50, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd457[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x51, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd458[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x52, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd459[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x53, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd460[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x54, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd461[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x55, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd462[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x56, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd463[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x57, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd464[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x58, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd465[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x59, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd466[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd467[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd468[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd469[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd470[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd471[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x5F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd472[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x60, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd473[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x61, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd474[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x62, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd475[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x63, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd476[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x64, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd477[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x65, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd478[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x66, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd479[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x67, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd480[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x68, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd481[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x69, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd482[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd483[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd484[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd485[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd486[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd487[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x6F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd488[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x70, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd489[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x71, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd490[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x72, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd491[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x73, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd492[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x74, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd493[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x75, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd494[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x76, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd495[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x77, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd496[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x78, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd497[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x79, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd498[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7A, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd499[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7B, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd500[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7C, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd501[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7D, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd502[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7E, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd503[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x7F, 0x00, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd504[] = {
 	0x06, 0x00, 0x39, 0xC0,
 	0xFF, 0xFF, 0x98, 0x06,
 	0x04, 0x06, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd51[] = {
+static char ili9806e_fwvga_video_on_cmd505[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x00, 0x20, 0xFF, 0xFF,
+	0x00, 0x21, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd52[] = {
+static char ili9806e_fwvga_video_on_cmd506[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x01, 0x0A, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd53[] = {
+static char ili9806e_fwvga_video_on_cmd507[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x02, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd54[] = {
+static char ili9806e_fwvga_video_on_cmd508[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x03, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd55[] = {
+static char ili9806e_fwvga_video_on_cmd509[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x04, 0x01, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd56[] = {
+static char ili9806e_fwvga_video_on_cmd510[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x05, 0x01, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd57[] = {
+static char ili9806e_fwvga_video_on_cmd511[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x06, 0x98, 0xFF, 0xFF,
+	0x06, 0x80, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd58[] = {
+static char ili9806e_fwvga_video_on_cmd512[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x07, 0x06, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd59[] = {
+static char ili9806e_fwvga_video_on_cmd513[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x08, 0x01, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd60[] = {
+static char ili9806e_fwvga_video_on_cmd514[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x09, 0x80, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd61[] = {
+static char ili9806e_fwvga_video_on_cmd515[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x0A, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd62[] = {
+static char ili9806e_fwvga_video_on_cmd516[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x0B, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd63[] = {
+static char ili9806e_fwvga_video_on_cmd517[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x0C, 0x01, 0xFF, 0xFF,
+	0x0C, 0x0A, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd64[] = {
+static char ili9806e_fwvga_video_on_cmd518[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x0D, 0x01, 0xFF, 0xFF,
+	0x0D, 0x0A, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd65[] = {
+static char ili9806e_fwvga_video_on_cmd519[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x0E, 0x05, 0xFF, 0xFF,
+	0x0E, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd66[] = {
+static char ili9806e_fwvga_video_on_cmd520[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x0F, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd67[] = {
+static char ili9806e_fwvga_video_on_cmd521[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x10, 0xF0, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd68[] = {
+static char ili9806e_fwvga_video_on_cmd522[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x11, 0xF4, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd69[] = {
+static char ili9806e_fwvga_video_on_cmd523[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x12, 0x01, 0xFF, 0xFF,
+	0x12, 0x04, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd70[] = {
+static char ili9806e_fwvga_video_on_cmd524[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x13, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd71[] = {
+static char ili9806e_fwvga_video_on_cmd525[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x14, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd72[] = {
+static char ili9806e_fwvga_video_on_cmd526[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x15, 0xC0, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd73[] = {
+static char ili9806e_fwvga_video_on_cmd527[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x16, 0x08, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd74[] = {
+static char ili9806e_fwvga_video_on_cmd528[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x17, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd75[] = {
+static char ili9806e_fwvga_video_on_cmd529[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x18, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd76[] = {
+static char ili9806e_fwvga_video_on_cmd530[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x19, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd77[] = {
+static char ili9806e_fwvga_video_on_cmd531[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x1A, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd78[] = {
+static char ili9806e_fwvga_video_on_cmd532[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x1B, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd79[] = {
+static char ili9806e_fwvga_video_on_cmd533[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x1C, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd80[] = {
+static char ili9806e_fwvga_video_on_cmd534[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x1D, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd81[] = {
+static char ili9806e_fwvga_video_on_cmd535[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x20, 0x01, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd82[] = {
+static char ili9806e_fwvga_video_on_cmd536[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x21, 0x23, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd83[] = {
+static char ili9806e_fwvga_video_on_cmd537[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x22, 0x45, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd84[] = {
+static char ili9806e_fwvga_video_on_cmd538[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x23, 0x67, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd85[] = {
+static char ili9806e_fwvga_video_on_cmd539[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x24, 0x01, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd86[] = {
+static char ili9806e_fwvga_video_on_cmd540[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x25, 0x23, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd87[] = {
+static char ili9806e_fwvga_video_on_cmd541[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x26, 0x45, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd88[] = {
+static char ili9806e_fwvga_video_on_cmd542[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x27, 0x67, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd89[] = {
+static char ili9806e_fwvga_video_on_cmd543[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x30, 0x11, 0xFF, 0xFF,
+	0x30, 0x01, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd90[] = {
+static char ili9806e_fwvga_video_on_cmd544[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x31, 0x11, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd91[] = {
+static char ili9806e_fwvga_video_on_cmd545[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x32, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd92[] = {
+static char ili9806e_fwvga_video_on_cmd546[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x33, 0xEE, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd93[] = {
+static char ili9806e_fwvga_video_on_cmd547[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x34, 0xFF, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd94[] = {
+static char ili9806e_fwvga_video_on_cmd548[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x35, 0xBB, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd95[] = {
+static char ili9806e_fwvga_video_on_cmd549[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x36, 0xAA, 0xFF, 0xFF,
+	0x36, 0xCA, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd96[] = {
+static char ili9806e_fwvga_video_on_cmd550[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x37, 0xDD, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd97[] = {
+static char ili9806e_fwvga_video_on_cmd551[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x38, 0xCC, 0xFF, 0xFF,
+	0x38, 0xAC, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd98[] = {
+static char ili9806e_fwvga_video_on_cmd552[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x39, 0x66, 0xFF, 0xFF,
+	0x39, 0x76, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd99[] = {
+static char ili9806e_fwvga_video_on_cmd553[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x3A, 0x77, 0xFF, 0xFF,
+	0x3A, 0x67, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd100[] = {
+static char ili9806e_fwvga_video_on_cmd554[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x3B, 0x22, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd101[] = {
+static char ili9806e_fwvga_video_on_cmd555[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x3C, 0x22, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd102[] = {
+static char ili9806e_fwvga_video_on_cmd556[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x3D, 0x22, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd103[] = {
+static char ili9806e_fwvga_video_on_cmd557[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x3E, 0x22, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd104[] = {
+static char ili9806e_fwvga_video_on_cmd558[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x3F, 0x22, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd105[] = {
+static char ili9806e_fwvga_video_on_cmd559[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x40, 0x22, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd106[] = {
+static char ili9806e_fwvga_video_on_cmd560[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x52, 0x10, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd561[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x53, 0x10, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd562[] = {
 	0x06, 0x00, 0x39, 0xC0,
 	0xFF, 0xFF, 0x98, 0x06,
 	0x04, 0x07, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd107[] = {
+static char ili9806e_fwvga_video_on_cmd563[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x17, 0x22, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd108[] = {
+static char ili9806e_fwvga_video_on_cmd564[] = {
 	0x02, 0x00, 0x39, 0xC0,
 	0x02, 0x77, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd109[] = {
+static char ili9806e_fwvga_video_on_cmd565[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0xE1, 0x79, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd566[] = {
+	0x02, 0x00, 0x39, 0xC0,
+	0x06, 0x01, 0xFF, 0xFF,
+};
+
+static char ili9806e_fwvga_video_on_cmd567[] = {
 	0x06, 0x00, 0x39, 0xC0,
 	0xFF, 0xFF, 0x98, 0x06,
 	0x04, 0x00, 0xFF, 0xFF,
 };
 
-static char ili9806e_fwvga_video_on_cmd110[] = {
+static char ili9806e_fwvga_video_on_cmd568[] = {
 	0x11, 0x00, 0x05, 0x80
 };
 
-static char ili9806e_fwvga_video_on_cmd111[] = {
+static char ili9806e_fwvga_video_on_cmd569[] = {
 	0x29, 0x00, 0x05, 0x80
 };
 
@@ -677,8 +2971,8 @@
 	{0x8, ili9806e_fwvga_video_on_cmd47, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd48, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd49, 0x00},
-	{0xc, ili9806e_fwvga_video_on_cmd50, 0x00},
-	{0x8, ili9806e_fwvga_video_on_cmd51, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd50, 0x00},
+	{0xc, ili9806e_fwvga_video_on_cmd51, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd52, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd53, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd54, 0x00},
@@ -733,15 +3027,472 @@
 	{0x8, ili9806e_fwvga_video_on_cmd103, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd104, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd105, 0x00},
-	{0xc, ili9806e_fwvga_video_on_cmd106, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd106, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd107, 0x00},
 	{0x8, ili9806e_fwvga_video_on_cmd108, 0x00},
-	{0xc, ili9806e_fwvga_video_on_cmd109, 0x00},
-	{0x4, ili9806e_fwvga_video_on_cmd110, 0x96},
-	{0x4, ili9806e_fwvga_video_on_cmd111, 0x78}
+	{0x8, ili9806e_fwvga_video_on_cmd109, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd110, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd111, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd112, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd113, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd114, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd115, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd116, 0x00},
+	{0xc, ili9806e_fwvga_video_on_cmd117, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd118, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd119, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd120, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd121, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd122, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd123, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd124, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd125, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd126, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd127, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd128, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd129, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd130, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd131, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd132, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd133, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd134, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd135, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd136, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd137, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd138, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd139, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd140, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd141, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd142, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd143, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd144, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd145, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd146, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd147, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd148, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd149, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd150, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd151, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd152, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd153, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd154, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd155, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd156, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd157, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd158, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd159, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd160, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd161, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd162, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd163, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd164, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd165, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd166, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd167, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd168, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd169, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd170, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd171, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd172, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd173, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd174, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd175, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd176, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd177, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd178, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd179, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd180, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd181, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd182, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd183, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd184, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd185, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd186, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd187, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd188, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd189, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd190, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd191, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd192, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd193, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd194, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd195, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd196, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd197, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd198, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd199, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd200, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd201, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd202, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd203, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd204, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd205, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd206, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd207, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd208, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd209, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd210, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd211, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd212, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd213, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd214, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd215, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd216, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd217, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd218, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd219, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd220, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd221, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd222, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd223, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd224, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd225, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd226, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd227, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd228, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd229, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd230, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd231, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd232, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd233, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd234, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd235, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd236, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd237, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd238, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd239, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd240, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd241, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd242, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd243, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd244, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd245, 0x00},
+	{0xc, ili9806e_fwvga_video_on_cmd246, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd247, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd248, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd249, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd250, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd251, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd252, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd253, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd254, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd255, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd256, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd257, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd258, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd259, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd260, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd261, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd262, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd263, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd264, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd265, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd266, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd267, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd268, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd269, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd270, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd271, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd272, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd273, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd274, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd275, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd276, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd277, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd278, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd279, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd280, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd281, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd282, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd283, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd284, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd285, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd286, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd287, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd288, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd289, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd290, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd291, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd292, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd293, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd294, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd295, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd296, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd297, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd298, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd299, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd300, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd301, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd302, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd303, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd304, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd305, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd306, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd307, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd308, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd309, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd310, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd311, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd312, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd313, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd314, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd315, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd316, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd317, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd318, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd319, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd320, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd321, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd322, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd323, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd324, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd325, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd326, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd327, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd328, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd329, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd330, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd331, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd332, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd333, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd334, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd335, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd336, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd337, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd338, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd339, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd340, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd341, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd342, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd343, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd344, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd345, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd346, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd347, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd348, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd349, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd350, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd351, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd352, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd353, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd354, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd355, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd356, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd357, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd358, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd359, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd360, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd361, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd362, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd363, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd364, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd365, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd366, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd367, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd368, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd369, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd370, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd371, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd372, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd373, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd374, 0x00},
+	{0xc, ili9806e_fwvga_video_on_cmd375, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd376, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd377, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd378, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd379, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd380, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd381, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd382, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd383, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd384, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd385, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd386, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd387, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd388, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd389, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd390, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd391, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd392, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd393, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd394, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd395, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd396, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd397, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd398, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd399, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd400, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd401, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd402, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd403, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd404, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd405, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd406, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd407, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd408, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd409, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd410, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd411, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd412, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd413, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd414, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd415, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd416, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd417, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd418, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd419, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd420, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd421, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd422, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd423, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd424, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd425, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd426, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd427, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd428, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd429, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd430, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd431, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd432, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd433, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd434, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd435, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd436, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd437, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd438, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd439, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd440, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd441, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd442, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd443, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd444, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd445, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd446, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd447, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd448, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd449, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd450, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd451, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd452, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd453, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd454, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd455, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd456, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd457, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd458, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd459, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd460, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd461, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd462, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd463, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd464, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd465, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd466, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd467, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd468, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd469, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd470, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd471, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd472, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd473, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd474, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd475, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd476, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd477, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd478, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd479, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd480, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd481, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd482, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd483, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd484, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd485, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd486, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd487, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd488, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd489, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd490, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd491, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd492, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd493, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd494, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd495, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd496, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd497, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd498, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd499, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd500, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd501, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd502, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd503, 0x00},
+	{0xc, ili9806e_fwvga_video_on_cmd504, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd505, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd506, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd507, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd508, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd509, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd510, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd511, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd512, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd513, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd514, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd515, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd516, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd517, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd518, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd519, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd520, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd521, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd522, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd523, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd524, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd525, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd526, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd527, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd528, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd529, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd530, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd531, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd532, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd533, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd534, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd535, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd536, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd537, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd538, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd539, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd540, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd541, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd542, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd543, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd544, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd545, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd546, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd547, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd548, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd549, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd550, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd551, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd552, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd553, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd554, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd555, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd556, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd557, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd558, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd559, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd560, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd561, 0x00},
+	{0xc, ili9806e_fwvga_video_on_cmd562, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd563, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd564, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd565, 0x00},
+	{0x8, ili9806e_fwvga_video_on_cmd566, 0x00},
+	{0xc, ili9806e_fwvga_video_on_cmd567, 0x00},
+	{0x4, ili9806e_fwvga_video_on_cmd568, 0x78},
+	{0x4, ili9806e_fwvga_video_on_cmd569, 0x0A}
 };
-
-#define ILI9806E_FWVGA_VIDEO_ON_COMMAND 112
+#define ILI9806E_FWVGA_VIDEO_ON_COMMAND 570
 
 
 static char ili9806e_fwvga_videooff_cmd0[] = {
diff --git a/dev/gcdb/display/include/panel_jdi_a216_fhd_video.h b/dev/gcdb/display/include/panel_jdi_a216_fhd_video.h
index 6f09f38..484edac 100755
--- a/dev/gcdb/display/include/panel_jdi_a216_fhd_video.h
+++ b/dev/gcdb/display/include/panel_jdi_a216_fhd_video.h
@@ -85,15 +85,28 @@
 	0x11, 0x00, 0x05, 0x80
 };
 
+static char jdi_a216_fhd_video_on_cmd5[] = {
+	0xB0, 0x04, 0x29, 0x80
+};
+
+static char jdi_a216_fhd_video_on_cmd6[] = {
+	0x06, 0x00, 0x29, 0xC0,
+	0xD0, 0x10, 0x93, 0xBB,
+	0x12, 0x8E, 0xFF, 0xFF
+};
+
+
 static struct mipi_dsi_cmd jdi_a216_fhd_video_on_command[] = {
 	{0x4, jdi_a216_fhd_video_on_cmd0, 0x0a},
 	{0x4, jdi_a216_fhd_video_on_cmd1, 0x0a},
 	{0x4, jdi_a216_fhd_video_on_cmd2, 0x0a},
 	{0x4, jdi_a216_fhd_video_on_cmd3, 0x28},
 	{0x4, jdi_a216_fhd_video_on_cmd4, 0xc8},
+	{0x4, jdi_a216_fhd_video_on_cmd5, 0x0a},
+	{0xc, jdi_a216_fhd_video_on_cmd6, 0x0a}
 };
 
-#define JDI_A216_FHD_VIDEO_ON_COMMAND 5
+#define JDI_A216_FHD_VIDEO_ON_COMMAND 7
 
 
 static char jdi_a216_fhd_videooff_cmd0[] = {
@@ -113,7 +126,7 @@
 
 
 static struct command_state jdi_a216_fhd_video_state = {
-	0, 1
+	1, 1
 };
 
 /*---------------------------------------------------------------------------*/
diff --git a/dev/gcdb/display/include/panel_r61318_hd_video.h b/dev/gcdb/display/include/panel_r61318_hd_video.h
index 72c27c2..5ac2c74 100644
--- a/dev/gcdb/display/include/panel_r61318_hd_video.h
+++ b/dev/gcdb/display/include/panel_r61318_hd_video.h
@@ -172,7 +172,7 @@
 
 static char r61318_hd_video_on_cmd17[] = {
 	0x02, 0x00, 0x29, 0xC0,
-	0xD4, 0x50, 0xFF, 0xFF,
+	0xD4, 0x4D, 0xFF, 0xFF,
 };
 
 static char r61318_hd_video_on_cmd18[] = {
@@ -181,20 +181,25 @@
 };
 
 static char r61318_hd_video_on_cmd19[] = {
-	0x02, 0x00, 0x39, 0xC0,
-	0x53, 0x24, 0xFF, 0xFF,
+	0x02, 0x00, 0x29, 0xC0,
+	0xBB, 0x2E, 0xFF, 0xFF
 };
 
 static char r61318_hd_video_on_cmd20[] = {
 	0x02, 0x00, 0x39, 0xC0,
-	0x51, 0xff, 0xFF, 0xFF,
+	0x53, 0x2C, 0xFF, 0xFF
 };
 
 static char r61318_hd_video_on_cmd21[] = {
-	0x11, 0x00, 0x05, 0x80
+	0x02, 0x00, 0x39, 0xC0,
+	0x51, 0xff, 0xFF, 0xFF,
 };
 
 static char r61318_hd_video_on_cmd22[] = {
+	0x11, 0x00, 0x05, 0x80
+};
+
+static char r61318_hd_video_on_cmd23[] = {
 	0x29, 0x00, 0x05, 0x80
 };
 
@@ -220,11 +225,12 @@
 	{0x8, r61318_hd_video_on_cmd18, 0x00},
 	{0x8, r61318_hd_video_on_cmd19, 0x00},
 	{0x8, r61318_hd_video_on_cmd20, 0x00},
-	{0x4, r61318_hd_video_on_cmd21, 0x78},
-	{0x4, r61318_hd_video_on_cmd22, 0x32}
+	{0x8, r61318_hd_video_on_cmd21, 0x00},
+	{0x4, r61318_hd_video_on_cmd22, 0x78},
+	{0x4, r61318_hd_video_on_cmd23, 0x32}
 };
 
-#define R61318_HD_VIDEO_ON_COMMAND 23
+#define R61318_HD_VIDEO_ON_COMMAND 24
 
 
 static char r61318_hd_videooff_cmd0[] = {
diff --git a/dev/gcdb/display/include/panel_sharp_1080p_cmd.h b/dev/gcdb/display/include/panel_sharp_1080p_cmd.h
new file mode 100644
index 0000000..353cbc3
--- /dev/null
+++ b/dev/gcdb/display/include/panel_sharp_1080p_cmd.h
@@ -0,0 +1,200 @@
+/* Copyright (c) 2015, 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 BY THE COPYRIGHT HOLDERS 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
+ * 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 _PANEL_SHARP_1080P_CMD_H_
+#define _PANEL_SHARP_1080P_CMD_H_
+
+/*---------------------------------------------------------------------------*/
+/* HEADER files                                                              */
+/*---------------------------------------------------------------------------*/
+#include "panel.h"
+
+/*---------------------------------------------------------------------------*/
+/* Panel configuration                                                       */
+/*---------------------------------------------------------------------------*/
+static struct panel_config sharp_1080p_cmd_panel_data = {
+	"qcom,mdss_dsi_sharp_1080p_cmd", "dsi:0:", "qcom,mdss-dsi-panel",
+	10, 1, "DISPLAY_1", 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel resolution                                                          */
+/*---------------------------------------------------------------------------*/
+static struct panel_resolution sharp_1080p_cmd_panel_res = {
+	1080, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel Color Information                                                   */
+/*---------------------------------------------------------------------------*/
+static struct color_info sharp_1080p_cmd_color = {
+	24, 0, 0xff, 0, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel Command information                                                 */
+/*---------------------------------------------------------------------------*/
+static char sharp_1080p_cmd_on_cmd0[] = {
+	0xbb, 0x10, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd1[] = {
+	0xb0, 0x03, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd2[] = {
+	0x11, 0x00, 0x05, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd3[] = {
+	0x51, 0xff, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd4[] = {
+	0x53, 0x24, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd5[] = {
+	0xff, 0x23, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd6[] = {
+	0x08, 0x05, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd7[] = {
+	0x46, 0x90, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd8[] = {
+	0xff, 0x10, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd9[] = {
+	0xff, 0xf0, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd10[] = {
+	0x92, 0x01, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd11[] = {
+	0xff, 0x10, 0x15, 0x80
+};
+
+static char sharp_1080p_cmd_on_cmd12[] = {
+	0x29, 0x00, 0x05, 0x80
+};
+
+static struct mipi_dsi_cmd sharp_1080p_cmd_on_command[] = {
+	{0x4 , sharp_1080p_cmd_on_cmd0, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd1, 0x00},
+	{0x3 , sharp_1080p_cmd_on_cmd2, 0x78},
+	{0x4 , sharp_1080p_cmd_on_cmd3, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd4, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd5, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd6, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd7, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd8, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd9, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd10, 0x00},
+	{0x4 , sharp_1080p_cmd_on_cmd11, 0x00},
+	{0x3 , sharp_1080p_cmd_on_cmd12, 0x28}
+};
+
+#define SHARP_1080P_CMD_ON_COMMAND 13
+
+
+static char sharp_1080p_cmdoff_cmd0[] = {
+	0x28, 0x00, 0x05, 0x80
+};
+
+static char sharp_1080p_cmdoff_cmd1[] = {
+	0x10, 0x00, 0x05, 0x80
+};
+
+static struct mipi_dsi_cmd sharp_1080p_cmd_off_command[] = {
+	{0x4 , sharp_1080p_cmdoff_cmd0, 0},
+	{0x4 , sharp_1080p_cmdoff_cmd1, 0}
+};
+
+#define SHARP_1080P_CMD_OFF_COMMAND 2
+
+
+static struct command_state sharp_1080p_cmd_state = {
+	0, 1
+};
+
+/*---------------------------------------------------------------------------*/
+/* Command mode panel information                                            */
+/*---------------------------------------------------------------------------*/
+static struct commandpanel_info sharp_1080p_cmd_command_panel = {
+	1, 1, 1, 0, 0, 0x2c, 0x3c, 0, 0, 1, 0, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Video mode panel information                                              */
+/*---------------------------------------------------------------------------*/
+static struct videopanel_info sharp_1080p_cmd_video_panel = {
+	0, 0, 0, 0, 1, 1, 2, 0, 0x9
+};
+
+/*---------------------------------------------------------------------------*/
+/* Lane Configuration                                                        */
+/*---------------------------------------------------------------------------*/
+static struct lane_configuration sharp_1080p_cmd_lane_config = {
+	4, 0, 1, 1, 1, 1, 0
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel Timing                                                              */
+/*---------------------------------------------------------------------------*/
+static const uint32_t sharp_1080p_cmd_timings[] = {
+	0xe7, 0x36, 0x24, 0x00, 0x66, 0x6a, 0x2a, 0x3a,  0x2d, 0x03, 0x04, 0x00
+};
+
+static struct panel_timing sharp_1080p_cmd_timing_info = {
+	0x0, 0x04, 0x04, 0x1b
+};
+
+/*---------------------------------------------------------------------------*/
+/* Panel reset sequence                                                      */
+/*---------------------------------------------------------------------------*/
+static struct panel_reset_sequence sharp_1080p_cmd_panel_reset_seq = {
+	{ 1, 0, 1, }, { 10, 10, 10, }, 2
+};
+
+/*---------------------------------------------------------------------------*/
+/* Backlight Settings                                                        */
+/*---------------------------------------------------------------------------*/
+static struct backlight sharp_1080p_cmd_backlight = {
+	1, 1, 4095, 100, 1, "PMIC_8941"
+};
+
+#endif /*_PANEL_sharp_1080P_CMD_H_*/
diff --git a/dev/pmic/pm8x41/include/pm8x41.h b/dev/pmic/pm8x41/include/pm8x41.h
index 717f09b..6e89f57 100644
--- a/dev/pmic/pm8x41/include/pm8x41.h
+++ b/dev/pmic/pm8x41/include/pm8x41.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -219,6 +219,7 @@
 uint32_t pm8x41_v2_resin_status();
 uint32_t pm8x41_resin_status();
 void pm8x41_reset_configure(uint8_t);
+void pm8994_reset_configure(uint8_t);
 void pm8x41_v2_reset_configure(uint8_t);
 int pm8x41_ldo_set_voltage(struct pm8x41_ldo *ldo, uint32_t voltage);
 int pm8x41_ldo_control(struct pm8x41_ldo *ldo, uint8_t enable);
diff --git a/dev/pmic/pm8x41/include/pm8x41_wled.h b/dev/pmic/pm8x41/include/pm8x41_wled.h
index 0fe7975..f112085 100644
--- a/dev/pmic/pm8x41/include/pm8x41_wled.h
+++ b/dev/pmic/pm8x41/include/pm8x41_wled.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -49,6 +49,11 @@
 #define PM_WLED_CURRENT_SINK         PM_WLED_CTNL_REG(0x4F)
 #define LEDn_FULL_SCALE_CURRENT(n)   (PM_WLED_LED_CTNL_REG(n) + 0x2)
 
+#define PM_LAB_BASE                  0X1DE00
+#define PM_LAB_CNTL(n)               (PM_LAB_BASE + n)
+#define PM_LAB_CURRENT_SENSE         PM_LAB_CNTL(0X4C)
+#define PM_LAB_PS_CTL                PM_LAB_CNTL(0X50)
+
 #define PM_WLED_LED1_SINK_MASK       BIT(5)
 #define PM_WLED_LED2_SINK_MASK       BIT(6)
 #define PM_WLED_LED3_SINK_MASK       BIT(7)
diff --git a/dev/pmic/pm8x41/pm8x41.c b/dev/pmic/pm8x41/pm8x41.c
index 5886161..e753f6c 100644
--- a/dev/pmic/pm8x41/pm8x41.c
+++ b/dev/pmic/pm8x41/pm8x41.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -33,7 +33,7 @@
 #include <string.h>
 #include <pm8x41_hw.h>
 #include <pm8x41.h>
-#include <rpm-smd.h>
+#include <rpm-ipc.h>
 #include <regulator.h>
 #include <platform/timer.h>
 
@@ -77,6 +77,24 @@
 	return val;
 }
 
+/* SPMI helper function which takes slave id as the i/p */
+void pm8xxx_reg_write(uint8_t slave_id, uint32_t addr, uint8_t val)
+{
+	struct pmic_arb_cmd cmd;
+	struct pmic_arb_param param;
+
+	cmd.address = PERIPH_ID(addr);
+	cmd.offset = REG_OFFSET(addr);
+	cmd.slave_id = slave_id;
+
+	cmd.priority = 0;
+
+	param.buffer = &val;
+	param.size   = 1;
+
+	pmic_arb_write_cmd(&cmd, &param);
+}
+
 void pm8x41_reg_write(uint32_t addr, uint8_t val)
 {
 	struct pmic_arb_cmd cmd;
@@ -333,6 +351,31 @@
 		return 0;
 }
 
+void pm8994_reset_configure(uint8_t reset_type)
+{
+	/* Slave ID of pm8994 and pmi8994 */
+	uint8_t slave_id[] = {0, 2};
+	uint8_t i;
+
+	/* Reset sequence
+	1. Disable the ps hold for pm8994
+	2. set reset type for both pm8994 & pmi8994
+	3. Enable ps hold for pm8994 to trigger the reset
+	*/
+	/* disable PS_HOLD_RESET */
+	pm8xxx_reg_write(slave_id[0], PON_PS_HOLD_RESET_CTL2, 0x0);
+
+	/* Delay needed for disable to kick in. */
+	udelay(300);
+
+	/* configure reset type */
+	for (i = 0; i < ARRAY_SIZE(slave_id); i++)
+		pm8xxx_reg_write(slave_id[i], PON_PS_HOLD_RESET_CTL, reset_type);
+
+	/* enable PS_HOLD_RESET */
+	pm8xxx_reg_write(slave_id[0], PON_PS_HOLD_RESET_CTL2, BIT(S2_RESET_EN_BIT));
+}
+
 void pm8x41_v2_reset_configure(uint8_t reset_type)
 {
 	uint8_t val;
diff --git a/dev/pmic/pm8x41/pm8x41_wled.c b/dev/pmic/pm8x41/pm8x41_wled.c
index 9c3b6d3..c6c48e2 100644
--- a/dev/pmic/pm8x41/pm8x41_wled.c
+++ b/dev/pmic/pm8x41/pm8x41_wled.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -88,6 +88,11 @@
 	pm8x41_wled_reg_write(LEDn_FULL_SCALE_CURRENT(3), wled_ctrl->full_current_scale);
 
 	pm8x41_wled_reg_write(PM_WLED_FDBCK_CONTROL, wled_ctrl->fdbck);
+
+	// Override default values for ISENSE and PS Threshold
+	pm8x41_wled_reg_write(PM_LAB_CURRENT_SENSE, 0x0A);
+	pm8x41_wled_reg_write(PM_LAB_PS_CTL, 0x80);
+
 	dprintf(SPEW, "WLED Configuration Success.\n");
 
 }
diff --git a/dev/qpnp_wled/include/qpnp_wled.h b/dev/qpnp_wled/include/qpnp_wled.h
index 3584a32..a04680d 100644
--- a/dev/qpnp_wled/include/qpnp_wled.h
+++ b/dev/qpnp_wled/include/qpnp_wled.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 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
@@ -168,6 +168,8 @@
 #define QPNP_WLED_MIN_MSLEEP                   20
 #define QPNP_WLED_MAX_BR_LEVEL                 1638
 
+#define PWRDN_DLY2_MASK                        0x3
+
 /* output feedback mode */
 enum qpnp_wled_fdbk_op {
        QPNP_WLED_FDBK_AUTO,
diff --git a/dev/qpnp_wled/qpnp_wled.c b/dev/qpnp_wled/qpnp_wled.c
index b96150c..2f4b196 100644
--- a/dev/qpnp_wled/qpnp_wled.c
+++ b/dev/qpnp_wled/qpnp_wled.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ /* Copyright (c) 2014-2015, 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
@@ -408,6 +408,10 @@
 	temp = wled->ibb_pwrup_dly_ms;
 	reg &= QPNP_WLED_IBB_PWRUP_DLY_MASK;
 	reg |= (temp << QPNP_WLED_IBB_PWRUP_DLY_SHIFT);
+	/* Power down delay bits could already be set, clear them before
+	 * or'ing new values
+	 */
+	reg &= ~(PWRDN_DLY2_MASK);
 	reg |= wled->ibb_pwrdn_dly_ms;
 	reg |= (wled->ibb_discharge_en << 2);
 
diff --git a/include/dev/udc.h b/include/dev/udc.h
index 42ced0e..31d9755 100644
--- a/include/dev/udc.h
+++ b/include/dev/udc.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, Google Inc.
  * All rights reserved.
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, 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
@@ -50,6 +50,8 @@
 
 #define UDC_TYPE_BULK_IN	1
 #define UDC_TYPE_BULK_OUT	2
+#define UDC_TYPE_INTR_IN	3
+#define UDC_TYPE_INTR_OUT	4
 
 struct udc_endpoint *udc_endpoint_alloc(unsigned type, unsigned maxpkt);
 void udc_endpoint_free(struct udc_endpoint *ept);
diff --git a/include/platform.h b/include/platform.h
index e71c407..623473b 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -54,6 +54,7 @@
 unsigned board_platform_id(void);
 unsigned check_reboot_mode(void);
 unsigned check_hard_reboot_mode(void);
+uint32_t check_alarm_boot(void);
 void platform_uninit_timer(void);
 void reboot_device(unsigned);
 int set_download_mode(enum dload_mode mode);
@@ -65,4 +66,5 @@
 int platform_is_msm8992();
 int boot_device_mask(int);
 uint32_t platform_detect_panel();
+uint32_t platform_get_max_periph();
 #endif
diff --git a/include/string.h b/include/string.h
index 661e746..593ecf2 100644
--- a/include/string.h
+++ b/include/string.h
@@ -33,6 +33,8 @@
 void *memchr (void const *, int, size_t) __PURE;
 int   memcmp (void const *, const void *, size_t) __PURE;
 void *memcpy (void *, void const *, size_t);
+/* secure memcpy, does not copy beyong size of dest buffer*/
+size_t memscpy (void *, size_t, void const *, size_t);
 void *memmove(void *, void const *, size_t);
 void *memset (void *, int, size_t);
 
diff --git a/include/target.h b/include/target.h
index 4a2891c..772afdf 100644
--- a/include/target.h
+++ b/include/target.h
@@ -85,4 +85,5 @@
 void ulpi_write(unsigned val, unsigned reg);
 void target_crypto_init_params(void);
 int target_cont_splash_screen(void);
+bool target_build_variant_user();
 #endif
diff --git a/lib/libc/malloc.c b/lib/libc/malloc.c
index 6f05f63..9cec44c 100644
--- a/lib/libc/malloc.c
+++ b/lib/libc/malloc.c
@@ -24,6 +24,7 @@
 #include <malloc.h>
 #include <string.h>
 #include <lib/heap.h>
+#include <arch/ops.h>
 
 void *malloc(size_t size)
 {
@@ -32,7 +33,11 @@
 
 void *memalign(size_t boundary, size_t size)
 {
-	return heap_alloc(size, boundary);
+	void *ptr;
+	ptr = heap_alloc(size, boundary);
+	/* Clean the cache before giving the memory */
+	arch_invalidate_cache_range((addr_t) ptr, size);
+	return ptr;
 }
 
 void *calloc(size_t count, size_t size)
diff --git a/lib/libc/string/memscpy.c b/lib/libc/string/memscpy.c
new file mode 100644
index 0000000..3dd4d6b
--- /dev/null
+++ b/lib/libc/string/memscpy.c
@@ -0,0 +1,37 @@
+/* Copyright (c) 2015, 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 Fundation, Inc. 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 <string.h>
+
+size_t memscpy(void *dest, size_t dst_size, const void *src, size_t src_size)
+{
+	size_t copy_size = dst_size < src_size ? dst_size : src_size;
+	memcpy(dest, src, copy_size);
+	return copy_size;
+}
diff --git a/lib/libc/string/rules.mk b/lib/libc/string/rules.mk
index fc1ceb2..97a5db8 100644
--- a/lib/libc/string/rules.mk
+++ b/lib/libc/string/rules.mk
@@ -8,6 +8,7 @@
 	memcpy \
 	memmove \
 	memset \
+	memscpy \
 	strcat \
 	strchr \
 	strcmp \
diff --git a/lib/zlib_inflate/adler32.c b/lib/zlib_inflate/adler32.c
new file mode 100644
index 0000000..a868f07
--- /dev/null
+++ b/lib/zlib_inflate/adler32.c
@@ -0,0 +1,179 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2011 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#define local static
+
+local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
+
+#define BASE 65521      /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware --
+   try it both ways to see which is faster */
+#ifdef NO_DIVIDE
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+   (thank you to John Reiser for pointing this out) */
+#  define CHOP(a) \
+    do { \
+        unsigned long tmp = a >> 16; \
+        a &= 0xffffUL; \
+        a += (tmp << 4) - tmp; \
+    } while (0)
+#  define MOD28(a) \
+    do { \
+        CHOP(a); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#  define MOD(a) \
+    do { \
+        CHOP(a); \
+        MOD28(a); \
+    } while (0)
+#  define MOD63(a) \
+    do { /* this assumes a is not negative */ \
+        z_off64_t tmp = a >> 32; \
+        a &= 0xffffffffL; \
+        a += (tmp << 8) - (tmp << 5) + tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#else
+#  define MOD(a) a %= BASE
+#  define MOD28(a) a %= BASE
+#  define MOD63(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long sum2;
+    unsigned n;
+
+    /* split Adler-32 into component sums */
+    sum2 = (adler >> 16) & 0xffff;
+    adler &= 0xffff;
+
+    /* in case user likes doing a byte at a time, keep it fast */
+    if (len == 1) {
+        adler += buf[0];
+        if (adler >= BASE)
+            adler -= BASE;
+        sum2 += adler;
+        if (sum2 >= BASE)
+            sum2 -= BASE;
+        return adler | (sum2 << 16);
+    }
+
+    /* initial Adler-32 value (deferred check for len == 1 speed) */
+    if (buf == Z_NULL)
+        return 1L;
+
+    /* in case short lengths are provided, keep it somewhat fast */
+    if (len < 16) {
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        if (adler >= BASE)
+            adler -= BASE;
+        MOD28(sum2);            /* only added so many BASE's */
+        return adler | (sum2 << 16);
+    }
+
+    /* do length NMAX blocks -- requires just one modulo operation */
+    while (len >= NMAX) {
+        len -= NMAX;
+        n = NMAX / 16;          /* NMAX is divisible by 16 */
+        do {
+            DO16(buf);          /* 16 sums unrolled */
+            buf += 16;
+        } while (--n);
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* do remaining bytes (less than NMAX, still just one modulo) */
+    if (len) {                  /* avoid modulos if none remaining */
+        while (len >= 16) {
+            len -= 16;
+            DO16(buf);
+            buf += 16;
+        }
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* return recombined sums */
+    return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off64_t len2;
+{
+    unsigned long sum1;
+    unsigned long sum2;
+    unsigned rem;
+
+    /* for negative len, return invalid adler32 as a clue for debugging */
+    if (len2 < 0)
+        return 0xffffffffUL;
+
+    /* the derivation of this formula is left as an exercise for the reader */
+    MOD63(len2);                /* assumes len2 >= 0 */
+    rem = (unsigned)len2;
+    sum1 = adler1 & 0xffff;
+    sum2 = rem * sum1;
+    MOD(sum2);
+    sum1 += (adler2 & 0xffff) + BASE - 1;
+    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
+    if (sum2 >= BASE) sum2 -= BASE;
+    return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off64_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
diff --git a/lib/zlib_inflate/crc32.c b/lib/zlib_inflate/crc32.c
new file mode 100644
index 0000000..979a719
--- /dev/null
+++ b/lib/zlib_inflate/crc32.c
@@ -0,0 +1,425 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors.  This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id$ */
+
+/*
+  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+  protection on the static variables used to control the first-use generation
+  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+  first call get_crc_table() to initialize the tables before allowing more than
+  one thread to use crc32().
+
+  DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
+ */
+
+#ifdef MAKECRCH
+#  include <stdio.h>
+#  ifndef DYNAMIC_CRC_TABLE
+#    define DYNAMIC_CRC_TABLE
+#  endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h"      /* for STDC and FAR definitions */
+
+#define local static
+
+/* Definitions for doing the crc four data bytes at a time. */
+#if !defined(NOBYFOUR) && defined(Z_U4)
+#  define BYFOUR
+#endif
+#ifdef BYFOUR
+   local unsigned long crc32_little OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+   local unsigned long crc32_big OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+#  define TBLS 8
+#else
+#  define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+                                         unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
+
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local z_crc_t FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+   local void write_table OF((FILE *, const z_crc_t FAR *));
+#endif /* MAKECRCH */
+/*
+  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+  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.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The first table is simply the CRC of all possible eight bit values.  This is
+  all the information needed to generate CRCs on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.  The remaining tables
+  allow for word-at-a-time CRC calculation for both big-endian and little-
+  endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+    z_crc_t c;
+    int n, k;
+    z_crc_t poly;                       /* polynomial exclusive-or pattern */
+    /* terms of polynomial defining this crc (except x^32): */
+    static volatile int first = 1;      /* flag to limit concurrent making */
+    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+    /* See if another task is already doing this (not thread-safe, but better
+       than nothing -- significantly reduces duration of vulnerability in
+       case the advice about DYNAMIC_CRC_TABLE is ignored) */
+    if (first) {
+        first = 0;
+
+        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+        poly = 0;
+        for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
+            poly |= (z_crc_t)1 << (31 - p[n]);
+
+        /* generate a crc for every 8-bit value */
+        for (n = 0; n < 256; n++) {
+            c = (z_crc_t)n;
+            for (k = 0; k < 8; k++)
+                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+            crc_table[0][n] = c;
+        }
+
+#ifdef BYFOUR
+        /* generate crc for each value followed by one, two, and three zeros,
+           and then the byte reversal of those as well as the first table */
+        for (n = 0; n < 256; n++) {
+            c = crc_table[0][n];
+            crc_table[4][n] = ZSWAP32(c);
+            for (k = 1; k < 4; k++) {
+                c = crc_table[0][c & 0xff] ^ (c >> 8);
+                crc_table[k][n] = c;
+                crc_table[k + 4][n] = ZSWAP32(c);
+            }
+        }
+#endif /* BYFOUR */
+
+        crc_table_empty = 0;
+    }
+    else {      /* not first */
+        /* wait for the other guy to finish (not efficient, but rare) */
+        while (crc_table_empty)
+            ;
+    }
+
+#ifdef MAKECRCH
+    /* write out CRC tables to crc32.h */
+    {
+        FILE *out;
+
+        out = fopen("crc32.h", "w");
+        if (out == NULL) return;
+        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+        fprintf(out, "local const z_crc_t FAR ");
+        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
+        write_table(out, crc_table[0]);
+#  ifdef BYFOUR
+        fprintf(out, "#ifdef BYFOUR\n");
+        for (k = 1; k < 8; k++) {
+            fprintf(out, "  },\n  {\n");
+            write_table(out, crc_table[k]);
+        }
+        fprintf(out, "#endif\n");
+#  endif /* BYFOUR */
+        fprintf(out, "  }\n};\n");
+        fclose(out);
+    }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+    FILE *out;
+    const z_crc_t FAR *table;
+{
+    int n;
+
+    for (n = 0; n < 256; n++)
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ",
+                (unsigned long)(table[n]),
+                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const z_crc_t FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+    return (const z_crc_t FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    uInt len;
+{
+    if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+    if (sizeof(void *) == sizeof(ptrdiff_t)) {
+        z_crc_t endian;
+
+        endian = 1;
+        if (*((unsigned char *)(&endian)))
+            return crc32_little(crc, buf, len);
+        else
+            return crc32_big(crc, buf, len);
+    }
+#endif /* BYFOUR */
+    crc = crc ^ 0xffffffffUL;
+    while (len >= 8) {
+        DO8;
+        len -= 8;
+    }
+    if (len) do {
+        DO1;
+    } while (--len);
+    return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
+
+    c = (z_crc_t)crc;
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+        len--;
+    }
+
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
+    while (len >= 32) {
+        DOLIT32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOLIT4;
+        len -= 4;
+    }
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
+
+    c = ZSWAP32((z_crc_t)crc);
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+        len--;
+    }
+
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
+    buf4--;
+    while (len >= 32) {
+        DOBIG32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOBIG4;
+        len -= 4;
+    }
+    buf4++;
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)(ZSWAP32(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+    unsigned long *mat;
+    unsigned long vec;
+{
+    unsigned long sum;
+
+    sum = 0;
+    while (vec) {
+        if (vec & 1)
+            sum ^= *mat;
+        vec >>= 1;
+        mat++;
+    }
+    return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+    unsigned long *square;
+    unsigned long *mat;
+{
+    int n;
+
+    for (n = 0; n < GF2_DIM; n++)
+        square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+local uLong crc32_combine_(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off64_t len2;
+{
+    int n;
+    unsigned long row;
+    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
+    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
+
+    /* degenerate case (also disallow negative lengths) */
+    if (len2 <= 0)
+        return crc1;
+
+    /* put operator for one zero bit in odd */
+    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
+    row = 1;
+    for (n = 1; n < GF2_DIM; n++) {
+        odd[n] = row;
+        row <<= 1;
+    }
+
+    /* put operator for two zero bits in even */
+    gf2_matrix_square(even, odd);
+
+    /* put operator for four zero bits in odd */
+    gf2_matrix_square(odd, even);
+
+    /* apply len2 zeros to crc1 (first square will put the operator for one
+       zero byte, eight zero bits, in even) */
+    do {
+        /* apply zeros operator for this bit of len2 */
+        gf2_matrix_square(even, odd);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(even, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if (len2 == 0)
+            break;
+
+        /* another iteration of the loop with odd and even swapped */
+        gf2_matrix_square(odd, even);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(odd, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+    } while (len2 != 0);
+
+    /* return combined crc */
+    crc1 ^= crc2;
+    return crc1;
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off_t len2;
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
+
+uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off64_t len2;
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
diff --git a/lib/zlib_inflate/crc32.h b/lib/zlib_inflate/crc32.h
new file mode 100644
index 0000000..9e0c778
--- /dev/null
+++ b/lib/zlib_inflate/crc32.h
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const z_crc_t FAR crc_table[TBLS][256] =
+{
+  {
+    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+    0x2d02ef8dUL
+#ifdef BYFOUR
+  },
+  {
+    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+    0x9324fd72UL
+  },
+  {
+    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+    0xbe9834edUL
+  },
+  {
+    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+    0xde0506f1UL
+  },
+  {
+    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+    0x8def022dUL
+  },
+  {
+    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+    0x72fd2493UL
+  },
+  {
+    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+    0xed3498beUL
+  },
+  {
+    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+    0xf10605deUL
+#endif
+  }
+};
diff --git a/lib/zlib_inflate/decompress.c b/lib/zlib_inflate/decompress.c
new file mode 100644
index 0000000..4a7ccc3
--- /dev/null
+++ b/lib/zlib_inflate/decompress.c
@@ -0,0 +1,154 @@
+/* Copyright (c) 2015, 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, Inc. 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.
+ */
+
+#define NO_GZIP
+
+#include "zutil.h"
+
+#ifdef DYNAMIC_CRC_TABLE
+#include "crc32.h"
+#endif
+
+#include "zconf.h"
+#include "zlib.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+#include "decompress.h"
+#include <sys/types.h>	/* for size_t */
+#include <string.h>
+#include <debug.h>
+#include <malloc.h>
+
+#define GZIP_HEADER_LEN 10
+#define GZIP_FILENAME_LIMIT 256
+
+static void zlib_free(voidpf qpaque, void *addr)
+{
+	return free(addr);
+}
+
+static void *zlib_alloc(voidpf qpaque, uInt items, size_t size)
+{
+	return malloc(items * size);
+}
+
+/* decompress gzip file "in_buf", return 0 if decompressed successful,
+ * return -1 if decompressed failed.
+ * in_buf - input gzip file
+ * in_len - input the length file
+ * out_buf - output the decompressed data
+ * out_buf_len - the available length of out_buf
+ * pos - position of the end of gzip file
+ * out_len - the length of decompressed data
+ */
+int decompress(unsigned char *in_buf, unsigned int in_len,
+		       unsigned char *out_buf,
+		       unsigned int out_buf_len,
+		       unsigned int *pos,
+		       unsigned int *out_len) {
+	struct z_stream_s *stream;
+	int rc = -1;
+	int i;
+
+	if (in_len < GZIP_HEADER_LEN) {
+		dprintf(INFO, "the input data is not a gzip package.\n");
+		return rc;
+	}
+	if (out_buf_len < in_len) {
+		dprintf(INFO, "the avaiable length of out_buf is not enough.\n");
+		return rc;
+	}
+
+	stream = malloc(sizeof(*stream));
+	if (stream == NULL) {
+		dprintf(INFO, "allocating z_stream failed.\n");
+		return rc;
+	}
+
+	stream->zalloc = zlib_alloc;
+	stream->zfree = zlib_free;
+	stream->next_out = out_buf;
+	stream->avail_out = out_buf_len;
+
+	/* skip over gzip header */
+	stream->next_in = in_buf + GZIP_HEADER_LEN;
+	stream->avail_in = out_buf_len - GZIP_HEADER_LEN;
+	/* skip over asciz filename */
+	if (in_buf[3] & 0x8) {
+		for (i = 0; i < GZIP_FILENAME_LIMIT && *stream->next_in++; i++) {
+			if (stream->avail_in == 0) {
+				dprintf(INFO, "header error\n");
+				goto gunzip_end;
+			}
+			--stream->avail_in;
+		}
+	}
+
+	rc = inflateInit2(stream, -MAX_WBITS);
+	if (rc != Z_OK) {
+		dprintf(INFO, "inflateInit2 failed!\n");
+		goto gunzip_end;
+	}
+
+	rc = inflate(stream, 0);
+	/* Z_STREAM_END is "we unpacked it all" */
+	if (rc == Z_STREAM_END) {
+		rc = 0;
+	} else if (rc != Z_OK) {
+		dprintf(INFO, "uncompression error \n");
+		rc = -1;
+	}
+
+	inflateEnd(stream);
+	if (pos)
+		/* alculation the length of the compressed package */
+		*pos = stream->next_in - in_buf + 8;
+
+	if (out_len)
+		*out_len = stream->total_out;
+
+gunzip_end:
+	free(stream);
+	return rc; /* returns 0 if decompressed successful */
+}
+
+/* check if the input "buf" file was a gzip package.
+ * Return true if the input "buf" is a gzip package.
+ */
+int is_gzip_package(unsigned char *buf, unsigned int len)
+{
+	if (len < 10 || !buf || buf[0] != 0x1f ||
+		buf[1] != 0x8b || buf[2] != 0x08)
+	{
+		dprintf(INFO, "Not a gzip file\n");
+		return false;
+	}
+
+	return true;
+}
diff --git a/platform/thulium/include/platform/partial_goods.h b/lib/zlib_inflate/decompress.h
similarity index 64%
copy from platform/thulium/include/platform/partial_goods.h
copy to lib/zlib_inflate/decompress.h
index 03c16ec..1cdd011 100644
--- a/platform/thulium/include/platform/partial_goods.h
+++ b/lib/zlib_inflate/decompress.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
-
+/* Copyright (c) 2015, 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:
@@ -9,7 +9,7 @@
  *     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
+ *   * Neither the name of The Linux Foundation, Inc. nor the names of its
  *     contributors may be used to endorse or promote products derived
  *     from this software without specific prior written permission.
  *
@@ -26,21 +26,10 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <partial_goods.h>
+#ifndef __PLATFORM_MSM_SHARED_DECOMPRESS_H
+#define __PLATFORM_MSM_SHARED_DECOMPRESS_H
 
-#define QFPROM_PTE_PART_ADDR    0x0007013C
+int is_gzip_package(unsigned char *, unsigned int);
 
-/* Look up table for partial goods */
-struct partial_goods table[] =
-{
-	{0x1, "/cpus", {{"cpu@100", "device_type"},}},
-	{0x2, "/cpus", {{"cpu@101", "device_type"},}},
-	{0x3, "/cpus", {{"cpu@100", "device_type"},
-                        {"cpu@101","device_type"},}},
-	{0x4, "/cpus", {{"cpu@100", "device_type"},
-                        {"cpu@101", "device_type"},
-                        {"cpu@1",   "device_type"},}},
-	{0x10, "/soc",  {{"qcom,kgsl-3d0", "status"},}},
-	{0x11, "/soc",  {{"qcom,vidc", "status"},}},
-	{0x12, "/soc",  {{"qcom,msm-adsp-loader", "status"},}},
-};
+int decompress(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int *, unsigned int *);
+#endif /* __PLATFORM_MSM_SHARED_DECOMPRESS_H */
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c
new file mode 100644
index 0000000..bda59ce
--- /dev/null
+++ b/lib/zlib_inflate/inffast.c
@@ -0,0 +1,340 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+   Based on testing to date,
+   Pre-increment preferred for:
+   - PowerPC G3 (Adler)
+   - MIPS R5000 (Randers-Pehrson)
+   Post-increment preferred for:
+   - none
+   No measurable difference:
+   - Pentium III (Anderson)
+   - M68060 (Nikl)
+ */
+#ifdef POSTINC
+#  define OFF 0
+#  define PUP(a) *(a)++
+#else
+#  define OFF 1
+#  define PUP(a) *++(a)
+#endif
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void ZLIB_INTERNAL inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *in;      /* local strm->next_in */
+    z_const unsigned char FAR *last;    /* have enough input while in < last */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code here;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in - OFF;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out - OFF;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    wnext = state->wnext;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+        }
+        here = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(here.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(here.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", here.val));
+            PUP(out) = (unsigned char)(here.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(here.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+            }
+            here = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(here.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(here.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(here.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(PUP(in)) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        if (state->sane) {
+                            strm->msg =
+                                (char *)"invalid distance too far back";
+                            state->mode = BAD;
+                            break;
+                        }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        if (len <= op - whave) {
+                            do {
+                                PUP(out) = 0;
+                            } while (--len);
+                            continue;
+                        }
+                        len -= op - whave;
+                        do {
+                            PUP(out) = 0;
+                        } while (--op > whave);
+                        if (op == 0) {
+                            from = out - dist;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--len);
+                            continue;
+                        }
+#endif
+                    }
+                    from = window - OFF;
+                    if (wnext == 0) {           /* very common case */
+                        from += wsize - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    else if (wnext < op) {      /* wrap around window */
+                        from += wsize + wnext - op;
+                        op -= wnext;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = window - OFF;
+                            if (wnext < len) {  /* some from start of window */
+                                op = wnext;
+                                len -= op;
+                                do {
+                                    PUP(out) = PUP(from);
+                                } while (--op);
+                                from = out - dist;      /* rest from output */
+                            }
+                        }
+                    }
+                    else {                      /* contiguous in window */
+                        from += wnext - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    while (len > 2) {
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    }
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+                else {
+                    from = out - dist;          /* copy direct from output */
+                    do {                        /* minimum length is three */
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    } while (len > 2);
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                here = dcode[here.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            here = lcode[here.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in + OFF;
+    strm->next_out = out + OFF;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and wnext == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/lib/zlib_inflate/inffast.h b/lib/zlib_inflate/inffast.h
new file mode 100644
index 0000000..e5c1aa4
--- /dev/null
+++ b/lib/zlib_inflate/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/lib/zlib_inflate/inffixed.h b/lib/zlib_inflate/inffixed.h
new file mode 100644
index 0000000..d628327
--- /dev/null
+++ b/lib/zlib_inflate/inffixed.h
@@ -0,0 +1,94 @@
+    /* inffixed.h -- table for decoding fixed codes
+     * Generated automatically by makefixed().
+     */
+
+    /* WARNING: this file should *not* be used by applications.
+       It is part of the implementation of this library and is
+       subject to change. Applications should only use zlib.h.
+     */
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+        {0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+        {22,5,193},{64,5,0}
+    };
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
new file mode 100644
index 0000000..e341300
--- /dev/null
+++ b/lib/zlib_inflate/inflate.c
@@ -0,0 +1,1514 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#define NO_GZIP
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+                           unsigned copy));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
+                              unsigned len));
+
+int ZEXPORT inflateResetKeep(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    if (state->wrap)        /* to support ill-conceived Java test suite */
+        strm->adler = state->wrap & 1;
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    state->sane = 1;
+    state->back = -1;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+    int wrap;
+    struct inflate_state FAR *state;
+
+    /* get the state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* extract wrap request from windowBits parameter */
+    if (windowBits < 0) {
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+        if (windowBits < 48)
+            windowBits &= 15;
+#endif
+    }
+
+    /* set number of window bits, free window if different */
+    if (windowBits && (windowBits < 8 || windowBits > 15))
+        return Z_STREAM_ERROR;
+    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+        ZFREE(strm, state->window);
+        state->window = Z_NULL;
+    }
+
+    /* update state and reset the rest of it */
+    state->wrap = wrap;
+    state->wbits = (unsigned)windowBits;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+    int ret;
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+#endif
+    }
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->window = Z_NULL;
+    ret = inflateReset2(strm, windowBits);
+    if (ret != Z_OK) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+    }
+    return ret;
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits < 0) {
+        state->hold = 0;
+        state->bits = 0;
+        return Z_OK;
+    }
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+               state.lencode[low].bits, state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, end, copy)
+z_streamp strm;
+const Bytef *end;
+unsigned copy;
+{
+    struct inflate_state FAR *state;
+    unsigned dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, 1U << state->wbits,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->wnext = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, end - state->wsize, state->wsize);
+        state->wnext = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->wnext;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->wnext, end - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, end - copy, copy);
+            state->wnext = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->wnext += dist;
+            if (state->wnext == state->wsize) state->wnext = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (state->wbits == 0)
+                state->wbits = len;
+            else if (len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if (state->flags & 0x0200) CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if (state->flags & 0x0200) CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if (state->flags & 0x0200)
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if (hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = ZSWAP32(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN_;             /* decode codes */
+                if (flush == Z_TREES) {
+                    DROPBITS(2);
+                    goto inf_leave;
+                }
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY_;
+            if (flush == Z_TREES) goto inf_leave;
+        case COPY_:
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (const code FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN_;
+            if (flush == Z_TREES) goto inf_leave;
+        case LEN_:
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                if (state->mode == TYPE)
+                    state->back = -1;
+                break;
+            }
+            state->back = 0;
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            state->length = (unsigned)here.val;
+            if ((int)(here.op) == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                state->mode = LIT;
+                break;
+            }
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->back = -1;
+                state->mode = TYPE;
+                break;
+            }
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->was = state->length;
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->whave) {
+                    if (state->sane) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                    Trace((stderr, "inflate.c too far\n"));
+                    copy -= state->whave;
+                    if (copy > state->length) copy = state->length;
+                    if (copy > left) copy = left;
+                    left -= copy;
+                    state->length -= copy;
+                    do {
+                        *put++ = 0;
+                    } while (--copy);
+                    if (state->length == 0) state->mode = LEN;
+                    break;
+#endif
+                }
+                if (copy > state->wnext) {
+                    copy -= state->wnext;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->wnext - copy);
+                if (copy > state->length) copy = state->length;
+            }
+            else {                              /* copy from output */
+                from = put - state->offset;
+                copy = state->length;
+            }
+            if (copy > left) copy = left;
+            left -= copy;
+            state->length -= copy;
+            do {
+                *put++ = *from++;
+            } while (--copy);
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if (out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     ZSWAP32(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+            (state->mode < CHECK || flush != Z_FINISH)))
+        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if (state->wrap && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0) +
+                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* copy dictionary */
+    if (state->whave && dictionary != Z_NULL) {
+        zmemcpy(dictionary, state->window + state->wnext,
+                state->whave - state->wnext);
+        zmemcpy(dictionary + state->whave - state->wnext,
+                state->window, state->wnext);
+    }
+    if (dictLength != Z_NULL)
+        *dictLength = state->whave;
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+    struct inflate_state FAR *state;
+    unsigned long dictid;
+    int ret;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary identifier */
+    if (state->mode == DICT) {
+        dictid = adler32(0L, Z_NULL, 0);
+        dictid = adler32(dictid, dictionary, dictLength);
+        if (dictid != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window using updatewindow(), which will amend the
+       existing dictionary if appropriate */
+    ret = updatewindow(strm, dictionary + dictLength, dictLength);
+    if (ret) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+const unsigned char FAR *buf;
+unsigned len;
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->sane = !subvert;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+    return Z_OK;
+#else
+    state->sane = 1;
+    return Z_DATA_ERROR;
+#endif
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
+    state = (struct inflate_state FAR *)strm->state;
+    return ((long)(state->back) << 16) +
+        (state->mode == COPY ? state->length :
+            (state->mode == MATCH ? state->was - state->length : 0));
+}
diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h
new file mode 100644
index 0000000..95f4986
--- /dev/null
+++ b/lib/zlib_inflate/inflate.h
@@ -0,0 +1,122 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2009 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip decoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD,       /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY_,      /* i/o: same as COPY below, but only first time in */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN_,       /* i: same as LEN below, but only first time in */
+            LEN,        /* i: waiting for length/lit/eob code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib) or (raw)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+                  HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+        (raw) -> TYPEDO
+    Read deflate blocks:
+            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+            STORED -> COPY_ -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN_
+            LEN_ -> LEN
+    Read deflate codes in fixed or dynamic block:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls.  Approximately 10K bytes. */
+struct inflate_state {
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+    gz_headerp head;            /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const FAR *lencode;    /* starting table for length/literal codes */
+    code const FAR *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code FAR *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+    int sane;                   /* if false, allow invalid distance too far */
+    int back;                   /* bits back of last unprocessed length/lit */
+    unsigned was;               /* initial length of match */
+};
diff --git a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c
new file mode 100644
index 0000000..44d89cf
--- /dev/null
+++ b/lib/zlib_inflate/inftrees.c
@@ -0,0 +1,306 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2013 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+   " inflate 1.2.8 Copyright 1995-2013 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/*
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code here;                  /* table entry for duplication */
+    code FAR *next;             /* next available space in table */
+    const unsigned short FAR *base;     /* base value table to use */
+    const unsigned short FAR *extra;    /* extra bits table to use */
+    int end;                    /* use base and extra for symbol > end */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
+    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577, 0, 0};
+    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+        28, 28, 29, 29, 64, 64};
+
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
+
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
+
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
+
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
+
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
+
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) {                     /* no symbols to code at all */
+        here.op = (unsigned char)64;    /* invalid code marker */
+        here.bits = (unsigned char)1;
+        here.val = (unsigned short)0;
+        *(*table)++ = here;             /* make a table to force an error */
+        *(*table)++ = here;
+        *bits = 1;
+        return 0;     /* no symbols, but wait for decoding to report error */
+    }
+    for (min = 1; min < max; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
+
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
+
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
+
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
+
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked for LENS and DIST tables against
+       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+       the initial root table size constants.  See the comments in inftrees.h
+       for more information.
+
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
+
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        end = 19;
+        break;
+    case LENS:
+        base = lbase;
+        base -= 257;
+        extra = lext;
+        extra -= 257;
+        end = 256;
+        break;
+    default:            /* DISTS */
+        base = dbase;
+        extra = dext;
+        end = -1;
+    }
+
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
+
+    /* check available table space */
+    if ((type == LENS && used > ENOUGH_LENS) ||
+        (type == DISTS && used > ENOUGH_DISTS))
+        return 1;
+
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        here.bits = (unsigned char)(len - drop);
+        if ((int)(work[sym]) < end) {
+            here.op = (unsigned char)0;
+            here.val = work[sym];
+        }
+        else if ((int)(work[sym]) > end) {
+            here.op = (unsigned char)(extra[work[sym]]);
+            here.val = base[work[sym]];
+        }
+        else {
+            here.op = (unsigned char)(32 + 64);         /* end of block */
+            here.val = 0;
+        }
+
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = here;
+        } while (fill != 0);
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
+
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
+
+            /* increment past last table */
+            next += min;            /* here min is 1 << curr */
+
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if ((type == LENS && used > ENOUGH_LENS) ||
+                (type == DISTS && used > ENOUGH_DISTS))
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
+    }
+
+    /* fill in remaining table entry if code is incomplete (guaranteed to have
+       at most one remaining entry, since if the code is incomplete, the
+       maximum code length that was allowed to get this far is one bit) */
+    if (huff != 0) {
+        here.op = (unsigned char)64;            /* invalid code marker */
+        here.bits = (unsigned char)(len - drop);
+        here.val = (unsigned short)0;
+        next[huff] = here;
+    }
+
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
+}
diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h
new file mode 100644
index 0000000..baa53a0
--- /dev/null
+++ b/lib/zlib_inflate/inftrees.h
@@ -0,0 +1,62 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    0001eeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table.  The maximum number of code structures is
+   1444, which is the sum of 852 for literal/length codes and 592 for distance
+   codes.  These values were found by exhaustive searches using the program
+   examples/enough.c found in the zlib distribtution.  The arguments to that
+   program are the number of symbols, the initial root table size, and the
+   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
+   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+   The initial root table size (9 or 6) is found in the fifth argument of the
+   inflate_table() calls in inflate.c and infback.c.  If the root table size is
+   changed, then these maximum sizes would be need to be recalculated and
+   updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
+                             unsigned codes, code FAR * FAR *table,
+                             unsigned FAR *bits, unsigned short FAR *work));
diff --git a/lib/zlib_inflate/rules.mk b/lib/zlib_inflate/rules.mk
new file mode 100755
index 0000000..96d2383
--- /dev/null
+++ b/lib/zlib_inflate/rules.mk
@@ -0,0 +1,9 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+OBJS += \
+	$(LOCAL_DIR)/zutil.o \
+	$(LOCAL_DIR)/adler32.o \
+	$(LOCAL_DIR)/inftrees.o \
+	$(LOCAL_DIR)/inflate.o \
+	$(LOCAL_DIR)/inffast.o \
+	$(LOCAL_DIR)/decompress.o
diff --git a/lib/zlib_inflate/zconf.h b/lib/zlib_inflate/zconf.h
new file mode 100644
index 0000000..9987a77
--- /dev/null
+++ b/lib/zlib_inflate/zconf.h
@@ -0,0 +1,511 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
+
+/* all linked symbols */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_bits        z__tr_flush_bits
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
+#  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
+#  define deflateEnd            z_deflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateInit_          z_deflateInit_
+#  define deflateParams         z_deflateParams
+#  define deflatePending        z_deflatePending
+#  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzvprintf             z_gzvprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzwrite               z_gzwrite
+#  endif
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetHeader      z_inflateGetHeader
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateGetDictionary  z_inflateGetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateUndermine      z_inflateUndermine
+#  define inflateResetKeep      z_inflateResetKeep
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#  endif
+#  define zError                z_zError
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
+#  define alloc_func            z_alloc_func
+#  define charf                 z_charf
+#  define free_func             z_free_func
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
+#  define in_func               z_in_func
+#  define intf                  z_intf
+#  define out_func              z_out_func
+#  define uInt                  z_uInt
+#  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
+#  define uLongf                z_uLongf
+#  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  elif (ULONG_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned long
+#  elif (USHRT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned short
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+#    include <stdarg.h>         /* for va_list */
+#  endif
+#endif
+
+#ifdef _WIN32
+#  ifndef Z_SOLO
+#    include <stddef.h>         /* for wchar_t */
+#  endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
+#  endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#  define z_off64_t off64_t
+#else
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/lib/zlib_inflate/zlib.h b/lib/zlib_inflate/zlib.h
new file mode 100644
index 0000000..8da7aa5
--- /dev/null
+++ b/lib/zlib_inflate/zlib.h
@@ -0,0 +1,1768 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.8, April 28th, 2013
+
+  Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.8"
+#define ZLIB_VERNUM 0x1280
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 8
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+    The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+    The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+    This library can optionally read and write gzip streams in memory as well.
+
+    The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    z_const Bytef *next_in;     /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total number of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total number of bytes output so far */
+
+    z_const char *msg;  /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
+   opaque value.
+
+     zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use in the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+#define Z_TREES         6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows.  deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).  Some
+    output may be provided even if flush is not set.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumulate before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed code
+  block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error.  After
+  deflate has returned Z_STREAM_END, the only possible operations on the stream
+  are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step.  In this case, avail_out must be at least the
+  value returned by deflateBound (see below).  Then deflate is guaranteed to
+  return Z_STREAM_END.  If not enough output space is provided, deflate will
+  not return Z_STREAM_END, and it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
+  binary.  This field is only for information purposes and does not affect the
+  compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression.  The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
+   exact value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit() does not process any header information -- that is deferred
+   until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows.  inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing will
+    resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all of the uncompressed data for the
+  operation to complete.  (The size of the uncompressed data may have been
+  saved by the compressor for this purpose.) The use of Z_FINISH is not
+  required to perform an inflation in one step.  However it may be used to
+  inform inflate that a faster approach can be used for the single inflate()
+  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
+  stream completes, which reduces inflate's memory footprint.  If the stream
+  does not complete, either because not all of the stream is provided or not
+  enough output space is provided, then a sliding window will be allocated and
+  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+  been used.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call.  So the effects of the flush parameter in this implementation are
+  on the return value of inflate() as noted below, when inflate() returns early
+  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+  memory for a sliding window when Z_FINISH is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the Adler-32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below.  At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained, so applications that need that information should
+  instead use raw inflate, see inflateInit2() below, or inflateBack() and
+  perform their own processing of the gzip header and trailer.  When processing
+  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+  producted so far.  The CRC-32 is checked against the gzip trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent.  In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
+
+     The method parameter is the compression method.  It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm.  Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output.  When using the zlib format, this
+   function must be called immediately after deflateInit, deflateInit2 or
+   deflateReset, and before any call of deflate.  When doing raw deflate, this
+   function must be called either before any call of deflate, or immediately
+   after the completion of a deflate block, i.e. after all input has been
+   consumed and all output has been delivered when using any of the flush
+   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
+   compressor and decompressor must use exactly the same dictionary (see
+   inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary.  Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor.  (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if not at a block boundary for raw deflate).  deflateSetDictionary does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter.  The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.  The
+   stream will keep the same compression level and any other attributes that
+   may have been set by deflateInit2.
+
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression level is changed, the input available so far is
+   compressed with the old level (and may be flushed); the new level will take
+   effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to be
+   compressed and flushed.  In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+   strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().  If that first deflate() call is provided the
+   sourceLen input bytes, an output buffer allocated to the size returned by
+   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+   to return Z_STREAM_END.  Note that it is possible for the compressed size to
+   be larger than the value returned by deflateBound() if flush options other
+   than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits));
+/*
+     deflatePending() returns the number of bytes and bits of output that have
+   been generated, but not yet provided in the available output.  The bytes not
+   provided would be due to the available output space having being consumed.
+   The number of bits of output not provided are between 0 and 7, where they
+   await more bits to join them in order to fill out a full byte.  If pending
+   or bits are Z_NULL, then those values are not set.
+
+     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+     If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter.  The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used.  If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream.  This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values.  If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is.  Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called at any
+   time to set the dictionary.  If the provided dictionary is smaller than the
+   window and there is already data in the window, then the provided dictionary
+   will amend what's there.  The application must insure that the dictionary
+   that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value).  inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
+/*
+     Returns the sliding dictionary being maintained by inflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If inflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a possible full flush point (see above
+   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+   All full flush points have this pattern, but not all occurrences of this
+   pattern are full flush points.
+
+     inflateSync returns Z_OK if a possible full flush point has been found,
+   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+   In the success case, the application may save the current current value of
+   total_in which indicates where valid compressed data was found.  In the
+   error case, the application may repeatedly call inflateSync, providing more
+   input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.
+
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above or -1 << 16 if the provided
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
+
+     The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+     If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *,
+                                z_const unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is potentially more efficient than
+   inflate() for file i/o applications, in that it avoids copying between the
+   output and the sliding window by simply making the window itself the output
+   buffer.  inflate() can be faster on modern CPUs when used with large
+   buffers.  inflateBack() trusts the application to not change the output
+   buffer passed by the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the normal
+   behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.) Note that inflateBack()
+   cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG/ZLIB_DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer.  The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer.  Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed buffer.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
+   the case where there is not enough room, uncompress() will fill the output
+   buffer with the uncompressed data up to that point.
+*/
+
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.)  'T' will
+   request transparent writing or appending with no compression and not using
+   the gzip format.
+
+     "a" can be used instead of "w" to request that the gzip stream that will
+   be written be appended to the file.  "+" will result in an error, since
+   reading and writing to the same gzip file is not supported.  The addition of
+   "x" when writing will create the file exclusively, which fails if the file
+   already exists.  On systems that support it, the addition of "e" when
+   reading or writing will set the flag to close the file on an execve() call.
+
+     These functions, as well as gzip, will read and decode a sequence of gzip
+   streams in a file.  The append function of gzopen() can be used to create
+   such a file.  (Also see gzflush() for another way to do this.)  When
+   appending, gzopen does not test whether the file begins with a gzip stream,
+   nor does it look for the end of the gzip streams to begin appending.  gzopen
+   will simply append a gzip stream to the existing file.
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.  When
+   reading, this will be detected automatically by looking for the magic two-
+   byte gzip header.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.  If you are using fileno() to get the
+   file descriptor from a FILE *, then you will have to use dup() to avoid
+   double-close()ing the file descriptor.  Both gzclose() and fclose() will
+   close the associated file descriptor, so they need to have different file
+   descriptors.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Two buffers are allocated, either both of the specified size when
+   writing, or one of the specified size and the other twice that size when
+   reading.  A larger buffer size of, for example, 64K or 128K bytes will
+   noticeably increase the speed of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy.  See the description
+   of deflateInit2 for the meaning of these parameters.
+
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file is not in gzip format, gzread copies the given number of
+   bytes into the buffer directly from the file.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream.  Any number of gzip streams may be
+   concatenated in the input file, and will all be decompressed by gzread().
+   If something other than a gzip stream is encountered after a gzip stream,
+   that remaining trailing garbage is ignored (and no error is returned).
+
+     gzread can be used to read a gzip file that is being concurrently written.
+   Upon reaching the end of the input, gzread will return with the available
+   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+   gzclearerr can be used to clear the end of file indicator in order to permit
+   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
+   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
+   middle of a gzip stream.  Note that gzread does not return -1 in the event
+   of an incomplete gzip stream.  This error is deferred until gzclose(), which
+   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+   stream.  Alternatively, gzerror can be used before gzclose to detect this
+   case.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or 0 in case of error.  The number of
+   uncompressed bytes written is limited to 8191, or one less than the buffer
+   size given to gzbuffer().  The caller should assure that this limit is not
+   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
+   nothing written.  In this case, there may also be a buffer overflow with
+   unpredictable consequences, which is possible only if zlib was compiled with
+   the insecure functions sprintf() or vsprintf() because the secure snprintf()
+   or vsnprintf() functions were not available.  This can be determined using
+   zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+     Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+
+     gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.  This is implemented as a macro for speed.
+   As such, it does not do all of the checking the other functions do.  I.e.
+   it does not check to see if file is NULL, nor whether the structure file
+   points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatented gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow.  If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+     gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+
+     When writing, gzdirect() returns true (1) if transparent writing was
+   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
+   gzdirect() is not needed when writing.  Transparent writing must be
+   explicitly requested, so the application already knows the answer.  When
+   linking statically, using gzdirect() will include all of the zlib code for
+   gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+   last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the compression
+   library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster.
+
+   Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
+   that the z_off_t type (like off_t) is a signed integer.  If len2 is
+   negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the crc.  Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                      (int)sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+                      ZLIB_VERSION, (int)sizeof(z_stream))
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure.  Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro.  The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously.  They can
+ * only be used by the gzgetc() macro.  You have been warned.
+ */
+struct gzFile_s {
+    unsigned have;
+    unsigned char *next;
+    z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#  define z_gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#else
+#  define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+#  ifdef Z_PREFIX_SET
+#    define z_gzopen z_gzopen64
+#    define z_gzseek z_gzseek64
+#    define z_gztell z_gztell64
+#    define z_gzoffset z_gzoffset64
+#    define z_adler32_combine z_adler32_combine64
+#    define z_crc32_combine z_crc32_combine64
+#  else
+#    define gzopen gzopen64
+#    define gzseek gzseek64
+#    define gztell gztell64
+#    define gzoffset gzoffset64
+#    define adler32_combine adler32_combine64
+#    define crc32_combine crc32_combine64
+#  endif
+#  ifndef Z_LARGE64
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* hack for buggy compilers */
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;};
+#endif
+
+/* undocumented functions */
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
+                                            const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+                                                  const char *format,
+                                                  va_list va));
+#  endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/lib/zlib_inflate/zutil.c b/lib/zlib_inflate/zutil.c
new file mode 100644
index 0000000..5f21a24
--- /dev/null
+++ b/lib/zlib_inflate/zutil.c
@@ -0,0 +1,326 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+#ifndef Z_SOLO
+/* Comment because LK does not contain gzguts.h */
+// #  include "gzguts.h"
+#endif
+
+#ifndef NO_DUMMY_DECL
+struct internal_state      {int dummy;}; /* for buggy compilers */
+#endif
+
+z_const char * const z_errmsg[10] = {
+"need dictionary",     /* Z_NEED_DICT       2  */
+"stream end",          /* Z_STREAM_END      1  */
+"",                    /* Z_OK              0  */
+"file error",          /* Z_ERRNO         (-1) */
+"stream error",        /* Z_STREAM_ERROR  (-2) */
+"data error",          /* Z_DATA_ERROR    (-3) */
+"insufficient memory", /* Z_MEM_ERROR     (-4) */
+"buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+    uLong flags;
+
+    flags = 0;
+    switch ((int)(sizeof(uInt))) {
+    case 2:     break;
+    case 4:     flags += 1;     break;
+    case 8:     flags += 2;     break;
+    default:    flags += 3;
+    }
+    switch ((int)(sizeof(uLong))) {
+    case 2:     break;
+    case 4:     flags += 1 << 2;        break;
+    case 8:     flags += 2 << 2;        break;
+    default:    flags += 3 << 2;
+    }
+    switch ((int)(sizeof(voidpf))) {
+    case 2:     break;
+    case 4:     flags += 1 << 4;        break;
+    case 8:     flags += 2 << 4;        break;
+    default:    flags += 3 << 4;
+    }
+    switch ((int)(sizeof(z_off_t))) {
+    case 2:     break;
+    case 4:     flags += 1 << 6;        break;
+    case 8:     flags += 2 << 6;        break;
+    default:    flags += 3 << 6;
+    }
+/* replace DEBUG with ZLIB_DEBUG since the former is already used in lk */
+#ifdef ZLIB_DEBUG
+    flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+    flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+    flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+    flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+    flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+    flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+    flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+    flags += 1L << 20;
+#endif
+#ifdef FASTEST
+    flags += 1L << 21;
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifdef NO_vsnprintf
+    flags += 1L << 25;
+#    ifdef HAS_vsprintf_void
+    flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_vsnprintf_void
+    flags += 1L << 26;
+#    endif
+#  endif
+#else
+    flags += 1L << 24;
+#  ifdef NO_snprintf
+    flags += 1L << 25;
+#    ifdef HAS_sprintf_void
+    flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_snprintf_void
+    flags += 1L << 26;
+#    endif
+#  endif
+#endif
+    return flags;
+}
+
+#ifdef ZLIB_DEBUG
+
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+    int err;
+{
+    return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+    /* The Microsoft C Run-Time Library for Windows CE doesn't have
+     * errno.  We define it as a global variable to simplify porting.
+     * Its value is always 0 and should not be used.
+     */
+    int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+#ifndef Z_SOLO
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+                              (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/lib/zlib_inflate/zutil.h b/lib/zlib_inflate/zutil.h
new file mode 100644
index 0000000..4de61bb
--- /dev/null
+++ b/lib/zlib_inflate/zutil.h
@@ -0,0 +1,254 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#ifdef HAVE_HIDDEN
+#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+#  define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#if defined(STDC) && !defined(Z_SOLO)
+#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+#    include <stddef.h>
+#  endif
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+#ifdef Z_SOLO
+   typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+#  define OS_CODE  0x00
+#  ifndef Z_SOLO
+#    if defined(__TURBOC__) || defined(__BORLANDC__)
+#      if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+         /* Allow compilation with ANSI keywords only enabled */
+         void _Cdecl farfree( void *block );
+         void *_Cdecl farmalloc( unsigned long nbytes );
+#      else
+#        include <alloc.h>
+#      endif
+#    else /* MSC or DJGPP */
+#      include <malloc.h>
+#    endif
+#  endif
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#  if defined(M_I86) && !defined(Z_SOLO)
+#    include <malloc.h>
+#  endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  ifndef Z_SOLO
+#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#      include <unix.h> /* for fdopen */
+#    else
+#      ifndef fdopen
+#        define fdopen(fd,mode) NULL /* No fdopen() */
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#ifdef WIN32
+#  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
+#    define OS_CODE  0x0b
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+#  if defined(_WIN32_WCE)
+#    define fdopen(fd,mode) NULL /* No fdopen() */
+#    ifndef _PTRDIFF_T_DEFINED
+       typedef int ptrdiff_t;
+#      define _PTRDIFF_T_DEFINED
+#    endif
+#  else
+#    define fdopen(fd,type)  _fdopen(fd,type)
+#  endif
+#endif
+
+#if defined(__BORLANDC__) && !defined(MSDOS)
+  #pragma warn -8004
+  #pragma warn -8008
+  #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && \
+    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#endif
+
+        /* common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#if defined(pyr) || defined(Z_SOLO)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+/* replace DEBUG with ZLIB_DEBUG since the former is already used in lk. */
+#ifdef ZLIB_DEBUG
+#  include <stdio.h>
+   extern int ZLIB_INTERNAL z_verbose;
+   extern void ZLIB_INTERNAL z_error OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+#ifndef Z_SOLO
+   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+                                    unsigned size));
+   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+#endif
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+#endif /* ZUTIL_H */
diff --git a/makefile b/makefile
index 252903e..1e818a8 100644
--- a/makefile
+++ b/makefile
@@ -105,6 +105,10 @@
   endif
 endif
 
+ifeq ($(USER_BUILD_VARIANT),true)
+  DEFINES += USER_BUILD_VARIANT=1
+endif
+
 # these need to be filled out by the project/target/platform rules.mk files
 TARGET :=
 PLATFORM :=
diff --git a/platform/init.c b/platform/init.c
index 34c5726..9919b22 100644
--- a/platform/init.c
+++ b/platform/init.c
@@ -145,3 +145,12 @@
 {
 	return 0;
 }
+
+__WEAK uint32_t check_alarm_boot()
+{
+	return 0;
+}
+__WEAK uint32_t platform_get_max_periph()
+{
+	return 128;
+}
diff --git a/platform/mdm9640/include/platform/iomap.h b/platform/mdm9640/include/platform/iomap.h
index 3d63543..c5eab42 100644
--- a/platform/mdm9640/include/platform/iomap.h
+++ b/platform/mdm9640/include/platform/iomap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 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
@@ -193,4 +193,7 @@
 /* QPIC DISPLAY */
 #define QPIC_BASE                   0x7980000
 #define APCS_ALIAS0_IPC_INTERRUPT   0xB011008
+/* eMMC Display */
+#define TLMM_EBI2_EMMC_GPIO_CFG     0x01111000
+#define EBI2_BOOT_SELECT            0x2
 #endif
diff --git a/platform/msm8909/include/platform/iomap.h b/platform/msm8909/include/platform/iomap.h
index e2a66fe..bca7c54 100644
--- a/platform/msm8909/include/platform/iomap.h
+++ b/platform/msm8909/include/platform/iomap.h
@@ -280,4 +280,5 @@
 #define SECURITY_CONTROL_CORE_FEATURE_CONFIG0    0x0005E004
 /* EBI2 */
 #define TLMM_EBI2_EMMC_GPIO_CFG     (TLMM_BASE_ADDR + 0x00111000)
+#define TCSR_BOOT_MISC_DETECT       0x193D100
 #endif
diff --git a/platform/msm8916/include/platform/iomap.h b/platform/msm8916/include/platform/iomap.h
index fd56c0e..2d9197c 100644
--- a/platform/msm8916/include/platform/iomap.h
+++ b/platform/msm8916/include/platform/iomap.h
@@ -51,9 +51,6 @@
 #define ABOOT_FORCE_RAMDISK_ADDR    DDR_START + 0x2000000
 #define ABOOT_FORCE_TAGS_ADDR       DDR_START + 0x1E00000
 
-/* 3GB DDR devices consider 0x40000000 as new mem base */
-#define BASE_ADDR_1                 0x40000000
-
 #define MSM_GIC_DIST_BASE           APPS_SS_BASE
 #define MSM_GIC_CPU_BASE            (APPS_SS_BASE + 0x2000)
 #define APPS_APCS_QTMR_AC_BASE      (APPS_SS_BASE + 0x00020000)
@@ -265,4 +262,5 @@
 #define HS_TIMER_CTRL               0x0BC
 
 #define TCSR_TZ_WONCE               0x193D000
+#define TCSR_BOOT_MISC_DETECT       0x193D100
 #endif
diff --git a/platform/msm8916/platform.c b/platform/msm8916/platform.c
index 66c703f..1531b28 100644
--- a/platform/msm8916/platform.c
+++ b/platform/msm8916/platform.c
@@ -39,12 +39,13 @@
 #include <board.h>
 #include <boot_stats.h>
 #include <platform.h>
+#include <target/display.h>
 
 #define MSM_IOMAP_SIZE ((MSM_IOMAP_END - MSM_IOMAP_BASE)/MB)
 #define A53_SS_SIZE    ((A53_SS_END - A53_SS_BASE)/MB)
 
 /* LK memory - cacheable, write through */
-#define LK_MEMORY         (MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH | \
+#define LK_MEMORY         (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE | \
 					MMU_MEMORY_AP_READ_WRITE)
 
 /* Peripherals - non-shared device */
@@ -55,6 +56,9 @@
 #define COMMON_MEMORY       (MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH | \
                            MMU_MEMORY_AP_READ_WRITE | MMU_MEMORY_XN)
 
+#define SCRATCH_MEMORY       (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE | \
+                           MMU_MEMORY_AP_READ_WRITE | MMU_MEMORY_XN)
+
 static mmu_section_t mmu_section_table[] = {
 /*           Physical addr,     Virtual addr,     Size (in MB),     Flags */
 	{    MEMBASE,           MEMBASE,          (MEMSIZE / MB),   LK_MEMORY},
@@ -62,9 +66,8 @@
 	{    A53_SS_BASE,       A53_SS_BASE,      A53_SS_SIZE,      IOMAP_MEMORY},
 	{    SYSTEM_IMEM_BASE,  SYSTEM_IMEM_BASE, 1,                COMMON_MEMORY},
 	{    MSM_SHARED_BASE,   MSM_SHARED_BASE,  1,                COMMON_MEMORY},
-	{    BASE_ADDR,         BASE_ADDR,        90,               COMMON_MEMORY},
 	{    SCRATCH_ADDR,      SCRATCH_ADDR,     256,              COMMON_MEMORY},
-	{    BASE_ADDR_1,       BASE_ADDR_1,     1024,              COMMON_MEMORY},
+	{    MIPI_FB_ADDR,      MIPI_FB_ADDR,     10,              COMMON_MEMORY},
 };
 
 
@@ -119,7 +122,14 @@
 	uint32_t i;
 	uint32_t sections;
 	uint32_t table_size = ARRAY_SIZE(mmu_section_table);
+	uint32_t ddr_start = get_ddr_start();
 
+	/*Mapping the ddr start address for loading the kernel about 90 MB*/
+	sections = 90;
+	while(sections--)
+	{
+		arm_mmu_map_section(ddr_start + sections * MB, ddr_start + sections* MB, COMMON_MEMORY);
+	}
 	/* Configure the MMU page entries for memory read from the
 	   mmu_section_table */
 	for (i = 0; i < table_size; i++)
@@ -208,30 +218,3 @@
 	else
 		return MSM_SHARED_BASE;
 }
-uint32_t get_ddr_start()
-{
-	uint32_t i;
-	ram_partition ptn_entry;
-	uint32_t len = 0;
-
-	ASSERT(smem_ram_ptable_init_v1());
-
-	len = smem_get_ram_ptable_len();
-
-	/* Determine the Start addr of the DDR RAM */
-	for(i = 0; i < len; i++)
-	{
-		smem_get_ram_ptable_entry(&ptn_entry, i);
-		if(ptn_entry.type == SYS_MEMORY)
-		{
-			if((ptn_entry.category == SDRAM) ||
-			   (ptn_entry.category == IMEM))
-			{
-				/* Check to ensure that start address is 1MB aligned */
-				ASSERT((ptn_entry.start & (MB-1)) == 0);
-				return ptn_entry.start;
-			}
-		}
-	}
-	ASSERT("DDR Start Mem Not found\n");
-}
diff --git a/platform/msm8952/acpuclock.c b/platform/msm8952/acpuclock.c
new file mode 100644
index 0000000..ff25ac0
--- /dev/null
+++ b/platform/msm8952/acpuclock.c
@@ -0,0 +1,287 @@
+/* Copyright (c) 2015, 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 <err.h>
+#include <assert.h>
+#include <debug.h>
+#include <reg.h>
+#include <platform/timer.h>
+#include <platform/iomap.h>
+#include <mmc.h>
+#include <clock.h>
+#include <platform/clock.h>
+#include <platform.h>
+
+void hsusb_clock_init(void)
+{
+	int ret;
+	struct clk *iclk, *cclk;
+
+	ret = clk_get_set_enable("usb_iface_clk", 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb_iface_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb_core_clk", 80000000, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb_core_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	mdelay(20);
+
+	iclk = clk_get("usb_iface_clk");
+	cclk = clk_get("usb_core_clk");
+
+	clk_disable(iclk);
+	clk_disable(cclk);
+
+	mdelay(20);
+
+	/* Start the block reset for usb */
+	writel(1, USB_HS_BCR);
+
+	mdelay(20);
+
+	/* Take usb block out of reset */
+	writel(0, USB_HS_BCR);
+
+	mdelay(20);
+
+	ret = clk_enable(iclk);
+
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_enable(cclk);
+
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
+void clock_init_mmc(uint32_t interface)
+{
+	char clk_name[64];
+	int ret;
+
+	snprintf(clk_name, sizeof(clk_name), "sdc%u_iface_clk", interface);
+
+	/* enable interface clock */
+	ret = clk_get_set_enable(clk_name, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set sdc1_iface_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
+/* Configure MMC clock */
+void clock_config_mmc(uint32_t interface, uint32_t freq)
+{
+	int ret = 1;
+	char clk_name[64];
+
+	snprintf(clk_name, sizeof(clk_name), "sdc%u_core_clk", interface);
+
+	if(freq == MMC_CLK_400KHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 400000, 1);
+	}
+	else if(freq == MMC_CLK_50MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 50000000, 1);
+	}
+	else if(freq == MMC_CLK_177MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 177770000, 1);
+	}
+	else if(freq == MMC_CLK_192MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 192000000, 1);
+	}
+	else if(freq == MMC_CLK_200MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 200000000, 1);
+	}
+	else if(freq == MMC_CLK_400MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 384000000, 1);
+	}
+	else
+	{
+		dprintf(CRITICAL, "sdc frequency (%u) is not supported\n", freq);
+		ASSERT(0);
+	}
+
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
+		ASSERT(0);
+	}
+}
+
+/* Configure UART clock based on the UART block id*/
+void clock_config_uart_dm(uint8_t id)
+{
+	int ret;
+	char iclk[64];
+	char cclk[64];
+
+	snprintf(iclk, sizeof(iclk), "uart%u_iface_clk", id);
+	snprintf(cclk, sizeof(cclk), "uart%u_core_clk", id);
+
+	ret = clk_get_set_enable(iclk, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set %s ret = %d\n", iclk, ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable(cclk, 7372800, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set %s ret = %d\n", cclk, ret);
+		ASSERT(0);
+	}
+}
+
+/* Function to asynchronously reset CE.
+ * Function assumes that all the CE clocks are off.
+ */
+static void ce_async_reset(uint8_t instance)
+{
+	/* Start the block reset for CE */
+	writel(1, GCC_CRYPTO_BCR);
+
+	udelay(2);
+
+	/* Take CE block out of reset */
+	writel(0, GCC_CRYPTO_BCR);
+
+	udelay(2);
+}
+
+void clock_ce_enable(uint8_t instance)
+{
+	int ret;
+	char clk_name[64];
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
+	ret = clk_get_set_enable(clk_name, 160000000, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set ce%u_src_clk ret = %d\n", instance, ret);
+		ASSERT(0);
+	}
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
+	ret = clk_get_set_enable(clk_name, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set ce%u_core_clk ret = %d\n", instance, ret);
+		ASSERT(0);
+	}
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
+	ret = clk_get_set_enable(clk_name, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set ce%u_ahb_clk ret = %d\n", instance, ret);
+		ASSERT(0);
+	}
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
+	ret = clk_get_set_enable(clk_name, 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set ce%u_axi_clk ret = %d\n", instance, ret);
+		ASSERT(0);
+	}
+
+	/* Wait for 48 * #pipes cycles.
+	 * This is necessary as immediately after an access control reset (boot up)
+	 * or a debug re-enable, the Crypto core sequentially clears its internal
+	 * pipe key storage memory. If pipe key initialization writes are attempted
+	 * during this time, they may be overwritten by the internal clearing logic.
+	 */
+	udelay(1);
+
+}
+
+void clock_ce_disable(uint8_t instance)
+{
+	struct clk *ahb_clk;
+	struct clk *cclk;
+	struct clk *axi_clk;
+	struct clk *src_clk;
+	char clk_name[64];
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
+	src_clk = clk_get(clk_name);
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
+	ahb_clk = clk_get(clk_name);
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
+	axi_clk = clk_get(clk_name);
+
+	snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
+	cclk    = clk_get(clk_name);
+
+	clk_disable(ahb_clk);
+	clk_disable(axi_clk);
+	clk_disable(cclk);
+	clk_disable(src_clk);
+
+	/* Some delay for the clocks to stabalize. */
+	udelay(1);
+
+}
+
+void clock_config_ce(uint8_t instance)
+{
+	/* Need to enable the clock before disabling since the clk_disable()
+	 * has a check to default to nop when the clk_enable() is not called
+	 * on that particular clock.
+	 */
+	clock_ce_enable(instance);
+
+	clock_ce_disable(instance);
+
+	ce_async_reset(instance);
+
+	clock_ce_enable(instance);
+}
diff --git a/platform/msm8952/gpio.c b/platform/msm8952/gpio.c
new file mode 100644
index 0000000..05b4977
--- /dev/null
+++ b/platform/msm8952/gpio.c
@@ -0,0 +1,72 @@
+/* Copyright (c) 2015, 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 <debug.h>
+#include <reg.h>
+#include <platform/iomap.h>
+#include <platform/gpio.h>
+#include <blsp_qup.h>
+
+void gpio_tlmm_config(uint32_t gpio, uint8_t func,
+			uint8_t dir, uint8_t pull,
+			uint8_t drvstr, uint32_t enable)
+{
+	uint32_t val = 0;
+
+	val |= pull;
+	val |= func << 2;
+	val |= drvstr << 6;
+	val |= enable << 9;
+
+	writel(val, (uint32_t *)GPIO_CONFIG_ADDR(gpio));
+	return;
+}
+
+void gpio_set_dir(uint32_t gpio, uint32_t dir)
+{
+	writel(dir, (uint32_t *)GPIO_IN_OUT_ADDR(gpio));
+
+	return;
+}
+
+uint32_t gpio_status(uint32_t gpio)
+{
+	return readl(GPIO_IN_OUT_ADDR(gpio)) & GPIO_IN;
+}
+
+/* Configure gpio for blsp uart 2 */
+void gpio_config_uart_dm(uint8_t id)
+{
+	/* configure rx gpio */
+	gpio_tlmm_config(5, 2, GPIO_INPUT, GPIO_NO_PULL,
+				GPIO_8MA, GPIO_DISABLE);
+
+	/* configure tx gpio */
+	gpio_tlmm_config(4, 2, GPIO_OUTPUT, GPIO_NO_PULL,
+				GPIO_8MA, GPIO_DISABLE);
+}
diff --git a/platform/msm8952/include/platform/clock.h b/platform/msm8952/include/platform/clock.h
new file mode 100644
index 0000000..c7efe6e
--- /dev/null
+++ b/platform/msm8952/include/platform/clock.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2015, 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 __MSM8952_CLOCK_H
+#define __MSM8952_CLOCK_H
+
+#include <clock.h>
+#include <clock_lib2.h>
+
+#define UART_DM_CLK_RX_TX_BIT_RATE 0xCC
+
+void platform_clock_init(void);
+
+void clock_init_mmc(uint32_t interface);
+void clock_config_mmc(uint32_t interface, uint32_t freq);
+void clock_config_uart_dm(uint8_t id);
+void hsusb_clock_init(void);
+void clock_config_ce(uint8_t instance);
+#endif
diff --git a/platform/msm8952/include/platform/gpio.h b/platform/msm8952/include/platform/gpio.h
new file mode 100644
index 0000000..b4d12e8
--- /dev/null
+++ b/platform/msm8952/include/platform/gpio.h
@@ -0,0 +1,72 @@
+/* Copyright (c) 2015, 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 __PLATFORM_MSM8952_GPIO_H
+#define __PLATFORM_MSM8952_GPIO_H
+
+#include <bits.h>
+#include <gpio.h>
+
+/* GPIO TLMM: Direction */
+#define GPIO_INPUT      0
+#define GPIO_OUTPUT     1
+
+/* GPIO TLMM: Pullup/Pulldown */
+#define GPIO_NO_PULL    0
+#define GPIO_PULL_DOWN  1
+#define GPIO_KEEPER     2
+#define GPIO_PULL_UP    3
+
+/* GPIO TLMM: Drive Strength */
+#define GPIO_2MA        0
+#define GPIO_4MA        1
+#define GPIO_6MA        2
+#define GPIO_8MA        3
+#define GPIO_10MA       4
+#define GPIO_12MA       5
+#define GPIO_14MA       6
+#define GPIO_16MA       7
+
+/* GPIO TLMM: Status */
+#define GPIO_ENABLE     0
+#define GPIO_DISABLE    1
+
+/* GPIO_IN_OUT register shifts. */
+#define GPIO_IN         BIT(0)
+#define GPIO_OUT        BIT(1)
+
+void gpio_config_uart_dm(uint8_t id);
+uint32_t gpio_status(uint32_t gpio);
+void gpio_set_dir(uint32_t gpio, uint32_t dir);
+void gpio_tlmm_config(uint32_t gpio,
+			uint8_t func,
+			uint8_t dir,
+			uint8_t pull,
+			uint8_t drvstr,
+			uint32_t enable);
+#endif
diff --git a/platform/msm8952/include/platform/iomap.h b/platform/msm8952/include/platform/iomap.h
new file mode 100644
index 0000000..f4712d7
--- /dev/null
+++ b/platform/msm8952/include/platform/iomap.h
@@ -0,0 +1,149 @@
+/* Copyright (c) 2015, 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 _PLATFORM_MSM8952_IOMAP_H_
+#define _PLATFORM_MSM8952_IOMAP_H_
+
+#define MSM_IOMAP_BASE                     0x00000000
+#define MSM_IOMAP_END                      0x08000000
+
+#define SDRAM_START_ADDR                   0x80000000
+
+#define DDR_START                          get_ddr_start()
+#define ABOOT_FORCE_KERNEL_ADDR            DDR_START + 0x8000
+#define ABOOT_FORCE_KERNEL64_ADDR          DDR_START + 0x80000
+#define ABOOT_FORCE_RAMDISK_ADDR           DDR_START + 0x2000000
+#define ABOOT_FORCE_TAGS_ADDR              DDR_START + 0x1E00000
+
+#define MSM_SHARED_BASE                    0x86300000
+#define MSM_SHARED_IMEM_BASE               0x08600000
+
+#define BS_INFO_OFFSET                     (0x6B0)
+#define BS_INFO_ADDR                       (MSM_SHARED_IMEM_BASE + BS_INFO_OFFSET)
+
+#define RESTART_REASON_ADDR                (MSM_SHARED_IMEM_BASE + 0x65C)
+
+#define APPS_SS_BASE                       0x0B000000
+#define APPS_SS_END                        0x0B200000
+
+#define MSM_GIC_DIST_BASE                  APPS_SS_BASE
+#define MSM_GIC_CPU_BASE                   (APPS_SS_BASE + 0x2000)
+#define APPS_APCS_QTMR_AC_BASE             (APPS_SS_BASE + 0x00020000)
+#define APPS_APCS_F0_QTMR_V1_BASE          (APPS_SS_BASE + 0x00021000)
+#define QTMR_BASE                          APPS_APCS_F0_QTMR_V1_BASE
+
+#define PERIPH_SS_BASE                     0x07800000
+
+#define MSM_SDC1_BASE                      (PERIPH_SS_BASE + 0x00024000)
+#define MSM_SDC2_BASE                      (PERIPH_SS_BASE + 0x00064000)
+
+/* UART */
+#define BLSP1_UART0_BASE                   (PERIPH_SS_BASE + 0x000AF000)
+#define BLSP1_UART1_BASE                   (PERIPH_SS_BASE + 0x000B0000)
+#define MSM_USB_BASE                       (PERIPH_SS_BASE + 0x000DB000)
+
+#define CLK_CTL_BASE                       0x1800000
+
+#define SPMI_BASE                          0x02000000
+#define SPMI_GENI_BASE                     (SPMI_BASE + 0xA000)
+#define SPMI_PIC_BASE                      (SPMI_BASE +  0x01800000)
+#define PMIC_ARB_CORE                      0x200F000
+
+#define TLMM_BASE_ADDR                     0x1000000
+#define GPIO_CONFIG_ADDR(x)                (TLMM_BASE_ADDR + (x)*0x1000)
+#define GPIO_IN_OUT_ADDR(x)                (TLMM_BASE_ADDR + 0x00000004 + (x)*0x1000)
+
+#define MPM2_MPM_CTRL_BASE                 0x004A0000
+#define MPM2_MPM_PS_HOLD                   0x004AB000
+#define MPM2_MPM_SLEEP_TIMETICK_COUNT_VAL  0x004A3000
+
+/* CRYPTO ENGINE */
+#define  MSM_CE1_BASE                      0x073A000
+#define  MSM_CE1_BAM_BASE                  0x0704000
+#define  GCC_CRYPTO_BCR                    (CLK_CTL_BASE + 0x16000)
+#define  GCC_CRYPTO_CMD_RCGR               (CLK_CTL_BASE + 0x16004)
+#define  GCC_CRYPTO_CFG_RCGR               (CLK_CTL_BASE + 0x16008)
+#define  GCC_CRYPTO_CBCR                   (CLK_CTL_BASE + 0x1601C)
+#define  GCC_CRYPTO_AXI_CBCR               (CLK_CTL_BASE + 0x16020)
+#define  GCC_CRYPTO_AHB_CBCR               (CLK_CTL_BASE + 0x16024)
+
+/* GPLL */
+#define GPLL0_STATUS                       (CLK_CTL_BASE + 0x2101C)
+#define APCS_GPLL_ENA_VOTE                 (CLK_CTL_BASE + 0x45000)
+#define APCS_CLOCK_BRANCH_ENA_VOTE         (CLK_CTL_BASE + 0x45004)
+#define GPLL4_MODE                         (CLK_CTL_BASE + 0x24000)
+
+/* SDCC */
+#define SDC1_HDRV_PULL_CTL                 (TLMM_BASE_ADDR + 0x10A000)
+#define SDCC1_BCR                          (CLK_CTL_BASE + 0x42000) /* block reset*/
+#define SDCC1_APPS_CBCR                    (CLK_CTL_BASE + 0x42018) /* branch ontrol */
+#define SDCC1_AHB_CBCR                     (CLK_CTL_BASE + 0x4201C)
+#define SDCC1_CMD_RCGR                     (CLK_CTL_BASE + 0x42004) /* cmd */
+#define SDCC1_CFG_RCGR                     (CLK_CTL_BASE + 0x42008) /* cfg */
+#define SDCC1_M                            (CLK_CTL_BASE + 0x4200C) /* m */
+#define SDCC1_N                            (CLK_CTL_BASE + 0x42010) /* n */
+#define SDCC1_D                            (CLK_CTL_BASE + 0x42014) /* d */
+
+/* SDHCI */
+#define MSM_SDC1_SDHCI_BASE                (PERIPH_SS_BASE + 0x00024900)
+#define MSM_SDC2_SDHCI_BASE                (PERIPH_SS_BASE + 0x00064900)
+
+#define SDCC_MCI_HC_MODE                   (0x00000078)
+#define SDCC_HC_PWRCTL_STATUS_REG          (0x000000DC)
+#define SDCC_HC_PWRCTL_MASK_REG            (0x000000E0)
+#define SDCC_HC_PWRCTL_CLEAR_REG           (0x000000E4)
+#define SDCC_HC_PWRCTL_CTL_REG             (0x000000E8)
+
+#define SDCC2_BCR                          (CLK_CTL_BASE + 0x43000) /* block reset */
+#define SDCC2_APPS_CBCR                    (CLK_CTL_BASE + 0x43018) /* branch control */
+#define SDCC2_AHB_CBCR                     (CLK_CTL_BASE + 0x4301C)
+#define SDCC2_CMD_RCGR                     (CLK_CTL_BASE + 0x43004) /* cmd */
+#define SDCC2_CFG_RCGR                     (CLK_CTL_BASE + 0x43008) /* cfg */
+#define SDCC2_M                            (CLK_CTL_BASE + 0x4300C) /* m */
+#define SDCC2_N                            (CLK_CTL_BASE + 0x43010) /* n */
+#define SDCC2_D                            (CLK_CTL_BASE + 0x43014) /* d */
+
+/* UART */
+#define BLSP1_AHB_CBCR                     (CLK_CTL_BASE + 0x1008)
+#define BLSP1_UART2_APPS_CBCR              (CLK_CTL_BASE + 0x302C)
+#define BLSP1_UART2_APPS_CMD_RCGR          (CLK_CTL_BASE + 0x3034)
+#define BLSP1_UART2_APPS_CFG_RCGR          (CLK_CTL_BASE + 0x3038)
+#define BLSP1_UART2_APPS_M                 (CLK_CTL_BASE + 0x303C)
+#define BLSP1_UART2_APPS_N                 (CLK_CTL_BASE + 0x3040)
+#define BLSP1_UART2_APPS_D                 (CLK_CTL_BASE + 0x3044)
+
+/* USB */
+#define USB_HS_BCR                         (CLK_CTL_BASE + 0x41000)
+#define USB_HS_SYSTEM_CBCR                 (CLK_CTL_BASE + 0x41004)
+#define USB_HS_AHB_CBCR                    (CLK_CTL_BASE + 0x41008)
+#define USB_HS_SYSTEM_CMD_RCGR             (CLK_CTL_BASE + 0x41010)
+#define USB_HS_SYSTEM_CFG_RCGR             (CLK_CTL_BASE + 0x41014)
+
+#define TCSR_TZ_WONCE               0x193D000
+#define TCSR_BOOT_MISC_DETECT       0x193D100
+#endif
diff --git a/platform/thulium/include/platform/irqs.h b/platform/msm8952/include/platform/irqs.h
similarity index 64%
copy from platform/thulium/include/platform/irqs.h
copy to platform/msm8952/include/platform/irqs.h
index 696c83f..810f113 100644
--- a/platform/thulium/include/platform/irqs.h
+++ b/platform/msm8952/include/platform/irqs.h
@@ -1,17 +1,17 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
-
+/* Copyright (c) 2015, 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, Inc. nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
+ *     * 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
@@ -26,9 +26,8 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-
-#ifndef __IRQS_THULIUM_H
-#define __IRQS_THULIUM_H
+#ifndef __IRQS_MSM8952_H
+#define __IRQS_MSM8952_H
 
 /* MSM ACPU Interrupt Numbers */
 
@@ -43,23 +42,18 @@
 #define INT_QTMR_NON_SECURE_PHY_TIMER_EXP      (GIC_PPI_START + 3)
 #define INT_QTMR_VIRTUAL_TIMER_EXP             (GIC_PPI_START + 4)
 
-#define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP      (GIC_SPI_START + 31)
+#define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP      (GIC_SPI_START + 257)
 
-#define USB30_EE1_IRQ                          (GIC_SPI_START + 131)
-
-#define GLINK_IPC_IRQ                          (GIC_SPI_START + 168)
-
-/* Retrofit universal macro names */
-#define INT_USB_HS                             USB30_EE1_IRQ
-
-#define SDCC1_PWRCTL_IRQ                       (GIC_SPI_START + 134)
+#define USB1_HS_BAM_IRQ                        (GIC_SPI_START + 135)
+#define USB1_HS_IRQ                            (GIC_SPI_START + 134)
+#define SDCC1_PWRCTL_IRQ                       (GIC_SPI_START + 138)
 #define SDCC2_PWRCTL_IRQ                       (GIC_SPI_START + 221)
 
-#define UFS_IRQ                                (GIC_SPI_START + 265)
+/* Retrofit universal macro names */
+#define INT_USB_HS                             USB1_HS_IRQ
 
-#define EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ         (GIC_SPI_START + 265)
+#define EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ         (GIC_SPI_START + 190)
 
-/* Fix this: where this comes from? */
 #define NR_MSM_IRQS                            256
 #define NR_GPIO_IRQS                           173
 #define NR_BOARD_IRQS                          0
@@ -67,4 +61,4 @@
 #define NR_IRQS                                (NR_MSM_IRQS + NR_GPIO_IRQS + \
                                                NR_BOARD_IRQS)
 
-#endif	/* __IRQS_THULIUM_H */
+#endif /* __IRQS_MSM8952_H */
diff --git a/platform/msm8952/msm8952-clock.c b/platform/msm8952/msm8952-clock.c
new file mode 100644
index 0000000..f464cc8
--- /dev/null
+++ b/platform/msm8952/msm8952-clock.c
@@ -0,0 +1,418 @@
+/* Copyright (c) 2015, 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 <assert.h>
+#include <reg.h>
+#include <err.h>
+#include <clock.h>
+#include <clock_pll.h>
+#include <clock_lib2.h>
+#include <platform/clock.h>
+#include <platform/iomap.h>
+#include <platform.h>
+
+/* Mux source select values */
+#define cxo_source_val    0
+#define gpll0_source_val  1
+#define gpll4_source_val  2
+#define cxo_mm_source_val 0
+#define gpll0_mm_source_val 1
+
+struct clk_freq_tbl rcg_dummy_freq = F_END;
+
+
+/* Clock Operations */
+static struct clk_ops clk_ops_branch =
+{
+	.enable     = clock_lib2_branch_clk_enable,
+	.disable    = clock_lib2_branch_clk_disable,
+	.set_rate   = clock_lib2_branch_set_rate,
+};
+
+static struct clk_ops clk_ops_rcg_mnd =
+{
+	.enable     = clock_lib2_rcg_enable,
+	.set_rate   = clock_lib2_rcg_set_rate,
+};
+
+static struct clk_ops clk_ops_rcg =
+{
+	.enable     = clock_lib2_rcg_enable,
+	.set_rate   = clock_lib2_rcg_set_rate,
+};
+
+static struct clk_ops clk_ops_cxo =
+{
+	.enable     = cxo_clk_enable,
+	.disable    = cxo_clk_disable,
+};
+
+static struct clk_ops clk_ops_pll_vote =
+{
+	.enable     = pll_vote_clk_enable,
+	.disable    = pll_vote_clk_disable,
+	.auto_off   = pll_vote_clk_disable,
+	.is_enabled = pll_vote_clk_is_enabled,
+};
+
+static struct clk_ops clk_ops_vote =
+{
+	.enable     = clock_lib2_vote_clk_enable,
+	.disable    = clock_lib2_vote_clk_disable,
+};
+
+/* Clock Sources */
+static struct fixed_clk cxo_clk_src =
+{
+	.c = {
+		.rate     = 19200000,
+		.dbg_name = "cxo_clk_src",
+		.ops      = &clk_ops_cxo,
+	},
+};
+
+static struct pll_vote_clk gpll0_clk_src =
+{
+	.en_reg       = (void *) APCS_GPLL_ENA_VOTE,
+	.en_mask      = BIT(0),
+	.status_reg   = (void *) GPLL0_STATUS,
+	.status_mask  = BIT(17),
+	.parent       = &cxo_clk_src.c,
+
+	.c = {
+		.rate     = 800000000,
+		.dbg_name = "gpll0_clk_src",
+		.ops      = &clk_ops_pll_vote,
+	},
+};
+
+static struct pll_vote_clk gpll4_clk_src =
+{
+	.en_reg       = (void *) APCS_GPLL_ENA_VOTE,
+	.en_mask      = BIT(5),
+	.status_reg   = (void *) GPLL4_MODE,
+	.status_mask  = BIT(30),
+	.parent       = &cxo_clk_src.c,
+
+	.c = {
+		.rate     = 1152000000,
+		.dbg_name = "gpll4_clk_src",
+		.ops      = &clk_ops_pll_vote,
+	},
+};
+
+/* SDCC Clocks */
+static struct clk_freq_tbl ftbl_gcc_sdcc1_apps_clk[] =
+{
+	F(   144000,    cxo,  16,   3,  25),
+	F(   400000,    cxo,  12,   1,   4),
+	F( 20000000,  gpll0,  10,   1,   4),
+	F( 25000000,  gpll0,  16,   1,   2),
+	F( 50000000,  gpll0,  16,   0,   0),
+	F(100000000,  gpll0,   8,   0,   0),
+	F(177770000,  gpll0, 4.5,   0,   0),
+	F(192000000,  gpll0,   6,   0,   0),
+	F(384000000,  gpll4,   3,   0,   0),
+	F_END
+};
+
+static struct rcg_clk sdcc1_apps_clk_src =
+{
+	.cmd_reg      = (uint32_t *) SDCC1_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) SDCC1_CFG_RCGR,
+	.m_reg        = (uint32_t *) SDCC1_M,
+	.n_reg        = (uint32_t *) SDCC1_N,
+	.d_reg        = (uint32_t *) SDCC1_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_sdcc1_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "sdc1_clk",
+		.ops      = &clk_ops_rcg_mnd,
+	},
+};
+
+static struct branch_clk gcc_sdcc1_apps_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC1_APPS_CBCR,
+	.parent       = &sdcc1_apps_clk_src.c,
+
+	.c = {
+		.dbg_name = "gcc_sdcc1_apps_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_sdcc1_ahb_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC1_AHB_CBCR,
+	.has_sibling  = 1,
+
+	.c = {
+		.dbg_name = "gcc_sdcc1_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_sdcc2_apps_clk[] =
+{
+	F(   144000,    cxo,  16,   3,  25),
+	F(   400000,    cxo,  12,   1,   4),
+	F( 20000000,  gpll0,  10,   1,   4),
+	F( 25000000,  gpll0,  16,   1,   2),
+	F( 50000000,  gpll0,  16,   0,   0),
+	F(100000000,  gpll0,   8,   0,   0),
+	F(177770000,  gpll0, 4.5,   0,   0),
+	F(200000000,  gpll0,   4,   0,   0),
+	F_END
+};
+
+static struct rcg_clk sdcc2_apps_clk_src =
+{
+	.cmd_reg      = (uint32_t *) SDCC2_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) SDCC2_CFG_RCGR,
+	.m_reg        = (uint32_t *) SDCC2_M,
+	.n_reg        = (uint32_t *) SDCC2_N,
+	.d_reg        = (uint32_t *) SDCC2_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_sdcc2_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "sdc2_clk",
+		.ops      = &clk_ops_rcg_mnd,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC2_APPS_CBCR,
+	.parent       = &sdcc2_apps_clk_src.c,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_apps_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC2_AHB_CBCR,
+	.has_sibling  = 1,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+/* UART Clocks */
+static struct clk_freq_tbl ftbl_gcc_blsp1_2_uart1_2_apps_clk[] =
+{
+	F( 3686400,  gpll0,    1,  72,  15625),
+	F( 7372800,  gpll0,    1, 144,  15625),
+	F(14745600,  gpll0,    1, 288,  15625),
+	F(16000000,  gpll0,   10,   1,      5),
+	F(19200000,    cxo,    1,   0,      0),
+	F(24000000,  gpll0,    1,   3,    100),
+	F(25000000,  gpll0,   16,   1,      2),
+	F(32000000,  gpll0,    1,   1,     25),
+	F(40000000,  gpll0,    1,   1,     20),
+	F(46400000,  gpll0,    1,  29,    500),
+	F(48000000,  gpll0,    1,   3,     50),
+	F(51200000,  gpll0,    1,   8,    125),
+	F(56000000,  gpll0,    1,   7,    100),
+	F(58982400,  gpll0,    1,1152,  15625),
+	F(60000000,  gpll0,    1,   3,     40),
+	F_END
+};
+
+static struct rcg_clk blsp1_uart2_apps_clk_src =
+{
+	.cmd_reg      = (uint32_t *) BLSP1_UART2_APPS_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) BLSP1_UART2_APPS_CFG_RCGR,
+	.m_reg        = (uint32_t *) BLSP1_UART2_APPS_M,
+	.n_reg        = (uint32_t *) BLSP1_UART2_APPS_N,
+	.d_reg        = (uint32_t *) BLSP1_UART2_APPS_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_blsp1_2_uart1_2_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "blsp1_uart2_apps_clk",
+		.ops      = &clk_ops_rcg_mnd,
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart2_apps_clk =
+{
+	.cbcr_reg     = (uint32_t *) BLSP1_UART2_APPS_CBCR,
+	.parent       = &blsp1_uart2_apps_clk_src.c,
+
+	.c = {
+		.dbg_name = "gcc_blsp1_uart2_apps_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct vote_clk gcc_blsp1_ahb_clk = {
+	.cbcr_reg     = (uint32_t *) BLSP1_AHB_CBCR,
+	.vote_reg     = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask      = BIT(10),
+
+	.c = {
+		.dbg_name = "gcc_blsp1_ahb_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+/* USB Clocks */
+static struct clk_freq_tbl ftbl_gcc_usb_hs_system_clk[] =
+{
+	F(133330000,  gpll0,    6,   0,   0),
+	F_END
+};
+
+static struct rcg_clk usb_hs_system_clk_src =
+{
+	.cmd_reg      = (uint32_t *) USB_HS_SYSTEM_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) USB_HS_SYSTEM_CFG_RCGR,
+
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_gcc_usb_hs_system_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "usb_hs_system_clk",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk gcc_usb_hs_system_clk =
+{
+	.cbcr_reg     = (uint32_t *) USB_HS_SYSTEM_CBCR,
+	.parent       = &usb_hs_system_clk_src.c,
+
+	.c = {
+		.dbg_name = "gcc_usb_hs_system_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_usb_hs_ahb_clk =
+{
+	.cbcr_reg     = (uint32_t *) USB_HS_AHB_CBCR,
+	.has_sibling  = 1,
+
+	.c = {
+		.dbg_name = "gcc_usb_hs_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
+	F(160000000,  gpll0,   5,   0,   0),
+	F_END
+};
+
+static struct rcg_clk ce1_clk_src = {
+	.cmd_reg      = (uint32_t *) GCC_CRYPTO_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) GCC_CRYPTO_CFG_RCGR,
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_gcc_ce1_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "ce1_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct vote_clk gcc_ce1_clk = {
+	.cbcr_reg      = (uint32_t *) GCC_CRYPTO_CBCR,
+	.vote_reg      = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask       = BIT(2),
+
+	.c = {
+		.dbg_name  = "gcc_ce1_clk",
+		.ops       = &clk_ops_vote,
+	},
+};
+
+static struct vote_clk gcc_ce1_ahb_clk = {
+	.cbcr_reg     = (uint32_t *) GCC_CRYPTO_AHB_CBCR,
+	.vote_reg     = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask      = BIT(0),
+
+	.c = {
+		.dbg_name = "gcc_ce1_ahb_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+static struct vote_clk gcc_ce1_axi_clk = {
+	.cbcr_reg     = (uint32_t *) GCC_CRYPTO_AXI_CBCR,
+	.vote_reg     = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask      = BIT(1),
+
+	.c = {
+		.dbg_name = "gcc_ce1_axi_clk",
+		.ops      = &clk_ops_vote,
+	},
+};
+
+/* Clock lookup table */
+static struct clk_lookup msm_clocks_8952[] =
+{
+	CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
+	CLK_LOOKUP("sdc1_core_clk",  gcc_sdcc1_apps_clk.c),
+
+	CLK_LOOKUP("sdc2_iface_clk", gcc_sdcc2_ahb_clk.c),
+	CLK_LOOKUP("sdc2_core_clk",  gcc_sdcc2_apps_clk.c),
+
+	CLK_LOOKUP("uart2_iface_clk", gcc_blsp1_ahb_clk.c),
+	CLK_LOOKUP("uart2_core_clk",  gcc_blsp1_uart2_apps_clk.c),
+
+	CLK_LOOKUP("usb_iface_clk",  gcc_usb_hs_ahb_clk.c),
+	CLK_LOOKUP("usb_core_clk",   gcc_usb_hs_system_clk.c),
+
+
+	CLK_LOOKUP("ce1_ahb_clk",  gcc_ce1_ahb_clk.c),
+	CLK_LOOKUP("ce1_axi_clk",  gcc_ce1_axi_clk.c),
+	CLK_LOOKUP("ce1_core_clk", gcc_ce1_clk.c),
+	CLK_LOOKUP("ce1_src_clk",  ce1_clk_src.c),
+};
+
+void platform_clock_init(void)
+{
+	clk_init(msm_clocks_8952, ARRAY_SIZE(msm_clocks_8952));
+}
diff --git a/platform/msm8952/platform.c b/platform/msm8952/platform.c
new file mode 100644
index 0000000..1ee7cdc
--- /dev/null
+++ b/platform/msm8952/platform.c
@@ -0,0 +1,169 @@
+/* Copyright (c) 2015, 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 <debug.h>
+#include <reg.h>
+#include <platform/iomap.h>
+#include <platform/irqs.h>
+#include <platform/clock.h>
+#include <qgic.h>
+#include <qtimer.h>
+#include <mmu.h>
+#include <arch/arm/mmu.h>
+#include <smem.h>
+#include <board.h>
+#include <boot_stats.h>
+#include <platform.h>
+
+#define MSM_IOMAP_SIZE ((MSM_IOMAP_END - MSM_IOMAP_BASE)/MB)
+#define APPS_SS_SIZE   ((APPS_SS_END - APPS_SS_BASE)/MB)
+
+/* LK memory - cacheable, write through */
+#define LK_MEMORY         (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE | \
+				MMU_MEMORY_AP_READ_WRITE)
+
+/* Peripherals - non-shared device */
+#define IOMAP_MEMORY      (MMU_MEMORY_TYPE_DEVICE_SHARED | \
+				MMU_MEMORY_AP_READ_WRITE | MMU_MEMORY_XN)
+
+/* IMEM memory - cacheable, write through */
+#define COMMON_MEMORY     (MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH | \
+				MMU_MEMORY_AP_READ_WRITE | MMU_MEMORY_XN)
+
+#define SCRATCH_MEMORY    (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE | \
+				MMU_MEMORY_AP_READ_WRITE | MMU_MEMORY_XN)
+
+static mmu_section_t mmu_section_table[] = {
+/*           Physical addr,         Virtual addr,            Size (in MB),     Flags */
+	{    MEMBASE,               MEMBASE,                 (MEMSIZE / MB),   LK_MEMORY},
+	{    MSM_IOMAP_BASE,        MSM_IOMAP_BASE,          MSM_IOMAP_SIZE,   IOMAP_MEMORY},
+	{    APPS_SS_BASE,          APPS_SS_BASE,            APPS_SS_SIZE,      IOMAP_MEMORY},
+	{    MSM_SHARED_IMEM_BASE,  MSM_SHARED_IMEM_BASE,    1,                COMMON_MEMORY},
+	{    SCRATCH_ADDR,          SCRATCH_ADDR,            256,              SCRATCH_MEMORY},
+};
+
+void platform_early_init(void)
+{
+	board_init();
+	platform_clock_init();
+	qgic_init();
+	qtimer_init();
+	scm_init();
+}
+
+void platform_init(void)
+{
+	dprintf(INFO, "platform_init()\n");
+}
+
+void platform_uninit(void)
+{
+	qtimer_uninit();
+}
+
+uint32_t platform_get_sclk_count(void)
+{
+	return readl(MPM2_MPM_SLEEP_TIMETICK_COUNT_VAL);
+}
+
+addr_t get_bs_info_addr()
+{
+	return ((addr_t)BS_INFO_ADDR);
+}
+
+int platform_use_identity_mmu_mappings(void)
+{
+	/* Use only the mappings specified in this file. */
+	return 0;
+}
+
+/* Setup MMU mapping for this platform */
+void platform_init_mmu_mappings(void)
+{
+	uint32_t i;
+	uint32_t sections;
+	uint32_t table_size = ARRAY_SIZE(mmu_section_table);
+	uint32_t ddr_start = get_ddr_start();
+	uint32_t smem_addr = platform_get_smem_base_addr();
+
+	/*Mapping the ddr start address for loading the kernel about 90 MB*/
+	sections = 90;
+	while(sections--)
+	{
+		arm_mmu_map_section(ddr_start + sections * MB, ddr_start + sections* MB, COMMON_MEMORY);
+	}
+
+
+	/* Mapping the SMEM addr */
+	arm_mmu_map_section(smem_addr, smem_addr, COMMON_MEMORY);
+
+	/* Configure the MMU page entries for memory read from the
+	   mmu_section_table */
+	for (i = 0; i < table_size; i++)
+	{
+		sections = mmu_section_table[i].num_of_sections;
+
+		while (sections--)
+		{
+			arm_mmu_map_section(mmu_section_table[i].paddress +
+								sections * MB,
+								mmu_section_table[i].vaddress +
+								sections * MB,
+								mmu_section_table[i].flags);
+		}
+	}
+}
+
+addr_t platform_get_virt_to_phys_mapping(addr_t virt_addr)
+{
+	/* Using 1-1 mapping on this platform. */
+	return virt_addr;
+}
+
+addr_t platform_get_phys_to_virt_mapping(addr_t phys_addr)
+{
+	/* Using 1-1 mapping on this platform. */
+	return phys_addr;
+}
+
+/* DYNAMIC SMEM REGION feature enables LK to dynamically
+ * read the SMEM addr info from TCSR_TZ_WONCE register.
+ * The first word read, if indicates a MAGIC number, then
+ * Dynamic SMEM is assumed to be enabled. Read the remaining
+ * SMEM info for SMEM Size and Phy_addr from the other bytes.
+ */
+uint32_t platform_get_smem_base_addr()
+{
+	struct smem_addr_info *smem_info = NULL;
+
+	smem_info = (struct smem_addr_info *)readl(TCSR_TZ_WONCE);
+	if(smem_info && (smem_info->identifier == SMEM_TARGET_INFO_IDENTIFIER))
+		return smem_info->phy_addr;
+	else
+		return MSM_SHARED_BASE;
+}
diff --git a/platform/msm8952/rules.mk b/platform/msm8952/rules.mk
new file mode 100644
index 0000000..a337b97
--- /dev/null
+++ b/platform/msm8952/rules.mk
@@ -0,0 +1,27 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH    := arm
+#Compiling this as cortex-a8 until the compiler supports krait
+ARM_CPU := cortex-a8
+CPU     := generic
+
+DEFINES += ARM_CPU_CORE_A7
+DEFINES += ARM_CORE_V8
+
+MMC_SLOT         := 1
+
+DEFINES += PERIPH_BLK_BLSP=1
+DEFINES += WITH_CPU_EARLY_INIT=0 WITH_CPU_WARM_BOOT=0 \
+	MMC_SLOT=$(MMC_SLOT) SSD_ENABLE
+
+INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared/include
+
+OBJS += \
+       $(LOCAL_DIR)/platform.o \
+       $(LOCAL_DIR)/acpuclock.o \
+       $(LOCAL_DIR)/msm8952-clock.o \
+       $(LOCAL_DIR)/gpio.o
+
+LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
+
+include platform/msm_shared/rules.mk
diff --git a/platform/msm8994/acpuclock.c b/platform/msm8994/acpuclock.c
index 6b77ea0..c59e61a 100644
--- a/platform/msm8994/acpuclock.c
+++ b/platform/msm8994/acpuclock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -37,6 +37,7 @@
 #include <platform/timer.h>
 #include <rpm-smd.h>
 #include <regulator.h>
+#include <platform.h>
 
 #define RPM_CE_CLK_TYPE    0x6563
 #define CE2_CLK_ID         0x1
@@ -161,7 +162,10 @@
 	}
 	else if(freq == MMC_CLK_192MHZ)
 	{
-		ret = clk_get_set_enable(clk_name, 192000000, 1);
+		if (platform_is_msm8992())
+			ret = clk_get_set_enable(clk_name, 172000000, 1);
+		else
+			ret = clk_get_set_enable(clk_name, 192000000, 1);
 	}
 	else if(freq == MMC_CLK_200MHZ)
 	{
@@ -169,7 +173,10 @@
 	}
 	else if(freq == MMC_CLK_400MHZ)
 	{
-		ret = clk_get_set_enable(clk_name, 384000000, 1);
+		if (platform_is_msm8992())
+			ret = clk_get_set_enable(clk_name, 344000000, 1);
+		else
+			ret = clk_get_set_enable(clk_name, 384000000, 1);
 	}
 	else
 	{
diff --git a/platform/msm8994/msm8994-clock.c b/platform/msm8994/msm8994-clock.c
index 358db25..8653f8d 100644
--- a/platform/msm8994/msm8994-clock.c
+++ b/platform/msm8994/msm8994-clock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -34,6 +34,7 @@
 #include <clock_lib2.h>
 #include <platform/clock.h>
 #include <platform/iomap.h>
+#include <platform.h>
 
 
 /* Mux source select values */
@@ -256,6 +257,19 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_sdcc1_apps_clk_8992[] =
+{
+	F(   144000,    cxo,  16,   3,  25),
+	F(   400000,    cxo,  12,   1,   4),
+	F( 20000000,  gpll0,  15,   1,   2),
+	F( 25000000,  gpll0,  12,   1,   2),
+	F( 50000000,  gpll0,  12,   0,   0),
+	F( 96000000,  gpll4,   6,   0,   0),
+	F(172000000,  gpll4,   2,   0,   0),
+	F(344000000,  gpll4,   1,   0,   0),
+	F_END
+};
+
 static struct clk_freq_tbl ftbl_gcc_sdcc2_4_apps_clk[] =
 {
 	F(   144000,    cxo,  16,   3,  25),
@@ -825,7 +839,16 @@
 	CLK_LOOKUP("edp_aux_clk",          mdss_edpaux_clk.c),
 };
 
+void msm8992_sdc1_clock_override()
+{
+	sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_8992;
+}
+
 void platform_clock_init(void)
 {
+	if (platform_is_msm8992())
+	{
+		msm8992_sdc1_clock_override();
+	}
 	clk_init(msm_8994_clocks, ARRAY_SIZE(msm_8994_clocks));
 }
diff --git a/platform/msm8994/platform.c b/platform/msm8994/platform.c
index 507158b..eaaadc0 100644
--- a/platform/msm8994/platform.c
+++ b/platform/msm8994/platform.c
@@ -40,7 +40,7 @@
 #define MSM_IOMAP_SIZE ((MSM_IOMAP_END - MSM_IOMAP_BASE)/MB)
 
 /* LK memory - cacheable, write through */
-#define LK_MEMORY         (MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH | \
+#define LK_MEMORY         (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE | \
                            MMU_MEMORY_AP_READ_WRITE)
 
 /* Peripherals - non-shared device */
@@ -123,7 +123,7 @@
 										sections * MB,
 										ptn_entry.start +
 										sections * MB,
-										(MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH | \
+										(MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE | \
 										 MMU_MEMORY_AP_READ_WRITE | MMU_MEMORY_XN));
 				}
 			}
diff --git a/platform/thulium/acpuclock.c b/platform/msm8996/acpuclock.c
similarity index 95%
rename from platform/thulium/acpuclock.c
rename to platform/msm8996/acpuclock.c
index e2ee7d5..15ebd30 100644
--- a/platform/thulium/acpuclock.c
+++ b/platform/msm8996/acpuclock.c
@@ -123,6 +123,20 @@
  */
 static void ce_async_reset(uint8_t instance)
 {
+	if (instance == 1)
+	{
+		/* Start the block reset for CE */
+		writel(1, GCC_CE1_BCR);
+		udelay(2);
+		/* Take CE block out of reset */
+		writel(0, GCC_CE1_BCR);
+		udelay(2);
+	}
+	else
+	{
+		dprintf(CRITICAL, "Unsupported CE instance: %u\n", instance);
+		ASSERT(0);
+	}
 }
 
 void clock_ce_enable(uint8_t instance)
diff --git a/platform/thulium/gpio.c b/platform/msm8996/gpio.c
similarity index 100%
rename from platform/thulium/gpio.c
rename to platform/msm8996/gpio.c
diff --git a/platform/thulium/include/platform/clock.h b/platform/msm8996/include/platform/clock.h
similarity index 100%
rename from platform/thulium/include/platform/clock.h
rename to platform/msm8996/include/platform/clock.h
diff --git a/platform/thulium/include/platform/gpio.h b/platform/msm8996/include/platform/gpio.h
similarity index 96%
rename from platform/thulium/include/platform/gpio.h
rename to platform/msm8996/include/platform/gpio.h
index c00512b..5626d50 100644
--- a/platform/thulium/include/platform/gpio.h
+++ b/platform/msm8996/include/platform/gpio.h
@@ -9,7 +9,7 @@
  *    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, Inc. nor the names of its
+ *  * 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.
  *
diff --git a/platform/thulium/include/platform/iomap.h b/platform/msm8996/include/platform/iomap.h
similarity index 94%
rename from platform/thulium/include/platform/iomap.h
rename to platform/msm8996/include/platform/iomap.h
index 276841d..180b237 100644
--- a/platform/thulium/include/platform/iomap.h
+++ b/platform/msm8996/include/platform/iomap.h
@@ -153,8 +153,9 @@
 #define SPMI_PIC_BASE               (SPMI_BASE + 0x1800000)
 #define PMIC_ARB_CORE               0x400F000
 
-#define MSM_CE_BAM_BASE             0x67A000
-#define MSM_CE_BASE                 0x644000
+#define MSM_CE_BAM_BASE             0x644000
+#define MSM_CE_BASE                 0x67A000
+#define GCC_CE1_BCR                 (CLK_CTL_BASE + 0x00041000)
 
 #define TLMM_BASE_ADDR              0x1010000
 #define GPIO_CONFIG_ADDR(x)         (TLMM_BASE_ADDR + (x)*0x1000)
@@ -164,6 +165,10 @@
 #define MPM2_MPM_PS_HOLD                     0x4AB000
 #define MPM2_MPM_SLEEP_TIMETICK_COUNT_VAL    0x4A3000
 
+/* QSEECOM: Secure app region notification */
+#define APP_REGION_ADDR 0x86600000
+#define APP_REGION_SIZE 0xd00000
+
 /* DRV strength for sdcc */
 #define SDC1_HDRV_PULL_CTL           (TLMM_BASE_ADDR + 0x0012C000)
 
@@ -188,4 +193,12 @@
 /* Dummy macro needed for compilation only */
 #define PLATFORM_QMP_OFFSET         0x0
 
+/* RPMB send receive buffer needs to be mapped
+ * as device memory, define the start address
+ * and size in MB
+ */
+#define RPMB_SND_RCV_BUF            0x8F200000
+#define RPMB_SND_RCV_BUF_SZ         0x1
+
+#define TCSR_BOOT_MISC_DETECT       0x007B3000
 #endif
diff --git a/platform/thulium/include/platform/irqs.h b/platform/msm8996/include/platform/irqs.h
similarity index 97%
rename from platform/thulium/include/platform/irqs.h
rename to platform/msm8996/include/platform/irqs.h
index 696c83f..ab5e2ff 100644
--- a/platform/thulium/include/platform/irqs.h
+++ b/platform/msm8996/include/platform/irqs.h
@@ -9,7 +9,7 @@
  *     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, Inc. nor the names of its
+ *   * 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.
  *
diff --git a/platform/thulium/include/platform/partial_goods.h b/platform/msm8996/include/platform/partial_goods.h
similarity index 96%
rename from platform/thulium/include/platform/partial_goods.h
rename to platform/msm8996/include/platform/partial_goods.h
index 03c16ec..926c0c6 100644
--- a/platform/thulium/include/platform/partial_goods.h
+++ b/platform/msm8996/include/platform/partial_goods.h
@@ -9,7 +9,7 @@
  *     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
+ *   * 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.
  *
diff --git a/platform/thulium/thulium-clock.c b/platform/msm8996/msm8996-clock.c
similarity index 98%
rename from platform/thulium/thulium-clock.c
rename to platform/msm8996/msm8996-clock.c
index d0a23ed..c082dc5 100644
--- a/platform/thulium/thulium-clock.c
+++ b/platform/msm8996/msm8996-clock.c
@@ -405,7 +405,7 @@
 
 
 /* Clock lookup table */
-static struct clk_lookup msm_thulium_clocks[] =
+static struct clk_lookup msm_msm8996_clocks[] =
 {
 	CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
 	CLK_LOOKUP("sdc1_core_clk",  gcc_sdcc1_apps_clk.c),
@@ -428,5 +428,5 @@
 
 void platform_clock_init(void)
 {
-	clk_init(msm_thulium_clocks, ARRAY_SIZE(msm_thulium_clocks));
+	clk_init(msm_msm8996_clocks, ARRAY_SIZE(msm_msm8996_clocks));
 }
diff --git a/platform/thulium/platform.c b/platform/msm8996/platform.c
similarity index 81%
rename from platform/thulium/platform.c
rename to platform/msm8996/platform.c
index be0678c..a82357b 100644
--- a/platform/thulium/platform.c
+++ b/platform/msm8996/platform.c
@@ -13,17 +13,17 @@
  *       contributors may be used to endorse or promote products derived
  *       from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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.
+ * 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 <debug.h>
@@ -59,6 +59,7 @@
 	{    KERNEL_ADDR,       KERNEL_ADDR,       KERNEL_SIZE,      SCRATCH_MEMORY},
 	{    SCRATCH_ADDR,      SCRATCH_ADDR,      SCRATCH_SIZE,     SCRATCH_MEMORY},
 	{    MSM_SHARED_BASE,   MSM_SHARED_BASE,   MSM_SHARED_SIZE,  SCRATCH_MEMORY},
+	{    RPMB_SND_RCV_BUF,  RPMB_SND_RCV_BUF,  RPMB_SND_RCV_BUF_SZ,    IOMAP_MEMORY},
 };
 
 void platform_early_init(void)
@@ -141,3 +142,8 @@
 	return readl(USB3_PHY_REVISION_ID3) << 24 | readl(USB3_PHY_REVISION_ID2) << 16 |
 		   readl(USB3_PHY_REVISION_ID1) << 8 | readl(USB3_PHY_REVISION_ID0);
 }
+
+uint32_t platform_get_max_periph()
+{
+	return 256;
+}
diff --git a/platform/thulium/rules.mk b/platform/msm8996/rules.mk
similarity index 94%
rename from platform/thulium/rules.mk
rename to platform/msm8996/rules.mk
index 10afc50..8db37d5 100644
--- a/platform/thulium/rules.mk
+++ b/platform/msm8996/rules.mk
@@ -20,7 +20,7 @@
 OBJS += \
 	$(LOCAL_DIR)/platform.o \
 	$(LOCAL_DIR)/acpuclock.o \
-	$(LOCAL_DIR)/thulium-clock.o \
+	$(LOCAL_DIR)/msm8996-clock.o \
 	$(LOCAL_DIR)/gpio.o
 
 LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
diff --git a/platform/msm_shared/crypto5_eng.c b/platform/msm_shared/crypto5_eng.c
index 0f592f9..8caad79 100644
--- a/platform/msm_shared/crypto5_eng.c
+++ b/platform/msm_shared/crypto5_eng.c
@@ -139,6 +139,8 @@
 #else
 	ret = (uint32_t)bam_add_cmd_element(&cmd_list_ptr, reg_addr, val, CE_WRITE_TYPE);
 
+	arch_clean_invalidate_cache_range((addr_t)&cmd_list_ptr, sizeof(struct cmd_element));
+
 	/* Enqueue the desc for the above command */
 	ret = bam_add_one_desc(bam_core,
 						   CRYPTO_WRITE_PIPE_INDEX,
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 0abf723..27296b4 100755
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -414,7 +414,7 @@
  * Return Value: DTB address : If appended device tree is found
  *               'NULL'         : Otherwise
  */
-void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags)
+void *dev_tree_appended(void *kernel, uint32_t kernel_size, uint32_t dtb_offset, void *tags)
 {
 	void *kernel_end = kernel + kernel_size;
 	uint32_t app_dtb_offset = 0;
@@ -437,8 +437,10 @@
 	}
 	list_initialize(&dt_entry_queue->node);
 
-
-	memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
+	if (dtb_offset)
+		app_dtb_offset = dtb_offset;
+	else
+		memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
 
 	if (((uintptr_t)kernel + (uintptr_t)app_dtb_offset) < (uintptr_t)kernel) {
 		return NULL;
diff --git a/platform/msm_shared/glink/glink_api.c b/platform/msm_shared/glink/glink_api.c
new file mode 100644
index 0000000..24f777d
--- /dev/null
+++ b/platform/msm_shared/glink/glink_api.c
@@ -0,0 +1,1532 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+#include <glink.h>
+#include <glink_rpm.h>
+#include <glink_os_utils.h>
+#include <glink_internal.h>
+#include <glink_vector.h>
+#include <glink_channel_migration.h>
+#include <smem_list.h>
+#include <smem_type.h>
+
+#define GLINK_NOT_INITIALIZED 0
+#define GLINK_INITIALIZED     1
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+int glink_core_status = GLINK_NOT_INITIALIZED;
+
+os_cs_type *glink_transport_q_cs;
+os_cs_type *glink_mem_log_cs;
+
+glink_mem_log_entry_type glink_mem_log_arr[GLINK_MEM_LOG_SIZE];
+uint32 glink_mem_log_idx = 0;
+
+/* Keep a list of registered transport for each edge allowed for this host */
+smem_list_type glink_registered_transports[GLINK_NUM_HOSTS];
+
+smem_list_type glink_link_notif_list;
+
+/* List of supported hosts */
+const char* glink_hosts_supported[]   = { "apss",
+                                          "mpss",
+                                          "lpass",
+                                          "dsps",
+                                          "wcnss",
+                                          "tz",
+                                          "rpm",
+                                        };
+
+/* Forward function declarations */
+void glinki_free_intents(glink_channel_ctx_type *open_ch_ctx);
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+glink_err_type glinki_add_ch_to_xport
+(
+  glink_transport_if_type  *if_ptr,
+  glink_transport_if_type  *req_if_ptr,
+  glink_channel_ctx_type   *ch_ctx,
+  glink_channel_ctx_type   **allocated_ch_ctx,
+  unsigned int              local_open,
+  boolean                      migration_state,
+  glink_xport_priority      migrated_ch_prio
+)
+{
+  glink_err_type             status = 0;
+  glink_channel_ctx_type     *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx = if_ptr->glink_core_priv;
+
+  /* See if channel already exists in open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if (strcmp(open_ch_ctx->name, ch_ctx->name) == 0)
+    {
+      /* We've found a channel name is already in the list of open channel */
+      /* increase reference open count for channel */
+      *allocated_ch_ctx = open_ch_ctx;
+      open_ch_ctx->ref_count++;
+
+      /* Case A: Channel was opened before on the same host */
+      if((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) && local_open) {
+
+        open_ch_ctx->req_if_ptr = req_if_ptr;
+
+        /* Copy local open ctx params */
+        open_ch_ctx->notify_rx = ch_ctx->notify_rx;
+        open_ch_ctx->notify_rxv = ch_ctx->notify_rxv;
+        open_ch_ctx->notify_tx_done = ch_ctx->notify_tx_done;
+        open_ch_ctx->notify_state = ch_ctx->notify_state;
+        open_ch_ctx->notify_rx_intent_req = ch_ctx->notify_rx_intent_req;
+        open_ch_ctx->notify_rx_intent = ch_ctx->notify_rx_intent;
+        open_ch_ctx->notify_rx_sigs = ch_ctx->notify_rx_sigs;
+        open_ch_ctx->priv = ch_ctx->priv;
+        open_ch_ctx->ch_open_options = ch_ctx->ch_open_options;
+
+        /* release lock before context switch otherwise it is causing
+         * deadlock */
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        /* Send open cmd to transport */
+        status = if_ptr->tx_cmd_ch_open(if_ptr,
+                      open_ch_ctx->lcid, open_ch_ctx->name,
+                      open_ch_ctx->req_if_ptr->glink_priority);
+      }
+      else if ((open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN) &&
+               (!local_open))
+      {
+        /* Case B: Channel was opened on this end and we got a remote open */
+        open_ch_ctx->rcid = ch_ctx->rcid;
+
+        status = xport_ctx->channel_init(open_ch_ctx);
+
+        /* release lock before context switch otherwise it is causing deadlock */
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        if (status == GLINK_STATUS_SUCCESS)
+        {
+          /* Send ACK to transport */
+          if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, open_ch_ctx->rcid, migrated_ch_prio);
+        }
+      } else if ((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE)
+                  && (local_open)) {
+        /* Allocate new channel context */
+        break; /* code would break out of loop and create new ch ctx */
+      } else {
+        /* Can't handle this state */
+        ASSERT(0);
+      }
+
+      break;
+    } /* end if match found */
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  if (open_ch_ctx != NULL)
+  {
+    glink_os_free(ch_ctx);
+
+    /* connect channel here if state is local open and remote open request
+     * comes up and channel migration is done; channel will be connected in
+     * remote_open_ack if channel state is remote open and local open
+     * request comes up */
+    if(open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN &&
+       migration_state == FALSE && status == GLINK_STATUS_SUCCESS)
+    {
+      /* Set the channel state to OPEN */
+      open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+      /* Inform the client */
+      open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+                                GLINK_CONNECTED);
+    }
+  }
+  else
+  {
+    /* Channel not in the list - it was not previously opened */
+    ch_ctx->if_ptr = if_ptr;
+    *allocated_ch_ctx = ch_ctx;
+
+    /* Set channel state */
+    if (local_open) {
+      /* This is a local open */
+      ch_ctx->state      = GLINK_CH_STATE_LOCAL_OPEN;
+      ch_ctx->req_if_ptr = req_if_ptr;
+    }
+    else {
+      ch_ctx->state = GLINK_CH_STATE_REMOTE_OPEN;
+    }
+
+    glink_os_cs_init(&ch_ctx->tx_cs);
+
+    /* Append the channel to the transport interface's open_list */
+    ch_ctx->ref_count++;
+    ch_ctx->lcid = xport_ctx->free_lcid;
+    xport_ctx->free_lcid++;
+    smem_list_append(&if_ptr->glink_core_priv->open_list, ch_ctx);
+
+    /* release lock before context switch otherwise it is causing deadlock */
+    glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+    /* Send the OPEN command to transport */
+    if (local_open)
+    {
+      status = if_ptr->tx_cmd_ch_open(if_ptr, ch_ctx->lcid,
+                                      ch_ctx->name,
+                                      ch_ctx->req_if_ptr->glink_priority);
+    }
+    else
+    {
+      /* initialize channel resources */
+      status = xport_ctx->channel_init(ch_ctx);
+
+      /* ACK the transport for remote open */
+      if (status == GLINK_STATUS_SUCCESS)
+      {
+        if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, ch_ctx->rcid,
+                                          migrated_ch_prio);
+      }
+    }
+
+    if (status != GLINK_STATUS_SUCCESS)
+    {
+      /* Remove the channel from the transport interface's open_list */
+      xport_ctx->free_lcid--;
+
+      glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+      smem_list_delete(&if_ptr->glink_core_priv->open_list, ch_ctx);
+      glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+      /* free the ch_ctx structure and return */
+      xport_ctx->channel_cleanup(ch_ctx);
+      glink_os_free(ch_ctx);
+    }
+  }
+
+  return status;
+}
+
+/** Default implementation of optional callbacks */
+
+static void glink_default_notify_rx_sigs
+(
+  glink_handle_type  handle,
+  const void         *priv,
+  uint32             prev,
+  uint32             curr
+)
+{
+  return;
+}
+
+static void glinki_call_link_notifier
+(
+  glink_link_notif_data_type *link_notif_data,
+  glink_core_xport_ctx_type  *xport_ctx,
+  glink_link_state_type      state
+)
+{
+  glink_link_info_type link_info;
+
+  ASSERT(xport_ctx);
+  ASSERT(link_notif_data);
+
+  link_info.xport = xport_ctx->xport;
+  link_info.remote_ss = xport_ctx->remote_ss;
+  link_info.link_state = state;
+  link_notif_data->link_notifier(&link_info, link_notif_data->priv);
+}
+
+static uint32 glinki_find_remote_host
+(
+  const char *remote_ss
+)
+{
+  uint32 remote_host;
+  ASSERT(remote_ss);
+
+  for(remote_host = 0;
+      remote_host < sizeof(glink_hosts_supported)/sizeof(char *);
+      remote_host++) {
+    if( 0 == strcmp(glink_hosts_supported[remote_host], remote_ss) ) {
+      /* Match found, break out of loop */
+      break;
+    }
+  }
+  return remote_host;
+}
+
+static void glinki_check_xport_and_notify
+(
+  glink_link_notif_data_type *link_notif_data,
+  glink_core_xport_ctx_type  *xport_ctx,
+  glink_link_state_type      state
+)
+{
+  glink_link_info_type link_info;
+
+  ASSERT(xport_ctx);
+  ASSERT(link_notif_data);
+
+  link_info.xport = xport_ctx->xport;
+  link_info.remote_ss = xport_ctx->remote_ss;
+  link_info.link_state = state;
+
+  if(link_notif_data->xport == NULL ||
+     0 == strcmp(xport_ctx->xport, link_notif_data->xport)) {
+    /* xport not specified, or it is specified and matches the current xport */
+    /* Invoke registered callback */
+    link_notif_data->link_notifier(&link_info, link_notif_data->priv);
+  }
+}
+
+
+static void glinki_scan_xports_and_notify
+(
+  glink_link_notif_data_type *link_notif_data
+)
+{
+  unsigned int remote_host;
+  glink_transport_if_type *if_ptr;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(link_notif_data);
+
+  /* Find matching subsystem */
+  if(link_notif_data->remote_ss) {
+    remote_host = glinki_find_remote_host(link_notif_data->remote_ss);
+
+    /* Find the xport and give link UP notification */
+    if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+    if(if_ptr == NULL) {
+      /* No registered xports at this time, return without doing anything */
+      return;
+    }
+
+    if(link_notif_data->xport) {
+      do {
+        xport_ctx = if_ptr->glink_core_priv;
+        if( 0 == strcmp(xport_ctx->xport, link_notif_data->xport) ) {
+          /* Match found, break out of loop */
+          break;
+        }
+      }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+
+      if((if_ptr != NULL) && (xport_ctx->status == GLINK_XPORT_LINK_UP)) {
+        /* Invoke registered callback */
+        glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                  GLINK_LINK_STATE_UP);
+      }
+    } else {
+      /* No xport has been specified, invoke notifier for all registered
+       * xports */
+      do {
+        xport_ctx = if_ptr->glink_core_priv;
+        if(xport_ctx->status == GLINK_XPORT_LINK_UP) {
+          /* Invoke registered callback */
+          glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                    GLINK_LINK_STATE_UP);
+        }
+      }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+    }
+  } else {
+    /* No remote ss is specified, invoke notifier for all remote_ss */
+    for(remote_host = 0;
+        remote_host < sizeof(glink_hosts_supported)/sizeof(char *);
+        remote_host++) {
+      /* Find the xport and give link UP notification */
+      if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+      if(if_ptr == NULL) {
+        /* No registered xports at this time, continue with next remote_ss */
+        continue;
+      }
+
+      if(link_notif_data->xport) {
+        do {
+          xport_ctx = if_ptr->glink_core_priv;
+          if( 0 == strcmp(xport_ctx->xport, link_notif_data->xport) ) {
+            /* Match found, break out of loop */
+            break;
+          }
+        }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+
+        if((if_ptr != NULL) && (xport_ctx->status == GLINK_XPORT_LINK_UP)) {
+          /* Invoke registered callback */
+          glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                    GLINK_LINK_STATE_UP);
+        }
+      } else {
+        /* No xport has been specified, invoke notifier for all registered
+         * xports */
+        do {
+          xport_ctx = if_ptr->glink_core_priv;
+          if(xport_ctx->status == GLINK_XPORT_LINK_UP) {
+            /* Invoke registered callback */
+            glinki_call_link_notifier(link_notif_data, xport_ctx,
+                                      GLINK_LINK_STATE_UP);
+          }
+        }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+      }
+    } /* end for remote_host */
+  }/* end if else (link_notif_data->remote_ss) */
+} /* glinki_scan_xports_and_notify */
+
+void glinki_scan_notif_list_and_notify
+(
+  glink_transport_if_type *if_ptr,
+  glink_link_state_type state
+)
+{
+  glink_link_notif_data_type *link_notif_data;
+  glink_core_xport_ctx_type  *xport_ctx = if_ptr->glink_core_priv;
+
+  link_notif_data = smem_list_first(&glink_link_notif_list);
+
+  if(link_notif_data == NULL) {
+    /* list empty */
+    return;
+  }
+
+  do {
+      if(link_notif_data->remote_ss &&
+         0 == strcmp(xport_ctx->remote_ss, link_notif_data->remote_ss)) {
+        /* remote_ss specified and matches */
+        glinki_check_xport_and_notify(link_notif_data, xport_ctx, state);
+      } else if(link_notif_data->remote_ss == NULL) {
+        /* remote_ss not specified, invoke link notif for any remote_ss */
+        if(link_notif_data->xport) {
+          glinki_check_xport_and_notify(link_notif_data, xport_ctx, state);
+        } /* if else link_notif_data->xport */
+      } /* if else link_notif_data->remote_ss */
+  } while ( (link_notif_data = smem_list_next(link_notif_data)) != NULL);
+
+} /* glinki_scan_notif_list_and_notify */
+
+void glinki_scan_channels_and_notify_discon
+(
+  glink_transport_if_type *if_ptr
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    /* Found channel, transition it to appropriate state based
+     * on current state */
+    if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+      open_ch_ctx->state = GLINK_CH_STATE_LOCAL_OPEN;
+
+      /* Inform the client */
+      open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+          GLINK_REMOTE_DISCONNECTED);
+    } else if (open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) {
+      /* Local side never opened the channel */
+      /* Free channel resources */
+      xport_ctx->channel_cleanup(open_ch_ctx);
+
+      smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+
+      glink_os_free(open_ch_ctx);
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+  glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+void glink_ssr(const char* remote_ss)
+{
+  unsigned int remote_host;
+  glink_transport_if_type *if_ptr;
+
+  remote_host = glinki_find_remote_host(remote_ss);
+
+  /* Scan through the registered interfaces with the crashing ss
+     and let the clients know about the crash via LINK_DOWN
+     notification followed by REMOTE_DISCONNECT */
+  if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+
+  while(if_ptr != NULL) {
+    /* Invoke LINK_DOWN notification for any registered notifiers */
+    glinki_scan_notif_list_and_notify(if_ptr, GLINK_LINK_STATE_DOWN);
+
+    /* Invoke REMOTE_DISCONNECT for all channels associated with if_ptr */
+    glinki_scan_channels_and_notify_discon(if_ptr);
+
+    /* Let the xport know about ssr */
+    if_ptr->ssr(if_ptr);
+
+    if_ptr = smem_list_next(if_ptr);
+  }
+}
+
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_init
+
+DESCRIPTION   Initializes the GLink core library.
+
+ARGUMENTS     None
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_init(void)
+{
+  uint32 i;
+
+  glink_mem_log_cs = glink_os_cs_create();
+
+  glink_core_status = GLINK_INITIALIZED;
+
+  /* Create/Initalize crtitical sections */
+  glink_transport_q_cs = glink_os_cs_create();
+  if(glink_transport_q_cs == NULL) {
+    return;
+  }
+
+  glink_os_cs_acquire(glink_transport_q_cs);
+  for(i= 0; i < sizeof(glink_registered_transports)/sizeof(smem_list_type);
+      i++)
+  {
+    smem_list_init(&glink_registered_transports[i]);
+  }
+  glink_os_cs_release(glink_transport_q_cs);
+}
+
+/*===========================================================================
+FUNCTION      glink_core_register_transport
+
+DESCRIPTION   Transport calls this API to register its interface with GLINK
+              Core
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            *cfg      Pointer to transport configuration structure.
+
+RETURN VALUE  Standard GLINK error codes.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_err_type glink_core_register_transport
+(
+  glink_transport_if_type       *if_ptr,
+  glink_core_transport_cfg_type *cfg
+)
+{
+  unsigned int remote_host = 0;
+  glink_core_xport_ctx_type *xport_ctx;
+  /* Param validation */
+  if(if_ptr == NULL || cfg == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  if(cfg->name == NULL       ||
+     cfg->remote_ss == NULL  ||
+     cfg->version == NULL    ||
+     cfg->version_count == 0 ||
+     cfg->max_cid == 0)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+
+  if(if_ptr->tx_cmd_version == NULL             ||
+     if_ptr->tx_cmd_version_ack == NULL         ||
+     if_ptr->set_version == NULL                ||
+     if_ptr->tx_cmd_ch_open == NULL             ||
+     if_ptr->tx_cmd_ch_close == NULL            ||
+     if_ptr->tx_cmd_ch_remote_open_ack == NULL  ||
+     if_ptr->tx_cmd_ch_remote_close_ack == NULL ||
+     if_ptr->tx_cmd_set_sigs  == NULL           ||
+     if_ptr->ssr  == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+        cfg->remote_ss, GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;;
+  }
+
+
+  /* Allocate/fill out the GLink Core interface structure */
+  {
+    glink_core_if_type *core_if = glink_os_calloc(sizeof(glink_core_if_type));
+    if(core_if == NULL) {
+      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+      return GLINK_STATUS_OUT_OF_RESOURCES;
+    }
+    core_if->link_up = glink_link_up;
+    core_if->rx_cmd_version = glink_rx_cmd_version;
+    core_if->rx_cmd_version_ack = glink_rx_cmd_version_ack;
+    core_if->rx_cmd_ch_remote_open = glink_rx_cmd_ch_remote_open;
+    core_if->rx_cmd_ch_open_ack = glink_rx_cmd_ch_open_ack;
+    core_if->rx_cmd_ch_close_ack = glink_rx_cmd_ch_close_ack;
+    core_if->rx_cmd_ch_remote_close = glink_rx_cmd_ch_remote_close;
+    core_if->ch_state_local_trans = glink_ch_state_local_trans;
+    core_if->rx_put_pkt_ctx = glink_rx_put_pkt_ctx;
+    core_if->rx_cmd_remote_sigs = glink_rx_cmd_remote_sigs;
+    core_if->tx_resume = glink_tx_resume;
+    core_if->set_core_version = glink_set_core_version;
+
+    /* Set the glink_core_if_ptr to point to the allocated structure */
+    if_ptr->glink_core_if_ptr = core_if;
+  }
+
+  /* Allocate/fill out the GLink private context data */
+  {
+     xport_ctx = glink_os_calloc(sizeof(glink_core_xport_ctx_type));
+    if(xport_ctx == NULL) {
+      /* Free previously allocated memory */
+      glink_os_free(if_ptr->glink_core_if_ptr);
+
+      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+
+      return GLINK_STATUS_OUT_OF_RESOURCES;
+    }
+
+    glink_os_string_copy(xport_ctx->xport, cfg->name,
+        sizeof(xport_ctx->xport));
+    glink_os_string_copy(xport_ctx->remote_ss, cfg->remote_ss,
+        sizeof(xport_ctx->xport));
+    xport_ctx->free_lcid = 1; /* lcid 0 is reserved for invalid channel */
+    xport_ctx->version_array = cfg->version;
+    xport_ctx->version_indx = cfg->version_count - 1;
+
+    glink_os_cs_init(&xport_ctx->channel_q_cs);
+    glink_os_cs_init(&xport_ctx->liid_cs);
+
+    glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+    smem_list_init(&xport_ctx->open_list);
+    glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+    /* Set the glink_core_if_ptr to point to the allocated structure */
+    if_ptr->glink_core_priv = xport_ctx;
+    xport_ctx->status = GLINK_XPORT_REGISTERED;
+  }
+
+  /* Push the transport interface into appropriate queue */
+  remote_host = glinki_find_remote_host(cfg->remote_ss);
+
+  if(remote_host == GLINK_NUM_HOSTS ) {
+    /* Unknown transport name trying to register with GLink */
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
+           xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);
+
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+  glink_os_cs_acquire(glink_transport_q_cs);
+  smem_list_append(&glink_registered_transports[remote_host], if_ptr);
+  glink_os_cs_release(glink_transport_q_cs);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Regsiters a client specified callback to be invoked when the specified
+ * transport (link) is up/down.
+ *
+ * @param[in]    link_id  Pointer to the configuration structure for the
+ *                        xport(link) to be monitored. See glink.h
+ * @param[in]    priv     Callback data returned to client when callback
+ *                        is invoked.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Puts the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_register_link_state_cb
+(
+  glink_link_id_type *link_id,
+  void*              priv
+)
+{
+  glink_link_notif_data_type* link_notif_data;
+  unsigned int remote_host;
+
+  /* Input validation */
+  ASSERT(link_id != NULL);
+
+  /* Make sure client provided us with the correct version of the input
+   * structure */
+  if(link_id->version != GLINK_LINK_ID_VER || link_id->link_notifier == NULL) {
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Save the callback on the notification list */
+  if((link_notif_data = glink_os_malloc(sizeof(glink_link_notif_data_type)))
+       == NULL) {
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  /* Check for remote_ss validity */
+  if(link_id->remote_ss != NULL) {
+    remote_host = glinki_find_remote_host(link_id->remote_ss);
+
+    if(remote_host == sizeof(glink_hosts_supported)/sizeof(char *)) {
+      glink_os_free(link_notif_data);
+      return GLINK_STATUS_INVALID_PARAM;
+    }
+  }
+
+  link_notif_data->xport = link_id->xport;
+  link_notif_data->remote_ss = link_id->remote_ss;
+  link_notif_data->link_notifier = link_id->link_notifier;
+  link_notif_data->priv = priv; /* private client data */
+
+  /* Append the request to the list for link UP/DOWN notifications */
+  smem_list_append(&glink_link_notif_list, link_notif_data);
+
+  /* Scan the list of available transport to see if this link is already up */
+  glinki_scan_xports_and_notify(link_notif_data);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Degsiter the link UP/DOWN notification callback associated with the
+ * provided handle.
+ *
+ * @param[in]    handle  Callback handler returned by
+ *                       glink_register_link_state_cb
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Removes the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_deregister_link_state_cb
+(
+  glink_link_handle_type handle
+)
+{
+  ASSERT(handle);
+
+  smem_list_delete(&glink_link_notif_list,
+                   (glink_link_notif_data_type*)handle);
+
+  glink_os_free(handle);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * This function gives best available transport for give edge
+ *
+ * @param[in]    remote_host  Index into glink_registered_transports array of
+ *                            registered transports list per edge
+ *
+ * @return       pointer to glink_transport_if_type
+ *
+ * @sideeffects  NONE
+ */
+glink_transport_if_type* glink_get_best_xport
+(
+  unsigned int remote_host
+)
+{
+  glink_transport_if_type   *if_ptr    = NULL, *best_if_ptr = NULL;
+  glink_xport_priority       priority  = GLINK_MIN_PRIORITY;
+  glink_core_xport_ctx_type *xport_ctx = NULL;
+
+  best_if_ptr = if_ptr = smem_list_first(
+                          &glink_registered_transports[remote_host]);
+
+  while(if_ptr != NULL)
+  {
+    /* check if priority of current transport is higher than
+     * current highest priority (0 = highest priority)
+     */
+    xport_ctx = if_ptr->glink_core_priv;
+    if( xport_ctx->status == GLINK_XPORT_LINK_UP &&
+        if_ptr->glink_priority < priority )
+    {
+      best_if_ptr = if_ptr;
+      priority    = if_ptr->glink_priority;
+    }
+
+    if_ptr    = smem_list_next(if_ptr);
+  } /* end while() */
+
+  return best_if_ptr;
+}
+
+/**
+ * Opens a logical GLink based on the specified config params
+ *
+ * @param[in]    cfg_ptr  Pointer to the configuration structure for the
+ *                        GLink. See glink.h
+ * @param[out]   handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Allocates channel resources and informs remote host about
+ *               channel open.
+ */
+glink_err_type glink_open
+(
+  glink_open_config_type *cfg_ptr,
+  glink_handle_type      *handle
+)
+{
+  glink_transport_if_type *if_ptr, *req_if_ptr;
+  glink_channel_ctx_type  *ch_ctx;
+  unsigned int            remote_host;
+
+  /* Param validation */
+  if(cfg_ptr == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  if(cfg_ptr->remote_ss == NULL             ||
+     cfg_ptr->name == NULL                  ||
+     cfg_ptr->notify_state == NULL)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
+        GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Evaluate the equivalent edge name->enum for future use */
+  remote_host = glinki_find_remote_host(cfg_ptr->remote_ss);
+
+  if(remote_host == GLINK_NUM_HOSTS ) {
+    /* Unknown transport name trying to register with GLink */
+    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, cfg_ptr->name, "",
+        cfg_ptr->remote_ss, GLINK_STATUS_INVALID_PARAM);
+
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Allocate and initialize channel info structure */
+  ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
+  if(ch_ctx == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, "",
+        "", GLINK_STATUS_OUT_OF_RESOURCES);
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  /* Fill in the channel info structure */
+  glink_os_string_copy(ch_ctx->name, cfg_ptr->name, sizeof(ch_ctx->name));
+  ch_ctx->priv = cfg_ptr->priv;
+  ch_ctx->notify_rx = cfg_ptr->notify_rx;
+  ch_ctx->notify_rxv = cfg_ptr->notify_rxv;
+  ch_ctx->notify_tx_done = cfg_ptr->notify_tx_done;
+  ch_ctx->notify_state = cfg_ptr->notify_state;
+  ch_ctx->notify_rx_intent_req = cfg_ptr->notify_rx_intent_req;
+  ch_ctx->notify_rx_intent = cfg_ptr->notify_rx_intent;
+  ch_ctx->notify_rx_sigs = cfg_ptr->notify_rx_sigs;
+  ch_ctx->ch_open_options = cfg_ptr->options;
+  ch_ctx->notify_rx_abort = cfg_ptr->notify_rx_abort;
+  ch_ctx->notify_tx_abort = cfg_ptr->notify_tx_abort;
+
+  if (ch_ctx->notify_rx_sigs == NULL) {
+    /* set default callback */
+    ch_ctx->notify_rx_sigs = glink_default_notify_rx_sigs;
+  }
+
+  glink_os_cs_acquire(glink_transport_q_cs);
+
+  /* Check to see if requested transport is available */
+  for (if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+       if_ptr != NULL;
+       if_ptr = smem_list_next(if_ptr))
+  {
+    glink_core_xport_ctx_type *xport_ctx = if_ptr->glink_core_priv;
+    glink_channel_ctx_type    *allocated_ch_ctx;
+
+    if (xport_ctx->status == GLINK_XPORT_LINK_UP &&
+        (cfg_ptr->transport == NULL ||
+         0 == strcmp(cfg_ptr->transport, xport_ctx->xport)) &&
+        xport_ctx->verify_open_cfg(ch_ctx))
+    {
+      glink_err_type status;
+
+      if(cfg_ptr->transport == NULL)
+      {
+        /* get best available transport */
+        if_ptr = req_if_ptr = glink_get_best_xport(remote_host);
+      }
+      else
+      {
+        if(cfg_ptr->options & GLINK_OPT_INITIAL_XPORT)
+        {
+          /* xport suggested by client is optional.
+           * get best available xport */
+          req_if_ptr = glink_get_best_xport(remote_host);
+        }
+        else
+        {
+          req_if_ptr = if_ptr;
+        }
+      }
+      /* Xport match found */
+      status = glinki_add_ch_to_xport( if_ptr,
+                                       req_if_ptr,
+                                       ch_ctx,
+                                       &allocated_ch_ctx,
+                                       TRUE,
+                                       TRUE,
+                                       if_ptr->glink_priority );
+
+      if (status == GLINK_STATUS_SUCCESS) {
+        /* Set the handle and return */
+        *handle = allocated_ch_ctx;
+      }
+      else {
+        *handle = NULL;
+      }
+
+      glink_os_cs_release(glink_transport_q_cs);
+
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, ch_ctx->name, xport_ctx->xport,
+        xport_ctx->remote_ss, status);
+      return status;
+    }
+  } /* end for() */
+
+  glink_os_cs_release(glink_transport_q_cs);
+
+  /* Code gets here if we are not able to find reqeusted transport */
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, cfg_ptr->transport,
+      cfg_ptr->remote_ss, GLINK_STATUS_NO_TRANSPORT);
+  glink_os_free(ch_ctx);
+  return GLINK_STATUS_NO_TRANSPORT;
+}
+
+/**
+ * Closes the GLink logical channel specified by the handle.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Closes local end of the channel and informs remote host
+ */
+glink_err_type glink_close
+(
+  glink_handle_type handle
+)
+{
+  glink_err_type status;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+  glink_ch_state_type ch_state;
+
+  if(handle == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  ch_state = handle->state;
+
+  /* Check to see if channel is in open/opening state */
+  if (ch_state != GLINK_CH_STATE_OPEN &&
+      ch_state != GLINK_CH_STATE_LOCAL_OPEN &&
+      ch_state != GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE &&
+      ch_state != GLINK_CH_STATE_REMOTE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, ch_state);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Transition to closing */
+  //handle->state = GLINK_CH_STATE_CLOSING;
+
+  /* Send CLOSE cmd to the transport interface */
+  status = handle->if_ptr->tx_cmd_ch_close(handle->if_ptr, handle->lcid);
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, status);
+  return status;
+
+}
+
+/**
+ * Transmit the provided buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *data      Pointer to the data buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   req_intent Whether to block and request for remote rx intent in
+ *                         case it is not available for this pkt tx
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_tx
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  const void        *data,
+  size_t            size,
+  uint32            options
+)
+{
+  return glink_txv(handle, pkt_priv, (void*)data, size,
+                   &glink_dummy_tx_vprovider, NULL, options);
+
+}
+
+/**
+ * Transmit the provided vector buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *iovec     Pointer to the vector buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   vprovider  Buffer provider for virtual space
+ *
+ * @param[in]   pprovider  Buffer provider for physical space
+ *
+ * @param[in]   req_intent Whether to block and request for remote rx intent in
+ *                         case it is not available for this pkt tx
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_txv
+(
+  glink_handle_type        handle,
+  const void               *pkt_priv,
+  void                     *iovec,
+  size_t                   size,
+  glink_buffer_provider_fn vprovider,
+  glink_buffer_provider_fn pprovider,
+  uint32                   options
+)
+{
+  glink_err_type         status;
+  glink_core_tx_pkt_type pctx;
+  boolean                req_intent = options & GLINK_TX_REQ_INTENT;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+
+  /* Input validation */
+  if(handle == NULL || iovec == NULL || size == 0 ||
+     (vprovider == NULL && pprovider == NULL)) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN )
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Protect the entire tx operation under a lock as a client may call
+     tx in different thread context */
+  glink_os_cs_acquire(&handle->tx_cs);
+
+  pctx.pkt_priv = pkt_priv;
+  pctx.size = size;
+  pctx.size_remaining = size;
+  pctx.vprovider = vprovider;
+  pctx.pprovider = pprovider;
+
+  if (vprovider == &glink_dummy_tx_vprovider)
+  {
+    pctx.data = (void*)iovec;
+    pctx.iovec = &pctx;
+  }
+  else
+  {
+    pctx.data = (void*)iovec;
+    pctx.iovec = iovec;
+  }
+
+  status = xport_ctx->use_rm_intent(handle, &pctx, req_intent);
+
+  /* Call transport API to transmit data */
+  while (pctx.size_remaining != 0 && status == GLINK_STATUS_SUCCESS)
+  {
+    status = handle->if_ptr->tx(handle->if_ptr, handle->lcid, &pctx);
+  }
+
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, status);
+
+  glink_os_cs_release(&handle->tx_cs);
+  return status;
+}
+
+/**
+ * Queue one or more Rx intent for the logical GPIC Link channel.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv Per packet private data
+ *
+ * @param[in]   size      Size of buffer
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL allocates rx buffers for receiving packets
+ */
+glink_err_type glink_queue_rx_intent
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  size_t            size
+)
+{
+  glink_err_type         status;
+  glink_rx_intent_type   *lc_intent;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+  size_t tmp;
+
+  /* Input validation */
+  if(handle == NULL || size == 0) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* short circuit for intentless mode */
+  if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Allocate an intent structure */
+  lc_intent = glink_os_calloc(sizeof(glink_rx_intent_type));
+  if(lc_intent == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+        xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  glink_os_cs_acquire(&handle->if_ptr->glink_core_priv->liid_cs);
+
+  /* Call transport API to allocate rx intent buffer */
+  status = handle->if_ptr->allocate_rx_intent(handle->if_ptr, size, lc_intent);
+  if(status != GLINK_STATUS_SUCCESS) {
+    glink_os_free(lc_intent);
+    glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+        xport_ctx->remote_ss, status);
+    return status;
+  }
+
+  if (handle->notify_rxv == NULL &&
+     (lc_intent->vprovider(lc_intent->iovec, 0, &tmp) == NULL || tmp < size)) {
+    /* Allocate bounce buffer for non-vectored Rx */
+    lc_intent->data = glink_os_malloc(size);
+
+    if(lc_intent->data == NULL) {
+      handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+      glink_os_free(lc_intent);
+      glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name,
+        xport_ctx->xport, xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+      return GLINK_STATUS_OUT_OF_RESOURCES;
+    }
+  }
+
+  /* push the intent on local queue. Do this before calling tx cmd
+     as transport may try to read data into the newly queued rx_buffer */
+  lc_intent->iid = handle->if_ptr->glink_core_priv->liid;
+  lc_intent->size = size;
+  lc_intent->pkt_priv = pkt_priv;
+  glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+  smem_list_append(&handle->pintents->local_intent_q, lc_intent);
+  glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+  /* Call transport API to queue rx intent */
+  /* Increment the local intent ID counter associated with this channel */
+  handle->if_ptr->glink_core_priv->liid++;
+
+  status = handle->if_ptr->tx_cmd_local_rx_intent(handle->if_ptr,
+              handle->lcid, size, lc_intent->iid);
+  if(status != GLINK_STATUS_SUCCESS) {
+    /* Failure */
+    glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+    smem_list_delete(&handle->pintents->local_intent_q, lc_intent);
+    glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+    handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+    glink_os_free(lc_intent->data);
+    glink_os_free(lc_intent);
+  }
+  glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, status);
+  return status;
+}
+
+/**
+ * Client uses this to signal to GLink layer that it is done with the received
+ * data buffer. This API should be called to free up the receive buffer, which,
+ * in zero-copy mode is actually remote-side's transmit buffer.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *ptr      Pointer to the received buffer
+ *
+ * @param[in]   reuse    Reuse intent
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL frees the Rx buffer
+ */
+glink_err_type glink_rx_done
+(
+  glink_handle_type handle,
+  const void        *ptr,
+  boolean           reuse
+)
+{
+  glink_rx_intent_type      *lc_intent;
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+
+  /* Input validation */
+  if(handle == NULL || ptr == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* short circuit for intentless mode */
+  if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
+    return GLINK_STATUS_SUCCESS;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  /* Free the intent */
+  lc_intent = smem_list_first(&handle->pintents->local_intent_client_q);
+  while(lc_intent != NULL) {
+    size_t tmp;
+
+    if(lc_intent->iovec == ptr || (handle->notify_rxv == NULL &&
+       (lc_intent->data == ptr ||
+       ptr == lc_intent->vprovider(lc_intent->iovec, 0, &tmp)))) {
+
+      uint32 iid;
+
+      /* Found intent, delete it */
+      glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+      smem_list_delete(&handle->pintents->local_intent_client_q, lc_intent);
+      glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+      iid = lc_intent->iid;
+
+      if (reuse)
+      {
+        lc_intent->used = 0;
+
+        glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+        smem_list_append(&handle->pintents->local_intent_q, lc_intent);
+        glink_os_cs_release(&handle->pintents->intent_q_cs);
+      }
+      else
+      {
+        /* Free the intent */
+        handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+        if(lc_intent->data) {
+          /* Free the bounce buffer if we had allocated one */
+          glink_os_free(lc_intent->data);
+        }
+        glink_os_free(lc_intent);
+      }
+
+      /* Note that the actual buffer, lc_intent->data, was allocated by the
+      * transport and should be freed by the xport. We should not touch it */
+      /* Let the xport know we are done with the buffer */
+      handle->if_ptr->tx_cmd_local_rx_done(handle->if_ptr, handle->lcid,
+                                           iid, reuse);
+
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+          xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+      return GLINK_STATUS_SUCCESS;
+    }
+    lc_intent = smem_list_next(lc_intent);
+  }
+
+  GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);
+  return GLINK_STATUS_INVALID_PARAM;
+}
+
+/**
+ * Set the 32 bit control signal field. Depending on the transport, it may
+ * take appropriate actions on the set bit-mask, or transmit the entire
+ * 32-bit value to the remote host.
+ *
+ * @param[in]   handle     GLink handle associated with the logical channel
+ *
+ * @param[in]   sig_value  32 bit signal word
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_set
+(
+  glink_handle_type handle,
+  uint32            sig_value
+)
+{
+  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+  glink_err_type status;
+
+  /* Input validation */
+  if(handle == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_SET, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  /* Make sure channel is in OPEN state */
+  if(handle->state != GLINK_CH_STATE_OPEN)
+  {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_SET, handle->name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  status = handle->if_ptr->tx_cmd_set_sigs(handle->if_ptr, handle->lcid,
+                                           sig_value);
+  if(GLINK_STATUS_SUCCESS == status) {
+    /* Update local copy of local control signal state */
+    handle->local_sigs = sig_value;
+  }
+
+  return status;
+}
+
+/**
+ * Get the local 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_local_get
+(
+  glink_handle_type handle,
+  uint32            *sig_value
+)
+{
+  /* Input validation */
+  if(handle == NULL || sig_value == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_L_GET, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  *sig_value = handle->local_sigs;
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Get the remote 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_remote_get
+(
+  glink_handle_type handle,
+  uint32            *sig_value
+)
+{
+  /* Input validation */
+  if(handle == NULL || sig_value == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_R_GET, NULL, "",
+        "", GLINK_STATUS_INVALID_PARAM);
+    return GLINK_STATUS_INVALID_PARAM;
+  }
+
+  *sig_value = handle->remote_sigs;
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*================= RESTRICTED API ==========================*/
+
+/**
+ * This API allows the RPM client to poll the transport for any new data
+ * that might have come in. It would *usually* be used when incoming interrupts
+ * are disabled.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_rx_poll
+(
+  glink_handle_type handle
+)
+{
+  ASSERT(handle);
+
+  if(handle->if_ptr->poll) {
+    return handle->if_ptr->poll(handle->if_ptr);
+  }
+  return GLINK_STATUS_FAILURE;
+}
+
+/**
+ * This API allows the RPM client to mask/unmask rx interrupts
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[in]   mask        Whether to mask or un-mask the incoming interrupt
+ *
+ * @param[in]   platform_struct Any platform specific into that transport may
+                                require
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_mask_rx_interrupt
+(
+  glink_handle_type handle,
+  boolean           mask,
+  void              *platform_struct
+)
+{
+  ASSERT(handle);
+
+  if(handle->if_ptr->mask_rx_irq) {
+    return handle->if_ptr->mask_rx_irq(handle->if_ptr, mask);
+  }
+  return GLINK_STATUS_FAILURE;
+}
+
+/**
+ * This API waits until link is down.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_wait_link_down
+(
+  glink_handle_type handle
+)
+{
+  ASSERT(handle && handle->if_ptr && handle->if_ptr->wait_link_down);
+
+  return handle->if_ptr->wait_link_down(handle->if_ptr) ?
+         GLINK_STATUS_SUCCESS : GLINK_STATUS_FAILURE;
+}
+
+/* ============ Internal Logging API ================ */
+void glink_mem_log
+(
+  const char *func,
+  uint32 line,
+  glink_log_event_type type,
+  const char *msg,
+  const char *xport,
+  const char *remote_ss,
+  uint32 param
+)
+{
+#ifdef DEBUG_GLINK
+  dprintf(INFO, "%s:%u, event:%d, msg:%s, xport:%s, remote_ss:%s, param:%u\n", func, line, type, msg, xport, remote_ss, param);
+#endif
+}
diff --git a/platform/msm_shared/glink/glink_core_if.c b/platform/msm_shared/glink/glink_core_if.c
new file mode 100644
index 0000000..3c66369
--- /dev/null
+++ b/platform/msm_shared/glink/glink_core_if.c
@@ -0,0 +1,983 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+
+#include "glink_os_utils.h"
+#include "glink.h"
+#include "glink_internal.h"
+#include "glink_core_if.h"
+#include "smem_list.h"
+#include "glink_channel_migration.h"
+
+
+#define FEATURE_CH_MIGRATION_FREE
+
+void glinki_scan_notif_list_and_notify
+(
+  glink_transport_if_type *if_ptr,
+  glink_link_state_type state
+);
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+                     LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_process_negotiation_complete
+===========================================================================*/
+/**
+
+  This is called when negotiation is complete.
+  It will set the version and call link up callback to notify
+
+
+  @param[in]    xport_ctx    transport context
+
+  @param[in]    if_ptr       Pointer to interface instance; must be unique
+                             for each edge
+
+  @param[in]    version      negotiated version
+
+  @param[in]    features     negotiated with local side
+
+  @return        None
+  @sideeffects   None.
+  @dependencies  None.
+*/
+/*=========================================================================*/
+static void glink_process_negotiation_complete
+(
+  glink_core_xport_ctx_type *xport_ctx,
+  glink_transport_if_type   *if_ptr,
+  uint32                    version,
+  uint32                    features
+)
+{
+  /* Version/Feautre can be negotiated both in ver_req and ver_ack
+   * Only go through process once in case they are negotiated
+   * in ver_req before receiving ver_ack */
+  if( xport_ctx->status == GLINK_XPORT_LINK_UP )
+  {
+    return;
+  }
+
+  /* setup core based on transport capabilities*/
+  xport_ctx->xport_capabilities = if_ptr->set_version( if_ptr,
+                                                       version,
+                                                       features );
+  glink_core_setup(if_ptr);
+
+  /* transport is ready to open channels */
+  if_ptr->glink_core_priv->status = GLINK_XPORT_LINK_UP;
+
+  /* Scan the notification list to check is we have to let any registered
+  * clients know that link came online */
+  glinki_scan_notif_list_and_notify(if_ptr, GLINK_LINK_STATE_UP);
+}
+
+static void glink_dummy_ch_migration_notification_cb
+(
+  glink_handle_type         handle,
+  const void               *priv,
+  glink_channel_event_type event
+)
+{
+}
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_link_up
+
+DESCRIPTION   Indicates that transport is now ready to start negotiation
+              using the v0 configuration
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_link_up
+(
+  glink_transport_if_type *if_ptr
+)
+{
+  const glink_core_version_type *version_array;
+  glink_core_xport_ctx_type *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  version_array = xport_ctx->version_array;
+
+  /* Update the transport state */
+  if_ptr->glink_core_priv->status = GLINK_XPORT_NEGOTIATING;
+
+  /* Start the negtiation */
+  if_ptr->tx_cmd_version(if_ptr, version_array->version,
+      version_array->features);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_LINK_UP, NULL, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version
+
+DESCRIPTION   Receive transport version for remote-initiated version
+              negotiation
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version  Remote Version
+
+            features Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+)
+{
+  const glink_core_version_type *ver;
+  uint32 negotiated_features;
+  glink_core_xport_ctx_type *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* The version to use must be a subset of supported version and features
+   * on this host and remote host */
+  ver = &xport_ctx->version_array[xport_ctx->version_indx];
+  ASSERT(ver);
+
+  if (version == ver->version)
+  {
+    /* Call the transport's negotiation function */
+    negotiated_features = ver->negotiate_features(if_ptr, ver, features);
+
+    /* If negotiated features match the provided features, version nogetiation
+     * is complete */
+    if(negotiated_features == features)
+    {
+      /* send version ack before allowing to open channels */
+      if_ptr->tx_cmd_version_ack(if_ptr, version, features);
+
+      glink_process_negotiation_complete( xport_ctx, if_ptr,
+                                          version, features );
+      return;
+    }
+    else
+    {
+      if_ptr->tx_cmd_version_ack(if_ptr, version, negotiated_features);
+    }
+  }
+  else
+  {
+    /* Next time use older version */
+    ver = &xport_ctx->version_array[xport_ctx->version_indx];
+
+    /* Versions don't match, return ACK with the feature set that we support */
+    if_ptr->tx_cmd_version_ack(if_ptr, ver->version, ver->features);
+  }
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version_ack
+
+DESCRIPTION   Receive ACK to previous glink_transport_if::tx_cmd_version
+              command
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version  Remote Version
+
+            features Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+)
+{
+  const glink_core_version_type* ver;
+  uint32 negotiated_features;
+  glink_core_xport_ctx_type *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Check to see if version returned by remote end is supported by
+   * this host. Remote side would have acked only when the version/features
+   * sent by this host did not match the remote */
+
+  ver = &xport_ctx->version_array[xport_ctx->version_indx];
+  ASSERT(ver);
+
+  if (ver->version == version)
+  {
+    /* Call the transport's negotiation function */
+    negotiated_features = ver->negotiate_features(if_ptr, ver, features);
+
+    if(negotiated_features != features)
+    {
+      /* Continue negotiating */
+      if_ptr->tx_cmd_version(if_ptr, version, negotiated_features);
+    }
+    else
+    {
+      glink_process_negotiation_complete( xport_ctx, if_ptr,
+                                          version, features );
+    }
+  }
+  else
+  {
+    while (ver->version > version)
+    {
+      /* Next time use older version */
+      ASSERT(xport_ctx->version_indx > 0);
+      xport_ctx->version_indx--;
+      ver = &xport_ctx->version_array[xport_ctx->version_indx];
+    }
+
+    /* Versions don't match, return ACK with the feature set that we support */
+    if_ptr->tx_cmd_version(if_ptr, ver->version, ver->features);
+  }
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_open
+
+DESCRIPTION   Receive remote channel open request; Calls
+              glink_transport_if:: tx_cmd_ch_remote_open_ack as a result
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid     Remote Channel ID
+
+            *name    String name for logical channel
+
+            prio     xport priority requested by remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_open
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  rcid,
+  const char              *name,
+  glink_xport_priority    priority
+)
+{
+  glink_channel_ctx_type *remote_ch_ctx;
+  glink_channel_ctx_type  *allocated_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+  glink_err_type status;
+  glink_xport_priority negotiated_prio;
+  boolean migration_state = TRUE;
+
+  ASSERT(if_ptr != NULL);
+  ASSERT(name != NULL);
+
+#ifndef FEATURE_CH_MIGRATION_FREE
+  glink_transport_if_type *present_if_ptr = NULL;
+  boolean channel_exist = FALSE;
+  glink_channel_ctx_type *present_ch_ctx = NULL;
+  /* search if channel with given name exists locally */
+  channel_exist = glinki_local_channel_exists(if_ptr, &present_if_ptr, name, &present_ch_ctx, TRUE);
+
+  /* start channel migration negotiation only if channel exists on local side
+   * for negotiation AND channel is willing to migrate */
+  if(channel_exist &&
+     (present_ch_ctx->ch_open_options & GLINK_OPT_INITIAL_XPORT))
+  {
+    /* channel exists on one of the xports for given remote ss */
+    current_prio =  present_ch_ctx->req_if_ptr->glink_priority;
+    negotiated_prio = glinki_negotiate_ch_migration(priority, current_prio);
+
+    /* if current channel is open in same xport as negotiated xport
+     * local side wont migrate. Set migration flag to FALSE */
+    if(negotiated_prio == present_if_ptr->glink_priority)
+    {
+      migration_state = FALSE;
+    }
+  }
+  else if(channel_exist)
+  {
+    /* channel exists but channel does not want to be moved to another xport.
+       channel is set in stone */
+    negotiated_prio = present_if_ptr->glink_priority;
+    migration_state = FALSE;
+  }
+  else
+  {
+    /* channel does not exist on local side as yet
+     * return negotiated prio as current xport prio on which
+     * remote open request is received */
+    negotiated_prio = if_ptr->glink_priority;
+    migration_state = FALSE;
+  }
+#else
+  negotiated_prio = if_ptr->glink_priority;
+    migration_state = FALSE;
+#endif
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Allocate and initialize channel info structure */
+  remote_ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
+  if(remote_ch_ctx == NULL) {
+    GLINK_LOG_EVENT(GLINK_EVENT_RM_CH_OPEN, name, xport_ctx->xport,
+        xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+    ASSERT(0);
+  }
+
+  /* Fill in the channel info structure */
+  glink_os_string_copy(remote_ch_ctx->name, name, sizeof(remote_ch_ctx->name));
+  remote_ch_ctx->rcid = rcid;
+
+  status = glinki_add_ch_to_xport(if_ptr, NULL, remote_ch_ctx,
+                                  &allocated_ch_ctx, FALSE,
+                                  migration_state, negotiated_prio);
+  ASSERT(status == GLINK_STATUS_SUCCESS);
+
+  GLINK_LOG_EVENT(GLINK_EVENT_RM_CH_OPEN, name, xport_ctx->xport,
+      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+#ifndef FEATURE_CH_MIGRATION_FREE
+
+  /* We are done with channel migration negotiation at this stage
+   * Tag all channels with given name on xports other than negotiated
+   * xport for deletion */
+  glinki_tag_ch_for_deletion(if_ptr, name, negotiated_prio);
+
+    if(migration_state == TRUE)
+    {
+      glink_channel_ctx_type *new_ch_ctx;
+
+    /* create a new channel context as current channel will be migrated */
+    new_ch_ctx = (glink_channel_ctx_type *)
+                   glink_os_calloc(sizeof(glink_channel_ctx_type));
+
+    /* Fill in the channel info structure */
+    new_ch_ctx->req_if_ptr =
+             glinki_get_xport_from_prio(negotiated_prio,
+                                          if_ptr->glink_core_priv->remote_ss);
+    glink_os_string_copy(new_ch_ctx->name, present_ch_ctx->name,
+                         sizeof(present_ch_ctx->name));
+    new_ch_ctx->priv = present_ch_ctx->priv;
+    new_ch_ctx->notify_rx = present_ch_ctx->notify_rx;
+    new_ch_ctx->notify_rxv = present_ch_ctx->notify_rxv;
+    new_ch_ctx->notify_tx_done = present_ch_ctx->notify_tx_done;
+    new_ch_ctx->notify_state = present_ch_ctx->notify_state;
+    new_ch_ctx->notify_rx_intent_req = present_ch_ctx->notify_rx_intent_req;
+    new_ch_ctx->notify_rx_intent = present_ch_ctx->notify_rx_intent;
+    new_ch_ctx->notify_rx_sigs = present_ch_ctx->notify_rx_sigs;
+    new_ch_ctx->ch_open_options = present_ch_ctx->ch_open_options;
+
+//      glink_os_cs_init(&new_ch_ctx->intent_q_cs);
+
+    /* close current channel */
+    present_ch_ctx->notify_state = glink_dummy_ch_migration_notification_cb;
+    if_ptr->tx_cmd_ch_close( if_ptr, present_ch_ctx->lcid );
+
+    /* add new channel context on negotiated xport */
+    glinki_add_ch_to_xport(new_ch_ctx->req_if_ptr,
+                           new_ch_ctx->req_if_ptr,
+                           new_ch_ctx,
+                           &allocated_ch_ctx,
+                           TRUE,
+                           TRUE,
+                           new_ch_ctx->req_if_ptr->glink_priority);
+  }
+#endif
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_open_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if:: tx_cmd_ch_open
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid     Local Channel ID
+
+            prio     Negotiated xport priority from remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_open_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  lcid,
+  glink_xport_priority    migrated_ch_prio
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Move to closed state. Implies we clean up the channel from the
+   * open list */
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->lcid == lcid) {
+#ifndef FEATURE_CH_MIGRATION_FREE
+      glink_transport_if_type *present_if_ptr = NULL;
+      glink_channel_ctx_type  *present_ch_ctx = NULL;
+      boolean channel_exist;
+      /* find the channel in all xport list */
+      channel_exist = glinki_local_channel_exists(if_ptr,
+                                                  &present_if_ptr,
+                                                  open_ch_ctx->name,
+                                                  &present_ch_ctx,
+                                                  FALSE);
+
+      if(if_ptr->glink_priority == migrated_ch_prio && !channel_exist)
+      {
+        /* only local side has opened the channel. Remote side has not come up yet
+         * which implies negotiation did not take place on remote side */
+        /* DO NOTHING */
+      }
+      else if(if_ptr->glink_priority == migrated_ch_prio)
+      {
+        /* remote channel exists. channel migration negotiation happened
+         * on remote side and negotitated xport is same as current xport */
+        if(present_ch_ctx->ref_count == 1)
+        {
+          /* remote channel is present on different xport than negotiated one.
+           * remote side will migrate its channel to negotiated xport */
+          /* DO NOTHING */
+        }
+        else if(present_ch_ctx->ref_count == 2)
+        {
+          /* remote channel is open on same xport as current xport.
+           * change channel state to GLINK_CH_STATE_OPEN and notify client */
+          open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+          open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+                                    GLINK_CONNECTED);
+        }
+        else
+        {
+          /* something went wrong in updating ref_count of channel */
+          ASSERT(0);
+        }
+      }
+      else
+      {
+
+        /* migrated xport priority <> current xport priority */
+        /* check if remote channel is opened on negotiated xport already */
+          if(migrated_ch_prio == present_if_ptr->glink_priority &&
+             (open_ch_ctx->ch_open_options & GLINK_OPT_INITIAL_XPORT))
+          {
+            /* remote channel is already on negotiated xport. remote channel
+             * will not migrate. Local side should migrate */
+
+            glink_channel_ctx_type *new_ch_ctx =
+              (glink_channel_ctx_type *)glink_os_calloc(
+                                       sizeof(glink_channel_ctx_type));
+
+            /* Fill in the channel info structure */
+            glink_os_string_copy(new_ch_ctx->name,
+                                 open_ch_ctx->name,
+                                 sizeof(open_ch_ctx->name));
+            new_ch_ctx->priv = open_ch_ctx->priv;
+            new_ch_ctx->notify_rx = open_ch_ctx->notify_rx;
+            new_ch_ctx->notify_rxv = open_ch_ctx->notify_rxv;
+            new_ch_ctx->notify_tx_done = open_ch_ctx->notify_tx_done;
+            new_ch_ctx->notify_state = open_ch_ctx->notify_state;
+            new_ch_ctx->notify_rx_intent_req =
+                                            open_ch_ctx->notify_rx_intent_req;
+            new_ch_ctx->notify_rx_intent = open_ch_ctx->notify_rx_intent;
+            new_ch_ctx->notify_rx_sigs = open_ch_ctx->notify_rx_sigs;
+            new_ch_ctx->ch_open_options = open_ch_ctx->ch_open_options;
+
+            present_ch_ctx->notify_state = glink_dummy_ch_migration_notification_cb;
+            if_ptr->tx_cmd_ch_close( if_ptr, present_ch_ctx->lcid );
+
+            /* migrate to negotiated xport */
+            glinki_add_ch_to_xport(present_if_ptr,
+                                   present_if_ptr,
+                                   new_ch_ctx,
+                                   NULL,
+                                   TRUE,
+                                   TRUE,
+                                   present_if_ptr->glink_priority);
+          }
+          else
+          {
+            /* Either our transport is "set in stone"  OR */
+            /* remote side will migrate to negotiated xport and will call
+             * remote open on this side which will cause channel migration
+             * negotiation and this side will ultimately migrate */
+            /* DO NOTHING */
+          }
+        }
+#else
+        if(open_ch_ctx->ref_count == 2)
+        {
+          /* remote channel is open on same xport as current xport.
+           * change channel state to GLINK_CH_STATE_OPEN and notify client */
+          open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+          open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+                                    GLINK_CONNECTED);
+        }
+#endif
+
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN_ACK, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, lcid);
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }
+  /* We are here in case we could not find the channel in the open list. */
+  ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_close_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if_type:: tx_cmd_ch_close
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid      Local Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_close_ack
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid     /* Local channel ID */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Move to closed state. Implies we clean up the channel from the
+   * open list */
+
+  /* Find channel in the open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->lcid == lcid) {
+      /* Found channel */
+      open_ch_ctx->ref_count--;
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE_ACK, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, lcid);
+
+      /* Transition state */
+      if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+        /* this side initiated close procedure */
+        open_ch_ctx->state = GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE;
+      } else if(open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN ||
+                open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE ||
+                open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) {
+        /* Other side never opened the port, or closed from its end */
+        /* Clear everything */
+        if(open_ch_ctx->ref_count == 0)
+        {
+          xport_ctx->channel_cleanup(open_ch_ctx);
+          /* re-use channel id if it can be done */
+          if(lcid == (xport_ctx->free_lcid-1)) {
+            /* If channel being closed is the last opened channel
+               re-use the lcid of this channel for any new channels */
+            xport_ctx->free_lcid--;
+          }
+          smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+
+          /* Notify the client */
+          open_ch_ctx->notify_state( open_ch_ctx, open_ch_ctx->priv,
+                                     GLINK_LOCAL_DISCONNECTED);
+          glink_os_free(open_ch_ctx);
+        }
+      } else {
+        /* Unsupported state */
+        ASSERT(0);
+      }
+
+      glink_os_cs_release(&xport_ctx->channel_q_cs);
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  /* We are here in case we could not find the channel in the open list. */
+  ASSERT(0);
+
+  glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_close
+
+DESCRIPTION   Remote channel close request; will result in sending
+              glink_transport_if_type:: tx_cmd_ch_remote_close_ack
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_close
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->rcid == rcid) {
+        GLINK_LOG_EVENT(GLINK_EVENT_CH_REMOTE_CLOSE, open_ch_ctx->name,
+            xport_ctx->xport, xport_ctx->remote_ss, rcid);
+      /* Found channel, transition it to appropriate state based
+       * on current state */
+      open_ch_ctx->ref_count--;
+
+      if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+         open_ch_ctx->state = GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE;
+
+        /* Inform the client */
+        open_ch_ctx->notify_state( open_ch_ctx, open_ch_ctx->priv,
+                                   GLINK_REMOTE_DISCONNECTED);
+
+        /* Send the remote close ACK back to the other side */
+        if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+
+        /* Free channel resources */
+        xport_ctx->channel_cleanup(open_ch_ctx);
+
+        GLINK_LOG_EVENT(GLINK_EVENT_CH_REMOTE_CLOSE, open_ch_ctx->name,
+            xport_ctx->xport, xport_ctx->remote_ss, rcid);
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        return;
+      } else if (open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN ||
+                 open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE) {
+        /* Local side never opened the channel OR it opened it but closed it */
+        /* Free channel resources */
+        xport_ctx->channel_cleanup(open_ch_ctx);
+
+        /* Send the remote close ACK back to the other side */
+        if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+
+        if(open_ch_ctx->ref_count == 0)
+        {
+          /* re-use channel id if it can be done */
+          if (open_ch_ctx->lcid == (xport_ctx->free_lcid - 1)) {
+            /* If channel being closed is the last opened channel
+            re-use the lcid of this channel for any new channels */
+            xport_ctx->free_lcid--;
+          }
+          smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+          glink_os_free(open_ch_ctx);
+        }
+
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+        return;
+      } else {
+        /* SHould not get this callback for a channel in any other state */
+
+        //OS_LOG_ERROR(3, "GLINK_RX_CMD_CH_REMOTE_CLOSE: received close cmd for invalid state"
+        //                "[channel ctx: 0x%x][current channel state: %d]",
+        //                open_ch_ctx, open_ch_ctx->state );
+        glink_os_cs_release(&xport_ctx->channel_q_cs);
+        if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+        return;
+      }
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  /* We are here in case we could not find the channel in the open list
+   * or OPEN state. */
+  ASSERT(0);
+
+  glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+/*===========================================================================
+FUNCTION      glink_ch_state_local_trans
+
+DESCRIPTION   Process local state transition
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_ch_state_local_trans
+(
+  glink_transport_if_type  *if_ptr,  /* Pointer to the interface instance */
+  uint32                   lcid,     /* Local channel ID */
+  glink_ch_state_type      new_state /* New local channel state */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->lcid == lcid) {
+      /* Found channel, transition it to appropriate state */
+      open_ch_ctx->state = new_state;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+    GLINK_LOG_EVENT(GLINK_EVENT_CH_STATE_TRANS, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, new_state);
+    return;
+  }/* end while */
+
+  /* We are here in case we could not find the channel in the open list
+   * or OPEN state. */
+  ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_put_pkt_ctx
+
+DESCRIPTION   Transport invokes this call to receive a packet fragment (must
+              have previously received an rx_cmd_rx_data packet)
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            *intent_ptr  Pointer to the intent fragment
+
+            complete     True if pkt is complete
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_put_pkt_ctx
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  glink_rx_intent_type    *intent_ptr, /* Fragment ptr */
+  boolean                 complete     /* True if pkt is complete */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  glink_core_xport_ctx_type  *xport_ctx;
+
+  ASSERT(if_ptr != NULL && intent_ptr != NULL);
+
+  xport_ctx = if_ptr->glink_core_priv;
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->rcid == rcid) {
+      /* Found channel */
+      GLINK_LOG_EVENT(GLINK_EVENT_CH_PUT_PKT_CTX, open_ch_ctx->name,
+          xport_ctx->xport, xport_ctx->remote_ss, intent_ptr->iid);
+
+      xport_ctx->channel_receive_pkt(open_ch_ctx, intent_ptr);
+
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }/* end while */
+
+  /* We end up here if we don't find the channel */
+  ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_remote_sigs
+
+DESCRIPTION   Transport invokes this call to inform GLink of remote side
+              changing its control signals
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            remote_sigs  Remote signal state.
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_remote_sigs
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  rcid,       /* Remote channel ID */
+  uint32                  remote_sigs /* Remote control signals */
+)
+{
+  glink_channel_ctx_type *open_ch_ctx;
+  uint32 prev_sigs;
+
+  ASSERT(if_ptr != NULL);
+
+  /* Find channel in the open_list */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+  while(open_ch_ctx != NULL)
+  {
+    if(open_ch_ctx->rcid == rcid) {
+      /* Found channel, let client know of new remote signal state */
+      prev_sigs = open_ch_ctx->remote_sigs;
+      open_ch_ctx->remote_sigs = remote_sigs;
+      open_ch_ctx->notify_rx_sigs(open_ch_ctx, open_ch_ctx->priv,
+                                  prev_sigs, remote_sigs);
+      return;
+    }
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }
+
+  /* We end up here if we don't find the channel */
+  ASSERT(0);
+}
+
+
+/*===========================================================================
+FUNCTION      glink_tx_resume
+
+DESCRIPTION   If transport was full and could not continue a transmit
+              operation, then it will call this function to notify the core
+              that it is ready to resume transmission.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_tx_resume
+(
+  glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+)
+{
+  /* Not sure what to do here */
+}
+
+
+/*===========================================================================
+FUNCTION      glink_set_core_version
+
+DESCRIPTION   Sets the core version used by the transport; called after
+              completing negotiation.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+             version   Negotiated transport version
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_set_core_version
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version  /* Version */
+)
+{
+}
diff --git a/platform/msm_shared/glink/glink_core_intentless_xport.c b/platform/msm_shared/glink/glink_core_intentless_xport.c
new file mode 100644
index 0000000..289ef18
--- /dev/null
+++ b/platform/msm_shared/glink/glink_core_intentless_xport.c
@@ -0,0 +1,131 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+
+#include "glink.h"
+#include "glink_internal.h"
+
+/*===========================================================================
+LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+  FUNCTION      glink_core_stub_intentless
+===========================================================================*/
+/**
+
+  Stub for intentless transport functionality.
+
+  @return     GLINK_STATUS_SUCCESS.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+
+static glink_err_type glink_core_stub_intentless(void)
+{
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+  FUNCTION      glink_verify_open_cfg_intentless
+===========================================================================*/
+/**
+
+  Verifies open config for an intentless transport
+
+  @param[in]  open_ch_ctx   Channel context.
+
+  @return     TRUE if config is good.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+static boolean glink_verify_open_cfg_intentless
+(
+glink_channel_ctx_type   *ch_ctx
+)
+{
+  return (ch_ctx->notify_rxv != NULL);
+}
+
+/*===========================================================================
+  FUNCTION      glink_channel_receive_pkt
+===========================================================================*/
+/**
+
+  Precesses Rx packet for the channel
+
+  @param[in]  open_ch_ctx   Channel context.
+  @param[in]  intent_ptr    Packet descriptor
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+static void glink_channel_receive_pkt_intentless
+(
+  glink_channel_ctx_type *open_ch_ctx,
+  glink_rx_intent_type *intent_ptr
+)
+{
+  open_ch_ctx->notify_rxv(open_ch_ctx, open_ch_ctx->priv,
+    NULL, intent_ptr->iovec, intent_ptr->pkt_sz, 0,
+    intent_ptr->vprovider, intent_ptr->pprovider);
+}
+
+/*===========================================================================
+EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+  FUNCTION      glink_core_setup_intentless_xport
+===========================================================================*/
+/**
+
+  Initializes internal core functions for the intentless transport.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup_intentless_xport(glink_transport_if_type *if_ptr)
+{
+  if_ptr->glink_core_priv->verify_open_cfg = glink_verify_open_cfg_intentless;
+  if_ptr->glink_core_priv->channel_init = (channel_init_fn)glink_core_stub_intentless;
+  if_ptr->glink_core_priv->channel_cleanup = (channel_cleanup_fn)glink_core_stub_intentless;
+  if_ptr->glink_core_priv->use_rm_intent = (use_rm_intent_fn)glink_core_stub_intentless;
+  if_ptr->glink_core_priv->channel_receive_pkt = glink_channel_receive_pkt_intentless;
+}
diff --git a/platform/msm_shared/glink/glink_os_utils_dal.c b/platform/msm_shared/glink/glink_os_utils_dal.c
new file mode 100644
index 0000000..7ad6fb7
--- /dev/null
+++ b/platform/msm_shared/glink/glink_os_utils_dal.c
@@ -0,0 +1,358 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+
+#include "glink_os_utils.h"
+#include <arch/defines.h>
+#include <malloc.h>
+#include <kernel/thread.h>
+#include <string.h>
+#include <kernel/event.h>
+#include <platform/irqs.h>
+#include <platform/interrupts.h>
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+
+#define OS_LOG_BUFFER_SIZE  ( 16384 )
+
+/*===========================================================================
+                           TYPE DEFINITIONS
+===========================================================================*/
+typedef void (*glink_os_thread_fn_type)(void* param);
+
+typedef struct _glink_os_thread_info_type {
+  glink_os_thread_fn_type thread_fn;
+  void                    *param;
+}glink_os_thread_info_type;
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_init
+===========================================================================*/
+/**
+  Initializes a Critical Section
+
+  @param[in]  cs   pointer to critical section object allocated by caller.
+
+  @return
+  TRUE if critical section was initialized, FALSE otherwise
+*/
+/*=========================================================================*/
+boolean glink_os_cs_init( os_cs_type *cs )
+{
+  boolean return_value = TRUE;
+
+  /* Create the new critical section */
+
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_cs_deinit
+===========================================================================*/
+/**
+  This function de-initializes a critical section.
+
+  @param[in]  cs         Pointer to the critical section to be de-initialized.
+
+  @return
+  TRUE if critical section was initialized, FALSE otherwise
+
+*/
+/*=========================================================================*/
+boolean glink_os_cs_deinit( os_cs_type *cs )
+{
+  /* Deinitialize the critical section */
+
+  return TRUE;
+}
+
+/*===========================================================================
+FUNCTION      glink_os_cs_acquire
+===========================================================================*/
+/**
+  Lock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_acquire( os_cs_type *cs )
+{
+  enter_critical_section();
+}
+
+/*===========================================================================
+FUNCTION      glink_os_cs_release
+===========================================================================*/
+/**
+  Unlock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_release( os_cs_type *cs )
+{
+  exit_critical_section();
+}
+
+/*===========================================================================
+FUNCTION      glink_os_cs_destroy
+===========================================================================*/
+/**
+  Destroys a Critical Section
+
+  @return     none.
+*/
+/*=========================================================================*/
+void glink_os_cs_destroy( os_cs_type *cs )
+{
+  /* Initialize the critical section */
+  return;
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_malloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap.  The region should be
+  freed using \c glink_os_free when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+
+void *glink_os_malloc( size_t size )
+{
+  void *pMem;
+
+  pMem = malloc(size);
+  if (pMem == NULL)
+      return NULL;
+  return pMem;
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_calloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap and initialize with
+  the zeroes.  The region should be freed using \c glink_os_free
+  when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_calloc( size_t size )
+{
+  void *pMem;
+  pMem = malloc(size);
+  if( pMem == NULL )
+  {
+    return NULL;
+  }
+  else
+  {
+    memset( pMem, 0, size );
+    return pMem;
+  }
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_free
+===========================================================================*/
+/**
+  Free a region of memory that was allocated by \c glink_os_malloc.
+
+  @param[in] pMem    The reference to the region of memory to be freed.
+
+  @return    NA
+*/
+/*=========================================================================*/
+void glink_os_free( void *pMem )
+{
+  free( pMem );
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_string_copy
+===========================================================================*/
+/**
+  Copies the source string into the destination buffer until
+  size is reached, or until a '\0' is encountered.  If valid,
+  the destination string will always be NULL deliminated.
+
+  @param[in] dst    The destination string, contents will be updated.
+  @param[in] src    The source string
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+char *glink_os_string_copy( char *dst, const char *src, uint32 size )
+{
+  ( void )strlcpy( dst, src, size );
+
+  return dst;
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_string_compare
+===========================================================================*/
+/**
+  Compares two strings delimited by size or NULL character.
+
+  @param[in] s1     String 1
+  @param[in] s2     String 2
+  @param[in] size   The maximum number of characters to compare
+
+  @return
+  0 if strings are identical (up to size characters), non-zero otherwise
+*/
+/*==========================================================================*/
+long glink_os_string_compare( const char *s1, const char *s2, uint32 size )
+{
+  return strncmp( s1, s2, size );
+}
+
+/*===========================================================================
+  FUNCTION  glink_os_copy_mem
+===========================================================================*/
+/**
+  Copies the source buffer into the destination buffer.
+
+  @param[in] dst    The destination, contents will be updated.
+  @param[in] src    The source
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+void glink_os_copy_mem( void *dst, const void *src, uint32 size )
+{
+  memcpy( dst, src, size );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_register_isr
+===========================================================================*/
+/**
+  Registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to register for
+  @param[in]  isr       Callback to be invoked when interrupt fires
+  @param[in]  cb_data   Data to be provided to the callback
+
+  @return     TRUE if registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_register_isr( uint32 irq_in, os_isr_cb_fn isr, void* cb_data )
+{
+  boolean return_value = TRUE;
+
+  /* Register the interrupt */
+  dprintf(SPEW, "Register interrupt: %u\n", irq_in);
+  register_int_handler(irq_in, (int_handler)(isr), cb_data);
+
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_deregister_isr
+===========================================================================*/
+/**
+  De-registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to deregister for
+
+  @return     TRUE if de-registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_deregister_isr( uint32 irq_in )
+{
+  boolean return_value = TRUE;
+  mask_interrupt(irq_in);
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_enable_interrupt
+===========================================================================*/
+/**
+  Enables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to enable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_enable_interrupt( uint32 irq_in )
+{
+  boolean return_value = TRUE;
+  unmask_interrupt(irq_in);
+  return ( return_value );
+}
+
+/*===========================================================================
+  FUNCTION      glink_os_disable_interrupt
+===========================================================================*/
+/**
+  Disables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to disable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_disable_interrupt( uint32 irq_in )
+{
+  boolean return_value = TRUE;
+  dprintf(INFO, "Disable IPC Interrupt\n");
+  mask_interrupt(irq_in);
+  return ( return_value );
+}
diff --git a/platform/msm_shared/glink/glink_rpmcore_setup.c b/platform/msm_shared/glink/glink_rpmcore_setup.c
new file mode 100644
index 0000000..a206afa
--- /dev/null
+++ b/platform/msm_shared/glink/glink_rpmcore_setup.c
@@ -0,0 +1,65 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+
+#include "glink.h"
+#include "glink_internal.h"
+
+
+/*===========================================================================
+EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glink_core_setup
+===========================================================================*/
+/**
+
+  Initializes internal core functions based on the transport capabilities.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup(glink_transport_if_type *if_ptr)
+{
+  if (if_ptr->glink_core_priv->xport_capabilities & GLINK_CAPABILITY_INTENTLESS)
+  {
+    glink_core_setup_intentless_xport(if_ptr);
+  }
+  else
+  {
+    ASSERT(0);
+  }
+}
diff --git a/platform/msm_shared/glink/glink_vector.c b/platform/msm_shared/glink/glink_vector.c
new file mode 100644
index 0000000..31f0883
--- /dev/null
+++ b/platform/msm_shared/glink/glink_vector.c
@@ -0,0 +1,196 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+#include "glink.h"
+#include "glink_core_if.h"
+#include "glink_transport_if.h"
+#include "glink_vector.h"
+#include "glink_os_utils.h"
+
+/*===========================================================================
+                       LOCAL DATA DECLARATIONS
+===========================================================================*/
+
+
+/*===========================================================================
+                       PRIVATE FUNCTIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glink_dummy_tx_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a non-vectored buffer.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_dummy_tx_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  glink_core_tx_pkt_type* pkt = (glink_core_tx_pkt_type*)iovec;
+
+  if (pkt == NULL || size == NULL || pkt->size <= offset)
+  {
+    return NULL;
+  }
+
+  *size = pkt->size - offset;
+
+  return (char*)(pkt->data) + offset;
+}
+
+/*===========================================================================
+FUNCTION      glink_iovec_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  glink_iovector_type* iovec_l = (glink_iovector_type*)iovec;
+
+  if (iovec_l == NULL || size == NULL)
+  {
+    return NULL;
+  }
+
+  if (!iovec_l->vlist)
+  {
+    // create vlist and map virtual from physical addresses
+    ASSERT(0);
+  }
+
+  if (!iovec_l->vlast || iovec_l->vlast->start_offset > offset)
+  {
+       iovec_l->vlast = iovec_l->vlist;
+  }
+
+  while (iovec_l->vlast &&
+         iovec_l->vlast->start_offset + iovec_l->vlast->size <= offset)
+  {
+    iovec_l->vlast = iovec_l->vlast->next;
+  }
+
+  if (iovec_l->vlast == NULL)
+  {
+    return NULL;
+  }
+
+  offset -= iovec_l->vlast->start_offset;
+  *size = iovec_l->vlast->size - offset;
+
+  return (char*)(iovec_l->vlast->data) + offset;
+}
+
+/*===========================================================================
+FUNCTION      glink_iovec_pprovider
+===========================================================================*/
+/**
+
+  Buffer provider for physical space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     physical address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_pprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  glink_iovector_type* iovec_l = (glink_iovector_type*)iovec;
+
+  if (iovec_l == NULL || size == NULL)
+  {
+    return NULL;
+  }
+
+  if (!iovec_l->plist)
+  {
+    // create plist and get physical addresses from virtual
+    ASSERT(0); // not implemented
+  }
+
+  if (!iovec_l->plast || iovec_l->plast->start_offset > offset)
+  {
+       iovec_l->plast = iovec_l->plist;
+  }
+
+  while (iovec_l->plast &&
+         iovec_l->plast->start_offset + iovec_l->plast->size <= offset)
+  {
+    iovec_l->plast = iovec_l->plast->next;
+  }
+
+  if (iovec_l->plast == NULL)
+  {
+    return NULL;
+  }
+
+  offset -= iovec_l->plast->start_offset;
+  *size = iovec_l->plast->size - offset;
+
+  return (char*)(iovec_l->plast->data) + offset;
+}
diff --git a/platform/msm_shared/glink/xport_rpm.c b/platform/msm_shared/glink/xport_rpm.c
new file mode 100644
index 0000000..05329f9
--- /dev/null
+++ b/platform/msm_shared/glink/xport_rpm.c
@@ -0,0 +1,1150 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+
+#include "glink.h"
+#include "glink_core_if.h"
+#include "glink_transport_if.h"
+#include "glink_os_utils.h"
+#include "glink_internal.h"
+#include "glink_vector.h"
+#include "xport_rpm_config.h"
+#include "xport_rpm.h"
+#include <reg.h>
+#include <bits.h>
+#include <platform/iomap.h>
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+#define XPORT_RPM_NAME "RPM"
+
+#define XPORT_RPM_LOG(msg, remote_host, param) \
+          GLINK_LOG_EVENT(GLINK_EVENT_XPORT_INTERNAL, msg, XPORT_RPM_NAME, \
+            remote_host, (uint32)param)
+
+#define MSGRAM_READ32(ctx, ind) (*(volatile uint32*)&(ctx)->rx_fifo[ind])
+#define CHECK_INDEX_WRAP_AROUND(ind, size) \
+          {if ((ind) >= (size)) ind = 0;}
+
+#define ROUNDUP64(d) (((d) + 7) & (~7))
+#define ROUNDUP32(d) (((d) + 3) & (~3))
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+extern const uint32 xport_rpm_config_num;
+extern const char* xport_rpm_msg_ram;
+extern const void* xport_rpm_msg_ram_toc;
+
+xport_rpm_config_type* xport_rpm_get_config(uint32 ind);
+
+/* RPM channel descriptor */
+typedef struct _xport_rpm_ind_type
+{
+  uint32 read_ind;
+  uint32 write_ind;
+} xport_rpm_ind_type;
+
+/* RPM transport context */
+typedef struct _xport_rpm_ctx_type
+{
+  /* context structure should start from trasport interface */
+  glink_transport_if_type xport_if;
+  const xport_rpm_config_type *pcfg;
+  volatile xport_rpm_ind_type* tx_desc;
+  volatile xport_rpm_ind_type* rx_desc;
+  char* tx_fifo;
+  char* rx_fifo;
+  uint32 tx_fifo_size;
+  uint32 rx_fifo_size;
+  os_cs_type *tx_link_lock;
+  os_cs_type *rx_link_lock;
+  uint32 pkt_start_ind;
+  uint32 pkt_size;
+  boolean reset;
+  boolean irq_mask;
+} xport_rpm_ctx_type;
+
+xport_rpm_ctx_type *xport_rpm_ctx = NULL;
+glink_core_version_type xport_rpm_version;
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      xport_rpm_plain_pkt_provider
+===========================================================================*/
+/**
+
+  Packet provider for virtual space that operates on MSG RAM FIFO.
+
+  @param[in]  iovec   Pointer to the vector.
+  @param[in]  offset  Offset within the vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+static void* xport_rpm_pkt_provider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+)
+{
+  xport_rpm_ctx_type* ctx_ptr = (xport_rpm_ctx_type*)iovec;
+  uint32 last;
+
+  if (ctx_ptr == NULL || size == NULL || ctx_ptr->pkt_size <= offset)
+  {
+    return NULL;
+  }
+
+  last = ctx_ptr->rx_fifo_size - ctx_ptr->pkt_start_ind;
+
+  if (offset >= last)
+  {
+    *size = ctx_ptr->pkt_size - offset;
+
+    return &ctx_ptr->rx_fifo[offset - last];
+  }
+
+  *size = ctx_ptr->pkt_size <= last ?
+          ctx_ptr->pkt_size - offset :
+          last - offset;
+
+  return &ctx_ptr->rx_fifo[offset + ctx_ptr->pkt_start_ind];
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_send_event
+===========================================================================*/
+/**
+
+  Updates shared write index and sends interrupt.
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+
+  @return     None.
+
+  @sideeffects  None.
+
+  @dependencies It should be invoked within tx_link_lock protection.
+*/
+/*=========================================================================*/
+static void xport_rpm_send_event
+(
+  xport_rpm_ctx_type *ctx_ptr
+)
+{
+  /* read out the write index to initiate a bus transaction from MSG RAM */
+  volatile uint32 write_ind = ctx_ptr->tx_desc->write_ind;
+
+  XPORT_RPM_LOG("Send event write ind", ctx_ptr->pcfg->remote_ss, write_ind);
+
+  // notify rpm
+  dprintf(SPEW, "%s:%d: Notify RPM with IPC interrupt\n", __func__, __LINE__);
+  /* Set BIT 0 to notify RPM via IPC interrupt*/
+  writel(BIT(0), APCS_HLOS_IPC_INTERRUPT_0);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_write_msgram
+===========================================================================*/
+/**
+
+  Copies data from local buffer into Tx FIFO located at MSG RAM
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+  @param[in]  write_ind Index to start wrting from.
+  @param[in]  buffer    Buffer to copy from.
+  @param[in]  size      Size of the data in the buffer.
+
+  @return     New write index.
+
+  @sideeffects  None.
+
+  @dependencies It should be invoked within tx_link_lock protection.
+*/
+/*=========================================================================*/
+static uint32 xport_rpm_write_msgram
+(
+  xport_rpm_ctx_type *ctx_ptr,
+  uint32 write_ind,
+  uint32 *buffer,
+  uint32 size
+)
+{
+  uint32 remaining = ctx_ptr->tx_fifo_size - write_ind;
+  uint32 *buffer_end;
+  volatile uint32* write_ptr = (volatile uint32*)&ctx_ptr->tx_fifo[write_ind];
+
+  if (remaining <= size)
+  {
+    buffer_end = (uint32*)((char*)buffer + remaining);
+
+    /* write in 32bit increments due to MSG RAM access requirement */
+    while (buffer < buffer_end)
+    {
+      *write_ptr++ = *buffer++;
+    }
+
+    size -= remaining;
+    write_ptr = (volatile uint32*)&ctx_ptr->tx_fifo[0];
+  }
+
+  buffer_end = (uint32*)((char*)buffer + size);
+
+  /* write in 32bit increments due to MSG RAM access requirement */
+  while (buffer < buffer_end)
+  {
+    *write_ptr++ = *buffer++;
+  }
+
+  return (char*)write_ptr - &ctx_ptr->tx_fifo[0];
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_send_cmd
+===========================================================================*/
+/**
+
+  Helper to send a single command.
+
+  @param[in]  ctx_ptr           Pointer to transport context.
+  @param[in]  cmd               buffer containing the command
+  @param[in]  cmd_size          Size of command buffer.
+  @param[in]  data              buffer containing the data
+  @param[in]  data_size         Size of data buffer.
+
+  @return     None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+static glink_err_type xport_rpm_send_cmd
+(
+  xport_rpm_ctx_type  *ctx_ptr,
+  uint32              *cmd,
+  uint32               cmd_size,
+  uint32              *data,
+  uint32               data_size
+)
+{
+  uint32 total_size = cmd_size + data_size;
+  uint32 reserve_size = ROUNDUP64(total_size);
+  uint32 write_ind, read_ind, avail_size;
+
+  glink_os_cs_acquire(ctx_ptr->tx_link_lock);
+
+  write_ind = ctx_ptr->tx_desc->write_ind;
+  read_ind = ctx_ptr->tx_desc->read_ind;
+  avail_size = write_ind < read_ind ? read_ind - write_ind :
+               ctx_ptr->tx_fifo_size - write_ind + read_ind;
+
+  if (reserve_size + sizeof(uint64_t) > avail_size)
+  {
+    glink_os_cs_release(ctx_ptr->tx_link_lock);
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+
+  XPORT_RPM_LOG("send cmd", ctx_ptr->pcfg->remote_ss, cmd[0]);
+
+  write_ind
+    = xport_rpm_write_msgram( ctx_ptr, write_ind,
+                              cmd, ROUNDUP32( cmd_size ) );
+
+  if (data != NULL)
+  {
+    write_ind
+      = xport_rpm_write_msgram( ctx_ptr, write_ind,
+                                data, ROUNDUP32( data_size ) );
+  }
+
+  /* add alignment bytes to Tx FIFO */
+  write_ind += (reserve_size - total_size) & (~3);
+
+  if (write_ind >= ctx_ptr->tx_fifo_size)
+  {
+    write_ind -= ctx_ptr->tx_fifo_size;
+  }
+
+  ctx_ptr->tx_desc->write_ind = write_ind;
+
+  xport_rpm_send_event(ctx_ptr);
+
+  glink_os_cs_release(ctx_ptr->tx_link_lock);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_version
+===========================================================================*/
+/**
+
+  Transmit a version command for local negotiation -
+  expected response is to be delivered via glink_rx_cmd_version_ack().
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  version   Version to be sent.
+  @param[in]  feature   Features to be sent.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32 version,
+  uint32 features
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_VERSION_REQ);
+  cmd[0] |= XPORT_RPM_SET_VERSION(version);
+  cmd[1] = features;
+
+  if(xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    dprintf(CRITICAL, "%s:%d: Send Version Failed\n", __func__, __LINE__);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_version_ack
+===========================================================================*/
+/**
+
+  Transmit a version ack for remote negotiation.
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  version   Version to be sent.
+  @param[in]  feature   Features to be sent.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_version_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32 version,
+  uint32 features
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_VERSION_ACK);
+  cmd[0] |= XPORT_RPM_SET_VERSION(version);
+  cmd[1] = features;
+
+  if (xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    dprintf(CRITICAL, "%s:%d: Send Version ACK Failed", __func__, __LINE__);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_set_version
+===========================================================================*/
+/**
+
+  Signals that negotiation is complete and the transport can now
+  do version-specific initialization.
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  version   Version to be used.
+  @param[in]  feature   Features to be used.
+
+  @return     Capabilities.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+uint32 xport_rpm_set_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32 version,
+  uint32 features
+)
+{
+  return GLINK_CAPABILITY_SIG_SUPPORT | GLINK_CAPABILITY_INTENTLESS;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_open
+===========================================================================*/
+/**
+
+  Sends the open command - expected response is to be delivered
+  via glink_rx_cmd_ch_open_ack().
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  lcid     Local channel ID.
+  @param[in]  name     Channel name.
+  @param[in]  prio     Requested xport priority by channel.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_ch_open
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid,
+  const char *name,
+  glink_xport_priority prio
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_OPEN_CHANNEL);
+  cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+  cmd[1] =  strlen(name) + 1;
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), (void*)name, cmd[1]);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_close
+===========================================================================*/
+/**
+
+  Sends the close command - expected response is to be delivered
+  via glink_rx_cmd_ch_close_ack().
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  lcid     Local channel ID.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_ch_close
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd;
+
+  cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_CLOSE_CHANNEL);
+  cmd |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_remote_open_ack
+===========================================================================*/
+/**
+
+  Sends the remote open ACK command.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  rcid     Remote channel ID.
+  @param[in]  prio     send negotiated xport priority to remote side.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_ch_remote_open_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32 rcid,
+  glink_xport_priority prio
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd;
+
+  cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_OPEN_CHANNEL_ACK);
+  cmd |= XPORT_RPM_SET_CHANNEL_ID(rcid);
+
+  if (xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    //ERR_FATAL("send Open Ack failed", 0, 0, 0);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_ch_remote_close_ack
+===========================================================================*/
+/**
+
+  Sends the remote close ACK command.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  rcid     Remote channel ID.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_ch_remote_close_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32 rcid
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd;
+
+  cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_CLOSE_CHANNEL_ACK);
+  cmd |= XPORT_RPM_SET_CHANNEL_ID(rcid);
+
+  if (xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+  {
+    dprintf(CRITICAL, "%s:%d: Send Clock ACK failed\n", __func__, __LINE__);
+    ASSERT(0);
+  }
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx
+===========================================================================*/
+/**
+
+  Send a data packet or a fragment of it.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  lcid     Local channel ID.
+  @param[in]  pctx     Packet TX context.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid,
+  glink_core_tx_pkt_type *pctx
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[4];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_TX_DATA);
+  cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+  cmd[1] = 0;
+  cmd[2] = pctx->size;
+  cmd[3] = 0;
+
+  pctx->size_remaining = 0;
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), (void*)pctx->data, pctx->size);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_tx_cmd_set_sigs
+===========================================================================*/
+/**
+
+  Sends the local channel signals as per the specified 32-bit mask.
+
+  @param[in]  if_ptr    Pointer to transport interface instance.
+  @param[in]  lcid      Local channel ID.
+  @param[in]  sigs      Signal mask.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_set_sigs
+(
+  glink_transport_if_type *if_ptr,
+  uint32 lcid,
+  uint32 sigs
+)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+  uint32 cmd[2];
+
+  cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_TX_SIGNALS);
+  cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+  cmd[1] = sigs;
+
+  return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0);
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_negotiate_features
+===========================================================================*/
+/**
+
+  Callback to verify feature set.
+
+  @param[in]  if_ptr        Pointer to transport interface.
+  @param[in]  version_ptr   Pointer to version descriptor.
+  @param[in]  features      Proposed feature set.
+
+  @return     0.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+uint32 xport_rpm_negotiate_features(
+  glink_transport_if_type *if_ptr,
+  const glink_core_version_type *version_ptr,
+  uint32 features)
+{
+  return 0;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_poll
+===========================================================================*/
+/**
+
+  Poll of RPM transport.
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_poll( xport_rpm_ctx_type *ctx_ptr )
+{
+  uint32 write_ind, read_ind;
+  boolean stop_processing = FALSE;
+
+  if (ctx_ptr->reset == TRUE)
+  {
+    /* reset flag has been set after SSR, notify link up */
+    ctx_ptr->reset = FALSE;
+    ctx_ptr->xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)ctx_ptr);
+  }
+
+  glink_os_cs_acquire(ctx_ptr->rx_link_lock);
+
+  /* Process pending commands and data */
+  write_ind = ctx_ptr->rx_desc->write_ind;
+  read_ind = ctx_ptr->rx_desc->read_ind;
+
+  XPORT_RPM_LOG("RPM ISR write ind", ctx_ptr->pcfg->remote_ss, write_ind);
+  XPORT_RPM_LOG("RPM ISR read ind", ctx_ptr->pcfg->remote_ss, read_ind);
+
+  /* Ensure the index is 64-bit aligned */
+  if ((write_ind & 0x7) != 0)
+  {
+    dprintf(CRITICAL,"%s:%d: Write Index is not aligned: %u\n",__func__, __LINE__, write_ind);
+    ASSERT(0);
+  }
+
+  while (write_ind != read_ind && !stop_processing)
+  {
+    uint32 cmd = MSGRAM_READ32(ctx_ptr, read_ind);
+    uint32 cid = XPORT_RPM_GET_CHANNEL_ID(cmd); // most commands have channel ID
+    uint32 cmd_arg;
+
+    /* it can't wrap aroud here so just inceremt the index */
+    read_ind += sizeof(cmd);
+
+    XPORT_RPM_LOG("Cmd Rx", ctx_ptr->pcfg->remote_ss, cmd);
+
+    switch (XPORT_RPM_GET_CMD_ID(cmd))
+    {
+      case XPORT_RPM_CMD_VERSION_REQ:
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* no need to incerment read_ind here since it will be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version(
+          (glink_transport_if_type *)ctx_ptr,
+          XPORT_RPM_GET_VERSION(cmd), cmd_arg);
+        break;
+
+      case XPORT_RPM_CMD_VERSION_ACK:
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* no need to increment read_ind here since it will be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version_ack(
+          (glink_transport_if_type *)ctx_ptr,
+          XPORT_RPM_GET_VERSION(cmd), cmd_arg);
+        break;
+
+      case XPORT_RPM_CMD_OPEN_CHANNEL:
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+        cmd_arg = ROUNDUP64(cmd_arg);
+
+        read_ind += sizeof(cmd_arg);
+
+        /* channel name should fit into the FIFO */
+        if (cmd_arg == 0 || cmd_arg >= ctx_ptr->rx_fifo_size)
+        {
+          dprintf(CRITICAL, "%s:%d: Invalid name length: %u", __func__, __LINE__, cmd_arg);
+          ASSERT(0);
+        }
+        else
+        {
+          char    tmpstr[ROUNDUP64(GLINK_CH_NAME_LEN)] = {0};
+          uint32  curr = 0;
+          uint32* string_ptr;
+          string_ptr = (uint32 *)&tmpstr[0];
+          while (curr < cmd_arg && curr < sizeof(tmpstr))
+          {
+            CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+            *(string_ptr++) = MSGRAM_READ32(ctx_ptr, read_ind);
+            curr += sizeof(uint32);
+            read_ind += sizeof(uint32);
+          }
+
+          /* add all the unread stuff */
+          read_ind += cmd_arg - curr;
+
+          /* make sure the last character is NULL */
+          tmpstr[sizeof(tmpstr) - 1] = 0;
+
+          ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
+            (glink_transport_if_type *)ctx_ptr, cid, tmpstr, GLINK_XPORT_RPM);
+        }
+
+        break;
+
+      case XPORT_RPM_CMD_CLOSE_CHANNEL:
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_close(
+          //(glink_transport_if_type *)ctx_ptr, XPORT_RPM_GET_CHANNEL_ID(cmd));
+          (glink_transport_if_type *)ctx_ptr, cid);
+
+        /* no need to increment read_ind here since it would be rounded up */
+
+        break;
+
+      case XPORT_RPM_CMD_OPEN_CHANNEL_ACK:
+
+        /* no need to increment read_ind here since it would be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
+            (glink_transport_if_type *)ctx_ptr, cid, GLINK_XPORT_RPM);
+
+        break;
+
+      case XPORT_RPM_CMD_CLOSE_CHANNEL_ACK:
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
+          (glink_transport_if_type *)ctx_ptr, cid);
+
+        /* no need to increment read_ind here since it would be rounded up */
+
+        break;
+
+      case XPORT_RPM_CMD_TX_DATA:
+      {
+        glink_rx_intent_type desc;
+        memset( &desc, sizeof( glink_rx_intent_type), 0 );
+
+        read_ind += sizeof(cmd_arg);
+
+        CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* packet data should fit into the FIFO */
+        if (cmd_arg >= ctx_ptr->rx_fifo_size)
+        {
+          dprintf(CRITICAL, "%s:%d: Invalid packet length: %u",__func__, __LINE__, cmd_arg);
+          ASSERT(0);
+        }
+
+        read_ind += 2*sizeof(cmd_arg);
+
+        CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+
+        ctx_ptr->pkt_start_ind = read_ind;
+        ctx_ptr->pkt_size = cmd_arg;
+
+        desc.size = cmd_arg;
+        desc.used = cmd_arg;
+        desc.pkt_sz = cmd_arg;
+        desc.iovec = ctx_ptr;
+        desc.vprovider = xport_rpm_pkt_provider;
+
+        read_ind += cmd_arg;
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_put_pkt_ctx(
+          (glink_transport_if_type *)ctx_ptr, cid,
+          &desc, TRUE);
+
+        /* If interrupt was disabled then stop delivering messages */
+        stop_processing = ctx_ptr->irq_mask;
+
+        break;
+      }
+
+      case XPORT_RPM_CMD_TX_SIGNALS:
+
+        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+        /* no need to incerement read_ind here since it will be rounded up */
+
+        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_remote_sigs(
+          (glink_transport_if_type *)ctx_ptr,
+          cid, cmd_arg);
+        break;
+
+      default:
+      	dprintf(CRITICAL, "%s:%d: Invalid Command: %u\n",__func__, __LINE__, cmd);
+      	ASSERT(0);
+        break;
+    }
+
+    read_ind = ROUNDUP64(read_ind);
+
+    if (read_ind >= ctx_ptr->rx_fifo_size)
+    {
+      read_ind -= ctx_ptr->rx_fifo_size;
+    }
+
+    /* Update the shared read index */
+    ctx_ptr->rx_desc->read_ind = read_ind;
+  }
+
+  glink_os_cs_release(ctx_ptr->rx_link_lock);
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+#ifdef GLINK_RPM_PROC
+/*===========================================================================
+FUNCTION      xport_rpm_isr
+===========================================================================*/
+/**
+
+  ISR of RPM transport.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_isr( void )
+{
+  xport_rpm_ctx_type *ctx_ptr  = xport_rpm_get_context();
+
+  return xport_rpm_poll( ctx_ptr );
+}
+#else
+/*===========================================================================
+FUNCTION      xport_rpm_isr
+===========================================================================*/
+/**
+
+  ISR of RPM transport.
+
+  @param[in]  ctx_ptr   Pointer to transport context.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+
+  @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_isr( xport_rpm_ctx_type *ctx_ptr )
+{
+  return xport_rpm_poll( ctx_ptr );
+}
+#endif
+
+
+/*===========================================================================
+FUNCTION      xport_rpm_ssr
+===========================================================================*/
+/**
+
+  Processes SSR event.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_ssr(glink_transport_if_type *if_ptr)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+  ctx_ptr->tx_desc->write_ind = 0;
+  ctx_ptr->rx_desc->read_ind = 0;
+  ctx_ptr->reset = TRUE;
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_wait_link_down
+===========================================================================*/
+/**
+
+  Waits for read/write indicies to be set to 0 by the remote host.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+
+  @return     TRUE if link is down, FALSE otherwise.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+boolean xport_rpm_wait_link_down(glink_transport_if_type *if_ptr)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+  return (ctx_ptr->tx_desc->write_ind == 0 &&
+          ctx_ptr->tx_desc->read_ind == 0  &&
+          ctx_ptr->rx_desc->write_ind == 0 &&
+          ctx_ptr->rx_desc->read_ind == 0);
+}
+
+
+/*===========================================================================
+FUNCTION      xport_rpm_mask_interrupt
+===========================================================================*/
+/**
+
+  Enables or disables interrupts.
+
+  @param[in]  if_ptr   Pointer to transport interface instance.
+  @param[in]  mask     TRUE=mask, FALSE=unmask
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_mask_interrupt(glink_transport_if_type *if_ptr, boolean mask)
+{
+  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+  if (ctx_ptr->irq_mask != mask)
+  {
+    if (mask)
+    {
+      glink_os_disable_interrupt(ctx_ptr->pcfg->irq_in);
+    }
+    else
+    {
+      glink_os_enable_interrupt(ctx_ptr->pcfg->irq_in);
+    }
+
+    ctx_ptr->irq_mask = mask;
+  }
+
+  return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+FUNCTION      xport_rpm_init
+===========================================================================*/
+/**
+
+  Initializes RPM transport.
+  Must be called before any other operations are done.
+
+  @param[in]  arg   The argument.
+
+  @return     Returns error code.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_init(void *arg)
+{
+  uint32 ind;
+  glink_core_transport_cfg_type xport_rpm_cfg = { 0 };
+  uint32 *msg_ram_toc = (uint32*)xport_rpm_msg_ram_toc;
+  xport_rpm_toc_entry_type *entry;
+  uint32 msg_ram_toc_num;
+  char* msg_ram_toc_entry_start = (char*)&msg_ram_toc[XPORT_RPM_TOC_ENTRIES_IDX];
+  dprintf(SPEW, "%s:%d: RPM Transport INIT\n", __func__, __LINE__);
+
+  if (xport_rpm_config_num == 0)
+  {
+    return GLINK_STATUS_SUCCESS;
+  }
+
+  if (msg_ram_toc[XPORT_RPM_TOC_MAGIC_IDX] != XPORT_RPM_TOC_MAGIC)
+  {
+    dprintf(CRITICAL, "%s:%d: RPM Transport Failure: Invalid ToC cookie\n", __func__, __LINE__);
+    return GLINK_STATUS_FAILURE;
+  }
+
+  msg_ram_toc_num = msg_ram_toc[XPORT_RPM_TOC_LENGTH_IDX];
+
+  if (msg_ram_toc_num == 0)
+  {
+    dprintf(SPEW, "%s:%d RPM Transport Success\n", __func__, __LINE__);
+    return GLINK_STATUS_SUCCESS;
+  }
+
+  xport_rpm_ctx = glink_os_calloc(sizeof(*xport_rpm_ctx)*xport_rpm_config_num);
+
+  if (xport_rpm_ctx == NULL)
+  {
+    dprintf(INFO, "%s:%d RPM Transport Failed to allocate context\n", __func__, __LINE__);
+    ASSERT(0);
+  }
+
+  /* Initialize supported version and features */
+  xport_rpm_version.version = 1;
+  xport_rpm_version.features = 0;
+  xport_rpm_version.negotiate_features = &xport_rpm_negotiate_features;
+
+  /* Initialize edges */
+  dprintf(SPEW, "%s:%d: Initialize Edges\n", __func__, __LINE__);
+
+  for (ind = 0; ind < xport_rpm_config_num; ind++)
+  {
+    xport_rpm_ctx[ind].pcfg = xport_rpm_get_config(ind);
+
+    /* Find FIFOs in MSG RAM ToC */
+    for (entry = (xport_rpm_toc_entry_type*)msg_ram_toc_entry_start;
+         (char*)entry < msg_ram_toc_num*sizeof(*entry) + msg_ram_toc_entry_start &&
+           (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL);
+         entry++)
+    {
+      if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->tx_fifo_id)
+      {
+        xport_rpm_ctx[ind].tx_desc = (xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
+        xport_rpm_ctx[ind].tx_desc->write_ind = 0;
+        xport_rpm_ctx[ind].tx_fifo = (char*)(xport_rpm_ctx[ind].tx_desc + 1);
+        xport_rpm_ctx[ind].tx_fifo_size = entry->fifo_size;
+      }
+      else if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->rx_fifo_id)
+      {
+        xport_rpm_ctx[ind].rx_desc =(xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
+        xport_rpm_ctx[ind].rx_desc->read_ind = 0;
+        xport_rpm_ctx[ind].rx_fifo = (char*)(xport_rpm_ctx[ind].rx_desc + 1);
+        xport_rpm_ctx[ind].rx_fifo_size = entry->fifo_size;
+      }
+    }
+
+    if (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL)
+    {
+      /* FIFOs not found in MSG RAM ToC. */
+      xport_rpm_ctx[ind].pcfg = NULL;
+      continue;
+    }
+
+    /* Initialize context */
+    xport_rpm_ctx[ind].tx_link_lock = NULL;
+    xport_rpm_ctx[ind].rx_link_lock = NULL;
+
+    /* Initialize GLink transport interface */
+    xport_rpm_ctx[ind].xport_if.tx_cmd_version = &xport_rpm_tx_cmd_version;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_version_ack = &xport_rpm_tx_cmd_version_ack;
+    xport_rpm_ctx[ind].xport_if.set_version = &xport_rpm_set_version;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_open = &xport_rpm_tx_cmd_ch_open;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_close = &xport_rpm_tx_cmd_ch_close;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_open_ack = &xport_rpm_tx_cmd_ch_remote_open_ack;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_close_ack = &xport_rpm_tx_cmd_ch_remote_close_ack;
+    xport_rpm_ctx[ind].xport_if.tx = &xport_rpm_tx;
+    xport_rpm_ctx[ind].xport_if.tx_cmd_set_sigs = &xport_rpm_tx_cmd_set_sigs;
+    xport_rpm_ctx[ind].xport_if.ssr = &xport_rpm_ssr;
+    xport_rpm_ctx[ind].xport_if.mask_rx_irq = &xport_rpm_mask_interrupt;
+    xport_rpm_ctx[ind].xport_if.poll = (poll_fn)&xport_rpm_poll;
+    xport_rpm_ctx[ind].xport_if.wait_link_down = &xport_rpm_wait_link_down;
+
+    /* TODO: glink transport priority */
+    xport_rpm_ctx[ind].xport_if.glink_priority = GLINK_XPORT_RPM;
+
+    /* Setup GLink configuration */
+    xport_rpm_cfg.name = XPORT_RPM_NAME;
+    xport_rpm_cfg.remote_ss = xport_rpm_ctx[ind].pcfg->remote_ss;
+    xport_rpm_cfg.version = &xport_rpm_version;
+    xport_rpm_cfg.version_count = 1;
+    xport_rpm_cfg.max_cid = 0xFF;
+    xport_rpm_cfg.max_iid = 0;
+    if (glink_core_register_transport(&xport_rpm_ctx[ind].xport_if, &xport_rpm_cfg) !=
+        GLINK_STATUS_SUCCESS)
+    {
+      /* Registration failed, set index to invalid. */
+      xport_rpm_ctx[ind].pcfg = NULL;
+      continue;
+    }
+
+    if ( !glink_os_register_isr( xport_rpm_ctx[ind].pcfg->irq_in,
+                                (os_isr_cb_fn)xport_rpm_isr,
+                                &xport_rpm_ctx[ind]) )
+    {
+       /* ISR registration failed, set index to invalid. */
+      xport_rpm_ctx[ind].pcfg = NULL;
+      continue;
+    }
+
+    /* send link up notification */
+    xport_rpm_ctx[ind].xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)&xport_rpm_ctx[ind].xport_if);
+  }
+
+  return GLINK_STATUS_SUCCESS;
+}
diff --git a/platform/msm_shared/glink/xport_rpm_config.c b/platform/msm_shared/glink/xport_rpm_config.c
new file mode 100644
index 0000000..1fff513
--- /dev/null
+++ b/platform/msm_shared/glink/xport_rpm_config.c
@@ -0,0 +1,92 @@
+/* Copyright (c) 2015, 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 FILES
+===========================================================================*/
+#include "xport_rpm_config.h"
+#include "smem_type.h"
+#include "glink_os_utils.h"
+#include <platform/iomap.h>
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+
+#define XPORT_RPM_MSG_RAM_BASE        RPM_SS_MSG_RAM_START_ADDRESS_BASE_PHYS
+#define XPORT_RPM_MSG_RAM_SIZE        RPM_SS_MSG_RAM_START_ADDRESS_BASE_SIZE
+
+/** Size of Glink RPM transport ToC in MSG RAM */
+#define XPORT_RPM_MSG_TOC_SIZE        0x100
+
+/*===========================================================================
+                        DATA DECLARATIONS
+===========================================================================*/
+const xport_rpm_config_type xport_rpm_config[] =
+{
+  /* LK->Rpm */
+  {
+    "rpm",                /* Remote host name        */
+    XPORT_RPM_AP2R_ID,    /* Tx FIFO ID in RPM ToC   */
+    XPORT_RPM_R2AP_ID,    /* Rx FIFO ID in RPM ToC   */
+    {                     /* Outgoing interrupt      */
+      8, //DALIPCINT_PROC_RPM,
+      0, //DALIPCINT_GP_0
+    },
+    200                   /* Incoming interrupt      */
+  }
+};
+
+const uint32 xport_rpm_config_num = ARRAY_LENGTH(xport_rpm_config);
+const char* xport_rpm_msg_ram = (char*)XPORT_RPM_MSG_RAM_BASE;
+const uint32* xport_rpm_msg_ram_toc = (uint32*)(XPORT_RPM_MSG_RAM_BASE + XPORT_RPM_MSG_RAM_SIZE - XPORT_RPM_MSG_TOC_SIZE);
+
+/*===========================================================================
+FUNCTION      xport_rpm_get_config
+===========================================================================*/
+/**
+
+  Provides a pointer to transport config strucutre.
+
+  @param[in]  ind    Index of the config
+
+  @return     Pointer to transport config strucutre.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+const xport_rpm_config_type* xport_rpm_get_config(uint32 ind)
+{
+  if (ind >= xport_rpm_config_num)
+  {
+    return NULL;
+  }
+
+  return &xport_rpm_config[ind];
+}
diff --git a/platform/msm_shared/hsusb.c b/platform/msm_shared/hsusb.c
index 839f301..5c7d61f 100644
--- a/platform/msm_shared/hsusb.c
+++ b/platform/msm_shared/hsusb.c
@@ -2,7 +2,7 @@
  * Copyright (c) 2008, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2015, 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
@@ -183,6 +183,11 @@
 	ept->next = ept_list;
 	ept_list = ept;
 
+	arch_clean_invalidate_cache_range((addr_t) ept,
+					  sizeof(struct udc_endpoint));
+	arch_clean_invalidate_cache_range((addr_t) ept->head,
+					  sizeof(struct ept_queue_head));
+
 	DBG("ept%d %s @%p/%p max=%d bit=%x\n",
 	    num, in ? "in" : "out", ept, ept->head, max_pkt, ept->bit);
 
@@ -525,6 +530,7 @@
 	DBG("setup_tx %p %d\n", buf, len);
 	memcpy(ep0req->buf, buf, len);
 	ep0req->buf = (void *)PA((addr_t)ep0req->buf);
+	arch_clean_invalidate_cache_range((addr_t)ep0req->buf, len);
 	ep0req->complete = ep0in_complete;
 	ep0req->length = len;
 	udc_request_queue(ep0in, ep0req);
@@ -541,6 +547,7 @@
 	arch_clean_invalidate_cache_range((addr_t) ept->head->setup_data,
 					  sizeof(struct ept_queue_head));
 	memcpy(&s, ept->head->setup_data, sizeof(s));
+	arch_clean_invalidate_cache_range((addr_t)&s, sizeof(s));
 	writel(ept->bit, USB_ENDPTSETUPSTAT);
 
 	DBG("handle_setup type=0x%02x req=0x%02x val=%d idx=%d len=%d (%s)\n",
@@ -559,9 +566,23 @@
 	case SETUP(DEVICE_READ, GET_DESCRIPTOR):
 		{
 			struct udc_descriptor *desc;
+			unsigned char* data = NULL;
+			unsigned n;
 			/* usb_highspeed? */
 			for (desc = desc_list; desc; desc = desc->next) {
 				if (desc->tag == s.value) {
+					/*Check for configuration type of descriptor*/
+					if (desc->tag == (TYPE_CONFIGURATION << 8)) {
+						data = desc->data;
+						data+= 9; /* skip config desc */
+						data+= 9; /* skip interface desc */
+						/* taking the max packet size based on the USB host speed connected */
+						for (n = 0; n < 2; n++) {
+							data[4] = usb_highspeed ? 512:64;
+							data[5] = (usb_highspeed ? 512:64)>>8;
+							data += 7;
+						}
+					}
 					unsigned len = desc->len;
 					if (len > s.length)
 						len = s.length;
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 04ce64d..1d2bd44 100755
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -142,5 +142,5 @@
 int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info);
 int update_device_tree(void *fdt, const char *, void *, unsigned);
 int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint64_t size, uint64_t addr);
-void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags);
+void *dev_tree_appended(void *kernel, uint32_t kernel_size, uint32_t dtb_offset, void *tags);
 #endif
diff --git a/platform/msm_shared/include/glink.h b/platform/msm_shared/include/glink.h
new file mode 100644
index 0000000..fe5b823
--- /dev/null
+++ b/platform/msm_shared/include/glink.h
@@ -0,0 +1,580 @@
+/* Copyright (c) 2015, 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 GLINK_H
+#define GLINK_H
+
+/**
+ * @file glink.h
+ *
+ * Public API for the GLink
+ */
+
+/** \defgroup glink GLink
+ * \ingroup SMD
+ *
+ * GLink reliable, in-order, datagram-based interprocessor communication
+ * over a set of supported transport (Shared Memory, UART, BAM, HSIC)
+ *
+ * All ports preserve message boundaries across the interprocessor channel; one
+ * write into the port exactly matches one read from the port.
+ */
+/*@{*/
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include <stdlib.h>
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+/** GLink status/return codes */
+typedef enum {
+  GLINK_STATUS_SUCCESS = 0,
+  GLINK_STATUS_FAILURE,
+  GLINK_STATUS_INVALID_PARAM,
+  GLINK_STATUS_NOT_INIT,
+  GLINK_STATUS_OUT_OF_RESOURCES,
+  GLINK_STATUS_NO_TRANSPORT
+}glink_err_type;
+
+/** List of possible suvsystems */
+/**
+  "apss"   Application Processor Subsystem
+  "mpss"   Modem subsystem
+  "lpass"  Low Power Audio Subsystem
+  "dsps"   Sensors Processor
+  "wcnss"  Wireless Connectivity Subsystem
+  "rpm"    Resource Power Manager processor
+*/
+
+/** Max allowed channel name length */
+#define GLINK_CH_NAME_LEN 32
+
+/* Bit position of DTR/CTS/CD/RI bits in control sigs 32 bit signal map */
+#define SMD_DTR_SIG_SHFT 31
+#define SMD_CTS_SIG_SHFT 30
+#define SMD_CD_SIG_SHFT  29
+#define SMD_RI_SIG_SHFT  28
+
+/** Version number for the glink_link_id_type structure */
+#define GLINK_LINK_ID_VER  0x00000001
+
+/** Macro to initialize the link identifier structure with default values.
+ * It memsets the header to 0 and initializes the header field */
+#define GLINK_LINK_ID_STRUCT_INIT(link_id) \
+                          (link_id).xport = 0; \
+                          (link_id).remote_ss = 0; \
+                          (link_id).link_notifier = 0; \
+                          (link_id).handle = 0; \
+                          (link_id).version = GLINK_LINK_ID_VER;
+
+/* GLink tx options */
+/* Whether to block and request for remote rx intent in
+ * case it is not available for this pkt tx */
+#define GLINK_TX_REQ_INTENT      0x00000001
+
+/* If the tx call is being made from single threaded context. GLink tries to
+ * flush data into the transport in glink_tx() context, or returns error if
+ * it is not able to do so */
+#define GLINK_TX_SINGLE_THREADED 0x00000002
+
+/* ======================= glink open cfg options ==================*/
+
+/* Specified transport is just the initial transport and migration is possible
+ * to higher-priority transports.  Without this flag, the open will fail if
+ * the transport does not exist. */
+#define GLINK_OPT_INITIAL_XPORT   0x00000001
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+/** Enums to identify link state */
+typedef enum {
+ GLINK_LINK_STATE_UP,  /* Called after specified link is online */
+ GLINK_LINK_STATE_DOWN /* Called after SSR (before REMOTE_DISCONNECT) */
+} glink_link_state_type;
+
+/** Data structure holding the link state information */
+typedef struct          glink_link_info_t {
+  const char*           xport;      /* Transport name */
+  const char*           remote_ss;  /* Remote subsystem name */
+  glink_link_state_type link_state; /* Link state */
+}glink_link_info_type;
+
+/* Callback function invoked when link goes up/down */
+typedef void (*glink_link_state_notif_cb)
+(
+  glink_link_info_type *link_info, /* Ptr to link information strcuture */
+  void* priv                       /* Client private data */
+);
+
+/**
+ * Opaque handle returned by glink_register_link_state_cb. Client uses this
+ * handle to call glink_deregister_link_state_cb() to deregister their
+ * callback
+ *
+ * Client must not modify or try to interpret this value
+ */
+typedef struct glink_link_notif_data_type * glink_link_handle_type;
+
+/** Data structure to provide link information for the link to monitor */
+typedef struct glink_link_id_t {
+  unsigned int              version; /* This fields identifies the verion of
+                                        the structure. Initialized by
+                                        GLINK_LINK_ID_STRUCT_INIT macro */
+
+  const char*               xport;         /* NULL = any transport */
+  const char*               remote_ss;     /* NULL = any subsystem */
+  glink_link_state_notif_cb link_notifier; /* Notification callback */
+  glink_link_handle_type    handle;  /* Set by glink_register_link_state_cb */
+}glink_link_id_type;
+
+/**
+ * Opaque handle returned by glink_open. Client uses this handle to call into
+ * GLink API for any further activity related to the channel,
+ *
+ * Client must to modify or try to interpret this value
+ */
+typedef struct glink_channel_ctx* glink_handle_type;
+
+/** GLink logical link state notifications */
+typedef enum {
+  /** Channel is fully opened. Both local and remote end have
+      opened channel from their respective ends, and data communication
+      can now take place */
+  GLINK_CONNECTED = 0,
+
+  /** Local side has called glink_close() and remote side has acknowledged
+      this end's close. Client may call glink_open() after this point */
+  GLINK_LOCAL_DISCONNECTED,
+
+  /** Remote side has called glink_close() to close the channel */
+  GLINK_REMOTE_DISCONNECTED
+}glink_channel_event_type;
+
+/** Vector buffer provider type*/
+typedef void* (*glink_buffer_provider_fn)
+(
+  void*  iovec,   /* vector buffer */
+  size_t offset,  /* offset from the beginning of the vector */
+  size_t *size    /* size of the returned contiguous buffer */
+);
+
+/** Data receive notification callback type*/
+typedef void (*glink_rx_notification_cb)
+(
+  glink_handle_type handle,     /* handle for the glink channel */
+  const void        *priv,      /* priv client data passed in glink_open */
+  const void        *pkt_priv,  /* private client data assiciated with the
+                                   rx intent that client queued earlier */
+  const void        *ptr,       /* pointer to the received buffer */
+  size_t            size,       /* size of the packet */
+  size_t            intent_used /* size of the intent used for this packet */
+);
+
+/** Vector receive notification callback type*/
+typedef void (*glink_rxv_notification_cb)
+(
+  glink_handle_type        handle,    /* handle for the glink channel */
+  const void               *priv,     /* priv client data passed in glink_open */
+  const void               *pkt_priv, /* private client data assiciated with the
+                                         rx intent that client queued earlier */
+  void                     *iovec,    /* pointer to the received vector */
+  size_t                   size,      /* size of the packet */
+  size_t                   intent_used, /* size of the intent used for this packet */
+  glink_buffer_provider_fn vprovider, /* Buffer provider for virtual space */
+  glink_buffer_provider_fn pprovider  /* Buffer provider for physical space */
+);
+
+/** Data transmit notification callback type*/
+typedef void (*glink_tx_notification_cb)
+(
+  glink_handle_type handle,    /* handle for the glink channel */
+  const void        *priv,     /* priv client data passed in glink_open */
+  const void        *pkt_priv, /* private client data assiciated with the
+                                  tx pkt that client queued earlier */
+  const void        *ptr,      /* pointer to the transmitted buffer */
+  size_t            size       /* size of the packet */
+);
+
+/** GLink channel state change notification callback type*/
+typedef void (*glink_state_notification_cb)
+(
+  glink_handle_type         handle, /* handle for the glink channel */
+  const void                *priv,  /* priv client data passed in glink_open */
+  glink_channel_event_type  event   /* Notification event */
+);
+
+/** Request for a receive intent of size req_size is queued. The request
+ * originates from the remote side GLink client. Return true if intent will
+ * be queued or false if intent request will be denied. */
+typedef bool (*glink_notify_rx_intent_req_cb)
+(
+  glink_handle_type         handle,   /* handle for the glink channel */
+  const void                *priv,    /* priv client data passed in glink_open */
+  size_t                    req_size  /* Requested size */
+);
+
+/** New intent arrival notification callback type*/
+typedef void (*glink_notify_rx_intent_cb)
+(
+  glink_handle_type         handle,   /* handle for the glink channel */
+  const void                *priv,    /* priv client data passed in glink_open */
+  size_t                    size      /* Intent size */
+);
+
+/** Control signal change notification - Invoked when remote side
+ *  alters its control signals */
+typedef void (*glink_notify_rx_sigs_cb)
+(
+  glink_handle_type  handle,   /* handle for the glink channel */
+  const void         *priv,    /* priv client data passed in glink_open  */
+  uint32_t             prev,     /* Previous remote state */
+  uint32_t             curr      /* Current remote state */
+);
+
+/** rx_intent abort notification. This callback would be invoked for
+ *  every rx_intent that is queued with GLink core at the time the
+ *  remote side or local side decides to close the port */
+typedef void(*glink_notify_rx_abort_cb)
+(
+glink_handle_type  handle,   /* handle for the glink channel */
+const void         *priv,    /* priv client data passed in glink_open  */
+const void         *pkt_priv /* pkt specific private data */
+);
+
+/** tx abort notification. This callback would be invoked if client
+ *   had queued a tx buffer with glink and it had not been transmitted i.e.
+ *   tx_done callback has not been called for this buffer and remote side
+ *   or local side closed the port*/
+typedef void(*glink_notify_tx_abort_cb)
+(
+glink_handle_type  handle,   /* handle for the glink channel */
+const void         *priv,    /* priv client data passed in glink_open  */
+const void         *pkt_priv /* pkt specific private data */
+);
+
+/**
+ * Data Structure for GLink logical channel open configuration
+ *
+ * This structure is used by the clients to open a GLink logical channel
+ * when calling glink_open()
+ */
+typedef struct {
+  /** string name for the transport to use (Optional)*/
+  const char                    *transport;
+
+  /** string name for the remote subsystem to which the user wants to
+      connect */
+  const char                    *remote_ss;
+
+  /** string name for the channel */
+  const char                    *name;
+
+  /** bitfield for specifying various options */
+  unsigned                      options;
+
+  /** Private data for client to maintain context. This data is passed back
+      to client in the notification callbacks */
+  const void                    *priv;
+
+  /** Data receive notification callback. Optional if notify_rxv is provided */
+  glink_rx_notification_cb      notify_rx;
+
+  /** Vector receive notification callback. Optional if notify_rx is provided */
+  glink_rxv_notification_cb     notify_rxv;
+
+  /** Data transmit notification callback */
+  glink_tx_notification_cb      notify_tx_done;
+
+  /** GLink channel state notification callback */
+  glink_state_notification_cb   notify_state;
+
+  /** Intent request from the remote side. Optional */
+  glink_notify_rx_intent_req_cb notify_rx_intent_req;
+
+  /** New intent arrival from the remote side */
+  glink_notify_rx_intent_cb     notify_rx_intent;
+
+  /** Control signal change notification - Invoked when remote side
+   *  alters its control signals. Optional */
+  glink_notify_rx_sigs_cb       notify_rx_sigs;
+
+  /** rx_intent abort notification. This callback would be invoked for
+   *  every rx_intent that is queued with GLink core at the time the
+   *  remote side or local side decides to close the port. Optional */
+  glink_notify_rx_abort_cb      notify_rx_abort;
+
+  /** tx abort notification. This callback would be invoked if client
+  *   had queued a tx buffer with glink and it had not been transmitted i.e.
+  *   tx_done callback has not been called for this buffer and remote side
+  *   or local side closed the port. Optional */
+  glink_notify_tx_abort_cb      notify_tx_abort;
+
+}glink_open_config_type;
+
+/*===========================================================================
+                      GLINK PUBLIC API
+===========================================================================*/
+/**
+ * Regsiters a client specified callback to be invoked when the specified
+ * transport (link) is up/down.
+ *
+ * @param[in]    link_id  Pointer to the configuration structure for the
+ *                        xport(link) to be monitored. See glink.h
+ * @param[in]    priv     Callback data returned to client when callback
+ *                        is invoked.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Puts the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_register_link_state_cb
+(
+  glink_link_id_type *link_id,
+  void* priv
+);
+
+/**
+ * Degsiter the link UP/DOWN notification callback associated with the
+ * provided handle.
+ *
+ * @param[in]    handle  Callback handler returned by
+ *                       glink_register_link_state_cb
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Removes the callback in a queue which gets scanned when a
+ *               transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_deregister_link_state_cb
+(
+  glink_link_handle_type handle
+);
+
+/**
+ * Opens a logical GLink based on the specified config params
+ *
+ * @param[in]    cfg_ptr  Pointer to the configuration structure for the
+ *                        GLink. See glink.h
+ * @param[out]   handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Allocates channel resources and informs remote host about
+ *               channel open.
+ */
+glink_err_type glink_open
+(
+  glink_open_config_type *cfg_ptr,
+  glink_handle_type      *handle
+);
+
+/**
+ * Closes the GLink logical channel specified by the handle.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Closes local end of the channel and informs remote host
+ */
+glink_err_type glink_close
+(
+  glink_handle_type handle
+);
+
+/**
+ * Transmit the provided buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *data      Pointer to the data buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   options    Flags specifying how transmission for this buffer
+ *                         would be handled. See GLINK_TX_* flag definitions.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_tx
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  const void        *data,
+  size_t            size,
+  uint32_t            options
+);
+
+/**
+ * Transmit the provided vector buffer over GLink.
+ *
+ * @param[in]    handle    GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv  Per packet private data
+ *
+ * @param[in]   *iovec     Pointer to the vector buffer to be transmitted
+ *
+ * @param[in]   size       Size of buffer
+ *
+ * @param[in]   vprovider  Buffer provider for virtual space
+ *
+ * @param[in]   pprovider  Buffer provider for physical space
+ *
+ * @param[in]   options    Flags specifying how transmission for this buffer
+ *                         would be handled. See GLINK_TX_* flag definitions.
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_txv
+(
+  glink_handle_type        handle,
+  const void               *pkt_priv,
+  void                     *iovec,
+  size_t                   size,
+  glink_buffer_provider_fn vprovider,
+  glink_buffer_provider_fn pprovider,
+  uint32_t                   options
+);
+
+/**
+ * Queue one or more Rx intent for the logical GPIC Link channel.
+ *
+ * @param[in]    handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *pkt_priv Per packet private data
+ *
+ * @param[in]   size      Size of buffer
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL allocates rx buffers for receiving packets
+ */
+glink_err_type glink_queue_rx_intent
+(
+  glink_handle_type handle,
+  const void        *pkt_priv,
+  size_t            size
+);
+
+/**
+ * Client uses this to signal to GLink layer that it is done with the received
+ * data buffer. This API should be called to free up the receive buffer, which,
+ * in zero-copy mode is actually remote-side's transmit buffer.
+ *
+ * @param[in]   handle   GLink handle associated with the logical channel
+ *
+ * @param[in]   *ptr     Pointer to the received buffer
+ *
+ * @param[in]   reuse    Reuse intent
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  GLink XAL frees the Rx buffer
+ */
+glink_err_type glink_rx_done
+(
+  glink_handle_type handle,
+  const void        *ptr,
+  bool           reuse
+);
+
+/**
+ * Set the 32 bit control signal field. Depending on the transport, it may
+ * take appropriate actions on the set bit-mask, or transmit the entire
+ * 32-bit value to the remote host.
+ *
+ * @param[in]   handle     GLink handle associated with the logical channel
+ *
+ * @param[in]   sig_value  32 bit signal word
+ *
+ * @return       Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_set
+(
+  glink_handle_type handle,
+  uint32_t            sig_value
+);
+
+/**
+ * Get the local 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_local_get
+(
+  glink_handle_type handle,
+  uint32_t            *sig_value
+);
+
+/**
+ * Get the remote 32 bit control signal bit-field.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[out]  *sig_value  Pointer to a 32 bit signal word to get sig value
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_sigs_remote_get
+(
+  glink_handle_type handle,
+  uint32_t            *sig_value
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //GLINK_H
diff --git a/platform/msm_shared/include/glink_channel_migration.h b/platform/msm_shared/include/glink_channel_migration.h
new file mode 100644
index 0000000..3693660
--- /dev/null
+++ b/platform/msm_shared/include/glink_channel_migration.h
@@ -0,0 +1,141 @@
+/* Copyright (c) 2015, 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 GLINK_CH_MGR__H
+#define GLINK_CH_MGR__H
+
+/*===========================================================================
+
+                    GLink channel migration Header File
+
+===========================================================================*/
+
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        FEATURE DEFINITIONS
+===========================================================================*/
+
+/**
+ * This function returns glink_transport_if pointer based on
+ *  XPORT priority
+ *
+ * @param[in]    prio       glink xport prio
+ * @param[in]   remote_ss   remote subsytem name
+ *
+ * @return       pointer to glink_transport_if_type struct
+ *
+ * @sideeffects  NONE
+ */
+glink_transport_if_type *glinki_get_xport_from_prio
+(
+  glink_xport_priority prio,
+  const char *remote_ss
+);
+
+/**
+ * This function negotiated xport priorities and gives best
+ *  available priority
+ *
+ * @param[in]    requested_best_prio priority requested by remote subsytem
+ * @param[in]    current_best_prio   priority requested by channel on local
+                                     side
+ *
+ * @return       Negotiated xport priority
+ *
+ * @sideeffects  NONE
+ */
+glink_xport_priority glinki_negotiate_ch_migration
+(
+  glink_xport_priority requested_prio,
+  glink_xport_priority current_prio
+);
+
+/**
+ * This function searches channel with given name on all available
+ * xports and returns channel context and xport on which channel is
+ * present. These return values are used to negotiate xport priorities
+ * and to decide if channel needs to be migrated from given xport
+ * to negotiated xport
+ *
+ * @param[in]    if_ptr              transport on which channel is opened
+ * @param[in]    name                name of the channel
+ * @param[in]    is_local_channel    flag to notify this function if channel to
+ *	                                 be searched will have state REMOTE_OPEN
+ *                                   or LOCAL_OPEN
+ * @param[out]   present_ch_ctx      channel context to be returned
+ * @param[out]   present_if_ptr      xport pointer on which channel is open
+ *
+ * @return       TRUE  -  if channel found
+ *               FALSE -  if channel is not found
+ *
+ * @sideeffects  NONE
+ */
+boolean glinki_local_channel_exists
+(
+  glink_transport_if_type *if_ptr,
+  glink_transport_if_type **present_if_ptr,
+  const char               *name,
+  glink_channel_ctx_type  **present_ch_ctx,
+  boolean                    is_local_channel
+);
+
+/**
+ * This function sets flag for channel context to represent
+ * that channel is tagged for deletion. This is to cover corner
+ * case where local side might close the channel but channel
+ * context still sticks around and might be found again for
+ * xport negotiation.
+ *
+ * @param[in]    if_ptr  transport on which channel is opened
+ * @param[in]    name    name of the channel
+ * @param[in]    prio    priority of negotiated xport. all channels on
+ *	                     xports other than xport with this prio will be
+ *		                 tagged for deletion
+ *
+ * @return       NONE
+ *
+ * @sideeffects  NONE
+ */
+void glinki_tag_ch_for_deletion
+(
+  glink_transport_if_type *if_ptr,
+  const char              *name,
+  glink_xport_priority    prio
+);
+
+#endif /* GLINK_CHANNEL_MIGRATION_H */
diff --git a/platform/msm_shared/include/glink_core_if.h b/platform/msm_shared/include/glink_core_if.h
new file mode 100644
index 0000000..040bf31
--- /dev/null
+++ b/platform/msm_shared/include/glink_core_if.h
@@ -0,0 +1,512 @@
+/* Copyright (c) 2015, 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 GLINK_CORE_IF_H
+#define GLINK_CORE_IF_H
+
+/**
+ * @file glink_core_if.h
+ *
+ * Public API for the transport abstraction layer to call into GLINK Core
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+
+#include "smem_list.h"
+#include "glink.h"
+#include "glink_transport_if.h"
+#include "glink_os_utils.h"
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+typedef struct glink_core_version glink_core_version_type;
+
+struct glink_channel_ctx;
+typedef struct glink_channel_ctx glink_channel_ctx_type;
+
+/**
+ * Transport status
+ */
+typedef enum {
+  GLINK_XPORT_REGISTERED = 0,
+  GLINK_XPORT_NEGOTIATING,
+  GLINK_XPORT_LINK_UP,
+
+}glink_transport_status_type;
+
+struct glink_rx_intent {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type    link;
+
+  void       *data;      /* Pointer to the data buffer to be transmitted */
+  const void *pkt_priv;  /* Per packet private data */
+  size_t     size;       /* Size of data buffer */
+  size_t     used;       /* Actual valid data in *data field */
+  size_t     pkt_sz;     /* Size of the packet */
+  uint32     iid;        /* Intent ID */
+  void       *iovec;     /* Pointer to the data buffer to be transmitted */
+  glink_buffer_provider_fn vprovider; /* Buffer provider for virtual space */
+  glink_buffer_provider_fn pprovider; /* Buffer provider for physical space */
+};
+/** GLink channel states*/
+typedef enum {
+  /** GLink channel state during initialization. No resources have been
+   *  allocated for this channel as neither GLink end has actually opened
+   *  the channel */
+  GLINK_CH_STATE_CLOSED,
+
+  /** GLink channel state when the local side has opened the channel. GLink
+   *  core is waiting for the other end of the channel to open */
+  GLINK_CH_STATE_LOCAL_OPEN,
+
+  /** GLink channel state when it is fully open. This implies that both ends
+   *  of the GLink channel are now open. Data transfer can now take place */
+  GLINK_CH_STATE_OPEN,
+
+  /** GLink channel state when remote side has initiated a OPEN operation. */
+  GLINK_CH_STATE_REMOTE_OPEN,
+
+  /** GLink channel state when remote side has initiated a CLOSE operation.
+   *  Data cannot be transmitted/received any further on this channel */
+  GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE,
+
+  /** GLink channel state when the local side has initiated a CLOSE. This
+   *  would be followed by a GLINK_STATE_CLOSE state transition after
+   *  the remote side has acknowledged the CLOSE request */
+   GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE,
+
+  /** GLink channel state would transition to SLEEP if the underlying
+   *  transport supports low power mode and decides to go into sleep
+   *  due to inactivity for some time or any other reason. */
+  GLINK_CH_STATE_SLEEP,
+
+  /** GLink channel state would transition to AWAKE state when underlying
+   *  transport layer has powered up the hardware */
+  GLINK_CH_STATE_AWAKE
+}glink_ch_state_type;
+
+/** Indicates that transport is now ready to start negotiation using the
+ *  v0 configuration. */
+typedef void (*link_up_fn)
+(
+  glink_transport_if_type *if_ptr    /* Pointer to the interface instance */
+);
+
+/** Receive transport version for remote-initiated version negotiation */
+typedef void (*rx_cmd_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Receive ACK to previous glink_transport_if_type::tx_cmd_version command */
+typedef void (*rx_cmd_version_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Sets the core version used by the transport; called after completing
+ *  negotiation.*/
+typedef void (*set_core_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version  /* Version */
+);
+
+/** Receive remote channel open request; expected response is
+ *  glink_transport_if_type:: tx_cmd_ch_remote_open_ack */
+typedef void (*rx_cmd_ch_remote_open_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  const char              *name,   /* String name for the logical channel */
+  glink_xport_priority    prio     /* priority of xport */
+);
+
+/** This function is invoked by the transport in response to
+ *  glink_transport_if_type:: tx_cmd_ch_open */
+typedef void (*rx_cmd_ch_open_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  glink_xport_priority    prio
+);
+
+/** This function is invoked by the transport in response to
+ *  glink_transport_if_type:: tx_cmd_ch_close */
+typedef void (*rx_cmd_ch_close_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid     /* Local channel ID */
+);
+
+/** Remote channel close request; will result in sending
+ *  glink_transport_if_type:: tx_cmd_ch_remote_close_ack */
+typedef void (*rx_cmd_ch_remote_close_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+);
+
+/** Process local state transition */
+typedef void (*ch_state_local_trans_fn)
+(
+  glink_transport_if_type  *if_ptr,  /* Pointer to the interface instance */
+  uint32                   lcid,     /* Local channel ID */
+  glink_ch_state_type      new_state /* New local channel state */
+);
+
+/** Transport invokes this call on receiving remote RX intent */
+typedef void (*rx_cmd_remote_rx_intent_put_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  uint32                  riid,    /* Remote intent ID */
+  size_t                  size     /* Size of receive intent */
+);
+
+/** Get receive packet context (if successful, should be followed by call to
+    rx_put_pkt_ctx) */
+typedef glink_rx_intent_type* (*rx_get_pkt_ctx_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  uint32                  liid     /* Local intent ID */
+);
+
+/** Receive a packet fragment (must have previously received an rx_cmd_rx_data
+    packet). */
+typedef void (*rx_put_pkt_ctx_fn)
+(
+  glink_transport_if_type *if_ptr,     /* Pointer to the interface instance */
+  uint32                  rcid,        /* Remote channel ID */
+  glink_rx_intent_type    *intent_ptr, /* Fragment ptr */
+  boolean                 complete     /* True if pkt is complete */
+);
+
+/** Transport invokes this call to inform GLink that remote side is
+ *  done with previous transmitted packet. */
+typedef void (*rx_cmd_tx_done_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  uint32                  riid,    /* Remote intent ID */
+  boolean                 reuse    /* Reuse intent */
+);
+
+/** Remote side is requesting an RX intent */
+typedef void (*rx_cmd_remote_rx_intent_req_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  size_t                  size     /* Size of the requested intent */
+);
+
+/** ACK to RX Intent Request */
+typedef void (*rx_cmd_rx_intent_req_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  boolean                 granted  /* True if RX Intent will be queued, FALSE
+                                      if request will not be granted. */
+);
+
+/** If transport was full and could not continue a transmit operation,
+ *  then it will call this function to notify the core that it is ready to
+ *  resume transmission. */
+typedef void (*tx_resume_fn)
+(
+  glink_transport_if_type *if_ptr  /* Pointer to the interface instance */
+);
+
+/** Received 32-bit signals value from remote side. It is passed on to
+ *  the client */
+typedef void (*rx_cmd_remote_sigs_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  rcid,       /* Remote channel ID */
+  uint32                  remote_sigs /* Remote control signals */
+);
+
+/** Channel open config verification */
+typedef boolean(*verify_open_cfg_fn)
+(
+  glink_channel_ctx_type   *ch_ctx    /* Pointer to the channel context */
+);
+
+/** Channel initialization */
+typedef glink_err_type (*channel_init_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx /* Pointer to the channel context */
+);
+
+/** Channel cleanup */
+typedef void (*channel_cleanup_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx /* Pointer to the channel context */
+);
+
+/** Channel receive pkt */
+typedef void(*channel_receive_pkt_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx,  /* Pointer to the channel context */
+  glink_rx_intent_type *intent_ptr      /* Pointer to the intent context */
+);
+
+/** Use remote intent */
+typedef glink_err_type(*use_rm_intent_fn)
+(
+  glink_channel_ctx_type *open_ch_ctx,  /* Pointer to the channel context */
+  glink_core_tx_pkt_type *pctx,         /* Pointer to the packet context */
+  boolean req_intent                    /* Request intent flag */
+);
+
+
+/** Transport specific data pointer that transport may choose fill in
+ * with some data */
+struct glink_core_xport_ctx
+{
+  /* Transport name */
+  char                          xport[32];
+
+  /* Remote subsystem name */
+  char                          remote_ss[32];
+
+  /** Keep track of version array index in use */
+  const glink_core_version_type *version_array;
+
+  /** Keep track of version array index in use */
+  uint32                        version_indx;
+
+  /* Keeps track of the current status of the transport */
+  glink_transport_status_type   status;
+
+  /* Transport's capabilities */
+  uint32                        xport_capabilities;
+
+  /* Free lcid */
+  uint32                        free_lcid;
+
+  /* Keeps track of the open channels for this transport/edge combination */
+  smem_list_type                open_list;
+
+  /* Critical section to protect access to open_list */
+  os_cs_type                    channel_q_cs;
+
+  /* Local channel intents queued so far. This also helps determining liid
+   * when client queues new rx intents locally */
+  uint32                        liid;
+
+  /* Critical section to protect access to liid allocation */
+  os_cs_type                    liid_cs;
+
+  /* channel open config verification */
+  verify_open_cfg_fn            verify_open_cfg;
+
+  /* channel init function */
+  channel_init_fn               channel_init;
+
+  /* channel cleanup function */
+  channel_cleanup_fn            channel_cleanup;
+
+  /* channel receive pkt */
+  channel_receive_pkt_fn        channel_receive_pkt;
+
+  /** Use remote intent */
+  use_rm_intent_fn              use_rm_intent;
+};
+
+/**
+ * Data Structure for Transport abstraction layer to call into GLink Core
+ * for logical channel control state update and data Tx/Rx notifications.
+ */
+struct glink_core_if
+{
+  /** Indicates that transport is now ready to start negotiation using the
+   *  v0 configuration. */
+  link_up_fn                     link_up;
+
+
+  /** Receive transport version for remote-initiated version negotiation */
+  rx_cmd_version_fn              rx_cmd_version;
+
+
+  /** Receive ACK to previous glink_transport_if_type::tx_cmd_version command */
+  rx_cmd_version_ack_fn          rx_cmd_version_ack;
+
+  /** Sets the core version used by the transport; called after completing
+   *  negotiation.*/
+  set_core_version_fn            set_core_version;
+
+  /** Receive remote channel open request; expected response is
+   *  glink_transport_if_type:: tx_cmd_ch_remote_open_ack */
+  rx_cmd_ch_remote_open_fn       rx_cmd_ch_remote_open;
+
+
+  /** This function is invoked by the transport in response to
+   *  glink_transport_if_type:: tx_cmd_ch_open */
+  rx_cmd_ch_open_ack_fn          rx_cmd_ch_open_ack;
+
+
+  /** This function is invoked by the transport in response to
+   *  glink_transport_if_type:: tx_cmd_ch_close */
+  rx_cmd_ch_close_ack_fn         rx_cmd_ch_close_ack;
+
+
+  /** Remote channel close request; will result in sending
+   *  glink_transport_if_type:: tx_cmd_ch_remote_close_ack */
+  rx_cmd_ch_remote_close_fn      rx_cmd_ch_remote_close;
+
+
+  /** Process local state transition */
+  ch_state_local_trans_fn        ch_state_local_trans;
+
+
+  /** Transport invokes this call on receiving remote RX intent */
+  rx_cmd_remote_rx_intent_put_fn rx_cmd_remote_rx_intent_put;
+
+  /** Get receive packet context (if successful, should be followed by call to
+      rx_put_pkt_ctx) */
+  rx_get_pkt_ctx_fn              rx_get_pkt_ctx;
+
+  /** Receive a packet fragment (must have previously received an rx_cmd_rx_data
+      packet). */
+  rx_put_pkt_ctx_fn              rx_put_pkt_ctx;
+
+  /** Transport invokes this call to inform GLink that remote side is
+   *   done with previous transmitted packet. */
+  rx_cmd_tx_done_fn              rx_cmd_tx_done;
+
+  /** Remote side is requesting an RX intent */
+  rx_cmd_remote_rx_intent_req_fn rx_cmd_remote_rx_intent_req;
+
+  /** ACK to RX Intent Request */
+  rx_cmd_rx_intent_req_ack_fn    rx_cmd_rx_intent_req_ack;
+
+  /** Received 32-bit signals value from remote side. It is passed on to
+   *  the client */
+  rx_cmd_remote_sigs_fn          rx_cmd_remote_sigs;
+
+  /** If transport was full and could not continue a transmit operation,
+   *  then it will call this function to notify the core that it is ready to
+   *  resume transmission. */
+  tx_resume_fn                   tx_resume;
+};
+
+/** Feature negotiation function.  The version negotiation starts out using
+ *  the full feature set from the features element and then calls this
+ *  function with a subset passed into the features argument.  This
+ *  function should filter passed in features with the supported feature
+ *  set.  For simple cases, a bitwise AND can be used, but for more
+ *  complicated cases (such as when features are mutually exclusive),
+ *  this function enables a more complex negotiation sequence.
+ */
+typedef uint32 (*negotiate_features_fn)
+(
+  glink_transport_if_type       *if_ptr,      /* Pointer to the interface
+                                                 instance */
+  const glink_core_version_type *version_ptr, /* Version structure */
+  uint32                        features      /* Subset of features based on
+                                                 negotiation */
+);
+
+/**
+ * Version structure
+ */
+struct glink_core_version {
+  uint32                   version;      /* Version number */
+  uint32                   features;     /* Set of features supported in
+                                            this version */
+
+  /** Feature negotiation function.  The version negotiation starts out using
+   *  the full feature set from the features element and then calls this
+   *  function with a subset passed into the features argument.  This
+   *  function should filter passed in features with the supported feature
+   *  set.  For simple cases, a bitwise AND can be used, but for more
+   *  complicated cases (such as when features are mutually exclusive),
+   *  this function enables a more complex negotiation sequence.
+   */
+  negotiate_features_fn    negotiate_features;
+};
+
+/**
+ * Data Structure for Transport abstraction layer to call into GLink Core
+ * while registering with GLink
+ */
+typedef struct {
+  const char                    *name;      /* Name of the transport */
+  const char                    *remote_ss; /* Remote host name */
+  const glink_core_version_type *version;   /* Array of supported versions */
+  size_t                        version_count; /* Number of elements in version[] */
+  uint32                        max_cid;    /* Max channel ID supported by
+                                               transport */
+  uint32                        max_iid;    /* Max Rx intent ID supported by
+                                               transport */
+}glink_core_transport_cfg_type;
+
+/*===========================================================================
+                      PUBLIC FUNCTION DECLARATIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_core_register_transport
+
+DESCRIPTION   Transport calls this API to register its interface with GLINK
+              Core
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            *cfg      Pointer to transport configuration structure.
+
+RETURN VALUE  Standard GLINK error codes.
+
+SIDE EFFECTS  None
+===========================================================================*/
+
+glink_err_type glink_core_register_transport
+(
+  glink_transport_if_type       *if_ptr,
+  glink_core_transport_cfg_type *cfg
+);
+
+#endif //GLINK_CORE_IF_H
+
diff --git a/platform/msm_shared/include/glink_internal.h b/platform/msm_shared/include/glink_internal.h
new file mode 100644
index 0000000..96b0a59
--- /dev/null
+++ b/platform/msm_shared/include/glink_internal.h
@@ -0,0 +1,845 @@
+/* Copyright (c) 2015, 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 GLINK_INTERNAL_H
+#define GLINK_INTERNAL_H
+
+/*===========================================================================
+
+                    GLink Core Internal Header File
+
+===========================================================================*/
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include "smem_list.h"
+#include "glink.h"
+#include "glink_os_utils.h"
+#include "glink_core_if.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        FEATURE DEFINITIONS
+===========================================================================*/
+#define GLINK_VERSION 0
+#define GLINK_FEATURE_FLAGS 0
+#define GLINK_NUM_HOSTS     7
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+#define GLINK_LOG_EVENT(type, ch_name, xport, remote_ss, param) \
+  glink_mem_log(__FUNCTION__, __LINE__, type, ch_name, xport, remote_ss, param);
+
+#define GLINK_MEM_LOG_SIZE 128
+
+/*===========================================================================
+                           TYPE DEFINITIONS
+===========================================================================*/
+typedef enum {
+  GLINK_EVENT_INIT,
+  GLINK_EVENT_REGISTER_XPORT,
+  GLINK_EVENT_CH_OPEN,
+  GLINK_EVENT_CH_CLOSE,
+  GLINK_EVENT_CH_TX,
+  GLINK_EVENT_CH_Q_RX_INTENT,
+  GLINK_EVENT_CH_RX_DONE,
+  GLINK_EVENT_LINK_UP,
+  GLINK_EVENT_RX_CMD_VER,
+  GLINK_EVENT_RM_CH_OPEN,
+  GLINK_EVENT_CH_OPEN_ACK,
+  GLINK_EVENT_CH_CLOSE_ACK,
+  GLINK_EVENT_CH_REMOTE_CLOSE,
+  GLINK_EVENT_CH_STATE_TRANS,
+  GLINK_EVENT_CH_INTENT_PUT,
+  GLINK_EVENT_CH_RX_DATA,
+  GLINK_EVENT_CH_RX_DATA_FRAG,
+  GLINK_EVENT_CH_GET_PKT_CTX,
+  GLINK_EVENT_CH_PUT_PKT_CTX,
+  GLINK_EVENT_CH_TX_DONE,
+  GLINK_EVENT_CH_SIG_SET,
+  GLINK_EVENT_CH_SIG_L_GET,
+  GLINK_EVENT_CH_SIG_R_GET,
+  GLINK_EVENT_XPORT_INTERNAL,
+}glink_log_event_type;
+
+typedef struct _glink_channel_intents_type {
+  /* Critical section to protest access to intent queues */
+  os_cs_type                    intent_q_cs;
+
+  /* Event that glink_tx waits on and blocks until remote rx_intents
+  * are available */
+  os_event_type                 rm_intent_avail_evt;
+
+  /* Size of requested intent that this channel wait on */
+  size_t                        rm_intent_req_size;
+
+  /* Linked list of remote Rx intents. Data can be transmitted only when
+  * remote intents are available */
+  smem_list_type                remote_intent_q;
+
+  /* Linked list of remote Rx intents which local GLink core has used to
+  * transmit data, and are pending Tx complete */
+  smem_list_type                remote_intent_pending_tx_q;
+
+  /* Linked list of local Rx intents. Data can be received only when
+  * local intents are available */
+  smem_list_type                local_intent_q;
+
+  /* Linked list of remote Rx intents held by the clients */
+  smem_list_type                local_intent_client_q;
+
+  /* Read intent being gathered */
+  glink_rx_intent_type          *cur_read_intent;
+
+} glink_channel_intents_type;
+
+struct glink_channel_ctx {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type           link;
+
+  /* Channel name */
+  char                          name[GLINK_CH_NAME_LEN];
+
+  /* Local channel ID */
+  uint32                        lcid;
+
+  /* Remote Channel ID */
+  uint32                        rcid;
+
+  /* Channel state */
+  glink_ch_state_type           state;
+
+  /* Channel local control signal state */
+  uint32                        local_sigs;
+
+  /* Channel remote control signal state */
+  uint32                        remote_sigs;
+
+  /* Critical section to protect tx operations */
+  os_cs_type                    tx_cs;
+
+  /* channel intent collection */
+  glink_channel_intents_type    *pintents;
+
+  /* Interface pointer with with this channel is registered */
+  glink_transport_if_type       *if_ptr;
+
+  /** Private data for client to maintain context. This data is passed back
+   * to client in the notification callbacks */
+  const void                    *priv;
+
+  /** Data receive notification callback */
+  glink_rx_notification_cb      notify_rx;
+
+  /** Vector receive notification callback */
+  glink_rxv_notification_cb      notify_rxv;
+
+  /** Data transmit notification callback */
+  glink_tx_notification_cb      notify_tx_done;
+
+  /** GLink channel state notification callback */
+  glink_state_notification_cb   notify_state;
+
+  /** Intent request from the remote side */
+  glink_notify_rx_intent_req_cb notify_rx_intent_req;
+
+  /** New intent arrival from the remote side */
+  glink_notify_rx_intent_cb     notify_rx_intent;
+
+  /** Control signal change notification - Invoked when remote side
+   *  alters its control signals */
+  glink_notify_rx_sigs_cb       notify_rx_sigs;
+
+  /** rx_intent abort notification. This callback would be invoked for
+  *  every rx_intent that is queued with GLink core at the time the
+  *  remote side or local side decides to close the port. Optional */
+  glink_notify_rx_abort_cb      notify_rx_abort;
+
+  /** tx abort notification. This callback would be invoked if client
+  *   had queued a tx buffer with glink and it had not been transmitted i.e.
+  *   tx_done callback has not been called for this buffer and remote side
+  *   or local side closed the port. Optional */
+  glink_notify_tx_abort_cb      notify_tx_abort;
+
+  /* glink transport if pointer for preferred channel */
+  glink_transport_if_type       *req_if_ptr;
+
+  /* reference count for no of times channel open/close has been called */
+  uint32                        ref_count;
+
+  /* flag to check if channel is marked for deletion
+   * This is workaround to prevent channel migration algorithm from finding channel
+   * which should be closed but has not been closed yet. This case occurs when glink_close
+   * is called for closing channel on initial xport and it is being opened on other xport.
+   * This may lead to remote side opening channel on neogitated xport from which local side
+   * will get remote open again. In this case channel to be closed will be found for negotiation
+   * on initial xport again and channel migration algorithm will be triggered(again)  */
+  boolean                       tag_ch_for_close;
+
+  /* save glink open config options */
+  uint32 ch_open_options;
+};
+
+
+typedef struct _glink_mem_log_entry_type {
+  const char *func;
+  uint32 line;
+  glink_log_event_type type;
+  const char *msg;
+  const char *xport;
+  const char *remote_ss;
+  uint32 param;
+} glink_mem_log_entry_type;
+
+/* Structure to store link notification callbacks */
+typedef struct {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type       link;
+
+  const char*               xport;         /* NULL = any transport */
+  const char*               remote_ss;     /* NULL = any subsystem */
+  glink_link_state_notif_cb link_notifier; /* Notification callback */
+  void                      *priv;         /* Notification priv ptr */
+} glink_link_notif_data_type;
+
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+extern os_cs_type *glink_transport_q_cs;
+extern const char *glink_hosts_supported[GLINK_NUM_HOSTS];
+extern smem_list_type glink_registered_transports[];
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_link_up
+
+DESCRIPTION   Indicates that transport is now ready to start negotiation
+              using the v0 configuration
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_link_up
+(
+  glink_transport_if_type *if_ptr
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version
+
+DESCRIPTION   Receive transport version for remote-initiated version
+              negotiation
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version   Remote Version
+
+            features  Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_version_ack
+
+DESCRIPTION   Receive ACK to previous glink_transport_if::tx_cmd_version
+              command
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            version   Remote Version
+
+            features  Remote Features
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_version_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  version,
+  uint32                  features
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_open
+
+DESCRIPTION   Receive remote channel open request; Calls
+              glink_transport_if:: tx_cmd_ch_remote_open_ack as a result
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+            *name     String name for logical channel
+
+            prio      requested xport priority from remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_open
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  rcid,
+  const char              *name,
+  glink_xport_priority    prio
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_open_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if:: tx_cmd_ch_open
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid      Local Channel ID
+
+            prio      Negotiated xport priority obtained from remote side
+                      after negotiation happened on remote side
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_open_ack
+(
+  glink_transport_if_type *if_ptr,
+  uint32                  lcid,
+  glink_xport_priority    prio
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_close_ack
+
+DESCRIPTION   This function is invoked by the transport in response to
+              glink_transport_if_type:: tx_cmd_ch_close
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            lcid      Local Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_close_ack
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid     /* Local channel ID */
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_ch_remote_close
+
+DESCRIPTION   Remote channel close request; will result in sending
+              glink_transport_if_type:: tx_cmd_ch_remote_close_ack
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_close
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+);
+
+/*===========================================================================
+FUNCTION      glink_ch_state_local_trans
+
+DESCRIPTION   Process local state transition
+
+ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
+                      for each edge
+
+            rcid      Remote Channel ID
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_ch_state_local_trans
+(
+  glink_transport_if_type  *if_ptr,  /* Pointer to the interface instance */
+  uint32                   lcid,     /* Local channel ID */
+  glink_ch_state_type      new_state /* New local channel state */
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_put_pkt_ctx
+
+DESCRIPTION   Transport invokes this call to receive a packet fragment (must
+              have previously received an rx_cmd_rx_data packet)
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            *intent_ptr  Pointer to the intent fragment
+
+            complete     True if pkt is complete
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_put_pkt_ctx
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  glink_rx_intent_type    *intent_ptr, /* Fragment ptr */
+  boolean                 complete     /* True if pkt is complete */
+);
+
+/*===========================================================================
+FUNCTION      glink_rx_cmd_remote_sigs
+
+DESCRIPTION   Transport invokes this call to inform GLink of remote side
+              changing its control signals
+
+ARGUMENTS   *if_ptr      Pointer to interface instance; must be unique
+                         for each edge
+
+            rcid         Remote Channel ID
+
+            remote_sigs  Remote signal state.
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_rx_cmd_remote_sigs
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  rcid,       /* Remote channel ID */
+  uint32                  remote_sigs /* Remote control signals */
+);
+
+/*===========================================================================
+FUNCTION      glink_tx_resume
+
+DESCRIPTION   If transport was full and could not continue a transmit
+              operation, then it will call this function to notify the core
+              that it is ready to resume transmission.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_tx_resume
+(
+  glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+/*===========================================================================
+FUNCTION      glink_set_core_version
+
+DESCRIPTION   Sets the core version used by the transport; called after
+              completing negotiation.
+
+ARGUMENTS   *if_ptr    Pointer to interface instance; must be unique
+                       for each edge
+
+             version   Negotiated transport version
+
+RETURN VALUE  None.
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glink_set_core_version
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version  /* Version */
+);
+
+/*===========================================================================
+                           CHANNEL CONTEXT APIS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glinki_ch_is_fully_opened
+
+DESCRIPTION   Determine if both the local and remote channel state is fully
+              open
+
+ARGUMENTS     *cfg_ptr   - Pointer to channel context
+
+RETURN VALUE  True if fully opened, FALSE otherwise.
+
+SIDE EFFECTS  None
+===========================================================================*/
+boolean glinki_ch_is_fully_opened
+(
+  glink_channel_ctx_type *ctx
+);
+
+
+/*===========================================================================
+FUNCTION      glinki_ch_push_local_rx_intent
+
+DESCRIPTION   Create and push a local receive intent to internal list
+
+ARGUMENTS     *cfg_ptr   - Pointer to channel context
+
+              *pkt_priv  - Client-provided opaque data
+
+              size       - Size of Receive Intent
+
+RETURN VALUE  Pointer to the new intent
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_push_local_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  const void             *pkt_priv,
+  size_t                 size
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_get_local_rx_intent
+
+DESCRIPTION   Lookup a local receive intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              liid        - Local Receive Intent ID
+
+RETURN VALUE  Pointer to the intent or NULL if not match is found.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_get_local_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  uint32                 liid
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_remove_local_rx_intent
+
+DESCRIPTION   Removes Local Receive Intent ID
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              liid        - Local Receive Intent ID
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_remove_local_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  uint32                 liid
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_set_local_rx_intent_notified
+
+DESCRIPTION   Sets the state of the intent as client-notified
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *intent_ptr - Pointer to the receive intent
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_set_local_rx_intent_notified
+(
+  glink_channel_ctx_type *ctx,
+  glink_rx_intent_type   *intent_ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_get_local_rx_intent_notified
+
+DESCRIPTION   Lookup a Local Receive Intent ID that is in the client-notified
+              state
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *ptr        - Data pointer of receive buffer from client
+                            (passed in through glink_rx_done)
+
+RETURN VALUE  Pointer to the intent or NULL if not match is found.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_get_local_rx_intent_notified
+(
+  glink_channel_ctx_type *ctx,
+  void                   *ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_remove_local_rx_intent_notified
+
+DESCRIPTION   Removes the Local Receive Intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *intent_ptr - Pointer to the receive intent
+
+RETURN VALUE  New channel context or NULL
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_channel_ctx_type* glinki_ch_remove_local_rx_intent_notified
+(
+  glink_channel_ctx_type *ctx,
+  glink_rx_intent_type   *intent_ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_push_remote_rx_intent
+
+DESCRIPTION   Adds a new Remote Receive Intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              size        - Size of the Remote Receive Intent
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_push_remote_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  size_t                 size
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_pop_remote_rx_intent
+
+DESCRIPTION   Removes a Remote Receive Intent
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              size        - Size of the Remote Receive Intent
+
+              *riid_ptr   - Pointer to the Remote Receive Intent
+
+RETURN VALUE  Standard GLink Err code.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_err_type glinki_ch_pop_remote_rx_intent
+(
+  glink_channel_ctx_type *ctx,
+  size_t                size,
+  uint32                *riid_ptr
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_get_tx_pending_remote_done
+
+DESCRIPTION   Lookup packet transmit context for a packet that is waiting for
+              the remote-done notification.
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              riid        - Remote Receive Intent ID
+
+RETURN VALUE  Pointer to the transmit packet context or NULL if not match is
+              found.
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_core_tx_pkt_type* glinki_ch_get_tx_pending_remote_done
+(
+  glink_channel_ctx_type *ctx,
+  uint32                 riid
+);
+
+/*===========================================================================
+FUNCTION      glinki_ch_remove_tx_pending_remote_done
+
+DESCRIPTION   Removes a packet transmit context for a packet that is waiting
+              for the remote-done notification.
+
+ARGUMENTS     *cfg_ptr    - Pointer to channel context
+
+              *tx_pkt     - Pointer to the packet context to remove
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+void glinki_ch_remove_tx_pending_remote_done
+(
+  glink_channel_ctx_type       *ctx,
+  glink_core_tx_pkt_type       *tx_pkt
+);
+
+/*===========================================================================
+FUNCTION      glinki_add_ch_to_xport
+
+DESCRIPTION   Add remote/local channel context to xport open channel queue
+
+ARGUMENTS     *if_ptr            - Pointer to xport if on which channel is to
+                                   be opened
+              *req_if_ptr        - Pointer to xport if on which channel
+			                       actually wants to open
+              *ch_ctx            - channel context
+              **allocated_ch_ctx - Pointer to channel context pointer
+              local_open         - flag to determine if channel is opened
+			                       locally or remotely
+              migration state    - flag to identify whether channel migration
+			                       negotiation is done
+                                   TRUE - negotiation is not complete
+                                   FALSE - negotiation is complete.
+								   channel is being opened on same xport as negotiated
+              prio               - negotiated xport priority
+			                       (used to send priority via remote_open_ack to
+								    remote side)
+              *tx_pkt            - Pointer to the packet context to remove
+
+RETURN VALUE  None
+
+SIDE EFFECTS  None
+===========================================================================*/
+glink_err_type glinki_add_ch_to_xport
+(
+  glink_transport_if_type  *if_ptr,
+  glink_transport_if_type  *req_if_ptr,
+  glink_channel_ctx_type   *ch_ctx,
+  glink_channel_ctx_type   **allocated_ch_ctx,
+  unsigned int              local_open,
+  boolean                  migration_state,
+  glink_xport_priority     prio
+);
+
+void glink_mem_log
+(
+  const char *func,
+  uint32 line,
+  glink_log_event_type type,
+  const char *msg,
+  const char *xport,
+  const char *remote_ss,
+  uint32 param
+);
+
+/*===========================================================================
+FUNCTION      glink_core_setup
+===========================================================================*/
+/**
+
+  Initializes internal core functions based on the transport capabilities.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup(glink_transport_if_type *if_ptr);
+
+/*===========================================================================
+FUNCTION      glink_core_setup_full_xport
+===========================================================================*/
+/**
+
+  Initializes internal core functions for the full-featured transport.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup_full_xport(glink_transport_if_type *if_ptr);
+
+/*===========================================================================
+FUNCTION      glink_core_setup_intentless_xport
+===========================================================================*/
+/**
+
+  Initializes internal core functions for the intentless transport.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_setup_intentless_xport(glink_transport_if_type *if_ptr);
+
+#endif /* GLINK_INTERNAL_H */
diff --git a/platform/msm_shared/include/glink_os_type.h b/platform/msm_shared/include/glink_os_type.h
new file mode 100644
index 0000000..091ad05
--- /dev/null
+++ b/platform/msm_shared/include/glink_os_type.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2015, 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 OS_TYPE_H
+#define OS_TYPE_H
+
+/*===========================================================================
+
+                      G-Link OS Specific types/functions
+
+===========================================================================*/
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include <string.h>
+#include <assert.h>
+
+/*===========================================================================
+                        MACRO DEFINITIONS
+===========================================================================*/
+
+#define OS_LOG_INIT( ) glink_os_log_init()
+
+/*===========================================================================
+                        TYPE DEFINITIONS
+===========================================================================*/
+#define DALSYS_SYNC_OBJ_SIZE_BYTES           40
+#define DALSYS_EVENT_OBJ_SIZE_BYTES          80
+
+typedef bool boolean;
+typedef uint64_t uint64;
+typedef uint32_t uint32;
+typedef long int32;
+#define TRUE 1
+#define FALSE 0
+
+typedef struct DALSYSEventObj  DALSYSEventObj;
+
+struct DALSYSEventObj
+{
+  unsigned long long _bSpace[DALSYS_EVENT_OBJ_SIZE_BYTES/sizeof(unsigned long long)];
+};
+
+
+typedef struct DALSYSSyncObj  DALSYSSyncObj;
+struct DALSYSSyncObj
+{
+  unsigned long long _bSpace[DALSYS_SYNC_OBJ_SIZE_BYTES/sizeof(unsigned long long)];
+};
+
+typedef DALSYSSyncObj os_cs_type;
+
+typedef void ( *os_timer_cb_fn )( void *cb_data );
+
+typedef struct
+{
+  void * dal_event;
+  DALSYSEventObj    dal_obj_memory;
+}os_event_type;
+
+typedef void ( *os_isr_cb_fn )( void *cb_data );
+
+typedef struct os_ipc_intr_struct
+{
+  uint32_t processor;
+  uint32_t irq_out;
+} os_ipc_intr_type;
+
+#endif /* OS_TYPE_H */
diff --git a/platform/msm_shared/include/glink_os_utils.h b/platform/msm_shared/include/glink_os_utils.h
new file mode 100644
index 0000000..e0a1613
--- /dev/null
+++ b/platform/msm_shared/include/glink_os_utils.h
@@ -0,0 +1,258 @@
+/* Copyright (c) 2015, 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 OS_UTILS_H
+#define OS_UTILS_H
+
+/*===========================================================================
+
+                      G-Link OS Specific types/functions
+
+===========================================================================*/
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include <glink_os_type.h>
+
+/*===========================================================================
+                        MACRO DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                        TYPE DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      glink_os_cs_init
+===========================================================================*/
+/**
+  Initializes a Critical Section
+
+  @param[in]  cs   pointer to critical section object allocated by caller.
+
+  @return
+  TRUE if critical section was initialized, FALSE otherwise
+*/
+/*=========================================================================*/
+bool glink_os_cs_init( os_cs_type *cs );
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_acquire
+===========================================================================*/
+/**
+  Lock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_acquire( os_cs_type *cs );
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_release
+===========================================================================*/
+/**
+  Unlock a critical section
+
+  @param[in]  cs   Pointer the the critical section
+
+  @return     None.
+*/
+/*=========================================================================*/
+void glink_os_cs_release( os_cs_type *cs );
+
+/*===========================================================================
+  FUNCTION      glink_os_cs_create
+===========================================================================*/
+/**
+  Create and initializesa Critical Section
+
+  @return     The critical section.
+*/
+/*=========================================================================*/
+os_cs_type *glink_os_cs_create( void );
+
+/*===========================================================================
+  FUNCTION  glink_os_malloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap.  The region should be
+  freed using \c glink_os_free when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_malloc( size_t size );
+
+/*===========================================================================
+  FUNCTION  glink_os_calloc
+===========================================================================*/
+/**
+  Dynamically allocate a region of memory from the heap and initialize with
+  the zeroes.  The region should be freed using \c glink_os_free
+  when no longer used.
+
+  @param[in]  size   The number of bytes to be allocated.
+
+  @return    The pointer to the region of memory that was allocated.
+             NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_calloc( size_t size );
+
+/*===========================================================================
+  FUNCTION  glink_os_free
+===========================================================================*/
+/**
+  Free a region of memory that was allocated by \c glink_os_malloc.
+
+  @param[in] pMem    The reference to the region of memory to be freed.
+
+  @return    NA
+*/
+/*=========================================================================*/
+void glink_os_free( void *pMem );
+
+/*===========================================================================
+  FUNCTION  glink_os_string_copy
+===========================================================================*/
+/**
+  Copies the source string into the destination buffer until
+  size is reached, or until a '\0' is encountered.  If valid,
+  the destination string will always be NULL deliminated.
+
+  @param[in] dst    The destination string, contents will be updated.
+  @param[in] src    The source string
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+char *glink_os_string_copy(char *dst, const char *src, uint32_t size);
+
+/*===========================================================================
+  FUNCTION  glink_os_string_compare
+===========================================================================*/
+/**
+  Compares two strings delimited by size or NULL character.
+
+  @param[in] s1     String 1
+  @param[in] s2     String 2
+  @param[in] size   The maximum number of characters to compare
+
+  @return
+  0 if strings are identical (up to size characters), non-zero otherwise
+*/
+/*==========================================================================*/
+long glink_os_string_compare( const char *s1, const char *s2, uint32_t size );
+
+/*===========================================================================
+  FUNCTION  glink_os_copy_mem
+===========================================================================*/
+/**
+  Copies the source buffer into the destination buffer.
+
+  @param[in] dst    The destination, contents will be updated.
+  @param[in] src    The source
+  @param[in] size   The maximum copy size (size of dst)
+
+  @return
+  The destination string pointer, dst.
+*/
+/*==========================================================================*/
+void glink_os_copy_mem(void *dst, const void *src, uint32_t size);
+
+/*===========================================================================
+  FUNCTION      glink_os_register_isr
+===========================================================================*/
+/**
+  Registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to register for
+  @param[in]  isr       Callback to be invoked when interrupt fires
+  @param[in]  cb_data   Data to be provided to the callback
+
+  @return     true if registration was successful, false otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_register_isr( uint32_t irq_in, os_isr_cb_fn isr, void *cb_data );
+
+/*===========================================================================
+  FUNCTION      glink_os_deregister_isr
+===========================================================================*/
+/**
+  De-registers ISR with the interrupt controller
+
+  @param[in]  irq_in    Interrupt to deregister for
+
+  @return     TRUE if de-registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_deregister_isr( uint32_t irq_in );
+
+/*===========================================================================
+  FUNCTION      glink_os_enable_interrupt
+===========================================================================*/
+/**
+  Enables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to enable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_enable_interrupt( uint32_t irq_in );
+
+/*===========================================================================
+  FUNCTION      glink_os_disable_interrupt
+===========================================================================*/
+/**
+  Disables the interrupt in the interrupt controller
+
+  @param[in]  irq_in    Interrupt to disable
+
+  @return     TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_disable_interrupt( uint32_t irq_in );
+
+bool glink_os_log_init( void );
+
+#endif /* OS_UTILS_H */
diff --git a/platform/msm_shared/include/glink_rpm.h b/platform/msm_shared/include/glink_rpm.h
new file mode 100644
index 0000000..c7cfdeb
--- /dev/null
+++ b/platform/msm_shared/include/glink_rpm.h
@@ -0,0 +1,108 @@
+/* Copyright (c) 2015, 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 GLINK_RPM_H
+#define GLINK_RPM_H
+
+/**
+ * @file glink_rpm.h
+ *
+ * Public API for the GLink-RPM
+ */
+
+/** \defgroup glink GLink
+ * \ingroup SMD
+ *
+ * GLink reliable, in-order, datagram-based interprocessor communication
+ * over a set of supported transport (Shared Memory, UART, BAM, HSIC)
+ *
+ * All ports preserve message boundaries across the interprocessor channel; one
+ * write into the port exactly matches one read from the port.
+ */
+/*@{*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "glink_os_utils.h"
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+
+/*================= RESTRICTED API ==========================*/
+/** Note that these API are only supported for RPM client. No other
+ * client may use these as a generic API as the underlying implementation
+ * works only for RPM ports */
+
+
+/**
+ * This API allows the RPM client to poll the transport for any new data
+ * that might have come in. It would *usually* be used when incoming interrupts
+ * are disabled.
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_rx_poll
+(
+  glink_handle_type handle
+);
+
+/**
+ * This API allows the RPM client to mask/unmask rx interrupts
+ *
+ * @param[in]   handle      GLink handle associated with the logical channel
+ *
+ * @param[in]   mask        Whether to mask or un-mask the incoming interrupt
+ *
+ * @param[in]   platform_struct Any platform specific into that transport may
+                                require
+ *
+ * @return      Standard GLink error codes
+ *
+ * @sideeffects  None
+ */
+glink_err_type glink_rpm_mask_rx_interrupt
+(
+  glink_handle_type handle,
+  boolean           mask,
+  void              *platform_struct
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //GLINK_RPM_H
+
diff --git a/platform/msm_shared/include/glink_transport_if.h b/platform/msm_shared/include/glink_transport_if.h
new file mode 100644
index 0000000..da9e2bd
--- /dev/null
+++ b/platform/msm_shared/include/glink_transport_if.h
@@ -0,0 +1,353 @@
+/* Copyright (c) 2015, 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 GLINK_TRANSPORT_IF_H
+#define GLINK_TRANSPORT_IF_H
+
+/**
+ * @file glink_transport_if.h
+ *
+ * Public API for the GLink Core to transport interface
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include <smem_list.h>
+#include <glink_os_utils.h>
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+/* GLink transport capability bit definitions */
+/* Whether transport supports signalling */
+#define GLINK_CAPABILITY_SIG_SUPPORT 0x00000001
+/* Intentless mode of operation */
+#define GLINK_CAPABILITY_INTENTLESS  0x00000002
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+/* forward declaration */
+struct glink_transport_if;
+typedef struct glink_transport_if   glink_transport_if_type;
+
+struct glink_core_xport_ctx;
+typedef struct glink_core_xport_ctx glink_core_xport_ctx_type;
+
+struct glink_core_if;
+typedef struct glink_core_if        glink_core_if_type;
+
+struct glink_rx_intent;
+typedef struct glink_rx_intent      glink_rx_intent_type;
+
+/* Priority of transports registered with glink */
+typedef enum {
+  GLINK_XPORT_SMEM = 100,
+  GLINK_XPORT_RPM = 100,
+  GLINK_XPORT_SMD = 200,
+  GLINK_XPORT_CP_ENGINE = 300,
+  GLINK_MIN_PRIORITY = GLINK_XPORT_CP_ENGINE,
+  GLINK_INVALID_PRIORITY
+} glink_xport_priority;
+
+/** Glink core -> Xport pkt type definition */
+typedef struct {
+  void       *data;      /* Pointer to the data buffer to be transmitted */
+  const void *pkt_priv;  /* Per packet private data */
+  uint32     iid;        /* Remote intent ID being used to transmit data */
+  size_t     size;       /* Size of data buffer */
+  size_t     size_remaining; /* Size left to transmit */
+  void       *iovec;      /* Pointer to the data buffer to be transmitted */
+  glink_buffer_provider_fn vprovider; /* Buffer provider for virtual space */
+  glink_buffer_provider_fn pprovider; /* Buffer provider for physical space */
+}glink_core_tx_pkt_type;
+
+/** Transmit a version command for local negotiation. The transport would call
+ *  glink_transport_if_type::rx_cmd_version_ack callback as a result */
+typedef void (*tx_cmd_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Transmit a version ack for remote nogotiation */
+typedef void (*tx_cmd_version_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Signals the negotiation is complete and transport can now do version
+ *  specific initialization. Return uint32 transport capabilities bit field */
+typedef uint32 (*set_version_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  version, /* Version */
+  uint32                  features /* Features */
+);
+
+/** Sends OPEN command to transport for transport to do whatever it deems
+ *  necessary to open a GLink logical channel.
+ *  GLink Core expects glink_transport_if_type::rx_cmd_ch_open_ack to be called
+ *  as a result of channel opening. */
+typedef glink_err_type (*tx_cmd_ch_open_fn)
+(
+  glink_transport_if_type *if_ptr,/* Pointer to the interface instance */
+  uint32                  lcid,   /* Local channel ID */
+  const char              *name,  /* String name for the logical channel */
+  glink_xport_priority    prio
+);
+
+/** Sends CLOSE command to transport for transport to do whatever it deems
+ *  necessary to close the specified GLink logical channel.
+ *  GLink Core expects glink_transport_if_type::rx_cmd_ch_close_ack to be
+ *  called as a result of channel closing. */
+typedef glink_err_type (*tx_cmd_ch_close_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                     lcid  /* Local channel ID */
+);
+
+/** Sends the remote open ACK command in response to receiving
+ *  glink_core_if_type::rx_cmd_ch_remote_open */
+typedef void (*tx_cmd_ch_remote_open_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid,    /* Remote channel ID */
+  glink_xport_priority    prio
+);
+
+/** Sends the remote close ACK command in response to receiving
+ *  glink_core_if_type::rx_cmd_ch_remote_close */
+typedef void (*tx_cmd_ch_remote_close_ack_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  rcid     /* Remote channel ID */
+);
+
+/** Allocates a receive buffer for the local rx intent */
+typedef glink_err_type (*allocate_rx_intent_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  size_t                  size,       /* Size of Rx intent */
+  glink_rx_intent_type    *intent_ptr /* Intent ptr */
+);
+
+/** Deallocates a receive buffer for the local rx intent */
+typedef glink_err_type (*deallocate_rx_intent_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  glink_rx_intent_type    *intent_ptr /* Intent ptr */
+);
+
+/** Send receive intent ID for a given channel */
+typedef glink_err_type (*tx_cmd_local_rx_intent_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  size_t                  size,    /* Size of Rx intent */
+  uint32                  liid     /* Local indent ID */
+);
+
+/** Send receive done command for an intent for the specified channel */
+typedef void(*tx_cmd_local_rx_done_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  uint32                  liid,    /* Local indent ID */
+  boolean                 reuse    /* Reuse indent */
+);
+
+/** Send a data packet to the transport to be transmitted over the specified
+ *  channel */
+typedef glink_err_type (*tx_fn)
+(
+  glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+  uint32                  lcid,    /* Local channel ID */
+  glink_core_tx_pkt_type  *pctx    /* Packet to be transmitted */
+);
+
+/** Send a intent request to the remote side to have it queue more rx intents
+ *  to unblock this end's tx operation */
+typedef glink_err_type (*tx_cmd_rx_intent_req_fn)
+(
+  glink_transport_if_type *if_ptr,   /* Pointer to the interface instance */
+  uint32                  lcid,      /* Local channel ID */
+  size_t                  size       /* Size of the requested intent */
+);
+
+/** Send the ACK back for the rx intent request send by the other side,
+ *  specifynig whether the request was granted ot not */
+typedef glink_err_type (*tx_cmd_remote_rx_intent_req_ack_fn)
+(
+  glink_transport_if_type *if_ptr,   /* Pointer to the interface instance */
+  uint32                  lcid,      /* Local channel ID */
+  boolean                 granted    /* Whether of not the intent request was
+                                        granted */
+);
+
+/** Sets the local channel signals as per the specified 32-bit mask.
+ *  Transport may also send the 32-bit value as-is to the remote side. */
+typedef glink_err_type (*tx_cmd_set_sigs_fn)
+(
+  glink_transport_if_type *if_ptr,   /* Pointer to the interface instance */
+  uint32                  lcid,      /* Local channel ID */
+  uint32                  sigs       /* Whether of not the intent request was
+                                        granted */
+);
+
+/** Lets the XAL know of SSR on that edge. */
+typedef glink_err_type (*ssr_fn)
+(
+  glink_transport_if_type *if_ptr   /* Pointer to the interface instance */
+);
+
+/** Trigger a poll for any rx data / signals on transport. */
+typedef glink_err_type (*poll_fn)
+(
+  glink_transport_if_type *if_ptr   /* Pointer to the interface instance */
+);
+
+/** Mask/Unmask rx interrupt associated with transport. */
+typedef glink_err_type (*mask_rx_irq_fn)
+(
+  glink_transport_if_type *if_ptr,  /* Pointer to the interface instance */
+  boolean                 mask      /* TRUE-mask, FALSE=unmask */
+);
+
+/** Wait for the link to go down. */
+typedef boolean (*wait_link_down_fn)
+(
+  glink_transport_if_type *if_ptr   /* Pointer to the interface instance */
+);
+
+
+/**
+ * Data Structure for GLink Core to call into transport API
+ *
+ * This structure is used by the GLink core to operate transport
+ * This set of function pointers to to be filled in by the transport
+ * abstraction layer.
+ */
+struct glink_transport_if {
+  /* Link needed for use with list APIs.  Must be at the head of the struct */
+  smem_list_link_type                link;
+
+  /** Transmit a version command for local negotiation. The transport would
+   * call glink_transport_if_type::rx_cmd_version_ack callback as a result */
+  tx_cmd_version_fn                  tx_cmd_version;
+
+  /** Transmit a version ack for remote nogotiation */
+  tx_cmd_version_ack_fn              tx_cmd_version_ack;
+
+  /** Signals the negotiation is complete and transport can now do version
+   *  specific initialization */
+  set_version_fn                     set_version;
+
+
+  /** Sends OPEN command to transport for transport to do whatever it deems
+   *  necessary to open a GLink logical channel.
+   *  GLink Core expects glink_transport_if_type::rx_cmd_ch_open_ack to be
+   *  called as a result of channel opening. */
+  tx_cmd_ch_open_fn                  tx_cmd_ch_open;
+
+
+  /** Sends CLOSE command to transport for transport to do whatever it deems
+   *  necessary to close the specified GLink logical channel.
+   *  GLink Core expects glink_transport_if_type::rx_cmd_ch_close_ack to be
+   *  called as a result of channel closing. */
+  tx_cmd_ch_close_fn                 tx_cmd_ch_close;
+
+
+  /** Sends the remote open ACK command in response to receiving
+   *  glink_core_if_type::rx_cmd_ch_remote_open */
+  tx_cmd_ch_remote_open_ack_fn       tx_cmd_ch_remote_open_ack;
+
+  /** Sends the remote close ACK command in response to receiving
+   *  glink_core_if_type::rx_cmd_ch_remote_close */
+  tx_cmd_ch_remote_close_ack_fn      tx_cmd_ch_remote_close_ack;
+
+  /** Allocates a receive vector buffer for the local rx intent */
+  allocate_rx_intent_fn               allocate_rx_intent;
+
+  /** Deallocates a receive vector buffer for the local rx intent */
+  deallocate_rx_intent_fn             deallocate_rx_intent;
+
+  /** Send receive intent ID for a given channel */
+  tx_cmd_local_rx_intent_fn          tx_cmd_local_rx_intent;
+
+
+  /** Send receive done command for an intent for the specified channel */
+  tx_cmd_local_rx_done_fn            tx_cmd_local_rx_done;
+
+
+  /** Send a data packet to the transport to be transmitted over the specified
+   *  channel */
+  tx_fn                              tx;
+
+   /** Send request to the remote to queue more rx intents */
+  tx_cmd_rx_intent_req_fn            tx_cmd_rx_intent_req;
+
+  /** Send ACK to the remote side's request to queue more rx intents */
+  tx_cmd_remote_rx_intent_req_ack_fn tx_cmd_remote_rx_intent_req_ack;
+
+  /** Sets the local channel signals as per the specified 32-bit mask.
+   *  Transport may also send the 32-bit value as-is to the remote side. */
+  tx_cmd_set_sigs_fn                 tx_cmd_set_sigs;
+
+  /** Lets the XAL know of SSR on that edge. */
+  ssr_fn                             ssr;
+
+  /** Trigger a poll for any rx data / signals on transport. */
+  poll_fn                            poll;
+
+  /** Mask/Unmask rx interrupt associated with transport */
+  mask_rx_irq_fn                     mask_rx_irq;
+
+  /** Wait for the link to go down. */
+  wait_link_down_fn                  wait_link_down;
+
+  /** Transport specific data pointer that transport may choose fill in
+   * with some data */
+  glink_core_xport_ctx_type          *glink_core_priv;
+
+  /** GLINK core interface pointer associated with this transport interface */
+  glink_core_if_type                 *glink_core_if_ptr;
+
+  /* glink transport priority */
+  glink_xport_priority                glink_priority;
+};
+
+#endif //GLINK_TRANSPORT_IF_H
diff --git a/platform/msm_shared/include/glink_vector.h b/platform/msm_shared/include/glink_vector.h
new file mode 100644
index 0000000..863c19a
--- /dev/null
+++ b/platform/msm_shared/include/glink_vector.h
@@ -0,0 +1,155 @@
+/* Copyright (c) 2015, 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 GLINK_VECTOR_H
+#define GLINK_VECTOR_H
+
+/*===========================================================================
+
+                    GLink Vector Header File
+
+===========================================================================*/
+
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include "glink.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+                        FEATURE DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                           MACRO DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                           TYPE DEFINITIONS
+===========================================================================*/
+typedef struct _glink_iovector_element_type {
+  struct _glink_iovector_element_type *next;
+  void* data;
+  size_t start_offset;
+  size_t size;
+} glink_iovector_element_type;
+
+typedef struct _glink_iovector_type {
+  glink_iovector_element_type *vlist; /* virtual buffers list */
+  glink_iovector_element_type *vlast; /* last accessed element in vlist */
+  glink_iovector_element_type *plist; /* physical buffers list */
+  glink_iovector_element_type *plast; /* last accessed element in plist */
+} glink_iovector_type;
+
+/*===========================================================================
+                              GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+                    LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+                    EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION      glink_dummy_tx_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a non-vectored buffer.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_dummy_tx_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+);
+
+/*===========================================================================
+FUNCTION      glink_dummy_rx_vprovider
+===========================================================================*/
+/**
+
+  Buffer provider for virtual space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     virtual address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_vprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+);
+
+/*===========================================================================
+FUNCTION      glink_dummy_rx_pprovider
+===========================================================================*/
+/**
+
+  Buffer provider for physical space that operates on a Glink iovec.
+
+  @param[in]  iovec   Pointer to the dummy vector.
+  @param[in]  offset  Offset within the dummy vector.
+  @param[out] size    Size of the provied buffer.
+
+  @return     physical address of the buffer.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void* glink_iovec_pprovider
+(
+  void*  iovec,
+  size_t offset,
+  size_t *size
+);
+
+#endif /* GLINK_VECTOR_H */
diff --git a/platform/msm_shared/include/mmc_sdhci.h b/platform/msm_shared/include/mmc_sdhci.h
index 1612e61..95d636e 100644
--- a/platform/msm_shared/include/mmc_sdhci.h
+++ b/platform/msm_shared/include/mmc_sdhci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -101,6 +101,7 @@
 #define MMC_USR_WP                                171
 #define MMC_ERASE_TIMEOUT_MULT                    223
 #define MMC_HC_ERASE_GRP_SIZE                     224
+#define MMC_PARTITION_CONFIG                      179
 
 /* Values for ext csd fields */
 #define MMC_HS_TIMING                             0x1
@@ -117,6 +118,13 @@
 #define MMC_HC_ERASE_MULT                         (512 * 1024)
 #define RST_N_FUNC_ENABLE                         BIT(0)
 
+/* RPMB Related */
+#define RPMB_PART_MIN_SIZE                        (128 * 2014)
+#define RPMB_SIZE_MULT                            168
+#define REL_WR_SEC_C                              222
+#define PARTITION_ACCESS_MASK                     0x7
+#define MAX_RPMB_CMDS                             0x3
+
 /* Command related */
 #define MMC_MAX_COMMAND_RETRY                     1000
 #define MMC_MAX_CARD_STAT_RETRY                   10000
@@ -226,6 +234,12 @@
 #define MMC_CARD_MMC(card) ((card->type == MMC_TYPE_STD_MMC) || \
 							(card->type == MMC_TYPE_MMCHC))
 
+enum part_access_type
+{
+	PART_ACCESS_DEFAULT = 0x0,
+	PART_ACCESS_RPMB = 0x3,
+};
+
 /* CSD Register.
  * Note: not all the fields have been defined here
  */
@@ -292,6 +306,8 @@
 	uint8_t *ext_csd;        /* Ext CSD for the card info */
 	uint32_t raw_csd[4];     /* Raw CSD for the card */
 	uint32_t raw_scr[2];     /* SCR for SD card */
+	uint32_t rpmb_size;      /* Size of rpmb partition */
+	uint32_t rel_wr_count;   /* Reliable write count */
 	struct mmc_cid cid;      /* CID structure */
 	struct mmc_csd csd;      /* CSD structure */
 	struct mmc_sd_scr scr;   /* SCR structure */
@@ -337,4 +353,6 @@
 void mmc_put_card_to_sleep(struct mmc_device *dev);
 /* API: Change the driver type of the card */
 bool mmc_set_drv_type(struct sdhci_host *host, struct mmc_card *card, uint8_t drv_type);
+/* API: Send the read & write command sequence to rpmb */
+uint32_t mmc_sdhci_rpmb_send(struct mmc_device *dev, struct mmc_command *cmd);
 #endif
diff --git a/platform/msm_shared/include/qseecom_lk.h b/platform/msm_shared/include/qseecom_lk.h
new file mode 100644
index 0000000..dd130ed
--- /dev/null
+++ b/platform/msm_shared/include/qseecom_lk.h
@@ -0,0 +1,164 @@
+/* Copyright (c) 2015, 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 _QSEECOM_LK_H_
+#define _QSEECOM_LK_H_
+
+#define MAX_APP_NAME_SIZE  32
+#define QSEECOM_HASH_SIZE  32
+
+/* TZ Diagnostic Area legacy version number */
+#define TZBSP_DIAG_MAJOR_VERSION_LEGACY 2
+
+/*
+ * Log ring buffer position
+ */
+struct tzdbg_log_pos_t {
+	uint16_t wrap;
+	uint16_t offset;
+};
+
+ /*
+ * Log ring buffer
+ */
+struct tzdbg_log_t {
+	struct tzdbg_log_pos_t log_pos;
+	/* open ended array to the end of the 4K IMEM buffer */
+	uint8_t log_buf[];
+};
+struct scm_desc {
+	uint32_t arginfo;
+	uint32_t args[10];
+	uint32_t ret[3];
+	/* private */
+	void *extra_arg_buf;
+	uint64_t x5;
+};
+/*
+ * struct qseecom_register_listener_req -
+ *      for register listener ioctl request
+ * @listener_id - service id (shared between userspace and QSE)
+ * @ifd_data_fd - ion handle
+ * @virt_sb_base - shared buffer base in user space
+ * @sb_size - shared buffer size
+ */
+struct qseecom_register_listener_req {
+	uint32_t listener_id; /* in */
+	void *virt_sb_base; /* in */
+	uint32_t sb_size; /* in */
+};
+
+/*
+ * struct qseecom_send_cmd_req - for send command ioctl request
+ * @cmd_req_len - command buffer length
+ * @cmd_req_buf - command buffer
+ * @resp_len - response buffer length
+ * @resp_buf - response buffer
+ */
+struct qseecom_send_cmd_req {
+	void *cmd_req_buf; /* in */
+	unsigned int cmd_req_len; /* in */
+	void *resp_buf; /* in/out */
+	unsigned int resp_len; /* in/out */
+};
+
+/*
+ * struct qseecom_ion_fd_info - ion fd handle data information
+ * @fd - ion handle to some memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_ion_fd_info {
+	int32_t fd;
+	uint32_t cmd_buf_offset;
+};
+
+/*
+ * struct qseecom_listener_send_resp_req - signal to continue the send_cmd req.
+ * Used as a trigger from HLOS service to notify QSEECOM that it's done with its
+ * operation and provide the response for QSEECOM can continue the incomplete
+ * command execution
+ * @resp_len - Length of the response
+ * @resp_buf - Response buffer where the response of the cmd should go.
+ */
+struct qseecom_send_resp_req {
+	void *resp_buf; /* in */
+	unsigned int resp_len; /* in */
+};
+
+/*
+ * struct qseecom_load_img_data - for sending image length information and
+ * ion file descriptor to the qseecom driver. ion file descriptor is used
+ * for retrieving the ion file handle and in turn the physical address of
+ * the image location.
+ * @mdt_len - Length of the .mdt file in bytes.
+ * @img_len - Length of the .mdt + .b00 +..+.bxx images files in bytes
+ * @ion_fd - Ion file descriptor used when allocating memory.
+ * @img_name - Name of the image.
+*/
+struct qseecom_load_img_req {
+	uint32_t mdt_len; /* in */
+	uint32_t img_len; /* in */
+	int32_t  ifd_data_fd; /* in */
+	char  img_name[MAX_APP_NAME_SIZE]; /* in */
+	int app_id; /* out*/
+};
+
+struct qseecom_set_sb_mem_param_req {
+	int32_t ifd_data_fd; /* in */
+	void *virt_sb_base; /* in */
+	uint32_t sb_len; /* in */
+};
+
+/*
+ * struct qseecom_qseos_version_req - get qseos version
+ * @qseos_version - version number
+ */
+struct qseecom_qseos_version_req {
+	unsigned int qseos_version; /* in */
+};
+
+/*
+ * struct qseecom_qseos_app_load_query - verify if app is loaded in qsee
+ * @app_name[MAX_APP_NAME_SIZE]-  name of the app.
+ * @app_id - app id.
+ */
+struct qseecom_qseos_app_load_query {
+	char app_name[MAX_APP_NAME_SIZE]; /* in */
+	int app_id; /* out */
+};
+
+struct qseecom_send_svc_cmd_req {
+	uint32_t cmd_id;
+	void *cmd_req_buf; /* in */
+	unsigned int cmd_req_len; /* in */
+	void *resp_buf; /* in/out */
+	unsigned int resp_len; /* in/out */
+};
+
+
+#endif /* _QSEECOM_LK_H_ */
diff --git a/platform/msm_shared/include/qseecom_lk_api.h b/platform/msm_shared/include/qseecom_lk_api.h
new file mode 100644
index 0000000..c26da9b
--- /dev/null
+++ b/platform/msm_shared/include/qseecom_lk_api.h
@@ -0,0 +1,189 @@
+/* Copyright (c) 2015, 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 __QSEECOM_LK_API_H_
+#define __QSEECOM_LK_API_H_
+
+#define MAX_APP_NAME_LEN 32
+
+#include <stdint.h>
+/**
+* Qseecom Init
+*	To be called before any calls to qsee secure apps.
+*
+* @return int
+*   Success:	Init succeeded.
+*   Failure:	Error code (negative only).
+*/
+int qseecom_init();
+
+/**
+* Qseecom Tz Init
+*	To be called before any calls to qsee secure apps.
+*
+* @return int
+*   Success:	Tz init succeeded.
+*   Failure:	Error code (negative only).
+*/
+int qseecom_tz_init();
+
+/**
+* Qseecom Exit
+*	To be called before exit of lk.
+*	Once this is called no calls to
+*	Qsee Apps.
+*
+* @return int
+*   Success:	Exit succeeded.
+*   Failure:	Error code (negative only).
+*/
+int qseecom_exit();
+
+/**
+* Start a Secure App
+*
+* @param char* app_name
+*   App name of the Secure App to be started
+*   The app_name provided should be the same
+*   name as the partition/ file and should
+*   be the same name mentioned in TZ_APP_NAME
+*   in the secure app.
+*
+* @return int
+*   Success:	handle to be used for all calls to
+*   			Secure app. Always greater than zero.
+*   Failure:	Error code (negative only).
+*/
+int qseecom_start_app(char *app_name);
+
+/**
+* Shutdown a Secure App
+*
+* @param int handle
+*   Handle  of the Secure App to be shutdown
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_shutdown_app(int handle);
+
+/**
+* Shutdown a Secure App
+*
+* @param int handle
+*   Handle  of the Secure App to send the cmd
+*
+* @param void *send_buf
+*   Pointer to the App request buffer
+*
+* @param uint32_t sbuf_len
+*   Size of the request buffer
+*
+* @param void *resp_buf
+*   Pointer to the App response buffer
+*
+* @param uint32_t rbuf_len
+*   Size of the response buffer
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_send_command(int handle, void *send_buf,
+			uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len);
+
+typedef int (*ListenerCallback)(void*, uint32_t);
+
+/**
+ * @param char* service_name
+ * 	 The name of the listener service.
+ * @param uint32_t  id
+ * 	 The id used to register a listener with
+ * 	 QSEE in the secure side. This id should
+ * 	 be unique.
+ * @param ListenerCallback service_cmd_handler
+ *   This is the service cmd handler, this cb
+ *   is called for a specific service request.
+ *   The input params are,
+ * 		@param void *buf
+ * 		  The shared buffer which contains the
+ * 		  request from the secure side. The service
+ * 		  also updates this buffer with the response.
+ * 		@param uint32_t size
+ * 		  The size of the shared buffer.
+ *      @return int
+ *        Success:	Exit succeeded.
+ *        Failure:	Error code (negative only).
+ */
+struct qseecom_listener_services {
+	char *service_name;
+	uint32_t  id;
+	uint32_t sb_size;
+	ListenerCallback service_cmd_handler;
+};
+
+/**
+* Registers a Listener Service with QSEE
+*  This api should be called after all
+*  service specific initialization is
+*  completed, once this is called the
+*  service_cmd_handler for the service can
+*  be called.
+*
+* @param struct qseecom_listener_services listnr
+*   Listener structure that contains all the info
+*   to register a listener service.
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_register_listener(struct qseecom_listener_services *listnr);
+
+/**
+* De-Registers a Listener Service with QSEE
+*  This api should be called before exiting lk and
+*  all service de-init should be done before calling
+*  the api. service_cmd_handler will not be called
+*  after this api is called.
+*
+* @param uint32_t listnr_id
+*   Pre-defined Listener ID to be de-registered
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_deregister_listener(uint32_t listnr_id);
+
+#endif /* __QSEECOM_API_LK_H_ */
diff --git a/platform/msm_shared/include/qseecomi_lk.h b/platform/msm_shared/include/qseecomi_lk.h
new file mode 100644
index 0000000..ee442be
--- /dev/null
+++ b/platform/msm_shared/include/qseecomi_lk.h
@@ -0,0 +1,518 @@
+/* Copyright (c) 2013-2014, 2015, 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 __QSEECOMI_LK_H_
+#define __QSEECOMI_LK_H_
+
+#include <qseecom_lk.h>
+
+#define QSEECOM_KEY_ID_SIZE   32
+
+#define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63
+#define QSEOS_RESULT_FAIL_KS_OP               -64
+#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS       -65
+#define QSEOS_RESULT_FAIL_MAX_KEYS            -66
+#define QSEOS_RESULT_FAIL_SAVE_KS             -67
+#define QSEOS_RESULT_FAIL_LOAD_KS             -68
+#define QSEOS_RESULT_FAIL_KS_ALREADY_DONE     -69
+#define QSEOS_RESULT_FAIL_KEY_ID_DNE          -70
+#define QSEOS_RESULT_FAIL_INCORRECT_PSWD      -71
+#define QSEOS_RESULT_FAIL_MAX_ATTEMPT         -72
+
+enum qseecom_command_scm_resp_type {
+	QSEOS_APP_ID = 0xEE01,
+	QSEOS_LISTENER_ID
+};
+
+typedef enum
+{
+  QSEE_APP_START_COMMAND = 0x01,
+  QSEE_APP_SHUTDOWN_COMMAND,
+  QSEE_APP_LOOKUP_COMMAND,
+  QSEE_REGISTER_LISTENER,
+  QSEE_DEREGISTER_LISTENER,
+  QSEE_CLIENT_SEND_DATA_COMMAND,
+  QSEE_LISTENER_DATA_RSP_COMMAND,
+  QSEE_LOAD_EXTERNAL_ELF_COMMAND,
+  QSEE_UNLOAD_EXTERNAL_ELF_COMMAND,
+  QSEE_GET_APP_STATE_COMMAND,
+  QSEE_LOAD_SERV_IMAGE_COMMAND,
+  QSEE_UNLOAD_SERV_IMAGE_COMMAND,
+  QSEE_APP_REGION_NOTIFICATION,
+  QSEE_REGISTER_LOG_BUF_COMMAND,
+  QSEE_RPMB_PROVISION_KEY_COMMAND,
+  QSEE_RPMB_ERASE_COMMAND,
+  QSEE_KS_GEN_KEY_COMMAND,
+  QSEE_KS_DEL_KEY_COMMAND,
+  QSEE_KS_GET_MAX_KEYS_COMMAND,
+  QSEE_KS_SET_PIPE_KEY_COMMAND,
+  QSEE_KS_UPDATE_KEY_COMMAND,
+  QSEE_GP_OPEN_SESSION,
+  QSEE_GP_INVOKE_COMMAND,
+  QSEE_GP_CLOSE_SESSION,
+}qsee_smc_command_type;
+
+enum qseecom_qceos_cmd_status {
+	QSEOS_RESULT_SUCCESS = 0,
+	QSEOS_RESULT_INCOMPLETE,
+	QSEOS_RESULT_FAILURE  = 0xFFFFFFFF
+};
+
+enum qseecom_pipe_type {
+	QSEOS_PIPE_ENC = 0x1,
+	QSEOS_PIPE_ENC_XTS = 0x2,
+	QSEOS_PIPE_AUTH = 0x4,
+	QSEOS_PIPE_ENUM_FILL = 0x7FFFFFFF
+};
+
+struct __attribute__ ((packed)) qsee_apps_region_info_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t addr;
+	uint32_t size;
+};
+
+struct __attribute__ ((packed)) qseecom_check_app_ireq {
+	uint32_t qsee_cmd_id;
+	char     app_name[MAX_APP_NAME_SIZE];
+};
+
+struct __attribute__ ((packed)) qseecom_load_app_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t mdt_len;		/* Length of the mdt file */
+	uint32_t img_len;		/* Length of .bxx and .mdt files */
+	uint32_t phy_addr;		/* phy addr of the start of image */
+	char     app_name[MAX_APP_NAME_SIZE];	/* application name*/
+};
+
+struct __attribute__ ((packed)) qseecom_unload_app_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t  app_id;
+};
+
+struct __attribute__ ((packed)) qseecom_load_lib_image_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t mdt_len;
+	uint32_t img_len;
+	uint32_t phy_addr;
+};
+
+struct __attribute__ ((packed)) qseecom_unload_lib_image_ireq {
+	uint32_t qsee_cmd_id;
+};
+
+struct __attribute__ ((packed)) qseecom_register_listener_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t listener_id;
+	uint32_t sb_ptr;
+	uint32_t sb_len;
+};
+
+struct __attribute__ ((packed)) qseecom_unregister_listener_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t  listener_id;
+};
+
+struct __attribute__ ((packed)) qseecom_client_send_data_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t app_id;
+	uint32_t req_ptr;
+	uint32_t req_len;
+	uint32_t rsp_ptr;/* First 4 bytes should be the return status */
+	uint32_t rsp_len;
+};
+
+struct __attribute__ ((packed)) qseecom_reg_log_buf_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t phy_addr;
+	uint32_t len;
+};
+
+/* send_data resp */
+struct __attribute__ ((packed)) qseecom_client_listener_data_irsp {
+	uint32_t qsee_cmd_id;
+	uint32_t listener_id;
+	uint32_t status;
+};
+
+/*
+ * struct qseecom_command_scm_resp - qseecom response buffer
+ * @cmd_status: value from enum tz_sched_cmd_status
+ * @sb_in_rsp_addr: points to physical location of response
+ *                buffer
+ * @sb_in_rsp_len: length of command response
+ */
+struct __attribute__ ((packed)) qseecom_command_scm_resp {
+	uint32_t result;
+	enum qseecom_command_scm_resp_type resp_type;
+	unsigned int data;
+};
+
+struct qseecom_rpmb_provision_key {
+	uint32_t key_type;
+};
+
+struct __attribute__ ((packed)) qseecom_client_send_service_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t key_type; /* in */
+	unsigned int req_len; /* in */
+	uint32_t rsp_ptr; /* in/out */
+	unsigned int rsp_len; /* in/out */
+};
+
+struct __attribute__ ((packed)) qseecom_key_generate_ireq {
+	uint32_t qsee_command_id;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
+};
+
+struct __attribute__ ((packed)) qseecom_key_select_ireq {
+	uint32_t qsee_command_id;
+	uint32_t ce;
+	uint32_t pipe;
+	uint32_t pipe_type;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
+};
+
+struct __attribute__ ((packed)) qseecom_key_delete_ireq {
+	uint32_t qsee_command_id;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
+
+};
+
+struct __attribute__ ((packed)) qseecom_key_userinfo_update_ireq {
+	uint32_t qsee_command_id;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t current_hash32[QSEECOM_HASH_SIZE];
+	uint8_t new_hash32[QSEECOM_HASH_SIZE];
+};
+
+struct __attribute__ ((packed)) qseecom_key_max_count_query_ireq {
+	uint32_t flags;
+};
+
+struct __attribute__ ((packed)) qseecom_key_max_count_query_irsp {
+	uint32_t max_key_count;
+};
+
+struct __attribute__ ((packed)) qseecom_qteec_ireq {
+	uint32_t    qsee_cmd_id;
+	uint32_t    app_id;
+	uint32_t    req_ptr;
+	uint32_t    req_len;
+	uint32_t    resp_ptr;
+	uint32_t    resp_len;
+};
+
+struct __attribute__ ((packed)) qseecom_client_send_fsm_key_req {
+	uint32_t qsee_cmd_id;
+	uint32_t req_ptr;
+	uint32_t req_len;
+	uint32_t rsp_ptr;
+	uint32_t rsp_len;
+};
+
+
+/**********      ARMV8 SMC INTERFACE TZ MACRO     *******************/
+
+#define TZ_SVC_APP_MGR                   1     /* Application management */
+#define TZ_SVC_LISTENER                  2     /* Listener service management */
+#define TZ_SVC_EXTERNAL                  3     /* External image loading */
+#define TZ_SVC_RPMB                      4     /* RPMB */
+#define TZ_SVC_KEYSTORE                  5     /* Keystore management */
+#define TZ_SVC_ES                        16    /* Enterprise Security */
+
+/*----------------------------------------------------------------------------
+ * Owning Entity IDs (defined by ARM SMC doc)
+ * -------------------------------------------------------------------------*/
+#define TZ_OWNER_ARM                     0     /** ARM Architecture call ID */
+#define TZ_OWNER_CPU                     1     /** CPU service call ID */
+#define TZ_OWNER_SIP                     2     /** SIP service call ID */
+#define TZ_OWNER_OEM                     3     /** OEM service call ID */
+#define TZ_OWNER_STD                     4     /** Standard service call ID */
+
+/** Values 5-47 are reserved for future use */
+
+/** Trusted Application call IDs */
+#define TZ_OWNER_TZ_APPS                 48
+#define TZ_OWNER_TZ_APPS_RESERVED        49
+/** Trusted OS Call IDs */
+#define TZ_OWNER_QSEE_OS                 50
+#define TZ_OWNER_MOBI_OS                 51
+#define TZ_OWNER_OS_RESERVED_3           52
+#define TZ_OWNER_OS_RESERVED_4           53
+#define TZ_OWNER_OS_RESERVED_5           54
+#define TZ_OWNER_OS_RESERVED_6           55
+#define TZ_OWNER_OS_RESERVED_7           56
+#define TZ_OWNER_OS_RESERVED_8           57
+#define TZ_OWNER_OS_RESERVED_9           58
+#define TZ_OWNER_OS_RESERVED_10          59
+#define TZ_OWNER_OS_RESERVED_11          60
+#define TZ_OWNER_OS_RESERVED_12          61
+#define TZ_OWNER_OS_RESERVED_13          62
+#define TZ_OWNER_OS_RESERVED_14          63
+
+#define TZ_SVC_INFO                      6     /* Misc. information services */
+
+/** Trusted Application call groups */
+#define TZ_SVC_APP_ID_PLACEHOLDER        0     /* SVC bits will contain App ID */
+
+/** General helper macro to create a bitmask from bits low to high. */
+#define TZ_MASK_BITS(h, l)     ((0xffffffff >> (32 - ((h - l) + 1))) << l)
+
+/**
+   Macro used to define an SMC ID based on the owner ID,
+   service ID, and function number.
+*/
+#define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \
+	((uint32_t)((((o & 0x3f) << 24) | (s & 0xff) << 8) | (f & 0xff)))
+
+#define TZ_SYSCALL_PARAM_NARGS_MASK  TZ_MASK_BITS(3, 0)
+#define TZ_SYSCALL_PARAM_TYPE_MASK   TZ_MASK_BITS(1, 0)
+
+#define TZ_SYSCALL_CREATE_PARAM_ID(nargs, p1, p2, p3, \
+	p4, p5, p6, p7, p8, p9, p10) \
+	((nargs&TZ_SYSCALL_PARAM_NARGS_MASK)+ \
+	((p1&TZ_SYSCALL_PARAM_TYPE_MASK)<<4)+ \
+	((p2&TZ_SYSCALL_PARAM_TYPE_MASK)<<6)+ \
+	((p3&TZ_SYSCALL_PARAM_TYPE_MASK)<<8)+ \
+	((p4&TZ_SYSCALL_PARAM_TYPE_MASK)<<10)+ \
+	((p5&TZ_SYSCALL_PARAM_TYPE_MASK)<<12)+ \
+	((p6&TZ_SYSCALL_PARAM_TYPE_MASK)<<14)+ \
+	((p7&TZ_SYSCALL_PARAM_TYPE_MASK)<<16)+ \
+	((p8&TZ_SYSCALL_PARAM_TYPE_MASK)<<18)+ \
+	((p9&TZ_SYSCALL_PARAM_TYPE_MASK)<<20)+ \
+	((p10&TZ_SYSCALL_PARAM_TYPE_MASK)<<22))
+
+/**
+   Macros used to create the Parameter ID associated with the syscall
+ */
+#define TZ_SYSCALL_CREATE_PARAM_ID_0 0
+#define TZ_SYSCALL_CREATE_PARAM_ID_1(p1) \
+	TZ_SYSCALL_CREATE_PARAM_ID(1, p1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_2(p1, p2) \
+	TZ_SYSCALL_CREATE_PARAM_ID(2, p1, p2, 0, 0, 0, 0, 0, 0, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_3(p1, p2, p3) \
+	TZ_SYSCALL_CREATE_PARAM_ID(3, p1, p2, p3, 0, 0, 0, 0, 0, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_4(p1, p2, p3, p4) \
+	TZ_SYSCALL_CREATE_PARAM_ID(4, p1, p2, p3, p4, 0, 0, 0, 0, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_5(p1, p2, p3, p4, p5) \
+	TZ_SYSCALL_CREATE_PARAM_ID(5, p1, p2, p3, p4, p5, 0, 0, 0, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_6(p1, p2, p3, p4, p5, p6) \
+	TZ_SYSCALL_CREATE_PARAM_ID(6, p1, p2, p3, p4, p5, p6, 0, 0, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_7(p1, p2, p3, p4, p5, p6, p7) \
+	TZ_SYSCALL_CREATE_PARAM_ID(7, p1, p2, p3, p4, p5, p6, p7, 0, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_8(p1, p2, p3, p4, p5, p6, p7, p8) \
+	TZ_SYSCALL_CREATE_PARAM_ID(8, p1, p2, p3, p4, p5, p6, p7, p8, 0, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
+	TZ_SYSCALL_CREATE_PARAM_ID(9, p1, p2, p3, p4, p5, p6, p7, p8, p9, 0)
+#define TZ_SYSCALL_CREATE_PARAM_ID_10(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) \
+	TZ_SYSCALL_CREATE_PARAM_ID(10, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
+
+/**
+   Macro used to obtain the Parameter ID associated with the syscall
+ */
+#define TZ_SYSCALL_GET_PARAM_ID(CMD_ID)        CMD_ID ## _PARAM_ID
+
+#define TZ_SYSCALL_PARAM_TYPE_VAL              0x0     /** type of value */
+#define TZ_SYSCALL_PARAM_TYPE_BUF_RO           0x1     /** type of buffer read-only */
+#define TZ_SYSCALL_PARAM_TYPE_BUF_RW           0x2     /** type of buffer read-write */
+
+#define TZ_OS_APP_START_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x01)
+
+#define TZ_OS_APP_START_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_3( \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \
+	TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_APP_SHUTDOWN_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x02)
+
+#define TZ_OS_APP_SHUTDOWN_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_APP_LOOKUP_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x03)
+
+#define TZ_OS_APP_LOOKUP_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_APP_GET_STATE_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x04)
+
+#define TZ_OS_APP_GET_STATE_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_APP_REGION_NOTIFICATION_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x05)
+
+#define TZ_OS_APP_REGION_NOTIFICATION_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_REGISTER_LOG_BUFFER_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x06)
+
+#define TZ_OS_REGISTER_LOG_BUFFER_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_LOAD_SERVICES_IMAGE_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x07)
+
+#define TZ_OS_LOAD_SERVICES_IMAGE_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_3( \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \
+	TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_UNLOAD_SERVICES_IMAGE_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_APP_MGR, 0x08)
+
+#define TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_0
+
+#define TZ_OS_REGISTER_LISTENER_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x01)
+
+#define TZ_OS_REGISTER_LISTENER_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_3( \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
+	TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_DEREGISTER_LISTENER_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x02)
+
+#define TZ_OS_DEREGISTER_LISTENER_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_LISTENER_RESPONSE_HANDLER_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x03)
+
+#define TZ_OS_LISTENER_RESPONSE_HANDLER_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_LOAD_EXTERNAL_IMAGE_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_EXTERNAL, 0x01)
+
+#define TZ_OS_LOAD_EXTERNAL_IMAGE_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_3( \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \
+	TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_APP_QSAPP_SEND_DATA_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \
+	TZ_SVC_APP_ID_PLACEHOLDER, 0x01)
+
+
+#define TZ_APP_QSAPP_SEND_DATA_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_5( \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
+	TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_UNLOAD_EXTERNAL_IMAGE_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_EXTERNAL, 0x02)
+
+#define TZ_OS_UNLOAD_EXTERNAL_IMAGE_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_0
+
+#define TZ_INFO_IS_SVC_AVAILABLE_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_INFO, 0x01)
+
+#define TZ_INFO_IS_SVC_AVAILABLE_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_INFO_GET_FEATURE_VERSION_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_INFO, 0x03)
+
+#define TZ_INFO_GET_FEATURE_VERSION_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_RPMB_PROVISION_KEY_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_RPMB, 0x01)
+
+#define TZ_OS_RPMB_PROVISION_KEY_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_RPMB_ERASE_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_RPMB, 0x02)
+
+#define TZ_OS_RPMB_ERASE_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_0
+
+#define TZ_OS_KS_GEN_KEY_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_KEYSTORE, 0x01)
+
+#define TZ_OS_KS_GEN_KEY_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_KS_DEL_KEY_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_KEYSTORE, 0x02)
+
+#define TZ_OS_KS_DEL_KEY_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_KS_GET_MAX_KEYS_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_KEYSTORE, 0x03)
+
+#define TZ_OS_KS_GET_MAX_KEYS_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_KS_SET_PIPE_KEY_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_KEYSTORE, 0x04)
+
+#define TZ_OS_KS_SET_PIPE_KEY_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_OS_KS_UPDATE_KEY_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_KEYSTORE, 0x05)
+
+#define TZ_OS_KS_UPDATE_KEY_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_2( \
+	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#define TZ_ES_SAVE_PARTITION_HASH_ID \
+	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_ES, 0x01)
+
+#define TZ_ES_SAVE_PARTITION_HASH_ID_PARAM_ID \
+	TZ_SYSCALL_CREATE_PARAM_ID_3( \
+	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
+	TZ_SYSCALL_PARAM_TYPE_VAL)
+
+#endif /* __QSEECOMI_LK_H_ */
diff --git a/platform/msm_shared/include/rpm-glink.h b/platform/msm_shared/include/rpm-glink.h
new file mode 100644
index 0000000..1d8060a
--- /dev/null
+++ b/platform/msm_shared/include/rpm-glink.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2015, 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 Fundation, Inc. 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 __RPM_GLINK_H
+#define __RPM_GLINK_H
+
+#include <arch/defines.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <rpm-ipc.h>
+#include <glink.h>
+
+typedef struct
+{
+	uint32_t version;
+	uint32_t cmd;
+	uint32_t seqnumber;
+	uint32_t namelength;
+	char name[32];
+} rpm_ssr_req;
+
+typedef rpm_cmd rpm_ack_msg;
+glink_err_type rpm_glink_send_data(uint32_t *data, uint32_t len, msg_type type);
+uint32_t rpm_glink_recv_data(char *rx_buffer, uint32_t *len);
+void rpm_glink_clk_enable(uint32_t *data, uint32_t len);
+void rpm_glink_clk_disable(uint32_t *data, uint32_t len);
+void rpm_glink_init();
+void rpm_glink_uninit();
+void rpm_scalar_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv, void *buffer, size_t size, size_t intent_used);
+void rpm_vector_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv, void *buffer, size_t size, size_t intent_used, glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider);
+void rpm_glink_tx_done_isr(void);
+
+void rpm_glink_notify_state_isr(glink_handle_type handle, void *data, glink_channel_event_type event);
+#endif
diff --git a/platform/msm_shared/include/rpm-ipc.h b/platform/msm_shared/include/rpm-ipc.h
new file mode 100644
index 0000000..f02e8b0
--- /dev/null
+++ b/platform/msm_shared/include/rpm-ipc.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2015, 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 Fundation, Inc. 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 __RPM_IPC_H
+#define __RPM_IPC_H
+
+#include <arch/defines.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#define RPM_REQ_MAGIC 0x00716572
+#define RPM_CMD_MAGIC 0x00646d63
+#define REQ_MSG_LENGTH 0x14
+#define CMD_MSG_LENGTH 0x08
+#define ACK_MSG_LENGTH 0x0C
+
+typedef enum
+{
+	RPM_REQUEST_TYPE,
+	RPM_CMD_TYPE,
+	RPM_SUCCESS_REQ_ACK,
+	RPM_SUCCESS_CMD_ACK,
+	RPM_ERROR_ACK,
+}msg_type;
+
+enum
+{
+	RESOURCETYPE,
+	RESOURCEID,
+	KVP_KEY,
+	KVP_LENGTH,
+	KVP_VALUE,
+};
+
+typedef struct
+{
+	uint32_t type;
+	uint32_t len;
+} rpm_gen_hdr;
+
+typedef struct
+{
+	uint32_t key;
+	uint32_t len;
+	uint32_t val;
+} kvp_data;
+
+typedef struct
+{
+	uint32_t id;
+	uint32_t set;
+	uint32_t resourceType;
+	uint32_t resourceId;
+	uint32_t dataLength;
+}rpm_req_hdr;
+
+typedef struct
+{
+	rpm_gen_hdr hdr;
+	rpm_req_hdr req_hdr;
+	kvp_data *data;
+} rpm_req;
+
+typedef struct
+{
+	rpm_gen_hdr hdr;
+	kvp_data *data;
+} rpm_cmd;
+
+typedef rpm_cmd rpm_ack_msg;
+int rpm_send_data(uint32_t *data, uint32_t len, msg_type type);
+void rpm_clk_enable(uint32_t *data, uint32_t len);
+
+void fill_kvp_object(kvp_data **kdata, uint32_t *data, uint32_t len);
+void free_kvp_object(kvp_data **kdata);
+#endif
diff --git a/platform/msm_shared/include/rpm-smd.h b/platform/msm_shared/include/rpm-smd.h
index 5ac8a1b..a1eb4a2 100644
--- a/platform/msm_shared/include/rpm-smd.h
+++ b/platform/msm_shared/include/rpm-smd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 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
@@ -33,65 +33,10 @@
 #include <arch/defines.h>
 #include <stdint.h>
 #include <sys/types.h>
+#include <rpm-ipc.h>
 
-typedef enum
-{
-	RPM_REQUEST_TYPE,
-	RPM_CMD_TYPE,
-	RPM_SUCCESS_REQ_ACK,
-	RPM_SUCCESS_CMD_ACK,
-	RPM_ERROR_ACK,
-}msg_type;
-
-enum
-{
-	RESOURCETYPE,
-	RESOURCEID,
-	KVP_KEY,
-	KVP_LENGTH,
-	KVP_VALUE,
-};
-
-typedef struct
-{
-	uint32_t type;
-	uint32_t len;
-} rpm_gen_hdr;
-
-typedef struct
-{
-	uint32_t key;
-	uint32_t len;
-	uint32_t val;
-} kvp_data;
-
-typedef struct
-{
-	uint32_t id;
-	uint32_t set;
-	uint32_t resourceType;
-	uint32_t resourceId;
-	uint32_t dataLength;
-}rpm_req_hdr;
-
-typedef struct
-{
-	rpm_gen_hdr hdr;
-	rpm_req_hdr req_hdr;
-	kvp_data *data;
-} rpm_req;
-
-typedef struct
-{
-	rpm_gen_hdr hdr;
-	kvp_data *data;
-} rpm_cmd;
-
-typedef rpm_cmd rpm_ack_msg;
-int rpm_send_data(uint32_t *data, uint32_t len, msg_type type);
-uint32_t rpm_recv_data(uint32_t *len);
-void rpm_clk_enable(uint32_t *data, uint32_t len);
-void rpm_clk_disable(uint32_t *data, uint32_t len);
+int rpm_smd_send_data(uint32_t *data, uint32_t len, msg_type type);
+uint32_t rpm_smd_recv_data(uint32_t *len);
 void rpm_smd_init();
 void rpm_smd_uninit();
 #endif
diff --git a/platform/msm_shared/include/rpmb.h b/platform/msm_shared/include/rpmb.h
index 8bbd985..6cd7ecd 100644
--- a/platform/msm_shared/include/rpmb.h
+++ b/platform/msm_shared/include/rpmb.h
@@ -26,6 +26,49 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef _RPMB_H_
+#define _RPMB_H_
+
+#include <qseecom_lk_api.h>
+#include <mmc_sdhci.h>
+#include <ufs.h>
+#include <debug.h>
+
+#define RPMB_SECTOR_SIZE            256
+#define RPMB_LSTNR_ID               0x2000
+#define RPMB_BLK_SIZE               512
+#define RPMB_FRAME_SIZE             512
+#define RPMB_MIN_BLK_CNT            1
+#define RPMB_MIN_BLK_SZ             512
+
+enum app_commands
+{
+	CLIENT_CMD_READ_LK_DEVICE_STATE = 0,
+	CLIENT_CMD_LK_END_MILESTONE,
+	CLIENT_CMD_GET_VERSION,
+	CLIENT_CMD_WRITE_LK_DEVICE_STATE,
+};
+
+struct send_cmd_req
+{
+	uint32_t cmd_id;
+	uint32_t data;
+	uint32_t len;
+}__PACKED;
+
+struct send_cmd_rsp
+{
+	uint32_t cmd_id;
+	uint32_t data;
+	int32_t status;
+}__PACKED;
+
+enum device_type
+{
+	EMMC_RPMB = 3,
+	UFS_RPMB = 9,
+};
+
 /* RPMB request and response types */
 enum rpmb_rr_type {
 	KEY_PROVISION = 0x1,
@@ -62,9 +105,61 @@
 	uint8_t  keyMAC[32];
 	uint8_t  data[256];
 	uint8_t  nonce[16];
-	uint32_t writecounter;
-	uint16_t address;
-	uint16_t blockcount;
+	uint8_t writecounter[4];
+	uint8_t address[2];
+	uint8_t blockcount[2];
 	uint8_t  result[2];
-	uint16_t requestresponse;
+	uint8_t requestresponse[2];
 };
+
+struct rpmb_init_info
+{
+	uint32_t size;
+	uint32_t rel_wr_count;
+	uint32_t dev_type;
+};
+
+/* dump a given RPMB frame */
+static inline void dump_rpmb_frame(uint8_t *frame, const char *frame_type)
+{
+    int i;
+    char buf[512] = {0};
+    char *p = buf;
+
+    printf("Printing %s frame (in hex)\n", frame_type);
+    printf("________0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F__0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F\n");
+    for (i = 0; i < 512; i++) {
+        if (!(i % 32)) {
+            snprintf(p, 8, "| %2d | ", (i + 1) / 32);
+            p += 7;
+        }
+        snprintf(p, 4, "%.2x ", frame[i]);
+        p += 3;
+        if (((i + 1) % 32) == 0) {
+            printf("%s\n", buf);
+            p = buf;
+        }
+    }
+    printf("________F__E__D__C__B__A__9__8__7__6__5__4__3__2__1__0__F__E__D__C__B__A__9__8__7__6__5__4__3__2__1__0\n");
+}
+
+int read_device_info_rpmb(void *info, uint32_t sz);
+int write_device_info_rpmb(void *info, uint32_t sz);
+
+/* Function Prototypes */
+int rpmb_write_emmc(struct mmc_device *dev, uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len);
+int rpmb_read_emmc(struct mmc_device *dev, uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len);
+int rpmb_write_ufs(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len);
+int rpmb_read_ufs(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len);
+
+/* APIs exposed to applications */
+int rpmb_init();
+int rpmb_uninit();
+int rpmb_write(uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len);
+int rpmb_read(uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len);
+struct rpmb_init_info *rpmb_get_init_info();
+int rpmb_get_app_handle();
+bool is_sec_app_loaded();
+int load_sec_app();
+int unload_sec_app();
+#endif
diff --git a/platform/msm_shared/include/rpmb_listener.h b/platform/msm_shared/include/rpmb_listener.h
new file mode 100644
index 0000000..a3bb3e5
--- /dev/null
+++ b/platform/msm_shared/include/rpmb_listener.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2015, 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 <qseecom_lk_api.h>
+#include <mmc_sdhci.h>
+#include <ufs.h>
+
+#define RPMB_LSTNR_ID               0x2000
+
+int rpmb_listener_start();
+int rpmb_listener_stop();
diff --git a/platform/msm_shared/include/scm.h b/platform/msm_shared/include/scm.h
index 283f1cc..2cdca66 100644
--- a/platform/msm_shared/include/scm.h
+++ b/platform/msm_shared/include/scm.h
@@ -256,6 +256,7 @@
 
 #define PRNG_CMD_ID                 0x01
 #define IS_CALL_AVAIL_CMD           0x01
+#define IS_SECURE_BOOT_ENABLED      0x04
 
 /* Download Mode specific arguments to be passed to TZ */
 #define SCM_EDLOAD_MODE 0x01
@@ -317,6 +318,10 @@
 int scm_svc_get_secure_state(uint32_t *state_low, uint32_t *state_high);
 
 int scm_protect_keystore(uint32_t * img_ptr, uint32_t  img_len);
+int
+scm_call(uint32_t svc_id, uint32_t cmd_id, const void *cmd_buf,
+        size_t cmd_len, void *resp_buf, size_t resp_len);
+
 
 #define SCM_SVC_FUSE                0x08
 #define SCM_BLOW_SW_FUSE_ID         0x01
@@ -337,9 +342,11 @@
 
 #define SCM_SVC_PWR                     0x9
 #define SCM_IO_DISABLE_PMIC_ARBITER     0x1
+#define SCM_IO_DISABLE_PMIC_ARBITER1    0x2
 
 #define SCM_SVC_MILESTONE_32_64_ID      0x1
 #define SCM_SVC_MILESTONE_CMD_ID        0xf
+#define SCM_SVC_TZSCHEDULER             0xFC
 
 enum ap_ce_channel_type {
 AP_CE_REGISTER_USE = 0,
@@ -349,6 +356,11 @@
 /* Apps CE resource. */
 #define TZ_RESOURCE_CE_AP  2
 
+/* Secure IO Service IDs */
+#define SCM_IO_READ     0x1
+#define SCM_IO_WRITE    0x2
+#define SCM_SVC_IO      0x5
+
 uint8_t switch_ce_chn_cmd(enum ap_ce_channel_type channel);
 
 /**
@@ -443,4 +455,10 @@
  * Used for checking if armv8 SCM support present
  */
 void scm_init();
+bool is_secure_boot_enable();
+
+/* Is armv8 supported */
+bool is_scm_armv8_support();
+
+int scm_dload_mode(int mode);
 #endif
diff --git a/platform/msm_shared/include/sdhci.h b/platform/msm_shared/include/sdhci.h
index 604ac81..c0b484d 100644
--- a/platform/msm_shared/include/sdhci.h
+++ b/platform/msm_shared/include/sdhci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -100,6 +100,7 @@
 	uint32_t cmd_retry;     /* Retry the command, if card is busy */
 	uint32_t cmd23_support; /* If card supports cmd23 */
 	uint64_t cmd_timeout;   /* Command timeout in us */
+	bool write_flag;        /* Write flag, for reliable write cases */
 	struct mmc_data data;   /* Data pointer */
 };
 
diff --git a/platform/msm_shared/include/smem_list.h b/platform/msm_shared/include/smem_list.h
new file mode 100644
index 0000000..22148cb
--- /dev/null
+++ b/platform/msm_shared/include/smem_list.h
@@ -0,0 +1,214 @@
+/* Copyright (c) 2015, 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 SMEM_LIST_H
+#define SMEM_LIST_H
+
+/**
+ * @file smem_list.h
+ *
+ * Public data types and functions to implement a generic
+ * list.
+ */
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup smem
+@{ */
+
+
+/*===========================================================================
+
+                        TYPE DEFINITIONS
+
+===========================================================================*/
+
+/** Defines the structure to link to the SMEM list */
+typedef struct smem_list_link
+{
+  struct smem_list_link *next;
+} smem_list_link_type;
+
+
+/** Defines the generic SMEM list type */
+typedef struct smem_list
+{
+  smem_list_link_type *next;
+  long count;
+} smem_list_type;
+
+/*===========================================================================
+
+                      PUBLIC FUNCTION DECLARATIONS
+
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      smem_list_init
+===========================================================================*/
+/**
+  Creates a generic list.
+
+  @param[in/out] list   Pointer to the user list.
+
+  @return
+  N/A.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_init( smem_list_type *list );
+
+/*===========================================================================
+FUNCTION      smem_list_append
+===========================================================================*/
+/**
+  Appends an element to the end of a generic list.
+
+  The element must contain a smem_list_link_type at its base address.
+  The element should not be already present in any list.
+
+  @param[in/out] list   Pointer to the user list.
+  @param[in] item       Element to be inserted.
+
+  @return
+  N/A.
+
+  @dependencies
+  The element must contain a smem_list_link_type at its base address.
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_append( smem_list_type *list, void *item );
+
+/*===========================================================================
+FUNCTION      smem_list_delete
+===========================================================================*/
+/**
+  Removes the specified element from a generic list.
+
+  The element may be present at any point in the list.
+
+  @param[in] list       Pointer to the user list.
+  @param[in] item       Element to be removed.
+
+  @return
+  0 if the element is deleted, or a negative error code if the element
+  is not found.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_delete( smem_list_type *list, void *item );
+
+/*===========================================================================
+FUNCTION      smem_list_first
+===========================================================================*/
+/**
+  Retrieves the first element in the list without removing it.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the first element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_first( smem_list_type *list );
+
+/*===========================================================================
+FUNCTION      smem_list_next
+===========================================================================*/
+/**
+  Retrieves the next element in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the next element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_next( void * item );
+
+/*===========================================================================
+FUNCTION      smem_list_count
+===========================================================================*/
+/**
+  Gets the number of elements in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Count of elements in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_count( smem_list_type *list );
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */ /* end_addtogroup smem */
+
+#endif /* SMEM_LIST_H */
diff --git a/platform/msm_shared/include/smem_type.h b/platform/msm_shared/include/smem_type.h
new file mode 100644
index 0000000..17a2bb0
--- /dev/null
+++ b/platform/msm_shared/include/smem_type.h
@@ -0,0 +1,237 @@
+/* Copyright (c) 2015, 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 SMEM_TYPE_H
+#define SMEM_TYPE_H
+
+/**
+ * @file smem_type.h
+ *
+ * Public data types used by SMEM
+ */
+
+/** @addtogroup smem
+@{ */
+
+/*===========================================================================
+                               TYPE DEFINITIONS
+===========================================================================*/
+/******************************************************************************
+   The most significant two bytes of this number are the smem major version and
+ the least significant two bytes are the smem minor version.  The major version
+ number should be updated whenever a change which causes an incompatibility is
+ introduced.
+   The minor version number can track API changes and deprecations that will
+ not affect remote processors.  This may include changes to the smem_mem_type
+ enum, if dependencies have already been satisfied on the relevant processors.
+   Inconsistencies in minor version, between processors, will not prevent smem
+ from booting, but major version inconsistencies will.
+   0x2XXX in the minor version indicates that it is the SMEM minor version, and
+ unrelated to proc comm, which no longer exists.
+******************************************************************************/
+#define SMEM_VERSION_ID                     0x000B2002
+
+#define SMEM_MAJOR_VERSION_MASK             0xFFFF0000
+#define SMEM_MINOR_VERSION_MASK             0x0000FFFF
+#define SMEM_FULL_VERSION_MASK              0xFFFFFFFF
+
+#define SMEM_NUM_SMD_CHANNELS               64
+#define SMEM_NUM_SMP2P_EDGES                8
+
+/** Types of memory that can be requested via smem_alloc.
+
+  All of these types of memory have corresponding buffers allocated in
+  smem_data_decl. If a buffer is added to smem_data_decl, add a corresponding
+  entry to this list.
+
+  SMEM_VERSION_FIRST and SMEM_VERSION_LAST are the first and last
+  boundaries for external version checking via the smem_version_set routine.
+  To set up versioning for a shared item, add an entry between
+  SMEM_VERSION_FIRST and SMEM_VERSION_LAST and update the SMEM version in
+  smem_version.h.
+
+  SMEM_VERSION_LAST need not be the last item in the enum.
+*/
+typedef enum
+{
+  SMEM_MEM_FIRST,
+  SMEM_RESERVED_PROC_COMM = SMEM_MEM_FIRST,
+  SMEM_FIRST_FIXED_BUFFER = SMEM_RESERVED_PROC_COMM,
+  SMEM_HEAP_INFO,
+  SMEM_ALLOCATION_TABLE,
+  SMEM_VERSION_INFO,
+  SMEM_HW_RESET_DETECT,
+  SMEM_RESERVED_AARM_WARM_BOOT,
+  SMEM_DIAG_ERR_MESSAGE,
+  SMEM_SPINLOCK_ARRAY,
+  SMEM_MEMORY_BARRIER_LOCATION,
+  SMEM_LAST_FIXED_BUFFER = SMEM_MEMORY_BARRIER_LOCATION,
+  SMEM_AARM_PARTITION_TABLE,
+  SMEM_AARM_BAD_BLOCK_TABLE,
+  SMEM_RESERVE_BAD_BLOCKS,
+  SMEM_RESERVED_WM_UUID,
+  SMEM_CHANNEL_ALLOC_TBL,
+  SMEM_SMD_BASE_ID,
+  SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_CHANNELS,
+  SMEM_SMEM_LOG_EVENTS,
+  SMEM_RESERVED_SMEM_STATIC_LOG_IDX,
+  SMEM_RESERVED_SMEM_STATIC_LOG_EVENTS,
+  SMEM_RESERVED_SMEM_SLOW_CLOCK_SYNC,
+  SMEM_RESERVED_SMEM_SLOW_CLOCK_VALUE,
+  SMEM_RESERVED_BIO_LED_BUF,
+  SMEM_SMSM_SHARED_STATE,
+  SMEM_RESERVED_SMSM_INT_INFO,
+  SMEM_RESERVED_SMSM_SLEEP_DELAY,
+  SMEM_RESERVED_SMSM_LIMIT_SLEEP,
+  SMEM_RESERVED_SLEEP_POWER_COLLAPSE_DISABLED,
+  SMEM_APPS_POWER_STATUS = SMEM_RESERVED_SLEEP_POWER_COLLAPSE_DISABLED, /*APSS power status*/
+  SMEM_RESERVED_KEYPAD_KEYS_PRESSED,
+  SMEM_RESERVED_KEYPAD_STATE_UPDATED,
+  SMEM_RESERVED_KEYPAD_STATE_IDX,
+  SMEM_RESERVED_GPIO_INT,
+  SMEM_RESERVED_MDDI_LCD_IDX,
+  SMEM_RESERVED_MDDI_HOST_DRIVER_STATE,
+  SMEM_RESERVED_MDDI_LCD_DISP_STATE,
+  SMEM_RESERVED_LCD_CUR_PANEL,
+  SMEM_RESERVED_MARM_BOOT_SEGMENT_INFO,
+  SMEM_RESERVED_AARM_BOOT_SEGMENT_INFO,
+  SMEM_RESERVED_SLEEP_STATIC,
+  SMEM_RESERVED_SCORPION_FREQUENCY,
+  SMEM_RESERVED_SMD_PROFILES,
+  SMEM_RESERVED_TSSC_BUSY,
+  SMEM_RESERVED_HS_SUSPEND_FILTER_INFO,
+  SMEM_RESERVED_BATT_INFO,
+  SMEM_RESERVED_APPS_BOOT_MODE,
+  SMEM_VERSION_FIRST,
+  SMEM_VERSION_SMD = SMEM_VERSION_FIRST,
+  SMEM_VERSION_SMD_BRIDGE,
+  SMEM_VERSION_SMSM,
+  SMEM_VERSION_SMD_NWAY_LOOP,
+  SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24,
+  SMEM_RESERVED_OSS_RRCASN1_BUF1,
+  SMEM_RESERVED_OSS_RRCASN1_BUF2,
+  SMEM_ID_VENDOR0,
+  SMEM_ID_VENDOR1,
+  SMEM_ID_VENDOR2,
+  SMEM_HW_SW_BUILD_ID,
+  SMEM_RESERVED_SMD_BLOCK_PORT_BASE_ID,
+  SMEM_RESERVED_SMD_BLOCK_PORT_PROC0_HEAP =
+                   SMEM_RESERVED_SMD_BLOCK_PORT_BASE_ID +
+                   SMEM_NUM_SMD_CHANNELS,
+  SMEM_RESERVED_SMD_BLOCK_PORT_PROC1_HEAP =
+                   SMEM_RESERVED_SMD_BLOCK_PORT_PROC0_HEAP +
+                   SMEM_NUM_SMD_CHANNELS,
+  SMEM_I2C_MUTEX = SMEM_RESERVED_SMD_BLOCK_PORT_PROC1_HEAP +
+                   SMEM_NUM_SMD_CHANNELS,
+  SMEM_SCLK_CONVERSION,
+  SMEM_RESERVED_SMD_SMSM_INTR_MUX,
+  SMEM_SMSM_CPU_INTR_MASK,
+  SMEM_RESERVED_APPS_DEM_SLAVE_DATA,
+  SMEM_RESERVED_QDSP6_DEM_SLAVE_DATA,
+  SMEM_RESERVED_CLKREGIM_BSP,
+  SMEM_RESERVED_CLKREGIM_SOURCES,
+  SMEM_SMD_FIFO_BASE_ID,
+  SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID +
+                                    SMEM_NUM_SMD_CHANNELS,
+  SMEM_POWER_ON_STATUS_INFO,
+  SMEM_DAL_AREA,
+  SMEM_SMEM_LOG_POWER_IDX,
+  SMEM_SMEM_LOG_POWER_WRAP,
+  SMEM_SMEM_LOG_POWER_EVENTS,
+  SMEM_ERR_CRASH_LOG,
+  SMEM_ERR_F3_TRACE_LOG,
+  SMEM_SMD_BRIDGE_ALLOC_TABLE,
+  SMEM_SMD_FEATURE_SET,
+  SMEM_RESERVED_SD_IMG_UPGRADE_STATUS,
+  SMEM_SEFS_INFO,
+  SMEM_RESERVED_RESET_LOG,
+  SMEM_RESERVED_RESET_LOG_SYMBOLS,
+  SMEM_MODEM_SW_BUILD_ID,
+  SMEM_SMEM_LOG_MPROC_WRAP,
+  SMEM_RESERVED_BOOT_INFO_FOR_APPS,
+  SMEM_SMSM_SIZE_INFO,
+  SMEM_SMD_LOOPBACK_REGISTER,
+  SMEM_SSR_REASON_MSS0,
+  SMEM_SSR_REASON_WCNSS0,
+  SMEM_SSR_REASON_LPASS0,
+  SMEM_SSR_REASON_DSPS0,
+  SMEM_SSR_REASON_VCODEC0,
+  SMEM_VOICE,
+  SMEM_ID_SMP2P_BASE_APPS, /* = 427 */
+  SMEM_ID_SMP2P_BASE_MODEM = SMEM_ID_SMP2P_BASE_APPS +
+                              SMEM_NUM_SMP2P_EDGES, /* = 435 */
+  SMEM_ID_SMP2P_BASE_ADSP = SMEM_ID_SMP2P_BASE_MODEM +
+                              SMEM_NUM_SMP2P_EDGES, /* = 443 */
+  SMEM_ID_SMP2P_BASE_WCN = SMEM_ID_SMP2P_BASE_ADSP +
+                              SMEM_NUM_SMP2P_EDGES, /* = 451 */
+  SMEM_ID_SMP2P_BASE_RPM = SMEM_ID_SMP2P_BASE_WCN +
+                              SMEM_NUM_SMP2P_EDGES, /* = 459 */
+  SMEM_FLASH_DEVICE_INFO = SMEM_ID_SMP2P_BASE_RPM +
+                              SMEM_NUM_SMP2P_EDGES, /* = 467 */
+  SMEM_BAM_PIPE_MEMORY, /* = 468 */
+  SMEM_IMAGE_VERSION_TABLE, /* = 469 */
+  SMEM_LC_DEBUGGER, /* = 470 */
+  SMEM_FLASH_NAND_DEV_INFO, /* =471 */
+  SMEM_A2_BAM_DESCRIPTOR_FIFO,          /* = 472 */
+  SMEM_CPR_CONFIG,                      /* = 473 */
+  SMEM_CLOCK_INFO,                      /* = 474 */
+  SMEM_IPC_INFO,                        /* = 475 */
+  SMEM_RF_EEPROM_DATA,                  /* = 476 */
+  SMEM_COEX_MDM_WCN,                    /* = 477 */
+  SMEM_GLINK_NATIVE_XPORT_DESCRIPTOR,   /* = 478 */
+  SMEM_GLINK_NATIVE_XPORT_FIFO_0,       /* = 479 */
+  SMEM_GLINK_NATIVE_XPORT_FIFO_1,       /* = 480 */
+
+  SMEM_MEM_LAST = SMEM_GLINK_NATIVE_XPORT_FIFO_1,
+  SMEM_INVALID
+} smem_mem_type;
+
+/**
+ * A list of hosts supported in SMEM
+*/
+typedef enum
+{
+  SMEM_APPS      = 0,                     /**< Apps Processor */
+  SMEM_MODEM     = 1,                     /**< Modem processor */
+  SMEM_ADSP      = 2,                     /**< ADSP processor */
+  SMEM_RSVD3     = 3,                     /**< Reserved */
+  SMEM_WCN       = 4,                     /**< WCN processor */
+  SMEM_RSVD5     = 5,                     /**< Reserved */
+  SMEM_RPM       = 6,                     /**< RPM processor */
+  SMEM_NUM_HOSTS = 7,                     /**< Max number of host in target */
+  SMEM_INVALID_HOST,                      /**< Invalid processor */
+
+  SMEM_Q6        = SMEM_ADSP,             /**< Kept for legacy purposes.
+                                           **  New code should use SMEM_ADSP */
+  SMEM_RIVA      = SMEM_WCN,              /**< Kept for legacy purposes.
+                                           **  New code should use SMEM_WCN */
+}smem_host_type;
+
+/** @} */ /* end_addtogroup smem */
+
+#endif /* SMEM_TYPE_H */
diff --git a/platform/msm_shared/include/spmi.h b/platform/msm_shared/include/spmi.h
index 5e6deb4..85cd66a 100644
--- a/platform/msm_shared/include/spmi.h
+++ b/platform/msm_shared/include/spmi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012,2014 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012,2014-2015 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
@@ -101,8 +101,6 @@
 #define SPMI_CMD_DEV_DESC_BLK_MASTER_READ    0x10
 #define SPMI_CMD_DEV_DESC_BLK_SLAVE_READ     0x11
 
-/* Max number of Peripherals supported by SPMI */
-#define MAX_PERIPH                           128
 #define PMIC_ARB_SPMI_HW_VERSION             (SPMI_BASE + 0xF000)
 
 enum spmi_geni_cmd_return_value{
diff --git a/platform/msm_shared/include/ucs.h b/platform/msm_shared/include/ucs.h
index 48c50db..a512955 100644
--- a/platform/msm_shared/include/ucs.h
+++ b/platform/msm_shared/include/ucs.h
@@ -29,6 +29,8 @@
 #ifndef _UCS_H
 #define _UCS_H
 
+#include <upiu.h>
+
 #define SCSI_MAX_DATA_TRANS_BLK_LEN    0xFFFF
 #define UFS_DEFAULT_SECTORE_SIZE       4096
 
@@ -43,10 +45,6 @@
 #define SCSI_SEC_PROT                  0xEC
 #define SCSI_SEC_UFS_PROT_ID           0x0001
 
-#define RPMB_BLK_SIZE                  512
-#define RPMB_FRAME_SIZE                512
-#define RPMB_MIN_BLK_CNT               1
-
 /* FLAGS for indication of read or write */
 enum scsi_upiu_flags
 {
@@ -163,6 +161,7 @@
 }__PACKED;
 
 int ucs_scsi_send_inquiry(struct ufs_dev *dev);
+int ucs_do_scsi_cmd(struct ufs_dev *dev, struct scsi_req_build_type *req);
 int ucs_do_scsi_read(struct ufs_dev *dev, struct scsi_rdwr_req *req);
 int ucs_do_scsi_write(struct ufs_dev *dev, struct scsi_rdwr_req *req);
 int ucs_do_scsi_unmap(struct ufs_dev *dev, struct scsi_unmap_req *req);
@@ -177,4 +176,5 @@
 
 /* This function parses the first byte of the sense data and returns the sense key */
 int parse_sense_key(uint32_t sense_data);
+int ucs_do_request_sense(struct ufs_dev *dev, uint8_t lun);
 #endif
diff --git a/platform/msm_shared/include/ufs.h b/platform/msm_shared/include/ufs.h
index c28c949..0af2dc5 100644
--- a/platform/msm_shared/include/ufs.h
+++ b/platform/msm_shared/include/ufs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -124,4 +124,5 @@
 uint32_t ufs_get_erase_blk_size(struct ufs_dev* dev);
 void ufs_dump_is_register(struct ufs_dev* dev);
 void ufs_dump_hc_registers(struct ufs_dev* dev);
+void ufs_rpmb_init(struct ufs_dev *dev);
 #endif
diff --git a/platform/msm_shared/include/xport_rpm.h b/platform/msm_shared/include/xport_rpm.h
new file mode 100644
index 0000000..2566172
--- /dev/null
+++ b/platform/msm_shared/include/xport_rpm.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2015, 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 XPORT_RPM_H
+#define XPORT_RPM_H
+
+/**
+ * @file xport_rpm.h
+ *
+ * Internal definitions for RPM Glink transport
+ */
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include "glink_transport_if.h"
+#include <glink.h>
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+
+/* Version request command */
+#define XPORT_RPM_CMD_VERSION_REQ       0x0
+/* Version ACK command */
+#define XPORT_RPM_CMD_VERSION_ACK       0x1
+/* Open channel command */
+#define XPORT_RPM_CMD_OPEN_CHANNEL      0x2
+/* Close channel command */
+#define XPORT_RPM_CMD_CLOSE_CHANNEL     0x3
+/* Open channel ACK command */
+#define XPORT_RPM_CMD_OPEN_CHANNEL_ACK  0x4
+/* Tx data command */
+#define XPORT_RPM_CMD_TX_DATA           0x9
+/* Close channel ACK command */
+#define XPORT_RPM_CMD_CLOSE_CHANNEL_ACK 0xB
+/* Tx signals command */
+#define XPORT_RPM_CMD_TX_SIGNALS        0xF
+
+
+#define XPORT_RPM_GET_CMD_ID(c)      ((c) & 0xFFFF)
+#define XPORT_RPM_SET_CMD_ID(cmd_id) ((cmd_id) & 0xFFFF)
+
+#define XPORT_RPM_GET_CHANNEL_ID(c)   (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_CHANNEL_ID(cid) (((cid) << 16) & 0xFFFF0000)
+#define XPORT_RPM_GET_STR_LEN(c)      (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_STR_LEN(c)      (((c) << 16) & 0xFFFF0000)
+#define XPORT_RPM_GET_PRIO(c)         ((c) & 0xFFFF)
+#define XPORT_RPM_SET_PRIO(c)         ((c) & 0xFFFF)
+
+#define XPORT_RPM_GET_VERSION(c) (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_VERSION(v) (((v) << 16) & 0xFFFF0000)
+
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+
+glink_err_type xport_rpm_init(void *arg);
+#endif //XPORT_RPM_H
+
diff --git a/platform/msm_shared/include/xport_rpm_config.h b/platform/msm_shared/include/xport_rpm_config.h
new file mode 100644
index 0000000..e0e24dd
--- /dev/null
+++ b/platform/msm_shared/include/xport_rpm_config.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2015, 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 XPORT_RPM_CONFIG_H
+#define XPORT_RPM_CONFIG_H
+
+/**
+ * @file xport_rpm_config.h
+ *
+ * Internal definitions for RPM Glink transport configurations
+ */
+
+/*===========================================================================
+                        INCLUDE FILES
+===========================================================================*/
+#include "glink.h"
+#include "glink_os_utils.h"
+#include "smem_type.h"
+
+/*===========================================================================
+                      MACRO DECLARATIONS
+===========================================================================*/
+#define XPORT_RPM_TOC_MAGIC 0x67727430
+
+#define XPORT_RPM_AP2R_ID   0x61703272
+#define XPORT_RPM_R2AP_ID   0x72326170
+#define XPORT_RPM_MP2R_ID   0x6D703272
+#define XPORT_RPM_R2MP_ID   0x72326D70
+#define XPORT_RPM_AD2R_ID   0x61643272
+#define XPORT_RPM_R2AD_ID   0x72326164
+#define XPORT_RPM_SC2R_ID   0x73633272
+#define XPORT_RPM_R2SC_ID   0x72327363
+#define XPORT_RPM_WC2R_ID   0x77633272
+#define XPORT_RPM_R2WC_ID   0x72327763
+#define XPORT_RPM_TZ2R_ID   0x747A3272
+#define XPORT_RPM_R2TZ_ID   0x7232747A
+
+#define XPORT_RPM_TOC_MAGIC_IDX    0
+#define XPORT_RPM_TOC_LENGTH_IDX   1
+#define XPORT_RPM_TOC_ENTRIES_IDX  2
+
+#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
+
+/*===========================================================================
+                      TYPE DECLARATIONS
+===========================================================================*/
+typedef struct _xport_rpm_toc_entry_type
+{
+  uint32 fifo_id;                   /* FIFO ID                */
+  uint32 fifo_offset;               /* FIFO offset in MSG RAM */
+  uint32 fifo_size;                 /* FIFO size              */
+} xport_rpm_toc_entry_type;
+
+typedef struct _xport_rpm_toc_config_type
+{
+  uint32 fifo_id;                    /* FIFO ID                        */
+  smem_host_type host;               /* Host ID for MSG RAM allocation */
+  uint32 fifo_size;                  /* FIFO size                      */
+} xport_rpm_toc_config_type;
+
+
+typedef struct _xport_rpm_config_type
+{
+  const char* remote_ss;            /* Remote host name        */
+  uint32 tx_fifo_id;                /* Tx FIFO ID in RPM ToC   */
+  uint32 rx_fifo_id;                /* Rx FIFO ID in RPM ToC   */
+  os_ipc_intr_type irq_out;         /* Outgoing interrupt      */
+  uint32 irq_in;                    /* Incoming interrupt      */
+} xport_rpm_config_type;
+
+#endif //XPORT_RPM_CONFIG_H
+
diff --git a/platform/msm_shared/mdp5.c b/platform/msm_shared/mdp5.c
index ddda7ee..b48efb7 100755
--- a/platform/msm_shared/mdp5.c
+++ b/platform/msm_shared/mdp5.c
@@ -40,8 +40,7 @@
 #include <clock.h>
 #include <scm.h>
 
-#define MDP_MIN_FETCH		9
-#define MDSS_MDP_MAX_FETCH	12
+#define MDSS_MDP_MAX_PREFILL_FETCH	25
 
 int restore_secure_cfg(uint32_t id);
 
@@ -538,7 +537,8 @@
 					uint32_t intf_base)
 {
 	uint32_t mdp_hw_rev = readl(MDP_HW_REV);
-	uint32_t v_total, h_total, fetch_start, vfp_start, fetch_lines;
+	uint32_t v_total, h_total, fetch_start, vfp_start;
+	uint32_t prefetch_avail, prefetch_needed;
 	uint32_t adjust_xres = 0;
 	uint32_t fetch_enable = BIT(31);
 
@@ -554,16 +554,20 @@
 	/*
 	 * MDP programmable fetch is for MDP with rev >= 1.05.
 	 * Programmable fetch is not needed if vertical back porch
-	 * is >= 9.
+	 * plus vertical puls width is >= 25.
 	 */
 	if (mdp_hw_rev < MDSS_MDP_HW_REV_105 ||
-			lcdc->v_back_porch >= MDP_MIN_FETCH)
+			(lcdc->v_back_porch + lcdc->v_pulse_width) >=
+			MDSS_MDP_MAX_PREFILL_FETCH)
 		return;
 
 	adjust_xres = pinfo->xres;
 	if (pinfo->lcdc.split_display)
 		adjust_xres /= 2;
 
+	if (pinfo->fbc.enabled && pinfo->fbc.comp_ratio)
+		adjust_xres /= pinfo->fbc.comp_ratio;
+
 	/*
 	 * Fetch should always be outside the active lines. If the fetching
 	 * is programmed within active region, hardware behavior is unknown.
@@ -574,16 +578,19 @@
 							lcdc->h_front_porch;
 	vfp_start = lcdc->v_pulse_width + lcdc->v_back_porch + pinfo->yres;
 
-	fetch_lines = v_total - vfp_start;
+	prefetch_avail = v_total - vfp_start;
+	prefetch_needed = MDSS_MDP_MAX_PREFILL_FETCH -
+		lcdc->v_back_porch -
+		lcdc->v_pulse_width;
 
 	/*
 	 * In some cases, vertical front porch is too high. In such cases limit
-	 * the mdp fetch lines  as the last 12 lines of vertical front porch.
+	 * the mdp fetch lines  as the last (25 - vbp - vpw) lines of vertical front porch.
 	 */
-	if (fetch_lines > MDSS_MDP_MAX_FETCH)
-		fetch_lines = MDSS_MDP_MAX_FETCH;
+	if (prefetch_avail > prefetch_needed)
+		prefetch_avail = prefetch_needed;
 
-	fetch_start = (v_total - fetch_lines) * h_total + 1;
+	fetch_start = (v_total - prefetch_avail) * h_total + 1;
 
 	if (pinfo->dfps.panel_dfps.enabled)
 		fetch_enable |= BIT(23);
diff --git a/platform/msm_shared/mipi_dsi.c b/platform/msm_shared/mipi_dsi.c
index b18a508..66f95c6 100644
--- a/platform/msm_shared/mipi_dsi.c
+++ b/platform/msm_shared/mipi_dsi.c
@@ -41,6 +41,7 @@
 #include <platform/timer.h>
 #include <err.h>
 #include <msm_panel.h>
+#include <arch/ops.h>
 
 extern void mdp_disable(void);
 extern int mipi_dsi_cmd_config(struct fbcon_config mipi_fb_cfg,
@@ -218,6 +219,7 @@
 			size = 4 - size;
 		size += cm->size;
 		memcpy((uint8_t *)off, (cm->payload), size);
+		arch_clean_invalidate_cache_range((addr_t)(off), size);
 		writel(off, ctl_base + DMA_CMD_OFFSET);
 		writel(size, ctl_base + DMA_CMD_LENGTH);
 		if (dual_dsi) {
@@ -412,6 +414,10 @@
 		tmp |= BIT(28);
 		writel(tmp, mipi->ctl_base + LANE_CTL);
 	}
+
+	if ((mipi->mode == DSI_VIDEO_MODE) && mipi->tx_eot_append)
+		writel(0x1, mipi->ctl_base + EOT_PACKET_CTRL);
+
 #endif
 
 	return 0;
@@ -824,6 +830,7 @@
 			goto mipi_cmds_error;
 
 		memcpy((void *)off, (cm->payload), cm->size);
+		arch_clean_invalidate_cache_range((addr_t)(off), size);
 		writel(off, DSI_DMA_CMD_OFFSET);
 		writel(cm->size, DSI_DMA_CMD_LENGTH);	// reg 0x48 for this build
 		dsb();
diff --git a/platform/msm_shared/mmc_sdhci.c b/platform/msm_shared/mmc_sdhci.c
index 2632961..3bc7110 100644
--- a/platform/msm_shared/mmc_sdhci.c
+++ b/platform/msm_shared/mmc_sdhci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -240,6 +240,9 @@
 		card->wp_grp_size = (card->csd.wp_grp_size + 1) * (card->csd.erase_grp_size + 1) \
 					  * (card->csd.erase_grp_mult + 1);
 
+	card->rpmb_size = RPMB_PART_MIN_SIZE * card->ext_csd[RPMB_SIZE_MULT];
+	card->rel_wr_count = card->ext_csd[REL_WR_SEC_C];
+
 	dprintf(SPEW, "Decoded CSD fields:\n");
 	dprintf(SPEW, "cmmc_structure: %u\n", mmc_csd.cmmc_structure);
 	dprintf(SPEW, "card_cmd_class: %x\n", mmc_csd.card_cmd_class);
@@ -2366,3 +2369,107 @@
 	if(sdhci_send_command(&dev->host, &cmd))
 		dprintf(CRITICAL, "card sleep error: %s\n", __func__);
 }
+
+/*
+ * Switch the partition access type to rpmb or default
+ */
+static uint32_t mmc_sdhci_switch_part(struct mmc_device *dev, uint32_t type)
+{
+	uint32_t part_access;
+	uint32_t ret;
+
+	/* Clear the partition access */
+	part_access = dev->card.ext_csd[MMC_PARTITION_CONFIG] & ~PARTITION_ACCESS_MASK;
+	part_access |= type;
+
+	ret = mmc_switch_cmd(&dev->host, &dev->card, MMC_ACCESS_WRITE, MMC_PARTITION_CONFIG, part_access);
+
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to switch partition to type: %u\n", type);
+		return 1;
+	}
+
+	dev->card.ext_csd[MMC_PARTITION_CONFIG] = part_access;
+	return 0;
+}
+
+static uint32_t mmc_sdhci_set_blk_cnt(struct mmc_device *dev, uint32_t blk_cnt, uint32_t rel_write)
+{
+	struct mmc_command cmd = {0};
+
+	cmd.cmd_index = CMD23_SET_BLOCK_COUNT;
+	cmd.argument = blk_cnt & 0x0000ffff;
+	cmd.argument |= rel_write;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+
+	if (sdhci_send_command(&dev->host, &cmd))
+	{
+		dprintf(CRITICAL, "Set block count failed: %s\n", __func__);
+		return 1;
+	}
+
+	return 0;
+}
+
+uint32_t mmc_sdhci_rpmb_send(struct mmc_device *dev, struct mmc_command *cmd)
+{
+	int i;
+	uint32_t retry = 5;
+	uint32_t status;
+	uint32_t rel_write = 0;
+	uint32_t ret = 1;
+
+	ASSERT(cmd);
+
+	/* 1. Set the partition type to rpmb */
+	if (mmc_sdhci_switch_part(dev, PART_ACCESS_RPMB))
+		return 1;
+
+	for (i = 0; i < MAX_RPMB_CMDS; i++)
+	{
+		if (!cmd[i].cmd_index)
+			break;
+
+		if (cmd[i].write_flag == true)
+			rel_write = BIT(31);
+		else
+			rel_write = 0;
+
+		/* 2. Set the block count using cmd23 */
+		if (mmc_sdhci_set_blk_cnt(dev, cmd[i].data.num_blocks, rel_write))
+			goto err;
+
+		/* 3. Send the command */
+		if (sdhci_send_command(&dev->host, &cmd[i]))
+			goto err;
+		do
+		{
+			/* 4. Poll for card status to ensure rpmb operation completeness */
+			if (mmc_get_card_status(&dev->host, &dev->card, &status))
+			{
+				dprintf(CRITICAL, "Failed to get card status after rpmb operations\n");
+				goto err;
+			}
+
+			retry--;
+			udelay(500);
+			if (!retry)
+			{
+				dprintf(CRITICAL, "Card status check timed out after rpmb operations\n");
+				goto err;
+			}
+		} while(!(status & MMC_READY_FOR_DATA) || (MMC_CARD_STATUS(status) == MMC_PROG_STATE));
+	}
+
+	/* If we reach here, that means success */
+	ret = 0;
+
+err:
+	/* 5. Switch the partition back to default type */
+	if (mmc_sdhci_switch_part(dev, PART_ACCESS_DEFAULT))
+		ret = 1;
+
+	return ret;
+}
diff --git a/platform/msm_shared/mmc_wrapper.c b/platform/msm_shared/mmc_wrapper.c
index bcec0ad..10e9955 100755
--- a/platform/msm_shared/mmc_wrapper.c
+++ b/platform/msm_shared/mmc_wrapper.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -124,6 +124,12 @@
 	if (data_len % block_size)
 		data_len = ROUNDUP(data_len, block_size);
 
+	/*
+	 * Flush the cache before handing over the data to
+	 * storage driver
+	 */
+	arch_clean_invalidate_cache_range((addr_t)in, data_len);
+
 	if (platform_boot_dev_isemmc())
 	{
 		/* TODO: This function is aware of max data that can be
@@ -151,8 +157,6 @@
 	}
 	else
 	{
-		arch_clean_invalidate_cache_range((addr_t)in, data_len);
-
 		ret = ufs_write((struct ufs_dev *)dev, data_addr, (addr_t)in, (data_len / block_size));
 
 		if (ret)
@@ -185,6 +189,13 @@
 	ASSERT(!(data_addr % block_size));
 	ASSERT(!(data_len % block_size));
 
+	/*
+	 * dma onto write back memory is unsafe/nonportable,
+	 * but callers to this routine normally provide
+	 * write back buffers. Invalidate cache
+	 * before read data from mmc.
+         */
+	arch_clean_invalidate_cache_range((addr_t)(out), data_len);
 
 	if (platform_boot_dev_isemmc())
 	{
@@ -296,6 +307,9 @@
 
 	memset((void *)out, 0, erase_size);
 
+	/* Flush the data to memory before writing to storage */
+	arch_clean_invalidate_cache_range((addr_t) out , erase_size);
+
 	if (mmc_sdhci_write(dev, out, blk_addr, num_blks))
 	{
 		dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr);
@@ -597,7 +611,9 @@
 	unsigned long long  ptn = 0;
 	uint64_t size;
 	int index = -1;
+#ifdef UFS_SUPPORT
 	int ret = 0;
+#endif
 
 	dev = target_mmc_device();
 	block_size = mmc_get_device_blocksize();
@@ -614,7 +630,8 @@
 			return 1;
 		}
 
-		size = partition_get_size(index);
+		/* Convert the size to blocks */
+		size = partition_get_size(index) / block_size;
 
 		/*
 		 * For read only partitions the minimum size allocated on the disk is
@@ -623,13 +640,20 @@
 		 */
 		if (partition_read_only(index) && size < card->wp_grp_size)
 		{
+			/* Write protect api takes the size in bytes, convert size to bytes */
 			size = card->wp_grp_size * block_size;
 		}
+		else
+		{
+			size *= block_size;
+		}
+
 		/* Set the power on WP bit */
 		return mmc_set_clr_power_on_wp_user((struct mmc_device *)dev, (ptn / block_size), size, set_clr);
 	}
 	else
 	{
+#ifdef UFS_SUPPORT
 		/* Enable the power on WP fo all LUNs which have WP bit is enabled */
 		ret = dme_set_fpoweronwpen((struct ufs_dev*) dev);
 		if (ret < 0)
@@ -637,6 +661,7 @@
 			dprintf(CRITICAL, "Failure to WP UFS partition\n");
 			return 1;
 		}
+#endif
 	}
 
 	return 0;
diff --git a/platform/msm_shared/partition_parser.c b/platform/msm_shared/partition_parser.c
index 38b2a80..970d7ce 100644
--- a/platform/msm_shared/partition_parser.c
+++ b/platform/msm_shared/partition_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 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
@@ -872,10 +872,8 @@
 		return INVALID_PTN;
 	}
 	for (n = 0; n < partition_count; n++) {
-		if (!memcmp
-		    (name, &partition_entries[n].name, input_string_length)
-		    && input_string_length ==
-		    strlen((const char *)&partition_entries[n].name)) {
+		if ((input_string_length == strlen((const char *)&partition_entries[n].name))
+			&& !memcmp(name, &partition_entries[n].name, input_string_length)) {
 			return n;
 		}
 	}
@@ -978,7 +976,7 @@
 {
 	unsigned int type_offset = TABLE_ENTRY_0 + OFFSET_TYPE;
 
-	if (size < type_offset) {
+	if (size < (type_offset + sizeof (*partition_type))) {
 		goto end;
 	}
 
diff --git a/platform/msm_shared/qseecom_lk.c b/platform/msm_shared/qseecom_lk.c
new file mode 100644
index 0000000..4374601
--- /dev/null
+++ b/platform/msm_shared/qseecom_lk.c
@@ -0,0 +1,1400 @@
+/* Copyright (c) 2012-2015, 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.
+ */
+
+#define pr_fmt(fmt) "QSEECOM: %s: " fmt, __func__
+
+#include <partition_parser.h>
+#include <qseecom_lk.h>
+#include <scm.h>
+#include <qseecomi_lk.h>
+#include "qseecom_lk_api.h"
+#include <debug.h>
+#include <kernel/mutex.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <arch/defines.h>
+#include <string.h>
+#include <platform/iomap.h>
+#include <platform.h>
+
+#define QSEOS_VERSION_14  0x14
+#define QSEEE_VERSION_00  0x400000
+#define QSEE_VERSION_20   0x800000
+
+
+#define QSEOS_CHECK_VERSION_CMD  0x00001803
+
+#define MAX_SCM_ARGS 10
+#define N_EXT_SCM_ARGS 7
+#define FIRST_EXT_ARG_IDX 3
+
+#define N_REGISTER_ARGS (MAX_SCM_ARGS - N_EXT_SCM_ARGS + 1)
+
+#define QSEE_LOG_BUF_SIZE (4096)
+#define GENERIC_ERROR -1
+#define LISTENER_ALREADY_PRESENT_ERROR -2
+
+#define TZ_CALL 6
+enum qseecom_client_handle_type {
+	QSEECOM_CLIENT_APP = 1,
+	QSEECOM_LISTENER_SERVICE,
+	QSEECOM_SECURE_SERVICE,
+	QSEECOM_GENERIC,
+	QSEECOM_UNAVAILABLE_CLIENT_APP,
+};
+
+struct qseecom_registered_listener_list {
+	struct list_node node;
+	struct qseecom_register_listener_req svc;
+	ListenerCallback CallbackFn;
+};
+
+struct qseecom_registered_app_list {
+	struct list_node node;
+	uint32_t  app_id;
+	uint32_t  ref_cnt;
+	char app_name[MAX_APP_NAME_SIZE];
+	int  handle;
+};
+
+struct qseecom_control {
+	struct list_node  registered_listener_list_head;
+	mutex_t           registered_listener_list_lock;
+
+	struct list_node  registered_app_list_head;
+	mutex_t           registered_app_list_lock;
+
+	uint32_t          qseos_version;
+	uint32_t          qsee_version;
+	int               handle;
+	bool              commonlib_loaded;
+	mutex_t           global_data_lock;
+	uint32_t          cmnlib_loaded;
+	uint32_t          qseecom_init_done;
+	uint32_t          qseecom_tz_init_done;
+};
+
+struct qseecom_listener_handle {
+	uint32_t               id;
+};
+
+static struct qseecom_reg_log_buf_ireq logbuf_req;
+static struct qseecom_control qseecom;
+static int __qseecom_process_incomplete_cmd(struct qseecom_command_scm_resp *resp,
+          struct qseecom_client_listener_data_irsp *send_data_rsp);
+
+/*
+ * Appsbl runs in Aarch32 when this is ported for Aarch64,
+ * change return type for uint64_t.
+ */
+static uint32_t __qseecom_uvirt_to_kphys(uint64_t virt)
+{
+	dprintf(SPEW, "%s called\n", __func__);
+	return (uint32_t)platform_get_virt_to_phys_mapping((addr_t)virt);
+}
+
+static int _disp_log_stats(struct tzdbg_log_t *log, uint32_t log_len,
+		uint32_t startOffset, uint32_t endOffset)
+{
+	uint32_t MaxBufSize = 0;
+	uint32_t LogBufSize = 0;
+	uint32_t LogBufFirstHalf = 0;
+	uint32_t len = 0;
+	char *pCurPos, *pPrintPos = NULL;
+	void *pLogBuf = NULL;
+	int ret = GENERIC_ERROR;
+
+	MaxBufSize = QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t);
+
+	dprintf(SPEW, "%s called\n", __func__);
+	if (startOffset < endOffset)
+	{
+		LogBufSize = endOffset - startOffset;
+		pLogBuf = malloc(LogBufSize);
+		if (NULL == pLogBuf)
+		{
+			ret = GENERIC_ERROR;
+			dprintf(CRITICAL, "Failed to alloc buffer to print TZ Log:%u\n", LogBufSize);
+			goto err;
+		}
+		memset(pLogBuf, 0, LogBufSize);
+		memscpy(pLogBuf, LogBufSize, (char *)((uint32_t)log->log_buf + startOffset), LogBufSize);
+	}
+	else if ( endOffset < startOffset)
+	{
+		LogBufSize =  MaxBufSize - (startOffset - endOffset);
+		LogBufFirstHalf = MaxBufSize - startOffset;
+		pLogBuf = malloc(LogBufSize);
+		if (NULL == pLogBuf)
+		{
+			ret = GENERIC_ERROR;
+			dprintf(CRITICAL, "Failed to alloc buffer to print TZ Log:%u\n", LogBufSize);
+			goto err;
+		}
+		memset(pLogBuf, 0, LogBufSize);
+		memscpy(pLogBuf, LogBufSize, (char *)((uint32_t)log->log_buf + startOffset), LogBufFirstHalf);
+		memscpy((char *)((uint32_t)pLogBuf+ LogBufFirstHalf), (LogBufSize - LogBufFirstHalf), log->log_buf, endOffset);
+	}
+	else //endOffset == startOffset
+	{
+		ret = 0;
+		goto err;
+	}
+
+	/*
+	 *  Read from ring buff while there is data and space in return buff
+	 */
+	pCurPos = pLogBuf;
+	pPrintPos = pCurPos;
+	while (len < LogBufSize)
+	{
+			//QSEE separate each line by "\r \n"
+			if ((*pCurPos == '\r')&&(*(pCurPos+1) == '\n'))
+			{
+				//update the line to dump
+				*pCurPos = '\0';
+				len++;
+				pCurPos++;
+				*pCurPos = '\0';
+				len++;
+				pCurPos++;
+				dprintf(ALWAYS, "%s\n", pPrintPos);
+				pPrintPos = pCurPos;
+				continue;
+			}
+			len++;
+			pCurPos++;
+	}
+	ret = 0;
+	free(pLogBuf);
+err:
+	return ret;
+}
+
+static int allocate_extra_arg_buffer(uint32_t fn_id, struct scm_desc *desc)
+{
+	int i;
+	int ret = GENERIC_ERROR;
+	scmcall_arg arg = {0};
+	scmcall_ret ret_arg = {0};
+	int arglen = 0;
+
+	if (!desc) {
+		dprintf(CRITICAL, "%s: Invalid input\n", __func__);
+		return GENERIC_ERROR;
+	}
+
+	dprintf(SPEW, "%s called\n", __func__);
+	arglen = desc->arginfo & 0xf;
+
+	dprintf(SPEW, "%s:fn_id:%u, desc->arginfo:%u desc->args[0]:%u desc->args[1]:%u desc->args[2]:%u desc->args[3]:%u desc->args[4]:%u\n",
+			__func__, fn_id, desc->arginfo, desc->args[0], desc->args[1], desc->args[2], desc->args[3], desc->args[4]);
+
+	arg.x0 = fn_id;
+	arg.x1 = desc->arginfo;
+	arg.x2 = desc->args[0];
+	arg.x3 = desc->args[1];
+	arg.x4 = desc->args[2];
+
+	if (arglen > FIRST_EXT_ARG_IDX) {
+		for (i = 0; i < (arglen - FIRST_EXT_ARG_IDX); i++) {
+			arg.x5[i] = desc->args[i + FIRST_EXT_ARG_IDX];
+		}
+	}
+	ret = scm_call2(&arg, &ret_arg);
+	desc->ret[0] = ret_arg.x1;
+	desc->ret[1] = ret_arg.x2;
+	desc->ret[2] = ret_arg.x3;
+
+	dprintf(SPEW, "%s:ret:%d, desc->ret[0]]:%u desc->ret[1]:%u desc->ret[2]:%u\n",
+			__func__, ret, desc->ret[0], desc->ret[1], desc->ret[2]);
+	return ret;
+}
+
+static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
+			const void *req_buf, void *resp_buf)
+{
+	int      ret = 0;
+	uint32_t smc_id = 0;
+	uint32_t qseos_cmd_id = 0;
+	struct scm_desc desc = {0};
+	struct qseecom_command_scm_resp *scm_resp = NULL;
+
+	if (!req_buf || !resp_buf) {
+		dprintf(CRITICAL, "Invalid buffer pointer\n");
+		return GENERIC_ERROR;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+
+	qseos_cmd_id = *(uint32_t *)req_buf;
+	scm_resp = (struct qseecom_command_scm_resp *)resp_buf;
+
+	switch (svc_id) {
+		case TZ_CALL: {
+			if (tz_cmd_id == 1) {
+				smc_id = TZ_INFO_IS_SVC_AVAILABLE_ID;
+				desc.arginfo = TZ_INFO_IS_SVC_AVAILABLE_ID_PARAM_ID;
+				desc.args[0] = TZ_INFO_GET_FEATURE_VERSION_ID;
+			} else if (tz_cmd_id == 3) {
+				smc_id = TZ_INFO_GET_FEATURE_VERSION_ID;
+				desc.arginfo = TZ_INFO_GET_FEATURE_VERSION_ID_PARAM_ID;
+				desc.args[0] = *(uint32_t *)req_buf;
+			}
+			ret = allocate_extra_arg_buffer(smc_id, &desc);
+			break;
+		}
+
+		case SCM_SVC_TZSCHEDULER: {
+			switch (qseos_cmd_id) {
+				case QSEE_APP_START_COMMAND: {
+					struct qseecom_load_app_ireq *req;
+					req = (struct qseecom_load_app_ireq *)req_buf;
+					smc_id = TZ_OS_APP_START_ID;
+					desc.arginfo = TZ_OS_APP_START_ID_PARAM_ID;
+					desc.args[0] = req->mdt_len;
+					desc.args[1] = req->img_len;
+					desc.args[2] = req->phy_addr;
+					dprintf(SPEW, "args[0]:%u args[1]:%u args[2]:%u\n",
+							desc.args[0], desc.args[1], desc.args[2]);
+					dprintf(SPEW, "mdt_len:%u img_len:%u phy_addr:%u\n",
+							req->mdt_len, req->img_len, req->phy_addr);
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+
+					break;
+				}
+				case QSEE_APP_SHUTDOWN_COMMAND: {
+					struct qseecom_unload_app_ireq *req;
+					req = (struct qseecom_unload_app_ireq *)req_buf;
+					smc_id = TZ_OS_APP_SHUTDOWN_ID;
+					desc.arginfo = TZ_OS_APP_SHUTDOWN_ID_PARAM_ID;
+					desc.args[0] = req->app_id;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_APP_REGION_NOTIFICATION: {
+					struct qsee_apps_region_info_ireq *req;
+					req = (struct qsee_apps_region_info_ireq *)req_buf;
+					smc_id = TZ_OS_APP_REGION_NOTIFICATION_ID;
+					desc.arginfo =
+						TZ_OS_APP_REGION_NOTIFICATION_ID_PARAM_ID;
+					desc.args[0] = req->addr;
+					desc.args[1] = req->size;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_LOAD_SERV_IMAGE_COMMAND: {
+					struct qseecom_load_app_ireq *req;
+					req = (struct qseecom_load_app_ireq *)req_buf;
+					smc_id = TZ_OS_LOAD_SERVICES_IMAGE_ID;
+					desc.arginfo = TZ_OS_LOAD_SERVICES_IMAGE_ID_PARAM_ID;
+					desc.args[0] = req->mdt_len;
+					desc.args[1] = req->img_len;
+					desc.args[2] = req->phy_addr;
+					dprintf(SPEW, "QSEE_LOAD_SERV_IMAGE_COMMAND mdt_len:%u img_len:%u phy_addr:%u\n",
+							req->mdt_len, req->img_len, req->phy_addr);
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_UNLOAD_SERV_IMAGE_COMMAND: {
+					smc_id = TZ_OS_UNLOAD_SERVICES_IMAGE_ID;
+					desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_REGISTER_LISTENER: {
+					struct qseecom_register_listener_ireq *req;
+					req = (struct qseecom_register_listener_ireq *)req_buf;
+					smc_id = TZ_OS_REGISTER_LISTENER_ID;
+					desc.arginfo =
+						TZ_OS_REGISTER_LISTENER_ID_PARAM_ID;
+					desc.args[0] = req->listener_id;
+					desc.args[1] = req->sb_ptr;
+					desc.args[2] = req->sb_len;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_DEREGISTER_LISTENER: {
+					struct qseecom_unregister_listener_ireq *req;
+					req = (struct qseecom_unregister_listener_ireq *)
+						req_buf;
+					smc_id = TZ_OS_DEREGISTER_LISTENER_ID;
+					desc.arginfo = TZ_OS_DEREGISTER_LISTENER_ID_PARAM_ID;
+					desc.args[0] = req->listener_id;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_LISTENER_DATA_RSP_COMMAND: {
+					struct qseecom_client_listener_data_irsp *req;
+					req = (struct qseecom_client_listener_data_irsp *)
+						req_buf;
+					smc_id = TZ_OS_LISTENER_RESPONSE_HANDLER_ID;
+					desc.arginfo =
+						TZ_OS_LISTENER_RESPONSE_HANDLER_ID_PARAM_ID;
+					desc.args[0] = req->listener_id;
+					desc.args[1] = req->status;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_CLIENT_SEND_DATA_COMMAND: {
+					struct qseecom_client_send_data_ireq *req;
+					req = (struct qseecom_client_send_data_ireq *)req_buf;
+					smc_id = TZ_APP_QSAPP_SEND_DATA_ID;
+					desc.arginfo = TZ_APP_QSAPP_SEND_DATA_ID_PARAM_ID;
+					desc.args[0] = req->app_id;
+					desc.args[1] = req->req_ptr;
+					desc.args[2] = req->req_len;
+					desc.args[3] = req->rsp_ptr;
+					desc.args[4] = req->rsp_len;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_RPMB_PROVISION_KEY_COMMAND: {
+					struct qseecom_client_send_service_ireq *req;
+					req = (struct qseecom_client_send_service_ireq *)
+						req_buf;
+					smc_id = TZ_OS_RPMB_PROVISION_KEY_ID;
+					desc.arginfo = TZ_OS_RPMB_PROVISION_KEY_ID_PARAM_ID;
+					desc.args[0] = req->key_type;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				case QSEE_RPMB_ERASE_COMMAND: {
+					smc_id = TZ_OS_RPMB_ERASE_ID;
+					desc.arginfo = TZ_OS_RPMB_ERASE_ID_PARAM_ID;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+
+				case QSEE_REGISTER_LOG_BUF_COMMAND: {
+					struct qseecom_reg_log_buf_ireq *req;
+					req = (struct qseecom_reg_log_buf_ireq *)req_buf;
+					smc_id = TZ_OS_REGISTER_LOG_BUFFER_ID;
+					desc.arginfo = TZ_OS_REGISTER_LOG_BUFFER_ID_PARAM_ID;
+					desc.args[0] = req->phy_addr;
+					desc.args[1] = req->len;
+					ret = allocate_extra_arg_buffer(smc_id, &desc);
+					break;
+				}
+				default: {
+					dprintf(CRITICAL, "qseos_cmd_id 0x%d is not supported by armv8 scm_call2.\n",
+								qseos_cmd_id);
+					ret = GENERIC_ERROR;
+					break;
+				}
+			} /*end of switch (qsee_cmd_id)  */
+			break;
+		} /*end of case SCM_SVC_TZSCHEDULER*/
+		default: {
+			dprintf(CRITICAL, "svc_id 0x%x is not supported by armv8 scm_call2.\n",
+						svc_id);
+			ret = GENERIC_ERROR;
+			break;
+		}
+	} /*end of switch svc_id */
+	scm_resp->result = desc.ret[0];
+	scm_resp->resp_type = desc.ret[1];
+	scm_resp->data = desc.ret[2];
+	dprintf(SPEW, "svc_id = 0x%x, tz_cmd_id = 0x%x, qseos_cmd_id = 0x%x, smc_id = 0x%x, param_id = 0x%x\n",
+		svc_id, tz_cmd_id, qseos_cmd_id, smc_id, desc.arginfo);
+	dprintf(SPEW, "scm_resp->result = 0x%x, scm_resp->resp_type = 0x%x, scm_resp->data = 0x%x\n",
+		scm_resp->result, scm_resp->resp_type, scm_resp->data);
+	return ret;
+}
+
+static int qseecom_scm_call(uint32_t svc_id, uint32_t tz_cmd_id, void *cmd_buf,
+		size_t cmd_len, void *resp_buf, size_t resp_len)
+{
+	void *req = NULL;
+	struct qseecom_command_scm_resp *resp = NULL;
+	struct qseecom_client_listener_data_irsp send_data_rsp = {0};
+	int ret = GENERIC_ERROR;
+	uint32_t qseos_cmd_id = 0;
+
+	if ((!cmd_buf) || (!resp_buf))
+			return GENERIC_ERROR;
+
+	dprintf(SPEW, "%s called\n", __func__);
+	mutex_acquire(&qseecom.registered_app_list_lock);
+	req = cmd_buf;
+	qseos_cmd_id = *(uint32_t *)req;
+	resp = (struct qseecom_command_scm_resp *) resp_buf;
+
+	do {
+		if (!is_scm_armv8_support()) {
+			ret = scm_call(svc_id, tz_cmd_id, req, cmd_len,
+					resp_buf, resp_len);
+		} else {
+			ret = qseecom_scm_call2(svc_id, tz_cmd_id, req, resp);
+		}
+
+		if (ret) {
+			dprintf(CRITICAL, "ERROR: scm_call to load failed : ret %d\n", ret);
+			ret = GENERIC_ERROR;
+			goto err;
+		}
+
+		if (svc_id == TZ_CALL) {
+			goto err;
+		}
+
+		switch (resp->result) {
+			case QSEOS_RESULT_SUCCESS:
+				if(((resp->resp_type != QSEOS_APP_ID) || (resp->data <= 0)) &&
+					((qseos_cmd_id == QSEE_CLIENT_SEND_DATA_COMMAND) ||
+							(qseos_cmd_id == QSEE_LISTENER_DATA_RSP_COMMAND)))
+				{
+					dprintf(CRITICAL, "ERROR: Resp type %d or Resp Data %d incorrect\n",
+							resp->resp_type, resp->data);
+					ret = GENERIC_ERROR;
+					goto err;
+				}
+				goto err;
+			case QSEOS_RESULT_FAILURE:
+				dprintf(CRITICAL, "scm call failed w/response result%d\n", resp->result);
+				ret = GENERIC_ERROR;
+				goto err;
+			case  QSEOS_RESULT_INCOMPLETE:
+				if(resp->resp_type != QSEOS_LISTENER_ID)
+				{
+					ret = GENERIC_ERROR;
+					dprintf(CRITICAL, "Listener service incorrect resp->result:%d resp->resp_type:%d\n",
+							resp->result, resp->resp_type);
+					goto err;
+				}
+				__qseecom_process_incomplete_cmd(resp, &send_data_rsp);
+				req = (void *)&send_data_rsp;
+				qseos_cmd_id = QSEE_LISTENER_DATA_RSP_COMMAND;
+				break;
+			default:
+				dprintf(CRITICAL, "scm call return unknown response %d\n",	resp->result);
+				ret = GENERIC_ERROR;
+				goto err;
+		}
+	} while(true);
+
+err:
+	mutex_release(&qseecom.registered_app_list_lock);
+	return ret;
+
+}
+
+static int __qseecom_process_incomplete_cmd(struct qseecom_command_scm_resp *resp,
+		struct qseecom_client_listener_data_irsp *send_data_rsp)
+{
+	int ret = 0;
+	struct qseecom_registered_listener_list *entry;
+
+	if ((!resp) || (!send_data_rsp))
+	{
+		return GENERIC_ERROR;
+	}
+
+	dprintf(SPEW, "%s called\n", __func__);
+	mutex_acquire(&qseecom.global_data_lock);
+
+	list_for_every_entry(&qseecom.registered_listener_list_head,
+			entry, struct qseecom_registered_listener_list, node) {
+		if (resp->data == entry->svc.listener_id) {
+			arch_invalidate_cache_range((addr_t) entry->svc.virt_sb_base, entry->svc.sb_size);
+			entry->CallbackFn(entry->svc.virt_sb_base, entry->svc.sb_size);
+			arch_clean_invalidate_cache_range((addr_t) entry->svc.virt_sb_base, entry->svc.sb_size);
+			break;
+		}
+	}
+	send_data_rsp->qsee_cmd_id = QSEE_LISTENER_DATA_RSP_COMMAND;
+	send_data_rsp->listener_id  = entry->svc.listener_id;
+	send_data_rsp->status  = 0;
+	mutex_release(&qseecom.global_data_lock);
+	return ret;
+}
+
+static int __qseecom_load_app(const char *app_name, unsigned int *app_id)
+{
+	int index = INVALID_PTN;
+	unsigned long long ptn = 0;
+	unsigned long long size = 0;
+	void *buf = NULL;
+	void *req = NULL;
+	struct qseecom_load_app_ireq load_req = {0};
+	struct qseecom_command_scm_resp resp;
+	struct tzdbg_log_t *log = NULL;
+	uint32_t QseeLogStart = 0;
+	uint32_t QseeLogNewStart = 0;
+
+	int ret = GENERIC_ERROR;
+	uint8_t lun = 0;
+
+	if (!app_name)
+		return GENERIC_ERROR;
+
+	dprintf(SPEW, "%s called\n", __func__);
+	index = partition_get_index(app_name);
+	lun = partition_get_lun(index);
+	mmc_set_lun(lun);
+
+	size = partition_get_size(index);
+
+	buf = memalign(PAGE_SIZE, ROUNDUP(size, PAGE_SIZE));
+	if (!buf) {
+		dprintf(CRITICAL, "%s: Aloc failed for %s image\n",
+				__func__, app_name);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+
+	ptn = partition_get_offset(index);
+	if(ptn == 0) {
+		dprintf(CRITICAL, "ERROR: No %s found\n", app_name);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+	if (mmc_read(ptn, (unsigned int *) buf, size)) {
+		dprintf(CRITICAL, "ERROR: Cannot read %s image\n", app_name);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+
+	/* Currently on 8994 only 32-bit phy addr is supported
+	 * Hence downcasting is okay
+	 */
+	load_req.phy_addr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
+	load_req.qsee_cmd_id = QSEE_APP_START_COMMAND;
+	load_req.img_len = size;
+	load_req.mdt_len = 0;
+	dprintf(SPEW, "phy_addr:%u img_len:%u\n", load_req.phy_addr, load_req.img_len);
+
+	memscpy(&load_req.app_name, MAX_APP_NAME_SIZE, app_name, MAX_APP_NAME_SIZE);
+	req = (void *)&load_req;
+
+	log = (struct tzdbg_log_t *)logbuf_req.phy_addr;
+	arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
+	QseeLogStart = (uint32_t) log->log_pos.offset;
+
+	arch_clean_invalidate_cache_range((addr_t) load_req.phy_addr, load_req.img_len);
+	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, req,
+				sizeof(struct qseecom_load_lib_image_ireq),
+							&resp, sizeof(resp));
+	if(ret == 0)
+		*app_id = resp.data;
+	else
+		*app_id = 0;
+	arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
+	QseeLogNewStart = (uint32_t) log->log_pos.offset;
+
+	_disp_log_stats((struct tzdbg_log_t *) logbuf_req.phy_addr, QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t),
+			QseeLogStart, QseeLogNewStart);
+err:
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+static int qseecom_load_commonlib_image(char * app_name)
+{
+	int index = INVALID_PTN;
+	unsigned long long ptn = 0;
+	unsigned long long size = 0;
+	void *buf = NULL;
+	void *req = NULL;
+	struct qseecom_load_app_ireq load_req = {0};
+	struct qseecom_command_scm_resp resp = {0};
+	int ret = GENERIC_ERROR;
+	uint8_t lun = 0;
+
+	dprintf(SPEW, "%s called\n", __func__);
+	index = partition_get_index(app_name);
+	lun = partition_get_lun(index);
+	mmc_set_lun(lun);
+
+	size = partition_get_size(index);
+
+	buf = memalign(PAGE_SIZE, ROUNDUP(size, PAGE_SIZE));
+	if (!buf) {
+		dprintf(CRITICAL, "%s: Aloc failed for %s image\n",
+				__func__, app_name);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+
+	ptn = partition_get_offset(index);
+	if(ptn == 0) {
+		dprintf(CRITICAL, "ERROR: No %s found\n", app_name);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+	if (mmc_read(ptn, (unsigned int *) buf, size)) {
+		dprintf(CRITICAL, "ERROR: Cannot read %s image\n", app_name);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+
+	/* Currently on 8994 only 32-bit phy addr is supported
+	 * Hence downcasting is okay
+	 */
+	load_req.phy_addr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
+	load_req.qsee_cmd_id = QSEE_LOAD_SERV_IMAGE_COMMAND;
+	load_req.img_len = size;
+	load_req.mdt_len = 0;
+
+	memscpy(load_req.app_name, MAX_APP_NAME_SIZE, app_name, MAX_APP_NAME_SIZE);
+	req = (void *)&load_req;
+
+	arch_clean_invalidate_cache_range((addr_t) load_req.phy_addr, load_req.img_len);
+	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, req,
+				sizeof(struct qseecom_load_lib_image_ireq),
+							&resp, sizeof(resp));
+	if(ret == 0)
+		ret = resp.data;
+
+err:
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+static int qseecom_unload_commonlib_image(void)
+{
+	int ret = GENERIC_ERROR;
+	struct qseecom_unload_lib_image_ireq unload_req = {0};
+	struct qseecom_command_scm_resp resp;
+
+	dprintf(SPEW, "%s called\n", __func__);
+	/* Populate the remaining parameters */
+	unload_req.qsee_cmd_id = QSEE_UNLOAD_SERV_IMAGE_COMMAND;
+	/* SCM_CALL to load the image */
+	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &unload_req,
+			sizeof(struct qseecom_unload_lib_image_ireq),
+						&resp, sizeof(resp));
+	return ret;
+}
+
+/*
+ * This function is called with the global
+ * data mutex acquired.
+ */
+static struct qseecom_registered_app_list *
+	__qseecom_add_app_entry(char *app_name, uint32_t app_id)
+{
+	struct qseecom_registered_app_list *entry = NULL;
+	int32_t ret = GENERIC_ERROR;
+
+	if ((!app_name) || (app_id == 0)) {
+		dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
+		return NULL;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+
+	entry = malloc(sizeof(*entry));
+	if (!entry) {
+		dprintf(CRITICAL, "malloc for app entry failed\n");
+		ret =  GENERIC_ERROR;
+		goto err;
+	}
+	entry->app_id = app_id;
+	entry->ref_cnt = 1;
+	strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE);
+
+	dprintf(SPEW, "%s: Adding app:%s app_id:%u to list\n", __func__, entry->app_name, entry->app_id);
+	list_add_tail(&qseecom.registered_app_list_head, &entry->node);
+	ret = 0;
+err:
+	if (entry && (ret < 0)) {
+		free(entry);
+		return NULL;
+	}
+	return entry;
+}
+
+/*
+ * This function is called with the global
+ * data mutex acquired.
+ */
+static int
+	__qseecom_remove_app_entry(struct qseecom_registered_app_list *entry)
+{
+	if (!entry) {
+		dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
+		return GENERIC_ERROR;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+	list_delete(&entry->node);
+	free(entry);
+
+	return 0;
+}
+
+/*
+ * This function is called with the global
+ * data mutex acquired.
+ */
+struct qseecom_registered_listener_list *
+	__qseecom_check_listener_exists(uint32_t listener_id)
+{
+	struct qseecom_registered_listener_list *entry = NULL;
+	bool listener_present = false;
+
+	if (!listener_id) {
+		dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
+		return NULL;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+
+	list_for_every_entry(&qseecom.registered_listener_list_head,
+			entry, struct qseecom_registered_listener_list, node) {
+		if (entry->svc.listener_id == listener_id) {
+			listener_present = true;
+			break;
+		}
+	}
+	if (listener_present)
+		return entry;
+	else
+		return NULL;
+}
+
+/*
+ * This function is called with the global
+ * data mutex acquired.
+ */
+static struct qseecom_registered_app_list
+	*__qseecom_check_handle_exists(int handle)
+{
+	struct qseecom_registered_app_list *entry;
+	bool app_present = false;
+
+	if (handle <= 0) {
+		dprintf(CRITICAL, "%s: Invalid Input\n", __func__);
+		return NULL;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+	list_for_every_entry(&qseecom.registered_app_list_head,
+			entry, struct qseecom_registered_app_list, node) {
+		if (entry->handle == handle) {
+			app_present = true;
+			break;
+		}
+	}
+
+	if (app_present == true)
+		return entry;
+	else
+		return NULL;
+
+}
+
+
+static struct qseecom_registered_app_list *
+	__qseecom_check_app_exists(char *app_name)
+{
+	struct qseecom_registered_app_list *entry = NULL;
+
+	dprintf(SPEW, "%s called\n", __func__);
+	list_for_every_entry(&qseecom.registered_app_list_head,
+			entry, struct qseecom_registered_app_list, node) {
+		if (!strncmp(app_name, entry->app_name, 32)) {
+			dprintf(SPEW, "%s: app_name:%s\n", __func__, app_name);
+			return entry;
+		}
+	}
+	return NULL;
+}
+
+static int qseecom_unload_app(uint32_t app_id)
+{
+	int ret = 0;
+	struct qseecom_command_scm_resp resp;
+	struct qseecom_unload_app_ireq req;
+
+	dprintf(SPEW, "%s called\n", __func__);
+	/* Populate the structure for sending scm call to load image */
+	req.qsee_cmd_id = QSEE_APP_SHUTDOWN_COMMAND;
+	req.app_id = app_id;
+
+	/* SCM_CALL to unload the app */
+	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+			sizeof(struct qseecom_unload_app_ireq),
+			&resp, sizeof(resp));
+
+	return ret;
+}
+
+
+static int __qseecom_send_cmd(uint32_t app_id, struct qseecom_send_cmd_req *req)
+{
+	int ret = 0;
+	struct qseecom_client_send_data_ireq send_data_req;
+	struct qseecom_command_scm_resp resp;
+	void *buf = NULL;
+	uint32_t size = 0;
+
+	if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
+		dprintf(CRITICAL, "%s: cmd buffer or response buffer is null\n",
+				__func__);
+		return GENERIC_ERROR;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+
+	/* Allocate for req or rsp len whichever is higher, both req and rsp point
+	 * to the same buffer
+	 */
+	size = (req->cmd_req_len > req->resp_len) ? req->cmd_req_len : req->resp_len;
+
+	/* The req rsp buffer will be xPU protected by TZ during a TZ APP call
+	 * This will still be protected during a listener call and there is a
+	 * possibility of prefetching happening, which will cause xPU violation.
+	 * Hence using (device memory with xN set) to prevent I or D prefetching.
+	 * This is a contiguous region of 1MB used only for this, hence will not
+	 * free this.
+	 */
+	buf = (void *)RPMB_SND_RCV_BUF;
+	if (!buf) {
+		dprintf(CRITICAL, "%s: Aloc failed for app_id:%d of size:%d\n",
+				__func__, app_id, size);
+		return GENERIC_ERROR;
+	}
+
+	memscpy(buf, ROUNDUP(size, PAGE_SIZE), req->cmd_req_buf, req->cmd_req_len);
+
+	send_data_req.qsee_cmd_id = QSEE_CLIENT_SEND_DATA_COMMAND;
+	send_data_req.app_id = app_id;
+
+	/* Currently on 8994 only 32-bit phy addr is supported
+	 * Hence downcasting is okay
+	 */
+	send_data_req.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
+	send_data_req.req_len = req->cmd_req_len;
+	send_data_req.rsp_ptr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
+	send_data_req.rsp_len = req->resp_len;
+
+	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
+				(void *)&send_data_req,
+				sizeof(send_data_req), (void *)&resp, sizeof(resp));
+
+	memscpy(req->resp_buf, req->resp_len, (void *)send_data_req.rsp_ptr, send_data_req.rsp_len);
+	return ret;
+}
+
+/**
+* Start a Secure App
+*
+* @param char* app_name
+*   App name of the Secure App to be started
+*
+* @return int
+*   Success:	handle to be used for all calls to
+*   			Secure app. Always greater than zero.
+*   Failure:	Error code (negative only).
+*/
+int qseecom_start_app(char *app_name)
+{
+	int32_t ret = GENERIC_ERROR;
+	int handle = 0;
+	struct qseecom_registered_app_list *entry = NULL;
+	unsigned int app_id = 0;
+
+	if (!app_name) {
+		dprintf(CRITICAL, "%s: Input error\n", __func__);
+		goto err;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+
+
+	mutex_acquire(&qseecom.global_data_lock);
+	if ((!qseecom.qseecom_init_done)
+			|| (!qseecom.qseecom_tz_init_done)){
+		dprintf(CRITICAL, "%s qseecom_init not done\n",
+							__func__);
+		mutex_release(&qseecom.global_data_lock);
+		return ret;
+	}
+	/* Load commonlib image*/
+	if (!qseecom.cmnlib_loaded) {
+		ret = qseecom_load_commonlib_image("cmnlib");
+		if (ret) {
+			mutex_release(&qseecom.global_data_lock);
+			dprintf(CRITICAL, "%s qseecom_load_commonlib_image failed with status:%d\n",
+					__func__, ret);
+			goto err;
+		}
+		qseecom.cmnlib_loaded = 1;
+	}
+	/* Check if App already exits, if exits increase ref_cnt
+	 * and return handle, else load the app from partition,
+	 * call into TZ to load it, add to list and then return
+	 * handle.
+	 */
+
+	entry = __qseecom_check_app_exists(app_name);
+	if (!entry) {
+		mutex_release(&qseecom.global_data_lock);
+		/* load the app and get the app_id  */
+		dprintf(INFO, "%s: Loading app %s for the first time'\n",
+				__func__, app_name);
+
+		ret = __qseecom_load_app(app_name, &app_id);
+		if ((ret < 0) || (app_id ==0)) {
+			dprintf(CRITICAL, "%s: __qseecom_load_app failed with err:%d for app:%s\n",
+					__func__, ret, app_name);
+			ret = GENERIC_ERROR;
+			goto err;
+		}
+		mutex_acquire(&qseecom.global_data_lock);
+		entry = __qseecom_add_app_entry(app_name, app_id);
+		if (!entry)
+		{
+			dprintf(CRITICAL, "%s: __qseecom_add_app_entry failed\n", __func__);
+			ret = GENERIC_ERROR;
+			mutex_release(&qseecom.global_data_lock);
+			goto err;
+		}
+		qseecom.handle++;
+		entry->handle = qseecom.handle;
+		handle = entry->handle;
+		mutex_release(&qseecom.global_data_lock);
+	}
+	else {
+		entry->ref_cnt++;
+		handle = entry->handle;
+		mutex_release(&qseecom.global_data_lock);
+	}
+	return handle;
+err:
+	return ret;
+}
+
+/**
+* Shutdown a Secure App
+*
+* @param int handle
+*   Handle  of the Secure App to be shutdown
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_shutdown_app(int handle)
+{
+	int ret = GENERIC_ERROR;
+	int ref_cnt = 0;
+	struct qseecom_registered_app_list *entry = NULL;
+	struct tzdbg_log_t *log = NULL;
+	uint32_t QseeLogStart = 0;
+	uint32_t QseeLogNewStart = 0;
+
+	if (handle <= 0) {
+		dprintf(CRITICAL, "%s: Invalid Handle %d\n", __func__, handle);
+		goto err;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+	mutex_acquire(&qseecom.global_data_lock);
+	if ((!qseecom.qseecom_init_done)
+			|| (!qseecom.qseecom_tz_init_done)) {
+		dprintf(CRITICAL, "%s qseecom_init not done\n",
+							__func__);
+		mutex_release(&qseecom.global_data_lock);
+		return ret;
+	}
+	entry = __qseecom_check_handle_exists(handle);
+	if (!entry) {
+		dprintf(CRITICAL, "%s: Shutdown on an app that was never loaded handle:%d\n",
+				__func__, handle);
+		ret = GENERIC_ERROR;
+		mutex_release(&qseecom.global_data_lock);
+		goto err;
+	}
+
+	/* Decrement ref_cnt by 1, if ref_cnt is 0 after
+	 * decrementing unload the app by calling into
+	 * TZ else just return.
+	 */
+
+	if(entry->ref_cnt != 0)
+		entry->ref_cnt--;
+	ref_cnt = entry->ref_cnt;
+	mutex_release(&qseecom.global_data_lock);
+	if (ref_cnt == 0) {
+		log = (struct tzdbg_log_t *)logbuf_req.phy_addr;
+		arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
+		QseeLogStart = (uint32_t) log->log_pos.offset;
+
+		ret = qseecom_unload_app(entry->app_id);
+		arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
+		QseeLogNewStart = (uint32_t) log->log_pos.offset;
+
+		_disp_log_stats((struct tzdbg_log_t *) logbuf_req.phy_addr, QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t),
+				QseeLogStart, QseeLogNewStart);
+		if(ret) {
+			dprintf(CRITICAL, "%s: qseecom_unload_app failed with err:%d for handle:%d\n",
+					__func__, ret, handle);
+			goto err;
+		}
+		mutex_acquire(&qseecom.global_data_lock);
+		ret = __qseecom_remove_app_entry(entry);
+		mutex_release(&qseecom.global_data_lock);
+		if(ret) {
+			dprintf(CRITICAL, "%s: __qseecom_remove_app_entry failed with err:%d for handle:%d\n",
+					__func__, ret, handle);
+			goto err;
+		}
+	}
+	ret = 0;
+err:
+	return ret;
+}
+
+/**
+* Send cmd to a Secure App
+*
+* @param int handle
+*   Handle  of the Secure App to send the cmd
+*
+* @param void *send_buf
+*   Pointer to the App request buffer
+*
+* @param uint32_t sbuf_len
+*   Size of the request buffer
+*
+* @param void *resp_buf
+*   Pointer to the App response buffer
+*
+* @param uint32_t rbuf_len
+*   Size of the response buffer
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_send_command(int handle, void *send_buf,
+			uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len)
+{
+	int ret = GENERIC_ERROR;
+	uint32_t app_id = 0;
+	struct qseecom_registered_app_list *entry = NULL;
+	struct qseecom_send_cmd_req req = {0, 0, 0, 0};
+	struct tzdbg_log_t *log = NULL;
+	uint32_t QseeLogStart = 0;
+	uint32_t QseeLogNewStart = 0;
+
+	if (handle <= 0) {
+		dprintf(CRITICAL, "%s Handle is Invalid\n", __func__);
+		return GENERIC_ERROR;
+	}
+
+	if((!send_buf) || (!resp_buf)) {
+		dprintf(CRITICAL, "%s: Input Buffers invalid\n", __func__);
+		return GENERIC_ERROR;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+	mutex_acquire(&qseecom.global_data_lock);
+	if ((!qseecom.qseecom_init_done)
+			|| (!qseecom.qseecom_tz_init_done)) {
+		dprintf(CRITICAL, "%s qseecom_init not done\n",
+							__func__);
+		mutex_release(&qseecom.global_data_lock);
+		return ret;
+	}
+	entry = __qseecom_check_handle_exists(handle);
+	if (!entry) {
+		dprintf(CRITICAL, "%s: Send cmd on an app that was never loaded handle:%d\n",
+				__func__, handle);
+		ret = GENERIC_ERROR;
+		mutex_release(&qseecom.global_data_lock);
+		goto err;
+	}
+
+	app_id = entry->app_id;
+	mutex_release(&qseecom.global_data_lock);
+
+	req.cmd_req_len = sbuf_len;
+	req.resp_len = rbuf_len;
+	req.cmd_req_buf = send_buf;
+	req.resp_buf = resp_buf;
+
+	log = (struct tzdbg_log_t *)logbuf_req.phy_addr;
+	arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
+	QseeLogStart = (uint32_t) log->log_pos.offset;
+
+	ret = __qseecom_send_cmd(app_id, &req);
+	if (ret) {
+		dprintf(CRITICAL, "%s __qseecom_send_cmd failed with err:%d for handle:%d\n",
+				__func__, ret, handle);
+		goto err;
+	}
+	arch_invalidate_cache_range((addr_t) logbuf_req.phy_addr, logbuf_req.len);
+	QseeLogNewStart = (uint32_t) log->log_pos.offset;
+
+	_disp_log_stats((struct tzdbg_log_t *) logbuf_req.phy_addr, QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t),
+			QseeLogStart, QseeLogNewStart);
+	ret = 0;
+	dprintf(SPEW, "sending cmd_req->rsp size: %u, ptr: 0x%p\n",
+			req.resp_len, req.resp_buf);
+err:
+	return ret;
+}
+
+/**
+* Registers a Listener Service with QSEE
+*
+* @param uint32_t listnr_id
+*   Pre-defined Listener ID to be registered
+*
+* @param uint32_t sb_size
+*   Shared buffer size required for the listener
+*   service.
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_register_listener(struct qseecom_listener_services *listnr)
+{
+	int ret = GENERIC_ERROR;
+	struct qseecom_registered_listener_list *new_entry = NULL;
+	struct qseecom_register_listener_ireq req;
+	struct qseecom_command_scm_resp resp;
+
+	mutex_acquire(&qseecom.global_data_lock);
+	if (!qseecom.qseecom_init_done) {
+		dprintf(CRITICAL, "%s qseecom_init not done\n",
+							__func__);
+		mutex_release(&qseecom.global_data_lock);
+		return ret;
+	}
+	mutex_release(&qseecom.global_data_lock);
+
+	mutex_acquire(&qseecom.registered_listener_list_lock);
+
+	if ((!listnr)) {
+		dprintf(CRITICAL, "%s Invalid Input listnr\n", __func__);
+		return GENERIC_ERROR;
+	}
+
+	if ((!listnr->id) || (!listnr->sb_size) || (!listnr->service_cmd_handler)) {
+		dprintf(CRITICAL, "%s Invalid Input listnr_id:%d sb_size:%d\n",
+				__func__, listnr->id, listnr->sb_size);
+		return GENERIC_ERROR;
+	}
+	dprintf(SPEW, "%s called\n", __func__);
+	new_entry = __qseecom_check_listener_exists(listnr->id);
+	if (new_entry) {
+		dprintf(CRITICAL, "Service is not unique and is already registered\n");
+		ret = LISTENER_ALREADY_PRESENT_ERROR;
+		goto err;
+	}
+
+	new_entry = malloc(sizeof(*new_entry));
+	if (!new_entry) {
+		dprintf(CRITICAL, "%s new_entry malloc failed for size:%d\n", __func__, sizeof(*new_entry));
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+	memset(new_entry, 0, sizeof(*new_entry));
+	new_entry->svc.listener_id = listnr->id;
+	new_entry->svc.sb_size = listnr->sb_size;
+	new_entry->CallbackFn = listnr->service_cmd_handler;
+
+	new_entry->svc.virt_sb_base = memalign(PAGE_SIZE, ROUNDUP(listnr->sb_size, PAGE_SIZE));
+	if (!new_entry->svc.virt_sb_base) {
+		dprintf(CRITICAL, "%s virt_sb_base malloc failed for size:%d\n", __func__, listnr->sb_size);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+	memset(new_entry->svc.virt_sb_base, 0, ROUNDUP(listnr->sb_size, PAGE_SIZE));
+	arch_clean_invalidate_cache_range((addr_t) new_entry->svc.virt_sb_base, ROUNDUP(listnr->sb_size, PAGE_SIZE));
+
+	req.qsee_cmd_id = QSEE_REGISTER_LISTENER;
+	req.listener_id = new_entry->svc.listener_id;
+	req.sb_len = new_entry->svc.sb_size;
+	/* convert to 32bit addr for tz */
+	req.sb_ptr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) new_entry->svc.virt_sb_base);
+
+	resp.result = QSEOS_RESULT_INCOMPLETE;
+
+	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+					sizeof(req), &resp, sizeof(resp));
+	if (ret) {
+		dprintf(CRITICAL, "qseecom_scm_call failed with err: %d\n", ret);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+	/* Add entry to Listener list */
+	list_add_tail(&qseecom.registered_listener_list_head, &new_entry->node);
+err:
+	if ((ret) &&
+			(ret != LISTENER_ALREADY_PRESENT_ERROR)) {
+		if ((new_entry) &&
+				(new_entry->svc.virt_sb_base))
+			free(new_entry->svc.virt_sb_base);
+		if (new_entry)
+			free(new_entry);
+	}
+	mutex_release(&qseecom.registered_listener_list_lock);
+	return ret;
+}
+
+/**
+* De-Registers a Listener Service with QSEE
+*
+* @param uint32_t listnr_id
+*   Pre-defined Listener ID to be de-registered
+*
+* @return int
+*   Status:
+*     0 - Success
+*     Negative value indicates failure.
+*/
+int qseecom_deregister_listener(uint32_t listnr_id)
+{
+	int ret = GENERIC_ERROR;
+	struct qseecom_registered_listener_list *new_entry = NULL;
+	struct qseecom_unregister_listener_ireq req;
+	struct qseecom_command_scm_resp resp;
+
+	mutex_acquire(&qseecom.global_data_lock);
+	if (!qseecom.qseecom_init_done) {
+		dprintf(CRITICAL, "%s qseecom_init not done\n",
+							__func__);
+		mutex_release(&qseecom.global_data_lock);
+		return ret;
+	}
+	mutex_release(&qseecom.global_data_lock);
+
+	mutex_acquire(&qseecom.registered_listener_list_lock);
+	dprintf(SPEW, "%s called\n", __func__);
+	new_entry = __qseecom_check_listener_exists(listnr_id);
+	if (!new_entry) {
+		dprintf(CRITICAL, "Service not present\n");
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+
+	req.qsee_cmd_id = QSEE_DEREGISTER_LISTENER;
+	req.listener_id = listnr_id;
+	resp.result = QSEOS_RESULT_INCOMPLETE;
+
+	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+					sizeof(req), &resp, sizeof(resp));
+	if (ret) {
+		dprintf(CRITICAL, "scm_call() failed with err: %d (lstnr id=%d)\n",
+				ret, req.listener_id);
+		ret = GENERIC_ERROR;
+		goto err;
+	}
+
+	list_delete(&new_entry->node);
+
+err:
+	if (ret == 0) {
+		if (new_entry)
+			free(new_entry);
+	}
+	mutex_release(&qseecom.registered_listener_list_lock);
+	return ret;
+}
+
+int qseecom_tz_init()
+{
+	struct qsee_apps_region_info_ireq req;
+	struct qseecom_command_scm_resp resp;
+	int rc = GENERIC_ERROR;
+	/* register log buffer scm request */
+	void *buf = NULL;
+	/* Register app region with TZ */
+	req.qsee_cmd_id = QSEE_APP_REGION_NOTIFICATION;
+	req.addr = APP_REGION_ADDR;
+	req.size = APP_REGION_SIZE;
+	dprintf(ALWAYS, "secure app region addr=0x%x size=0x%x",
+					req.addr, req.size);
+	rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
+			&req, sizeof(req),
+			&resp, sizeof(resp));
+	dprintf(ALWAYS, "TZ App region notif returned with status:%d addr:%x size:%d\n",
+			rc, req.addr, req.size);
+	if (rc)
+		goto err;
+	buf = memalign(PAGE_SIZE, ROUNDUP(QSEE_LOG_BUF_SIZE, PAGE_SIZE));
+	if (!buf) {
+		rc = GENERIC_ERROR;
+		goto err;
+	}
+	memset(buf, 0, ROUNDUP(QSEE_LOG_BUF_SIZE, PAGE_SIZE));
+	logbuf_req.qsee_cmd_id = QSEE_REGISTER_LOG_BUF_COMMAND;
+	logbuf_req.phy_addr = (uint32_t)__qseecom_uvirt_to_kphys((uint32_t) buf);
+	logbuf_req.len = QSEE_LOG_BUF_SIZE;
+
+	rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
+			&logbuf_req, sizeof(logbuf_req),
+			&resp, sizeof(resp));
+	dprintf(ALWAYS, "TZ App log region register returned with status:%d addr:%x size:%d\n",
+			rc, logbuf_req.phy_addr, logbuf_req.len);
+	if (rc)
+		goto err;
+err:
+	if (!rc) {
+		qseecom.qseecom_tz_init_done = 1;
+		dprintf(ALWAYS, "Qseecom TZ Init Done in Appsbl\n");
+	}
+	return rc;
+}
+
+int qseecom_init()
+{
+	int rc = GENERIC_ERROR;
+
+	memset (&qseecom, 0, sizeof(struct qseecom_control));
+	dprintf(SPEW, "%s called\n", __func__);
+	mutex_init(&(qseecom.global_data_lock));
+	mutex_init(&(qseecom.registered_app_list_lock));
+	mutex_init(&(qseecom.registered_listener_list_lock));
+
+	list_initialize(&(qseecom.registered_app_list_head));
+	list_initialize(&(qseecom.registered_listener_list_head));
+
+	qseecom.qseos_version = QSEOS_VERSION_14;
+	rc = 0;
+
+	if (!rc) {
+		qseecom.qseecom_init_done = 1;
+		dprintf(ALWAYS, "Qseecom Init Done in Appsbl\n");
+	}
+	return rc;
+}
+
+int qseecom_exit()
+{
+	dprintf(SPEW, "%s called\n", __func__);
+
+	if (logbuf_req.phy_addr)
+		free((void *)logbuf_req.phy_addr);
+	qseecom.qseecom_init_done = 0;
+	dprintf(ALWAYS, "Qseecom De-Init Done in Appsbl\n");
+	return 0;
+}
diff --git a/platform/msm_shared/reboot.c b/platform/msm_shared/reboot.c
new file mode 100644
index 0000000..fb29ab5
--- /dev/null
+++ b/platform/msm_shared/reboot.c
@@ -0,0 +1,143 @@
+/* Copyright (c) 2015, 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 <debug.h>
+#include <platform/iomap.h>
+#include <reg.h>
+#include <target.h>
+#include <platform.h>
+#include <uart_dm.h>
+#include <mmc.h>
+#include <dev/keys.h>
+#include <spmi_v2.h>
+#include <pm8x41.h>
+#include <board.h>
+#include <baseband.h>
+#include <hsusb.h>
+#include <scm.h>
+#include <platform/gpio.h>
+#include <platform/irqs.h>
+#include <platform/clock.h>
+#include <crypto5_wrapper.h>
+#include <partition_parser.h>
+#include <stdlib.h>
+#include <reboot.h>
+
+#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 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;
+}
+
+/* Return true if it is triggered by alarm. */
+uint32_t check_alarm_boot(void)
+{
+	/* Check reboot reason and power on reason */
+	if (pm8x41_get_is_cold_boot()) {
+		if (pm8x41_get_pon_reason() == RTC_TRG)
+			return 1;
+	} else {
+		if (readl(RESTART_REASON_ADDR) == ALARM_BOOT)
+			return 1;
+	}
+
+	return 0;
+}
+
+void reboot_device(unsigned reboot_reason)
+{
+	uint8_t reset_type = 0;
+	uint32_t ret = 0;
+
+	/* Need to clear the SW_RESET_ENTRY register and
+	 * write to the BOOT_MISC_REG for known reset cases
+	 */
+	if(reboot_reason != DLOAD)
+		scm_dload_mode(NORMAL_MODE);
+
+	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 == DLOAD) || (reboot_reason == RECOVERY_MODE))
+		reset_type = PON_PSHOLD_WARM_RESET;
+	else
+		reset_type = PON_PSHOLD_HARD_RESET;
+
+	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");
+}
+
diff --git a/platform/msm_shared/reboot.h b/platform/msm_shared/reboot.h
new file mode 100644
index 0000000..7156c01
--- /dev/null
+++ b/platform/msm_shared/reboot.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+#define FASTBOOT_MODE     0x77665500
+#define RECOVERY_MODE     0x77665502
+#define ALARM_BOOT        0x77665503
+#define RTC_TRG           4
+#define PON_SOFT_RB_SPARE 0x88F
+
+#if USER_FORCE_RESET_SUPPORT
+/* Return 1 if it is a force resin triggered by user. */
+uint32_t is_user_force_reset(void);
+#endif
+
+unsigned check_reboot_mode(void);
+
+unsigned check_hard_reboot_mode(void);
+
+uint32_t check_alarm_boot(void);
+
+void reboot_device(unsigned reboot_reason);
diff --git a/platform/msm_shared/rpm-glink.c b/platform/msm_shared/rpm-glink.c
new file mode 100644
index 0000000..01cae61
--- /dev/null
+++ b/platform/msm_shared/rpm-glink.c
@@ -0,0 +1,379 @@
+/* Copyright (c) 2015, 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 Fundation, Inc. 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 <rpm-glink.h>
+#include <smd.h>
+#include <glink.h>
+#include <glink_rpm.h>
+#include <xport_rpm.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <arch/defines.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <platform/timer.h>
+#include <platform/interrupts.h>
+#include <platform/clock.h>
+#include <platform/iomap.h>
+#include <platform/irqs.h>
+#include <pm8x41.h>
+#include <kernel/event.h>
+
+#define RPM_REQ_MAGIC 0x00716572
+#define RPM_CMD_MAGIC 0x00646d63
+#define REQ_MSG_LENGTH 0x14
+#define CMD_MSG_LENGTH 0x08
+#define ACK_MSG_LENGTH 0x0C
+
+glink_handle_type rpm_glink_port, ssr_glink_port;
+static uint32_t msg_id;
+static event_t wait_for_data;
+
+extern glink_err_type glink_wait_link_down(glink_handle_type handle);
+
+glink_err_type rpm_glink_send_data(uint32_t *data, uint32_t len, msg_type type)
+{
+	rpm_req req;
+	rpm_cmd cmd;
+	glink_err_type send_err = 0;
+	uint32_t len_to_rpm = 0;
+	void *rpm_data = NULL;
+	event_init(&wait_for_data, false, EVENT_FLAG_AUTOUNSIGNAL);
+
+	switch(type)
+	{
+		case RPM_REQUEST_TYPE:
+			req.hdr.type = RPM_REQ_MAGIC;
+			req.hdr.len = len + REQ_MSG_LENGTH;//20
+			req.req_hdr.id = ++msg_id;
+			req.req_hdr.set = 0;
+			req.req_hdr.resourceType = data[RESOURCETYPE];
+			req.req_hdr.resourceId = data[RESOURCEID];
+			req.req_hdr.dataLength = len;
+
+			fill_kvp_object(&req.data, data, len);
+			len_to_rpm = req.req_hdr.dataLength + 0x28;
+
+			rpm_data = (void*) malloc(len_to_rpm);
+			ASSERT(rpm_data);
+			memset(rpm_data, 0, len_to_rpm);
+			memcpy(rpm_data, &req.hdr, sizeof(rpm_gen_hdr));
+			memcpy(rpm_data + sizeof(rpm_gen_hdr), &req.req_hdr, sizeof(rpm_req_hdr));
+			memcpy(rpm_data + sizeof(rpm_gen_hdr)+ sizeof(rpm_req_hdr), req.data, len);
+
+			// Send Data Request to RPM
+			send_err = glink_tx(rpm_glink_port, NULL, (const void *)rpm_data, len_to_rpm, 0);
+			if (send_err)
+			{
+				dprintf(CRITICAL, "%s:%d, Glink tx error\n", __func__, __LINE__);
+				free(rpm_data);
+				free_kvp_object(&req.data);
+				break;
+			}
+#ifdef DEBUG_GLINK
+			dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
+#endif
+			event_wait(&wait_for_data);
+			free(rpm_data);
+			free_kvp_object(&req.data);
+			break;
+		case RPM_CMD_TYPE:
+			cmd.hdr.type = RPM_CMD_MAGIC;
+			cmd.hdr.len = CMD_MSG_LENGTH;//0x8;
+			len_to_rpm  = sizeof(rpm_cmd);
+
+			fill_kvp_object(&cmd.data, data, len);
+			send_err = glink_tx(rpm_glink_port, NULL, (const void *)&cmd, len_to_rpm, 0);
+			if (send_err)
+				dprintf(CRITICAL, "%s:%d, Glink tx error\n", __func__, __LINE__);
+			free_kvp_object(&cmd.data);
+			break;
+		default:
+			dprintf(CRITICAL, "Invalid RPM Request\n");
+			break;
+	}
+
+	return send_err;
+}
+
+uint32_t rpm_glink_recv_data(char *rx_buffer, uint32_t* len)
+{
+	rpm_ack_msg *resp;
+	msg_type type = 0;
+	uint32_t ret = 0;
+	/* As per the current design rpm response does not exceed 20 bytes */
+	if (rx_buffer == NULL)
+	{
+		dprintf(CRITICAL, "Invalid pointer to data received from RPM\n");
+		return 99;
+	}
+	resp = (rpm_ack_msg *)rx_buffer;
+
+	arch_invalidate_cache_range((addr_t)resp, sizeof(rpm_gen_hdr));
+
+	if(resp->hdr.type == RPM_CMD_MAGIC)
+	{
+		type = RPM_CMD_TYPE;
+	}
+	else if(resp->hdr.type == RPM_REQ_MAGIC)
+	{
+		type = RPM_REQUEST_TYPE;
+	}
+
+	if (type == RPM_CMD_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
+	{
+		dprintf(SPEW, "Received SUCCESS CMD ACK\n");
+	}
+	else if (type == RPM_REQUEST_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
+	{
+		dprintf(SPEW, "Received SUCCESS REQ ACK \n");
+	}
+	else
+	{
+		ret = 1;
+		dprintf(CRITICAL, "Received ERROR ACK \n");
+	}
+
+	if(!ret)
+	{
+		ret = sizeof(rpm_gen_hdr) + sizeof(kvp_data);
+	}
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "%s:%d Return value %u\n", __func__, __LINE__, ret);
+#endif
+	return ret;
+}
+
+void rpm_vector_glink_ssr_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
+							void *buffer, size_t size, size_t intent_used,
+							glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
+{
+	char rx_buffer[12];
+	char *return_buffer = NULL;
+	uint32_t ret = 0;
+	uint32_t offset = 0;
+	size_t return_size = 0;
+
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "RPM Vector GLINK SSR ISR\n");
+#endif
+	if (size == 0)
+	{
+		dprintf(CRITICAL, "Invalid size of RPM response\n");
+		ASSERT(0);
+	}
+	if (size > sizeof(rx_buffer))
+	{
+		dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
+		ASSERT(0);
+	}
+	do
+	{
+		return_buffer = vprovider(buffer, offset, &return_size);
+		if(return_buffer)
+		{
+			memcpy(rx_buffer+offset,return_buffer, return_size);
+			offset += return_size;
+		}
+	} while(return_buffer);
+	ret = rpm_glink_recv_data(rx_buffer,(uint32_t *)&size);
+	if(ret)
+	{
+		dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
+	}
+	// Release the mutex
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "Received Data from RPM\n");
+#endif
+	event_signal(&wait_for_data, false);
+}
+
+void rpm_vector_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
+							void *buffer, size_t size, size_t intent_used,
+							glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
+{
+	char rx_buffer[64];
+	char *return_buffer = NULL;
+	uint32_t ret = 0;
+	uint32_t offset = 0;
+	size_t return_size = 0;
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "RPM Vector GLINK ISR\n");
+#endif
+	if (size == 0)
+	{
+		dprintf(CRITICAL, "Invalid size of RPM response\n");
+		ASSERT(0);
+	}
+	if (size > sizeof(rx_buffer))
+	{
+		dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
+		ASSERT(0);
+	}
+	do
+	{
+		return_buffer = vprovider(buffer, offset, &return_size);
+		if(return_buffer)
+		{
+			memcpy(rx_buffer+offset,return_buffer, return_size);
+			offset += return_size;
+		}
+	} while(return_buffer);
+	ret = rpm_glink_recv_data(rx_buffer, (uint32_t *)&size);
+	if(ret)
+	{
+		dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
+	}
+	// Release the mutex
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "Received Data from RPM\n");
+#endif
+	event_signal(&wait_for_data, false);
+}
+
+void rpm_glink_notify_state_isr(glink_handle_type handle, void *data, glink_channel_event_type event)
+{
+	if(event == GLINK_CONNECTED)
+	{
+		dprintf(INFO, "Glink Connection between APPS and RPM established\n");
+		return;
+	}
+}
+
+void rpm_glink_tx_done_isr(void)
+{
+	//empty function for tx_done cb. Nothing required here for now since we are always in
+	//"single-threaded" operation of sending GLink requests
+	return;
+}
+
+void rpm_glink_open(glink_link_info_type *link_info, void* priv)
+{
+	glink_err_type ret;
+	glink_open_config_type glink_open_cfg = {0}, glink_ssr_open_cfg = {0};
+
+	// Open channel for tx
+	glink_open_cfg.name = "rpm_requests";
+	glink_open_cfg.remote_ss = link_info->remote_ss;
+	glink_open_cfg.notify_rx = NULL;
+	glink_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_isr;
+	glink_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
+	glink_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_isr;
+	glink_open_cfg.priv = NULL;
+	ret = glink_open(&glink_open_cfg, &rpm_glink_port);
+	if (ret == GLINK_STATUS_SUCCESS)
+		dprintf(INFO, "Opening RPM Glink Port success\n");
+	else
+	{
+		dprintf(CRITICAL, "Opening RPM Glink Port failure %d\n", ret);
+		ASSERT(0);
+	}
+
+	// Open Channel for tear down
+	glink_ssr_open_cfg.name = "glink_ssr";
+	glink_ssr_open_cfg.remote_ss = link_info->remote_ss;
+	glink_ssr_open_cfg.notify_rx = NULL;
+	glink_ssr_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_ssr_isr;
+	glink_ssr_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
+	glink_ssr_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_isr;
+	glink_ssr_open_cfg.priv = NULL;
+
+	ret = glink_open(&glink_ssr_open_cfg, &ssr_glink_port);
+	if (ret == GLINK_STATUS_SUCCESS)
+		dprintf(INFO, "Opening SSR Glink Port success\n");
+	else
+	{
+		dprintf(CRITICAL, "Opening SSR Glink Port failure %d\n", ret);
+		ASSERT(0);
+	}
+
+}
+
+void rpm_glink_init()
+{
+	glink_err_type ret;
+	glink_link_id_type link_id;
+
+	dprintf(INFO, "RPM GLink Init\n");
+	// Initialize RPM transport
+	ret = xport_rpm_init(NULL);
+	if (ret == GLINK_STATUS_SUCCESS)
+	{
+		unmask_interrupt(GLINK_IPC_IRQ);
+		GLINK_LINK_ID_STRUCT_INIT(link_id);
+		link_id.remote_ss = "rpm";
+		link_id.link_notifier = (glink_link_state_notif_cb)rpm_glink_open;
+		glink_register_link_state_cb(&link_id, NULL);
+	}
+	else
+	{
+		dprintf(CRITICAL, "RPM Glink Init Failure\n");
+		ASSERT(0);
+	}
+}
+
+void rpm_glink_uninit()
+{
+	rpm_ssr_req req;
+	glink_err_type ret;
+	uint32_t len_to_rpm, loop = 100000;
+
+	// update ssr request
+	req.version = 0;
+	req.cmd = 0;
+	req.seqnumber = 0;
+	memset(req.name, 0, sizeof(req.name));
+	strncpy(req.name, "apss", 4);
+	req.namelength = strlen(req.name);
+	len_to_rpm = sizeof(rpm_ssr_req);
+	dprintf(INFO, "RPM GLINK UnInit\n");
+	ret = glink_tx(ssr_glink_port, NULL, (const void *)&req, len_to_rpm, 0);
+
+	if (ret)
+	{
+		dprintf(CRITICAL, "Glink SSR Channel: Tx for link tear down request failure\n");
+		ASSERT(0);
+	}
+
+#ifdef DEBUG_GLINK
+	dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
+#endif
+	// loop till the FIFO indices are cleared
+	while((ret = glink_wait_link_down(ssr_glink_port)) && loop)
+	{
+		loop--;
+		mdelay(1);
+		continue;
+	}
+	if (!loop)
+	{
+		dprintf(INFO, "%s:%d, Tearing down Glink SSR Channel Timed out\n", __func__, __LINE__);
+		ASSERT(0);
+	}
+}
diff --git a/platform/msm_shared/rpm-ipc.c b/platform/msm_shared/rpm-ipc.c
new file mode 100644
index 0000000..2bd3c51
--- /dev/null
+++ b/platform/msm_shared/rpm-ipc.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2015, 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 Fundation, Inc. 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 <arch/defines.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <rpm-ipc.h>
+#include <rpm-glink.h>
+#include <rpm-smd.h>
+#include <string.h>
+
+void fill_kvp_object(kvp_data **kdata, uint32_t *data, uint32_t len)
+{
+	*kdata = (kvp_data *) memalign(CACHE_LINE, ROUNDUP(len, CACHE_LINE));
+	ASSERT(*kdata);
+
+	memcpy(*kdata, data+2, len);
+}
+
+void free_kvp_object(kvp_data **kdata)
+{
+	if(*kdata)
+		free(*kdata);
+}
+
+int rpm_send_data(uint32_t *data, uint32_t len, msg_type type)
+{
+	int ret = 0;
+#ifdef GLINK_SUPPORT
+	ret = rpm_glink_send_data(data, len, type);
+#else
+	ret = rpm_smd_send_data(data, len, type);
+#endif
+	return ret;
+}
+
+void rpm_clk_enable(uint32_t *data, uint32_t len)
+{
+	if(rpm_send_data(data, len, RPM_REQUEST_TYPE))
+	{
+		dprintf(CRITICAL, "Clock enable failure\n");
+		ASSERT(0);
+	}
+}
diff --git a/platform/msm_shared/rpm-smd.c b/platform/msm_shared/rpm-smd.c
index 693d369..d6869ee 100644
--- a/platform/msm_shared/rpm-smd.c
+++ b/platform/msm_shared/rpm-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 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
@@ -36,12 +36,6 @@
 #include <stdlib.h>
 #include <platform/timer.h>
 
-#define RPM_REQ_MAGIC 0x00716572
-#define RPM_CMD_MAGIC 0x00646d63
-#define REQ_MSG_LENGTH 0x14
-#define CMD_MSG_LENGTH 0x08
-#define ACK_MSG_LENGTH 0x0C
-
 static uint32_t msg_id;
 smd_channel_info_t ch;
 
@@ -55,21 +49,7 @@
 	smd_uninit(&ch);
 }
 
-static void fill_kvp_object(kvp_data **kdata, uint32_t *data, uint32_t len)
-{
-	*kdata = (kvp_data *) memalign(CACHE_LINE, ROUNDUP(len, CACHE_LINE));
-	ASSERT(*kdata);
-
-	memcpy(*kdata, data+2, len);
-}
-
-static void free_kvp_object(kvp_data **kdata)
-{
-	if(*kdata)
-		free(*kdata);
-}
-
-int rpm_send_data(uint32_t *data, uint32_t len, msg_type type)
+int rpm_smd_send_data(uint32_t *data, uint32_t len, msg_type type)
 {
 	rpm_req req;
 	rpm_cmd cmd;
@@ -103,7 +83,7 @@
 			ret = smd_write(&ch, smd_data, len_to_smd, SMD_APPS_RPM);
 
 			/* Read the response */
-			ack_msg_len = rpm_recv_data(&rlen);
+			ack_msg_len = rpm_smd_recv_data(&rlen);
 
 			smd_signal_read_complete(&ch, ack_msg_len);
 
@@ -127,7 +107,7 @@
 	return ret;
 }
 
-uint32_t rpm_recv_data(uint32_t* len)
+uint32_t rpm_smd_recv_data(uint32_t* len)
 {
 	rpm_ack_msg *resp;
 	msg_type type;
@@ -171,15 +151,3 @@
 
 	return ret;
 }
-
-void rpm_clk_enable(uint32_t *data, uint32_t len)
-{
-	/* Send the request to SMD */
-	rpm_send_data(data, len, RPM_REQUEST_TYPE);
-}
-
-void rpm_clk_disable(uint32_t *data, uint32_t len)
-{
-	dprintf(CRITICAL,"Clock disable\n");
-}
-
diff --git a/platform/msm_shared/rpmb/rpmb.c b/platform/msm_shared/rpmb/rpmb.c
new file mode 100644
index 0000000..de67c46
--- /dev/null
+++ b/platform/msm_shared/rpmb/rpmb.c
@@ -0,0 +1,251 @@
+/* Copyright (c) 2013-2015, 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 <platform.h>
+#include <rpmb.h>
+#include <rpmb_listener.h>
+#include <mmc_sdhci.h>
+#include <boot_device.h>
+#include <debug.h>
+#include <target.h>
+
+static bool lksec_app_loaded;
+
+static void *dev;
+static int app_handle;
+struct rpmb_init_info info;
+
+int rpmb_init()
+{
+	int ret = 0;
+
+	dev = target_mmc_device();
+
+	/* 1. Initialize storage specific data */
+	if (platform_boot_dev_isemmc())
+	{
+		struct mmc_device *mmc_dev = (struct mmc_device *) dev;
+		info.size = mmc_dev->card.rpmb_size / RPMB_MIN_BLK_SZ;
+		info.rel_wr_count = mmc_dev->card.rel_wr_count;
+		info.dev_type  = EMMC_RPMB;
+	}
+	else
+	{
+		struct ufs_dev *ufs_dev = (struct ufs_dev *) dev;
+		ufs_rpmb_init(ufs_dev);
+		info.size = ufs_dev->rpmb_num_blocks;
+		info.rel_wr_count = ufs_dev->rpmb_rw_size;
+		info.dev_type  = UFS_RPMB;
+	}
+
+	/* Initialize Qseecom */
+	ret = qseecom_init();
+
+	if (ret < 0)
+	{
+		dprintf(CRITICAL, "Failed to initialize qseecom, error: %d\n", ret);
+		goto err;
+	}
+
+	/* Register & start the listener */
+	ret = rpmb_listener_start();
+	if (ret < 0)
+	{
+		dprintf(CRITICAL, "Error registering the handler\n");
+		goto err;
+	}
+
+	/* Start Qseecom */
+	ret = qseecom_tz_init();
+
+	if (ret < 0)
+	{
+		dprintf(CRITICAL, "Failed to start qseecom, error: %d\n", ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+struct rpmb_init_info *rpmb_get_init_info()
+{
+	return &info;
+}
+
+int rpmb_read(uint32_t *req, uint32_t req_len, uint32_t *resp, uint32_t *resp_len)
+{
+	if (platform_boot_dev_isemmc())
+		return rpmb_read_emmc(dev, req, req_len, resp, resp_len);
+	else
+		return rpmb_read_ufs(dev, req, req_len, resp, resp_len);
+}
+
+int rpmb_write(uint32_t *req, uint32_t req_len, uint32_t *resp, uint32_t *resp_len)
+{
+	if (platform_boot_dev_isemmc())
+		return rpmb_write_emmc(dev, req, req_len, resp, resp_len);
+	else
+		return rpmb_write_ufs(dev, req, req_len, resp, resp_len);
+}
+
+/* This API calls into TZ app to read device_info */
+int read_device_info_rpmb(void *info, uint32_t sz)
+{
+	int ret = 0;
+	struct send_cmd_req read_req = {0};
+	struct send_cmd_rsp read_rsp = {0};
+
+	/*
+	 * Load the sec app for first time
+	 */
+	if (!lksec_app_loaded)
+	{
+		if (load_sec_app() < 0)
+		{
+			dprintf(CRITICAL, "Failed to load App for rpmb\n");
+			ASSERT(0);
+		}
+		lksec_app_loaded = true;
+	}
+
+	read_req.cmd_id = CLIENT_CMD_READ_LK_DEVICE_STATE;
+	read_req.data   = (uint32_t) info;
+	read_req.len    = sz;
+
+	read_rsp.cmd_id = CLIENT_CMD_READ_LK_DEVICE_STATE;
+
+	/* Read the device info */
+	ret = qseecom_send_command(app_handle, (void*) &read_req, sizeof(read_req), (void*) &read_rsp, sizeof(read_rsp));
+
+	if (ret < 0 || read_rsp.status < 0)
+	{
+		dprintf(CRITICAL, "Reading device info failed: Error: %d\n", read_rsp.status);
+		return read_rsp.status;
+	}
+
+	return 0;
+}
+
+int write_device_info_rpmb(void *info, uint32_t sz)
+{
+	int ret = 0;
+
+	struct send_cmd_req write_req = {0};
+	struct send_cmd_rsp write_rsp = {0};
+
+	write_req.cmd_id = CLIENT_CMD_WRITE_LK_DEVICE_STATE;
+	write_req.data   = (uint32_t) info;
+	write_req.len    = sz;
+
+	write_rsp.cmd_id = CLIENT_CMD_WRITE_LK_DEVICE_STATE;
+
+	/* Write the device info */
+	ret = qseecom_send_command(app_handle, (void *)&write_req, sizeof(write_req), (void *)&write_rsp, sizeof(write_rsp));
+
+	if (ret < 0 || write_rsp.status < 0)
+	{
+		dprintf(CRITICAL, "Writing device info failed: Error: %d\n", write_rsp.status);
+		return ret;
+	}
+
+	return 0;
+}
+
+int rpmb_get_app_handle()
+{
+	return app_handle;
+}
+
+int rpmb_uninit()
+{
+	int ret = 0;
+
+	ret = rpmb_listener_stop(RPMB_LSTNR_ID);
+	if (ret < 0)
+	{
+		dprintf(CRITICAL, "Failed to stop Qseecom Listener\n");
+		return ret;
+	}
+	ret = qseecom_exit();
+
+	if (ret < 0)
+	{
+		dprintf(CRITICAL, "Failed to exit qseecom \n");
+		return ret;
+	}
+
+	return ret;
+}
+
+int load_sec_app()
+{
+	/* start TZ app */
+	app_handle = qseecom_start_app("lksecapp");
+
+	if (app_handle < 0)
+	{
+		dprintf(CRITICAL, "Failure to load TZ app: lksecapp, error: %d\n", app_handle);
+		return app_handle;
+	}
+
+	return 0;
+}
+
+int unload_sec_app()
+{
+	int ret = 0;
+
+	struct send_cmd_req req = {0};
+	struct send_cmd_rsp rsp = {0};
+
+	req.cmd_id = CLIENT_CMD_LK_END_MILESTONE;
+	rsp.cmd_id = CLIENT_CMD_LK_END_MILESTONE;
+
+	/* Milestone end command */
+	ret = qseecom_send_command(app_handle, (void *)&req, sizeof(req), (void *)&rsp, sizeof(rsp));
+
+	if (ret < 0 || rsp.status < 0)
+	{
+		dprintf(CRITICAL, "Failed to send milestone end command: Error: %x\n", rsp.status);
+		return ret;
+	}
+
+	if (qseecom_shutdown_app(app_handle) < 0)
+	{
+		dprintf(CRITICAL, "Failed to Shutdown sec app\n");
+		ASSERT(0);
+	}
+
+
+	return 0;
+}
+
+bool is_sec_app_loaded()
+{
+	return lksec_app_loaded;
+}
diff --git a/platform/msm_shared/rpmb/rpmb_emmc.c b/platform/msm_shared/rpmb/rpmb_emmc.c
new file mode 100644
index 0000000..2bfa545
--- /dev/null
+++ b/platform/msm_shared/rpmb/rpmb_emmc.c
@@ -0,0 +1,179 @@
+/* Copyright (c) 2015, 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 <rpmb.h>
+#include <mmc_sdhci.h>
+#include <debug.h>
+
+static const char *str_err[] =
+{
+	"Operation Ok",
+	"General failure",
+	"Authentication error (MAC comparison not matching, MAC calculation failure)",
+	"Counter failure (counters not matching in comparison, counter incrementing failure)",
+	"Address failure (address out of range, wrong address alignment)",
+	"Write failure (data/counter/result write failure)",
+	"Read failure (data/counter/result read failure)",
+	"Authentication Key not yet programmed",
+};
+
+static struct rpmb_frame read_result_reg =
+{
+	.requestresponse[1] = READ_RESULT_FLAG,
+};
+
+int rpmb_write_emmc(struct mmc_device *dev,uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len)
+{
+	uint32_t i;
+	int ret = 0;
+	struct mmc_command cmd[3] = {{0},{0},{0}};
+	struct rpmb_frame *result = (struct rpmb_frame *)resp_buf;
+
+	for (i = 0; i < blk_cnt; i++)
+	{
+#if DEBUG_RPMB
+		dump_rpmb_frame((uint8_t *)req_buf, "request");
+#endif
+
+		/* CMD25 program data packet */
+		cmd[0].write_flag = true;
+		cmd[0].cmd_index = CMD25_WRITE_MULTIPLE_BLOCK;
+		cmd[0].argument = 0;
+		cmd[0].cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd[0].resp_type = SDHCI_CMD_RESP_R1;
+		cmd[0].trans_mode = SDHCI_MMC_WRITE;
+		cmd[0].data_present = 0x1;
+		cmd[0].data.data_ptr = (void *)req_buf;
+		cmd[0].data.num_blocks = RPMB_MIN_BLK_CNT;
+
+		/* CMD25 Result Register Read Request Packet */
+		cmd[1].write_flag = false;
+		cmd[1].cmd_index = CMD25_WRITE_MULTIPLE_BLOCK;
+		cmd[1].argument = 0;
+		cmd[1].cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd[1].resp_type = SDHCI_CMD_RESP_R1;
+		cmd[1].trans_mode = SDHCI_MMC_WRITE;
+		cmd[1].data_present = 0x1;
+		cmd[1].data.data_ptr = (void *)&read_result_reg;
+		cmd[1].data.num_blocks = RPMB_MIN_BLK_CNT;
+
+		/* Read actual result with read request */
+		cmd[2].write_flag = false;
+		cmd[2].cmd_index = CMD18_READ_MULTIPLE_BLOCK;
+		cmd[2].argument = 0;
+		cmd[2].cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd[2].resp_type = SDHCI_CMD_RESP_R1;
+		cmd[2].trans_mode = SDHCI_MMC_READ;
+		cmd[2].data_present = 0x1;
+		cmd[2].data.data_ptr = (void *)resp_buf;
+		cmd[2].data.num_blocks = RPMB_MIN_BLK_CNT;
+
+		ret = mmc_sdhci_rpmb_send(dev, cmd);
+
+		if (ret)
+		{
+			dprintf(CRITICAL, "Failed to Send the RPMB write sequnce of commands\n");
+			break;
+		}
+
+		if (result->result[0] == 0x80)
+		{
+			dprintf(CRITICAL, "Max write counter reached: \n");
+			break;
+		}
+
+		if (result->result[1])
+		{
+			dprintf(CRITICAL, "%s\n", str_err[result->result[1]]);
+			break;
+		}
+
+		req_buf = (uint32_t*) ((uint8_t*)req_buf + RPMB_BLK_SIZE);
+
+#if DEBUG_RPMB
+		dump_rpmb_frame((uint8_t *)resp_buf, "response");
+#endif
+	}
+	*resp_len = RPMB_MIN_BLK_CNT * RPMB_BLK_SIZE;
+
+	return 0;
+}
+
+int rpmb_read_emmc(struct mmc_device *dev, uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len)
+{
+	struct mmc_command cmd[3] = {{0}, {0}, {0}};
+	int ret = 0;
+	struct rpmb_frame *result = (struct rpmb_frame *)resp_buf;
+
+#if DEBUG_RPMB
+	dump_rpmb_frame((uint8_t *)req_buf, "request");
+#endif
+
+	/* CMD25 program data packet */
+	cmd[0].write_flag = false;
+	cmd[0].cmd_index = CMD25_WRITE_MULTIPLE_BLOCK;
+	cmd[0].argument = 0;
+	cmd[0].cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd[0].resp_type = SDHCI_CMD_RESP_R1;
+	cmd[0].trans_mode = SDHCI_MMC_WRITE;
+	cmd[0].data_present = 0x1;
+	cmd[0].data.data_ptr = (void *)req_buf;
+	cmd[0].data.num_blocks = RPMB_MIN_BLK_CNT;
+
+	/* Read actual result with read request */
+	cmd[1].write_flag = false;
+	cmd[1].cmd_index = CMD18_READ_MULTIPLE_BLOCK;
+	cmd[1].argument = 0;
+	cmd[1].cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd[1].resp_type = SDHCI_CMD_RESP_R1;
+	cmd[1].trans_mode = SDHCI_MMC_READ;
+	cmd[1].data_present = 0x1;
+	cmd[1].data.data_ptr = (void *)resp_buf;
+	cmd[1].data.num_blocks = blk_cnt;
+	cmd[1].cmd23_support  = 0x1;
+
+	ret = mmc_sdhci_rpmb_send(dev, cmd);
+
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to Send the RPMB read sequence of commands\n");
+		return -1;
+	}
+
+	if (result->result[1])
+	{
+		dprintf(CRITICAL, "%s\n", str_err[result->result[1]]);
+	}
+
+#if DEBUG_RPMB
+	dump_rpmb_frame((uint8_t *)resp_buf, "response");
+#endif
+	*resp_len = blk_cnt * RPMB_BLK_SIZE;
+
+	return 0;
+}
diff --git a/platform/msm_shared/rpmb/rpmb_listener.c b/platform/msm_shared/rpmb/rpmb_listener.c
new file mode 100644
index 0000000..7cf0b79
--- /dev/null
+++ b/platform/msm_shared/rpmb/rpmb_listener.c
@@ -0,0 +1,199 @@
+/* Copyright (c) 2013-2015, 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 <debug.h>
+#include <rpmb.h>
+#include <rpmb_listener.h>
+#include <qseecom_lk_api.h>
+
+#define RPMB_LSTNR_VERSION_2        0x2
+
+typedef enum
+{
+	TZ_CM_CMD_RPMB_INIT = 0x101,    //257
+	TZ_CM_CMD_RPMB_READ,        //258
+	TZ_CM_CMD_RPMB_WRITE,       //259
+	TZ_CM_CMD_RPMB_PARTITION,   //260
+} tz_rpmb_cmd_type;
+
+struct tz_device_init_req
+{
+	uint32_t cmd_id;
+	uint32_t version;
+}__PACKED;
+
+/* RPMB Init response message */
+struct tz_device_init_resp
+{
+    uint32_t cmd_id;           /* Command ID */
+    uint32_t version;          /* Messaging version from RPMB listener */
+    uint32_t status;           /* RPMB init status */
+    uint32_t num_sectors;      /* Size of RPMB (in sectors) */
+    uint32_t rel_wr_count;     /* Reliable write count for the RPMB */
+    uint32_t dev_type;         /* Storage device type (like eMMC or UFS) */
+    uint32_t reserved1;        /* Reserved 1 */
+    uint32_t reserved2;        /* Reserved 2 */
+    uint32_t reserved3;        /* Reserved 3 */
+    uint32_t reserved4;        /* Reserved 4 */
+}__PACKED;
+
+struct tz_rpmb_rw_req
+{
+	uint32_t cmd_id;
+	uint32_t num_sectors;
+	uint32_t req_buff_len;
+	uint32_t req_buff_offset;
+}__PACKED;
+
+struct tz_rpmb_rw_resp
+{
+	uint32_t cmd_id;
+	int32_t  status;
+	uint32_t res_buff_len;
+	uint32_t res_buff_offset;
+}__PACKED;
+
+typedef int (*ListenerCallback)(void*, uint32_t);
+
+static void handle_init_request(void *buf, uint32_t sz)
+{
+	struct tz_device_init_req *init_req_p = NULL;
+	struct tz_device_init_resp *init_resp = (struct tz_device_init_resp*) buf;
+	struct rpmb_init_info *rpmb_info = NULL;
+
+	init_req_p = (struct tz_device_init_req *) buf;
+
+	rpmb_info = rpmb_get_init_info();
+
+	if (rpmb_info)
+		init_resp->status = 0;
+
+	init_resp->cmd_id = init_req_p->cmd_id;
+	init_resp->version = RPMB_LSTNR_VERSION_2;
+	init_resp->num_sectors = rpmb_info->size / RPMB_SECTOR_SIZE;
+	init_resp->rel_wr_count = rpmb_info->rel_wr_count;
+	init_resp->dev_type = rpmb_info->dev_type;
+}
+
+static void handle_rw_request(void *buf, uint32_t sz)
+{
+	struct tz_rpmb_rw_req *req_p = (struct tz_rpmb_rw_req *)buf;
+	struct tz_rpmb_rw_resp *resp_p = NULL;
+	uint32_t *req_buf = buf + req_p->req_buff_offset;
+	uint32_t *resp_buf = buf + sizeof(struct tz_rpmb_rw_resp);
+
+	resp_p = (struct tz_rpmb_rw_resp *) buf;
+
+	switch (req_p->cmd_id)
+	{
+		case TZ_CM_CMD_RPMB_READ:
+#if DEBUG_RPMB
+			dprintf(INFO, "Read Request received\n");
+#endif
+			resp_p->status = rpmb_read(req_buf, req_p->num_sectors, resp_buf, &resp_p->res_buff_len);
+			break;
+		case TZ_CM_CMD_RPMB_WRITE:
+#if DEBUG_RPMB
+			dprintf(INFO, "Write Request received\n");
+#endif
+			resp_p->status = rpmb_write(req_buf, req_p->num_sectors, resp_buf, &resp_p->res_buff_len);
+			break;
+		default:
+			dprintf(CRITICAL, "Unsupported request command request: %u\n", req_p->cmd_id);
+			ASSERT(0);
+	};
+
+	resp_p->res_buff_offset = sizeof(struct tz_rpmb_rw_resp);
+	resp_p->cmd_id = req_p->cmd_id;
+}
+
+int rpmb_cmd_handler(void *buf, uint32_t sz)
+{
+	int ret = 0;
+	uint32_t cmd_id;
+
+	ASSERT(buf);
+
+	cmd_id = (uint32_t) *((uint32_t *)buf);
+
+	switch(cmd_id)
+	{
+		case TZ_CM_CMD_RPMB_READ:
+		case TZ_CM_CMD_RPMB_WRITE:
+			handle_rw_request(buf, sz);
+			break;
+		case TZ_CM_CMD_RPMB_INIT:
+#if DEBUG_RPMB
+			dprintf(INFO, "RPMB init received\n");
+#endif
+			handle_init_request(buf, sz);
+			break;
+		case TZ_CM_CMD_RPMB_PARTITION:
+#if DEBUG_RPMB
+			dprintf(INFO, "Partition init received\n");
+#endif
+			ret = -1;
+			break;
+		default:
+			/* Does qseecom need a response here? */
+			dprintf(CRITICAL, "Unsupported Request from qseecom: %d\n", cmd_id);
+			ASSERT(0);
+	};
+
+	return ret;
+}
+
+int rpmb_listener_start()
+{
+	int ret;
+	struct qseecom_listener_services rpmb_listener;
+
+	rpmb_listener.service_name = "RPMB system services";
+	rpmb_listener.id           =  RPMB_LSTNR_ID;
+	rpmb_listener.sb_size      = 20 * 1024;
+	rpmb_listener.service_cmd_handler = rpmb_cmd_handler;
+
+	ret = qseecom_register_listener(&rpmb_listener);
+
+	if (ret < 0)
+		dprintf(CRITICAL, "Failed to register rpmb listener\n");
+
+	return ret;
+}
+
+int rpmb_listener_stop(int id)
+{
+	int ret;
+
+	ret = qseecom_deregister_listener(id);
+
+	if (ret < 0)
+		dprintf(CRITICAL, "Failed to unregister rpmb listener\n");
+
+	return ret;
+}
+
diff --git a/platform/msm_shared/rpmb/rpmb_ufs.c b/platform/msm_shared/rpmb/rpmb_ufs.c
new file mode 100644
index 0000000..3cc4d91
--- /dev/null
+++ b/platform/msm_shared/rpmb/rpmb_ufs.c
@@ -0,0 +1,294 @@
+/* Copyright (c) 2015, 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 <ufs.h>
+#include <ucs.h>
+#include <upiu.h>
+#include <rpmb.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <arch/defines.h>
+
+static struct rpmb_frame read_result_reg =
+{
+	.requestresponse[1] = READ_RESULT_FLAG,
+};
+
+int rpmb_read_ufs(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len)
+{
+	// validate input parameters
+	ASSERT(req_buf);
+	ASSERT(resp_buf);
+	ASSERT(resp_len);
+
+	STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_sec_protocol_cdb));
+	struct scsi_req_build_type   req_upiu;
+	struct scsi_sec_protocol_cdb *cdb_out_param, *cdb_in_param;
+	uint32_t                     blks_remaining;
+	uint32_t                     blks_to_transfer;
+	uint64_t                     bytes_to_transfer;
+	uint64_t                     max_size;
+	blks_remaining    = blk_cnt;
+	blks_to_transfer  = blks_remaining;
+	bytes_to_transfer = blks_to_transfer * RPMB_FRAME_SIZE;
+
+#ifdef DEBUG_RPMB
+	dump_rpmb_frame((uint8_t *)req_buf, "request");
+#endif
+
+	// check if total bytes to transfer exceed max supported size
+	max_size = dev->rpmb_rw_size * RPMB_FRAME_SIZE * blk_cnt;
+	if (bytes_to_transfer > max_size)
+	{
+		dprintf(CRITICAL, "RPMB request transfer size %llu greater than max transfer size %llu\n", bytes_to_transfer, max_size);
+		return -UFS_FAILURE;
+	}
+#ifdef DEBUG_RPMB
+	dprintf(SPEW, "rpmb_read: req_buf: 0x%x blk_count: 0x%x\n", *req_buf, blk_cnt);
+	dprintf(INFO, "rpmb_read: bytes_to_transfer: 0x%x blks_to_transfer: 0x%x\n",
+                   bytes_to_transfer, blks_to_transfer);
+#endif
+	// send the request
+	cdb_out_param = (struct scsi_sec_protocol_cdb*) cdb;
+	memset(cdb_out_param, 0, sizeof(struct scsi_sec_protocol_cdb));
+
+	cdb_out_param->opcode                = SCSI_CMD_SECPROT_OUT;
+	cdb_out_param->cdb1                  = SCSI_SEC_PROT;
+	cdb_out_param->sec_protocol_specific = BE16(SCSI_SEC_UFS_PROT_ID);
+	cdb_out_param->alloc_tlen            = BE32(bytes_to_transfer);
+
+	// Flush CDB to memory
+	dsb();
+	arch_clean_invalidate_cache_range((addr_t) cdb_out_param, sizeof(struct scsi_sec_protocol_cdb));
+
+	memset(&req_upiu, 0, sizeof(struct scsi_req_build_type));
+
+	req_upiu.cdb              = (addr_t) cdb_out_param;
+	req_upiu.data_buffer_addr = (addr_t) req_buf;
+	req_upiu.data_len         = bytes_to_transfer;
+	req_upiu.flags            = UPIU_FLAGS_WRITE;
+	req_upiu.lun              = UFS_WLUN_RPMB;
+	req_upiu.dd               = UTRD_TARGET_TO_SYSTEM;
+
+#ifdef DEBUG_RPMB
+	dprintf(INFO, "Sending RPMB Read request\n");
+#endif
+	if (ucs_do_scsi_cmd(dev, &req_upiu))
+	{
+		dprintf(CRITICAL, "%s:%d ucs_do_scsi_rpmb_read: failed\n", __func__, __LINE__);
+		return -UFS_FAILURE;
+	}
+#ifdef DEBUG_RPMB
+	dprintf(INFO, "Sending RPMB Read request complete\n");
+#endif
+	// read the response
+	cdb_in_param = (struct scsi_sec_protocol_cdb*) cdb;
+	memset(cdb_in_param, 0, sizeof(struct scsi_sec_protocol_cdb));
+
+	cdb_in_param->opcode                = SCSI_CMD_SECPROT_IN;
+	cdb_in_param->cdb1                  = SCSI_SEC_PROT;
+	cdb_in_param->sec_protocol_specific = BE16(SCSI_SEC_UFS_PROT_ID);
+	cdb_in_param->alloc_tlen            = BE32(bytes_to_transfer);
+
+	// Flush CDB to memory
+	dsb();
+	arch_clean_invalidate_cache_range((addr_t) cdb_in_param, sizeof(struct scsi_sec_protocol_cdb));
+
+	memset(&req_upiu, 0, sizeof(struct scsi_req_build_type));
+
+	req_upiu.cdb              = (addr_t) cdb_in_param;
+	req_upiu.data_buffer_addr = (addr_t) resp_buf;
+	req_upiu.data_len         = bytes_to_transfer;
+	req_upiu.flags            = UPIU_FLAGS_READ;
+	req_upiu.lun              = UFS_WLUN_RPMB;
+	req_upiu.dd               = UTRD_SYSTEM_TO_TARGET;
+
+#ifdef DEBUG_RPMB
+	dprintf(INFO, "Sending RPMB Read response\n");
+#endif
+	if (ucs_do_scsi_cmd(dev, &req_upiu))
+	{
+		dprintf(CRITICAL, "%s:%d ucs_do_scsi_rpmb_read: failed\n", __func__, __LINE__);
+		return -UFS_FAILURE;
+	}
+#ifdef DEBUG_RPMB
+	dprintf(SPEW, "Sending RPMB Read response complete\n");
+	dump_rpmb_frame((uint8_t *)resp_buf, "response");
+#endif
+	*resp_len = bytes_to_transfer;
+	return UFS_SUCCESS;
+}
+
+int rpmb_write_ufs(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt, uint32_t *resp_buf, uint32_t *resp_len)
+{
+	// validate input parameters
+	ASSERT(req_buf);
+	ASSERT(resp_buf);
+	ASSERT(resp_len);
+
+	STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_sec_protocol_cdb));
+	struct scsi_req_build_type   req_upiu;
+	struct scsi_sec_protocol_cdb *cdb_out_param, *cdb_in_param;
+	uint32_t                     blks_remaining;
+	uint32_t                     blks_to_transfer;
+	uint64_t                     bytes_to_transfer;
+	uint64_t                     max_size;
+	uint32_t                     result_frame_bytes = RPMB_FRAME_SIZE;
+	uint32_t                     i;
+
+	blks_remaining    = blk_cnt;
+	blks_to_transfer  = blks_remaining;
+	bytes_to_transfer = blks_to_transfer * RPMB_FRAME_SIZE;
+
+	// check if total bytes to transfer exceed max supported size
+	max_size = dev->rpmb_rw_size * RPMB_FRAME_SIZE * blk_cnt;
+	if (bytes_to_transfer > max_size)
+	{
+		dprintf(CRITICAL, "RPMB request transfer size %llu greater than max transfer size %llu\n", bytes_to_transfer, max_size);
+		return -UFS_FAILURE;
+	}
+#ifdef DEBUG_RPMB
+	dprintf(INFO, "%s: req_buf: 0x%x blk_count: 0x%x\n", __func__,*req_buf, blk_cnt);
+	dprintf(INFO, "%s: bytes_to_transfer: 0x%x blks_to_transfer: 0x%x\n", __func__
+                   bytes_to_transfer, blk_cnt);
+	dump_rpmb_frame((uint8_t *)req_buf, "request");
+#endif
+
+	for (i = 0; i < blk_cnt; i++)
+	{
+		// send the request
+		cdb_out_param = (struct scsi_sec_protocol_cdb*) cdb;
+		memset(cdb_out_param, 0, sizeof(struct scsi_sec_protocol_cdb));
+
+		cdb_out_param->opcode                = SCSI_CMD_SECPROT_OUT;
+		cdb_out_param->cdb1                  = SCSI_SEC_PROT;
+		cdb_out_param->sec_protocol_specific = BE16(SCSI_SEC_UFS_PROT_ID);
+		cdb_out_param->alloc_tlen            = BE32(RPMB_FRAME_SIZE);
+
+		// Flush CDB to memory
+		dsb();
+		arch_clean_invalidate_cache_range((addr_t) cdb_out_param, sizeof(struct scsi_sec_protocol_cdb));
+
+		memset(&req_upiu, 0, sizeof(struct scsi_req_build_type));
+
+		req_upiu.cdb              = (addr_t) cdb_out_param;
+		req_upiu.data_buffer_addr = (addr_t) req_buf;
+		req_upiu.data_len         = RPMB_FRAME_SIZE;
+		req_upiu.flags            = UPIU_FLAGS_WRITE;
+		req_upiu.lun              = UFS_WLUN_RPMB;
+		req_upiu.dd               = UTRD_TARGET_TO_SYSTEM;
+
+#ifdef DEBUG_RPMB
+		dprintf(INFO, "Sending RPMB write request: Start\n");
+#endif
+		if (ucs_do_scsi_cmd(dev, &req_upiu))
+		{
+			dprintf(CRITICAL, "%s:%d ucs_do_scsi_rpmb_read: failed\n", __func__, __LINE__);
+			return -UFS_FAILURE;
+		}
+#ifdef DEBUG_RPMB
+		dprintf(INFO, "Sending RPMB write request: Done\n");
+#endif
+		// Result Read
+		cdb_in_param = (struct scsi_sec_protocol_cdb*) cdb;
+		memset(cdb_in_param, 0, sizeof(struct scsi_sec_protocol_cdb));
+
+		cdb_in_param->opcode                = SCSI_CMD_SECPROT_OUT;
+		cdb_in_param->cdb1                  = SCSI_SEC_PROT;
+		cdb_in_param->sec_protocol_specific = BE16(SCSI_SEC_UFS_PROT_ID);
+		cdb_in_param->alloc_tlen            = BE32(RPMB_FRAME_SIZE);
+
+		// Flush CDB to memory
+		dsb();
+		arch_clean_invalidate_cache_range((addr_t) cdb_in_param, sizeof(struct scsi_sec_protocol_cdb));
+
+		memset(&req_upiu, 0, sizeof(struct scsi_req_build_type));
+
+		req_upiu.cdb              = (addr_t) cdb_in_param;
+		req_upiu.data_buffer_addr = (addr_t) &read_result_reg ;
+		req_upiu.data_len         = result_frame_bytes;
+		req_upiu.flags            = UPIU_FLAGS_WRITE;
+		req_upiu.lun              = UFS_WLUN_RPMB;
+		req_upiu.dd               = UTRD_TARGET_TO_SYSTEM;
+
+#ifdef DEBUG_RPMB
+		dprintf(INFO, "Sending RPMB Result Read Register: Start \n");
+#endif
+		if (ucs_do_scsi_cmd(dev, &req_upiu))
+		{
+			dprintf(CRITICAL, "%s:%d ucs_do_scsi_rpmb_read: failed\n", __func__, __LINE__);
+			return -UFS_FAILURE;
+		}
+#ifdef DEBUG_RPMB
+		dprintf(SPEW, "Sending RPMB Result Read Register: Done\n");
+#endif
+
+		// Retrieve verification result
+		cdb_in_param = (struct scsi_sec_protocol_cdb*) cdb;
+		memset(cdb_in_param, 0, sizeof(struct scsi_sec_protocol_cdb));
+
+		cdb_in_param->opcode                = SCSI_CMD_SECPROT_IN;
+		cdb_in_param->cdb1                  = SCSI_SEC_PROT;
+		cdb_in_param->sec_protocol_specific = BE16(SCSI_SEC_UFS_PROT_ID);
+		cdb_in_param->alloc_tlen            = BE32(RPMB_FRAME_SIZE);
+
+		// Flush CDB to memory
+		dsb();
+		arch_clean_invalidate_cache_range((addr_t) cdb_in_param, sizeof(struct scsi_sec_protocol_cdb));
+
+		memset(&req_upiu, 0, sizeof(struct scsi_req_build_type));
+
+		req_upiu.cdb              = (addr_t) cdb_in_param;
+		req_upiu.data_buffer_addr = (addr_t) resp_buf;
+		req_upiu.data_len         = result_frame_bytes;
+		req_upiu.flags            = UPIU_FLAGS_READ;
+		req_upiu.lun              = UFS_WLUN_RPMB;
+		req_upiu.dd               = UTRD_SYSTEM_TO_TARGET;
+
+#ifdef DEBUG_RPMB
+		dprintf(INFO, "Sending RPMB Response for Result Read Register : Start\n");
+#endif
+		if (ucs_do_scsi_cmd(dev, &req_upiu))
+		{
+			dprintf(CRITICAL, "%s:%d ucs_do_scsi_rpmb_read: failed\n", __func__, __LINE__);
+			return -UFS_FAILURE;
+		}
+#ifdef DEBUG_RPMB
+		dprintf(SPEW, "Sending RPMB Response for Result Read Register: Done\n");
+		dump_rpmb_frame((uint8_t *)resp_buf, "response");
+#endif
+
+		req_buf = (uint32_t*) ((uint8_t*)req_buf + RPMB_BLK_SIZE);
+	}
+
+	*resp_len = RPMB_MIN_BLK_CNT * RPMB_BLK_SIZE;
+
+	return 0;
+}
diff --git a/platform/msm_shared/rpmb/rules.mk b/platform/msm_shared/rpmb/rules.mk
new file mode 100644
index 0000000..0e76433
--- /dev/null
+++ b/platform/msm_shared/rpmb/rules.mk
@@ -0,0 +1,8 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+INCLUDES += -I$(LOCAL_DIR)/include
+
+OBJS += $(LOCAL_DIR)/rpmb.o \
+		$(LOCAL_DIR)/rpmb_listener.o \
+		$(LOCAL_DIR)/rpmb_emmc.o \
+		$(LOCAL_DIR)/rpmb_ufs.o
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
old mode 100755
new mode 100644
index 793b88c..fe90e5d
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -23,6 +23,7 @@
 
 ifeq ($(ENABLE_SMD_SUPPORT),1)
 OBJS += \
+	$(LOCAL_DIR)/rpm-ipc.o \
 	$(LOCAL_DIR)/rpm-smd.o \
 	$(LOCAL_DIR)/smd.o
 endif
@@ -43,6 +44,21 @@
 	$(LOCAL_DIR)/boot_verifier.o
 endif
 
+ifeq ($(ENABLE_GLINK_SUPPORT),1)
+OBJS += \
+		$(LOCAL_DIR)/rpm-ipc.o \
+		$(LOCAL_DIR)/glink/glink_api.o \
+		$(LOCAL_DIR)/glink/glink_core_if.o \
+		$(LOCAL_DIR)/glink/glink_rpmcore_setup.o \
+		$(LOCAL_DIR)/glink/glink_core_intentless_xport.o \
+		$(LOCAL_DIR)/glink/glink_os_utils_dal.o \
+		$(LOCAL_DIR)/glink/glink_vector.o \
+		$(LOCAL_DIR)/glink/xport_rpm.o \
+		$(LOCAL_DIR)/glink/xport_rpm_config.o \
+		$(LOCAL_DIR)/smem_list.o \
+		$(LOCAL_DIR)/rpm-glink.o
+endif
+
 ifeq ($(PLATFORM),msm8x60)
 	OBJS += $(LOCAL_DIR)/mipi_dsi.o \
 			$(LOCAL_DIR)/i2c_qup.o \
@@ -483,7 +499,7 @@
 			$(LOCAL_DIR)/mipi_dsi_autopll.o
 endif
 
-ifeq ($(PLATFORM),thulium)
+ifeq ($(PLATFORM),msm8996)
 	OBJS += $(LOCAL_DIR)/qtimer.o \
 			$(LOCAL_DIR)/qtimer_mmap.o \
 			$(LOCAL_DIR)/interrupts.o \
@@ -498,6 +514,7 @@
 			$(LOCAL_DIR)/dev_tree.o \
 			$(LOCAL_DIR)/gpio.o \
 			$(LOCAL_DIR)/scm.o \
+			$(LOCAL_DIR)/qseecom_lk.o \
 			$(LOCAL_DIR)/qmp_usb30_phy.o \
 			$(LOCAL_DIR)/qusb2_phy.o \
 			$(LOCAL_DIR)/certificate.o \
@@ -517,6 +534,31 @@
 			$(LOCAL_DIR)/dme.o
 endif
 
+ifeq ($(PLATFORM),msm8952)
+	OBJS += $(LOCAL_DIR)/qgic.o \
+			$(LOCAL_DIR)/qtimer.o \
+			$(LOCAL_DIR)/qtimer_mmap.o \
+			$(LOCAL_DIR)/interrupts.o \
+			$(LOCAL_DIR)/clock.o \
+			$(LOCAL_DIR)/clock_pll.o \
+			$(LOCAL_DIR)/clock_lib2.o \
+			$(LOCAL_DIR)/uart_dm.o \
+			$(LOCAL_DIR)/board.o \
+			$(LOCAL_DIR)/spmi.o \
+			$(LOCAL_DIR)/bam.o \
+			$(LOCAL_DIR)/qpic_nand.o \
+			$(LOCAL_DIR)/scm.o \
+			$(LOCAL_DIR)/dev_tree.o \
+			$(LOCAL_DIR)/gpio.o \
+			$(LOCAL_DIR)/dload_util.o \
+			$(LOCAL_DIR)/shutdown_detect.o \
+			$(LOCAL_DIR)/certificate.o \
+			$(LOCAL_DIR)/image_verify.o \
+			$(LOCAL_DIR)/crypto_hash.o \
+			$(LOCAL_DIR)/crypto5_eng.o \
+			$(LOCAL_DIR)/crypto5_wrapper.o
+endif
+
 ifeq ($(ENABLE_BOOT_CONFIG_SUPPORT), 1)
 	OBJS += \
 		$(LOCAL_DIR)/boot_device.o
@@ -533,3 +575,11 @@
 ifeq ($(ENABLE_PARTIAL_GOODS_SUPPORT), 1)
 	OBJS += $(LOCAL_DIR)/partial_goods.o
 endif
+
+ifeq ($(ENABLE_RPMB_SUPPORT), 1)
+include platform/msm_shared/rpmb/rules.mk
+endif
+
+ifeq ($(ENABLE_REBOOT_MODULE), 1)
+	OBJS += $(LOCAL_DIR)/reboot.o
+endif
diff --git a/platform/msm_shared/scm.c b/platform/msm_shared/scm.c
index b45fd3d..88e6898 100644
--- a/platform/msm_shared/scm.c
+++ b/platform/msm_shared/scm.c
@@ -34,6 +34,8 @@
 #include <arch/ops.h>
 #include <rand.h>
 #include <image_verify.h>
+#include <dload_util.h>
+#include <platform/iomap.h>
 #include "scm.h"
 
 #pragma GCC optimize ("O0")
@@ -54,6 +56,12 @@
 
 /* SCM interface as per ARM spec present? */
 bool scm_arm_support;
+static uint32_t scm_io_write(uint32_t address, uint32_t val);
+
+bool is_scm_armv8_support()
+{
+	return scm_arm_support;
+}
 
 static void scm_arm_support_available(uint32_t svc_id, uint32_t cmd_id)
 {
@@ -958,14 +966,29 @@
 int scm_halt_pmic_arbiter()
 {
 	int ret = 0;
+	scmcall_arg scm_arg = {0};
 
-	if (scm_arm_support)
-	{
-		dprintf(INFO, "%s:SCM call is not supported\n",__func__);
-		return -1;
+	if (scm_arm_support) {
+		scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER);
+		scm_arg.x1 = MAKE_SCM_ARGS(0x1);
+		scm_arg.x2 = 0;
+		scm_arg.atomic = true;
+		ret = scm_call2(&scm_arg, NULL);
+	} else {
+		ret = scm_call_atomic(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER, 0);
 	}
 
-	ret = scm_call_atomic(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER, 0);
+	/* Retry with the SCM_IO_DISABLE_PMIC_ARBITER1 func ID if the above Func ID fails*/
+	if(ret) {
+		if (scm_arm_support) {
+			scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER1);
+			scm_arg.x1 = MAKE_SCM_ARGS(0x1);
+			scm_arg.x2 = 0;
+			scm_arg.atomic = true;
+			ret = scm_call2(&scm_arg, NULL);
+		} else
+			ret = scm_call_atomic(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER1, 0);
+	}
 
 	return ret;
 }
@@ -1117,20 +1140,22 @@
 	register uint32_t r4 __asm__("r4") = x4;
 	register uint32_t r5 __asm__("r5") = x5;
 
-	__asm__ volatile(
-		__asmeq("%0", "r0")
-		__asmeq("%1", "r1")
-		__asmeq("%2", "r2")
-		__asmeq("%3", "r3")
-		__asmeq("%4", "r0")
-		__asmeq("%5", "r1")
-		__asmeq("%6", "r2")
-		__asmeq("%7", "r3")
-		__asmeq("%8", "r4")
-		__asmeq("%9", "r5")
-		"smc    #0  @ switch to secure world\n"
-		: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
-		: "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5));
+	do {
+		__asm__ volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r1")
+			__asmeq("%2", "r2")
+			__asmeq("%3", "r3")
+			__asmeq("%4", "r0")
+			__asmeq("%5", "r1")
+			__asmeq("%6", "r2")
+			__asmeq("%7", "r3")
+			__asmeq("%8", "r4")
+			__asmeq("%9", "r5")
+			"smc    #0  @ switch to secure world\n"
+			: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
+			: "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5));
+	} while(r0 == 1);
 
 	if (ret)
 	{
@@ -1178,3 +1203,133 @@
 
 	return 0;
 }
+
+static bool secure_boot_enabled = true;
+static bool wdog_debug_fuse_disabled = true;
+
+void scm_check_boot_fuses()
+{
+	uint32_t ret = 0;
+	uint32_t resp;
+	scmcall_arg scm_arg = {0};
+	scmcall_ret scm_ret = {0};
+
+	if (!scm_arm_support) {
+		ret = scm_call(TZBSP_SVC_INFO, IS_SECURE_BOOT_ENABLED, NULL, 0, &resp, sizeof(resp));
+	} else {
+		scm_arg.x0 = MAKE_SIP_SCM_CMD(TZBSP_SVC_INFO, IS_SECURE_BOOT_ENABLED);
+		ret = scm_call2(&scm_arg, &scm_ret);
+		resp = scm_ret.x1;
+	}
+
+	/* Parse Bit 0 and Bit 2 of the response */
+	if(!ret) {
+		/* Bit 0 - SECBOOT_ENABLE_CHECK */
+		if(resp & 0x1)
+			secure_boot_enabled = false;
+		/* Bit 2 - DEBUG_DISABLE_CHECK */
+		if(resp & 0x4)
+			wdog_debug_fuse_disabled = false;
+	} else
+		dprintf(CRITICAL, "scm call to check secure boot fuses failed\n");
+}
+
+bool is_secure_boot_enable()
+{
+	scm_check_boot_fuses();
+	return secure_boot_enabled;
+}
+
+static uint32_t scm_io_read(addr_t address)
+{
+	uint32_t ret;
+	scmcall_arg scm_arg = {0};
+	scmcall_ret scm_ret = {0};
+
+	if (!scm_arm_support) {
+		ret = scm_call_atomic(SCM_SVC_IO, SCM_IO_READ, address);
+	} else {
+		scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_IO, SCM_IO_READ);
+		scm_arg.x1 = MAKE_SCM_ARGS(0x1);
+		scm_arg.x2 = address;
+		scm_arg.atomic = true;
+		ret = scm_call2(&scm_arg, &scm_ret);
+	}
+	return ret;
+}
+
+static uint32_t scm_io_write(uint32_t address, uint32_t val)
+{
+	uint32_t ret;
+	scmcall_arg scm_arg = {0};
+	scmcall_ret scm_ret = {0};
+
+	if (!scm_arm_support) {
+		ret = scm_call_atomic2(SCM_SVC_IO, SCM_IO_WRITE, address, val);
+	} else {
+		scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_IO, SCM_IO_WRITE);
+		scm_arg.x1 = MAKE_SCM_ARGS(0x2);
+		scm_arg.x2 = address;
+		scm_arg.x3 = val;
+		scm_arg.atomic = true;
+		ret = scm_call2(&scm_arg, &scm_ret);
+	}
+	return ret;
+}
+
+static int scm_call2_atomic(uint32_t svc, uint32_t cmd, uint32_t arg1, uint32_t arg2)
+{
+	uint32_t ret = 0;
+	scmcall_arg scm_arg = {0};
+	scmcall_ret scm_ret = {0};
+
+	if (!scm_arm_support)
+	{
+		ret = scm_call_atomic2(svc, cmd, arg1, arg2);
+	} else {
+		scm_arg.x0 = MAKE_SIP_SCM_CMD(svc, cmd);
+		scm_arg.x1 = MAKE_SCM_ARGS(0x2);
+		scm_arg.x2 = arg1;
+		scm_arg.x3 = arg2;
+		ret =  scm_call2(&scm_arg, &scm_ret);
+	}
+	return ret;
+}
+
+#if PLATFORM_USE_SCM_DLOAD
+int scm_dload_mode(int mode)
+{
+	int ret = 0;
+	uint32_t dload_type;
+
+	dprintf(SPEW, "DLOAD mode: %d\n", mode);
+	if (mode == NORMAL_DLOAD)
+		dload_type = SCM_DLOAD_MODE;
+	else if(mode == EMERGENCY_DLOAD)
+		dload_type = SCM_EDLOAD_MODE;
+	else
+		dload_type = 0;
+
+	/* Write to the Boot MISC register */
+	ret = scm_call2_atomic(SCM_SVC_BOOT, SCM_DLOAD_CMD, dload_type, 0);
+
+	if (ret) {
+		ret = scm_io_write(TCSR_BOOT_MISC_DETECT,dload_type);
+		if(ret) {
+			dprintf(CRITICAL, "Failed to write to boot misc: %d\n", ret);
+			return ret;
+		}
+	}
+
+	scm_check_boot_fuses();
+
+	/* Make WDOG_DEBUG DISABLE scm call only in non-secure boot */
+	if(!(secure_boot_enabled || wdog_debug_fuse_disabled)) {
+		ret = scm_call2_atomic(SCM_SVC_BOOT, WDOG_DEBUG_DISABLE, 1, 0);
+		if(ret)
+			dprintf(CRITICAL, "Failed to disable the wdog debug \n");
+	}
+
+	return ret;
+}
+#endif
diff --git a/platform/msm_shared/sdhci_msm.c b/platform/msm_shared/sdhci_msm.c
index 4e83a55..47bdfd1 100644
--- a/platform/msm_shared/sdhci_msm.c
+++ b/platform/msm_shared/sdhci_msm.c
@@ -42,6 +42,7 @@
 
 
 #define MX_DRV_SUPPORTED_HS200 3
+static bool attempt_cdr_unlock;
 
 /* Known data stored in the card & read during tuning
  * process. 64 bytes for 4bit bus width & 128 bytes
@@ -336,7 +337,7 @@
 	msm_set_dll_freq(host);
 
 	/* Configure the mclk freq based on the current clock rate
-	 * and fll cycle count as per hpg section 15.2.2
+	 * and fll cycle count
 	 */
 	if (host->major == 1 && host->minor >= 0x42)
 	{
@@ -720,15 +721,6 @@
 	/* In Tuning mode */
 	host->tuning_in_progress = true;
 
-	/* Calibration for CDCLP533 needed for HS400 mode */
-	if (msm_host->tuning_done && !msm_host->calibration_done && host->timing == MMC_HS400_TIMING)
-	{
-		ret = sdhci_msm_hs400_calibration(host);
-		if (!ret)
-			msm_host->calibration_done = true;
-		goto out;
-	}
-
 	if (bus_width == DATA_BUS_WIDTH_8BIT)
 	{
 		tuning_block = (uint32_t *)tuning_block_128;
@@ -744,26 +736,34 @@
 
 	ASSERT(tuning_data);
 
+	/* Calibration for CDCLP533 needed for HS400 mode */
+	if (msm_host->tuning_done && !msm_host->calibration_done && host->timing == MMC_HS400_TIMING)
+	{
+		ret = sdhci_msm_hs400_calibration(host);
+		if (!ret)
+			msm_host->calibration_done = true;
+		goto out;
+	}
+
 	/* Reset & Initialize the DLL block */
 	if (sdhci_msm_init_dll(host))
 	{
 			ret = 1;
-			goto free;
+			goto out;
 	}
 
 retry_tuning:
 	tuned_phase_cnt = 0;
 	phase = 0;
+	struct mmc_command cmd = {0};
 
 	while (phase < MAX_PHASES)
 	{
-		struct mmc_command cmd = {0};
-
 		/* configure dll to set phase delay */
 		if (sdhci_msm_config_dll(host, phase))
 		{
 			ret = 1;
-			goto free;
+			goto out;
 		}
 
 		cmd.cmd_index = CMD21_SEND_TUNING_BLOCK;
@@ -802,6 +802,12 @@
 	if (drv_type_changed)
 		mmc_set_drv_type(host, card, 0);
 
+	if (tuned_phase_cnt == MAX_PHASES)
+	{
+		attempt_cdr_unlock = true;
+		dprintf(CRITICAL, "WARNING: All phase passed.The selected phase may not be optimal\n");
+	}
+
 	/* Find the appropriate tuned phase */
 	if (tuned_phase_cnt)
 	{
@@ -817,7 +823,7 @@
 		{
 			dprintf(CRITICAL, "Failed in selecting the tuning phase\n");
 			ret = 1;
-			goto free;
+			goto out;
 		}
 
 		phase = (uint32_t) ret;
@@ -826,7 +832,7 @@
 		DBG("\n: %s: Tuned Phase: 0x%08x\n", __func__, phase);
 
 		if (sdhci_msm_config_dll(host, phase))
-			goto free;
+			goto out;
 
 		/* Save the tuned phase */
 		host->msm_host->saved_phase = phase;
@@ -837,9 +843,30 @@
 		ret = 1;
 	}
 
-free:
-	free(tuning_data);
 out:
+	/* If all the tuning phases passed, send CMD21 after enabling
+	 * CDR to make sure right tuning phase is selected by CDR
+	 */
+	if (attempt_cdr_unlock)
+	{
+		cmd.cmd_index = CMD21_SEND_TUNING_BLOCK;
+		cmd.argument = 0x0;
+		cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd.resp_type = SDHCI_CMD_RESP_R1;
+		cmd.trans_mode = SDHCI_MMC_READ;
+		cmd.data_present = 0x1;
+		cmd.data.data_ptr = tuning_data;
+		cmd.data.blk_sz = size;
+		cmd.data.num_blocks = 0x1;
+
+		/* send command */
+		if (!sdhci_send_command(host, &cmd))
+		{
+			DBG("\n: %s: Sending CMD21 after CDR enable with default phases fail\n", __func__);
+		}
+	}
+
+	free(tuning_data);
 	/* Tuning done */
 	host->tuning_in_progress = false;
 	host->msm_host->tuning_done = true;
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index db186d4..3468435 100644
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -54,6 +54,7 @@
 {
 	SMEM_RAM_PTABLE_VERSION_0,
 	SMEM_RAM_PTABLE_VERSION_1,
+	SMEM_RAM_PTABLE_VERSION_2,
 };
 
 struct smem_proc_comm {
@@ -400,14 +401,15 @@
 	MDM9609  = 262,
 	MSM8239  = 263,
 	APQ8009  = 265,
-	MSMTELLURIUM  = 264,
-	MSMTERBIUM    = 266,
+	MSM8952  = 264,
+	MSM8956  = 266,
 	MSM8929  = 268,
 	MSM8629  = 269,
 	MSM8229  = 270,
 	APQ8029  = 271,
 	MSM8609  = 275,
 	FSM9916  = 276,
+	MSM8976  = 278,
 };
 
 enum platform {
@@ -549,6 +551,20 @@
 	uint32_t reserved5;     /* Reserved for future use */
 } __attribute__ ((__packed__));
 
+struct smem_ram_ptn_v2 {
+	char name[RAM_PART_NAME_LENGTH];
+	uint64_t start;
+	uint64_t size;
+	uint32_t attr;          /* RAM Partition attribute: READ_ONLY, READWRITE etc.*/
+	uint32_t category;      /* RAM Partition category: EBI0, EBI1, IRAM, IMEM */
+	uint32_t domain;        /* RAM Partition domain: APPS, MODEM, APPS & MODEM (SHARED) etc. */
+	uint32_t type;          /* RAM Partition type: system, bootloader, appsboot, apps etc. */
+	uint32_t num_partitions;/* Number of memory partitions */
+	uint32_t hw_info;       /* hw information such as type and frequency */
+	uint64_t reserved;      /* Reserved for future use */
+	uint64_t available_length; /* Available partition length in RAM in bytes */
+} __attribute__ ((__packed__));
+
 struct smem_ram_ptable {
 	unsigned magic[2];
 	unsigned version;
@@ -572,6 +588,12 @@
 	struct smem_ram_ptn_v1 parts[RAM_NUM_PART_ENTRIES];
 } __attribute__ ((__packed__));
 
+struct smem_ram_ptable_v2 {
+	struct smem_ram_ptable_hdr hdr;
+	uint32_t reserved2;     /* Added for 8 bytes alignment of header */
+	struct smem_ram_ptn_v2 parts[RAM_NUM_PART_ENTRIES];
+} __attribute__ ((__packed__));
+
 /* Power on reason/status info */
 #define PWR_ON_EVENT_RTC_ALARM 0x2
 #define PWR_ON_EVENT_USB_CHG   0x20
@@ -600,8 +622,8 @@
 	struct smem_ptn parts[SMEM_PTABLE_MAX_PARTS];
 } __attribute__ ((__packed__));
 
-typedef struct smem_ram_ptable_v1 ram_partition_table;
-typedef struct smem_ram_ptn_v1 ram_partition;
+typedef struct smem_ram_ptable_v2 ram_partition_table;
+typedef struct smem_ram_ptn_v2 ram_partition;
 
 unsigned smem_read_alloc_entry_offset(smem_mem_type_t type, void *buf, int len, int offset);
 int smem_ram_ptable_init(struct smem_ram_ptable *smem_ram_ptable);
@@ -610,4 +632,5 @@
 uint32_t smem_get_ram_ptable_version(void);
 uint32_t smem_get_ram_ptable_len(void);
 void* smem_get_alloc_entry(smem_mem_type_t type, uint32_t* size);
+uint32_t get_ddr_start();
 #endif				/* __PLATFORM_MSM_SHARED_SMEM_H */
diff --git a/platform/msm_shared/smem_list.c b/platform/msm_shared/smem_list.c
new file mode 100644
index 0000000..fc89671
--- /dev/null
+++ b/platform/msm_shared/smem_list.c
@@ -0,0 +1,242 @@
+/* Copyright (c) 2015, 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.
+*/
+
+/*===========================================================================
+
+                         S H A R E D   M E M O R Y
+
+===========================================================================*/
+
+
+
+/*===========================================================================
+
+                        INCLUDE FILES
+
+===========================================================================*/
+#include "smem_list.h"
+#include <sys/types.h>
+
+/*=============================================================================
+
+            GLOBAL DEFINITIONS AND DECLARATIONS FOR MODULE
+
+=============================================================================*/
+
+
+/*===========================================================================
+
+                      PRIVATE FUNCTION DECLARATIONS
+
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION      smem_list_init
+===========================================================================*/
+/**
+  Creates a generic list.
+
+  @param[in/out] list   Pointer to the user list.
+
+  @return
+  N/A.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_init( smem_list_type *list )
+{
+  list->next  = NULL;
+  list->count = 0;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_append
+===========================================================================*/
+/**
+  Appends an element to the end of a generic list.
+
+  The element must contain a smem_list_link_type at its base address.
+  The element should not be already present in any list.
+
+  @param[in/out] list   Pointer to the user list.
+  @param[in] item       Element to be inserted.
+
+  @return
+  N/A.
+
+  @dependencies
+  The element must contain a smem_list_link_type at its base address.
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void smem_list_append( smem_list_type *list, void *item )
+{
+  smem_list_link_type *link = ( smem_list_link_type * )list;
+
+  /* get next item until link->next points to null */
+  while( link->next )
+  {
+    link = link->next;
+  }
+
+  /* link->next points to null here, but we can point it to the new item */
+  link->next = item;
+
+  /* point link to the head of the new item */
+  link = item;
+
+  /* terminate the list */
+  link->next = NULL;
+
+  list->count++;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_delete
+===========================================================================*/
+/**
+  Removes the specified element from a generic list.
+
+  The element may be present at any point in the list.
+
+  @param[in] list       Pointer to the user list.
+  @param[in] item       Element to be removed.
+
+  @return
+  0 if the element is deleted, or a negative error code if the element
+  is not found.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_delete( smem_list_type *list, void *item )
+{
+  smem_list_link_type *link = ( smem_list_link_type * )list;
+
+  /* get next item until link points to item in question */
+  while( link->next != item )
+  {
+    if( NULL == link->next )
+    {
+      return -1;
+    }
+
+    link = link->next;
+  }
+
+  link->next = ( ( smem_list_link_type * )item )->next;
+
+  list->count--;
+
+  return 0;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_first
+===========================================================================*/
+/**
+  Retrieves the first element in the list without removing it.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the first element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_first( smem_list_type *list )
+{
+  /* return the first item in the list */
+  return list->next;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_next
+===========================================================================*/
+/**
+  Retrieves the next element in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Pointer to the next element in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+void *smem_list_next( void * item )
+{
+  /* just return the item that this item points to
+   * (base address contains a pointer) */
+  return ( ( smem_list_link_type * )item )->next;
+}
+
+/*===========================================================================
+FUNCTION      smem_list_count
+===========================================================================*/
+/**
+  Gets the number of elements in the list.
+
+  @param[in] list       Pointer to the user list.
+
+  @return
+  Count of elements in the list.
+
+  @dependencies
+  List must be protected by critical sections for multi-threaded use.
+
+  @sideeffects
+  None.
+*/
+/*=========================================================================*/
+long smem_list_count( smem_list_type *list )
+{
+  return list->count;
+}
+
diff --git a/platform/msm_shared/smem_ptable.c b/platform/msm_shared/smem_ptable.c
index fd27e10..b573cc8 100644
--- a/platform/msm_shared/smem_ptable.c
+++ b/platform/msm_shared/smem_ptable.c
@@ -2,7 +2,7 @@
  * Copyright (c) 2009, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2012,2015 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
@@ -35,6 +35,7 @@
 #include <platform/iomap.h>
 #include <lib/ptable.h>
 
+#include "board.h"
 #include "smem.h"
 
 
@@ -154,18 +155,34 @@
 
 static void smem_copy_ram_ptable(void *buf)
 {
-	struct smem_ram_ptable *table_v0;
-	struct smem_ram_ptable_v1 *table_v1;
+	struct smem_ram_ptable *table_v0 = NULL;
+	struct smem_ram_ptable_v1 *table_v1 = NULL;
+	struct smem_ram_ptable_v2 *table_v2 = NULL;
 	uint32_t pentry = 0;
 
 	ptable.hdr = *(struct smem_ram_ptable_hdr*)buf;
 
 	/* Perform member to member copy from smem_ram_ptable to wrapper struct ram_ptable */
-	if(ptable.hdr.version == SMEM_RAM_PTABLE_VERSION_1)
+	if(ptable.hdr.version == SMEM_RAM_PTABLE_VERSION_2)
+	{
+		table_v2 = (struct smem_ram_ptable_v2*)buf;
+
+		memcpy(&ptable, table_v2, sizeof(ram_partition_table));
+	}
+	else if(ptable.hdr.version == SMEM_RAM_PTABLE_VERSION_1)
 	{
 		table_v1 = (struct smem_ram_ptable_v1*)buf;
 
-		memcpy(&ptable, table_v1, sizeof(ram_partition_table));
+		for(pentry = 0; pentry < ((struct smem_ram_ptable_hdr*)buf)->len; pentry++)
+		{
+			ptable.parts[pentry].start          = table_v1->parts[pentry].start;
+			ptable.parts[pentry].size           = table_v1->parts[pentry].size;
+			ptable.parts[pentry].attr           = table_v1->parts[pentry].attr;
+			ptable.parts[pentry].category       = table_v1->parts[pentry].category;
+			ptable.parts[pentry].domain         = table_v1->parts[pentry].domain;
+			ptable.parts[pentry].type           = table_v1->parts[pentry].type;
+			ptable.parts[pentry].num_partitions = table_v1->parts[pentry].num_partitions;
+		}
 	}
 	else if(ptable.hdr.version == SMEM_RAM_PTABLE_VERSION_0)
 	{
@@ -214,7 +231,7 @@
 }
 
 /* RAM Partition table from SMEM */
-static uint32_t buffer[sizeof(struct smem_ram_ptable_v1)];
+static uint32_t buffer[sizeof(struct smem_ram_ptable_v2)];
 int smem_ram_ptable_init_v1()
 {
 	uint32_t i;
@@ -232,7 +249,9 @@
 	if(ret)
 		return 0;
 
-	if(version == SMEM_RAM_PTABLE_VERSION_1)
+	if(version == SMEM_RAM_PTABLE_VERSION_2)
+		smem_ram_ptable_size = sizeof(struct smem_ram_ptable_v2);
+	else if(version == SMEM_RAM_PTABLE_VERSION_1)
 		smem_ram_ptable_size = sizeof(struct smem_ram_ptable_v1);
 	else if(version == SMEM_RAM_PTABLE_VERSION_0)
 		smem_ram_ptable_size = sizeof(struct smem_ram_ptable);
@@ -276,3 +295,32 @@
 {
 	return ptable.hdr.version;
 }
+
+uint32_t get_ddr_start()
+{
+	uint32_t i;
+	ram_partition ptn_entry;
+	uint32_t len = 0;
+
+	ASSERT(smem_ram_ptable_init_v1());
+
+	len = smem_get_ram_ptable_len();
+
+	/* Determine the Start addr of the DDR RAM */
+	for(i = 0; i < len; i++)
+	{
+		smem_get_ram_ptable_entry(&ptn_entry, i);
+		if(ptn_entry.type == SYS_MEMORY)
+		{
+			if((ptn_entry.category == SDRAM) ||
+			   (ptn_entry.category == IMEM))
+			{
+				/* Check to ensure that start address is 1MB aligned */
+				ASSERT((ptn_entry.start & (MB-1)) == 0);
+				return ptn_entry.start;
+			}
+		}
+	}
+	ASSERT("DDR Start Mem Not found\n");
+	return 0;
+}
diff --git a/platform/msm_shared/spmi.c b/platform/msm_shared/spmi.c
index d82fbb9..7408a9d 100644
--- a/platform/msm_shared/spmi.c
+++ b/platform/msm_shared/spmi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2014-2015, 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
@@ -34,6 +34,7 @@
 #include <platform/irqs.h>
 #include <platform/interrupts.h>
 #include <malloc.h>
+#include <platform.h>
 
 #define PMIC_ARB_V2 0x20010000
 #define CHNL_IDX(sid, pid) ((sid << 8) | pid)
@@ -44,10 +45,11 @@
 static spmi_callback callback;
 static uint32_t pmic_arb_ver;
 static uint8_t *chnl_tbl;
+static uint32_t max_peripherals;
 
 static void spmi_lookup_chnl_number()
 {
-	int i;
+	uint32_t i;
 	uint8_t slave_id = 0;
 	uint8_t ppid_address = 0;
 	/* We need a max of sid (4 bits) + pid (8bits) of uint8_t's */
@@ -57,7 +59,7 @@
 	chnl_tbl = (uint8_t *) malloc(chnl_tbl_sz);
 	ASSERT(chnl_tbl);
 
-	for(i = 0; i < MAX_PERIPH ; i++)
+	for(i = 0; i < max_peripherals; i++)
 	{
 #if SPMI_CORE_V2
 		slave_id = (readl(PMIC_ARB_REG_CHLN(i)) & 0xf0000) >> 16;
@@ -74,6 +76,7 @@
 {
 	/* Read the version numver */
 	pmic_arb_ver = readl(PMIC_ARB_SPMI_HW_VERSION);
+	max_peripherals = platform_get_max_periph();
 
 	if (pmic_arb_ver < PMIC_ARB_V2)
 	{
diff --git a/platform/msm_shared/ucs.c b/platform/msm_shared/ucs.c
index f820734..a1ab6f3 100644
--- a/platform/msm_shared/ucs.c
+++ b/platform/msm_shared/ucs.c
@@ -31,8 +31,7 @@
 #include <endian.h>
 #include <string.h>
 #include <utp.h>
-
-static int ucs_do_request_sense(struct ufs_dev *dev);
+#include <rpmb.h>
 
 int ucs_do_scsi_cmd(struct ufs_dev *dev, struct scsi_req_build_type *req)
 {
@@ -394,6 +393,7 @@
         /* Flush cdb to memory. */
 	dsb();
 	arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN);
+	arch_invalidate_cache_range((addr_t) param, sizeof(struct unmap_param_list));
 
 	memset((void*)&req_upiu, 0 , sizeof(struct scsi_req_build_type));
 
@@ -463,7 +463,7 @@
 	dprintf(CRITICAL,"----end of buffer---\n");
 }
 
-static int ucs_do_request_sense(struct ufs_dev *dev)
+int ucs_do_request_sense(struct ufs_dev *dev, uint8_t lun)
 {
 	STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_sense_cdb));
 	struct scsi_req_build_type req_upiu;
@@ -487,7 +487,7 @@
 	req_upiu.data_buffer_addr  = (addr_t) buf;
 	req_upiu.data_len          = SCSI_SENSE_BUF_LEN;
 	req_upiu.flags			   = UPIU_FLAGS_READ;
-	req_upiu.lun			   = 0;
+	req_upiu.lun			   = lun;
 	req_upiu.dd			       = UTRD_TARGET_TO_SYSTEM;
 
 	if (ucs_do_scsi_cmd(dev, &req_upiu))
@@ -499,7 +499,9 @@
 	/* Flush buffer. */
 	arch_invalidate_cache_range((addr_t) buf, SCSI_INQUIRY_LEN);
 
+#if DEBUG_UFS
 	dump_sense_buffer(buf, SCSI_SENSE_BUF_LEN);
+#endif
 
 	return UFS_SUCCESS;
 }
diff --git a/platform/msm_shared/ufs.c b/platform/msm_shared/ufs.c
index 0bb7eb5..d3b7065 100644
--- a/platform/msm_shared/ufs.c
+++ b/platform/msm_shared/ufs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -89,10 +89,17 @@
 	qgic_change_interrupt_cfg(UFS_IRQ, INTERRUPT_LVL_N_TO_N);
 }
 
-static void ufs_rpmb_init(struct ufs_dev *dev)
+void ufs_rpmb_init(struct ufs_dev *dev)
 {
 	int ret = 0;
 
+	/*
+	 * Perform request sense on lun to clear
+	 * attention pending, other wise all the read/write
+	 * operations would fail with check condition error
+	 */
+	ucs_do_request_sense(dev, UFS_WLUN_RPMB);
+
 	// calculate the size of rpmb partition in sectors
 	ret = dme_read_unit_desc(dev, UFS_WLUN_RPMB);
 	if (ret != UFS_SUCCESS)
@@ -167,13 +174,8 @@
 	if(ret)
 	{
 		dprintf(CRITICAL, "UFS erase failed \n");
-		return ret;
 	}
-	ret = dme_set_fpurgeenable((struct ufs_dev *)dev);
-	if (ret)
-	{
-		dprintf(CRITICAL, "UFS purge operation failed after erase\n");
-	}
+
 	return ret;
 }
 
diff --git a/platform/msm_shared/usb30_dwc.c b/platform/msm_shared/usb30_dwc.c
index 6f419cd..5ae8801 100644
--- a/platform/msm_shared/usb30_dwc.c
+++ b/platform/msm_shared/usb30_dwc.c
@@ -1730,7 +1730,7 @@
 
 	ep->bytes_queued = 0;
 
-	if (ep->type == EP_TYPE_CONTROL)
+	if (ep->type == EP_TYPE_CONTROL || ep->type == EP_TYPE_INTERRUPT)
 	{
 		memset(trb, 0, sizeof(dwc_trb_t));
 
diff --git a/platform/msm_shared/usb30_dwc.h b/platform/msm_shared/usb30_dwc.h
index 1a69a61..14402e7 100644
--- a/platform/msm_shared/usb30_dwc.h
+++ b/platform/msm_shared/usb30_dwc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -379,7 +379,7 @@
 } dwc_notify_event_t;
 
 /* maximum number of endpoints supported. */
-#define DWC_MAX_NUM_OF_EP     4
+#define DWC_MAX_NUM_OF_EP     8
 
 /* length of setup packet */
 #define DWC_SETUP_PKT_LEN    8
diff --git a/platform/msm_shared/usb30_udc.c b/platform/msm_shared/usb30_udc.c
index 0e5e1b0..d9d18a2 100644
--- a/platform/msm_shared/usb30_udc.c
+++ b/platform/msm_shared/usb30_udc.c
@@ -559,7 +559,7 @@
 
 						ep->number        = ept->num;
 						ep->dir           = ept->in;
-						ep->type          = EP_TYPE_BULK; /* the only one supported */
+						ep->type          = ept->type;
 						ep->max_pkt_size  = ept->maxpkt;
 						ep->burst_size    = ept->maxburst;
 						ep->zlp           = 0;             /* TODO: zlp could be made part of ept */
@@ -848,6 +848,7 @@
 
 static struct udc_endpoint *_udc_endpoint_alloc(uint8_t num,
 												uint8_t in,
+												uint8_t type,
 												uint16_t max_pkt)
 {
 	struct udc_endpoint *ept;
@@ -858,6 +859,7 @@
 
 	ept->maxpkt     = max_pkt;
 	ept->num        = num;
+	ept->type       = type;
 	ept->in         = !!in;
 	ept->maxburst   = 4;      /* no performance improvement is seen beyond burst size of 4 */
 	ept->trb_count  = 66;     /* each trb can transfer (16MB - 1). 65 for 1GB transfer + 1 for roundup/zero length pkt. */
@@ -881,8 +883,16 @@
 
 	if (type == UDC_TYPE_BULK_IN) {
 		in = 1;
+		type = EP_TYPE_BULK;
 	} else if (type == UDC_TYPE_BULK_OUT) {
 		in = 0;
+		type = EP_TYPE_BULK;
+	} else if (type == UDC_TYPE_INTR_IN) {
+		in = 1;
+		type = EP_TYPE_INTERRUPT;
+	} else if (type == UDC_TYPE_INTR_OUT){
+		in = 0;
+		type = EP_TYPE_INTERRUPT;
 	} else {
 		return 0;
 	}
@@ -891,7 +901,7 @@
 		uint32_t bit = in ? EPT_TX(n) : EPT_RX(n);
 		if (udc->ept_alloc_table & bit)
 			continue;
-		ept = _udc_endpoint_alloc(n, in, maxpkt);
+		ept = _udc_endpoint_alloc(n, in, type, maxpkt);
 		if (ept)
 			udc->ept_alloc_table |= bit;
 		return ept;
diff --git a/platform/msm_shared/usb30_udc.h b/platform/msm_shared/usb30_udc.h
index 02e86fa..97ef7e8 100644
--- a/platform/msm_shared/usb30_udc.h
+++ b/platform/msm_shared/usb30_udc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013, 2015 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
@@ -84,6 +84,7 @@
 struct udc_endpoint {
 	struct udc_endpoint *next;
 	uint8_t              num;
+	uint8_t              type;
 	uint8_t              in;
 	uint16_t             maxpkt;
 	uint32_t             maxburst;  /* max pkts that this ep can transfer before waiting for ack. */
diff --git a/project/msm8909.mk b/project/msm8909.mk
index afc40f6..59f63f7 100644
--- a/project/msm8909.mk
+++ b/project/msm8909.mk
@@ -20,7 +20,7 @@
 
 #DEFINES += WITH_DEBUG_DCC=1
 DEFINES += WITH_DEBUG_LOG_BUF=1
-DEFINES += WITH_DEBUG_UART=0
+DEFINES += WITH_DEBUG_UART=1
 #DEFINES += WITH_DEBUG_FBCON=1
 DEFINES += DEVICE_TREE=1
 #DEFINES += MMC_BOOT_BAM=1
@@ -65,3 +65,9 @@
 ifeq ($(ENABLE_BOOT_CONFIG_SUPPORT),1)
 DEFINES += BOOT_CONFIG_SUPPORT=1
 endif
+
+#SCM call before entering DLOAD mode
+DEFINES += PLATFORM_USE_SCM_DLOAD=1
+
+#Enable the external reboot functions
+ENABLE_REBOOT_MODULE := 1
diff --git a/project/msm8916.mk b/project/msm8916.mk
index 5f51f80..5322f72 100644
--- a/project/msm8916.mk
+++ b/project/msm8916.mk
@@ -51,3 +51,9 @@
 
 #enable user force reset feature
 DEFINES += USER_FORCE_RESET_SUPPORT=1
+
+#SCM call before entering DLOAD mode
+DEFINES += PLATFORM_USE_SCM_DLOAD=1
+
+#Enable the external reboot functions
+ENABLE_REBOOT_MODULE := 1
\ No newline at end of file
diff --git a/project/msm8952.mk b/project/msm8952.mk
new file mode 100644
index 0000000..1a27c22
--- /dev/null
+++ b/project/msm8952.mk
@@ -0,0 +1,60 @@
+# top level project rules for the MSM8952 project
+#
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+TARGET := msm8952
+
+MODULES += app/aboot
+
+ifeq ($(TARGET_BUILD_VARIANT),user)
+DEBUG := 0
+else
+DEBUG := 1
+endif
+
+EMMC_BOOT := 1
+
+#ENABLE_SMD_SUPPORT := 1
+#ENABLE_PWM_SUPPORT := true
+
+#DEFINES += WITH_DEBUG_DCC=1
+DEFINES += WITH_DEBUG_LOG_BUF=1
+DEFINES += WITH_DEBUG_UART=1
+#DEFINES += WITH_DEBUG_FBCON=1
+DEFINES += DEVICE_TREE=1
+#DEFINES += MMC_BOOT_BAM=1
+DEFINES += CRYPTO_BAM=1
+DEFINES += SPMI_CORE_V2=1
+DEFINES += ABOOT_IGNORE_BOOT_HEADER_ADDRS=1
+
+DEFINES += BAM_V170=1
+
+#Enable the feature of long press power on
+#DEFINES += LONG_PRESS_POWER_ON=1
+
+#Disable thumb mode
+ENABLE_THUMB := false
+
+ENABLE_SDHCI_SUPPORT := 1
+
+ifeq ($(ENABLE_SDHCI_SUPPORT),1)
+DEFINES += MMC_SDHCI_SUPPORT=1
+endif
+
+#enable power on vibrator feature
+#ENABLE_PON_VIB_SUPPORT := true
+
+ifeq ($(EMMC_BOOT),1)
+DEFINES += _EMMC_BOOT=1
+endif
+
+ifeq ($(ENABLE_PON_VIB_SUPPORT),true)
+DEFINES += PON_VIB_SUPPORT=1
+endif
+
+ifeq ($(ENABLE_SMD_SUPPORT),1)
+DEFINES += SMD_SUPPORT=1
+endif
+
+#SCM call before entering DLOAD mode
+DEFINES += PLATFORM_USE_SCM_DLOAD=1
diff --git a/project/thulium.mk b/project/msm8996.mk
similarity index 83%
rename from project/thulium.mk
rename to project/msm8996.mk
index 05e764f..dfe74cf 100644
--- a/project/thulium.mk
+++ b/project/msm8996.mk
@@ -1,8 +1,8 @@
-# top level project rules for the thulium project
+# top level project rules for the msm8996 project
 #
 LOCAL_DIR := $(GET_LOCAL_DIR)
 
-TARGET := thulium
+TARGET := msm8996
 
 MODULES += app/aboot
 
@@ -19,6 +19,7 @@
 ENABLE_USB30_SUPPORT := 1
 ENABLE_QGIC3 := 1
 ENABLE_PARTIAL_GOODS_SUPPORT := 1
+ENABLE_RPMB_SUPPORT := 1
 
 DEFINES +=VIRTIO=1
 
@@ -27,6 +28,7 @@
 #DEFINES += WITH_DEBUG_FBCON=1
 DEFINES += DEVICE_TREE=1
 DEFINES += SPMI_CORE_V2=1
+DEFINES += BAM_V170=1
 
 DEFINES += ABOOT_IGNORE_BOOT_HEADER_ADDRS=1
 
@@ -36,6 +38,7 @@
 DEFINES += ABOOT_FORCE_KERNEL64_ADDR=0x80080000
 DEFINES += USB_RESET_FROM_CLK=1
 DEFINES += USE_BOOTDEV_CMDLINE=1
+DEFINES += USE_RPMB_FOR_DEVINFO=1
 
 #Disable thumb mode
 ENABLE_THUMB := false
@@ -61,3 +64,6 @@
 endif
 
 CFLAGS += -Werror
+
+#SCM call before entering DLOAD mode
+DEFINES += PLATFORM_USE_SCM_DLOAD=1
diff --git a/scripts/buildall b/scripts/buildall
index c355387..38db25e 100755
--- a/scripts/buildall
+++ b/scripts/buildall
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-PROJECTS="msm8226 msm8974 apq8084 msm8994 mdm9630 mdm9640 msm8610 msm8916 thulium"
+PROJECTS="msm8226 msm8974 apq8084 msm8994 mdm9630 mdm9640 msm8610 msm8916 msm8996"
 FAILED=""
 
 for p in $PROJECTS; do
diff --git a/target/fsm9010/init.c b/target/fsm9010/init.c
index 7e47d47..e5c50bb 100644
--- a/target/fsm9010/init.c
+++ b/target/fsm9010/init.c
@@ -288,7 +288,10 @@
 	};
 
 	switch (platform) {
+	case FSM9008:
 	case FSM9010:
+	case FSM9016:
+	case FSM9055:
 		board->baseband = BASEBAND_MSM;
 		break;
 	default:
diff --git a/target/fsm9010/meminfo.c b/target/fsm9010/meminfo.c
index fa0f96a..3c1fc98 100644
--- a/target/fsm9010/meminfo.c
+++ b/target/fsm9010/meminfo.c
@@ -90,6 +90,6 @@
 
 unsigned target_get_max_flash_size(void)
 {
-	return (86 * 1024 * 1024);
+	return (222 * 1024 * 1024);
 }
 #endif /* DEVICE_TREE */
diff --git a/target/fsm9010/rules.mk b/target/fsm9010/rules.mk
index 17a1b1d..8e7fd48 100644
--- a/target/fsm9010/rules.mk
+++ b/target/fsm9010/rules.mk
@@ -12,7 +12,7 @@
 TAGS_ADDR        := BASE_ADDR+0x01e00000
 KERNEL_ADDR      := BASE_ADDR+0x00008000
 RAMDISK_ADDR     := BASE_ADDR+0x02000000
-SCRATCH_ADDR     := 0x0e000000
+SCRATCH_ADDR     := 0x32200000
 
 MODULES += \
 	dev/keys \
diff --git a/target/init.c b/target/init.c
index ae1e311..9191572 100644
--- a/target/init.c
+++ b/target/init.c
@@ -221,3 +221,13 @@
 {
 	return DDR_CONFIG_VAL;
 }
+
+/* Return Build variant */
+__WEAK bool target_build_variant_user()
+{
+#if USER_BUILD_VARIANT
+	return true;
+#else
+	return false;
+#endif
+}
diff --git a/target/mdm9640/init.c b/target/mdm9640/init.c
index 442d117..09dedef 100644
--- a/target/mdm9640/init.c
+++ b/target/mdm9640/init.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 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
@@ -83,7 +83,7 @@
 
 #define LAST_NAND_PTN_LEN_PATTERN                     0xFFFFFFFF
 
-#define EXT4_CMDLINE  " rootfstype=ext4 root=/dev/mmcblk0p"
+#define EXT4_CMDLINE  " rootwait rootfstype=ext4 root=/dev/mmcblk0p"
 #define UBI_CMDLINE " rootfstype=ubifs rootflags=bulk_read ubi.fm_autoconvert=1"
 
 struct qpic_nand_init_config config;
@@ -143,6 +143,9 @@
 			dprintf(CRITICAL, "Error reading the partition table info\n");
 			ASSERT(0);
 		}
+		/* Below setting is to enable EBI2 function selection in TLMM so
+		   that GPIOs can be used for display */
+		writel((readl(TLMM_EBI2_EMMC_GPIO_CFG) | EBI2_BOOT_SELECT), TLMM_EBI2_EMMC_GPIO_CFG);
 	} else {
 		config.pipes.read_pipe = DATA_PRODUCER_PIPE;
 		config.pipes.write_pipe = DATA_CONSUMER_PIPE;
@@ -179,7 +182,10 @@
 	 * This call should be based on the pmic version
 	 * when PM8019 v2 is available.
 	 */
-	pm8x41_v2_reset_configure(PON_PSHOLD_WARM_RESET);
+	if (reboot_reason)
+		pm8x41_v2_reset_configure(PON_PSHOLD_WARM_RESET);
+	else
+		pm8x41_v2_reset_configure(PON_PSHOLD_HARD_RESET);
 
 	/* Drop PS_HOLD for MSM */
 	writel(0x00, MPM2_MPM_PS_HOLD);
diff --git a/target/msm8226/meminfo.c b/target/msm8226/meminfo.c
index 5de0ef0..5882a2f 100644
--- a/target/msm8226/meminfo.c
+++ b/target/msm8226/meminfo.c
@@ -78,24 +78,10 @@
 
 void *target_get_scratch_address(void)
 {
-	void *scratch_addr = 0;
-
-	if(target_is_cdp_qvga())
-		scratch_addr = (void *)SCRATCH_ADDR_128MAP;
-	else
-		scratch_addr = (void *)SCRATCH_ADDR_512MAP;
-
-	return scratch_addr;
+	return (void *)SCRATCH_ADDR;
 }
 
 unsigned target_get_max_flash_size(void)
 {
-	uint32_t max_flash_size = 0;
-
-	if(target_is_cdp_qvga())
-		max_flash_size = SCRATCH_SIZE_128MAP;
-	else
-		max_flash_size = SCRATCH_SIZE_512MAP;
-
-	return max_flash_size;
+	return SCRATCH_SIZE;
 }
diff --git a/target/msm8226/oem_panel.c b/target/msm8226/oem_panel.c
index 354c08e..442fa29 100755
--- a/target/msm8226/oem_panel.c
+++ b/target/msm8226/oem_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -50,6 +50,7 @@
 #include "include/panel_ssd2080m_720p_video.h"
 #include "include/panel_jdi_1080p_video.h"
 #include "include/panel_nt35590_qvga_cmd.h"
+#include "include/panel_auo_qvga_cmd.h"
 
 #define DISPLAY_MAX_PANEL_DETECTION 2
 
@@ -69,6 +70,7 @@
 SSD2080M_720P_VIDEO_PANEL,
 JDI_1080P_VIDEO_PANEL,
 NT35590_QVGA_CMD_PANEL,
+AUO_QVGA_CMD_PANEL,
 UNKNOWN_PANEL
 };
 
@@ -86,6 +88,7 @@
 	{"ssd2080m_720p_video", SSD2080M_720P_VIDEO_PANEL},
 	{"jdi_1080p_video", JDI_1080P_VIDEO_PANEL},
 	{"nt35590_qvga_cmd", NT35590_QVGA_CMD_PANEL},
+	{"auo_qvga_cmd", AUO_QVGA_CMD_PANEL},
 };
 
 static uint32_t panel_id;
@@ -355,6 +358,29 @@
 		memcpy(phy_db->timing,
 				nt35590_qvga_cmd_timings, TIMING_SIZE);
 		break;
+	case AUO_QVGA_CMD_PANEL:
+		panelstruct->paneldata    = &auo_qvga_cmd_panel_data;
+		panelstruct->panelres     = &auo_qvga_cmd_panel_res;
+		panelstruct->color        = &auo_qvga_cmd_color;
+		panelstruct->videopanel   = &auo_qvga_cmd_video_panel;
+		panelstruct->commandpanel = &auo_qvga_cmd_command_panel;
+		panelstruct->state        = &auo_qvga_cmd_state;
+		panelstruct->laneconfig   = &auo_qvga_cmd_lane_config;
+		panelstruct->paneltiminginfo = &auo_qvga_cmd_timing_info;
+		panelstruct->panelresetseq
+					= &auo_qvga_cmd_panel_reset_seq;
+		panelstruct->backlightinfo = &auo_qvga_cmd_backlight;
+		pinfo->mipi.panel_on_cmds
+					= auo_qvga_cmd_on_command;
+		pinfo->mipi.num_of_panel_on_cmds
+					= auo_QVGA_CMD_ON_COMMAND;
+		pinfo->mipi.panel_off_cmds
+					= auo_qvga_cmd_off_command;
+		pinfo->mipi.num_of_panel_off_cmds
+					= auo_QVGA_CMD_OFF_COMMAND;
+		memcpy(phy_db->timing,
+				auo_qvga_cmd_timings, TIMING_SIZE);
+		break;
         case UNKNOWN_PANEL:
                 memset(panelstruct, 0, sizeof(struct panel_struct));
                 memset(pinfo->mipi.panel_on_cmds, 0,
diff --git a/target/msm8226/rules.mk b/target/msm8226/rules.mk
index 91119ea..3be3c36 100755
--- a/target/msm8226/rules.mk
+++ b/target/msm8226/rules.mk
@@ -14,10 +14,7 @@
 KERNEL_ADDR      := BASE_ADDR+0x00008000
 RAMDISK_ADDR     := BASE_ADDR+0x01000000
 SCRATCH_ADDR     := 0x10000000
-SCRATCH_ADDR_128MAP     := 0x04200000
-SCRATCH_ADDR_512MAP     := 0x10000000
-SCRATCH_SIZE_128MAP     := 0x03D00000
-SCRATCH_SIZE_512MAP     := 0x20000000
+SCRATCH_SIZE     := 0x20000000
 
 DEFINES += DISPLAY_SPLASH_SCREEN=1
 DEFINES += DISPLAY_TYPE_MIPI=1
@@ -39,10 +36,7 @@
 	KERNEL_ADDR=$(KERNEL_ADDR) \
 	RAMDISK_ADDR=$(RAMDISK_ADDR) \
 	SCRATCH_ADDR=$(SCRATCH_ADDR) \
-	SCRATCH_ADDR_128MAP=$(SCRATCH_ADDR_128MAP) \
-	SCRATCH_ADDR_512MAP=$(SCRATCH_ADDR_512MAP) \
-	SCRATCH_SIZE_128MAP=$(SCRATCH_SIZE_128MAP) \
-	SCRATCH_SIZE_512MAP=$(SCRATCH_SIZE_512MAP)
+	SCRATCH_SIZE=$(SCRATCH_SIZE)
 
 
 OBJS += \
diff --git a/target/msm8226/target_display.c b/target/msm8226/target_display.c
index 4ac9b37..77ca16e 100755
--- a/target/msm8226/target_display.c
+++ b/target/msm8226/target_display.c
@@ -262,6 +262,8 @@
 							PWM_BL_LPG_CHAN_ID,
 							enable);
 			break;
+		case BL_DCS:
+			break;
 		default:
 			dprintf(CRITICAL, "backlight type:%d not supported\n",
 							bl->bl_interface_type);
diff --git a/target/msm8909/init.c b/target/msm8909/init.c
index 96232fe..ec1a568 100644
--- a/target/msm8909/init.c
+++ b/target/msm8909/init.c
@@ -66,8 +66,6 @@
 #define VIBRATE_TIME    250
 #endif
 
-#define FASTBOOT_MODE           0x77665500
-
 #define CE1_INSTANCE            1
 #define CE_EE                   1
 #define CE_FIFO_SIZE            64
@@ -151,8 +149,15 @@
 void target_early_init(void)
 {
 #if WITH_DEBUG_UART
-	uart_dm_init(1, 0, BLSP1_UART0_BASE);
+	/* Do not intilaise UART in case the h/w
+	* is RCM.
+	*/
+	if( board_hardware_id()!= HW_PLATFORM_RCM )
+		uart_dm_init(1, 0, BLSP1_UART0_BASE);
+	else
+		return;
 #endif
+
 }
 
 int target_is_emmc_boot(void)
@@ -367,41 +372,6 @@
 	return LINUX_MACHTYPE_UNKNOWN;
 }
 
-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;
-}
-
-static int scm_dload_mode(int mode)
-{
-	int ret = 0;
-	uint32_t dload_type;
-
-	dprintf(SPEW, "DLOAD mode: %d\n", mode);
-	if (mode == NORMAL_DLOAD)
-		dload_type = SCM_DLOAD_MODE;
-	else if(mode == EMERGENCY_DLOAD)
-		dload_type = SCM_EDLOAD_MODE;
-	else
-		dload_type = 0;
-
-	ret = scm_call_atomic2(SCM_SVC_BOOT, SCM_DLOAD_CMD, dload_type, 0);
-	if (ret)
-		dprintf(CRITICAL, "Failed to write to boot misc: %d\n", ret);
-
-	ret = scm_call_atomic2(SCM_SVC_BOOT, WDOG_DEBUG_DISABLE, 1, 0);
-	if (ret)
-		dprintf(CRITICAL, "Failed to disable the wdog debug \n");
-
-	return ret;
-}
-
 /* Configure PMIC and Drop PS_HOLD for shutdown */
 void shutdown_device()
 {
@@ -417,42 +387,6 @@
 
 }
 
-void reboot_device(unsigned reboot_reason)
-{
-	uint8_t reset_type = 0;
-	uint32_t ret = 0;
-
-	/* Need to clear the SW_RESET_ENTRY register and
-	* write to the BOOT_MISC_REG for known reset cases
-	*/
-	if(reboot_reason != DLOAD)
-		scm_dload_mode(NORMAL_MODE);
-
-	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 == DLOAD))
-		reset_type = PON_PSHOLD_WARM_RESET;
-	else
-		reset_type = PON_PSHOLD_HARD_RESET;
-
-	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");
-}
-
 /* Detect the target type */
 void target_detect(struct board_data *board)
 {
diff --git a/target/msm8909/oem_panel.c b/target/msm8909/oem_panel.c
index 50aad97..f7b5717 100644
--- a/target/msm8909/oem_panel.c
+++ b/target/msm8909/oem_panel.c
@@ -205,10 +205,14 @@
 		panelstruct->panelresetseq
 					= &truly_wvga_cmd_reset_seq;
 		panelstruct->backlightinfo = &truly_wvga_cmd_backlight;
-		pinfo->mipi.panel_cmds
+		pinfo->mipi.panel_on_cmds
 					= truly_wvga_cmd_on_command;
-		pinfo->mipi.num_of_panel_cmds
+		pinfo->mipi.num_of_panel_on_cmds
 					= TRULY_WVGA_CMD_ON_COMMAND;
+		pinfo->mipi.panel_off_cmds
+					= truly_wvga_cmd_off_command;
+		pinfo->mipi.num_of_panel_off_cmds
+					= TRULY_WVGA_CMD_OFF_COMMAND;
 		memcpy(phy_db->timing,
 				truly_wvga_cmd_timings, TIMING_SIZE);
 		break;
@@ -275,10 +279,14 @@
 		panelstruct->panelresetseq
 					 = &hx8394d_qhd_video_panel_reset_seq;
 		panelstruct->backlightinfo = &hx8394d_qhd_video_backlight;
-		pinfo->mipi.panel_cmds
+		pinfo->mipi.panel_on_cmds
 					= hx8394d_qhd_video_on_command;
-		pinfo->mipi.num_of_panel_cmds
+		pinfo->mipi.num_of_panel_on_cmds
 					= HX8394D_QHD_VIDEO_ON_COMMAND;
+		pinfo->mipi.panel_off_cmds
+					= hx8394d_qhd_video_off_command;
+		pinfo->mipi.num_of_panel_off_cmds
+					= HX8394D_QHD_VIDEO_OFF_COMMAND;
 		memcpy(phy_db->timing,
 				hx8394d_qhd_video_timings, TIMING_SIZE);
 		pinfo->mipi.signature = HX8394D_QHD_VIDEO_SIGNATURE;
diff --git a/target/msm8909/rules.mk b/target/msm8909/rules.mk
index 5753859..b3e2059 100644
--- a/target/msm8909/rules.mk
+++ b/target/msm8909/rules.mk
@@ -14,6 +14,7 @@
 DEFINES += DISPLAY_SPLASH_SCREEN=1
 DEFINES += DISPLAY_TYPE_MIPI=1
 DEFINES += DISPLAY_TYPE_DSI6G=1
+DEFINES += NO_ALARM_DISPLAY=0
 
 MODULES += \
 	dev/keys \
diff --git a/target/msm8916/init.c b/target/msm8916/init.c
index f1aff17..f0f6bba 100644
--- a/target/msm8916/init.c
+++ b/target/msm8916/init.c
@@ -65,9 +65,6 @@
 #define VIBRATE_TIME    250
 #endif
 
-#define FASTBOOT_MODE           0x77665500
-#define PON_SOFT_RB_SPARE       0x88F
-
 #define CE1_INSTANCE            1
 #define CE_EE                   1
 #define CE_FIFO_SIZE            64
@@ -169,23 +166,6 @@
 		keys_post_event(KEY_VOLUMEUP, 1);
 }
 
-#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
-
 void target_init(void)
 {
 	uint32_t base_addr;
@@ -231,55 +211,6 @@
 	return LINUX_MACHTYPE_UNKNOWN;
 }
 
-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;
-}
-
-static int scm_dload_mode(int mode)
-{
-	int ret = 0;
-	uint32_t dload_type;
-
-	dprintf(SPEW, "DLOAD mode: %d\n", mode);
-	if (mode == NORMAL_DLOAD)
-		dload_type = SCM_DLOAD_MODE;
-	else if(mode == EMERGENCY_DLOAD)
-		dload_type = SCM_EDLOAD_MODE;
-	else
-		dload_type = 0;
-
-	ret = scm_call_atomic2(SCM_SVC_BOOT, SCM_DLOAD_CMD, dload_type, 0);
-	if (ret)
-		dprintf(CRITICAL, "Failed to write to boot misc: %d\n", ret);
-
-	ret = scm_call_atomic2(SCM_SVC_BOOT, WDOG_DEBUG_DISABLE, 1, 0);
-	if (ret)
-		dprintf(CRITICAL, "Failed to disable the wdog debug \n");
-
-	return ret;
-}
 /* Configure PMIC and Drop PS_HOLD for shutdown */
 void shutdown_device()
 {
@@ -298,41 +229,6 @@
 	ASSERT(0);
 }
 
-void reboot_device(unsigned reboot_reason)
-{
-	uint8_t reset_type = 0;
-	uint32_t ret = 0;
-
-	/* Need to clear the SW_RESET_ENTRY register and
-	 * write to the BOOT_MISC_REG for known reset cases
-	 */
-	if(reboot_reason != DLOAD)
-		scm_dload_mode(NORMAL_MODE);
-
-	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 == DLOAD))
-		reset_type = PON_PSHOLD_WARM_RESET;
-	else
-		reset_type = PON_PSHOLD_HARD_RESET;
-
-	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");
-}
-
 /* Detect the target type */
 void target_detect(struct board_data *board)
 {
@@ -391,7 +287,7 @@
 	{
 		{ SDC1_CLK_HDRV_CTL_OFF,  TLMM_CUR_VAL_16MA, TLMM_HDRV_MASK, 0},
 		{ SDC1_CMD_HDRV_CTL_OFF,  TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK, 0},
-		{ SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_6MA, TLMM_HDRV_MASK , 0},
+		{ SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK , 0},
 	};
 
 	/* Pull configs for sdc pins */
@@ -481,7 +377,7 @@
 	if (is_cold_boot &&
 			(!(pon_reason & HARD_RST)) &&
 			(!(pon_reason & KPDPWR_N)) &&
-			((pon_reason & USB_CHG) || (pon_reason & DC_CHG)))
+			((pon_reason & USB_CHG) || (pon_reason & DC_CHG) || (pon_reason & CBLPWR_N)))
 		return 1;
 	else
 		return 0;
diff --git a/target/msm8916/oem_panel.c b/target/msm8916/oem_panel.c
index ae2725d..4c51fcb 100644
--- a/target/msm8916/oem_panel.c
+++ b/target/msm8916/oem_panel.c
@@ -64,6 +64,8 @@
 #define NT35590_720P_CMD_PANEL_ON_DELAY 40
 #define SAMSUNG_WXGA_VIDEO_PANEL_ON_DELAY 100
 
+#define BOARD_SOC_VERSION3	0x30000
+
 /*---------------------------------------------------------------------------*/
 /* static panel selection variable                                           */
 /*---------------------------------------------------------------------------*/
@@ -634,6 +636,9 @@
 				panel_id = JDI_1080P_VIDEO_PANEL;
 				break;
 			case 1:
+				panel_id = HX8394D_720P_VIDEO_PANEL;
+				break;
+			case 2:
 				panel_id = NT35590_720P_VIDEO_PANEL;
 				break;
 			default:
@@ -708,7 +713,9 @@
 	 * Update all data structures after 'panel_init' label. Only panel
 	 * selection is supposed to happen before that.
 	 */
-	if (platform_is_msm8939() || platform_is_msm8929() || (hw_id == HW_PLATFORM_QRD)) {
+	if ((platform_is_msm8939() && (board_soc_version() !=
+		BOARD_SOC_VERSION3)) || platform_is_msm8929() ||
+		(hw_id == HW_PLATFORM_QRD)) {
 		phy_db->regulator_mode = DSI_PHY_REGULATOR_LDO_MODE;
 		memcpy(panel_regulator_settings,
 				ldo_regulator_settings, REGULATOR_SIZE);
diff --git a/target/msm8916/target_display.c b/target/msm8916/target_display.c
index 0ddaec1..43a2903 100644
--- a/target/msm8916/target_display.c
+++ b/target/msm8916/target_display.c
@@ -62,33 +62,124 @@
 	mdelay(1);
 }
 
-static uint32_t dsi_pll_enable_seq_8916(uint32_t pll_base)
+static void dsi_pll_toggle_lock_detect_8916(uint32_t pll_base)
 {
-	uint32_t pll_locked = 0;
+	writel(0x04, pll_base + 0x0064); /* LKDetect CFG2 */
+	udelay(1);
+	writel(0x05, pll_base + 0x0064); /* LKDetect CFG2 */
+	udelay(512);
+}
 
+static void dsi_pll_sw_reset_8916(uint32_t pll_base)
+{
 	writel(0x01, pll_base + 0x0068); /* PLL TEST CFG */
 	udelay(1);
 	writel(0x00, pll_base + 0x0068); /* PLL TEST CFG */
+}
+
+static uint32_t gf_1_dsi_pll_enable_sequence_8916(uint32_t pll_base)
+{
+	uint32_t rc;
+
+	dsi_pll_sw_reset_8916(pll_base);
 
 	/*
 	 * Add hardware recommended delays between register writes for
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
-	writel(0x34, pll_base + 0x0070); /* CAL CFG1*/
-	udelay(1);
+	writel(0x14, pll_base + 0x0070); /* CAL CFG1*/
 	writel(0x01, pll_base + 0x0020); /* GLB CFG */
-	udelay(1);
 	writel(0x05, pll_base + 0x0020); /* GLB CFG */
-	udelay(1);
+	udelay(3);
 	writel(0x0f, pll_base + 0x0020); /* GLB CFG */
-	udelay(1);
+	udelay(500);
 
-	writel(0x04, pll_base + 0x0064); /* LKDetect CFG2 */
-	udelay(1);
-	writel(0x05, pll_base + 0x0064); /* LKDetect CFG2 */
-	udelay(512);
-	pll_locked = readl(pll_base + 0x00c0) & 0x01;
+	dsi_pll_toggle_lock_detect_8916(pll_base);
+	rc = readl(pll_base + 0x00c0) & 0x01;
+
+	return rc;
+}
+
+static uint32_t gf_2_dsi_pll_enable_sequence_8916(uint32_t pll_base)
+{
+	uint32_t rc;
+
+	dsi_pll_sw_reset_8916(pll_base);
+
+	/*
+	 * Add hardware recommended delays between register writes for
+	 * the updates to take effect. These delays are necessary for the
+	 * PLL to successfully lock
+	 */
+	writel(0x04, pll_base + 0x0070); /* CAL CFG1*/
+	writel(0x01, pll_base + 0x0020); /* GLB CFG */
+	writel(0x05, pll_base + 0x0020); /* GLB CFG */
+	udelay(3);
+	writel(0x0f, pll_base + 0x0020); /* GLB CFG */
+	udelay(500);
+
+	dsi_pll_toggle_lock_detect_8916(pll_base);
+	rc = readl(pll_base + 0x00c0) & 0x01;
+
+	return rc;
+}
+
+static uint32_t tsmc_dsi_pll_enable_sequence_8916(uint32_t pll_base)
+{
+	uint32_t rc;
+
+	dsi_pll_sw_reset_8916(pll_base);
+	/*
+	 * Add hardware recommended delays between register writes for
+	 * the updates to take effect. These delays are necessary for the
+	 * PLL to successfully lock
+	 */
+
+	writel(0x34, pll_base + 0x0070); /* CAL CFG1*/
+	writel(0x01, pll_base + 0x0020); /* GLB CFG */
+	writel(0x05, pll_base + 0x0020); /* GLB CFG */
+	writel(0x0f, pll_base + 0x0020); /* GLB CFG */
+	udelay(500);
+
+	dsi_pll_toggle_lock_detect_8916(pll_base);
+	rc = readl(pll_base + 0x00c0) & 0x01;
+
+	return rc;
+}
+
+
+static uint32_t dsi_pll_enable_seq_8916(uint32_t pll_base)
+{
+	uint32_t pll_locked = 0;
+	uint32_t counter = 0;
+
+	do {
+		pll_locked = tsmc_dsi_pll_enable_sequence_8916(pll_base);
+
+		dprintf(SPEW, "TSMC pll locked status is %d\n", pll_locked);
+		++counter;
+	} while (!pll_locked && (counter < 3));
+
+	if(!pll_locked) {
+		counter = 0;
+		do {
+			pll_locked = gf_1_dsi_pll_enable_sequence_8916(pll_base);
+
+			dprintf(SPEW, "GF P1 pll locked status is %d\n", pll_locked);
+			++counter;
+		} while (!pll_locked && (counter < 3));
+	}
+
+	if(!pll_locked) {
+		counter = 0;
+		do {
+			pll_locked = gf_2_dsi_pll_enable_sequence_8916(pll_base);
+
+			dprintf(SPEW, "GF P2 pll locked status is %d\n", pll_locked);
+			++counter;
+		} while (!pll_locked && (counter < 3));
+	}
 
 	return pll_locked;
 }
diff --git a/target/msm8952/init.c b/target/msm8952/init.c
new file mode 100644
index 0000000..445e132
--- /dev/null
+++ b/target/msm8952/init.c
@@ -0,0 +1,505 @@
+/* Copyright (c) 2015, 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 <debug.h>
+#include <platform/iomap.h>
+#include <reg.h>
+#include <target.h>
+#include <platform.h>
+#include <uart_dm.h>
+#include <mmc.h>
+#include <platform/gpio.h>
+#include <dev/keys.h>
+#include <spmi_v2.h>
+#include <pm8x41.h>
+#include <board.h>
+#include <baseband.h>
+#include <hsusb.h>
+#include <scm.h>
+#include <platform/gpio.h>
+#include <platform/gpio.h>
+#include <platform/irqs.h>
+#include <platform/clock.h>
+#include <crypto5_wrapper.h>
+#include <partition_parser.h>
+#include <stdlib.h>
+
+#if LONG_PRESS_POWER_ON
+#include <shutdown_detect.h>
+#endif
+
+#define PMIC_ARB_CHANNEL_NUM    0
+#define PMIC_ARB_OWNER_ID       0
+#define TLMM_VOL_UP_BTN_GPIO    85
+
+#define FASTBOOT_MODE           0x77665500
+#define PON_SOFT_RB_SPARE       0x88F
+
+#define CE1_INSTANCE            1
+#define CE_EE                   1
+#define CE_FIFO_SIZE            64
+#define CE_READ_PIPE            3
+#define CE_WRITE_PIPE           2
+#define CE_READ_PIPE_LOCK_GRP   0
+#define CE_WRITE_PIPE_LOCK_GRP  0
+#define CE_ARRAY_SIZE           20
+
+struct mmc_device *dev;
+
+static uint32_t mmc_pwrctl_base[] =
+	{ MSM_SDC1_BASE, MSM_SDC2_BASE };
+
+static uint32_t mmc_sdhci_base[] =
+	{ MSM_SDC1_SDHCI_BASE, MSM_SDC2_SDHCI_BASE };
+
+static uint32_t  mmc_sdc_pwrctl_irq[] =
+	{ SDCC1_PWRCTL_IRQ, SDCC2_PWRCTL_IRQ };
+
+void target_early_init(void)
+{
+#if WITH_DEBUG_UART
+	uart_dm_init(2, 0, BLSP1_UART1_BASE);
+#endif
+}
+
+static void set_sdc_power_ctrl()
+{
+	/* Drive strength configs for sdc pins */
+	struct tlmm_cfgs sdc1_hdrv_cfg[] =
+	{
+		{ SDC1_CLK_HDRV_CTL_OFF,  TLMM_CUR_VAL_16MA, TLMM_HDRV_MASK, 0},
+		{ SDC1_CMD_HDRV_CTL_OFF,  TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK, 0},
+		{ SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK , 0},
+	};
+
+	/* Pull configs for sdc pins */
+	struct tlmm_cfgs sdc1_pull_cfg[] =
+	{
+		{ SDC1_CLK_PULL_CTL_OFF,  TLMM_NO_PULL, TLMM_PULL_MASK, 0},
+		{ SDC1_CMD_PULL_CTL_OFF,  TLMM_PULL_UP, TLMM_PULL_MASK, 0},
+		{ SDC1_DATA_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK, 0},
+	};
+
+	/* Set the drive strength & pull control values */
+	tlmm_set_hdrive_ctrl(sdc1_hdrv_cfg, ARRAY_SIZE(sdc1_hdrv_cfg));
+	tlmm_set_pull_ctrl(sdc1_pull_cfg, ARRAY_SIZE(sdc1_pull_cfg));
+}
+
+void target_sdc_init()
+{
+	struct mmc_config_data config;
+
+	/* Set drive strength & pull ctrl values */
+	set_sdc_power_ctrl();
+
+	/* Try slot 1*/
+	config.slot          = 1;
+	config.bus_width     = DATA_BUS_WIDTH_8BIT;
+	config.max_clk_rate  = MMC_CLK_177MHZ;
+	config.sdhc_base     = mmc_sdhci_base[config.slot - 1];
+	config.pwrctl_base   = mmc_pwrctl_base[config.slot - 1];
+	config.pwr_irq       = mmc_sdc_pwrctl_irq[config.slot - 1];
+	config.hs400_support = 1;
+
+	if (!(dev = mmc_init(&config))) {
+	/* Try slot 2 */
+		config.slot          = 2;
+		config.max_clk_rate  = MMC_CLK_200MHZ;
+		config.sdhc_base     = mmc_sdhci_base[config.slot - 1];
+		config.pwrctl_base   = mmc_pwrctl_base[config.slot - 1];
+		config.pwr_irq       = mmc_sdc_pwrctl_irq[config.slot - 1];
+		config.hs400_support = 0;
+
+		if (!(dev = mmc_init(&config))) {
+			dprintf(CRITICAL, "mmc init failed!");
+			ASSERT(0);
+		}
+	}
+}
+
+void *target_mmc_device()
+{
+	return (void *) dev;
+}
+
+/* Return 1 if vol_up pressed */
+static int target_volume_up()
+{
+	uint8_t status = 0;
+
+	gpio_tlmm_config(TLMM_VOL_UP_BTN_GPIO, 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA, GPIO_ENABLE);
+
+	/* Wait for the gpio config to take effect - debounce time */
+	thread_sleep(10);
+
+	/* Get status of GPIO */
+	status = gpio_status(TLMM_VOL_UP_BTN_GPIO);
+
+	/* Active high signal. */
+	return status;
+}
+
+/* Return 1 if vol_down pressed */
+uint32_t target_volume_down()
+{
+	/* Volume down button tied in with PMIC RESIN. */
+	return pm8x41_resin_status();
+}
+
+static void target_keystatus()
+{
+	keys_init();
+
+	if(target_volume_down())
+		keys_post_event(KEY_VOLUMEDOWN, 1);
+
+	if(target_volume_up())
+		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 */
+	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)
+{
+	uint32_t base_addr;
+	uint8_t slot;
+
+	dprintf(INFO, "target_init()\n");
+
+	spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
+
+	target_keystatus();
+
+	target_sdc_init();
+	if (partition_read_table())
+	{
+		dprintf(CRITICAL, "Error reading the partition table info\n");
+		ASSERT(0);
+	}
+
+#if LONG_PRESS_POWER_ON
+	shutdown_detect();
+#endif
+	if (target_use_signed_kernel())
+		target_crypto_init_params();
+}
+
+void target_serialno(unsigned char *buf)
+{
+	uint32_t serialno;
+	if (target_is_emmc_boot()) {
+		serialno = mmc_get_psn();
+		snprintf((char *)buf, 13, "%x", serialno);
+	}
+}
+
+unsigned board_machtype(void)
+{
+	return LINUX_MACHTYPE_UNKNOWN;
+}
+
+/* Detect the target type */
+void target_detect(struct board_data *board)
+{
+	/* This is already filled as part of board.c */
+}
+
+/* Detect the modem type */
+void target_baseband_detect(struct board_data *board)
+{
+	uint32_t platform;
+
+	platform = board->platform;
+
+	switch(platform) {
+	case MSM8952:
+	case MSM8956:
+	case MSM8976:
+		board->baseband = BASEBAND_MSM;
+		break;
+	default:
+		dprintf(CRITICAL, "Platform type: %u is not supported\n",platform);
+		ASSERT(0);
+	};
+}
+
+unsigned target_baseband()
+{
+	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 dload_mode mode)
+{
+	int ret = 0;
+	ret = scm_dload_mode(mode);
+
+	pm8x41_clear_pmic_watchdog();
+
+	return ret;
+}
+
+int emmc_recovery_init(void)
+{
+	return _emmc_recovery_init();
+}
+
+void reboot_device(unsigned reboot_reason)
+{
+	uint8_t reset_type = 0;
+	uint32_t ret = 0;
+
+	/* Need to clear the SW_RESET_ENTRY register and
+	 * write to the BOOT_MISC_REG for known reset cases
+	 */
+	if(reboot_reason != DLOAD)
+		scm_dload_mode(NORMAL_MODE);
+
+	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 == DLOAD))
+		reset_type = PON_PSHOLD_WARM_RESET;
+	else
+		reset_type = PON_PSHOLD_HARD_RESET;
+
+	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)
+{
+	uint8_t pon_reason = pm8x41_get_pon_reason();
+	uint8_t is_cold_boot = pm8x41_get_is_cold_boot();
+	dprintf(INFO, "%s : pon_reason is %d cold_boot:%d\n", __func__,
+		pon_reason, is_cold_boot);
+	/* In case of fastboot reboot,adb reboot or if we see the power key
+	* pressed we do not want go into charger mode.
+	* fastboot reboot is warm boot with PON hard reset bit not set
+	* adb reboot is a cold boot with PON hard reset bit set
+	*/
+	if (is_cold_boot &&
+			(!(pon_reason & HARD_RST)) &&
+			(!(pon_reason & KPDPWR_N)) &&
+			((pon_reason & USB_CHG)))
+		return 1;
+	else
+		return 0;
+}
+
+void target_uninit(void)
+{
+	mmc_put_card_to_sleep(dev);
+	sdhci_mode_disable(&dev->host);
+	if (crypto_initialized())
+		crypto_eng_cleanup();
+
+	if (target_is_ssd_enabled())
+		clock_ce_disable(CE1_INSTANCE);
+}
+
+void target_usb_init(void)
+{
+	uint32_t val;
+
+	/* Select and enable external configuration with USB PHY */
+	ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);
+
+	/* Enable sess_vld */
+	val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
+	writel(val, USB_GENCONFIG_2);
+
+	/* Enable external vbus configuration in the LINK */
+	val = readl(USB_USBCMD);
+	val |= SESS_VLD_CTRL;
+	writel(val, USB_USBCMD);
+}
+
+void target_usb_stop(void)
+{
+	/* Disable VBUS mimicing in the controller. */
+	ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_CLEAR);
+}
+
+/* Do any target specific intialization needed before entering fastboot mode */
+void target_fastboot_init(void)
+{
+	if (target_is_ssd_enabled()) {
+		clock_ce_enable(CE1_INSTANCE);
+		target_load_ssd_keystore();
+	}
+}
+
+void target_load_ssd_keystore(void)
+{
+	uint64_t ptn;
+	int      index;
+	uint64_t size;
+	uint32_t *buffer = NULL;
+
+	if (!target_is_ssd_enabled())
+		return;
+
+	index = partition_get_index("ssd");
+
+	ptn = partition_get_offset(index);
+	if (ptn == 0){
+		dprintf(CRITICAL, "Error: ssd partition not found\n");
+		return;
+	}
+
+	size = partition_get_size(index);
+	if (size == 0) {
+		dprintf(CRITICAL, "Error: invalid ssd partition size\n");
+		return;
+	}
+
+	buffer = memalign(CACHE_LINE, ROUNDUP(size, CACHE_LINE));
+	if (!buffer) {
+		dprintf(CRITICAL, "Error: allocating memory for ssd buffer\n");
+		return;
+	}
+
+	if (mmc_read(ptn, buffer, size)) {
+		dprintf(CRITICAL, "Error: cannot read data\n");
+		free(buffer);
+		return;
+	}
+
+	clock_ce_enable(CE1_INSTANCE);
+	scm_protect_keystore(buffer, size);
+	clock_ce_disable(CE1_INSTANCE);
+	free(buffer);
+}
+
+crypto_engine_type board_ce_type(void)
+{
+	return CRYPTO_ENGINE_TYPE_HW;
+}
+
+/* Set up params for h/w CE. */
+void target_crypto_init_params()
+{
+	struct crypto_init_params ce_params;
+
+	/* Set up base addresses and instance. */
+	ce_params.crypto_instance  = CE1_INSTANCE;
+	ce_params.crypto_base      = MSM_CE1_BASE;
+	ce_params.bam_base         = MSM_CE1_BAM_BASE;
+
+	/* Set up BAM config. */
+	ce_params.bam_ee               = CE_EE;
+	ce_params.pipes.read_pipe      = CE_READ_PIPE;
+	ce_params.pipes.write_pipe     = CE_WRITE_PIPE;
+	ce_params.pipes.read_pipe_grp  = CE_READ_PIPE_LOCK_GRP;
+	ce_params.pipes.write_pipe_grp = CE_WRITE_PIPE_LOCK_GRP;
+
+	/* Assign buffer sizes. */
+	ce_params.num_ce           = CE_ARRAY_SIZE;
+	ce_params.read_fifo_size   = CE_FIFO_SIZE;
+	ce_params.write_fifo_size  = CE_FIFO_SIZE;
+
+	/* BAM is initialized by TZ for this platform.
+	 * Do not do it again as the initialization address space
+	 * is locked.
+	 */
+	ce_params.do_bam_init      = 0;
+
+	crypto_init_params(&ce_params);
+}
diff --git a/target/thulium/meminfo.c b/target/msm8952/meminfo.c
similarity index 96%
rename from target/thulium/meminfo.c
rename to target/msm8952/meminfo.c
index 9aa1dd5..b2f46df 100644
--- a/target/thulium/meminfo.c
+++ b/target/msm8952/meminfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 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
@@ -64,14 +64,11 @@
 
 			if (ret)
 			{
-				dprintf(CRITICAL, "Failed to add secondary banks memory addresses\n"
-);
+				dprintf(CRITICAL, "Failed to add secondary banks memory addresses\n");
 				goto target_dev_tree_mem_err;
 			}
-
 		}
 	}
-
 target_dev_tree_mem_err:
 
 	return ret;
diff --git a/target/msm8952/rules.mk b/target/msm8952/rules.mk
new file mode 100644
index 0000000..31d4c36
--- /dev/null
+++ b/target/msm8952/rules.mk
@@ -0,0 +1,29 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared
+
+PLATFORM := msm8952
+
+MEMBASE := 0x8F600000 # SDRAM
+MEMSIZE := 0x00100000 # 1MB
+
+BASE_ADDR        := 0x80000000
+SCRATCH_ADDR     := 0x90000000
+
+MODULES += \
+	dev/keys \
+	dev/vib \
+	lib/ptable \
+	dev/pmic/pm8x41 \
+	lib/libfdt
+
+DEFINES += \
+	MEMSIZE=$(MEMSIZE) \
+	MEMBASE=$(MEMBASE) \
+	BASE_ADDR=$(BASE_ADDR) \
+	SCRATCH_ADDR=$(SCRATCH_ADDR)
+
+
+OBJS += \
+	$(LOCAL_DIR)/init.o \
+	$(LOCAL_DIR)/meminfo.o
diff --git a/target/msm8952/tools/makefile b/target/msm8952/tools/makefile
new file mode 100644
index 0000000..da48f0d
--- /dev/null
+++ b/target/msm8952/tools/makefile
@@ -0,0 +1,12 @@
+#Makefile to generate appsboot.mbn
+
+ifeq ($(BOOTLOADER_OUT),.)
+APPSBOOTOUT_DIR  := $(BUILDDIR)
+else
+APPSBOOTOUT_DIR  := $(BOOTLOADER_OUT)/../..
+endif
+
+APPSBOOTHEADER: emmc_appsboot.mbn
+
+emmc_appsboot.mbn: $(OUTELF_STRIP)
+	$(hide) cp -f $(OUTELF_STRIP) $(APPSBOOTOUT_DIR)/emmc_appsboot.mbn
diff --git a/target/msm8994/init.c b/target/msm8994/init.c
index 4e2e160..824bdc1 100644
--- a/target/msm8994/init.c
+++ b/target/msm8994/init.c
@@ -105,7 +105,7 @@
 }
 
 /* Return 1 if vol_up pressed */
-static int target_volume_up()
+int target_volume_up()
 {
 	uint8_t status = 0;
 	struct pm8x41_gpio gpio;
@@ -446,16 +446,22 @@
 void reboot_device(unsigned reboot_reason)
 {
 	uint8_t reset_type = 0;
+	uint32_t restart_reason_addr;
+
+	if (platform_is_msm8994())
+		restart_reason_addr = RESTART_REASON_ADDR;
+	else
+		restart_reason_addr = RESTART_REASON_ADDR2;
 
 	/* Write the reboot reason */
-	writel(reboot_reason, RESTART_REASON_ADDR);
+	writel(reboot_reason, restart_reason_addr);
 
 	if(reboot_reason == FASTBOOT_MODE)
 		reset_type = PON_PSHOLD_WARM_RESET;
 	else
 		reset_type = PON_PSHOLD_HARD_RESET;
 
-	pm8x41_reset_configure(reset_type);
+	pm8994_reset_configure(reset_type);
 
 	/* Drop PS_HOLD for MSM */
 	writel(0x00, MPM2_MPM_PS_HOLD);
@@ -556,7 +562,7 @@
 	dprintf(CRITICAL, "Going down for shutdown.\n");
 
 	/* Configure PMIC for shutdown. */
-	pm8x41_reset_configure(PON_PSHOLD_SHUTDOWN);
+	pm8994_reset_configure(PON_PSHOLD_SHUTDOWN);
 
 	/* Drop PS_HOLD for MSM */
 	writel(0x00, MPM2_MPM_PS_HOLD);
diff --git a/target/msm8994/oem_panel.c b/target/msm8994/oem_panel.c
index de292b5..62795ad 100644
--- a/target/msm8994/oem_panel.c
+++ b/target/msm8994/oem_panel.c
@@ -48,6 +48,7 @@
 #include "include/panel_jdi_qhd_dualdsi_cmd.h"
 #include "include/panel_jdi_4k_dualdsi_video.h"
 #include "include/panel_jdi_1080p_video.h"
+#include "include/panel_sharp_1080p_cmd.h"
 #include "include/panel_hx8379a_truly_fwvga_video.h"
 #include "include/panel_nt35597_wqxga_video.h"
 #include "include/panel_nt35597_wqxga_cmd.h"
@@ -61,6 +62,7 @@
 JDI_QHD_DUALDSI_CMD_PANEL,
 JDI_4K_DUALDSI_VIDEO_PANEL,
 JDI_1080P_VIDEO_PANEL,
+SHARP_1080P_CMD_PANEL,
 HX8379A_TRULY_FWVGA_VIDEO_PANEL,
 NOVATEK_WQXGA_VIDEO_PANEL,
 NOVATEK_WQXGA_CMD_PANEL,
@@ -77,6 +79,7 @@
 	{"jdi_qhd_dualdsi_cmd", JDI_QHD_DUALDSI_CMD_PANEL},
 	{"jdi_4k_dualdsi_video", JDI_4K_DUALDSI_VIDEO_PANEL},
 	{"jdi_1080p_video", JDI_1080P_VIDEO_PANEL},
+	{"sharp_1080p_cmd", SHARP_1080P_CMD_PANEL},
 	{"hx8379a_truly_fwvga_video", HX8379A_TRULY_FWVGA_VIDEO_PANEL},
 	{"nt35597_wqxga_video", NOVATEK_WQXGA_VIDEO_PANEL},
 	{"nt35597_wqxga_cmd", NOVATEK_WQXGA_CMD_PANEL},
@@ -158,6 +161,7 @@
 		memcpy(phy_db->timing,
 			sharp_wqxga_dualdsi_video_timings, TIMING_SIZE);
 		pinfo->dfps.panel_dfps = sharp_wqxga_dualdsi_video_dfps;
+		pinfo->mipi.tx_eot_append = true;
 		break;
 	case JDI_QHD_DUALDSI_VIDEO_PANEL:
 		pan_type = PANEL_TYPE_DSI;
@@ -278,6 +282,32 @@
 		memcpy(phy_db->timing,
 			jdi_1080p_video_timings, TIMING_SIZE);
 		break;
+	case SHARP_1080P_CMD_PANEL:
+		pan_type = PANEL_TYPE_DSI;
+		pinfo->lcd_reg_en = 0;
+		panelstruct->paneldata    = &sharp_1080p_cmd_panel_data;
+		panelstruct->panelres     = &sharp_1080p_cmd_panel_res;
+		panelstruct->color        = &sharp_1080p_cmd_color;
+		panelstruct->videopanel   = &sharp_1080p_cmd_video_panel;
+		panelstruct->commandpanel = &sharp_1080p_cmd_command_panel;
+		panelstruct->state        = &sharp_1080p_cmd_state;
+		panelstruct->laneconfig   = &sharp_1080p_cmd_lane_config;
+		panelstruct->paneltiminginfo
+			= &sharp_1080p_cmd_timing_info;
+		panelstruct->panelresetseq
+					 = &sharp_1080p_cmd_panel_reset_seq;
+		panelstruct->backlightinfo = &sharp_1080p_cmd_backlight;
+		pinfo->mipi.panel_on_cmds
+			= sharp_1080p_cmd_on_command;
+		pinfo->mipi.num_of_panel_on_cmds
+			= SHARP_1080P_CMD_ON_COMMAND;
+		pinfo->mipi.panel_off_cmds
+			= sharp_1080p_cmd_off_command;
+		pinfo->mipi.num_of_panel_off_cmds
+			= SHARP_1080P_CMD_OFF_COMMAND;
+		memcpy(phy_db->timing,
+			sharp_1080p_cmd_timings, TIMING_SIZE);
+		break;
 	case HX8379A_TRULY_FWVGA_VIDEO_PANEL:
 		pan_type = PANEL_TYPE_DSI;
 		pinfo->lcd_reg_en = 1;
diff --git a/target/msm8994/regulator.c b/target/msm8994/regulator.c
index 8a8d1e1..51bd966 100644
--- a/target/msm8994/regulator.c
+++ b/target/msm8994/regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 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
@@ -28,22 +28,22 @@
  */
 
 #include <regulator.h>
-#include <rpm-smd.h>
+#include <rpm-ipc.h>
 
 static uint32_t ldo2[][11]=
 {
 	{
 		LDOA_RES_TYPE, 2,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
 	},
 
 	{
 		LDOA_RES_TYPE, 2,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 1250000,
+		KEY_CURRENT, 4, 16,
 	},
 };
 
@@ -52,15 +52,15 @@
 	{
 		LDOA_RES_TYPE, 12,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
 	},
 
 	{
 		LDOA_RES_TYPE, 12,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 1800000,
+		KEY_CURRENT, 4, 11,
 	},
 };
 
@@ -69,32 +69,32 @@
 	{
 		LDOA_RES_TYPE, 14,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
 	},
 
 	{
 		LDOA_RES_TYPE, 14,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 1800000,
+		KEY_CURRENT, 4, 52,
 	},
 };
 
-static uint32_t ldo28[][11]=
+static uint32_t ldo28[][14]=
 {
 	{
 		LDOA_RES_TYPE, 28,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
 	},
 
 	{
 		LDOA_RES_TYPE, 28,
 		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
-		KEY_LDO_SOFTWARE_MODE, 4, SW_MODE_LDO_IPEAK,
 		KEY_MICRO_VOLT, 4, 1000000,
+		KEY_CURRENT, 4, 72,
 	},
 
 };
diff --git a/target/thulium/init.c b/target/msm8996/init.c
similarity index 89%
rename from target/thulium/init.c
rename to target/msm8996/init.c
index 28c6b2c..356ef5e 100644
--- a/target/thulium/init.c
+++ b/target/msm8996/init.c
@@ -55,6 +55,7 @@
 #include <qmp_phy.h>
 #include <sdhci_msm.h>
 #include <qusb2_phy.h>
+#include <rpmb.h>
 
 #define CE_INSTANCE             1
 #define CE_EE                   1
@@ -136,6 +137,22 @@
 		/* Disable HC mode before jumping to kernel */
 		sdhci_mode_disable(&dev->host);
 	}
+
+	if (is_sec_app_loaded())
+	{
+		if (unload_sec_app() < 0)
+		{
+			dprintf(CRITICAL, "Failed to unload App for rpmb\n");
+			ASSERT(0);
+		}
+	}
+
+	if (rpmb_uninit() < 0)
+	{
+		dprintf(CRITICAL, "RPMB uninit failed\n");
+		ASSERT(0);
+	}
+
 }
 
 static void set_sdc_power_ctrl()
@@ -238,6 +255,12 @@
 
 	/* Storage initialization is complete, read the partition table info */
 	mmc_read_partition_table(0);
+
+	if (rpmb_init() < 0)
+	{
+		dprintf(CRITICAL, "RPMB init failed\n");
+		ASSERT(0);
+	}
 }
 
 unsigned board_machtype(void)
@@ -392,3 +415,31 @@
 
 	crypto_init_params(&ce_params);
 }
+
+unsigned target_pause_for_battery_charge(void)
+{
+	uint8_t pon_reason = pm8x41_get_pon_reason();
+	uint8_t is_cold_boot = pm8x41_get_is_cold_boot();
+	dprintf(INFO, "%s : pon_reason is %d cold_boot:%d\n", __func__,
+		pon_reason, is_cold_boot);
+	/* In case of fastboot reboot,adb reboot or if we see the power key
+	* pressed we do not want go into charger mode.
+	* fastboot reboot is warm boot with PON hard reset bit not set
+	* adb reboot is a cold boot with PON hard reset bit set
+	*/
+	if (is_cold_boot &&
+			(!(pon_reason & HARD_RST)) &&
+			(!(pon_reason & KPDPWR_N)) &&
+			((pon_reason & PON1)))
+		return 1;
+	else
+		return 0;
+}
+
+int set_download_mode(enum dload_mode mode)
+{
+	int ret = 0;
+	ret = scm_dload_mode(mode);
+
+	return ret;
+}
diff --git a/target/thulium/meminfo.c b/target/msm8996/meminfo.c
similarity index 91%
copy from target/thulium/meminfo.c
copy to target/msm8996/meminfo.c
index 9aa1dd5..c65525f 100644
--- a/target/thulium/meminfo.c
+++ b/target/msm8996/meminfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 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
@@ -41,6 +41,7 @@
 	unsigned int index;
 	int ret = 0;
 	uint32_t len = 0;
+	uint64_t size = 0;
 
 	/* Make sure RAM partition table is initialized */
 	ASSERT(smem_ram_ptable_init_v1());
@@ -56,11 +57,16 @@
 			(ptn_entry.type == SYS_MEMORY))
 		{
 
+			if (smem_get_ram_ptable_version() == SMEM_RAM_PTABLE_VERSION_2)
+				size = ptn_entry.available_length;
+			else
+				size = ptn_entry.size;
+
 			/* Pass along all other usable memory regions to Linux */
 			ret = dev_tree_add_mem_info(fdt,
 							memory_node_offset,
 							ptn_entry.start,
-							ptn_entry.size);
+							size);
 
 			if (ret)
 			{
diff --git a/target/thulium/rules.mk b/target/msm8996/rules.mk
similarity index 90%
rename from target/thulium/rules.mk
rename to target/msm8996/rules.mk
index 5ec0e88..28ab538 100644
--- a/target/thulium/rules.mk
+++ b/target/msm8996/rules.mk
@@ -2,14 +2,14 @@
 
 INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared
 
-PLATFORM := thulium
+PLATFORM := msm8996
 
 MEMBASE := 0x8F000000 # SDRAM
-MEMSIZE := 0x00100000 # 1MB
+MEMSIZE := 0x00200000 # 2MB
 
 BASE_ADDR    := 0x0000000
 
-SCRATCH_ADDR := 0x8F100000
+SCRATCH_ADDR := 0x8F300000
 SCRATCH_SIZE := 512
 KERNEL_ADDR  := 0x80000000
 KERNEL_SIZE  := 62
diff --git a/target/thulium/tools/makefile b/target/msm8996/tools/makefile
similarity index 100%
rename from target/thulium/tools/makefile
rename to target/msm8996/tools/makefile