Merge tag 'dm-pull-13oct23' of https://source.denx.de/u-boot/custodians/u-boot-dm

improvements with dev_read_addr_..._ptr()
scan all entries in multi-device boot_targets
EFI empty-capsule support
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c
index 9be2d9e..ef245fe 100644
--- a/arch/arm/mach-k3/sysfw-loader.c
+++ b/arch/arm/mach-k3/sysfw-loader.c
@@ -321,7 +321,7 @@
 static void *k3_sysfw_get_spi_addr(void)
 {
 	struct udevice *dev;
-	fdt_addr_t addr;
+	void *addr;
 	int ret;
 	unsigned int sf_bus = spl_spi_boot_bus();
 
@@ -329,11 +329,11 @@
 	if (ret)
 		return NULL;
 
-	addr = dev_read_addr_index(dev, 1);
-	if (addr == FDT_ADDR_T_NONE)
+	addr = dev_read_addr_index_ptr(dev, 1);
+	if (!addr)
 		return NULL;
 
-	return (void *)(addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS);
+	return addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS;
 }
 
 static void k3_sysfw_spi_copy(u32 *dst, u32 *src, size_t len)
@@ -349,18 +349,18 @@
 static void *get_sysfw_hf_addr(void)
 {
 	struct udevice *dev;
-	fdt_addr_t addr;
+	void *addr;
 	int ret;
 
 	ret = uclass_find_first_device(UCLASS_MTD, &dev);
 	if (ret)
 		return NULL;
 
-	addr = dev_read_addr_index(dev, 1);
-	if (addr == FDT_ADDR_T_NONE)
+	addr = dev_read_addr_index_ptr(dev, 1);
+	if (!addr)
 		return NULL;
 
-	return (void *)(addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS);
+	return addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS;
 }
 #endif
 
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
index 09e3d10..7590f1b 100644
--- a/arch/sandbox/cpu/spl.c
+++ b/arch/sandbox/cpu/spl.c
@@ -126,6 +126,9 @@
 {
 	struct sandbox_state *state = state_get_current();
 
+	if (!CONFIG_IS_ENABLED(UNIT_TEST))
+		return;
+
 	if (state->run_unittests) {
 		struct unit_test *tests = UNIT_TEST_ALL_START();
 		const int count = UNIT_TEST_ALL_COUNT();
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 974ddee..44ae98a 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -469,10 +469,11 @@
 			 * if no sequence number was provided, we must scan all
 			 * bootdevs for this media uclass
 			 */
-			if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && seq == -1)
+			if (seq == -1)
 				method_flags |= BOOTFLOW_METHF_SINGLE_UCLASS;
 			if (method_flagsp)
 				*method_flagsp = method_flags;
+			log_debug("method flags %x\n", method_flags);
 			return 0;
 		}
 		log_debug("- no device in %s\n", media->name);
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 6ef62e1..e03932e 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -260,8 +260,25 @@
 		} else {
 			log_debug("labels %p\n", iter->labels);
 			if (iter->labels) {
-				ret = bootdev_next_label(iter, &dev,
-							 &method_flags);
+				/*
+				 * when the label is "mmc" we want to scan all
+				 * mmc bootdevs, not just the first. See
+				 * bootdev_find_by_label() where this flag is
+				 * set up
+				 */
+				if (iter->method_flags & BOOTFLOW_METHF_SINGLE_UCLASS) {
+					uclass_next_device(&dev);
+					log_debug("looking for next device %s: %s\n",
+						  iter->dev->name,
+						  dev ? dev->name : "<none>");
+				} else {
+					dev = NULL;
+				}
+				if (!dev) {
+					log_debug("looking at next label\n");
+					ret = bootdev_next_label(iter, &dev,
+								 &method_flags);
+				}
 			} else {
 				ret = bootdev_next_prio(iter, &dev);
 				method_flags = 0;
diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
index f8510d3..fb16ac7 100644
--- a/doc/develop/uefi/uefi.rst
+++ b/doc/develop/uefi/uefi.rst
@@ -385,6 +385,23 @@
 efi-capsule binman entry type, which describes all the properties that
 can be specified.
 
+Dumping capsule headers
+***********************
+
+The mkeficapsule tool also provides a command-line option to dump the
+contents of the capsule header. This is a useful functionality when
+trying to understand the structure of a capsule and is also used in
+capsule verification. This feature is used in testing the capsule
+contents in binman's test framework.
+
+To check the contents of the capsule headers, the mkeficapsule command
+can be used.
+
+.. code-block:: console
+
+    $ mkeficapsule --dump-capsule \
+      <capsule_file_name>
+
 Performing the update
 *********************
 
diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c
index b79d138..8e774d4 100644
--- a/drivers/core/fdtaddr.c
+++ b/drivers/core/fdtaddr.c
@@ -145,7 +145,7 @@
 	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
 				      "reg-names", name);
 	if (index < 0)
-		return index;
+		return FDT_ADDR_T_NONE;
 
 	return devfdt_get_addr_index(dev, index);
 #else
@@ -153,6 +153,16 @@
 #endif
 }
 
+void *devfdt_get_addr_name_ptr(const struct udevice *dev, const char *name)
+{
+	fdt_addr_t addr = devfdt_get_addr_name(dev, name);
+
+	if (addr == FDT_ADDR_T_NONE)
+		return NULL;
+
+	return map_sysmem(addr, 0);
+}
+
 fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev,
 				     const char *name, fdt_size_t *size)
 {
@@ -162,7 +172,7 @@
 	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
 				      "reg-names", name);
 	if (index < 0)
-		return index;
+		return FDT_ADDR_T_NONE;
 
 	return devfdt_get_addr_size_index(dev, index, size);
 #else
@@ -170,6 +180,17 @@
 #endif
 }
 
+void *devfdt_get_addr_size_name_ptr(const struct udevice *dev,
+				    const char *name, fdt_size_t *size)
+{
+	fdt_addr_t addr = devfdt_get_addr_size_name(dev, name, size);
+
+	if (addr == FDT_ADDR_T_NONE)
+		return NULL;
+
+	return map_sysmem(addr, 0);
+}
+
 fdt_addr_t devfdt_get_addr(const struct udevice *dev)
 {
 	return devfdt_get_addr_index(dev, 0);
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 4190134..1a4a95c 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -181,6 +181,16 @@
 		return dev_read_addr_index(dev, index);
 }
 
+void *dev_read_addr_name_ptr(const struct udevice *dev, const char *name)
+{
+	fdt_addr_t addr = dev_read_addr_name(dev, name);
+
+	if (addr == FDT_ADDR_T_NONE)
+		return NULL;
+
+	return map_sysmem(addr, 0);
+}
+
 fdt_addr_t dev_read_addr_size_name(const struct udevice *dev, const char *name,
 				   fdt_size_t *size)
 {
@@ -192,6 +202,17 @@
 		return dev_read_addr_size_index(dev, index, size);
 }
 
+void *dev_read_addr_size_name_ptr(const struct udevice *dev, const char *name,
+				  fdt_size_t *size)
+{
+	fdt_addr_t addr = dev_read_addr_size_name(dev, name, size);
+
+	if (addr == FDT_ADDR_T_NONE)
+		return NULL;
+
+	return map_sysmem(addr, 0);
+}
+
 void *dev_remap_addr_name(const struct udevice *dev, const char *name)
 {
 	fdt_addr_t addr = dev_read_addr_name(dev, name);
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 4f2effd..9273c70 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -1287,7 +1287,7 @@
 	u32 cap2, cap3, cap4;
 	int i;
 
-	ud->mmrs[MMR_GCFG] = (uint32_t *)devfdt_get_addr_name(dev, mmr_names[MMR_GCFG]);
+	ud->mmrs[MMR_GCFG] = dev_read_addr_name_ptr(dev, mmr_names[MMR_GCFG]);
 	if (!ud->mmrs[MMR_GCFG])
 		return -EINVAL;
 
@@ -1325,8 +1325,7 @@
 		if (i == MMR_RCHANRT && ud->rchan_cnt == 0)
 			continue;
 
-		ud->mmrs[i] = (uint32_t *)devfdt_get_addr_name(dev,
-				mmr_names[i]);
+		ud->mmrs[i] = dev_read_addr_name_ptr(dev, mmr_names[i]);
 		if (!ud->mmrs[i])
 			return -EINVAL;
 	}
