Merge tag 'efi-2024-04-rc1' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request efi-2024-04-rc1

Documentation:

* update coreboot graphics documentation
* fix '---' rendering

UEFI:

* add missing pointer check after memory allocation in efidebug
* replace duplicate functions efi_dp_append and efi_dp_concat
* support fmp versioning for multi bank update
* avoid using dm_scan_other() in EFI app
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 34a59cb..8234e60 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -531,7 +531,7 @@
 	dp = efi_dp_shorten(dp_volume);
 	if (!dp)
 		dp = dp_volume;
-	dp = efi_dp_append(dp, &fp->dp);
+	dp = efi_dp_concat(dp, &fp->dp, false);
 	free(buf);
 
 	return dp;
@@ -1484,7 +1484,8 @@
 			ret = EFI_OUT_OF_RESOURCES;
 			goto out;
 		}
-		initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp, dp);
+		initrd_dp = efi_dp_concat((const struct efi_device_path *)&id_dp,
+					  dp, false);
 		efi_free_pool(dp);
 	}
 
@@ -1495,7 +1496,7 @@
 	}
 	final_dp_size = efi_dp_size(dp) + sizeof(END);
 	if (initrd_dp) {
-		final_dp = efi_dp_concat(dp, initrd_dp);
+		final_dp = efi_dp_concat(dp, initrd_dp, true);
 		final_dp_size += efi_dp_size(initrd_dp) + sizeof(END);
 	} else {
 		final_dp = efi_dp_dup(dp);
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index e10fbf8..aa85237 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -699,8 +699,8 @@
 	if (!short_fp)
 		short_fp = tmp_fp;
 
-	initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp,
-				  short_fp);
+	initrd_dp = efi_dp_concat((const struct efi_device_path *)&id_dp,
+				  short_fp, false);
 
 out:
 	efi_free_pool(tmp_dp);
@@ -754,6 +754,10 @@
 
 	uridp_len = sizeof(struct efi_device_path) + strlen(argv[3]) + 1;
 	uridp = efi_alloc(uridp_len + sizeof(END));
+	if (!uridp) {
+		log_err("Out of memory\n");
+		return CMD_RET_FAILURE;
+	}
 	uridp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 	uridp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_URI;
 	uridp->dp.length = uridp_len;
@@ -916,7 +920,7 @@
 		goto out;
 	}
 
-	final_fp = efi_dp_concat(file_path, initrd_dp);
+	final_fp = efi_dp_concat(file_path, initrd_dp, true);
 	if (!final_fp) {
 		printf("Cannot create final device path\n");
 		r = CMD_RET_FAILURE;
diff --git a/configs/efi-x86_app64_defconfig b/configs/efi-x86_app64_defconfig
index ceaebc7..3d02148 100644
--- a/configs/efi-x86_app64_defconfig
+++ b/configs/efi-x86_app64_defconfig
@@ -18,6 +18,7 @@
 CONFIG_SYS_PBSIZE=532
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_PART=y
diff --git a/doc/board/coreboot/coreboot.rst b/doc/board/coreboot/coreboot.rst
index 10a251c..7154f59 100644
--- a/doc/board/coreboot/coreboot.rst
+++ b/doc/board/coreboot/coreboot.rst
@@ -32,10 +32,9 @@
 If you want to use ELF as the coreboot payload, change U-Boot configuration to
 use CONFIG_OF_EMBED instead of CONFIG_OF_SEPARATE.
 
-To enable video you must enable these options in coreboot:
+To enable video you must enable CONFIG_GENERIC_LINEAR_FRAMEBUFFER in coreboot:
 
-   - Set framebuffer graphics resolution (1280x1024 32k-color (1:5:5))
-   - Keep VESA framebuffer
+   - Devices->Display->Framebuffer mode->Linear "high resolution" framebuffer
 
 At present it seems that for Minnowboard Max, coreboot does not pass through
 the video information correctly (it always says the resolution is 0x0). This
@@ -184,13 +183,13 @@
 
 To update the `coreboot.rom` file which is used:
 
-#. Build coreboot with `CONFIG_LINEAR_FRAMEBUFFER=y`. If using `make menuconfig`
-   this is under
-   `Devices ->Display->Framebuffer mode->Linear "high resolution" framebuffer`.
+#. Build coreboot with `CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y`. If using
+   `make menuconfig`, this is under
+   `Devices->Display->Framebuffer mode->Linear "high resolution" framebuffer`.
 
 #. Compress the resulting `coreboot.rom`::
 
-      xz -c /path/to/coreboot/build/coreboot.rom >coreboot.rom.xz
+      xz -c /path/to/coreboot/build/coreboot.rom > coreboot.rom.xz
 
 #. Upload the file to Google drive
 
diff --git a/doc/develop/sending_patches.rst b/doc/develop/sending_patches.rst
index 5a6962f..3f25b1d 100644
--- a/doc/develop/sending_patches.rst
+++ b/doc/develop/sending_patches.rst
@@ -121,7 +121,7 @@
    * For new features: a description of the feature and your implementation.
 
 * Additional comments which you don't want included in U-Boot's history can be
-  included below the first "---" in the message body.
+  included below the first "``---``" in the message body.
 
 * If your description gets too long, that's a strong indication that you should
   split up your patch.
@@ -253,7 +253,7 @@
 
 * Please make sure to keep a "change log", i.e. a description of what you have
   changed compared to previous versions of this patch. This change log should
-  be added below the "---" line in the patch, which starts the "comment
+  be added below the "``---``" line in the patch, which starts the "comment
   section", i.e. which contains text that does not get included into the
   actual commit message.
   Note: it is *not* sufficient to provide a change log in some cover letter
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 34e7fbb..d372504 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -819,8 +819,6 @@
 /* size of multi-instance device path excluding end node */
 efi_uintn_t efi_dp_size(const struct efi_device_path *dp);
 struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp);
-struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
-				      const struct efi_device_path *dp2);
 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
 					   const struct efi_device_path *node);
 /* Create a device path node of given type, sub-type, length */
@@ -937,7 +935,8 @@
 struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
 				       const efi_guid_t *guid);
 struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
-				      const struct efi_device_path *dp2);
+				      const struct efi_device_path *dp2,
+				      bool split_end_node);
 struct efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path);
 efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
 					 efi_uintn_t *size);
diff --git a/include/fwu.h b/include/fwu.h
index ac5c5de..eb5638f 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -122,21 +122,18 @@
 int fwu_set_active_index(uint active_idx);
 
 /**
- * fwu_get_image_index() - Get the Image Index to be used for capsule update
- * @image_index: The Image Index for the image
- *
- * The FWU multi bank update feature computes the value of image_index at
- * runtime, based on the bank to which the image needs to be written to.
- * Derive the image_index value for the image.
+ * fwu_get_dfu_alt_num() - Get the dfu_alt_num to be used for capsule update
+ * @image_index:	The Image Index for the image
+ * @alt_num:		pointer to store dfu_alt_num
  *
  * Currently, the capsule update driver uses the DFU framework for
  * the updates. This function gets the DFU alt number which is to
- * be used as the Image Index
+ * be used for capsule update.
  *
  * Return: 0 if OK, -ve on error
  *
  */
-int fwu_get_image_index(u8 *image_index);
+int fwu_get_dfu_alt_num(u8 image_index, u8 *alt_num);
 
 /**
  * fwu_revert_boot_index() - Revert the active index in the FWU metadata
diff --git a/lib/efi/Makefile b/lib/efi/Makefile
index a790d2d..232fa68 100644
--- a/lib/efi/Makefile
+++ b/lib/efi/Makefile
@@ -2,7 +2,7 @@
 #
 # (C) Copyright 2015 Google, Inc
 
-obj-$(CONFIG_EFI_APP) += efi_app.o efi.o
+obj-$(CONFIG_EFI_APP) += efi_app.o efi.o efi_app_init.o
 obj-$(CONFIG_EFI_STUB) += efi_info.o
 
 CFLAGS_REMOVE_efi_stub.o := -mregparm=3 \
diff --git a/lib/efi/efi_app.c b/lib/efi/efi_app.c
index 119db66..88332c3 100644
--- a/lib/efi/efi_app.c
+++ b/lib/efi/efi_app.c
@@ -67,49 +67,6 @@
 	return 0;
 }
 
-/**
- * efi_bind_block() - bind a new block device to an EFI device
- *
- * Binds a new top-level EFI_MEDIA device as well as a child block device so
- * that the block device can be accessed in U-Boot.
- *
- * The device can then be accessed using 'part list efi 0', 'fat ls efi 0:1',
- * for example, just like any other interface type.
- *
- * @handle: handle of the controller on which this driver is installed
- * @blkio: block io protocol proxied by this driver
- * @device_path: EFI device path structure for this
- * @len: Length of @device_path in bytes
- * @devp: Returns the bound device
- * Return: 0 if OK, -ve on error
- */
-int efi_bind_block(efi_handle_t handle, struct efi_block_io *blkio,
-		   struct efi_device_path *device_path, int len,
-		   struct udevice **devp)
-{
-	struct efi_media_plat plat;
-	struct udevice *dev;
-	char name[18];
-	int ret;
-
-	plat.handle = handle;
-	plat.blkio = blkio;
-	plat.device_path = malloc(device_path->length);
-	if (!plat.device_path)
-		return log_msg_ret("path", -ENOMEM);
-	memcpy(plat.device_path, device_path, device_path->length);
-	ret = device_bind(dm_root(), DM_DRIVER_GET(efi_media), "efi_media",
-			  &plat, ofnode_null(), &dev);
-	if (ret)
-		return log_msg_ret("bind", ret);
-
-	snprintf(name, sizeof(name), "efi_media_%x", dev_seq(dev));
-	device_set_name(dev, name);
-	*devp = dev;
-
-	return 0;
-}
-
 static efi_status_t setup_memory(struct efi_priv *priv)
 {
 	struct efi_boot_services *boot = priv->boot;
@@ -178,150 +135,6 @@
 	global_data_ptr = NULL;
 }
 
