diff mbox series

[v5,20/23] FWU: synquacer: Generate dfu_alt_info from devicetree partition

Message ID 20220609123010.1017463-21-sughosh.ganu@linaro.org
State New
Headers show
Series FWU: Add FWU Multi Bank Update feature support | expand

Commit Message

Sughosh Ganu June 9, 2022, 12:30 p.m. UTC
From: Masami Hiramatsu <masami.hiramatsu@linaro.org>

Generate dfu_alt_info from the partition uuid information in the
devicetree, and record the mapping of partition uuid and the
index of dfu_alt_num.

This could be a reference implementation of the automatic DFU
generation for FWU multi-bank update for non GPT firmware
platforms.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu@linaro.org>
Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
 .../synquacer-sc2a11-developerbox-u-boot.dtsi |   3 +
 board/socionext/developerbox/Kconfig          |   1 +
 board/socionext/developerbox/fwu_plat.c       |  79 ++++----
 include/configs/synquacer.h                   |   6 +-
 include/fwu.h                                 |   6 +
 lib/fwu_updates/Makefile                      |   1 +
 lib/fwu_updates/fwu_mtd.c                     | 173 ++++++++++++++++++
 7 files changed, 221 insertions(+), 48 deletions(-)
 create mode 100644 lib/fwu_updates/fwu_mtd.c

Comments

