Merge "app: aboot: erase userdata footer when ufs storage is used."
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 33d95d6..4f26616 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -448,6 +448,14 @@
 		cmdline_len += strlen(warmboot_cmdline);
 	}
 
+#if TARGET_CMDLINE_SUPPORT
+	char *target_cmdline_buf = malloc(TARGET_MAX_CMDLNBUF);
+	int target_cmd_line_len;
+	ASSERT(target_cmdline_buf);
+	target_cmd_line_len = target_update_cmdline(target_cmdline_buf);
+	cmdline_len += target_cmd_line_len;
+#endif
+
 	if (cmdline_len > 0) {
 		const char *src;
 		unsigned char *dst;
@@ -627,6 +635,16 @@
 			while ((*dst++ = *src++));
 			free(target_boot_params);
 		}
+
+#if TARGET_CMDLINE_SUPPORT
+		if (target_cmdline_buf && target_cmd_line_len)
+		{
+			if (have_cmdline) --dst;
+			src = target_cmdline_buf;
+			while((*dst++ = *src++));
+			free(target_cmdline_buf);
+		}
+#endif
 	}
 
 
@@ -709,7 +727,7 @@
 void generate_atags(unsigned *ptr, const char *cmdline,
                     void *ramdisk, unsigned ramdisk_size)
 {
-
+	unsigned *orig_ptr = ptr;
 	ptr = atag_core(ptr);
 	ptr = atag_ramdisk(ptr, ramdisk, ramdisk_size);
 	ptr = target_atag_mem(ptr);
@@ -719,8 +737,18 @@
 		ptr = atag_ptable(&ptr);
 	}
 
-	ptr = atag_cmdline(ptr, cmdline);
-	ptr = atag_end(ptr);
+	/*
+	 * Atags size filled till + cmdline size + 1 unsigned for 4-byte boundary + 4 unsigned
+	 * for atag identifier in atag_cmdline and atag_end should be with in MAX_TAGS_SIZE bytes
+	 */
+	if (((ptr - orig_ptr) + strlen(cmdline) + 5 * sizeof(unsigned)) <  MAX_TAGS_SIZE) {
+		ptr = atag_cmdline(ptr, cmdline);
+		ptr = atag_end(ptr);
+	}
+	else {
+		dprintf(CRITICAL,"Crossing ATAGs Max size allowed\n");
+		ASSERT(0);
+	}
 }
 
 typedef void entry_func_ptr(unsigned, unsigned, unsigned*);
@@ -3155,6 +3183,7 @@
 	struct ptentry *ptn;
 	struct ptable *ptable;
 	unsigned extra = 0;
