Merge changes from topic "stm32mp-emmc-boot-fip" into integration

* changes:
  feat(stm32mp1): extend STM32MP_EMMC_BOOT support to FIP format
  refactor(mmc): replace magic value with new PART_CFG_BOOT_PARTITION_NO_ACCESS
  refactor(mmc): export user/boot partition switch functions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index c327e71..0458733 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -755,29 +755,51 @@
 	return PART_CFG_CURRENT_BOOT_PARTITION(mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]);
 }
 
-size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size)
+int mmc_part_switch_current_boot(void)
 {
-	size_t size_read;
-	int ret;
 	unsigned char current_boot_part = mmc_current_boot_part();
+	int ret;
 
 	if (current_boot_part != 1U &&
 	    current_boot_part != 2U) {
 		ERROR("Got unexpected value for active boot partition, %u\n", current_boot_part);
-		return 0;
+		return -EIO;
 	}
 
 	ret = mmc_part_switch(current_boot_part);
 	if (ret < 0) {
 		ERROR("Failed to switch to boot partition, %d\n", ret);
+	}
+
+	return ret;
+}
+
+int mmc_part_switch_user(void)
+{
+	int ret;
+
+	ret = mmc_part_switch(PART_CFG_BOOT_PARTITION_NO_ACCESS);
+	if (ret < 0) {
+		ERROR("Failed to switch to user partition, %d\n", ret);
+	}
+
+	return ret;
+}
+
+size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size)
+{
+	size_t size_read;
+	int ret;
+
+	ret = mmc_part_switch_current_boot();
+	if (ret < 0) {
 		return 0;
 	}
 
 	size_read = mmc_read_blocks(lba, buf, size);
 
-	ret = mmc_part_switch(0);
+	ret = mmc_part_switch_user();
 	if (ret < 0) {
-		ERROR("Failed to switch back to user partition, %d\n", ret);
 		return 0;
 	}
 
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
index 834a80f..24a5502 100644
--- a/include/drivers/mmc.h
+++ b/include/drivers/mmc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -66,6 +66,7 @@
 #define EXT_CSD_PART_CONFIG_ACC_MASK	GENMASK(2, 0)
 #define PART_CFG_BOOT_PARTITION1_ENABLE	(U(1) << 3)
 #define PART_CFG_BOOT_PARTITION1_ACCESS (U(1) << 0)
+#define PART_CFG_BOOT_PARTITION_NO_ACCESS	U(0)
 #define PART_CFG_BOOT_PART_EN_MASK		GENMASK(5, 3)
 #define PART_CFG_BOOT_PART_EN_SHIFT		3
 #define PART_CFG_CURRENT_BOOT_PARTITION(x)	(((x) & PART_CFG_BOOT_PART_EN_MASK) >> \
@@ -236,6 +237,8 @@
 size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size);
 size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size);
 size_t mmc_rpmb_erase_blocks(int lba, size_t size);
+int mmc_part_switch_current_boot(void);
+int mmc_part_switch_user(void);
 size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size);
 int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
 	     unsigned int width, unsigned int flags,
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index b2038bc..94c36d9 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -122,6 +122,37 @@
 	return io_dev_init(storage_dev_handle, 0);
 }
 
+#if STM32MP_EMMC_BOOT
+static uint32_t get_boot_part_fip_header(void)
+{
+	io_block_spec_t emmc_boot_fip_block_spec = {
+		.offset = STM32MP_EMMC_BOOT_FIP_OFFSET,
+		.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
+	};
+	uint32_t magic = 0U;
+	int io_result;
+	size_t bytes_read;
+	uintptr_t fip_hdr_handle;
+
+	io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_fip_block_spec,
+			    &fip_hdr_handle);
+	assert(io_result == 0);
+
+	io_result = io_read(fip_hdr_handle, (uintptr_t)&magic, sizeof(magic),
+			    &bytes_read);
+	if ((io_result != 0) || (bytes_read != sizeof(magic))) {
+		panic();
+	}
+
+	io_close(fip_hdr_handle);
+
+	VERBOSE("%s: eMMC boot magic at offset 256K: %08x\n",
+		__func__, magic);
+
+	return magic;
+}
+#endif
+
 static void print_boot_device(boot_api_context_t *boot_context)
 {
 	switch (boot_context->boot_interface_selected) {
@@ -195,7 +226,7 @@
 		panic();
 	}
 
-	/* Open MMC as a block device to read GPT table */
+	/* Open MMC as a block device to read FIP */
 	io_result = register_io_dev_block(&mmc_dev_con);
 	if (io_result != 0) {
 		panic();
@@ -204,6 +235,25 @@
 	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
+
+#if STM32MP_EMMC_BOOT
+	if (mmc_dev_type == MMC_IS_EMMC) {
+		io_result = mmc_part_switch_current_boot();
+		assert(io_result == 0);
+
+		if (get_boot_part_fip_header() != TOC_HEADER_NAME) {
+			WARN("%s: Can't find FIP header on eMMC boot partition. Trying GPT\n",
+			     __func__);
+			io_result = mmc_part_switch_user();
+			assert(io_result == 0);
+			return;
+		}
+
+		VERBOSE("%s: FIP header found on eMMC boot partition\n",
+			__func__);
+		image_block_spec.offset = STM32MP_EMMC_BOOT_FIP_OFFSET;
+	}
+#endif
 }
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -385,8 +435,14 @@
 
 	switch (boot_itf) {
 #if STM32MP_SDMMC || STM32MP_EMMC
-	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+#if STM32MP_EMMC_BOOT
+		if (image_block_spec.offset == STM32MP_EMMC_BOOT_FIP_OFFSET) {
+			break;
+		}
+#endif
+		/* fallthrough */
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
 		if (!gpt_init_done) {
 /*
  * With FWU Multi Bank feature enabled, the selection of
diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h
index 7a277fd..2076175 100644
--- a/plat/st/stm32mp1/stm32mp1_fip_def.h
+++ b/plat/st/stm32mp1/stm32mp1_fip_def.h
@@ -98,8 +98,9 @@
 #endif
 
 /*******************************************************************************
- * STM32MP1 RAW partition offset for MTD devices
+ * STM32MP1 RAW partition offset for devices without GPT
  ******************************************************************************/
+#define STM32MP_EMMC_BOOT_FIP_OFFSET	U(0x00040000)
 #define STM32MP_NOR_FIP_OFFSET		U(0x00080000)
 #define STM32MP_NAND_FIP_OFFSET		U(0x00200000)