Michal Simek June 17, 2022, 2:02 p.m. UTC | #1
On 6/9/22 14:30, Sughosh Ganu wrote:
> From: Masami Hiramatsu <masami.hiramatsu@linaro.org>
> 
> Generate dfu_alt_info from the partition uuid information in the
> devicetree, and record the mapping of partition uuid and the
> index of dfu_alt_num.
> 
> This could be a reference implementation of the automatic DFU
> generation for FWU multi-bank update for non GPT firmware
> platforms.
> 
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu@linaro.org>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
>   .../synquacer-sc2a11-developerbox-u-boot.dtsi |   3 +
>   board/socionext/developerbox/Kconfig          |   1 +
>   board/socionext/developerbox/fwu_plat.c       |  79 ++++----
>   include/configs/synquacer.h                   |   6 +-
>   include/fwu.h                                 |   6 +
>   lib/fwu_updates/Makefile                      |   1 +
>   lib/fwu_updates/fwu_mtd.c                     | 173 ++++++++++++++++++
>   7 files changed, 221 insertions(+), 48 deletions(-)
>   create mode 100644 lib/fwu_updates/fwu_mtd.c
> 
> diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
> index ab4e3d1c2b..c7ec8a0321 100644
> --- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
> +++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
> @@ -36,6 +36,7 @@
>   				compatible = "fixed-partitions";
>   				#address-cells = <1>;
>   				#size-cells = <1>;
> +				uuid = "17e86d77-41f9-4fd7-87ec-a55df9842de5";
>   
>   				partition@0 {
>   					label = "BootStrap-BL1";
> @@ -88,10 +89,12 @@
>   				partition@600000 {
>   					label = "FIP-Bank0";
>   					reg = <0x600000 0x400000>;
> +					uuid = "5a66a702-99fd-4fef-a392-c26e261a2828";
>   				};
>   				partition@a00000 {
>   					label = "FIP-Bank1";
>   					reg = <0xa00000 0x400000>;
> +					uuid = "a8f868a1-6e5c-4757-878d-ce63375ef2c0";
>   				};
>   			};
>   		};
> diff --git a/board/socionext/developerbox/Kconfig b/board/socionext/developerbox/Kconfig
> index 7df6750baf..ad2a284f13 100644
> --- a/board/socionext/developerbox/Kconfig
> +++ b/board/socionext/developerbox/Kconfig
> @@ -38,6 +38,7 @@ config FWU_MULTI_BANK_UPDATE
>   	select DM_SPI_FLASH
>   	select DM_FWU_MDATA
>   	select BOARD_LATE_INIT
> +	select SET_DFU_ALT_INFO
>   
>   config FWU_NUM_BANKS
>   	default 2
> diff --git a/board/socionext/developerbox/fwu_plat.c b/board/socionext/developerbox/fwu_plat.c
> index fd6d0e3659..ff06eade7d 100644
> --- a/board/socionext/developerbox/fwu_plat.c
> +++ b/board/socionext/developerbox/fwu_plat.c
> @@ -10,8 +10,10 @@
>   #include <fwu_mdata.h>
>   #include <malloc.h>
>   #include <memalign.h>
> +#include <mtd.h>
>   #include <spi.h>
>   #include <spi_flash.h>
> +#include <uuid.h>
>   
>   #include <linux/errno.h>
>   #include <linux/types.h>
> @@ -94,6 +96,36 @@ static int sf_save_data(u32 offs, u32 size, void *data)
>   	return ret;
>   }
>   
> +#define DFU_ALT_BUF_LEN 256
> +#define DFU_ALT_NUM_MAX (CONFIG_FWU_NUM_IMAGES_PER_BANK * CONFIG_FWU_NUM_BANKS)
> +
> +/* Generate dfu_alt_info from partitions */
> +void set_dfu_alt_info(char *interface, char *devstr)
> +{
> +	int ret;
> +	struct mtd_info *mtd;
> +	static char *buf = NULL;
> +
> +	if (!buf) {
> +		buf = malloc_cache_aligned(DFU_ALT_BUF_LEN);
> +		memset(buf, 0, DFU_ALT_BUF_LEN);
> +
> +		mtd_probe_devices();
> +
> +		mtd = get_mtd_device_nm("nor1");
> +		if (IS_ERR_OR_NULL(mtd))
> +			return;
> +
> +		ret = fwu_gen_alt_info_from_mtd(buf, DFU_ALT_BUF_LEN, mtd);
> +		if (ret < 0) {
> +			log_err("Error: Failed to generate dfu_alt_info. (%d)\n", ret);
> +			return;
> +		}
> +		log_debug("Make dfu_alt_info: '%s'\n", buf);
> +	}
> +	env_set("dfu_alt_info", buf);
> +}
> +
>   #define PLAT_METADATA_OFFSET	0x510000
>   #define PLAT_METADATA_SIZE	(sizeof(struct devbox_metadata))
>   
> @@ -105,49 +137,7 @@ struct __packed devbox_metadata {
>   int fwu_plat_get_alt_num(struct udevice __always_unused *dev,
>   			 efi_guid_t *image_id, int *alt_num)
>   {
> -	struct fwu_image_bank_info *bank;
> -	struct fwu_mdata *mdata;
> -	int i, ret;
> -
> -	ret = fwu_get_mdata(&mdata);
> -	if (ret < 0)
> -		return ret;
> -
> -	/*
> -	 * DeveloperBox FWU expects Bank:Image = 1:1, and the dfu_alt_info
> -	 * only has the entries for banks. Thus the alt_no should be equal
> -	 * to the bank index number.
> -	 */
> -	ret = -ENOENT;
> -	for (i = 0; i < CONFIG_FWU_NUM_BANKS; i++) {
> -		bank = &mdata->img_entry[0].img_bank_info[i];
> -		if (guidcmp(image_id, &bank->image_uuid) == 0) {
> -			*alt_num = i;
> -			ret = 0;
> -			break;
> -		}
> -	}
> -
> -	free(mdata);
> -
> -	return ret;
> -}
> -
> -/* This assumes that user doesn't change system default dfu_alt_info */
> -efi_status_t fill_image_type_guid_array(const efi_guid_t __always_unused
> -					*default_guid,
> -					efi_guid_t **part_guid_arr)
> -{
> -	int i;
> -
> -	*part_guid_arr = malloc(sizeof(efi_guid_t) * DEFAULT_DFU_ALT_NUM);
> -	if (!*part_guid_arr)
> -		return EFI_OUT_OF_RESOURCES;
> -
> -	for (i = 0; i < DEFAULT_DFU_ALT_NUM; i++)
> -		guidcpy((*part_guid_arr + i), &devbox_fip_image_type_guid);
> -
> -	return EFI_SUCCESS;
> +	return fwu_get_mtd_alt_num(image_id, alt_num, "nor1", 0);
>   }
>   
>   int fwu_plat_get_update_index(u32 *update_idx)
> @@ -188,6 +178,9 @@ int board_late_init(void)
>   {
>   	int ret;
>   
> +	/* Make mmc available for EFI */
> +	run_command("mmc dev 0", 0);
> +

What is this for?

And I can't see any single note about in commit message.

Thanks,
Michal
Jassi Brar July 18, 2022, 2:49 p.m. UTC | #2
On Fri, 17 Jun 2022 at 09:02, Michal Simek <michal.simek@amd.com> wrote:
> On 6/9/22 14:30, Sughosh Ganu wrote:
> > From: Masami Hiramatsu <masami.hiramatsu@linaro.org>
.....

> >
> > @@ -188,6 +178,9 @@ int board_late_init(void)
> >   {
> >       int ret;
> >
> > +     /* Make mmc available for EFI */
> > +     run_command("mmc dev 0", 0);
> > +
>
> What is this for?
>
> And I can't see any single note about in commit message.
>
For some reason, we get "No EFI system partition" during bootup and
the mmc does not show up in 'efidebug devices' unless we manually run
this (or mmc part) command.
    Though not elegant, I found similar being done by some other
platforms....  grep run_command -rw board/*
I am happy to learn the proper way of doing it.

Thanks.
AKASHI Takahiro July 20, 2022, 1:13 a.m. UTC | #3
On Mon, Jul 18, 2022 at 09:49:56AM -0500, Jassi Brar wrote:
> On Fri, 17 Jun 2022 at 09:02, Michal Simek <michal.simek@amd.com> wrote:
> > On 6/9/22 14:30, Sughosh Ganu wrote:
> > > From: Masami Hiramatsu <masami.hiramatsu@linaro.org>
> .....
> 
> > >
> > > @@ -188,6 +178,9 @@ int board_late_init(void)
> > >   {
> > >       int ret;
> > >
> > > +     /* Make mmc available for EFI */
> > > +     run_command("mmc dev 0", 0);
> > > +
> >
> > What is this for?
> >
> > And I can't see any single note about in commit message.
> >
> For some reason, we get "No EFI system partition" during bootup and
> the mmc does not show up in 'efidebug devices' unless we manually run
> this (or mmc part) command.

As far as UEFI is concerned, any U-Boot block device will be
recognized as a UEFI disk(block_io) object *only* after device_probe()
is called.

-Takahiro Akashi


>     Though not elegant, I found similar being done by some other
> platforms....  grep run_command -rw board/*
> I am happy to learn the proper way of doing it.
> 
> Thanks.
Jassi Brar July 20, 2022, 3:16 a.m. UTC | #4
On Tue, 19 Jul 2022 at 20:13, Takahiro Akashi
<takahiro.akashi@linaro.org> wrote:
>
> On Mon, Jul 18, 2022 at 09:49:56AM -0500, Jassi Brar wrote:
> > On Fri, 17 Jun 2022 at 09:02, Michal Simek <michal.simek@amd.com> wrote:
> > > On 6/9/22 14:30, Sughosh Ganu wrote:
> > > > From: Masami Hiramatsu <masami.hiramatsu@linaro.org>
> > .....
> >
> > > >
> > > > @@ -188,6 +178,9 @@ int board_late_init(void)
> > > >   {
> > > >       int ret;
> > > >
> > > > +     /* Make mmc available for EFI */
> > > > +     run_command("mmc dev 0", 0);
> > > > +
> > >
> > > What is this for?
> > >
> > > And I can't see any single note about in commit message.
> > >
> > For some reason, we get "No EFI system partition" during bootup and
> > the mmc does not show up in 'efidebug devices' unless we manually run
> > this (or mmc part) command.
>
> As far as UEFI is concerned, any U-Boot block device will be
> recognized as a UEFI disk(block_io) object *only* after device_probe()
> is called.
>
OK, thanks for the clarification.  And I shouldn't feel too bad about
the hack then :)

thanks.
diff mbox series

Patch

diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
index ab4e3d1c2b..c7ec8a0321 100644
--- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
+++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
@@ -36,6 +36,7 @@ 
 				compatible = "fixed-partitions";
 				#address-cells = <1>;
 				#size-cells = <1>;
+				uuid = "17e86d77-41f9-4fd7-87ec-a55df9842de5";
 
 				partition@0 {
 					label = "BootStrap-BL1";
@@ -88,10 +89,12 @@ 
 				partition@600000 {
 					label = "FIP-Bank0";
 					reg = <0x600000 0x400000>;
+					uuid = "5a66a702-99fd-4fef-a392-c26e261a2828";
 				};
 				partition@a00000 {
 					label = "FIP-Bank1";
 					reg = <0xa00000 0x400000>;
+					uuid = "a8f868a1-6e5c-4757-878d-ce63375ef2c0";
 				};
 			};
 		};
diff --git a/board/socionext/developerbox/Kconfig b/board/socionext/developerbox/Kconfig
index 7df6750baf..ad2a284f13 100644
--- a/board/socionext/developerbox/Kconfig
+++ b/board/socionext/developerbox/Kconfig
@@ -38,6 +38,7 @@  config FWU_MULTI_BANK_UPDATE
 	select DM_SPI_FLASH
 	select DM_FWU_MDATA
 	select BOARD_LATE_INIT
+	select SET_DFU_ALT_INFO
 
 config FWU_NUM_BANKS
 	default 2
diff --git a/board/socionext/developerbox/fwu_plat.c b/board/socionext/developerbox/fwu_plat.c
index fd6d0e3659..ff06eade7d 100644
--- a/board/socionext/developerbox/fwu_plat.c
+++ b/board/socionext/developerbox/fwu_plat.c
@@ -10,8 +10,10 @@ 
 #include <fwu_mdata.h>
 #include <malloc.h>
 #include <memalign.h>
+#include <mtd.h>
 #include <spi.h>
 #include <spi_flash.h>
+#include <uuid.h>
 
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -94,6 +96,36 @@  static int sf_save_data(u32 offs, u32 size, void *data)
 	return ret;
 }
 
