Allow fastboot to flash mmc0boot0 and mmc0boot1

- Add the concept of "special partitions" to fb_mmc. This lets us alias
a specified name to a different hardware partition on the MMC.

Change-Id: I924216467011f768ff5bdaf27f0c48380ab4b923
diff --git a/configs/mt8516_coral_defconfig b/configs/mt8516_coral_defconfig
index e329cd2..3994293 100644
--- a/configs/mt8516_coral_defconfig
+++ b/configs/mt8516_coral_defconfig
@@ -51,6 +51,7 @@
 CONFIG_FASTBOOT_BUF_SIZE=0x4000000
 CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_GPT_NAME="mmc0"
 CONFIG_DM_GPIO=y
 # CONFIG_INPUT is not set
 CONFIG_DM_MMC=y
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
index b0b19c5..a824c22 100644
--- a/drivers/fastboot/fb_mmc.c
+++ b/drivers/fastboot/fb_mmc.c
@@ -25,6 +25,33 @@
 	struct blk_desc	*dev_desc;
 };
 
+struct special_partition {
+	char *name;
+	int idx;
+};
+struct special_partition special_partitions[] = {
+	{ "mmc0boot0", 1 },
+	{ "mmc0boot1", 2 },
+};
+
+static struct special_partition* get_special_partition(const char *name) {
+	for (int i = 0; i < ARRAY_SIZE(special_partitions); i++) {
+		struct special_partition *part = &special_partitions[i];
+		if (strcmp(name, part->name) == 0) {
+			return part;
+		}
+	}
+	return NULL;
+}
+
+static int switch_to_special_partition(struct special_partition *part) {
+	return blk_select_hwpart_devnum(IF_TYPE_MMC, CONFIG_FASTBOOT_FLASH_MMC_DEV, part->idx);
+}
+
+static void switch_to_main_partition(void) {
+	blk_select_hwpart_devnum(IF_TYPE_MMC, CONFIG_FASTBOOT_FLASH_MMC_DEV, 0);
+}
+
 static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc,
 		const char *name, disk_partition_t *info)
 {
@@ -101,9 +128,17 @@
 		const char *part_name, void *buffer,
 		u32 download_bytes, char *response)
 {
+	struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
 	lbaint_t blkcnt;
 	lbaint_t blks;
 
+	struct special_partition *part = get_special_partition(part_name);
+	if (part) {
+		info->blksz = dev_desc->blksz;
+		info->size = mmc->capacity_boot;
+		info->start = 0;
+	}
+
 	/* determine number of blocks to write */
 	blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1));
 	blkcnt = lldiv(blkcnt, info->blksz);
@@ -396,12 +431,20 @@
 	}
 #endif
 
-	if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
+	struct special_partition *part = get_special_partition(cmd);
+	if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0 && !part) {
 		pr_err("cannot find partition: '%s'\n", cmd);
 		fastboot_fail("cannot find partition", response);
 		return;
 	}
 
+	if (part) {
+		if (switch_to_special_partition(part)) {
+			pr_err("cannot switch to special partition: '%s'\n", cmd);
+			fastboot_fail("cannot switch partition", response);
+		}
+	}
+
 	if (is_sparse_image(download_buffer)) {
 		struct fb_mmc_sparse sparse_priv;
 		struct sparse_storage sparse;
@@ -428,6 +471,9 @@
 		write_raw_image(dev_desc, &info, cmd, download_buffer,
 				download_bytes, response);
 	}
+	if (part) {
+		switch_to_main_partition();
+	}
 }
 
 /**