[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