msm_shared/smem_ptable: fix partition partition parsing logic

Existing code ignores the length field in the smem nand partition header
and fails when there are more than 16 partitions. This change uses
the length field to parse all nand partitions.

Change-Id: I2d2042cdfd5e6e0809d01607054c8fab857e5a45
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index 1179739..a873534 100755
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -2,7 +2,7 @@
  * Copyright (c) 2009, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, 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
@@ -250,6 +250,7 @@
 	HW_PLATFORM_FLUID = 3,
 	HW_PLATFORM_SVLTE = 4,
 	HW_PLATFORM_QT = 6,
+	HW_PLATFORM_MTP_MDM = 7,
 	HW_PLATFORM_MTP = 8,
 	HW_PLATFORM_LIQUID = 9,
 	HW_PLATFORM_DRAGON = 10,
@@ -377,8 +378,30 @@
 #define PWR_ON_EVENT_USB_CHG   0x20
 #define PWR_ON_EVENT_WALL_CHG  0x40
 
-unsigned smem_read_alloc_entry_offset(smem_mem_type_t type, void *buf, int len,
-				      int offset);
+#define SMEM_PTABLE_MAX_PARTS_V3  16
+#define SMEM_PTABLE_MAX_PARTS_V4  32
+#define SMEM_PTABLE_MAX_PARTS     SMEM_PTABLE_MAX_PARTS_V4
+
+#define SMEM_PTABLE_HDR_LEN    (4*sizeof(unsigned))
+
+struct smem_ptn {
+	char name[16];
+	unsigned start;
+	unsigned size;
+	unsigned attr;
+} __attribute__ ((__packed__));
+
+
+struct smem_ptable {
+#define _SMEM_PTABLE_MAGIC_1 0x55ee73aa
+#define _SMEM_PTABLE_MAGIC_2 0xe35ebddb
+	unsigned magic[2];
+	unsigned version;
+	unsigned len;
+	struct smem_ptn parts[SMEM_PTABLE_MAX_PARTS];
+} __attribute__ ((__packed__));
+
+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);
 
 #endif				/* __PLATFORM_MSM_SHARED_SMEM_H */
diff --git a/platform/msm_shared/smem_ptable.c b/platform/msm_shared/smem_ptable.c
index 149f06b..291b242 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-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, 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
@@ -11,7 +11,7 @@
  *    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 
+ *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -21,7 +21,7 @@
  * 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 
+ * 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
@@ -37,31 +37,16 @@
 
 #include "smem.h"
 
-struct smem_ptn {
-	char name[16];
-	unsigned start;
-	unsigned size;
-	unsigned attr;
-} __attribute__ ((__packed__));
-
-struct smem_ptable {
-#define _SMEM_PTABLE_MAGIC_1 0x55ee73aa
-#define _SMEM_PTABLE_MAGIC_2 0xe35ebddb
-	unsigned magic[2];
-	unsigned version;
-	unsigned len;
-	struct smem_ptn parts[16];
-} __attribute__ ((__packed__));
 
 /* partition table from SMEM */
 static struct smem_ptable smem_ptable;
-static unsigned smem_apps_flash_start;
+static unsigned smem_apps_flash_start = 0xFFFFFFFF;
 
 static void dump_smem_ptable(void)
 {
-	int i;
+	unsigned i;
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < smem_ptable.len; i++) {
 		struct smem_ptn *p = &smem_ptable.parts[i];
 		if (p->name[0] == '\0')
 			continue;
@@ -73,21 +58,55 @@
 void smem_ptable_init(void)
 {
 	unsigned i;
+	unsigned ret;
+	unsigned len;
 
-	smem_apps_flash_start = 0xffffffff;
+	/* Read only the header portion of ptable */
+	ret = smem_read_alloc_entry_offset(SMEM_AARM_PARTITION_TABLE,
+									   &smem_ptable,
+									   SMEM_PTABLE_HDR_LEN,
+									   0);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to read ptable hdr (%d)", ret);
+		ASSERT(0);
+	}
 
-	i = smem_read_alloc_entry(SMEM_AARM_PARTITION_TABLE,
-				  &smem_ptable, sizeof(smem_ptable));
-	if (i != 0)
-		return;
-
+	/* Verify ptable magic */
 	if (smem_ptable.magic[0] != _SMEM_PTABLE_MAGIC_1 ||
 	    smem_ptable.magic[1] != _SMEM_PTABLE_MAGIC_2)
 		return;
 
+	/* Ensure that # of partitions is less than the max we have allocated. */
+	ASSERT(smem_ptable.len <= SMEM_PTABLE_MAX_PARTS);
+
+	/* Find out length of partition data based on table version. */
+	if (smem_ptable.version <= 3)
+	{
+		len = SMEM_PTABLE_HDR_LEN + SMEM_PTABLE_MAX_PARTS_V3*sizeof(struct smem_ptn);
+	}
+	else if (smem_ptable.version == 4)
+	{
+		len = SMEM_PTABLE_HDR_LEN + SMEM_PTABLE_MAX_PARTS_V4*sizeof(struct smem_ptn);
+	}
+	else
+	{
+		dprintf(CRITICAL, "Unknown ptable version (%d)", smem_ptable.version);
+		ASSERT(0);
+	}
+
+	ret = smem_read_alloc_entry(SMEM_AARM_PARTITION_TABLE,
+								&smem_ptable,
+								len);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to read ptable (%d)", ret);
+		ASSERT(0);
+	}
+
 	dump_smem_ptable();
 	dprintf(INFO, "smem ptable found: ver: %d len: %d\n",
-		smem_ptable.version, smem_ptable.len);
+			smem_ptable.version, smem_ptable.len);
 
 	for (i = 0; i < smem_ptable.len; i++) {
 		if (!strcmp(smem_ptable.parts[i].name, "0:APPS"))
@@ -106,13 +125,13 @@
 
 void smem_add_modem_partitions(struct ptable *flash_ptable)
 {
-	int i;
+	unsigned i;
 
 	if (smem_ptable.magic[0] != _SMEM_PTABLE_MAGIC_1 ||
 	    smem_ptable.magic[1] != _SMEM_PTABLE_MAGIC_2)
 		return;
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < smem_ptable.len; i++) {
 		char *token;
 		char *pname = NULL;
 		struct smem_ptn *p = &smem_ptable.parts[i];