platform: msm_shared: Add support to write protect devinfo

Add API to write protect devinfo for verified boot feature. As
part of this add the following functions to support this
* Add api to get read-only attribute of a partition
* Enable RST_n_FUNC of emmc for power-on write protect to work

Change-Id: I466d7ee447680bf5dd2782a6a09232d866251197
diff --git a/platform/msm_shared/include/mmc_sdhci.h b/platform/msm_shared/include/mmc_sdhci.h
index 0098c0e..5f5ba72 100644
--- a/platform/msm_shared/include/mmc_sdhci.h
+++ b/platform/msm_shared/include/mmc_sdhci.h
@@ -86,6 +86,7 @@
 
 /* EXT_CSD */
 /* Offsets in the ext csd */
+#define MMC_EXT_CSD_RST_N_FUNC                    162
 #define MMC_EXT_MMC_BUS_WIDTH                     183
 #define MMC_EXT_MMC_HS_TIMING                     185
 #define MMC_DEVICE_TYPE                           196
@@ -114,6 +115,7 @@
 #define MMC_SEC_COUNT3_SHIFT                      16
 #define MMC_SEC_COUNT2_SHIFT                      8
 #define MMC_HC_ERASE_MULT                         (512 * 1024)
+#define RST_N_FUNC_ENABLE                         BIT(0)
 
 /* Command related */
 #define MMC_MAX_COMMAND_RETRY                     1000
diff --git a/platform/msm_shared/include/mmc_wrapper.h b/platform/msm_shared/include/mmc_wrapper.h
index 57f74a0..f52a117 100644
--- a/platform/msm_shared/include/mmc_wrapper.h
+++ b/platform/msm_shared/include/mmc_wrapper.h
@@ -48,4 +48,5 @@
 void mmc_set_lun(uint8_t lun);
 uint8_t mmc_get_lun(void);
 void  mmc_read_partition_table(uint8_t arg);
+uint32_t mmc_write_protect(const char *name, int set_clr);
 #endif
diff --git a/platform/msm_shared/include/partition_parser.h b/platform/msm_shared/include/partition_parser.h
index a2d3edd..af69e03 100644
--- a/platform/msm_shared/include/partition_parser.h
+++ b/platform/msm_shared/include/partition_parser.h
@@ -73,6 +73,7 @@
 #define PARTITION_TYPE_GUID_SIZE   16
 #define UNIQUE_PARTITION_GUID_SIZE 16
 #define NUM_PARTITIONS             128
+#define PART_ATT_READONLY_OFFSET   60
 
 /* Some useful define used to access the MBR/EBR table */
 #define BLOCK_SIZE                0x200
@@ -179,5 +180,6 @@
 
 /* For Debugging */
 void partition_dump(void);
-
+/* Read only attribute for partition */
+int partition_read_only(int index);
 #endif
diff --git a/platform/msm_shared/mmc_sdhci.c b/platform/msm_shared/mmc_sdhci.c
index 411f22c..76145eb 100644
--- a/platform/msm_shared/mmc_sdhci.c
+++ b/platform/msm_shared/mmc_sdhci.c
@@ -1665,6 +1665,18 @@
 
 	card->block_size = MMC_BLK_SZ;
 
+	/* Enable RST_n_FUNCTION */
+	if (!card->ext_csd[MMC_EXT_CSD_RST_N_FUNC])
+	{
+		mmc_return = mmc_switch_cmd(host, card, MMC_SET_BIT, MMC_EXT_CSD_RST_N_FUNC, RST_N_FUNC_ENABLE);
+
+		if (mmc_return)
+		{
+			dprintf(CRITICAL, "Failed to enable RST_n_FUNCTION\n");
+			return mmc_return;
+		}
+	}
+
 	return mmc_return;
 }
 
diff --git a/platform/msm_shared/mmc_wrapper.c b/platform/msm_shared/mmc_wrapper.c
index c660a5f..12bcd4d 100755
--- a/platform/msm_shared/mmc_wrapper.c
+++ b/platform/msm_shared/mmc_wrapper.c
@@ -34,6 +34,7 @@
 #include <ufs.h>
 #include <target.h>
 #include <string.h>
+#include <partition_parser.h>
 
 /*
  * Weak function for UFS.
@@ -586,3 +587,56 @@
 		}
 	}
 }
+
+uint32_t mmc_write_protect(const char *ptn_name, int set_clr)
+{
+	void *dev = NULL;
+	struct mmc_card *card = NULL;
+	uint32_t block_size;
+	unsigned long long  ptn = 0;
+	uint64_t size;
+	int index = -1;
+	int ret = 0;
+
+	dev = target_mmc_device();
+	block_size = mmc_get_device_blocksize();
+
+	if (platform_boot_dev_isemmc())
+	{
+		card = &((struct mmc_device *)dev)->card;
+
+		index = partition_get_index(ptn_name);
+
+		ptn = partition_get_offset(index);
+		if(!ptn)
+		{
+			return 1;
+		}
+
+		size = partition_get_size(index);
+
+		/*
+		 * For read only partitions the minimum size allocated on the disk is
+		 * 1 WP GRP size. If the size of partition is less than 1 WP GRP size
+		 * protect atleast one WP group.
+		 */
+		if (partition_read_only(index) && size < card->wp_grp_size)
+		{
+			size = card->wp_grp_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
+	{
+		/* 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)
+		{
+			dprintf(CRITICAL, "Failure to WP UFS partition\n");
+			return 1;
+		}
+	}
+
+	return 0;
+}
diff --git a/platform/msm_shared/partition_parser.c b/platform/msm_shared/partition_parser.c
index d8774b9..d40fb8a 100644
--- a/platform/msm_shared/partition_parser.c
+++ b/platform/msm_shared/partition_parser.c
@@ -1057,3 +1057,8 @@
 {
 	return (gpt_partitions_exist != 0);
 }
+
+int partition_read_only(int index)
+{
+	 return partition_entries[index].attribute_flag >> PART_ATT_READONLY_OFFSET;
+}