feat(stm32mp1): add FWU with boot from NOR-SPI

Refactor the SDCARD/EMMC FWU, to add the NOR-SPI use case.
SPI-NOR FWU won't use a real partition uuid to find the correct FIP,
but the UUID from metadata will correspond with a hardcoded offset in
the NOR.
While at it change some __unused keywords to __maybe_unused to ease
checkpatch.pl analysis.

Signed-off-by: Frank Bodammer <frank.bodammer@siemens.com>
Signed-off-by: Nicolas Toromanoff <nicolas.toromanoff@foss.st.com>
Signed-off-by: Yann Gautier <yann.gautier@st.com>
Change-Id: I2fe56ba8534a3c5dfaf8aeb16e7b286909883cc2
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index c935b7d..5b0a171 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -222,7 +222,7 @@
 static void boot_mmc(enum mmc_device_type mmc_dev_type,
 		     uint16_t boot_interface_instance)
 {
-	int io_result __unused;
+	int io_result __maybe_unused;
 	struct stm32_sdmmc2_params params;
 
 	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
@@ -294,7 +294,7 @@
 #if STM32MP_SPI_NOR
 static void boot_spi_nor(boot_api_context_t *boot_context)
 {
-	int io_result __unused;
+	int io_result __maybe_unused;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -313,7 +313,7 @@
 #if STM32MP_RAW_NAND
 static void boot_fmc2_nand(boot_api_context_t *boot_context)
 {
-	int io_result __unused;
+	int io_result __maybe_unused;
 
 	io_result = stm32_fmc2_init();
 	assert(io_result == 0);
@@ -332,7 +332,7 @@
 #if STM32MP_SPI_NAND
 static void boot_spi_nand(boot_api_context_t *boot_context)
 {
-	int io_result __unused;
+	int io_result __maybe_unused;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -351,7 +351,7 @@
 #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
 static void mmap_io_setup(void)
 {
-	int io_result __unused;
+	int io_result __maybe_unused;
 
 	io_result = register_io_dev_memmap(&memmap_dev_con);
 	assert(io_result == 0);
@@ -364,7 +364,7 @@
 #if STM32MP_UART_PROGRAMMER
 static void stm32cubeprogrammer_uart(void)
 {
-	int ret __unused;
+	int ret __maybe_unused;
 	boot_api_context_t *boot_context =
 		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
 	uintptr_t uart_base;
@@ -378,7 +378,7 @@
 #if STM32MP_USB_PROGRAMMER
 static void stm32cubeprogrammer_usb(void)
 {
-	int ret __unused;
+	int ret __maybe_unused;
 	struct usb_handle *pdev;
 
 	/* Init USB on platform */
@@ -390,10 +390,9 @@
 #endif
 #endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
 
-
 void stm32mp_io_setup(void)
 {
-	int io_result __unused;
+	int io_result __maybe_unused;
 	boot_api_context_t *boot_context =
 		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
 
@@ -473,7 +472,7 @@
 
 int bl2_plat_handle_pre_image_load(unsigned int image_id)
 {
-	static bool gpt_init_done __unused;
+	static bool gpt_init_done __maybe_unused;
 	uint16_t boot_itf = stm32mp_get_boot_itf_selected();
 
 	switch (boot_itf) {
@@ -516,6 +515,7 @@
 			gpt_init_done = true;
 		} else {
 			bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
 			assert(bl_mem_params != NULL);
 
 			mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
@@ -538,7 +538,14 @@
 
 #if STM32MP_SPI_NOR
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+/*
+ * With FWU Multi Bank feature enabled, the selection of
+ * the image to boot will be done by fwu_init calling the
+ * platform hook, plat_fwu_set_images_source.
+ */
+#if !PSA_FWU_SUPPORT
 		image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
+#endif
 		break;
 #endif
 
@@ -591,7 +598,7 @@
 	return rc;
 }
 
-#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
+#if (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT
 /*
  * In each boot in non-trial mode, we set the BKP register to
  * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
@@ -652,54 +659,108 @@
 {
 	unsigned int i;
 	uint32_t boot_idx;
-	const partition_entry_t *entry;
-	const uuid_t *img_type_uuid, *img_uuid;
+	const partition_entry_t *entry __maybe_unused;
+	const uuid_t *img_type_uuid;
+	const uuid_t *img_uuid __maybe_unused;
 	io_block_spec_t *image_spec;
+	const uint16_t boot_itf = stm32mp_get_boot_itf_selected();
 
 	boot_idx = plat_fwu_get_boot_idx();
 	assert(boot_idx < NR_OF_FW_BANKS);
 
 	for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
 		img_type_uuid = &metadata->img_entry[i].img_type_uuid;
+
+		img_uuid = &metadata->img_entry[i].img_props[boot_idx].img_uuid;
+
 		image_spec = stm32_get_image_spec(img_type_uuid);
 		if (image_spec == NULL) {
 			ERROR("Unable to get image spec for the image in the metadata\n");
 			panic();
 		}
 
-		img_uuid =
-			&metadata->img_entry[i].img_props[boot_idx].img_uuid;
+		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:
+			entry = get_partition_entry_by_uuid(img_uuid);
+			if (entry == NULL) {
+				ERROR("No partition with the uuid mentioned in metadata\n");
+				panic();
+			}
 
-		entry = get_partition_entry_by_uuid(img_uuid);
-		if (entry == NULL) {
-			ERROR("Unable to find the partition with the uuid mentioned in metadata\n");
+			image_spec->offset = entry->start;
+			image_spec->length = entry->length;
+			break;
+#endif
+#if STM32MP_SPI_NOR
+		case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+			if (guidcmp(img_uuid, &STM32MP_NOR_FIP_A_GUID) == 0) {
+				image_spec->offset = STM32MP_NOR_FIP_A_OFFSET;
+			} else if (guidcmp(img_uuid, &STM32MP_NOR_FIP_B_GUID) == 0) {
+				image_spec->offset = STM32MP_NOR_FIP_B_OFFSET;
+			} else {
+				ERROR("Invalid uuid mentioned in metadata\n");
+				panic();
+			}
+			break;
+#endif
+		default:
 			panic();
+			break;
 		}
-
-		image_spec->offset = entry->start;
-		image_spec->length = entry->length;
 	}
 }
 
 static int plat_set_image_source(unsigned int image_id,
 				 uintptr_t *handle,
-				 uintptr_t *image_spec,
-				 const char *part_name)
+				 uintptr_t *image_spec)
 {
 	struct plat_io_policy *policy;
-	io_block_spec_t *spec;
-	const partition_entry_t *entry = get_partition_entry(part_name);
-
-	if (entry == NULL) {
-		ERROR("Unable to find the %s partition\n", part_name);
-		return -ENOENT;
-	}
+	io_block_spec_t *spec __maybe_unused;
+	const partition_entry_t *entry __maybe_unused;
+	const uint16_t boot_itf = stm32mp_get_boot_itf_selected();
 
 	policy = &policies[image_id];
-
 	spec = (io_block_spec_t *)policy->image_spec;
-	spec->offset = entry->start;
-	spec->length = entry->length;
+
+	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:
+		partition_init(GPT_IMAGE_ID);
+
+		if (image_id == FWU_METADATA_IMAGE_ID) {
+			entry = get_partition_entry(METADATA_PART_1);
+		} else {
+			entry = get_partition_entry(METADATA_PART_2);
+		}
+
+		if (entry == NULL) {
+			ERROR("Unable to find a metadata partition\n");
+			return -ENOENT;
+		}
+
+		spec->offset = entry->start;
+		spec->length = entry->length;
+		break;
+#endif
+
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		if (image_id == FWU_METADATA_IMAGE_ID) {
+			spec->offset = STM32MP_NOR_METADATA1_OFFSET;
+		} else {
+			spec->offset = STM32MP_NOR_METADATA2_OFFSET;
+		}
+
+		spec->length = sizeof(struct fwu_metadata);
+		break;
+#endif
+	default:
+		panic();
+		break;
+	}
 
 	*image_spec = policy->image_spec;
 	*handle = *policy->dev_handle;
@@ -711,20 +772,9 @@
 				       uintptr_t *handle,
 				       uintptr_t *image_spec)
 {
-	char *part_name;
-
 	assert((image_id == FWU_METADATA_IMAGE_ID) ||
 	       (image_id == BKUP_FWU_METADATA_IMAGE_ID));
 
-	partition_init(GPT_IMAGE_ID);
-
-	if (image_id == FWU_METADATA_IMAGE_ID) {
-		part_name = METADATA_PART_1;
-	} else {
-		part_name = METADATA_PART_2;
-	}
-
-	return plat_set_image_source(image_id, handle, image_spec,
-				     part_name);
+	return plat_set_image_source(image_id, handle, image_spec);
 }
-#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
+#endif /* (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT */
diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c
index 1a59f0b..5514c09 100644
--- a/plat/st/common/stm32mp_fconf_io.c
+++ b/plat/st/common/stm32mp_fconf_io.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2021-2023, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,12 +27,12 @@
 };
 #endif
 
-#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
+#if (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT
 static io_block_spec_t metadata_block_spec = {
 	.offset = 0,    /* To be filled at runtime */
 	.length = 0,    /* To be filled at runtime */
 };
-#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
+#endif /* (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT */
 
 /* By default, STM32 platforms load images from the FIP */
 struct plat_io_policy policies[MAX_NUMBER_IDS] = {
@@ -58,7 +58,7 @@
 		.check = open_storage
 	},
 #endif
-#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
+#if (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT
 	[FWU_METADATA_IMAGE_ID] = {
 		.dev_handle = &storage_dev_handle,
 		.image_spec = (uintptr_t)&metadata_block_spec,
@@ -71,7 +71,7 @@
 		.img_type_guid = NULL_GUID,
 		.check = open_storage
 	},
-#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
+#endif /* (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT */
 };
 
 #define DEFAULT_UUID_NUMBER	U(7)
diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h
index 4098386..fa2d20e 100644
--- a/plat/st/stm32mp1/stm32mp1_fip_def.h
+++ b/plat/st/stm32mp1/stm32mp1_fip_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2021-2023, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -128,11 +128,26 @@
  * STM32MP1 RAW partition offset for devices without GPT
  ******************************************************************************/
 #define STM32MP_EMMC_BOOT_FIP_OFFSET	U(0x00040000)
+#if PSA_FWU_SUPPORT
+#define STM32MP_NOR_METADATA1_OFFSET	U(0x00080000)
+#define STM32MP_NOR_METADATA2_OFFSET	U(0x000C0000)
+#define STM32MP_NOR_FIP_A_OFFSET	U(0x00100000)
+#define STM32MP_NOR_FIP_A_GUID		(const struct efi_guid)EFI_GUID(0x4fd84c93,  \
+					0x54ef, 0x463f, 0xa7, 0xef, 0xae, 0x25, 0xff,\
+					0x88, 0x70, 0x87)
+
+#define STM32MP_NOR_FIP_B_OFFSET	U(0x00500000)
+#define STM32MP_NOR_FIP_B_GUID		(const struct efi_guid)EFI_GUID(0x09c54952,  \
+					0xd5bf, 0x45af, 0xac, 0xee, 0x33, 0x53, 0x03,\
+					0x76, 0x6f, 0xb3)
+
+#else /* PSA_FWU_SUPPORT */
 #ifndef STM32MP_NOR_FIP_OFFSET
 #define STM32MP_NOR_FIP_OFFSET		U(0x00080000)
 #endif
 #ifndef STM32MP_NAND_FIP_OFFSET
 #define STM32MP_NAND_FIP_OFFSET		U(0x00200000)
 #endif
+#endif /* PSA_FWU_SUPPORT */
 
 #endif /* STM32MP1_FIP_DEF_H */