-/**
- * devpath_is_partition() - Figure out if a device path is a partition
- *
- * Checks if a device path refers to a partition on some media device. This
- * works by checking for a valid partition number in a hard-driver media device
- * as the final component of the device path.
- *
- * @path:	device path
- * Return:	true if a partition, false if not
- *		(e.g. it might be media which contains partitions)
- */
-static bool devpath_is_partition(const struct efi_device_path *path)
-{
-	const struct efi_device_path *p;
-	bool was_part = false;
-
-	for (p = path; p->type != DEVICE_PATH_TYPE_END;
-	     p = (void *)p + p->length) {
-		was_part = false;
-		if (p->type == DEVICE_PATH_TYPE_MEDIA_DEVICE &&
-		    p->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH) {
-			struct efi_device_path_hard_drive_path *hd =
-				(void *)path;
-
-			if (hd->partition_number)
-				was_part = true;
-		}
-	}
-
-	return was_part;
-}
-
-/**
- * setup_block() - Find all block devices and setup EFI devices for them
- *
- * Partitions are ignored, since U-Boot has partition handling. Errors with
- * particular devices produce a warning but execution continues to try to
- * find others.
- *
- * Return: 0 if found, -ENOSYS if there is no boot-services table, -ENOTSUPP
- *	if a required protocol is not supported
- */
-static int setup_block(void)
-{
-	efi_guid_t efi_blkio_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
-	efi_guid_t efi_devpath_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
-	efi_guid_t efi_pathutil_guid = EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
-	efi_guid_t efi_pathtext_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
-	struct efi_boot_services *boot = efi_get_boot();
-	struct efi_device_path_utilities_protocol *util;
-	struct efi_device_path_to_text_protocol *text;
-	struct efi_device_path *path;
-	struct efi_block_io *blkio;
-	efi_uintn_t num_handles;
-	efi_handle_t *handle;
-	int ret, i;
-
-	if (!boot)
-		return log_msg_ret("sys", -ENOSYS);
-
-	/* Find all devices which support the block I/O protocol */
-	ret = boot->locate_handle_buffer(BY_PROTOCOL, &efi_blkio_guid, NULL,
-				  &num_handles, &handle);
-	if (ret)
-		return log_msg_ret("loc", -ENOTSUPP);
-	log_debug("Found %d handles:\n", (int)num_handles);
-
-	/* We need to look up the path size and convert it to text */
-	ret = boot->locate_protocol(&efi_pathutil_guid, NULL, (void **)&util);
-	if (ret)
-		return log_msg_ret("util", -ENOTSUPP);
-	ret = boot->locate_protocol(&efi_pathtext_guid, NULL, (void **)&text);
-	if (ret)
-		return log_msg_ret("text", -ENOTSUPP);
-
-	for (i = 0; i < num_handles; i++) {
-		struct udevice *dev;
-		const u16 *name;
-		bool is_part;
-		int len;
-
-		ret = boot->handle_protocol(handle[i], &efi_devpath_guid,
-					    (void **)&path);
-		if (ret) {
-			log_warning("- devpath %d failed (ret=%d)\n", i, ret);
-			continue;
-		}
-
-		ret = boot->handle_protocol(handle[i], &efi_blkio_guid,
-					    (void **)&blkio);
-		if (ret) {
-			log_warning("- blkio %d failed (ret=%d)\n", i, ret);
-			continue;
-		}
-
-		name = text->convert_device_path_to_text(path, true, false);
-		is_part = devpath_is_partition(path);
-
-		if (!is_part) {
-			len = util->get_device_path_size(path);
-			ret = efi_bind_block(handle[i], blkio, path, len, &dev);
-			if (ret) {
-				log_warning("- blkio bind %d failed (ret=%d)\n",
-					    i, ret);
-				continue;
-			}
-		} else {
-			dev = NULL;
-		}
-
-		/*
-		 * Show the device name if we created one. Otherwise indicate
-		 * that it is a partition.
-		 */
-		printf("%2d: %-12s %ls\n", i, dev ? dev->name : "<partition>",
-		       name);
-	}
-	boot->free_pool(handle);
-
-	return 0;
-}
-
-/**
- * dm_scan_other() - Scan for UEFI devices that should be available to U-Boot
- *
- * This sets up block devices within U-Boot for those found in UEFI. With this,
- * U-Boot can access those devices
- *
- * @pre_reloc_only: true to only bind pre-relocation devices (ignored)
- * Returns: 0 on success, -ve on error
- */
-int dm_scan_other(bool pre_reloc_only)
-{
-	if (gd->flags & GD_FLG_RELOC) {
-		int ret;
-
-		ret = setup_block();
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 static void scan_tables(struct efi_system_table *sys_table)
 {
 	efi_guid_t acpi = EFI_ACPI_TABLE_GUID;
diff --git a/lib/efi/efi_app_init.c b/lib/efi/efi_app_init.c
new file mode 100644
index 0000000..c5e4192
--- /dev/null
+++ b/lib/efi/efi_app_init.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI-app board implementation
+ *
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <dm.h>
+#include <efi.h>
+#include <efi_api.h>
+#include <errno.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
+#include <linux/types.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * efi_bind_block() - bind a new block device to an EFI device
+ *
+ * Binds a new top-level EFI_MEDIA device as well as a child block device so
+ * that the block device can be accessed in U-Boot.
+ *
+ * The device can then be accessed using 'part list efi 0', 'fat ls efi 0:1',
+ * for example, just like any other interface type.
+ *
+ * @handle: handle of the controller on which this driver is installed
+ * @blkio: block io protocol proxied by this driver
+ * @device_path: EFI device path structure for this
+ * @len: Length of @device_path in bytes
+ * @devp: Returns the bound device
+ * Return: 0 if OK, -ve on error
+ */
+int efi_bind_block(efi_handle_t handle, struct efi_block_io *blkio,
+		   struct efi_device_path *device_path, int len,
+		   struct udevice **devp)
+{
+	struct efi_media_plat plat;
+	struct udevice *dev;
+	char name[18];
+	int ret;
+
+	plat.handle = handle;
+	plat.blkio = blkio;
+	plat.device_path = malloc(device_path->length);
+	if (!plat.device_path)
+		return log_msg_ret("path", -ENOMEM);
+	memcpy(plat.device_path, device_path, device_path->length);
+	ret = device_bind(dm_root(), DM_DRIVER_GET(efi_media), "efi_media",
+			  &plat, ofnode_null(), &dev);
+	if (ret)
+		return log_msg_ret("bind", ret);
+
+	snprintf(name, sizeof(name), "efi_media_%x", dev_seq(dev));
+	device_set_name(dev, name);
+	*devp = dev;
+
+	return 0;
+}
+
+/**
+ * devpath_is_partition() - Figure out if a device path is a partition
+ *
+ * Checks if a device path refers to a partition on some media device. This
+ * works by checking for a valid partition number in a hard-driver media device
+ * as the final component of the device path.
+ *
+ * @path:	device path
+ * Return:	true if a partition, false if not
+ *		(e.g. it might be media which contains partitions)
+ */
+static bool devpath_is_partition(const struct efi_device_path *path)
+{
+	const struct efi_device_path *p;
+	bool was_part = false;
+
+	for (p = path; p->type != DEVICE_PATH_TYPE_END;
+	     p = (void *)p + p->length) {
+		was_part = false;
+		if (p->type == DEVICE_PATH_TYPE_MEDIA_DEVICE &&
+		    p->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH) {
+			struct efi_device_path_hard_drive_path *hd =
+				(void *)path;
+
+			if (hd->partition_number)
+				was_part = true;
+		}
+	}
+
+	return was_part;
+}
+
+/**
+ * setup_block() - Find all block devices and setup EFI devices for them
+ *
+ * Partitions are ignored, since U-Boot has partition handling. Errors with
+ * particular devices produce a warning but execution continues to try to
+ * find others.
+ *
+ * Return: 0 if found, -ENOSYS if there is no boot-services table, -ENOTSUPP
+ *	if a required protocol is not supported
+ */
+static int setup_block(void)
+{
+	efi_guid_t efi_blkio_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+	efi_guid_t efi_devpath_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+	efi_guid_t efi_pathutil_guid = EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
+	efi_guid_t efi_pathtext_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
+	struct efi_boot_services *boot = efi_get_boot();
+	struct efi_device_path_utilities_protocol *util;
+	struct efi_device_path_to_text_protocol *text;
+	struct efi_device_path *path;
+	struct efi_block_io *blkio;
+	efi_uintn_t num_handles;
+	efi_handle_t *handle;
+	int ret, i;
+
+	if (!boot)
+		return log_msg_ret("sys", -ENOSYS);
+
+	/* Find all devices which support the block I/O protocol */
+	ret = boot->locate_handle_buffer(BY_PROTOCOL, &efi_blkio_guid, NULL,
+				  &num_handles, &handle);
+	if (ret)
+		return log_msg_ret("loc", -ENOTSUPP);
+	log_debug("Found %d handles:\n", (int)num_handles);
+
+	/* We need to look up the path size and convert it to text */
+	ret = boot->locate_protocol(&efi_pathutil_guid, NULL, (void **)&util);
+	if (ret)
+		return log_msg_ret("util", -ENOTSUPP);
+	ret = boot->locate_protocol(&efi_pathtext_guid, NULL, (void **)&text);
+	if (ret)
+		return log_msg_ret("text", -ENOTSUPP);
+
+	for (i = 0; i < num_handles; i++) {
+		struct udevice *dev;
+		const u16 *name;
+		bool is_part;
+		int len;
+
+		ret = boot->handle_protocol(handle[i], &efi_devpath_guid,
+					    (void **)&path);
+		if (ret) {
+			log_warning("- devpath %d failed (ret=%d)\n", i, ret);
+			continue;
+		}
+
+		ret = boot->handle_protocol(handle[i], &efi_blkio_guid,
+					    (void **)&blkio);
+		if (ret) {
+			log_warning("- blkio %d failed (ret=%d)\n", i, ret);
+			continue;
+		}
+
+		name = text->convert_device_path_to_text(path, true, false);
+		is_part = devpath_is_partition(path);
+
+		if (!is_part) {
+			len = util->get_device_path_size(path);
+			ret = efi_bind_block(handle[i], blkio, path, len, &dev);
+			if (ret) {
+				log_warning("- blkio bind %d failed (ret=%d)\n",
+					    i, ret);
+				continue;
+			}
+		} else {
+			dev = NULL;
+		}
+
+		/*
+		 * Show the device name if we created one. Otherwise indicate
+		 * that it is a partition.
+		 */
+		printf("%2d: %-12s %ls\n", i, dev ? dev->name : "<partition>",
+		       name);
+	}
+	boot->free_pool(handle);
+
+	return 0;
+}
+
+/**
+ * board_early_init_r() - Scan for UEFI devices that should be available
+ *
+ * This sets up block devices within U-Boot for those found in UEFI. With this,
+ * U-Boot can access those devices
+ *
+ * Returns: 0 on success, -ve on error
+ */
+int board_early_init_r(void)
+{
+	if (gd->flags & GD_FLG_RELOC) {
+		int ret;
+
+		ret = setup_block();
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index a032d3a..dd2dd23 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -143,7 +143,7 @@
 		if (!dp)
 			continue;
 
-		dp = efi_dp_append(dp, fp);
+		dp = efi_dp_concat(dp, fp, false);
 		if (!dp)
 			continue;
 
@@ -1579,8 +1579,8 @@
 			goto out;
 		msg_path = file_path;
 	} else {
-		file_path = efi_dp_append(bootefi_device_path,
-					  bootefi_image_path);
+		file_path = efi_dp_concat(bootefi_device_path,
+					  bootefi_image_path, false);
 		msg_path = bootefi_image_path;
 		log_debug("Loaded from disk\n");
 	}
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index c579d89..1951291 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1816,7 +1816,7 @@
 	if (device_path) {
 		info->device_handle = efi_dp_find_obj(device_path, NULL, NULL);
 
-		dp = efi_dp_append(device_path, file_path);
+		dp = efi_dp_concat(device_path, file_path, false);
 		if (!dp) {
 			ret = EFI_OUT_OF_RESOURCES;
 			goto failure;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 8dbd810..500fa10 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -271,30 +271,27 @@
 }
 
 /**
- * efi_dp_append_or_concatenate() - Append or concatenate two device paths.
- *				    Concatenated device path will be separated
- *				    by a sub-type 0xff end node
+ * efi_dp_concat() - Concatenate two device paths and add and terminate them
+ *                   with an end node.
  *
- * @dp1:	First device path
- * @dp2:	Second device path
- * @concat:	If true the two device paths will be concatenated and separated
- *		by an end of entrire device path sub-type 0xff end node.
- *		If true the second device path will be appended to the first and
- *		terminated by an end node
+ * @dp1:	    First device path
+ * @dp2:	    Second device path
+ * @split_end_node: If true the two device paths will be concatenated and
+ *                  separated by an end node (DEVICE_PATH_SUB_TYPE_END).
+ *		    If false the second device path will be concatenated to the
+ *		    first one as-is.
  *
  * Return:
  * concatenated device path or NULL. Caller must free the returned value
  */
-static struct
-efi_device_path *efi_dp_append_or_concatenate(const struct efi_device_path *dp1,
-					      const struct efi_device_path *dp2,
-					      bool concat)
+struct
+efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
+			       const struct efi_device_path *dp2,
+			       bool split_end_node)
 {
 	struct efi_device_path *ret;
-	size_t end_size = sizeof(END);
+	size_t end_size;
 
-	if (concat)
-		end_size = 2 * sizeof(END);
 	if (!dp1 && !dp2) {
 		/* return an end node */
 		ret = efi_dp_dup(&END);
@@ -306,14 +303,20 @@
 		/* both dp1 and dp2 are non-null */
 		unsigned sz1 = efi_dp_size(dp1);
 		unsigned sz2 = efi_dp_size(dp2);
-		void *p = efi_alloc(sz1 + sz2 + end_size);
+		void *p;
+
+		if (split_end_node)
+			end_size = 2 * sizeof(END);
+		else
+			end_size = sizeof(END);
+		p = efi_alloc(sz1 + sz2 + end_size);
 		if (!p)
 			return NULL;
 		ret = p;
 		memcpy(p, dp1, sz1);
 		p += sz1;
 
-		if (concat) {
+		if (split_end_node) {
 			memcpy(p, &END, sizeof(END));
 			p += sizeof(END);
 		}
@@ -327,37 +330,6 @@
 	return ret;
 }
 
-/**
- * efi_dp_append() - Append a device to an existing device path.
- *
- * @dp1:	First device path
- * @dp2:	Second device path
- *
- * Return:
- * concatenated device path or NULL. Caller must free the returned value
- */
-struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
-				      const struct efi_device_path *dp2)
-{
-	return efi_dp_append_or_concatenate(dp1, dp2, false);
-}
-
-/**
- * efi_dp_concat() - Concatenate 2 device paths. The final device path will
- *                   contain two device paths separated by and end node (0xff).
- *
- * @dp1:	First device path
- * @dp2:	Second device path
- *
- * Return:
- * concatenated device path or NULL. Caller must free the returned value
- */
-struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
-				      const struct efi_device_path *dp2)
-{
-	return efi_dp_append_or_concatenate(dp1, dp2, true);
-}
-
 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
 					   const struct efi_device_path *node)
 {
diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c
index 844d8ac..c95dbfa 100644
--- a/lib/efi_loader/efi_device_path_utilities.c
+++ b/lib/efi_loader/efi_device_path_utilities.c
@@ -76,7 +76,7 @@
 	const struct efi_device_path *src2)
 {
 	EFI_ENTRY("%pD, %pD", src1, src2);
-	return EFI_EXIT(efi_dp_append(src1, src2));
+	return EFI_EXIT(efi_dp_concat(src1, src2, false));
 }
 
 /*
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index ed99700..013842f 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -31,20 +31,15 @@
  *
  * @header:	EFI object header
  * @ops:	EFI disk I/O protocol interface
- * @dev_index:	device index of block device
  * @media:	block I/O media information
  * @dp:		device path to the block device
- * @part:	partition
  * @volume:	simple file system protocol of the partition
- * @dev:	associated DM device
  */
 struct efi_disk_obj {
 	struct efi_object header;
 	struct efi_block_io ops;
-	int dev_index;
 	struct efi_block_io_media media;
 	struct efi_device_path *dp;
-	unsigned int part;
 	struct efi_simple_file_system_protocol *volume;
 };
 
@@ -382,7 +377,6 @@
  * @parent:		parent handle
  * @dp_parent:		parent device path
  * @desc:		internal block device
- * @dev_index:		device index for block device
  * @part_info:		partition info
  * @part:		partition
  * @disk:		pointer to receive the created handle
@@ -393,7 +387,6 @@
 				efi_handle_t parent,
 				struct efi_device_path *dp_parent,
 				struct blk_desc *desc,
-				int dev_index,
 				struct disk_partition *part_info,
 				unsigned int part,
 				struct efi_disk_obj **disk,
@@ -455,7 +448,6 @@
 		diskobj->dp = efi_dp_from_part(desc, part);
 		diskobj->media.last_block = desc->lba - 1;
 	}
-	diskobj->part = part;
 
 	/*
 	 * Install the device path and the block IO protocol.
@@ -498,7 +490,6 @@
 			goto error;
 	}
 	diskobj->ops = block_io_disk_template;
-	diskobj->dev_index = dev_index;
 
 	/* Fill in EFI IO Media info (for read/write callbacks) */
 	diskobj->media.removable_media = desc->removable;
@@ -518,7 +509,7 @@
 
 	EFI_PRINT("BlockIO: part %u, present %d, logical %d, removable %d"
 		  ", last_block %llu\n",
-		  diskobj->part,
+		  part,
 		  diskobj->media.media_present,
 		  diskobj->media.logical_partition,
 		  diskobj->media.removable_media,
@@ -565,7 +556,7 @@
 	diskid = desc->devnum;
 
 	ret = efi_disk_add_dev(NULL, NULL, desc,
-			       diskid, NULL, 0, &disk, agent_handle);
+			       NULL, 0, &disk, agent_handle);
 	if (ret != EFI_SUCCESS) {
 		if (ret == EFI_NOT_READY) {
 			log_notice("Disk %s not ready\n", dev->name);
@@ -626,7 +617,7 @@
 		return -1;
 	dp_parent = (struct efi_device_path *)handler->protocol_interface;
 
-	ret = efi_disk_add_dev(parent, dp_parent, desc, diskid,
+	ret = efi_disk_add_dev(parent, dp_parent, desc,
 			       info, part, &disk, agent_handle);
 	if (ret != EFI_SUCCESS) {
 		log_err("Adding partition for %s failed\n", dev->name);
diff --git a/lib/efi_loader/efi_esrt.c b/lib/efi_loader/efi_esrt.c
index dafd447..443bd99 100644
--- a/lib/efi_loader/efi_esrt.c
+++ b/lib/efi_loader/efi_esrt.c
@@ -364,7 +364,7 @@
 		if (ret != EFI_SUCCESS) {
 			EFI_PRINT("ESRT Unable to find FMP handle (%u)\n",
 				  idx);
-			goto out;
+			continue;
 		}
 		fmp = handler->protocol_interface;
 
@@ -379,15 +379,14 @@
 			 * fmp->get_image_info to return BUFFER_TO_SMALL.
 			 */
 			EFI_PRINT("ESRT erroneous FMP implementation\n");
-			ret = EFI_INVALID_PARAMETER;
-			goto out;
+			continue;
 		}
 
 		ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, info_size,
 					(void **)&img_info);
 		if (ret != EFI_SUCCESS) {
 			EFI_PRINT("ESRT failed to allocate memory for image info\n");
-			goto out;
+			continue;
 		}
 
 		/*
@@ -405,7 +404,7 @@
 		if (ret != EFI_SUCCESS) {
 			EFI_PRINT("ESRT failed to obtain image info from FMP\n");
 			efi_free_pool(img_info);
-			goto out;
+			continue;
 		}
 
 		num_entries += desc_count;
@@ -413,6 +412,13 @@
 		efi_free_pool(img_info);
 	}
 
+	/* error occurs in fmp->get_image_info() if num_entries is 0 here */
+	if (!num_entries) {
+		EFI_PRINT("Error occurs, num_entries should not be 0\n");
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
 	EFI_PRINT("ESRT create table with %u entries\n", num_entries);
 	/*
 	 * Allocate an ESRT with the sufficient number of entries to accommodate
@@ -436,7 +442,7 @@
 		if (ret != EFI_SUCCESS) {
 			EFI_PRINT("ESRT unable to find FMP handle (%u)\n",
 				  idx);
-			break;
+			continue;
 		}
 		fmp = handler->protocol_interface;
 
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index 1fde188..9fd1329 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -206,18 +206,10 @@
 {
 	u16 varname[13]; /* u"FmpStateXXXX" */
 	efi_status_t ret;
-	efi_uintn_t size;
-	struct fmp_state var_state = { 0 };
-
-	efi_create_indexed_name(varname, sizeof(varname), "FmpState",
-				fw_array->image_index);
-	size = sizeof(var_state);
-	ret = efi_get_variable_int(varname, &fw_array->image_type_id,
-				   NULL, &size, &var_state, NULL);
-	if (ret == EFI_SUCCESS)
-		image_info->version = var_state.fw_version;
-	else
-		image_info->version = 0;
+	efi_uintn_t size, expected_size;
+	uint num_banks = 1;
+	uint active_index = 0;
+	struct fmp_state *var_state;
 
 	efi_firmware_get_lsv_from_dtb(fw_array->image_index,
 				      &fw_array->image_type_id,
@@ -226,6 +218,31 @@
 	image_info->version_name = NULL; /* not supported */
 	image_info->last_attempt_version = 0;
 	image_info->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
+	image_info->version = 0;
+
+	/* get the fw_version */
+	efi_create_indexed_name(varname, sizeof(varname), "FmpState",
+				fw_array->image_index);
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		ret = fwu_get_active_index(&active_index);
+		if (ret)
+			return;
+
+		num_banks = CONFIG_FWU_NUM_BANKS;
+	}
+
+	size = num_banks * sizeof(*var_state);
+	expected_size = size;
+	var_state = calloc(1, size);
+	if (!var_state)
+		return;
+
+	ret = efi_get_variable_int(varname, &fw_array->image_type_id,
+				   NULL, &size, var_state, NULL);
+	if (ret == EFI_SUCCESS && expected_size == size)
+		image_info->version = var_state[active_index].fw_version;
+
+	free(var_state);
 }
 
 /**
@@ -361,8 +378,11 @@
 {
 	u16 varname[13]; /* u"FmpStateXXXX" */
 	efi_status_t ret;
+	uint num_banks = 1;
+	uint update_bank = 0;
+	efi_uintn_t size;
 	efi_guid_t *image_type_id;
-	struct fmp_state var_state = { 0 };
+	struct fmp_state *var_state;
 
 	image_type_id = efi_firmware_get_image_type_id(image_index);
 	if (!image_type_id)
@@ -371,19 +391,44 @@
 	efi_create_indexed_name(varname, sizeof(varname), "FmpState",
 				image_index);
 
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		ret = fwu_plat_get_update_index(&update_bank);
+		if (ret)
+			return EFI_INVALID_PARAMETER;
+
+		num_banks = CONFIG_FWU_NUM_BANKS;
+	}
+
+	size = num_banks * sizeof(*var_state);
+	var_state = calloc(1, size);
+	if (!var_state)
+		return EFI_OUT_OF_RESOURCES;
+
+	/*
+	 * GetVariable may fail, EFI_NOT_FOUND is returned if FmpState
+	 * variable has not been set yet.
+	 * Ignore the error here since the correct FmpState variable
+	 * is set later.
+	 */
+	efi_get_variable_int(varname, image_type_id, NULL, &size, var_state,
+			     NULL);
+
 	/*
 	 * Only the fw_version is set here.
 	 * lowest_supported_version in FmpState variable is ignored since
 	 * it can be tampered if the file based EFI variable storage is used.
 	 */
-	var_state.fw_version = state->fw_version;
+	var_state[update_bank].fw_version = state->fw_version;
 
+	size = num_banks * sizeof(*var_state);
 	ret = efi_set_variable_int(varname, image_type_id,
 				   EFI_VARIABLE_READ_ONLY |
 				   EFI_VARIABLE_NON_VOLATILE |
 				   EFI_VARIABLE_BOOTSERVICE_ACCESS |
 				   EFI_VARIABLE_RUNTIME_ACCESS,
-				   sizeof(var_state), &var_state, false);
+				   size, var_state, false);
+
+	free(var_state);
 
 	return ret;
 }
@@ -610,6 +655,7 @@
 	u16 **abort_reason)
 {
 	int ret;
+	u8 dfu_alt_num;
 	efi_status_t status;
 	struct fmp_state state = { 0 };
 
@@ -624,19 +670,25 @@
 	if (status != EFI_SUCCESS)
 		return EFI_EXIT(status);
 
+	/*
+	 * dfu_alt_num is assigned from 0 while image_index starts from 1.
+	 * dfu_alt_num is calculated by (image_index - 1) when multi bank update
+	 * is not used.
+	 */
+	dfu_alt_num = image_index - 1;
 	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
 		/*
 		 * Based on the value of update bank, derive the
 		 * image index value.
 		 */
-		ret = fwu_get_image_index(&image_index);
+		ret = fwu_get_dfu_alt_num(image_index, &dfu_alt_num);
 		if (ret) {
 			log_debug("Unable to get FWU image_index\n");
 			return EFI_EXIT(EFI_DEVICE_ERROR);
 		}
 	}
 