+	uint64_t partition_size = 0;
 
 	ptable = flash_get_ptable();
 	if (ptable == NULL) {
@@ -3186,6 +3215,17 @@
 	else
 		sz = ROUND_TO_PAGE(sz, page_mask);
 
+	partition_size = (uint64_t)ptn->length * (uint64_t)flash_num_pages_per_blk() *  (uint64_t)flash_page_size();
+	if (partition_size > UINT_MAX) {
+		fastboot_fail("Invalid partition size");
+		return;
+	}
+
+	if (sz > partition_size) {
+		fastboot_fail("Image size too large");
+		return;
+	}
+
 	dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
 	if (!memcmp((void *)data, UBI_MAGIC, UBI_MAGIC_SIZE)) {
 		if (flash_ubi_img(ptn, data, sz)) {
diff --git a/app/aboot/fastboot_test.c b/app/aboot/fastboot_test.c
index 64c0f7f..70bc64e 100644
--- a/app/aboot/fastboot_test.c
+++ b/app/aboot/fastboot_test.c
@@ -88,6 +88,13 @@
 	dprintf(INFO, "Running RPMB test case, please make sure RPMB key is provisioned ...\n");
 	struct device_info *write_info = memalign(PAGE_SIZE, 4096);
 	struct device_info *read_info = memalign(PAGE_SIZE, 4096);
+
+	if((write_info == NULL)||(read_info == NULL))
+	{
+		dprintf(CRITICAL, "Failed to allocate memory for devinfo %s %d \n",__FUNCTION__,__LINE__);
+		goto err;
+	}
+
 	if((read_device_info_rpmb((void*) read_info, PAGE_SIZE)) < 0)
 		dprintf(INFO, "RPMB READ TEST : [ FAIL ]\n");
 
@@ -104,6 +111,7 @@
 	else
 		dprintf(INFO, "RPMB READ/WRITE TEST: [ FAIL ]\n");
 
+err:
 	free(read_info);
 	free(write_info);
 #endif
diff --git a/app/aboot/mdtp.c b/app/aboot/mdtp.c
index f02eae9..136fab5 100644
--- a/app/aboot/mdtp.c
+++ b/app/aboot/mdtp.c
@@ -40,6 +40,7 @@
 #include <stdlib.h>
 #include <boot_verifier.h>
 #include <image_verify.h>
+#include <qtimer.h>
 #include "scm.h"
 #include "mdtp.h"
 #include "mdtp_fs.h"
@@ -74,7 +75,6 @@
 
 extern int check_aboot_addr_range_overlap(uintptr_t start, uint32_t size);
 int scm_random(uint32_t * rbuf, uint32_t  r_len);
-extern void mdelay(unsigned msecs);
 void free_mdtp_image(void);
 
 /********************************************************************************/
@@ -240,10 +240,10 @@
 
 /* Validate a hash table calculated per block of a given partition */
 static int verify_partition_block_hash(char *name,
-								uint64_t size,
-								uint32_t verify_num_blocks,
-								DIP_hash_table_entry_t *hash_table,
-								uint8_t *force_verify_block)
+									uint64_t size,
+									uint32_t verify_num_blocks,
+									DIP_hash_table_entry_t *hash_table,
+									uint8_t *force_verify_block)
 {
 	unsigned char digest[HASH_LEN]={0};
 	unsigned long long ptn = 0;
@@ -334,14 +334,14 @@
 
 /* Validate the partition parameters read from DIP */
 static int validate_partition_params(uint64_t size,
-						mdtp_fwlock_mode_t hash_mode,
-						uint32_t verify_ratio)
+									mdtp_fwlock_mode_t hash_mode,
+									uint32_t verify_ratio)
 {
 	if (size == 0 || size > (uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS ||
-		hash_mode > MDTP_FWLOCK_MODE_FILES || verify_ratio > 100)
+			hash_mode > MDTP_FWLOCK_MODE_FILES || verify_ratio > 100)
 	{
 		dprintf(CRITICAL, "mdtp: validate_partition_params: error, size=%llu, hash_mode=%d, verify_ratio=%d\n",
-			size, hash_mode, verify_ratio);
+				size, hash_mode, verify_ratio);
 		return -1;
 	}
 
@@ -350,11 +350,11 @@
 
 /* Verify a given partitinon */
 static int verify_partition(char *name,
-						uint64_t size,
-						mdtp_fwlock_mode_t hash_mode,
-						uint32_t verify_num_blocks,
-						DIP_hash_table_entry_t *hash_table,
-						uint8_t *force_verify_block)
+							uint64_t size,
+							mdtp_fwlock_mode_t hash_mode,
+							uint32_t verify_num_blocks,
+							DIP_hash_table_entry_t *hash_table,
+							uint8_t *force_verify_block)
 {
 	if (hash_mode == MDTP_FWLOCK_MODE_SINGLE)
 	{
@@ -524,14 +524,14 @@
 			ptn = partition_get_offset(index);
 			if(ptn == 0) {
 				dprintf(CRITICAL, "ERROR: partition %s not found\n",
-					ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
+						ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
 				return -1;
 			}
 
 			if(mmc_read(ptn + ext_partition->image_size, (void *)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
 			{
 				dprintf(CRITICAL, "ERROR: Cannot read %s image signature\n",
-					ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
+						ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
 				return -1;
 			}
 		}
@@ -570,8 +570,8 @@
 
 /* Verify all protected partitinons according to the DIP */
 static void verify_all_partitions(DIP_t *dip,
-								 mdtp_ext_partition_verification_t *ext_partition,
-								 verify_result_t *verify_result)
+								mdtp_ext_partition_verification_t *ext_partition,
+								verify_result_t *verify_result)
 {
 	int i;
 	int verify_failure = 0;
@@ -810,8 +810,8 @@
 	arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
 
 	ret = mdtp_cipher_dip_cmd((uint8_t*)enc_dip, sizeof(DIP_t),
-								(uint8_t*)dec_dip, sizeof(DIP_t),
-								DIP_DECRYPT);
+							(uint8_t*)dec_dip, sizeof(DIP_t),
+							DIP_DECRYPT);
 	if (ret)
 	{
 		dprintf(CRITICAL, "mdtp: mdtp_tzbsp_dec_verify_DIP: ERROR, cannot cipher DIP\n");
@@ -856,8 +856,8 @@
 	arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
 
 	ret = mdtp_cipher_dip_cmd((uint8_t*)dec_dip, sizeof(DIP_t),
-								(uint8_t*)enc_dip, sizeof(DIP_t),
-								DIP_ENCRYPT);
+							(uint8_t*)enc_dip, sizeof(DIP_t),
+							DIP_ENCRYPT);
 	if (ret)
 	{
 		dprintf(CRITICAL, "mdtp: mdtp_tzbsp_enc_hash_DIP: ERROR, cannot cipher DIP\n");
@@ -886,11 +886,7 @@
 	/* Disallow the CIPHER_DIP SCM by calling it MAX_CIPHER_DIP_SCM_CALLS times */
 	for (i=0; i<MAX_CIPHER_DIP_SCM_CALLS; i++)
 	{
-		if(mdtp_tzbsp_enc_hash_DIP(dip, dip) != 0)
-		{
-			/* Couldn't disallowd CIPHER_DIP SCM - stop device from booting */
-			display_error_msg(); /* This will never return */
-		}
+		mdtp_tzbsp_enc_hash_DIP(dip, dip);
 	}
 
 	free(dip);
@@ -947,7 +943,7 @@
 
 	//Bad size
 	if(validate_partition_params((uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS + 1,
-		MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
+			MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
 		dprintf(INFO, "validate_partition_params_ut: [FAIL (2)].\n");
 		return -1;
 	}
@@ -969,7 +965,7 @@
 
 	//Unkown hashing mode
 	if(verify_partition("system", partition_size, BAD_HASH_MODE, verify_num_blocks,
-		&partition_hash_table, &partition_force_verify_block) != -1){
+			&partition_hash_table, &partition_force_verify_block) != -1){
 		dprintf(INFO, "verify_partition_ut: Failed Test 1.\n");
 		dprintf(INFO, "MDTP LK UT: verify_partition_ut [ FAIL ]\n");
 		return -1;
diff --git a/app/aboot/mdtp_fs.c b/app/aboot/mdtp_fs.c
index b848c7a..f52fda9 100644
--- a/app/aboot/mdtp_fs.c
+++ b/app/aboot/mdtp_fs.c
@@ -44,6 +44,63 @@
 static mdtp_image_t mdtp_img;
 
 /*---------------------------------------------------------
+ * Internal Functions
+ *-------------------------------------------------------*/
+
+static int mdtp_read_metadata(uint32_t offset){
+	int index = INVALID_PTN;
+	unsigned long long ptn = 0;
+	int i = 0;
+	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 -1;
+	}
+
+	ptn = partition_get_offset(index);
+	mmc_set_lun(partition_get_lun(index));
+
+	if (ptn == 0) {
+		dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
+		return -1;
+	}
+
+	for(i = 0; i< MAX_PARAMS; i++) {
+		mdtp_img.meta_data.params[i] = MDTP_PARAM_UNSET_VALUE; //Initialize params for error check
+	}
+
+	uint8_t *base = memalign(block_size, ROUNDUP(MDTP_HEADER_LEN, block_size));
+	if (!base) {
+		dprintf(CRITICAL, "ERROR: mdtp malloc failed\n");
+		return -1;
+	}
+
+	// read image meta data
+	if (mmc_read(ptn+offset, (void*)base, MDTP_HEADER_LEN)) {
+		dprintf(CRITICAL, "ERROR: mdtp meta data read failed\n");
+		free(base);
+		return -1;
+	}
+
+	uint32_t params_size = MAX_PARAMS * sizeof(uint32_t);
+	uint32_t images_params_size = MAX_IMAGES*sizeof(mdtp_image_params_t);
+	memscpy(mdtp_img.meta_data.params, sizeof(mdtp_img.meta_data.params), base, params_size);
+	memscpy(mdtp_img.meta_data.image_params, META_DATA_PARTITION_LEN,
+			base + sizeof(mdtp_img.meta_data.params), images_params_size);
+
+	dprintf(INFO, "mdtp: metadata loaded\n");
+
+	free(base);
+	return 0;
+}
+
+static void mdtp_fs_set_param(mdtp_parameter_id_t param, uint32_t value){
+	mdtp_img.meta_data.params[param] = value;
+}
+
+/*---------------------------------------------------------
  * External Functions
  *-------------------------------------------------------*/
 
@@ -63,53 +120,90 @@
 	return mdtp_img.meta_data.params[param];
 }
 
-
 int mdtp_fs_init(){
-	int index = INVALID_PTN;
-	unsigned long long ptn = 0;
-	int i = 0;
-	uint32_t block_size = mmc_get_device_blocksize();
+	uint32_t i;
+	struct fbcon_config *fb_config = NULL;
+	mdtp_image_params_t image_params;
+	mdtp_image_t mdtp_image_sets_metadata;
+	uint32_t image_sets_num;
+	uint32_t metadata_offset = 0;
 
-	index = partition_get_index("mdtp");
-	if (index == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
-		return 1;
+	// Read image sets metadata
+	if (mdtp_read_metadata(metadata_offset)){
+		dprintf(CRITICAL, "ERROR: failed to read image sets metadata\n");
+		return -1;
 	}
 
-	ptn = partition_get_offset(index);
-	mmc_set_lun(partition_get_lun(index));
-
-	if (ptn == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
-		return 1;
+	// Verify that metadata version is supported
+	if (mdtp_fs_get_param(VERSION) != SUPPORTED_METADATA_VERSION){
+		dprintf(CRITICAL, "ERROR: metadata version is not supported: %d\n", mdtp_fs_get_param(VERSION));
+		return -1;
 	}
 
-	for(i = 0; i< MAX_PARAMS; i++) {
-		mdtp_img.meta_data.params[i] = -1; //Initiate params for errors check
+	// Verify that metadata version is as expected
+	if (mdtp_fs_get_param(TYPE) != IMAGE_SETS){
+		dprintf(CRITICAL, "ERROR: unexpected type for image sets metadata: %d\n", mdtp_fs_get_param(TYPE));
+		return -1;
 	}
 
-	uint8_t *base = memalign(block_size, ROUNDUP(MDTP_HEADER_LEN, block_size));
-	if (!base) {
-		dprintf(CRITICAL, "ERROR: mdtp malloc failed\n");
-		return 1;
+	image_sets_num = mdtp_fs_get_param(IMAGE_SETS_NUM);
+	if (image_sets_num < 1) {
+		dprintf(CRITICAL, "ERROR: invalid number of image sets: %d\n", image_sets_num);
+		return -1;
 	}
 
-	// read image meta data
-	if (mmc_read(ptn, (void*)base, MDTP_HEADER_LEN)) {
-		dprintf(CRITICAL, "ERROR: mdtp meta data read failed\n");
-		free(base);
-		return 1;
+	// Get screen configuration
+	fb_config = fbcon_display();
+
+	// Image sets are sorted by screen resolution (width, height), from low to high.
+	// We begin with the smallest image set, and check if bigger image sets also fit the screen.
+	image_params = mdtp_img.meta_data.image_params[0];
+
+	for (i=1; i<image_sets_num; i++){
+
+		//if both width and height still fit the screen, update image_params
+		if (mdtp_img.meta_data.image_params[i].width <= fb_config->width &&
+				mdtp_img.meta_data.image_params[i].height <= fb_config->height)
+		{
+			image_params = mdtp_img.meta_data.image_params[i];
+		}
+
+		// if we reached an image set in which the width is larger than
+		// the screen width, no point in checking additional image sets.
+		else if (mdtp_img.meta_data.image_params[i].width > fb_config->width)
+			break;
 	}
 
-	uint32_t params_size = MAX_PARAMS * sizeof(uint32_t);
-	uint32_t images_params_size = MAX_IMAGES*sizeof(mdtp_image_params_t);
-	memscpy(mdtp_img.meta_data.params, sizeof(mdtp_img.meta_data.params), base, params_size);
-	memscpy(mdtp_img.meta_data.image_params, META_DATA_PARTITION_LEN,
-			base + sizeof(mdtp_img.meta_data.params), images_params_size);
+	dprintf(INFO, "mdtp: image set offset: 0x%x\n", image_params.offset);
+	dprintf(INFO, "mdtp: image set width: %d, screen width: %d\n", image_params.width, fb_config->width);
+	dprintf(INFO, "mdtp: image set height: %d, screen height: %d\n", image_params.height, fb_config->height);
+
+	// Backup image sets metadata for required parameters
+	mdtp_image_sets_metadata = mdtp_img;
+
+	// Read images metadata
+	if (mdtp_read_metadata(image_params.offset)){
+		dprintf(CRITICAL, "ERROR: failed to read images metadata\n");
+		return -1;
+	}
+
+	// Verify that metadata version is supported
+	if (mdtp_fs_get_param(VERSION) != SUPPORTED_METADATA_VERSION){
+		dprintf(CRITICAL, "ERROR: metadata version is not supported: %d\n", mdtp_fs_get_param(VERSION));
+		return -1;
+	}
+
+	// Verify that metadata version is as expected
+	if (mdtp_fs_get_param(TYPE) != IMAGES){
+		dprintf(CRITICAL, "ERROR: unexpected type for images metadata: %d\n", mdtp_fs_get_param(TYPE));
+		return -1;
+	}
+
+	// Copy eFuse from image sets metadata
+	mdtp_fs_set_param(VIRTUAL_FUSE, mdtp_image_sets_metadata.meta_data.params[VIRTUAL_FUSE]);
 
 	dprintf(INFO, "mdtp: mdtp_img loaded\n");
 
-	free(base);
 	return 0;
 }
 
diff --git a/app/aboot/mdtp_fs.h b/app/aboot/mdtp_fs.h
index 33ddf55..e131c12 100644
--- a/app/aboot/mdtp_fs.h
+++ b/app/aboot/mdtp_fs.h
@@ -29,19 +29,26 @@
 #ifndef MDTP_FS_H
 #define MDTP_FS_H
 
-#define MAX_IMAGES					(40)
-#define MDTP_HEADER_LEN 			(4096)
-#define META_DATA_PARTITION_LEN		(2048)
-#define MAX_PARAMS 					(512)
+#define MAX_IMAGES                      (40)
+#define MDTP_HEADER_LEN                 (4096)
+#define META_DATA_PARTITION_LEN         (2048)
+#define MAX_PARAMS                      (512)
+#define MDTP_PARAM_UNSET_VALUE          (111)
+#define SUPPORTED_METADATA_VERSION      (1)
+
 /*
-MDTP header layout:
+MDTP image layout:
+-The mdtp image file contains two layers that both include mdtp_img headers:
+	1. The first header includes the image sets metadata.
+	2. Once we decided which image set we would like to display, we read the metadata
+	   of that specific image set (contains metadata of the actual images).
 -The mdtp_img header is a fixed length of 4096 Bytes.
--The mdtp_img header is devided into 2 partitions:
+-The mdtp_img header is divided into 2 partitions:
 	1.MDTP parameters (eFuse, digit-space, etc..)
-	2.Images meta-data (offset, width, height)
+	2.Images/image sets meta-data (offset, width, height)
 -Each partition size is 2048 Bytes.
--Each parameter is 4 Bytes long, 512 params MAX.
--Each meta-data part (offset/width/height) is 4 Bytes long.
+-Each parameter is 4 Bytes long, 512 params max.
+-Each meta-data parameter (offset/width/height) is 4 Bytes long.
 */
 
 
@@ -76,7 +83,9 @@
 	PIN_UNSELECTED_6 = 24, PIN_UNSELECTED_7 = 25,
 	PIN_UNSELECTED_8 = 26, PIN_UNSELECTED_9 = 27} mdtp_image_id_t;
 
-typedef enum {VIRTUAL_FUSE = 0, DIGIT_SPACE = 1} mdtp_parameter_id_t ;
+typedef enum {VIRTUAL_FUSE = 0, DIGIT_SPACE = 1, VERSION = 2, TYPE = 3, IMAGE_SETS_NUM = 4} mdtp_parameter_id_t;
+
+typedef enum {IMAGES = 1, IMAGE_SETS = 2} mdtp_metadata_type_t;
 
 /*---------------------------------------------------------
  * External Functions
diff --git a/app/aboot/mdtp_fuse.c b/app/aboot/mdtp_fuse.c
index 439fb73..44d2eb5 100644
--- a/app/aboot/mdtp_fuse.c
+++ b/app/aboot/mdtp_fuse.c
@@ -43,7 +43,7 @@
 
 typedef union
 {
-    struct {
+	struct {
 		uint8_t enable1       : 1;
 		uint8_t disable1      : 1;
 		uint8_t enable2       : 1;
@@ -79,7 +79,7 @@
 #define SHK_FUSE           0x02
 #define DEBUG_FUSE         0x04
 
-    /* Make sure we only read the test mode once */
+	/* Make sure we only read the test mode once */
 	if (test_mode_set)
 		return test_mode;
 
@@ -95,7 +95,7 @@
 	{
 		dprintf(CRITICAL, "mdtp: is_test_mode: qsee_get_secure_state returned error: %d, status.value[0]: %d\n", ret, status_low);
 		test_mode = 0;
-    }
+	}
 
 	test_mode_set = 1;
 	dprintf(INFO, "mdtp: is_test_mode: test mode is set to %d\n", test_mode);
@@ -111,7 +111,7 @@
 static int read_metadata(metadata_t *metadata)
 {
 	int eFuse = mdtp_fs_get_param(VIRTUAL_FUSE);
-	if(eFuse == -1){ //Error initiating eFuse
+	if(eFuse == MDTP_PARAM_UNSET_VALUE){      //Error initializing eFuse
 		dprintf(CRITICAL, "mdtp: eFuse reading error\n");
 		return -1;
 	}
@@ -215,8 +215,8 @@
 	}
 
 	if (!(eFuses.bitwise.enable1 && !eFuses.bitwise.disable1) &&
-		!(eFuses.bitwise.enable2 && !eFuses.bitwise.disable2) &&
-		!(eFuses.bitwise.enable3 && !eFuses.bitwise.disable3))
+			!(eFuses.bitwise.enable2 && !eFuses.bitwise.disable2) &&
+			!(eFuses.bitwise.enable3 && !eFuses.bitwise.disable3))
 	{
 		*enabled = 0;
 	}
diff --git a/app/aboot/mdtp_ui.c b/app/aboot/mdtp_ui.c
index fafb787..ed14e65 100644
--- a/app/aboot/mdtp_ui.c
+++ b/app/aboot/mdtp_ui.c
@@ -33,10 +33,11 @@
 #include <partition_parser.h>
 #include <stdlib.h>
 #include <string.h>
+#include <display_menu.h>
+#include <qtimer.h>
 #include "mdtp.h"
 #include "mdtp_defs.h"
 #include "mdtp_fs.h"
-#include <display_menu.h>
 
 // Image releative locations
 #define ERROR_MESSAGE_RELATIVE_Y_LOCATION   (0.18)
@@ -54,15 +55,14 @@
 
 #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();
 extern int msm_display_on();
 
 struct mdtp_fbimage {
-    uint32_t width;
-    uint32_t height;
-    uint8_t image[MDTP_MAX_IMAGE_SIZE];
+	uint32_t width;
+	uint32_t height;
+	uint8_t image[MDTP_MAX_IMAGE_SIZE];
 };
 
 /*----------------------------------------------------------------------------
@@ -71,6 +71,7 @@
 
 static uint32_t g_pin_frames_x_location[MDTP_PIN_LEN] = {0};
 static uint32_t g_pin_frames_y_location = 0;
+static bool g_diplay_pin = false;
 
 static bool g_initial_screen_displayed = false;
 
@@ -130,9 +131,9 @@
 		unsigned bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
 
 		if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*bytes_per_bpp, block_size))) {
-				fbcon_clear();
-				dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
-				return NULL;
+			fbcon_clear();
+			dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
+			return NULL;
 		}
 
 		logo->width = width;
@@ -167,7 +168,7 @@
 
 	if (fb_config)
 	{
-	    image_base = (y *(fb_config->width));
+		image_base = (y *(fb_config->width));
 		bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
 
 		unsigned count = fb_config->width*section_height;
@@ -177,8 +178,8 @@
 	}
 	else
 	{
-	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
-	    display_error_msg(); /* This will never return */
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		display_error_msg(); /* This will never return */
 	}
 }
 
@@ -189,13 +190,13 @@
  */
 static void fbcon_putImage_in_location(struct mdtp_fbimage *fbimg, uint32_t x, uint32_t y)
 {
-    unsigned i = 0;
-    unsigned bytes_per_bpp;
-    unsigned image_base;
-    unsigned width, pitch, height;
-    unsigned char *logo_base = NULL;
+	unsigned i = 0;
+	unsigned bytes_per_bpp;
+	unsigned image_base;
+	unsigned width, pitch, height;
+	unsigned char *logo_base = NULL;
 
-    if (!fb_config) {
+	if (!fb_config) {
 		dprintf(CRITICAL,"ERROR: NULL configuration, image cannot be displayed\n");
 		return;
 	}
@@ -206,8 +207,8 @@
 		logo_base = (unsigned char *)fbimg->image;
 	}
 	else {
-	    dprintf(CRITICAL,"ERROR: invalid image struct\n");
-	    return;
+		dprintf(CRITICAL,"ERROR: invalid image struct\n");
+		return;
 	}
 
 	bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
@@ -222,16 +223,16 @@
 		}
 
 		if (fbimg->width > fb_config->width || fbimg->height > fb_config->height ||
-				 (x > (fb_config->width - fbimg->width)) || (y > (fb_config->height - fbimg->height)))
+				(x > (fb_config->width - fbimg->width)) || (y > (fb_config->height - fbimg->height)))
 		{
-		    dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen or exceeds its margins\n");
-		    return;
+			dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen or exceeds its margins\n");
+			return;
 		}
 
 		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);
+					logo_base + ((height - 1 - i) * pitch * bytes_per_bpp), width * bytes_per_bpp);
 		}
 	}
 	else
@@ -254,26 +255,26 @@
  */
 static int display_error_message()
 {
-    struct mdtp_fbimage *fbimg;
+	struct mdtp_fbimage *fbimg;
 
-    if (fb_config)
+	if (fb_config)
 	{
-        uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ALERT_MESSAGE),fb_config->width);
+		uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ALERT_MESSAGE),fb_config->width);
 		uint32_t y = ((fb_config->height)*ERROR_MESSAGE_RELATIVE_Y_LOCATION);
