[PATCH] arm: meson: add support for EFI capsule updates
Evgeny Bachinin
eabachinin at salutedevices.com
Wed Oct 8 14:20:36 CEST 2025
Hello, see below, please
On Tue, Oct 07, 2025 at 07:10:07PM +0000, Ferass El Hafidi wrote:
> Previously, few Amlogic devices supported EFI capsule updates.
> Generally only the Libre Computer ones with SPI flash supported it,
> thanks to board-specific code.
>
> This commit commonises capsule update support across supported
> Amlogic boards. Similar to Qualcomm's support for it, the dfu string
> and firmware name is automatically generated at runtime depending on
> which device we are booted from. Right now this supports flashing to
> the eMMC/SD and SPI flash.
>
> As usual, the capsule UUID is automatically generated. You can get it
> by enabling CONFIG_CMD_EFIDEBUG and running:
>
> => efidebug capsule esrt
> ========================================
> ESRT: fw_resource_count=1
> ESRT: fw_resource_count_max=1
> ESRT: fw_resource_version=1
> [entry 0]==============================
> ESRT: fw_class=796180D4-AAB2-50F1-B16A-53DFF9CA89B2
> ESRT: fw_type=unknown
> ESRT: fw_version=0
> ESRT: lowest_supported_fw_version=0
> ESRT: capsule_flags=0
> ESRT: last_attempt_version=0
> ESRT: last_attempt_status=success
> ========================================
>
> Signed-off-by: Ferass El Hafidi <funderscore at postmarketos.org>
> ---
> Currently EFI capsule updates are only supported on the following
> Amlogic-based boards:
>
> - Libre Computer AML-S805X-AC
> - Libre Computer AML-A311D-CC
> - Libre Computer AML-S905D3-CC
>
> This is done with board-specific configuration in board/libre-computer/.
>
> With this patch, EFI capsule updates can now work on most of the other
> Amlogic boards supported by u-boot, such as the Libre Computer
> AML-S905X-CC, without the need for board-specific configuration
> beforehand.
> ---
> arch/arm/include/asm/arch-meson/boot.h | 2 ++
> arch/arm/mach-meson/Makefile | 2 +-
> arch/arm/mach-meson/board-common.c | 3 ++
> arch/arm/mach-meson/capsule.c | 59 ++++++++++++++++++++++++++++++++++
> 4 files changed, 65 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/include/asm/arch-meson/boot.h b/arch/arm/include/asm/arch-meson/boot.h
> index a11dfde719e3e48e10bcb1f6b1b84eb8586ca9e7..e66b45983fe2f5d81f83642c01502a72773213b2 100644
> --- a/arch/arm/include/asm/arch-meson/boot.h
> +++ b/arch/arm/include/asm/arch-meson/boot.h
> @@ -21,6 +21,8 @@ int meson_get_boot_device(void);
>
> int meson_get_soc_rev(char *buff, size_t buff_len);
>
> +void meson_setup_capsule(void);
> +
minor: maybe, add kernel-doc description ?
(up to you & maintainers)
> /**
> * meson_get_socinfo - retrieve cpu_id of the Amlogic SoC
> *
> diff --git a/arch/arm/mach-meson/Makefile b/arch/arm/mach-meson/Makefile
> index 535b0878b9105e7a83729bea65fa4cd70cd4beac..640921e2b8e9b4777f0b212991edea26de2987d4 100644
> --- a/arch/arm/mach-meson/Makefile
> +++ b/arch/arm/mach-meson/Makefile
> @@ -2,7 +2,7 @@
> #
> # Copyright (c) 2016 Beniamino Galvani <b.galvani at gmail.com>
>
> -obj-y += board-common.o sm.o board-info.o
> +obj-y += board-common.o sm.o board-info.o capsule.o
> obj-$(CONFIG_MESON_GX) += board-gx.o
> obj-$(CONFIG_MESON_AXG) += board-axg.o
> obj-$(CONFIG_MESON_G12A) += board-g12a.o
> diff --git a/arch/arm/mach-meson/board-common.c b/arch/arm/mach-meson/board-common.c
> index 39774c43049a40ed11578086603717571bedd23b..df9f576e7d2a1ce77b9a98259de4c3abf87784ed 100644
> --- a/arch/arm/mach-meson/board-common.c
> +++ b/arch/arm/mach-meson/board-common.c
> @@ -145,6 +145,9 @@ int board_late_init(void)
> {
> meson_set_boot_source();
>
> + /* Generate dfu_string for EFI capsule updates */
> + meson_setup_capsule();
> +
How many AMlogic boards in the wild support DFU by default and 'EFI
capsule updates'?
I assume the answer: "not all boards", because meson arch does not
select CONFIG_DFU (or similar) for all meson-boards by default in
related Kconfig files. CMIIW, please.
board-common.c - is a common file for any Amlogic board, hence any
board-specific addition must be at least under ifdef guards.
But ifdefs suggest that something wrong is here.
>From architecture p.o.v the board specific code should go in a strong
implementation of, say, meson_board_late_init(), residing in your
board_specific.c, where board_specific.c can be actually common for all
your Libre Computer boards.
P.S> sorry, if my assumption about question above is wrong.
> return meson_board_late_init();
> }
>
> diff --git a/arch/arm/mach-meson/capsule.c b/arch/arm/mach-meson/capsule.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..a798f8a3e8c3a8807720af4ef89ccfc20f22f2f8
> --- /dev/null
> +++ b/arch/arm/mach-meson/capsule.c
> @@ -0,0 +1,59 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2025, Ferass El Hafidi <funderscore at postmarketos.org>
> + */
> +
> +#include <dm.h>
> +#include <asm/arch/boot.h>
> +#include <efi_loader.h>
> +#include <mmc.h>
According to coding style, ABC order is needed here
https://docs.u-boot.org/en/latest/develop/codingstyle.html#include-files
> +
> +/*
> + * To be able to support multiple devices and flash to the correct one we need
> + * to automatically generate the dfu_string and fw_name to match the device we
> + * are booted from. This is done by meson_setup_capsule() which is then called
> + * in board_late_init(). Right now we support EFI capsule updates on SPI flash,
Extra space after `in board_late_init(). Right...`
and `booted from. This...`
> + * eMMC and SD cards.
> + */
> +struct efi_fw_image fw_images[] = {
> + {
> + .image_index = 1,
> + },
> +};
> +
> +struct efi_capsule_update_info update_info = {
> + .dfu_string = NULL, /* to be set in meson_capsule_setup */
> + .num_images = ARRAY_SIZE(fw_images),
> + .images = fw_images,
> +};
> +
> +/*
> + * TODO: Support usecase e.g. FIT image on eMMC + SPL on SD.
> + */
> +void meson_setup_capsule(void)
> +{
> + static char dfu_string[32] = { 0 };
> + int mmc_devnum = 0; /* mmc0 => SD card */
> + static uint32_t max_size = 0x2000; /* 4 MB */
1) JFYI, checkpatch warns:
```
CHECK: Prefer kernel type 'u32' over 'uint32_t'
#125: FILE: arch/arm/mach-meson/capsule.c:37:
+ static uint32_t max_size = 0x2000; /* 4 MB */
```
2) BTW, why is it static? Looks like it could be just local var
3) 0x2000 does not match 4 MB or I did not get.
> + uint32_t offset = 0x1; /* offset for flashing to eMMC/SD */
```
CHECK: Prefer kernel type 'u32' over 'uint32_t'
#126: FILE: arch/arm/mach-meson/capsule.c:38:
+ uint32_t offset = 0x1; /* offset for flashing to eMMC/SD */
```
> + int boot_device = meson_get_boot_device();
> +
> + switch (boot_device) {
> + case BOOT_DEVICE_EMMC:
> + mmc_devnum = 1; /* mmc1 is always eMMC */
Is it intentional omission of `break;` here? If yes, I'd suggest to
explicitly write (for readability): /* fall through */
> + case BOOT_DEVICE_SD:
> + snprintf(dfu_string, 32, "mmc %d=u-boot.bin raw %d %d", mmc_devnum, offset, max_size);
> + fw_images[0].fw_name = u"U_BOOT_MESON_MMC";
> + break;
> + case BOOT_DEVICE_SPI:
> + /* We assume there's only one SPI flash */
> + fw_images[0].fw_name = u"U_BOOT_MESON_SPI";
> + snprintf(dfu_string, 32, "sf 0:0=u-boot.bin raw 0 %d", max_size);
> + break;
> + default:
> + debug("Boot device %d unsupported\n", boot_device);
minor:
is it intended to execute below code in a case when boot device is
unsupported? may be just return, here? or `/* fall through */` ?
> + }
> + debug("EFI Capsule DFU string: %s", dfu_string);
> +
> + update_info.dfu_string = dfu_string;
> +}
>
> ---
> base-commit: 072264c4b3406aee50dad08355588577a547ab48
> change-id: 20251007-meson-capsule-a19539e0a54e
>
> Best regards,
> --
> Ferass El Hafidi <funderscore at postmarketos.org>
>
--
Best Regards,
Evgeny Bachinin
More information about the U-Boot
mailing list