+#define DFU_ALT_BUF_LEN 256
+#define DFU_ALT_NUM_MAX (CONFIG_FWU_NUM_IMAGES_PER_BANK * CONFIG_FWU_NUM_BANKS)
+
+/* Generate dfu_alt_info from partitions */
+void set_dfu_alt_info(char *interface, char *devstr)
+{
+	int ret;
+	struct mtd_info *mtd;
+	static char *buf = NULL;
+
+	if (!buf) {
+		buf = malloc_cache_aligned(DFU_ALT_BUF_LEN);
+		memset(buf, 0, DFU_ALT_BUF_LEN);
+
+		mtd_probe_devices();
+
+		mtd = get_mtd_device_nm("nor1");
+		if (IS_ERR_OR_NULL(mtd))
+			return;
+
+		ret = fwu_gen_alt_info_from_mtd(buf, DFU_ALT_BUF_LEN, mtd);
+		if (ret < 0) {
+			log_err("Error: Failed to generate dfu_alt_info. (%d)\n", ret);
+			return;
+		}
+		log_debug("Make dfu_alt_info: '%s'\n", buf);
+	}
+	env_set("dfu_alt_info", buf);
+}
+
 #define PLAT_METADATA_OFFSET	0x510000
 #define PLAT_METADATA_SIZE	(sizeof(struct devbox_metadata))
 