-        fbimg = mdtp_read_mmc_image(get_image_offset(ALERT_MESSAGE),get_image_width(ALERT_MESSAGE), get_image_height(ALERT_MESSAGE));
-        if (NULL == fbimg)
-        {
-            dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
-            return -1;
-        }
+		fbimg = mdtp_read_mmc_image(get_image_offset(ALERT_MESSAGE),get_image_width(ALERT_MESSAGE), get_image_height(ALERT_MESSAGE));
+		if (NULL == fbimg)
+		{
+			dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
+			return -1;
+		}
 
-        fbcon_putImage_in_location(fbimg, x, y);
+		fbcon_putImage_in_location(fbimg, x, y);
 
 		return 0;
 	}
 	else
 	{
-	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
 		return -1;
 	}
 }
@@ -284,24 +285,24 @@
  */
 static void display_image(uint32_t offset, uint32_t width, uint32_t height, uint32_t x, uint32_t y)
 {
-    struct mdtp_fbimage *fbimg;
+	struct mdtp_fbimage *fbimg;
 
-    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(); /* This will never return */
-        }
+	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(); /* This will never return */
+		}
 
-        fbcon_putImage_in_location(fbimg, x, y);
-    }
-    else
-    {
-        dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
-        display_error_msg(); /* This will never return */
-    }
+		fbcon_putImage_in_location(fbimg, x, y);
+	}
+	else
+	{
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		display_error_msg(); /* This will never return */
+	}
 }
 
 /**
@@ -329,7 +330,7 @@
  */
 static void display_invalid_pin()
 {
-    uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(MAINTEXT_INCORRECTPIN),fb_config->width);
+	uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(MAINTEXT_INCORRECTPIN),fb_config->width);
 	uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(MAINTEXT_INCORRECTPIN), get_image_width(MAINTEXT_INCORRECTPIN), get_image_height(MAINTEXT_INCORRECTPIN), x, y);