-	if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
+	if (dfu_write_by_alt(dfu_alt_num, (void *)image, image_size,
 			     NULL, NULL))
 		return EFI_EXIT(EFI_DEVICE_ERROR);
 
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index b580574..8651810 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -125,16 +125,14 @@
 	return 0;
 }
 
-static int fwu_get_image_type_id(u8 *image_index, efi_guid_t *image_type_id)
+static int fwu_get_image_type_id(u8 image_index, efi_guid_t *image_type_id)
 {
-	u8 index;
 	int i;
 	struct efi_fw_image *image;
 
-	index = *image_index;
 	image = update_info.images;
 	for (i = 0; i < update_info.num_images; i++) {
-		if (index == image[i].image_index) {
+		if (image_index == image[i].image_index) {
 			guidcpy(image_type_id, &image[i].image_type_id);
 			return 0;
 		}
@@ -332,24 +330,20 @@
 }
 
 /**
- * fwu_get_image_index() - Get the Image Index to be used for capsule update
- * @image_index: The Image Index for the image
- *
- * The FWU multi bank update feature computes the value of image_index at
- * runtime, based on the bank to which the image needs to be written to.
- * Derive the image_index value for the image.
+ * fwu_get_dfu_alt_num() - Get the dfu_alt_num to be used for capsule update
+ * @image_index:	The Image Index for the image
+ * @alt_num:		pointer to store dfu_alt_num
  *
  * Currently, the capsule update driver uses the DFU framework for
  * the updates. This function gets the DFU alt number which is to
- * be used as the Image Index
+ * be used for capsule update.
  *
  * Return: 0 if OK, -ve on error
  *
  */
-int fwu_get_image_index(u8 *image_index)
+int fwu_get_dfu_alt_num(u8 image_index, u8 *alt_num)
 {
 	int ret, i;
-	u8 alt_num;
 	uint update_bank;
 	efi_guid_t *image_guid, image_type_id;
 	struct fwu_mdata *mdata = &g_mdata;
@@ -365,7 +359,7 @@
 	ret = fwu_get_image_type_id(image_index, &image_type_id);
 	if (ret) {
 		log_debug("Unable to get image_type_id for image_index %u\n",
-			  *image_index);
+			  image_index);
 		goto out;
 	}
 
@@ -380,15 +374,13 @@
 			img_entry = &mdata->img_entry[i];
 			img_bank_info = &img_entry->img_bank_info[update_bank];
 			image_guid = &img_bank_info->image_uuid;
-			ret = fwu_plat_get_alt_num(g_dev, image_guid, &alt_num);
-			if (ret) {
+			ret = fwu_plat_get_alt_num(g_dev, image_guid, alt_num);
+			if (ret)
 				log_debug("alt_num not found for partition with GUID %pUs\n",
 					  image_guid);
-			} else {
+			else
 				log_debug("alt_num %d for partition %pUs\n",
-					  alt_num, image_guid);
-				*image_index = alt_num + 1;
-			}
+					  *alt_num, image_guid);
 
 			goto out;
 		}
diff --git a/tools/patman/patman.rst b/tools/patman/patman.rst
index a8b317e..e013558 100644
--- a/tools/patman/patman.rst
+++ b/tools/patman/patman.rst
@@ -280,7 +280,7 @@
 
 Commit-notes:
     Similar, but for a single commit (patch). These notes will appear
-    immediately below the --- cut in the patch file::
+    immediately below the ``---`` cut in the patch file::
 
         Commit-notes:
         blah blah