aboot: mdtp: Add support to multiple resolutions

mdtp.img used to hold a single set of images,
designed for a specific screen size.
This change was added to support the new mdtp.img
format, which now includes multiple image sets, for
multiple screen resolutions. The correct image set
to display is determined in runtime, based on the
actual screen resolution.

Change-Id: I6577a412632ad50b08e7de10bf57a5891d736c28
CRs-Fixed: 1008298
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);
 }
 
 /**