@@ -340,7 +341,7 @@
  */
 static void display_digits_instructions()
 {
-    uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(PINTEXT),fb_config->width);
+	uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(PINTEXT),fb_config->width);
 	uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(PINTEXT), get_image_width(PINTEXT), get_image_height(PINTEXT), x, y);
@@ -351,8 +352,8 @@
  */
 static void clear_digits_instructions()
 {
-    uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
-    fbcon_clear_section(y, get_image_height(PINTEXT));
+	uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
+	fbcon_clear_section(y, get_image_height(PINTEXT));
 }
 
 /**
@@ -360,8 +361,11 @@
  */
 static void display_digit(uint32_t x, uint32_t y, uint32_t digit)
 {
-    display_image(get_image_offset(PIN_UNSELECTED_0 + digit),
-    get_image_width(PIN_UNSELECTED_0 + digit), get_image_height(PIN_UNSELECTED_0 + digit), x, y);
+	if (g_diplay_pin == false)
+		return;
+
+	display_image(get_image_offset(PIN_UNSELECTED_0 + digit),
+			get_image_width(PIN_UNSELECTED_0 + digit), get_image_height(PIN_UNSELECTED_0 + digit), x, y);
 }
 
 /**
@@ -369,6 +373,9 @@
  */
 static void display_selected_digit(uint32_t x, uint32_t y, uint32_t digit)
 {
+	if (g_diplay_pin == false)
+		return;
+
 	display_image(get_image_offset(PIN_SELECTED_0 + digit),
 			get_image_width(PIN_SELECTED_0 + digit),
 			get_image_height(PIN_SELECTED_0 + digit), x, y);
@@ -379,7 +386,7 @@
  */
 static void display_ok_button()
 {
-    uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_OFF),fb_config->width);
+	uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_OFF),fb_config->width);
 	uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(BTN_OK_OFF), get_image_width(BTN_OK_OFF),get_image_height(BTN_OK_OFF), ok_x, ok_y);
@@ -390,7 +397,7 @@
  */
 static void display_selected_ok_button()
 {
-    uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_ON),fb_config->width);
+	uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_ON),fb_config->width);
 	uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(BTN_OK_ON), get_image_width(BTN_OK_ON), get_image_height(BTN_OK_ON),  ok_x, ok_y);
@@ -402,7 +409,7 @@
  */
 static void display_pin_instructions()
 {
-    uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ACCEPTEDIT_TEXT),fb_config->width);
+	uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ACCEPTEDIT_TEXT),fb_config->width);
 	uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(ACCEPTEDIT_TEXT), get_image_width(ACCEPTEDIT_TEXT), get_image_height(ACCEPTEDIT_TEXT), x, y);
@@ -413,7 +420,7 @@
  */
 static void clear_pin_message()
 {
-    uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
+	uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
 
 	fbcon_clear_section(y,get_image_height(ACCEPTEDIT_TEXT));
 }