diff --git a/drivers/gpio/tegra186_gpio.c b/drivers/gpio/tegra186_gpio.c
index 82dcaf9..94a20d1 100644
--- a/drivers/gpio/tegra186_gpio.c
+++ b/drivers/gpio/tegra186_gpio.c
@@ -176,8 +176,8 @@
 	if (parent_plat)
 		return 0;
 
-	regs = (uint32_t *)devfdt_get_addr_name(parent, "gpio");
-	if (regs == (uint32_t *)FDT_ADDR_T_NONE)
+	regs = dev_read_addr_name_ptr(parent, "gpio");
+	if (!regs)
 		return -EINVAL;
 
 	for (port = 0; port < ctlr_data->port_count; port++) {
diff --git a/drivers/mailbox/k3-sec-proxy.c b/drivers/mailbox/k3-sec-proxy.c
index 2707261..e0a18d8 100644
--- a/drivers/mailbox/k3-sec-proxy.c
+++ b/drivers/mailbox/k3-sec-proxy.c
@@ -84,9 +84,9 @@
 	struct mbox_chan chan;
 	struct k3_sec_proxy_desc *desc;
 	struct k3_sec_proxy_thread *chans;
-	phys_addr_t target_data;
-	phys_addr_t scfg;
-	phys_addr_t rt;
+	void *target_data;
+	void *scfg;
+	void *rt;
 };
 
 static inline u32 sp_readl(void __iomem *addr, unsigned int offset)
@@ -319,20 +319,20 @@
 		return -ENODEV;
 	}
 
