[PATCH 4/7] board: amd: Add capsule and FWU support
Padmarao Begari
padmarao.begari at amd.com
Thu May 14 12:22:21 CEST 2026
Add configure_capsule_updates() supporting MMC, SD and QSPI/OSPI
boot modes for DFU string generation. Add set_dfu_alt_info() for
FWU multi-bank mode to generate DFU alt info from NOR flash MTD
partitions. Add XILINX_BOOT_IMAGE_GUID for the capsule updatable
firmware image.
Signed-off-by: Padmarao Begari <padmarao.begari at amd.com>
---
board/amd/versal2/board.c | 131 +++++++++++++++++++++++++++++++++-
include/configs/amd_versal2.h | 5 ++
2 files changed, 135 insertions(+), 1 deletion(-)
diff --git a/board/amd/versal2/board.c b/board/amd/versal2/board.c
index d94c1494d53..4e68efc6416 100644
--- a/board/amd/versal2/board.c
+++ b/board/amd/versal2/board.c
@@ -1,17 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 - 2022, Xilinx, Inc.
- * Copyright (C) 2022 - 2025, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022 - 2026, Advanced Micro Devices, Inc.
*
* Michal Simek <michal.simek at amd.com>
*/
#include <cpu_func.h>
+#include <dfu.h>
+#include <env.h>
+#include <efi_loader.h>
#include <fdtdec.h>
+#include <fwu.h>
#include <init.h>
#include <env_internal.h>
#include <log.h>
#include <malloc.h>
+#include <memalign.h>
+#include <mmc.h>
+#include <mtd.h>
#include <time.h>
#include <asm/cache.h>
#include <asm/global_data.h>
@@ -26,6 +33,7 @@
#include "../../xilinx/common/board.h"
#include <linux/bitfield.h>
+#include <linux/sizes.h>
#include <debug_uart.h>
#include <generated/dt.h>
#include <linux/ioport.h>
@@ -347,6 +355,10 @@ int board_late_init(void)
int ret;
u32 multiboot;
+ if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) &&
+ !IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
+ configure_capsule_updates();
+
if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
debug("Saved variables - Skipping\n");
return 0;
@@ -475,3 +487,120 @@ enum env_location env_get_location(enum env_operation op, int prio)
}
}
#endif
+
+#define DFU_ALT_BUF_LEN SZ_1K
+
+#if defined(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) && \
+ !defined(CONFIG_FWU_MULTI_BANK_UPDATE)
+static void mtd_found_part(u32 *base, u32 *size)
+{
+ struct mtd_info *part, *mtd;
+
+ mtd_probe_devices();
+
+ mtd = get_mtd_device_nm("nor0");
+ if (!IS_ERR_OR_NULL(mtd)) {
+ list_for_each_entry(part, &mtd->partitions, node) {
+ debug("0x%012llx-0x%012llx : \"%s\"\n",
+ part->offset, part->offset + part->size,
+ part->name);
+
+ if (*base >= part->offset &&
+ *base < part->offset + part->size) {
+ debug("Found my partition: %d/%s\n",
+ part->index, part->name);
+ *base = part->offset;
+ *size = part->size;
+ break;
+ }
+ }
+ }
+}
+
+void configure_capsule_updates(void)
+{
+ int bootseq = 0, len = 0;
+ u32 multiboot = versal2_multi_boot();
+ u32 bootmode = versal2_get_bootmode();
+
+ ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
+
+ memset(buf, 0, DFU_ALT_BUF_LEN);
+
+ multiboot = env_get_hex("multiboot", multiboot);
+
+ switch (bootmode) {
+ case EMMC_MODE:
+ case SD_MODE:
+ case SD1_LSHFT_MODE:
+ case SD_MODE1:
+ bootseq = mmc_get_env_dev();
+
+ len += snprintf(buf + len, DFU_ALT_BUF_LEN, "mmc %d=boot",
+ bootseq);
+
+ if (multiboot)
+ len += snprintf(buf + len, DFU_ALT_BUF_LEN,
+ "%04d", multiboot);
+
+ len += snprintf(buf + len, DFU_ALT_BUF_LEN, ".bin fat %d 1",
+ bootseq);
+ break;
+ case QSPI_MODE_24BIT:
+ case QSPI_MODE_32BIT:
+ case OSPI_MODE:
+ {
+ u32 base = multiboot * SZ_32K;
+ u32 size = 0x1500000;
+ u32 limit = size;
+
+ mtd_found_part(&base, &limit);
+
+ len += snprintf(buf + len, DFU_ALT_BUF_LEN,
+ "sf 0:0=boot.bin raw 0x%x 0x%x",
+ base, limit);
+ }
+ break;
+ default:
+ return;
+ }
+
+ update_info.dfu_string = strdup(buf);
+ debug("Capsule DFU: %s\n", update_info.dfu_string);
+}
+#endif
+
+#if defined(CONFIG_FWU_MULTI_BANK_UPDATE)
+
+/* Generate dfu_alt_info from partitions */
+void set_dfu_alt_info(char *interface, char *devstr)
+{
+ int ret;
+ struct mtd_info *mtd;
+
+ /*
+ * It is called multiple times for every image
+ * per bank that's why enough to set it up once.
+ */
+ if (env_get("dfu_alt_info"))
+ return;
+
+ ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
+ memset(buf, 0, DFU_ALT_BUF_LEN);
+
+ mtd_probe_devices();
+
+ mtd = get_mtd_device_nm("nor0");
+ if (IS_ERR_OR_NULL(mtd))
+ return;
+
+ ret = fwu_gen_alt_info_from_mtd(buf, DFU_ALT_BUF_LEN, mtd);
+ if (ret < 0) {
+ log_err("Error: Failed to generate dfu_alt_info. (%d)\n", ret);
+ return;
+ }
+ log_debug("Make dfu_alt_info: '%s'\n", buf);
+
+ env_set("dfu_alt_info", buf);
+}
+#endif
diff --git a/include/configs/amd_versal2.h b/include/configs/amd_versal2.h
index fccc786219f..a07e12bd146 100644
--- a/include/configs/amd_versal2.h
+++ b/include/configs/amd_versal2.h
@@ -23,6 +23,11 @@
#define CFG_SYS_BAUDRATE_TABLE \
{ 4800, 9600, 19200, 38400, 57600, 115200 }
+/* GUID for capsule updatable firmware image */
+#define XILINX_BOOT_IMAGE_GUID \
+ EFI_GUID(0xed9e7fcf, 0x47b3, 0x40cd, 0xb6, 0xe3, \
+ 0x56, 0x5f, 0x14, 0x67, 0x6d, 0x82)
+
#if defined(CONFIG_CMD_DFU)
#define DFU_DEFAULT_POLL_TIMEOUT 300
#define DFU_ALT_INFO_RAM \
--
2.34.1
More information about the U-Boot
mailing list