@@ -442,7 +449,7 @@
 		fbcon_clear();
 
 		if (display_error_message())
-		    display_error_msg(); /* This will never return */
+			display_error_msg(); /* This will never return */
 		display_initial_delay();
 
 		mdelay(INITIAL_DELAY_MSECONDS);
@@ -450,16 +457,26 @@
 		g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION);
 
 		uint32_t total_pin_length = pin_length*get_image_width(PIN_UNSELECTED_0) + mdtp_fs_get_param(DIGIT_SPACE)*(pin_length - 1);
-		uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
 
-		for (uint32_t i=0; i<pin_length; i++)
+		if (fb_config->width > total_pin_length)
 		{
-			g_pin_frames_x_location[i] = complete_pin_centered + i*(mdtp_fs_get_param(DIGIT_SPACE) + get_image_width(PIN_UNSELECTED_0));
+			g_diplay_pin = true;
+
+			uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
+
+			for (uint32_t i=0; i<pin_length; i++)
+			{
+				g_pin_frames_x_location[i] = complete_pin_centered + i*(mdtp_fs_get_param(DIGIT_SPACE) + get_image_width(PIN_UNSELECTED_0));
+			}
+
+			for (uint32_t i=0; i<pin_length; i++)
+			{
+				display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
+			}
 		}
-
-		for (uint32_t i=0; i<pin_length; i++)
+		else
 		{
-			display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
+			dprintf(CRITICAL,"ERROR: screen is not wide enough, PIN digits can't be displayed\n");
 		}
 
 		display_ok_button();
@@ -468,8 +485,8 @@
 	}
 	else
 	{
-	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
-	    display_error_msg(); /* This will never return */
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		display_error_msg(); /* This will never return */
 	}
 }
 