@@ -105,49 +137,7 @@  struct __packed devbox_metadata {
 int fwu_plat_get_alt_num(struct udevice __always_unused *dev,
 			 efi_guid_t *image_id, int *alt_num)
 {
-	struct fwu_image_bank_info *bank;
-	struct fwu_mdata *mdata;
-	int i, ret;
-
-	ret = fwu_get_mdata(&mdata);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * DeveloperBox FWU expects Bank:Image = 1:1, and the dfu_alt_info
-	 * only has the entries for banks. Thus the alt_no should be equal
-	 * to the bank index number.
-	 */
-	ret = -ENOENT;
-	for (i = 0; i < CONFIG_FWU_NUM_BANKS; i++) {
-		bank = &mdata->img_entry[0].img_bank_info[i];
-		if (guidcmp(image_id, &bank->image_uuid) == 0) {
-			*alt_num = i;
-			ret = 0;
-			break;
-		}
-	}
-
-	free(mdata);
-
-	return ret;
-}
-
-/* This assumes that user doesn't change system default dfu_alt_info */
-efi_status_t fill_image_type_guid_array(const efi_guid_t __always_unused
-					*default_guid,
-					efi_guid_t **part_guid_arr)
-{
-	int i;
-
-	*part_guid_arr = malloc(sizeof(efi_guid_t) * DEFAULT_DFU_ALT_NUM);
-	if (!*part_guid_arr)
-		return EFI_OUT_OF_RESOURCES;
-
-	for (i = 0; i < DEFAULT_DFU_ALT_NUM; i++)
-		guidcpy((*part_guid_arr + i), &devbox_fip_image_type_guid);
-
-	return EFI_SUCCESS;
+	return fwu_get_mtd_alt_num(image_id, alt_num, "nor1", 0);
 }
 
 int fwu_plat_get_update_index(u32 *update_idx)
@@ -188,6 +178,9 @@  int board_late_init(void)
 {
 	int ret;
 
+	/* Make mmc available for EFI */
+	run_command("mmc dev 0", 0);
+
 	ret = devbox_load_plat_metadata();
 	if (ret < 0)
 		return ret;
diff --git a/include/configs/synquacer.h b/include/configs/synquacer.h
index 14eeb3f57e..103277661b 100644
--- a/include/configs/synquacer.h
+++ b/include/configs/synquacer.h
@@ -47,12 +47,8 @@ 
 /* Since U-Boot 64bit PCIe support is limited, disable 64bit MMIO support */
 
 #ifdef CONFIG_FWU_MULTI_BANK_UPDATE
-#define DEFAULT_DFU_ALT_NUM  2
-#define DEFAULT_DFU_ALT_INFO "dfu_alt_info="				\
-				"mtd nor1=bank0 raw  600000 400000;"	\
-					 "bank1 raw  a00000 400000\0"
+#define DEFAULT_DFU_ALT_INFO
 #else
-#define DEFAULT_DFU_ALT_NUM  1
 #define DEFAULT_DFU_ALT_INFO "dfu_alt_info="				\
 			"mtd nor1=fip.bin raw 600000 400000\0"
 #endif
diff --git a/include/fwu.h b/include/fwu.h
index 9c8012407b..fadbfedd07 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -63,4 +63,10 @@  void fwu_plat_get_bootidx(void *boot_idx);
 int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid,
 			 int *alt_num);
 int fwu_plat_get_update_index(u32 *update_idx);
+
+int fwu_get_mtd_alt_num(efi_guid_t *image_id, int *alt_num,
+			const char *mtd_dev, bool guid);
+int gen_image_alt_info(char *buf, size_t len, int sidx,
+		       struct fwu_image_entry *img, struct mtd_info *mtd);
+int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd);
 #endif /* _FWU_H_ */
diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile
index 74e37014e2..a135fd3f4a 100644
--- a/lib/fwu_updates/Makefile
+++ b/lib/fwu_updates/Makefile
@@ -4,3 +4,4 @@ 
 #
 
 obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o
+obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mtd.o
diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c
new file mode 100644
index 0000000000..3137f8635c
--- /dev/null
+++ b/lib/fwu_updates/fwu_mtd.c
@@ -0,0 +1,173 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <dfu.h>
+#include <fwu.h>
+#include <fwu_mdata.h>
+#include <log.h>
+#include <malloc.h>
+#include <mtd.h>
+#include <uuid.h>
+#include <vsprintf.h>
+
+#include <dm/ofnode.h>
+
+int fwu_get_mtd_alt_num(efi_guid_t *image_id, int *alt_num,
+			const char *mtd_dev, bool guid)
+{
+	int i, nalt;
+	int ret = -1;
+	struct mtd_info *mtd;
+	struct dfu_entity *dfu;
+	ofnode node, parts_node;
+	fdt_addr_t offset, size;
+	char uuidbuf[UUID_STR_LEN + 1];
+
+	mtd_probe_devices();
+	mtd = get_mtd_device_nm(mtd_dev);
+
+	/* Find partition node under given MTD device. */
+	parts_node = ofnode_by_compatible(mtd_get_ofnode(mtd),
+					  "fixed-partitions");
+
+	uuid_bin_to_str(image_id->b, uuidbuf,
+			guid ? UUID_STR_FORMAT_GUID : UUID_STR_FORMAT_STD);
+	node = ofnode_by_prop_value(parts_node, "uuid", uuidbuf,
+				    sizeof(uuidbuf));
+	if (!ofnode_valid(node)) {
+		log_warning("Warning: Failed to find partition by image UUID\n");
+		return -ENOENT;
+	}
+
+	offset = ofnode_get_addr_size_index_notrans(node, 0, &size);
+	if (offset == FDT_ADDR_T_NONE || !size)
+		return -ENOENT;
+
+	dfu_init_env_entities(NULL, NULL);
+
+	nalt = 0;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		nalt++;
+	}
+
+	if (!nalt) {
+		log_warning("No entities in dfu_alt_info\n");
+		dfu_free_entities();
+		return -ENOENT;
+	}
+
+	for (i = 0; i < nalt; i++) {
+		dfu = dfu_get_entity(i);
+
+		if (!dfu)
+			continue;
+
+		if (dfu->dev_type != DFU_DEV_MTD)
+			continue;
+
+		if (dfu->layout == DFU_RAW_ADDR &&
+		    dfu->data.mtd.start == offset &&
+		    dfu->data.mtd.size == size) {
+			*alt_num = dfu->alt;
+			ret = 0;
+			break;
+		}
+	}
+
+	dfu_free_entities();
+
+	return ret;
+}
+
+int gen_image_alt_info(char *buf, size_t len, int sidx,
+		       struct fwu_image_entry *img, struct mtd_info *mtd)
+{
+	char *p = buf, *end = buf + len;
+	char uuidbuf[UUID_STR_LEN + 1];
+	ofnode node, parts_node;
+	const char *suuid;
+	int i;
+
+	/* Find partition node under given MTD device. */
+	parts_node = ofnode_by_compatible(mtd_get_ofnode(mtd),
+					  "fixed-partitions");
+	if (!ofnode_valid(parts_node))
+		return -ENOENT;
+
+	/* Check the media UUID if exist. */
+	suuid = ofnode_read_string(parts_node, "uuid");
+	if (suuid) {
+		log_debug("Get location uuid %s\n", suuid);
+		uuid_bin_to_str(img->location_uuid.b, uuidbuf,
+				UUID_STR_FORMAT_STD);
+		if (strcasecmp(suuid, uuidbuf))
+			log_warning("Warning: Location UUID does not match!\n");
+	}
+
+	p += snprintf(p, end - p, "mtd %s", mtd->name);
+	if (end < p)
+		return -E2BIG;
+
+	/*
+	 * List up the image banks in the FWU mdata and search the corresponding
+	 * partition based on partition's uuid.
+	 */
+	for (i = 0; i < CONFIG_FWU_NUM_BANKS; i++) {
+		struct fwu_image_bank_info *bank;
+		fdt_addr_t offset, size;
+
+		/* Query a partition by image UUID */
+		bank = &img->img_bank_info[i];
+		uuid_bin_to_str(bank->image_uuid.b, uuidbuf,
+				UUID_STR_FORMAT_STD);
+		node = ofnode_by_prop_value(parts_node, "uuid", uuidbuf,
+					    sizeof(uuidbuf));
+		if (!ofnode_valid(node)) {
+			log_warning("Warning: Failed to find partition by image UUID\n");
+			break;
+		}
+
+		offset = ofnode_get_addr_size_index_notrans(node, 0, &size);
+		if (offset == FDT_ADDR_T_NONE || !size)
+			break;
+
+		p += snprintf(p, end - p, "%sbank%d raw %lx %lx",
+			      i == 0 ? "=" : ";", i, (unsigned long)offset,
+			      (unsigned long)size);
+		if (end < p)
+			return -E2BIG;
+	}
+
+	return i != CONFIG_FWU_NUM_BANKS ? -ENOENT : 0;
+}
+
+int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd)
+{
+	struct fwu_mdata *mdata;
+	int i, l, ret;
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret < 0) {
+		log_debug("Failed to get the FWU mdata.\n");
+		return ret;
+	}
+
+	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
+		ret = gen_image_alt_info(buf, len, i * CONFIG_FWU_NUM_BANKS,
+					 &mdata->img_entry[i], mtd);
+		if (ret)
+			break;
+		l = strlen(buf);
+		/* Replace the last ';' with '&' if there is another image. */
+		if (i != CONFIG_FWU_NUM_IMAGES_PER_BANK - 1 && l)
+			buf[l - 1] = '&';
+		len -= l;
+		buf += l;
+	}
+
+	free(mdata);
+
+	return ret;
+}