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

Sughosh Ganu sughosh.ganu at linaro.org
Thu Jun 9 14:30:07 CEST 2022


From: Masami Hiramatsu <masami.hiramatsu at 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 at linaro.org>
Signed-off-by: Sughosh Ganu <sughosh.ganu at 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 at 0 {
 					label = "BootStrap-BL1";
@@ -88,10 +89,12 @@
 				partition at 600000 {
 					label = "FIP-Bank0";
 					reg = <0x600000 0x400000>;
+					uuid = "5a66a702-99fd-4fef-a392-c26e261a2828";
 				};
 				partition at 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;
+}
-- 
2.25.1



More information about the U-Boot mailing list