-	spm->target_data = devfdt_get_addr_name(dev, "target_data");
-	if (spm->target_data == FDT_ADDR_T_NONE) {
+	spm->target_data = dev_read_addr_name_ptr(dev, "target_data");
+	if (!spm->target_data) {
 		dev_err(dev, "No reg property for target data base\n");
 		return -EINVAL;
 	}
 
-	spm->scfg = devfdt_get_addr_name(dev, "scfg");
-	if (spm->scfg == FDT_ADDR_T_NONE) {
+	spm->scfg = dev_read_addr_name_ptr(dev, "scfg");
+	if (!spm->scfg) {
 		dev_err(dev, "No reg property for Secure Cfg base\n");
 		return -EINVAL;
 	}
 
-	spm->rt = devfdt_get_addr_name(dev, "rt");
-	if (spm->rt == FDT_ADDR_T_NONE) {
+	spm->rt = dev_read_addr_name_ptr(dev, "rt");
+	if (!spm->rt) {
 		dev_err(dev, "No reg property for Real Time Cfg base\n");
 		return -EINVAL;
 	}
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 77dffca..6624e91 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -472,9 +472,9 @@
 	if (!data->cfg)
 		return -EINVAL;
 
-	data->base = (void __iomem *)devfdt_get_addr_name(dev, "phy_ctrl");
-	if (IS_ERR(data->base))
-		return PTR_ERR(data->base);
+	data->base = (void __iomem *)dev_read_addr_name_ptr(dev, "phy_ctrl");
+	if (!data->base)
+		return -EINVAL;
 
 	device_get_supply_regulator(dev, "usb0_vbus_power-supply",
 				    &data->vbus_power_supply);
@@ -555,9 +555,9 @@
 
 		if (i || data->cfg->phy0_dual_route) {
 			snprintf(name, sizeof(name), "pmu%d", i);
-			phy->pmu = (void __iomem *)devfdt_get_addr_name(dev, name);
-			if (IS_ERR(phy->pmu))
-				return PTR_ERR(phy->pmu);
+			phy->pmu = (void __iomem *)dev_read_addr_name_ptr(dev, name);
+			if (!phy->pmu)
+				return -EINVAL;
 		}
 
 		phy->id = i;
diff --git a/drivers/phy/phy-bcm-sr-pcie.c b/drivers/phy/phy-bcm-sr-pcie.c
index f0e7953..cf33bab 100644
--- a/drivers/phy/phy-bcm-sr-pcie.c
+++ b/drivers/phy/phy-bcm-sr-pcie.c
@@ -143,8 +143,8 @@
 
 	core->dev = dev;
 
-	core->base = (void __iomem *)devfdt_get_addr_name(dev, "reg_base");
-	core->cdru = (void __iomem *)devfdt_get_addr_name(dev, "cdru_base");
+	core->base = (void __iomem *)dev_read_addr_name_ptr(dev, "reg_base");
+	core->cdru = (void __iomem *)dev_read_addr_name_ptr(dev, "cdru_base");
 	debug("ip base %p\n", core->base);
 	debug("cdru base %p\n", core->cdru);
 
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index d80281f..d1db377 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <mapmem.h>
 #include <dm.h>
 #include <dm/device_compat.h>
 #include <dm/devres.h>
@@ -24,7 +25,7 @@
  * @bits_per_mux: true if one register controls more than one pin
  */
 struct single_pdata {
-	fdt_addr_t base;
+	void *base;
 	int offset;
 	u32 mask;
 	u32 width;
@@ -97,7 +98,7 @@
 
 #if (!IS_ENABLED(CONFIG_SANDBOX))
 
-static unsigned int single_read(struct udevice *dev, fdt_addr_t reg)
+static unsigned int single_read(struct udevice *dev, void *reg)
 {
 	struct single_pdata *pdata = dev_get_plat(dev);
 
@@ -113,7 +114,7 @@
 	return readb(reg);
 }
 
-static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg)
+static void single_write(struct udevice *dev, unsigned int val, void *reg)
 {
 	struct single_pdata *pdata = dev_get_plat(dev);
 
@@ -131,18 +132,18 @@
 
 #else /* CONFIG_SANDBOX  */
 
-static unsigned int single_read(struct udevice *dev, fdt_addr_t reg)
+static unsigned int single_read(struct udevice *dev, void *reg)
 {
 	struct single_priv *priv = dev_get_priv(dev);
 
-	return priv->sandbox_regs[reg];
+	return priv->sandbox_regs[map_to_sysmem(reg)];
 }
 
-static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg)
+static void single_write(struct udevice *dev, unsigned int val, void *reg)
 {
 	struct single_priv *priv = dev_get_priv(dev);
 
-	priv->sandbox_regs[reg] = val;
+	priv->sandbox_regs[map_to_sysmem(reg)] = val;
 }
 
 #endif /* CONFIG_SANDBOX  */
@@ -214,7 +215,8 @@
 {
 	struct single_pdata *pdata = dev_get_plat(dev);
 	struct single_priv *priv = dev_get_priv(dev);
-	fdt_addr_t reg;
+	phys_addr_t phys_reg;
+	void *reg;
 	const char *fname;
 	unsigned int val;
 	int offset, pin_shift = 0;
@@ -226,13 +228,15 @@
 	reg = pdata->base + offset;
 	val = single_read(dev, reg);
 
+	phys_reg = map_to_sysmem(reg);
+
 	if (pdata->bits_per_mux)
 		pin_shift = pin % (pdata->width / priv->bits_per_pin) *
 			priv->bits_per_pin;
 
 	val &= (pdata->mask << pin_shift);
 	fname = single_get_pin_function(dev, pin);
-	snprintf(buf, size, "%pa 0x%08x %s", &reg, val,
+	snprintf(buf, size, "%pa 0x%08x %s", &phys_reg, val,
 		 fname ? fname : "UNCLAIMED");
 	return 0;
 }
@@ -243,7 +247,7 @@
 	struct single_pdata *pdata = dev_get_plat(dev);
 	struct single_gpiofunc_range *frange = NULL;
 	struct list_head *pos, *tmp;
-	phys_addr_t reg;
+	void *reg;
 	int mux_bytes = 0;
 	u32 data;
 
@@ -321,7 +325,7 @@
 	int stride = pdata->args_count + 1;
 	int n, pin, count = size / sizeof(u32);
 	struct single_func *func;
-	phys_addr_t reg;
+	void *reg;
 	u32 offset, val, mux;
 
 	/* If function mask is null, needn't enable it. */
@@ -379,7 +383,7 @@
 	int n, pin, count = size / sizeof(struct single_fdt_bits_cfg);
 	int npins_in_reg, pin_num_from_lsb;
 	struct single_func *func;
-	phys_addr_t reg;
+	void *reg;
 	u32 offset, val, mask, bit_pos, val_pos, mask_pos, submask;
 
 	/* If function mask is null, needn't enable it. */
@@ -570,7 +574,7 @@
 
 static int single_of_to_plat(struct udevice *dev)
 {
-	fdt_addr_t addr;
+	void *addr;
 	fdt_size_t size;
 	struct single_pdata *pdata = dev_get_plat(dev);
 	int ret;
@@ -591,8 +595,8 @@
 		return -EINVAL;
 	}
 
-	addr = dev_read_addr_size_index(dev, 0, &size);
-	if (addr == FDT_ADDR_T_NONE) {
+	addr = dev_read_addr_size_index_ptr(dev, 0, &size);
+	if (!addr) {
 		dev_err(dev, "failed to get base register address\n");
 		return -EINVAL;
 	}
diff --git a/drivers/ram/k3-am654-ddrss.c b/drivers/ram/k3-am654-ddrss.c
index b8338f8..4a8a6a9 100644
--- a/drivers/ram/k3-am654-ddrss.c
+++ b/drivers/ram/k3-am654-ddrss.c
@@ -903,7 +903,7 @@
 static int am654_ddrss_ofdata_to_priv(struct udevice *dev)
 {
 	struct am654_ddrss_desc *ddrss = dev_get_priv(dev);
-	phys_addr_t reg;
+	void *reg;
 	int ret;
 
 	debug("%s(dev=%p)\n", __func__, dev);
@@ -926,26 +926,26 @@
 		return ret;
 	}
 
-	reg = devfdt_get_addr_name(dev, "ss");
-	if (reg == FDT_ADDR_T_NONE) {
+	reg = dev_read_addr_name_ptr(dev, "ss");
+	if (!reg) {
 		dev_err(dev, "No reg property for DDRSS wrapper logic\n");
 		return -EINVAL;
 	}
-	ddrss->ddrss_ss_cfg = (void *)reg;
+	ddrss->ddrss_ss_cfg = reg;
 
-	reg = devfdt_get_addr_name(dev, "ctl");
-	if (reg == FDT_ADDR_T_NONE) {
+	reg = dev_read_addr_name_ptr(dev, "ctl");
+	if (!reg) {
 		dev_err(dev, "No reg property for Controller region\n");
 		return -EINVAL;
 	}
-	ddrss->ddrss_ctl_cfg = (void *)reg;
+	ddrss->ddrss_ctl_cfg = reg;
 
-	reg = devfdt_get_addr_name(dev, "phy");
-	if (reg == FDT_ADDR_T_NONE) {
+	reg = dev_read_addr_name_ptr(dev, "phy");
+	if (!reg) {
 		dev_err(dev, "No reg property for PHY region\n");
 		return -EINVAL;
 	}
-	ddrss->ddrss_phy_cfg = (void *)reg;
+	ddrss->ddrss_phy_cfg = reg;
 
 	ret = dev_read_u32_array(dev, "ti,ss-reg",
 			         (u32 *)&ddrss->params.ss_reg,
diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index b54557f..5b6089e 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -331,32 +331,29 @@
 {
 	struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
 	struct k3_ddrss_data *ddrss_data = (struct k3_ddrss_data *)dev_get_driver_data(dev);
-	phys_addr_t reg;
+	void *reg;
 	int ret;
 
 	debug("%s(dev=%p)\n", __func__, dev);
 
-	reg = dev_read_addr_name(dev, "cfg");
-	if (reg == FDT_ADDR_T_NONE) {
+	reg = dev_read_addr_name_ptr(dev, "cfg");
+	if (!reg) {
 		dev_err(dev, "No reg property for DDRSS wrapper logic\n");
 		return -EINVAL;
 	}
-	ddrss->ddrss_ctl_cfg = (void *)reg;
+	ddrss->ddrss_ctl_cfg = reg;
 
-	reg = dev_read_addr_name(dev, "ctrl_mmr_lp4");
-	if (reg == FDT_ADDR_T_NONE) {
+	reg = dev_read_addr_name_ptr(dev, "ctrl_mmr_lp4");
+	if (!reg) {
 		dev_err(dev, "No reg property for CTRL MMR\n");
 		return -EINVAL;
 	}
-	ddrss->ddrss_ctrl_mmr = (void *)reg;
+	ddrss->ddrss_ctrl_mmr = reg;
 
-	reg = dev_read_addr_name(dev, "ss_cfg");
-	if (reg == FDT_ADDR_T_NONE) {
+	reg = dev_read_addr_name_ptr(dev, "ss_cfg");
+	if (!reg)
 		dev_dbg(dev, "No reg property for SS Config region, but this is optional so continuing.\n");
-		ddrss->ddrss_ss_cfg = NULL;
-	} else {
-		ddrss->ddrss_ss_cfg = (void *)reg;
-	}
+	ddrss->ddrss_ss_cfg = reg;
 
 	ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0);
 	if (ret) {
diff --git a/drivers/soc/ti/k3-navss-ringacc.c b/drivers/soc/ti/k3-navss-ringacc.c
index 9881bff..e028896 100644
--- a/drivers/soc/ti/k3-navss-ringacc.c
+++ b/drivers/soc/ti/k3-navss-ringacc.c
@@ -987,10 +987,10 @@
 	if (!base_cfg)
 		return -EINVAL;
 
-	base_rt = (uint32_t *)devfdt_get_addr_name(dev, "rt");
+	base_rt = dev_read_addr_name_ptr(dev, "rt");
 	pr_debug("rt %p\n", base_rt);
-	if (IS_ERR(base_rt))
-		return PTR_ERR(base_rt);
+	if (!base_rt)
+		return -EINVAL;
 
 	ringacc->rings = devm_kzalloc(dev,
 				      sizeof(*ringacc->rings) *
@@ -1045,9 +1045,9 @@
 	ringacc->tisci = data->tisci;
 	ringacc->tisci_dev_id = data->tisci_dev_id;
 
-	base_rt = (uint32_t *)devfdt_get_addr_name(dev, "ringrt");
-	if (IS_ERR(base_rt))
-		return base_rt;
+	base_rt = dev_read_addr_name_ptr(dev, "ringrt");
+	if (!base_rt)
+		return ERR_PTR(-EINVAL);
 
 	ringacc->rings = devm_kzalloc(dev,
 				      sizeof(*ringacc->rings) *
diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h
index 6d2fa8f..bf8132d 100644
--- a/include/dm/fdtaddr.h
+++ b/include/dm/fdtaddr.h
@@ -19,7 +19,7 @@
  *
  * @dev: Pointer to a device
  *
- * Return: addr
+ * Return: Address, or FDT_ADDR_T_NONE if there is no such property
  */
 fdt_addr_t devfdt_get_addr(const struct udevice *dev);
 
@@ -59,7 +59,7 @@
  * devfdt_remap_addr_name() - Get the reg property of a device, indexed by
  *                            name, as a memory-mapped I/O pointer
  * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *	  'reg-names' property providing named-based identification. @index
+ *	  'reg-names' property providing named-based identification. @name
  *	  indicates the value to search for in 'reg-names'.
  *
  * @dev: Pointer to a device
@@ -87,7 +87,7 @@
  * @index: the 'reg' property can hold a list of <addr, size> pairs
  *	   and @index is used to select which one is required
  *
- * Return: addr
+ * Return: Address, or FDT_ADDR_T_NONE if there is no such property
  */
 fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index);
 
@@ -114,7 +114,7 @@
  * @size: Pointer to size variable - this function returns the size
  *        specified in the 'reg' property here
  *
- * Return: addr
+ * Return: Address, or FDT_ADDR_T_NONE if there is no such property
  */
 fdt_addr_t devfdt_get_addr_size_index(const struct udevice *dev, int index,
 				      fdt_size_t *size);
@@ -139,14 +139,27 @@
  *
  * @dev: Pointer to a device
  * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *	  'reg-names' property providing named-based identification. @index
+ *	  'reg-names' property providing named-based identification. @name
  *	  indicates the value to search for in 'reg-names'.
  *
- * Return: addr
+ * Return: Address, or FDT_ADDR_T_NONE if there is no such property
  */
 fdt_addr_t devfdt_get_addr_name(const struct udevice *dev, const char *name);
 
 /**
+ * devfdt_get_addr_name_ptr() - Get the reg property of a device as a pointer,
+ *                              indexed by name
+ *
+ * @dev: Pointer to a device
+ * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
+ *	  'reg-names' property providing named-based identification. @name
+ *	  indicates the value to search for in 'reg-names'.
+ *
+ * Return: Pointer to addr, or NULL if there is no such property
+ */
+void *devfdt_get_addr_name_ptr(const struct udevice *dev, const char *name);
+
+/**
  * devfdt_get_addr_size_name() - Get the reg property and its size for a device,
  *				 indexed by name
  *
@@ -154,17 +167,35 @@
  *
  * @dev: Pointer to a device
  * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *	  'reg-names' property providing named-based identification. @index
+ *	  'reg-names' property providing named-based identification. @name
  *	  indicates the value to search for in 'reg-names'.
  * @size: Pointer to size variable - this function returns the size
  *        specified in the 'reg' property here
  *
- * Return: addr
+ * Return: Address, or FDT_ADDR_T_NONE if there is no such property
  */
 fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev,
 				     const char *name, fdt_size_t *size);
 
 /**
+ * devfdt_get_addr_size_name_ptr() - Get the reg property for a device as a
+ *                                   pointer, indexed by name
+ *
+ * Returns the address and size specified in the 'reg' property of a device.
+ *
+ * @dev: Pointer to a device
+ * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
+ *	  'reg-names' property providing named-based identification. @name
+ *	  indicates the value to search for in 'reg-names'.
+ * @size: Pointer to size variable - this function returns the size
+ *        specified in the 'reg' property here
+ *
+ * Return: Pointer to addr, or NULL if there is no such property
+ */
+void *devfdt_get_addr_size_name_ptr(const struct udevice *dev,
+				    const char *name, fdt_size_t *size);
+
+/**
  * devfdt_get_addr_pci() - Read an address and handle PCI address translation
  *
  * @dev: Device to read from
diff --git a/include/dm/read.h b/include/dm/read.h
index 3c2eea6..894bc69 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -277,7 +277,7 @@
  *
  * @dev: Device to read from
  * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *	  'reg-names' property providing named-based identification. @index
+ *	  'reg-names' property providing named-based identification. @name
  *	  indicates the value to search for in 'reg-names'.
  *
  * Return: address or FDT_ADDR_T_NONE if not found
@@ -285,11 +285,24 @@
 fdt_addr_t dev_read_addr_name(const struct udevice *dev, const char *name);
 
 /**
+ * dev_read_addr_name_ptr() - Get the reg property of a device as a pointer,
+ *                            indexed by name
+ *
+ * @dev: Device to read from
+ * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
+ *	  'reg-names' property providing named-based identification. @name
+ *	  indicates the value to search for in 'reg-names'.
+ *
+ * Return: pointer or NULL if not found
+ */
+void *dev_read_addr_name_ptr(const struct udevice *dev, const char *name);
+
+/**
  * dev_read_addr_size_name() - Get the reg property of a device, indexed by name
  *
  * @dev: Device to read from
  * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *	  'reg-names' property providing named-based identification. @index
+ *	  'reg-names' property providing named-based identification. @name
  *	  indicates the value to search for in 'reg-names'.
  *  @size: place to put size value (on success)
  *
@@ -299,12 +312,27 @@
 				   fdt_size_t *size);
 
 /**
+ * dev_read_addr_size_name_ptr() - Get the reg property of a device as a pointer,
+ *                                 indexed by name
+ *
+ * @dev: Device to read from
+ * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
+ *	  'reg-names' property providing named-based identification. @name
+ *	  indicates the value to search for in 'reg-names'.
+ *  @size: place to put size value (on success)
+ *
+ * Return: pointer or NULL if not found
+ */
+void *dev_read_addr_size_name_ptr(const struct udevice *dev, const char *name,
+				  fdt_size_t *size);
+
+/**
  * dev_remap_addr_name() - Get the reg property of a device, indexed by name,
  *                         as a memory-mapped I/O pointer
  *
  * @dev: Device to read from
  * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *	  'reg-names' property providing named-based identification. @index
+ *	  'reg-names' property providing named-based identification. @name
  *	  indicates the value to search for in 'reg-names'.
  *
  * Return: pointer or NULL if not found
@@ -980,6 +1008,12 @@
 	return devfdt_get_addr_name(dev, name);
 }
 
+static inline void *dev_read_addr_name_ptr(const struct udevice *dev,
+					   const char *name)
+{
+	return devfdt_get_addr_name_ptr(dev, name);
+}
+
 static inline fdt_addr_t dev_read_addr_size_name(const struct udevice *dev,
 						 const char *name,
 						 fdt_size_t *size)
@@ -987,6 +1021,13 @@
 	return devfdt_get_addr_size_name(dev, name, size);
 }
 
+static inline void *dev_read_addr_size_name_ptr(const struct udevice *dev,
+						const char *name,
+						fdt_size_t *size)
+{
+	return devfdt_get_addr_size_name_ptr(dev, name, size);
+}
+
 static inline fdt_addr_t dev_read_addr(const struct udevice *dev)
 {
 	return devfdt_get_addr(dev);
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 6b29213..c5f14a7 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -221,6 +221,16 @@
 	ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
 	bootflow_iter_uninit(&iter);
 
+	/* Make sure it scans a bootdevs in each target */
+	ut_assertok(env_set("boot_targets", "mmc spi"));
+	ut_asserteq(0, bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+	ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(3, iter.num_devs);
+	ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+	ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
+	ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
+	bootflow_iter_uninit(&iter);
+
 	return 0;
 }
 BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/tools/binman/btool/bootgen.py b/tools/binman/btool/bootgen.py
index f2ca552..1bc9f0a 100644
--- a/tools/binman/btool/bootgen.py
+++ b/tools/binman/btool/bootgen.py
@@ -132,6 +132,6 @@
 
         result = self.build_from_git(
             'https://github.com/Xilinx/bootgen',
-            'all',
+            ['all'],
             'bootgen')
         return result
diff --git a/tools/binman/btool/fiptool.py b/tools/binman/btool/fiptool.py
index c80f827..34002f5 100644
--- a/tools/binman/btool/fiptool.py
+++ b/tools/binman/btool/fiptool.py
@@ -109,6 +109,6 @@
             return None
         result = self.build_from_git(
             'https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git',
-            'fiptool',
+            ['fiptool'],
             'tools/fiptool/fiptool')
         return result
diff --git a/tools/binman/btool/futility.py b/tools/binman/btool/futility.py
index 04c9aef..0d3980d 100644
--- a/tools/binman/btool/futility.py
+++ b/tools/binman/btool/futility.py
@@ -170,7 +170,7 @@
         # .gitcookies file. So use a mirror instead.
         result = self.build_from_git(
             'https://github.com/sjg20/vboot_reference.git',
-            'all',
+            ['all'],
             'build/futility/futility',
             flags=['USE_FLASHROM=0'])
         return result
diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py
index 6117974..ef1da63 100644
--- a/tools/binman/btool/mkeficapsule.py
+++ b/tools/binman/btool/mkeficapsule.py
@@ -80,6 +80,32 @@
 
         return self.run_cmd(*args)
 
+    def generate_empty_capsule(self, image_guid, output_fname,
+                               accept=True):
+        """Generate empty capsules for FWU A/B updates
+
+        Args:
+            image_guid (str): GUID used for identifying the image
+                in case of an accept capsule
+            output_fname (str): Path to the output capsule file
+            accept (bool): Generate an accept capsule,
+                else a revert capsule
+
+        Returns:
+            str: Tool output
+        """
+        if accept:
+            args = [
+                f'--guid={image_guid}',
+                '--fw-accept'
+            ]
+        else:
+            args = [ '--fw-revert' ]
+
+        args += [ output_fname ]
+
+        return self.run_cmd(*args)
+
     def fetch(self, method):
         """Fetch handler for mkeficapsule
 
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index 801bd94..e7b4e93 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -532,6 +532,50 @@
 
 
 
+.. _etype_efi_empty_capsule:
+
+Entry: efi-empty-capsule: Entry for generating EFI Empty Capsule files
+----------------------------------------------------------------------
+
+The parameters needed for generation of the empty capsules can
+be provided as properties in the entry.
+
+Properties / Entry arguments:
+    - image-guid: Image GUID which will be used for identifying the
+      updatable image on the board. Mandatory for accept capsule.
+    - capsule-type - String to indicate type of capsule to generate. Valid
+      values are 'accept' and 'revert'.
+
+For more details on the description of the capsule format, and the capsule
+update functionality, refer Section 8.5 and Chapter 23 in the `UEFI
+specification`_. For more information on the empty capsule, refer the
+sections 2.3.2 and 2.3.3 in the `Dependable Boot specification`_.
+
+A typical accept empty capsule entry node would then look something
+like this::
+
+    empty-capsule {
+            type = "efi-empty-capsule";
+            /* GUID of the image being accepted */
+            image-type-id = SANDBOX_UBOOT_IMAGE_GUID;
+            capsule-type = "accept";
+    };
+
+A typical revert empty capsule entry node would then look something
+like this::
+
+    empty-capsule {
+            type = "efi-empty-capsule";
+            capsule-type = "revert";
+    };
+
+The empty capsules do not have any input payload image.
+
+.. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf
+.. _`Dependable Boot specification`: https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
+
+
+
 .. _etype_encrypted:
 
 Entry: encrypted: Externally built encrypted binary blob
diff --git a/tools/binman/etype/efi_capsule.py b/tools/binman/etype/efi_capsule.py
index 006eb63..e320371 100644
--- a/tools/binman/etype/efi_capsule.py
+++ b/tools/binman/etype/efi_capsule.py
@@ -11,6 +11,24 @@
 from dtoc import fdt_util
 from u_boot_pylib import tools
 
+def get_binman_test_guid(type_str):
+    """Get the test image GUID for binman
+
+    Based on the string passed to the function, return
+    the corresponding GUID.
+
+    Args:
+        type_str: Key value of the type of GUID to look for
+
+    Returns:
+        The actual GUID value (str)
+    """
+    TYPE_TO_GUID = {
+        'binman-test' : '09d7cf52-0720-4710-91d1-08469b7fe9c8'
+    }
+
+    return TYPE_TO_GUID[type_str]
+
 class Entry_efi_capsule(Entry_section):
     """Generate EFI capsules
 
@@ -104,12 +122,6 @@
             self.auth = 1
 
     def BuildSectionData(self, required):
-        def get_binman_test_guid(type_str):
-            TYPE_TO_GUID = {
-                'binman-test' : '09d7cf52-0720-4710-91d1-08469b7fe9c8'
-            }
-            return TYPE_TO_GUID[type_str]
-
         private_key = ''
         public_key_cert = ''
         if self.auth:
diff --git a/tools/binman/etype/efi_empty_capsule.py b/tools/binman/etype/efi_empty_capsule.py
new file mode 100644
index 0000000..064bf9a
--- /dev/null
+++ b/tools/binman/etype/efi_empty_capsule.py
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Linaro Limited
+#
+# Entry-type module for producing an empty  EFI capsule
+#
+
+import os
+
+from binman.entry import Entry
+from binman.etype.efi_capsule import get_binman_test_guid
+from binman.etype.section import Entry_section
+from dtoc import fdt_util
+from u_boot_pylib import tools
+
+class Entry_efi_empty_capsule(Entry_section):
+    """Generate EFI empty capsules
+
+    The parameters needed for generation of the empty capsules can
+    be provided as properties in the entry.
+
+    Properties / Entry arguments:
+    - image-guid: Image GUID which will be used for identifying the
+      updatable image on the board. Mandatory for accept capsule.
+    - capsule-type - String to indicate type of capsule to generate. Valid
+      values are 'accept' and 'revert'.
+
+    For more details on the description of the capsule format, and the capsule
+    update functionality, refer Section 8.5 and Chapter 23 in the `UEFI
+    specification`_. For more information on the empty capsule, refer the
+    sections 2.3.2 and 2.3.3 in the `Dependable Boot specification`_.
+
+    A typical accept empty capsule entry node would then look something like this
+
+    empty-capsule {
+            type = "efi-empty-capsule";
+            /* GUID of image being accepted */
+            image-type-id = SANDBOX_UBOOT_IMAGE_GUID;
+            capsule-type = "accept";
+    };
+
+    A typical revert empty capsule entry node would then look something like this
+
+    empty-capsule {
+            type = "efi-empty-capsule";
+            capsule-type = "revert";
+    };
+
+    The empty capsules do not have any input payload image.
+
+    .. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf
+    .. _`Dependable Boot specification`: https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+        self.required_props = ['capsule-type']
+        self.accept = 0
+        self.revert = 0
+
+    def ReadNode(self):
+        super().ReadNode()
+
+        self.image_guid = fdt_util.GetString(self._node, 'image-guid')
+        self.capsule_type = fdt_util.GetString(self._node, 'capsule-type')
+
+        if self.capsule_type != 'accept' and self.capsule_type != 'revert':
+            self.Raise('capsule-type should be either \'accept\' or \'revert\'')
+
+        if self.capsule_type == 'accept' and not self.image_guid:
+            self.Raise('Image GUID needed for generating accept capsule')
+
+    def BuildSectionData(self, required):
+        uniq = self.GetUniqueName()
+        outfile = self._filename if self._filename else 'capsule.%s' % uniq
+        capsule_fname = tools.get_output_filename(outfile)
+        accept = True if self.capsule_type == 'accept' else False
+        guid = self.image_guid
+        if self.image_guid == "binman-test":
+            guid = get_binman_test_guid('binman-test')
+
+        ret = self.mkeficapsule.generate_empty_capsule(guid, capsule_fname,
+                                                       accept)
+        if ret is not None:
+            return tools.read_file(capsule_fname)
+
+    def AddBintools(self, btools):
+        self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 8e41964..16156b7 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -121,9 +121,14 @@
 TEE_ADDR = 0x5678
 
 # Firmware Management Protocol(FMP) GUID
-FW_MGMT_GUID = 'edd5cb6d2de8444cbda17194199ad92a'
+FW_MGMT_GUID = '6dcbd5ed-e82d-4c44-bda1-7194199ad92a'
 # Image GUID specified in the DTS
-CAPSULE_IMAGE_GUID = '52cfd7092007104791d108469b7fe9c8'
+CAPSULE_IMAGE_GUID = '09d7cf52-0720-4710-91d1-08469b7fe9c8'
+# Windows cert GUID
+WIN_CERT_TYPE_EFI_GUID = '4aafd29d-68df-49ee-8aa9-347d375665a7'
+# Empty capsule GUIDs
+EMPTY_CAPSULE_ACCEPT_GUID = '0c996046-bcc0-4d04-85ec-e1fcedf1c6f8'
+EMPTY_CAPSULE_REVERT_GUID = 'acd58b4b-c0e8-475f-99b5-6b3f7e07aaf0'
 
 class TestFunctional(unittest.TestCase):
     """Functional tests for binman
@@ -7223,52 +7228,94 @@
         self.assertRegex(err,
                          "Image 'image'.*missing bintools.*: bootgen")
 
+    def _GetCapsuleHeaders(self, data):
+        """Get the capsule header contents
+
+        Args:
+            data: Capsule file contents
+
+        Returns:
+            Dict:
+                key: Capsule Header name (str)
+                value: Header field value (str)
+        """
+        capsule_file = os.path.join(self._indir, 'test.capsule')
+        tools.write_file(capsule_file, data)
+
+        out = tools.run('mkeficapsule', '--dump-capsule', capsule_file)
+        lines = out.splitlines()
+
+        re_line = re.compile(r'^([^:\-\t]*)(?:\t*\s*:\s*(.*))?$')
+        vals = {}
+        for line in lines:
+            mat = re_line.match(line)
+            if mat:
+                vals[mat.group(1)] = mat.group(2)
+
+        return vals
+
     def _CheckCapsule(self, data, signed_capsule=False, version_check=False,
                       capoemflags=False):
-        fmp_signature = "4d535331" # 'M', 'S', 'S', '1'
-        fmp_size = "10"
-        fmp_fw_version = "02"
-        oemflag = "0080"
+        fmp_signature = "3153534D" # 'M', 'S', 'S', '1'
+        fmp_size = "00000010"
+        fmp_fw_version = "00000002"
+        capsule_image_index = "00000001"
+        oemflag = "00018000"
+        auth_hdr_revision = "00000200"
+        auth_hdr_cert_type = "00000EF1"
 
-        payload_data = EFI_CAPSULE_DATA
+        payload_data_len = len(EFI_CAPSULE_DATA)
 
-        # TODO - Currently, these offsets for capsule fields are hardcoded.
-        # There are plans to add support to the mkeficapsule tool to dump
-        # the capsule contents which can then be used for capsule
-        # verification.
+        hdr = self._GetCapsuleHeaders(data)
 
-        # Firmware Management Protocol(FMP) GUID - offset(0 - 32)
-        self.assertEqual(FW_MGMT_GUID, data.hex()[:32])
-        # Image GUID - offset(96 - 128)
-        self.assertEqual(CAPSULE_IMAGE_GUID, data.hex()[96:128])
+        self.assertEqual(FW_MGMT_GUID.upper(), hdr['EFI_CAPSULE_HDR.CAPSULE_GUID'])
+
+        self.assertEqual(CAPSULE_IMAGE_GUID.upper(),
+                         hdr['FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID'])
+        self.assertEqual(capsule_image_index,
+                         hdr['FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_INDEX'])
 
         if capoemflags:
-            # OEM Flags - offset(40 - 44)
-            self.assertEqual(oemflag, data.hex()[40:44])
-        if signed_capsule and version_check:
-            # FMP header signature - offset(4770 - 4778)
-            self.assertEqual(fmp_signature, data.hex()[4770:4778])
-            # FMP header size - offset(4778 - 4780)
-            self.assertEqual(fmp_size, data.hex()[4778:4780])
-            # firmware version - offset(4786 - 4788)
-            self.assertEqual(fmp_fw_version, data.hex()[4786:4788])
-            # payload offset signed capsule(4802 - 4808)
-            self.assertEqual(payload_data.hex(), data.hex()[4802:4808])
-        elif signed_capsule:
-            # payload offset signed capsule(4770 - 4776)
-            self.assertEqual(payload_data.hex(), data.hex()[4770:4776])
-        elif version_check:
-            # FMP header signature - offset(184 - 192)
-            self.assertEqual(fmp_signature, data.hex()[184:192])
-            # FMP header size - offset(192 - 194)
-            self.assertEqual(fmp_size, data.hex()[192:194])
-            # firmware version - offset(200 - 202)
-            self.assertEqual(fmp_fw_version, data.hex()[200:202])
-            # payload offset for non-signed capsule with version header(216 - 222)
-            self.assertEqual(payload_data.hex(), data.hex()[216:222])
+            self.assertEqual(oemflag, hdr['EFI_CAPSULE_HDR.FLAGS'])
+
+        if signed_capsule:
+            self.assertEqual(auth_hdr_revision,
+                             hdr['EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wREVISION'])
+            self.assertEqual(auth_hdr_cert_type,
+                             hdr['EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wCERTTYPE'])
+            self.assertEqual(WIN_CERT_TYPE_EFI_GUID.upper(),
+                             hdr['EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.CERT_TYPE'])
+
+        if version_check:
+            self.assertEqual(fmp_signature,
+                             hdr['FMP_PAYLOAD_HDR.SIGNATURE'])
+            self.assertEqual(fmp_size,
+                             hdr['FMP_PAYLOAD_HDR.HEADER_SIZE'])
+            self.assertEqual(fmp_fw_version,
+                             hdr['FMP_PAYLOAD_HDR.FW_VERSION'])
+
+        self.assertEqual(payload_data_len, int(hdr['Payload Image Size']))
+
+    def _CheckEmptyCapsule(self, data, accept_capsule=False):
+        if accept_capsule:
+            capsule_hdr_guid = EMPTY_CAPSULE_ACCEPT_GUID
         else:
-            # payload offset for non-signed capsule with no version header(184 - 190)
-            self.assertEqual(payload_data.hex(), data.hex()[184:190])
+            capsule_hdr_guid = EMPTY_CAPSULE_REVERT_GUID
+
+        hdr = self._GetCapsuleHeaders(data)
+
+        self.assertEqual(capsule_hdr_guid.upper(),
+                         hdr['EFI_CAPSULE_HDR.CAPSULE_GUID'])
+
+        if accept_capsule:
+            capsule_size = "0000002C"
+        else:
+            capsule_size = "0000001C"
+        self.assertEqual(capsule_size,
+                         hdr['EFI_CAPSULE_HDR.CAPSULE_IMAGE_SIZE'])
+
+        if accept_capsule:
+            self.assertEqual(CAPSULE_IMAGE_GUID.upper(), hdr['ACCEPT_IMAGE_GUID'])
 
     def testCapsuleGen(self):
         """Test generation of EFI capsule"""
@@ -7334,5 +7381,38 @@
         self.assertIn("entry is missing properties: image-guid",
                       str(e.exception))
 
+    def testCapsuleGenAcceptCapsule(self):
+        """Test generationg of accept EFI capsule"""
+        data = self._DoReadFile('319_capsule_accept.dts')
+
+        self._CheckEmptyCapsule(data, accept_capsule=True)
+
+    def testCapsuleGenRevertCapsule(self):
+        """Test generationg of revert EFI capsule"""
+        data = self._DoReadFile('320_capsule_revert.dts')
+
+        self._CheckEmptyCapsule(data)
+
+    def testCapsuleGenAcceptGuidMissing(self):
+        """Test that binman errors out on missing image GUID for accept capsule"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('321_capsule_accept_missing_guid.dts')
+
+        self.assertIn("Image GUID needed for generating accept capsule",
+                      str(e.exception))
+
+    def testCapsuleGenEmptyCapsuleTypeMissing(self):
+        """Test that capsule-type is specified"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('322_empty_capsule_type_missing.dts')
+
+        self.assertIn("entry is missing properties: capsule-type",
+                      str(e.exception))
+
+    def testCapsuleGenAcceptOrRevertMissing(self):
+        """Test that both accept and revert capsule are not specified"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('323_capsule_accept_revert_missing.dts')
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/311_capsule.dts b/tools/binman/test/311_capsule.dts
index 8eb4250..0a62ef8 100644
--- a/tools/binman/test/311_capsule.dts
+++ b/tools/binman/test/311_capsule.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			image-index = <0x1>;
diff --git a/tools/binman/test/312_capsule_signed.dts b/tools/binman/test/312_capsule_signed.dts
index d1c76e2..4ab838e 100644
--- a/tools/binman/test/312_capsule_signed.dts
+++ b/tools/binman/test/312_capsule_signed.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			image-index = <0x1>;
diff --git a/tools/binman/test/313_capsule_version.dts b/tools/binman/test/313_capsule_version.dts
index bafef36..19e7e83 100644
--- a/tools/binman/test/313_capsule_version.dts
+++ b/tools/binman/test/313_capsule_version.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			image-index = <0x1>;
diff --git a/tools/binman/test/314_capsule_signed_ver.dts b/tools/binman/test/314_capsule_signed_ver.dts
index 85c784b..649b8cc 100644
--- a/tools/binman/test/314_capsule_signed_ver.dts
+++ b/tools/binman/test/314_capsule_signed_ver.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			image-index = <0x1>;
diff --git a/tools/binman/test/315_capsule_oemflags.dts b/tools/binman/test/315_capsule_oemflags.dts
index f736e87..45853f6 100644
--- a/tools/binman/test/315_capsule_oemflags.dts
+++ b/tools/binman/test/315_capsule_oemflags.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			image-index = <0x1>;
diff --git a/tools/binman/test/316_capsule_missing_key.dts b/tools/binman/test/316_capsule_missing_key.dts
index 2080b50..a14a74e 100644
--- a/tools/binman/test/316_capsule_missing_key.dts
+++ b/tools/binman/test/316_capsule_missing_key.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			image-index = <0x1>;
diff --git a/tools/binman/test/317_capsule_missing_index.dts b/tools/binman/test/317_capsule_missing_index.dts
index aadb61f..99a54d5 100644
--- a/tools/binman/test/317_capsule_missing_index.dts
+++ b/tools/binman/test/317_capsule_missing_index.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			/* Image GUID for testing capsule update */
diff --git a/tools/binman/test/318_capsule_missing_guid.dts b/tools/binman/test/318_capsule_missing_guid.dts
index d76afba..85d3317 100644
--- a/tools/binman/test/318_capsule_missing_guid.dts
+++ b/tools/binman/test/318_capsule_missing_guid.dts
@@ -3,9 +3,6 @@
 /dts-v1/;
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
 	binman {
 		efi-capsule {
 			image-index = <0x1>;
diff --git a/tools/binman/test/319_capsule_accept.dts b/tools/binman/test/319_capsule_accept.dts
new file mode 100644
index 0000000..d48e59f
--- /dev/null
+++ b/tools/binman/test/319_capsule_accept.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	binman {
+		efi-empty-capsule {
+			/* Image GUID for testing capsule update */
+			image-guid = "binman-test";
+			capsule-type = "accept";
+		};
+	};
+};
diff --git a/tools/binman/test/320_capsule_revert.dts b/tools/binman/test/320_capsule_revert.dts
new file mode 100644
index 0000000..bd141ef
--- /dev/null
+++ b/tools/binman/test/320_capsule_revert.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	binman {
+		efi-empty-capsule {
+			capsule-type = "revert";
+		};
+	};
+};
diff --git a/tools/binman/test/321_capsule_accept_missing_guid.dts b/tools/binman/test/321_capsule_accept_missing_guid.dts
new file mode 100644
index 0000000..a0088b1
--- /dev/null
+++ b/tools/binman/test/321_capsule_accept_missing_guid.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	binman {
+		efi-empty-capsule {
+			capsule-type = "accept";
+		};
+	};
+};
diff --git a/tools/binman/test/322_empty_capsule_type_missing.dts b/tools/binman/test/322_empty_capsule_type_missing.dts
new file mode 100644
index 0000000..d356168
--- /dev/null
+++ b/tools/binman/test/322_empty_capsule_type_missing.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	binman {
+		efi-empty-capsule {
+			/* Image GUID for testing capsule update */
+			image-guid = "binman-test";
+		};
+	};
+};
diff --git a/tools/binman/test/323_capsule_accept_revert_missing.dts b/tools/binman/test/323_capsule_accept_revert_missing.dts
new file mode 100644
index 0000000..31268b2
--- /dev/null
+++ b/tools/binman/test/323_capsule_accept_revert_missing.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	binman {
+		efi-empty-capsule {
+			/* Image GUID for testing capsule update */
+			image-guid = "binman-test";
+			capsule-type = "foo";
+		};
+	};
+};
diff --git a/tools/eficapsule.h b/tools/eficapsule.h
index 2099a2e..6efd07d 100644
--- a/tools/eficapsule.h
+++ b/tools/eficapsule.h
@@ -22,6 +22,8 @@
 #define __aligned(x)	__attribute__((__aligned__(x)))
 #endif
 
+#define ARRAY_SIZE(x)		(sizeof(x) / sizeof((x)[0]))
+
 typedef struct {
 	uint8_t b[16];
 } efi_guid_t __aligned(8);
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 52be1f1..b8fc606 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -29,7 +29,7 @@
 efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 
-static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
+static const char *opts_short = "g:i:I:v:p:c:m:o:dhARD";
 
 enum {
 	CAPSULE_NORMAL_BLOB = 0,
@@ -49,6 +49,7 @@
 	{"fw-accept", no_argument, NULL, 'A'},
 	{"fw-revert", no_argument, NULL, 'R'},
 	{"capoemflag", required_argument, NULL, 'o'},
+	{"dump-capsule", no_argument, NULL, 'D'},
 	{"help", no_argument, NULL, 'h'},
 	{NULL, 0, NULL, 0},
 };
@@ -69,6 +70,7 @@
 		"\t-A, --fw-accept  firmware accept capsule, requires GUID, no image blob\n"
 		"\t-R, --fw-revert  firmware revert capsule, takes no GUID, no image blob\n"
 		"\t-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff\n"
+		"\t-D, --dump-capsule          dump the contents of the capsule headers\n"
 		"\t-h, --help                  print a help message\n",
 		tool_name);
 }
@@ -647,6 +649,215 @@
 	return ret;
 }
 
+static void print_guid(void *ptr)
+{
+	int i;
+	efi_guid_t *guid = ptr;
+	const uint8_t seq[] = {
+		3, 2, 1, 0, '-', 5, 4, '-', 7, 6,
+		'-', 8, 9, '-', 10, 11, 12, 13, 14, 15 };
+
+	for (i = 0; i < ARRAY_SIZE(seq); i++) {
+		if (seq[i] == '-')
+			putchar(seq[i]);
+		else
+			printf("%02X", guid->b[seq[i]]);
+	}
+
+	printf("\n");
+}
+
+static uint32_t dump_fmp_payload_header(
+	struct fmp_payload_header *fmp_payload_hdr)
+{
+	if (fmp_payload_hdr->signature == FMP_PAYLOAD_HDR_SIGNATURE) {
+		printf("--------\n");
+		printf("FMP_PAYLOAD_HDR.SIGNATURE\t\t\t: %08X\n",
+		       FMP_PAYLOAD_HDR_SIGNATURE);
+		printf("FMP_PAYLOAD_HDR.HEADER_SIZE\t\t\t: %08X\n",
+		       fmp_payload_hdr->header_size);
+		printf("FMP_PAYLOAD_HDR.FW_VERSION\t\t\t: %08X\n",
+		       fmp_payload_hdr->fw_version);
+		printf("FMP_PAYLOAD_HDR.LOWEST_SUPPORTED_VERSION\t: %08X\n",
+		       fmp_payload_hdr->lowest_supported_version);
+		return fmp_payload_hdr->header_size;
+	}
+
+	return 0;
+}
+
+static void dump_capsule_auth_header(
+	struct efi_firmware_image_authentication *capsule_auth_hdr)
+{
+	printf("EFI_FIRMWARE_IMAGE_AUTH.MONOTONIC_COUNT\t\t: %08lX\n",
+	       capsule_auth_hdr->monotonic_count);
+	printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.dwLENGTH\t: %08X\n",
+	       capsule_auth_hdr->auth_info.hdr.dwLength);
+	printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wREVISION\t: %08X\n",
+	       capsule_auth_hdr->auth_info.hdr.wRevision);
+	printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wCERTTYPE\t: %08X\n",
+	       capsule_auth_hdr->auth_info.hdr.wCertificateType);
+	printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.CERT_TYPE\t: ");
+	print_guid(&capsule_auth_hdr->auth_info.cert_type);
+}
+
+static void dump_fmp_capsule_image_header(
+	struct efi_firmware_management_capsule_image_header *image_hdr)
+{
+	void *capsule_auth_hdr;
+	void *fmp_payload_hdr;
+	uint64_t signature_size = 0;
+	uint32_t payload_size = 0;
+	uint32_t fmp_payload_hdr_size = 0;
+	struct efi_firmware_image_authentication *auth_hdr;
+
+	printf("--------\n");
+	printf("FMP_CAPSULE_IMAGE_HDR.VERSION\t\t\t: %08X\n",
+	       image_hdr->version);
+	printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID\t: ");
+	print_guid(&image_hdr->update_image_type_id);
+	printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_INDEX\t: %08X\n",
+	       image_hdr->update_image_index);
+	printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_SIZE\t\t: %08X\n",
+	       image_hdr->update_image_size);
+	printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_VENDOR_CODE_SIZE\t: %08X\n",
+	       image_hdr->update_vendor_code_size);
+	printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_HARDWARE_INSTANCE\t: %08lX\n",
+	       image_hdr->update_hardware_instance);
+	printf("FMP_CAPSULE_IMAGE_HDR.IMAGE_CAPSULE_SUPPORT\t: %08lX\n",
+	       image_hdr->image_capsule_support);
+
+	printf("--------\n");
+	if (image_hdr->image_capsule_support & CAPSULE_SUPPORT_AUTHENTICATION) {
+		capsule_auth_hdr = (char *)image_hdr + sizeof(*image_hdr);
+		dump_capsule_auth_header(capsule_auth_hdr);
+
+		auth_hdr = capsule_auth_hdr;
+		signature_size = sizeof(auth_hdr->monotonic_count) +
+			auth_hdr->auth_info.hdr.dwLength;
+		fmp_payload_hdr = (char *)capsule_auth_hdr + signature_size;
+	} else {
+		printf("Capsule Authentication Not Enabled\n");
+		fmp_payload_hdr = (char *)image_hdr + sizeof(*image_hdr);
+	}
+
+	fmp_payload_hdr_size = dump_fmp_payload_header(fmp_payload_hdr);
+
+	payload_size = image_hdr->update_image_size - signature_size -
+		fmp_payload_hdr_size;
+	printf("--------\n");
+	printf("Payload Image Size\t\t\t\t: %08X\n", payload_size);
+}
+
+static void dump_fmp_header(
+	struct efi_firmware_management_capsule_header *fmp_hdr)
+{
+	int i;
+	void *capsule_image_hdr;
+
+	printf("EFI_FMP_HDR.VERSION\t\t\t\t: %08X\n", fmp_hdr->version);
+	printf("EFI_FMP_HDR.EMBEDDED_DRIVER_COUNT\t\t: %08X\n",
+	       fmp_hdr->embedded_driver_count);
+	printf("EFI_FMP_HDR.PAYLOAD_ITEM_COUNT\t\t\t: %08X\n",
+	       fmp_hdr->payload_item_count);
+
+	/*
+	 * We currently don't support Embedded Drivers.
+	 * Only worry about the payload items.
+	 */
+	for (i = 0; i < fmp_hdr->payload_item_count; i++) {
+		capsule_image_hdr = (char *)fmp_hdr +
+			fmp_hdr->item_offset_list[i];
+		dump_fmp_capsule_image_header(capsule_image_hdr);
+	}
+}
+
+static void dump_capsule_header(struct efi_capsule_header *capsule_hdr)
+{
+	printf("EFI_CAPSULE_HDR.CAPSULE_GUID\t\t\t: ");
+	print_guid((void *)&capsule_hdr->capsule_guid);
+	printf("EFI_CAPSULE_HDR.HEADER_SIZE\t\t\t: %08X\n",
+	       capsule_hdr->header_size);
+	printf("EFI_CAPSULE_HDR.FLAGS\t\t\t\t: %08X\n", capsule_hdr->flags);
+	printf("EFI_CAPSULE_HDR.CAPSULE_IMAGE_SIZE\t\t: %08X\n",
+	       capsule_hdr->capsule_image_size);
+}
+
+static void normal_capsule_dump(void *capsule_buf)
+{
+	void *fmp_hdr;
+	struct efi_capsule_header *hdr = capsule_buf;
+
+	dump_capsule_header(hdr);
+	printf("--------\n");
+
+	fmp_hdr = (char *)capsule_buf + sizeof(*hdr);
+	dump_fmp_header(fmp_hdr);
+}
+
+static void empty_capsule_dump(void *capsule_buf)
+{
+	efi_guid_t *accept_image_guid;
+	struct efi_capsule_header *hdr = capsule_buf;
+	efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID;
+
+	dump_capsule_header(hdr);
+
+	if (!memcmp(&efi_empty_accept_capsule, &hdr->capsule_guid,
+		    sizeof(efi_guid_t))) {
+		accept_image_guid = (void *)(char *)capsule_buf +
+			sizeof(struct efi_capsule_header);
+		printf("--------\n");
+		printf("ACCEPT_IMAGE_GUID\t\t\t\t: ");
+		print_guid(accept_image_guid);
+	}
+}
+
+static void dump_capsule_contents(char *capsule_file)
+{
+	int fd;
+	char *ptr;
+	efi_guid_t efi_fmp_guid = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
+	efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID;
+	efi_guid_t efi_empty_revert_capsule = FW_REVERT_OS_GUID;
+	struct stat sbuf;
+
+	if (!capsule_file) {
+		fprintf(stderr, "No capsule file provided\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if ((fd = open(capsule_file, O_RDONLY)) < 0) {
+		fprintf(stderr, "Error opening capsule file: %s\n",
+			capsule_file);
+		exit(EXIT_FAILURE);
+	}
+
+	if (fstat(fd, &sbuf) < 0) {
+		fprintf(stderr, "Can't stat capsule file: %s\n", capsule_file);
+		exit(EXIT_FAILURE);
+	}
+
+	if ((ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0))
+	    == MAP_FAILED) {
+		fprintf(stderr, "Can't mmap capsule file: %s\n", capsule_file);
+		exit(EXIT_FAILURE);
+	}
+
+	if (!memcmp(&efi_fmp_guid, ptr, sizeof(efi_guid_t))) {
+		normal_capsule_dump(ptr);
+	} else if (!memcmp(&efi_empty_accept_capsule, ptr,
+		   sizeof(efi_guid_t)) ||
+		   !memcmp(&efi_empty_revert_capsule, ptr,
+			   sizeof(efi_guid_t))) {
+		empty_capsule_dump(ptr);
+	} else {
+		fprintf(stderr, "Unable to decode the capsule file: %s\n",
+			capsule_file);
+		exit(EXIT_FAILURE);
+	}
+}
+
 /**
  * main - main entry function of mkeficapsule
  * @argc:	Number of arguments
@@ -666,6 +877,7 @@
 	unsigned long index, instance;
 	uint64_t mcount;
 	unsigned long oemflags;
+	bool capsule_dump;
 	char *privkey_file, *cert_file;
 	int c, idx;
 	struct fmp_payload_header_params fmp_ph_params = { 0 };
@@ -676,6 +888,7 @@
 	mcount = 0;
 	privkey_file = NULL;
 	cert_file = NULL;
+	capsule_dump = false;
 	dump_sig = 0;
 	capsule_type = CAPSULE_NORMAL_BLOB;
 	oemflags = 0;
@@ -754,12 +967,24 @@
 				exit(1);
 			}
 			break;
+		case 'D':
+			capsule_dump = true;
+			break;
 		default:
 			print_usage();
 			exit(EXIT_SUCCESS);
 		}
 	}
 
+	if (capsule_dump) {
+		if (argc != optind + 1) {
+			fprintf(stderr, "Must provide the capsule file to parse\n");
+			exit(EXIT_FAILURE);
+		}
+		dump_capsule_contents(argv[argc - 1]);
+		exit(EXIT_SUCCESS);
+	}
+
 	/* check necessary parameters */
 	if ((capsule_type == CAPSULE_NORMAL_BLOB &&
 	    ((argc != optind + 2) || !guid ||