@@ -574,12 +591,12 @@
  */
 void display_invalid_pin_msg()
 {
-    clear_pin_message();
-    display_ok_button();
+	clear_pin_message();
+	display_ok_button();
 
-    display_invalid_pin();
+	display_invalid_pin();
 
-    mdelay(INVALID_PIN_DELAY_MSECONDS);
+	mdelay(INVALID_PIN_DELAY_MSECONDS);
 }
 
 /**
diff --git a/dev/qpnp_wled/qpnp_wled.c b/dev/qpnp_wled/qpnp_wled.c
index 9cedbb7..3aa41f8 100644
--- a/dev/qpnp_wled/qpnp_wled.c
+++ b/dev/qpnp_wled/qpnp_wled.c
@@ -522,7 +522,7 @@
 			wled->strings[i] = i;
 
 	wled->ibb_bias_active = false;
-	wled->lab_fast_precharge = true;
+	wled->lab_fast_precharge = false;
 	wled->ibb_pwrup_dly_ms = config->pwr_up_delay;
 	wled->ibb_pwrdn_dly_ms = config->pwr_down_delay;
 	wled->ibb_discharge_en = config->ibb_discharge_en;
diff --git a/include/dev/flash.h b/include/dev/flash.h
index 9c41561..f908db8 100644
--- a/include/dev/flash.h
+++ b/include/dev/flash.h
@@ -77,6 +77,8 @@
 {
 	return flash_read_ext(ptn, 0, offset, data, bytes);
 }
+
+unsigned flash_num_pages_per_blk(void);
 unsigned flash_page_size(void);
 unsigned flash_block_size(void);
 unsigned flash_spare_size(void);
diff --git a/include/target.h b/include/target.h
index 17c0c0e..d0d830d 100644
--- a/include/target.h
+++ b/include/target.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2008 Travis Geiselbrecht
  *
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files
@@ -26,6 +26,7 @@
 #define __TARGET_H
 #include <qmp_phy.h>
 
+#define TARGET_MAX_CMDLNBUF 64
 /* Target helper functions exposed to USB driver */
 typedef struct {
 	void (*mux_config) ();
@@ -69,6 +70,7 @@
 
 const char * target_usb_controller();
 void target_usb_phy_reset(void);
+void target_usb_phy_sec_reset(void);
 void target_usb_phy_mux_configure(void);
 target_usb_iface_t * target_usb30_init();
 bool target_is_cdp_qvga();
@@ -104,4 +106,5 @@
 bool target_battery_soc_ok();
 bool target_battery_is_present();
 uint32_t target_get_pmic();
+int target_update_cmdline(char *cmdline);
 #endif
diff --git a/lib/heap/heap.c b/lib/heap/heap.c
index a4835f9..2f41f6c 100644
--- a/lib/heap/heap.c
+++ b/lib/heap/heap.c
@@ -156,19 +156,19 @@
 // nearby ones if possible. Returns base of whatever chunk it became in the list.
 static struct free_heap_chunk *heap_insert_free_chunk(struct free_heap_chunk *chunk)
 {
-#if DEBUGLEVEL > INFO
+#if DEBUG_HEAP
 	vaddr_t chunk_end = (vaddr_t)chunk + chunk->len;
+	dprintf(CRITICAL,"%s: chunk ptr %p, size 0x%lx, chunk_end 0x%x\n",
+				__FUNCTION__, chunk, chunk->len, chunk_end);
 #endif
 
-//	dprintf("%s: chunk ptr %p, size 0x%lx, chunk_end 0x%x\n", __FUNCTION__, chunk, chunk->len, chunk_end);
-
 	struct free_heap_chunk *next_chunk;
 	struct free_heap_chunk *last_chunk;
 
 	// walk through the list, finding the node to insert before
 	list_for_every_entry(&theheap.free_list, next_chunk, struct free_heap_chunk, node) {
 		if (chunk < next_chunk) {
-			DEBUG_ASSERT(chunk_end <= (vaddr_t)next_chunk);
+			DEBUG_ASSERT(((vaddr_t)chunk + chunk->len) <= (vaddr_t)next_chunk);
 
 			list_add_before(&next_chunk->node, &chunk->node);
 
diff --git a/lib/libc/string/strlcat.c b/lib/libc/string/strlcat.c
index 5e3488d..a505c59 100644
--- a/lib/libc/string/strlcat.c
+++ b/lib/libc/string/strlcat.c
@@ -40,7 +40,7 @@
 
 	dst+= j;
 
-	for(i= 0; ((i< s-1) && src[i]); i++) {
+	for(i= 0; ((i< s-j) && src[i]); i++) {
 		dst[i]= src[i];
 	}
 
diff --git a/platform/msm8952/platform.c b/platform/msm8952/platform.c
index 251bbb9..df7bbfa 100644
--- a/platform/msm8952/platform.c
+++ b/platform/msm8952/platform.c
@@ -205,6 +205,7 @@
 	switch(platform)
 	{
 		case MSM8937:
+		case MSM8940:
 		case APQ8037:
 			ret = 1;
 			break;
diff --git a/platform/msm8996/acpuclock.c b/platform/msm8996/acpuclock.c
index 7ed7ff6..5d2e7eb 100644
--- a/platform/msm8996/acpuclock.c
+++ b/platform/msm8996/acpuclock.c
@@ -208,6 +208,40 @@
 	writel(reg, GCC_USB30_GDSCR);
 }
 
+/* enables usb20 clocks */
+void clock_usb20_init(void)
+{
+	int ret;
+
+	ret = clk_get_set_enable("usb20_noc_usb20_clk", 0, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb20_noc_clk. ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb20_master_clk", 120000000, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb20_master_clk. ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb20_mock_utmi_clk", 60000000, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb20_mock_utmi_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb20_sleep_clk", 0, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb2_sleep_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
 /* enables usb30 clocks */
 void clock_usb30_init(void)
 {
diff --git a/platform/msm8996/include/platform/clock.h b/platform/msm8996/include/platform/clock.h
index 01a551e..6ff55e2 100644
--- a/platform/msm8996/include/platform/clock.h
+++ b/platform/msm8996/include/platform/clock.h
@@ -111,6 +111,7 @@
 void clock_ce_enable(uint8_t instance);
 void clock_ce_disable(uint8_t instance);
 void clock_usb30_init(void);
+void clock_usb20_init(void);
 void clock_reset_usb_phy();
 
 void mmss_dsi_clock_enable(uint32_t cfg_rcgr, uint32_t dual_dsi);
diff --git a/platform/msm8996/include/platform/iomap.h b/platform/msm8996/include/platform/iomap.h
index 2fb9c8a..42ef8a7 100644
--- a/platform/msm8996/include/platform/iomap.h
+++ b/platform/msm8996/include/platform/iomap.h
@@ -75,15 +75,33 @@
 #define GCC_BLSP2_QUP2_CFG_RCGR     (CLK_CTL_BASE + 0x28010)
 #define GCC_BLSP2_QUP2_CMD_RCGR     (CLK_CTL_BASE + 0x2800C)
 
+/* USB platform specific bases*/
+unsigned int usb_ctrl_base();
+unsigned int usb_qscratch_base();
+unsigned int usb_phy_base();
+unsigned int usb_phy_bcr();
+
+#define MSM_USB30_BASE              (usb_ctrl_base())
+#define MSM_USB30_QSCRATCH_BASE     (usb_qscratch_base())
+#define QUSB2_PHY_BASE              (usb_phy_base())
+#define GCC_QUSB2_PHY_BCR           (usb_phy_bcr())
+
 /* USB3.0 */
-#define MSM_USB30_BASE              0x6A00000
-#define MSM_USB30_QSCRATCH_BASE     0x6AF8800
+#define MSM_USB30_PRIM_BASE              0x6A00000
+#define MSM_USB30_QSCRATCH_PRIM_BASE     0x6AF8800
+/* USB2.0 */
+#define MSM_USB20_SEC_BASE              0x7600000
+#define MSM_USB20_SEC_QSCRATCH_BASE     0x76F8800
 /* SS QMP (Qulacomm Multi Protocol) */
 #define QMP_PHY_BASE                0x7410000
 
-/* QUSB2 PHY */
-#define QUSB2_PHY_BASE              0x7411000
-#define GCC_QUSB2_PHY_BCR           (CLK_CTL_BASE + 0x00012038)
+/* QUSB2 PHY primary */
+#define QUSB2_PRIM_PHY_BASE              0x7411000
+#define GCC_QUSB2_PRIM_PHY_BCR           (CLK_CTL_BASE + 0x00012038)
+
+/* QUSB2 PHY secondary */
+#define QUSB2_SEC_PHY_BASE              0x7412000
+#define GCC_QUSB2_SEC_PHY_BCR           (CLK_CTL_BASE + 0x0001203C)
 
 #define AHB2_PHY_BASE               0x7416000
 #define PERIPH_SS_AHB2PHY_TOP_CFG   (AHB2_PHY_BASE + 0x10)
@@ -138,6 +156,20 @@
 #define USB_PHY_CFG_AHB2PHY_CBCR    (CLK_CTL_BASE + 0x6A004)
 #define GCC_AGGRE2_USB3_AXI_CBCR    (CLK_CTL_BASE + 0x83018)
 
+/* USB20 clocks */
+#define USB_20_BCR                  (CLK_CTL_BASE + 0x12000)
+#define USB20_MASTER_CBCR           (CLK_CTL_BASE + 0x12004)
+#define USB20_SLEEP_CBCR            (CLK_CTL_BASE + 0x12008)
+#define USB20_MOCK_UTMI_CBCR        (CLK_CTL_BASE + 0x1200C)
+#define USB20_MASTER_CMD_RCGR       (CLK_CTL_BASE + 0x12010)
+#define USB20_MASTER_CFG_RCGR       (CLK_CTL_BASE + 0x12014)
+#define USB20_MASTER_M              (CLK_CTL_BASE + 0x12018)
+#define USB20_MASTER_N              (CLK_CTL_BASE + 0x1201c)
+#define USB20_MASTER_D              (CLK_CTL_BASE + 0x12020)
+#define USB20_MOCK_UTMI_CMD_RCGR    (CLK_CTL_BASE + 0x12024)
+#define USB20_MOCK_UTMI_CFG_RCGR    (CLK_CTL_BASE + 0x12028)
+#define PERIPH_NOC_USB20_AHB_CBCR   (CLK_CTL_BASE + 0x06010)
+
 /* SDCC */
 #define SDCC1_BCR                   (CLK_CTL_BASE + 0x13000) /* block reset */
 #define SDCC1_APPS_CBCR             (CLK_CTL_BASE + 0x13004) /* branch control */
@@ -209,7 +241,7 @@
  * as device memory, define the start address
  * and size in MB
  */
-#define RPMB_SND_RCV_BUF            0x91A00000
+#define RPMB_SND_RCV_BUF            0x91C00000
 #define RPMB_SND_RCV_BUF_SZ         0x2
 
 #define TCSR_BOOT_MISC_DETECT       0x007B3000
diff --git a/platform/msm8996/include/platform/irqs.h b/platform/msm8996/include/platform/irqs.h
index 61d267b..e5cc23d 100644
--- a/platform/msm8996/include/platform/irqs.h
+++ b/platform/msm8996/include/platform/irqs.h
@@ -45,7 +45,13 @@
 
 #define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP      (GIC_SPI_START + 31)
 
-#define USB30_EE1_IRQ                          (GIC_SPI_START + 131)
+/* to support secondary port usage, secondary port Interrupt*/
+int usb_irq();
+
+#define USB30_EE1_IRQ  			   (usb_irq())
+
+#define USB30_IRQ                          (GIC_SPI_START + 131)
+#define USB20_IRQ                          (GIC_SPI_START + 138)
 
 #define GLINK_IPC_IRQ                          (GIC_SPI_START + 168)
 
diff --git a/platform/msm8996/msm8996-clock.c b/platform/msm8996/msm8996-clock.c
index 782a624..8a02900 100644
--- a/platform/msm8996/msm8996-clock.c
+++ b/platform/msm8996/msm8996-clock.c
@@ -335,6 +335,16 @@
 	},
 };
 
+static struct branch_clk gcc_periph_noc_usb20_ahb_clk = {
+	.cbcr_reg    = (uint32_t *) PERIPH_NOC_USB20_AHB_CBCR,
+	.has_sibling = 1,
+
+	.c = {
+		.dbg_name = "periph_noc_usb20_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
 	F(  19200000, cxo,    1,    0,    0),
 	F( 120000000, gpll0,    5,    0,    0),
@@ -342,6 +352,13 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_usb20_master_clk[] = {
+	F(  19200000, cxo,    1,    0,    0),
+	F( 120000000, gpll0,    5,    0,    0),
+	F( 150000000, gpll0,    4,    0,    0),
+	F_END
+};
+
 static struct rcg_clk usb30_master_clk_src = {
 	.cmd_reg      = (uint32_t *) USB30_MASTER_CMD_RCGR,
 	.cfg_reg      = (uint32_t *) USB30_MASTER_CFG_RCGR,
@@ -359,6 +376,23 @@
 	},
 };
 
+static struct rcg_clk usb20_master_clk_src = {
+	.cmd_reg      = (uint32_t *) USB20_MASTER_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) USB20_MASTER_CFG_RCGR,
+	.m_reg        = (uint32_t *) USB20_MASTER_M,
+	.n_reg        = (uint32_t *) USB20_MASTER_N,
+	.d_reg        = (uint32_t *) USB20_MASTER_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_usb20_master_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "usb20_master_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
 static struct branch_clk gcc_usb30_master_clk = {
 	.cbcr_reg = (uint32_t *) USB30_MASTER_CBCR,
 	.bcr_reg  = (uint32_t *) USB_30_BCR,
@@ -370,6 +404,17 @@
 	},
 };
 
+static struct branch_clk gcc_usb20_master_clk = {
+	.cbcr_reg = (uint32_t *) USB20_MASTER_CBCR,
+	.bcr_reg  = (uint32_t *) USB_20_BCR,
+	.parent   = &usb20_master_clk_src.c,
+
+	.c = {
+		.dbg_name = "usb20_master_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct branch_clk gcc_aggre2_usb3_axi_clk = {
 	.cbcr_reg     = (uint32_t *) GCC_AGGRE2_USB3_AXI_CBCR,
 	.parent       = &usb30_master_clk_src.c,
@@ -385,6 +430,11 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_usb20_mock_utmi_clk_src[] = {
+	F(  60000000, gpll0,   10,    0,     0),
+	F_END
+};
+
 static struct rcg_clk usb30_mock_utmi_clk_src = {
 	.cmd_reg      = (uint32_t *) USB30_MOCK_UTMI_CMD_RCGR,
 	.cfg_reg      = (uint32_t *) USB30_MOCK_UTMI_CFG_RCGR,
@@ -398,6 +448,19 @@
 	},
 };
 
+static struct rcg_clk usb20_mock_utmi_clk_src = {
+	.cmd_reg      = (uint32_t *) USB20_MOCK_UTMI_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) USB20_MOCK_UTMI_CFG_RCGR,
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_gcc_usb20_mock_utmi_clk_src,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "usb20_mock_utmi_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
 static struct branch_clk gcc_usb30_mock_utmi_clk = {
 	.cbcr_reg    = (uint32_t *) USB30_MOCK_UTMI_CBCR,
 	.has_sibling = 0,
@@ -409,6 +472,18 @@
 	},
 };
 
+static struct branch_clk gcc_usb20_mock_utmi_clk = {
+	.cbcr_reg    = (uint32_t *) USB20_MOCK_UTMI_CBCR,
+	.has_sibling = 0,
+	.parent      = &usb20_mock_utmi_clk_src.c,
+
+	.c = {
+		.dbg_name = "usb20_mock_utmi_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+
 static struct branch_clk gcc_usb30_sleep_clk = {
 	.cbcr_reg    = (uint32_t *) USB30_SLEEP_CBCR,
 	.has_sibling = 1,
@@ -419,6 +494,16 @@
 	},
 };
 
+static struct branch_clk gcc_usb20_sleep_clk = {
+	.cbcr_reg    = (uint32_t *) USB20_SLEEP_CBCR,
+	.has_sibling = 1,
+
+	.c = {
+		.dbg_name = "usb20_sleep_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct clk_freq_tbl ftbl_gcc_usb30_phy_aux_clk_src[] = {
 	F(   1200000,         cxo,   16,    0,     0),
 	F_END
@@ -750,6 +835,12 @@
 
 	CLK_LOOKUP("usb_phy_cfg_ahb2phy_clk",     gcc_usb_phy_cfg_ahb2phy_clk.c),
 
+	/* USB20 clocks */
+	CLK_LOOKUP("usb20_noc_usb20_clk",     gcc_periph_noc_usb20_ahb_clk.c),
+	CLK_LOOKUP("usb20_master_clk",    gcc_usb20_master_clk.c),
+	CLK_LOOKUP("usb20_mock_utmi_clk", gcc_usb20_mock_utmi_clk.c),
+	CLK_LOOKUP("usb20_sleep_clk",     gcc_usb20_sleep_clk.c),
+
 	/* mdss clocks */
 	CLK_LOOKUP("mdss_mdp_clk",     mdss_mdp_clk.c),
 	CLK_LOOKUP("mdss_vsync_clk",       mdss_vsync_clk.c),
diff --git a/platform/msm8996/platform.c b/platform/msm8996/platform.c
index 79bf7c9..a3c2d3e 100644
--- a/platform/msm8996/platform.c
+++ b/platform/msm8996/platform.c
@@ -181,3 +181,46 @@
 
 	return false;
 }
+
+
+/* USB platform specific bases*/
+uint32_t usb_ctrl_base()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	MSM_USB20_SEC_BASE;
+	else
+		return	MSM_USB30_PRIM_BASE;
+
+}
+
+uint32_t usb_qscratch_base()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	MSM_USB20_SEC_QSCRATCH_BASE;
+	else
+		return	MSM_USB30_QSCRATCH_PRIM_BASE;
+}
+
+uint32_t usb_phy_base()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	QUSB2_SEC_PHY_BASE;
+	else
+		return	QUSB2_PRIM_PHY_BASE;
+}
+
+uint32_t usb_phy_bcr()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	GCC_QUSB2_SEC_PHY_BCR;
+	else
+		return	GCC_QUSB2_PRIM_PHY_BCR;
+}
+
+int usb_irq()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	USB20_IRQ;
+	else
+		return	USB30_IRQ;
+}
diff --git a/platform/msm_shared/display_menu.c b/platform/msm_shared/display_menu.c
index fb4e0a8..cea4937 100644
--- a/platform/msm_shared/display_menu.c
+++ b/platform/msm_shared/display_menu.c
@@ -257,12 +257,16 @@
 
 	/* Align Right */
 	str_target = str_align_right(str1, big_factor);
-	if(str_target != NULL)
+	if(str_target != NULL) {
 		display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, big_factor);
+		free(str_target);
+	}
 
 	str_target = str_align_right(str2, common_factor);
-	if(str_target != NULL)
+	if(str_target != NULL) {
 		display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, common_factor);
+		free(str_target);
+	}
 
 	display_fbcon_menu_message("\n< More options\n",
 		FBCON_COMMON_MSG, common_factor);
@@ -296,9 +300,6 @@
 		"Your device will boot in 5 seconds\n\n", FBCON_COMMON_MSG, common_factor);
 
 	msg_info->info.msg_type = type;
