stm32mp: stm32prog: add upport of partial update

Add support of partial update, update only some partitions,
and check the coherence of the layout with the existing GPT
partitions (offset and size).

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
index f630366..787bcde 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
@@ -481,8 +481,12 @@
 	struct mmc *mmc = NULL;
 	struct blk_desc *block_dev = NULL;
 	int part_id;
+	int ret;
 	u64 first_addr = 0, last_addr = 0;
 	struct stm32prog_part_t *part, *next_part;
+	u64 part_addr, part_size;
+	bool part_found;
+	const char *part_name;
 
 	switch (dev->target) {
 #ifdef CONFIG_MMC
@@ -515,6 +519,7 @@
 			 block_dev->lba, block_dev->blksz);
 		pr_debug(" available address = 0x%llx..0x%llx\n",
 			 first_addr, last_addr);
+		pr_debug(" full_update = %d\n", dev->full_update);
 		break;
 #endif
 	default:
@@ -522,6 +527,7 @@
 		return -ENODEV;
 	}
 	pr_debug(" erase size = 0x%x\n", dev->erase_size);
+	pr_debug(" full_update = %d\n", dev->full_update);
 
 	/* order partition list in offset order */
 	list_sort(NULL, &dev->part_list, &part_cmp);
@@ -598,6 +604,61 @@
 			 part->part_id, part->option, part->id, part->name,
 			 part->part_type, part->target,
 			 part->dev_id, part->addr, part->size);
+
+		part_addr = 0;
+		part_size = 0;
+		part_found = false;
+
+		/* check coherency with existing partition */
+		if (block_dev) {
+			/*
+			 * block devices with GPT: check user partition size
+			 * only for partial update, the GPT partions are be
+			 * created for full update
+			 */
+			if (dev->full_update || part->part_id < 0) {
+				pr_debug("\n");
+				continue;
+			}
+			disk_partition_t partinfo;
+
+			ret = part_get_info(block_dev, part->part_id,
+					    &partinfo);
+
+			if (ret) {
+				stm32prog_err("%s (0x%x):Couldn't find part %d on device mmc %d",
+					      part->name, part->id,
+					      part_id, part->dev_id);
+				return -ENODEV;
+			}
+			part_addr = (u64)partinfo.start * partinfo.blksz;
+			part_size = (u64)partinfo.size * partinfo.blksz;
+			part_name = (char *)partinfo.name;
+			part_found = true;
+		}
+
+		if (!part_found) {
+			stm32prog_err("%s (0x%x): Invalid partition",
+				      part->name, part->id);
+			pr_debug("\n");
+			continue;
+		}
+
+		pr_debug(" %08llx %08llx\n", part_addr, part_size);
+
+		if (part->addr != part_addr) {
+			stm32prog_err("%s (0x%x): Bad address for partition %d (%s) = 0x%llx <> 0x%llx expected",
+				      part->name, part->id, part->part_id,
+				      part_name, part->addr, part_addr);
+			return -ENODEV;
+		}
+		if (part->size != part_size) {
+			stm32prog_err("%s (0x%x): Bad size for partition %d (%s) at 0x%llx = 0x%llx <> 0x%llx expected",
+				      part->name, part->id, part->part_id,
+				      part_name, part->addr, part->size,
+				      part_size);
+			return -ENODEV;
+		}
 	}
 	return 0;
 }
@@ -644,6 +705,7 @@
 				/* new device found */
 				data->dev[j].target = part->target;
 				data->dev[j].dev_id = part->dev_id;
+				data->dev[j].full_update = true;
 				data->dev_nb++;
 				break;
 			} else if ((part->target == data->dev[j].target) &&
@@ -656,6 +718,8 @@
 			return -EINVAL;
 		}
 		part->dev = &data->dev[j];
+		if (!IS_SELECT(part))
+			part->dev->full_update = false;
 		list_add_tail(&part->list, &data->dev[j].part_list);
 	}
 
@@ -682,6 +746,11 @@
 	puts("partitions : ");
 	/* initialize the selected device */
 	for (i = 0; i < data->dev_nb; i++) {
+		/* create gpt partition support only for full update on MMC */
+		if (data->dev[i].target != STM32PROG_MMC ||
+		    !data->dev[i].full_update)
+			continue;
+
 		offset = 0;
 		rootfs_found = false;
 		memset(buf, 0, buflen);
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
index 6c3ad56..ea88459 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
@@ -69,6 +69,7 @@
 	struct mmc		*mmc;
 	/* list of partition for this device / ordered in offset */
 	struct list_head	part_list;
+	bool			full_update;
 };
 
 /* partition information build from FlashLayout and device */