-	if(str_target) {
-		free(str_target);
-	}
 
 	/* Initialize the time out time */
 	msg_info->info.timeout_time = 5000; //5s
diff --git a/platform/msm_shared/dme.c b/platform/msm_shared/dme.c
index c6d651d..c98730b 100644
--- a/platform/msm_shared/dme.c
+++ b/platform/msm_shared/dme.c
@@ -493,13 +493,20 @@
 		return -UFS_FAILURE;
 	}
 
-	dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt);
-
-	dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size);
-
 	// use only the lower 32 bits for rpmb partition size
 	if (index == UFS_WLUN_RPMB)
 		dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32);
+	/*
+	 rpmb will not use blk count and blk size from lun_cfg as it has
+	 its own entries in ufs_dev structure
+	*/
+	else
+	{
+		dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt);
+		dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size);
+	}
+
+
 
 	return UFS_SUCCESS;
 }
diff --git a/platform/msm_shared/partition_parser.c b/platform/msm_shared/partition_parser.c
index 65d58d4..22be711 100644
--- a/platform/msm_shared/partition_parser.c
+++ b/platform/msm_shared/partition_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, 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
@@ -454,6 +454,7 @@
 static unsigned int write_mbr(uint32_t size, uint8_t *mbrImage, uint32_t block_size)
 {
 	unsigned int ret;
+	uint64_t device_density;
 
 	/* Verify that passed in block is a valid MBR */
 	ret = partition_verify_mbr_signature(size, mbrImage);
@@ -461,6 +462,15 @@
 		goto end;
 	}
 
+	device_density = mmc_get_device_capacity();
+
+	/* Erasing the eMMC card before writing */
+	ret = mmc_erase_card(0x00000000, device_density);
+	if (ret) {
+		dprintf(CRITICAL, "Failed to erase the eMMC card\n");
+		goto end;
+	}
+
 	/* Write the MBR/EBR to mmc */
 	ret = write_mbr_in_blocks(size, mbrImage, block_size);
 	if (ret) {
diff --git a/platform/msm_shared/qpic_nand.c b/platform/msm_shared/qpic_nand.c
index baba30d..3fec647 100644
--- a/platform/msm_shared/qpic_nand.c
+++ b/platform/msm_shared/qpic_nand.c
@@ -1378,6 +1378,12 @@
 }
 
 unsigned
+flash_num_pages_per_blk(void)
+{
+	return flash.num_pages_per_blk;
+}
+
+unsigned
 flash_spare_size(void)
 {
     return flash.spare_size;
diff --git a/platform/msm_shared/rpm-glink.c b/platform/msm_shared/rpm-glink.c
index 2635cd1..f564480 100644
--- a/platform/msm_shared/rpm-glink.c
+++ b/platform/msm_shared/rpm-glink.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016 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
@@ -59,6 +59,19 @@
 
 extern glink_err_type glink_wait_link_down(glink_handle_type handle);
 
+static void rpmdatacpy(uint32_t * dst, uint32_t *src, uint32_t size)
+{
+	if(size%4)
+		ASSERT(0);
+	size = size/4;
+
+	while (size >0)
+	{
+		*dst++ = *src++;
+		size--;
+	}
+}
+
 glink_err_type rpm_glink_send_data(uint32_t *data, uint32_t len, msg_type type)
 {
 	rpm_req req;
@@ -198,7 +211,7 @@
 		return_buffer = vprovider(buffer, offset, &return_size);
 		if(return_buffer)
 		{
-			memcpy(rx_buffer+offset,return_buffer, return_size);
+			rpmdatacpy((uint32_t *)(rx_buffer + offset),(uint32_t *)return_buffer, return_size);
 			offset += return_size;
 		}
 	} while(return_buffer);
@@ -241,7 +254,7 @@
 		return_buffer = vprovider(buffer, offset, &return_size);
 		if(return_buffer)
 		{
-			memcpy(rx_buffer+offset,return_buffer, return_size);
+			rpmdatacpy((uint32_t *)(rx_buffer + offset),(uint32_t *)return_buffer, return_size);
 			offset += return_size;
 		}
 	} while(return_buffer);
diff --git a/platform/msm_shared/sdhci.c b/platform/msm_shared/sdhci.c
index c0f307e..aca1a9d 100644
--- a/platform/msm_shared/sdhci.c
+++ b/platform/msm_shared/sdhci.c
@@ -437,9 +437,11 @@
 	uint64_t max_trans_retry = (cmd->cmd_timeout ? cmd->cmd_timeout : SDHCI_MAX_TRANS_RETRY);
 
 	do {
+
 		int_status = REG_READ16(host, SDHCI_NRML_INT_STS_REG);
 
-		if (int_status  & SDHCI_INT_STS_CMD_COMPLETE)
+		if((int_status  & SDHCI_INT_STS_CMD_COMPLETE) &&
+			!(REG_READ16(host, SDHCI_ERR_INT_STS_REG) & SDHCI_CMD_TIMEOUT_MASK))
 			break;
 		/*
 		* Some controllers set the data timout first on issuing an erase & take time
diff --git a/platform/msm_shared/sdhci_msm.c b/platform/msm_shared/sdhci_msm.c
index d86baa6..1d4229a 100644
--- a/platform/msm_shared/sdhci_msm.c
+++ b/platform/msm_shared/sdhci_msm.c
@@ -780,7 +780,7 @@
 		if(err)
 		{
 
-			sts_retry = 5;
+			sts_retry = 50;
 			sts_cmd.cmd_index = CMD13_SEND_STATUS;
 			sts_cmd.argument = card->rca << 16;
 			sts_cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index d2e67d8..50193bd 100644
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -447,6 +447,7 @@
 	MSM8953  = 293,
 	MSM8937 = 294,
 	APQ8037 = 295,
+	MSM8940 = 313,
 	MSM8996L = 302,
 	MSM8917  = 303,
 	APQ8053 = 304,
diff --git a/project/msm8996.mk b/project/msm8996.mk
index 50ec0b7..8278849 100644
--- a/project/msm8996.mk
+++ b/project/msm8996.mk
@@ -136,3 +136,5 @@
 ifeq ($(ENABLE_WDOG_SUPPORT),1)
 DEFINES += WDOG_SUPPORT=1
 endif
+# Target specific command line
+DEFINES += TARGET_CMDLINE_SUPPORT=1
diff --git a/target/init.c b/target/init.c
index ba2e608..22ddb16 100644
--- a/target/init.c
+++ b/target/init.c
@@ -269,6 +269,7 @@
 			config->vib_type = VIB_LRA_TYPE;
 			break;
 		case MSM8937:
+		case MSM8940:
 		case APQ8037:
 		case MSM8917:
 		case MSM8217:
diff --git a/target/msm8952/init.c b/target/msm8952/init.c
index 47d3d04..d085f30 100644
--- a/target/msm8952/init.c
+++ b/target/msm8952/init.c
@@ -398,6 +398,7 @@
 	case MSM8956:
 	case MSM8976:
 	case MSM8937:
+	case MSM8940:
 	case MSM8917:
 	case MSM8217:
 	case MSM8617:
diff --git a/target/msm8952/oem_panel.c b/target/msm8952/oem_panel.c
index e01dfd0..60be169 100755
--- a/target/msm8952/oem_panel.c
+++ b/target/msm8952/oem_panel.c
@@ -707,6 +707,7 @@
 		memcpy(phy_db->timing,
 				lead_fl10802_fwvga_video_timings, TIMING_SIZE);
 		pinfo->mipi.signature = LEAD_FL10802_FWVGA_VIDEO_SIGNATURE;
+		pinfo->mipi.cmds_post_tg = 1;
 		break;
 	case UNKNOWN_PANEL:
 	default:
diff --git a/target/msm8996/init.c b/target/msm8996/init.c
index 065bbfa..51051c9 100644
--- a/target/msm8996/init.c
+++ b/target/msm8996/init.c
@@ -500,6 +500,11 @@
 	qusb2_phy_reset();
 }
 
+void target_usb_phy_sec_reset()
+{
+	qusb2_phy_reset();
+}
+
 target_usb_iface_t* target_usb30_init()
 {
 	target_usb_iface_t *t_usb_iface;
@@ -507,9 +512,20 @@
 	t_usb_iface = calloc(1, sizeof(target_usb_iface_t));
 	ASSERT(t_usb_iface);
 
-	t_usb_iface->phy_init   = usb30_qmp_phy_init;
-	t_usb_iface->phy_reset  = target_usb_phy_reset;
-	t_usb_iface->clock_init = clock_usb30_init;
+
+	/* for SBC we use secondary port */
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+	{
+		/* secondary port have no QMP phy,use only QUSB2 phy that have only reset */
+		t_usb_iface->phy_init   = NULL;
+		t_usb_iface->phy_reset  = target_usb_phy_sec_reset;
+		t_usb_iface->clock_init = clock_usb20_init;
+	} else {
+		t_usb_iface->phy_init   = usb30_qmp_phy_init;
+		t_usb_iface->phy_reset  = target_usb_phy_reset;
+		t_usb_iface->clock_init = clock_usb30_init;
+	}
+
 	t_usb_iface->vbus_override = 1;
 
 	return t_usb_iface;
@@ -607,3 +623,22 @@
 {
 	return PMIC_IS_PMI8996;
 }
+
+int target_update_cmdline(char *cmdline)
+{
+	uint32_t platform_id = board_platform_id();
+	int len = 0;
+	if (platform_id == APQ8096SG || platform_id == MSM8996SG)
+	{
+		strlcpy(cmdline, " fpsimd.fpsimd_settings=0", TARGET_MAX_CMDLNBUF);
+		len = strlen (cmdline);
+
+		/* App settings are not required for other than v1.0 SoC */
+		if (board_soc_version() > 0x10000) {
+			strlcpy(cmdline + len, " app_setting.use_app_setting=0", TARGET_MAX_CMDLNBUF - len);
+			len = strlen (cmdline);
+		}
+	}
+
+	return len;
+}
diff --git a/target/msm8996/rules.mk b/target/msm8996/rules.mk
index e59bfc2..c6918f7 100644
--- a/target/msm8996/rules.mk
+++ b/target/msm8996/rules.mk
@@ -8,13 +8,13 @@
 
 PLATFORM := msm8996
 
-MEMBASE := 0x91600000 # SDRAM
+MEMBASE := 0x91800000 # SDRAM
 MEMSIZE := 0x00400000 # 4MB
 
 BASE_ADDR    := 0x0000000
 
-SCRATCH_ADDR := 0x91C00000
-SCRATCH_SIZE := 740
+SCRATCH_ADDR := 0x91E00000
+SCRATCH_SIZE := 738
 KERNEL_ADDR  := 0x80000000
 KERNEL_SIZE  := 88