On 9/24/26 3:44 PM, Carlo Caione wrote:
> Genio firmware updates use MediaTek v1 metadata in misc to choose
> between bootloaders and bootloaders_b. Support this ABI in SPL so
> systems replacing BL2 can retain their firmware update and boot-success
> handling.
> 
> Make selection opt-in, since trial boots need an updater and a
> boot-success owner to maintain the retry state. Reject corrupt metadata
> and failed state updates rather than silently restarting the retry
> budget.
> 
> Signed-off-by: Carlo Caione <[email protected]>
> ---
> This is intended for systems with an updater and a boot-success owner
> that maintain the MediaTek v1 metadata. The option stays disabled in the
> standard defconfigs. It covers the firmware FIT slots; the DDR loader and
> SPL in boot0 remain shared.

Hmm... this might not get compile-tested if it isn't enabled somewhere by
default. Will have to think about that more. I don't really want a bunch
of defconfigs for every possible usage senario either because it takes time
to compile each one and gets confusing as to which one someone should
actually use.

> 
> This patch depends on the dynamic MMC partition selection series V3 [1].
> The mediatek-staging base e3ed6c6436ab includes both that series and the
> Genio SPL support.
> 
> [1] 
> https://lore.kernel.org/all/20260914-ccaione-upstream-part-dynamic-v3-0-a38c19e74...@baylibre.com/
> ---
>  arch/arm/mach-mediatek/Kconfig          |  17 ++++
>  arch/arm/mach-mediatek/Makefile         |   1 +
>  arch/arm/mach-mediatek/spl_ab.c         |  35 ++++++++
>  doc/board/mediatek/mt8188-genio-evk.rst |  88 +++++++++++++++++++-
>  include/mediatek/mtk_ab.h               |  48 +++++++++++
>  include/mmc.h                           |   1 +
>  lib/Kconfig                             |   1 +
>  lib/Makefile                            |   2 +
>  lib/mediatek/Kconfig                    |   9 +++
>  lib/mediatek/Makefile                   |   3 +
>  lib/mediatek/mtk_ab.c                   | 139 
> ++++++++++++++++++++++++++++++++

I don't see any other vendor libraries in lib/. Probably should live in
arch/arm/mach-mediatek/ with the rest of it.

>  11 files changed, 340 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
> index 13d5819510e..316337949b4 100644
> --- a/arch/arm/mach-mediatek/Kconfig
> +++ b/arch/arm/mach-mediatek/Kconfig
> @@ -221,6 +221,23 @@ config MTK_BROM_HEADER_INFO
>       default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8366 
> || TARGET_MT8183 || TARGET_MT8189 || TARGET_MT8195
>       default "lk=1" if TARGET_MT7623
>  
> +config SPL_MTK_FIRMWARE_AB
> +     bool "MediaTek firmware A/B boot in SPL"
> +     depends on TARGET_MT8188 && SPL_MMC && SPL_LOAD_FIT && SPL_BLK
> +     depends on !SPL_RAW_IMAGE_SUPPORT && !SPL_LEGACY_IMAGE_FORMAT
> +     depends on SPL_EFI_PARTITION
> +     depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC
> +     depends on !SPL_OS_BOOT && !SPL_FS_FAT && !SPL_FS_EXT4
> +     depends on !SPL_FS_SQUASHFS && !SPL_RAM_SUPPORT && !SUPPORT_EMMC_BOOT
> +     select SPL_MTK_AB
> +     select SPL_MMC_WRITE
> +     help
> +       Select firmware FITs from the bootloaders and bootloaders_b GPT
> +       partitions using MediaTek A/B metadata in misc. Track trial boots
> +       and switch slots when retries are exhausted.
> +
> +       An updater and a boot-success owner must maintain the metadata.
> +
>  config MTK_GENIO_BOOT_IMAGES
>       bool "Build MediaTek firmware images"
>       depends on TARGET_MT8188 && SPL
> diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
> index be3604a6776..96eb3ccb35c 100644
> --- a/arch/arm/mach-mediatek/Makefile
> +++ b/arch/arm/mach-mediatek/Makefile
> @@ -5,6 +5,7 @@ obj-y += cpu.o
>  obj-$(CONFIG_MTK_TZ_MOVABLE) += tzcfg.o
>  obj-$(CONFIG_XPL_BUILD)      += spl.o
>  obj-$(CONFIG_MTK_BROM_DOWNLOAD_AGENT_SPL_FASTBOOT)   += spl_fastboot.o
> +obj-$(CONFIG_$(PHASE_)MTK_FIRMWARE_AB) += spl_ab.o
>  
>  obj-$(CONFIG_TARGET_MT7622) += mt7622/
>  obj-$(CONFIG_TARGET_MT7623) += mt7623/
> diff --git a/arch/arm/mach-mediatek/spl_ab.c b/arch/arm/mach-mediatek/spl_ab.c
> new file mode 100644
> index 00000000000..1a4b2f0bcc5
> --- /dev/null
> +++ b/arch/arm/mach-mediatek/spl_ab.c
> @@ -0,0 +1,35 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (c) 2026 BayLibre SAS */
> +
> +#include <mmc.h>
> +#include <mediatek/mtk_ab.h>
> +#include <spl.h>
> +
> +int spl_mmc_boot_partition(struct mmc *mmc, const u32 boot_device)
> +{
> +     struct blk_desc *desc = mmc_get_blk_desc(mmc);
> +     unsigned int slot;
> +     int ret;
> +
> +     /* This platform boots firmware FITs from the eMMC user area only. */
> +     if (IS_SD(mmc) || desc->hwpart || !mmc->ext_csd) {

mtk_ab_select() already checks desc->hwpart so we don't need to do it here too.

> +             ret = -ENODEV;
> +             goto error;
> +     }
> +     /* U-Boot does not enable the eMMC cache; reject an unexpected cache. */

What code path could lead to this?

> +     if (mmc->ext_csd[EXT_CSD_CACHE_CTRL]) {
> +             ret = -EOPNOTSUPP;
> +             goto error;
> +     }
> +
> +     ret = mtk_ab_select(desc, &slot);
> +     if (ret < 0)
> +             goto error;
> +
> +     printf("MediaTek A/B: slot %c, partition %d\n", 'A' + slot, ret);
> +     return ret;
> +
> +error:
> +     printf("MediaTek A/B: selection failed (%d)\n", ret);
> +     return ret;
> +}
> diff --git a/doc/board/mediatek/mt8188-genio-evk.rst 
> b/doc/board/mediatek/mt8188-genio-evk.rst
> index 43948bb4365..2f1d80c04cb 100644
> --- a/doc/board/mediatek/mt8188-genio-evk.rst
> +++ b/doc/board/mediatek/mt8188-genio-evk.rst
> @@ -36,7 +36,8 @@ followed by U-Boot SPL. The DDR loader initializes DRAM, 
> copies the fixed
>  ``CONFIG_MTK_GENIO_DDR_LOADER_SIZE`` to ``CONFIG_SPL_TEXT_BASE`` and enters
>  SPL at EL3 with exceptions masked.
>  
> -SPL reads a FIT image from partition 1 of the eMMC user area. The FIT 
> contains
> +By default, SPL reads a FIT image from partition 1 of the eMMC user area.
> +Optional firmware A/B selection is described below. The FIT contains
>  Arm Trusted Firmware-A (BL31), OP-TEE (BL32), U-Boot proper (BL33) and the
>  U-Boot control devicetree. It is an ordinary, directly parseable FIT whose
>  first word is the FDT magic; the complete FIT container must not be 
> compressed.
> @@ -225,7 +226,9 @@ For example, after enabling 
> ``CONFIG_MTK_GENIO_BOOT_IMAGES`` as above::
>           --enable SHA256 \
>           --enable SPL_FIT_SIGNATURE \
>           --enable SPL_RSA \
> -         --enable SPL_SHA256
> +         --enable SPL_SHA256 \
> +         --disable SPL_RAW_IMAGE_SUPPORT \
> +         --disable SPL_LEGACY_IMAGE_FORMAT

This seems unrelated. Should be a separate patch? Or not necessary? Seems
like these should already be the default.

>     $ make olddefconfig
>     $ make BINMAN_INDIRS=/path/to/firmware-and-keys
>  
> @@ -252,12 +255,12 @@ Image                Destination
>  ===================  ================================================
>  
>  The standard Genio 510 and Genio 700 partition layouts name GPT partition 1
> -``bootloaders``. SPL selects the partition by number through
> +``bootloaders``. By default, SPL selects the partition by number through
>  ``CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION``; it does not locate it by 
> name.
>  
>  Writing an invalid image to eMMC boot0 can make the board unbootable. 
> Preserve
>  the platform recovery path and any backup bootloader partition while testing.
> -Selection of a backup partition is not implemented by this SPL configuration.
> +Selection of a backup partition requires the optional firmware A/B support.
>  
>  Using Genio Tools
>  ~~~~~~~~~~~~~~~~~
> @@ -360,3 +363,80 @@ Use raw images with the eMMC boot-area aliases 
> ``mmc0boot0`` and
>  ``mmc0boot1``: these aliases write the downloaded bytes without expanding
>  Android sparse images. Sparse flashing is supported for GPT partitions and
>  the eMMC user-area alias.
> +
> +Firmware A/B in SPL
> +------------------
> +
> +``CONFIG_SPL_MTK_FIRMWARE_AB`` enables A/B selection for the firmware loaded
> +by SPL from eMMC. It is disabled by default. Enable it only with an updater
> +that activates firmware slots and a service that confirms successful boots.
> +After selecting the board defconfig, enable it with::
> +
> +   $ scripts/config --file "${KBUILD_OUTPUT}/.config" \
> +         --disable SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION \
> +         --enable SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC \
> +         --disable SPL_RAW_IMAGE_SUPPORT \
> +         --disable SPL_LEGACY_IMAGE_FORMAT \
> +         --enable SPL_MTK_FIRMWARE_AB
> +   $ make olddefconfig
> +
> +Install a complete ``bootloaders.img`` FIT in each of the ``bootloaders``
> +(slot A) and ``bootloaders_b`` (slot B) GPT partitions. The ``misc`` 
> partition
> +stores the selected slot and boot-attempt counters. When migrating from BL2,
> +replace the FIP images in both slots with FIT images. If FIT signing is
> +enabled, both images must be signed with a key trusted by the installed SPL.

And we would need the extra option enabled from the previous secton too
for signed FIT images?

> +
> +The DDR loader and SPL in boot0 are shared by both firmware slots. Keep A/B
> +disabled in download-agent builds.

Why does it matter? If there is a technical reason, maybe we should enforce
that in Kconfig.

> +
> +With SPL installed in the standard RITY eMMC layout, the boot flow is::
> +
> +              BootROM
> +                 |
> +                 v
> +   +---------------------------+     +---------------------------+
> +   | boot0                     |     | boot1                     |
> +   | DDR loader -> SPL         |     | U-Boot environment        |
> +   | shared by slots A and B   |     | not a firmware slot       |
> +   +-------------+-------------+     +---------------------------+
> +                 |
> +                 v
> +   +-------------------------------------------------------------+
> +   | eMMC user area (GPT partitions)                             |
> +   |                                                             |
> +   |   +-----------------------------------------------------+   |
> +   |   | misc                                                |   |
> +   |   | Selected firmware slot and boot-attempt counters    |   |
> +   |   +-------------------------+---------------------------+   |
> +   |                             |                               |
> +   |                     select A or B                           |
> +   |              +--------------+--------------+                |
> +   |              v                             v                |
> +   |   +-----------------------+   +-------------------------+   |
> +   |   | bootloaders (slot A)  |   | bootloaders_b (slot B)  |   |
> +   |   | FIT: BL31, BL32, BL33 |   | FIT: BL31, BL32, BL33   |   |
> +   |   +-----------------------+   +-------------------------+   |
> +   +-------------------------------------------------------------+
> +
> +Firmware updates and rollback
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Use an updater and boot-success service compatible with MediaTek firmware
> +A/B metadata:
> +
> +1. Write and verify the new FIT in the inactive slot.
> +2. Activate that slot for trial booting.
> +3. After booting and completing the required health checks, mark the booted
> +   slot successful.
> +
> +A newly activated trial slot has eight boot attempts. Without confirmation,
> +even a working image eventually exhausts its attempts. SPL then selects the
> +other slot on the following boot, provided that slot has attempts remaining
> +or was previously marked successful. Blank metadata initially selects slot A.
> +
> +A failed FIT load or verification stops the current boot. Configure a 
> watchdog
> +or another reset mechanism if unattended retries are required. Keep a working
> +download/recovery path for exhausted slots or damaged metadata, including
> +damage caused by an interrupted metadata update. A slot already marked
> +successful is no longer subject to trial retries; a later failure of that
> +image requires recovery.

Are we going to need to add hooks for these extra recovery paths?

> diff --git a/include/mediatek/mtk_ab.h b/include/mediatek/mtk_ab.h
> new file mode 100644
> index 00000000000..515c8c68f59
> --- /dev/null
> +++ b/include/mediatek/mtk_ab.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: BSD-3-Clause */

I think code added to U-Boot is supposed to be GPL-2.0-or-later, so this
needs AND with both licenses.

> +/*
> + * Copyright (c) 2023, Mediatek Inc. All rights reserved.
> + * Copyright (c) 2026 BayLibre SAS
> + */
> +
> +#ifndef __MEDIATEK_MTK_AB_H
> +#define __MEDIATEK_MTK_AB_H
> +
> +#include <linux/types.h>
> +
> +struct blk_desc;
> +
> +#define MTK_AB_MAGIC 0x544f494d
> +#define MTK_AB_VERSION       1
> +#define MTK_AB_MAX_TRIES     9
> +
> +/* MediaTek v1 disk ABI, including the original AArch64 structure padding. */
> +struct mtk_ab_control {
> +     __le32 slot;
> +     __le32 magic;
> +     u8 version;
> +     u8 tries[2];
> +     u8 padding;
> +     u8 reserved[12];
> +     __le32 crc32;
> +};
> +
> +/**
> + * mtk_ab_select() - Select and account for a MediaTek firmware slot
> + * @desc: Block device containing the GPT user area
> + * @slot: Returns the selected slot (0 for A, 1 for B), only on success
> + *
> + * Resolve bootloaders, bootloaders_b and misc by name, validate the v1 
> record
> + * at the start of misc, and persist any required retry update before 
> returning.
> + * The caller must provide a valid, non-overlapping GPT layout.
> + * A zero counter denotes success; counters 1..8 consume a trial and 9 is
> + * exhausted. Only an all-zero or all-0xff record is initialized 
> automatically.
> + * Writes preserve the rest of the block and are verified with an uncached 
> read.
> + * This single-copy format does not provide power-fail atomicity. The caller
> + * must ensure device write caching cannot hide an uncommitted metadata 
> write.

These last two sentances don't sound reasuring. Does our 
spl_mmc_boot_partition()
implementation handle these?

> + *
> + * Return: Positive GPT partition number to boot, or a negative error. The
> + * caller must stop booting on error; a failed write may have changed 
> storage.
> + */
> +int mtk_ab_select(struct blk_desc *desc, unsigned int *slot);
> +
> +#endif
> diff --git a/include/mmc.h b/include/mmc.h
> index 9a796e0655f..623ca027ccf 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -212,6 +212,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  /*
>   * EXT_CSD fields
>   */
> +#define EXT_CSD_CACHE_CTRL           33      /* R/W */
>  #define EXT_CSD_BOOT_SIZE_MULT_MICRON        125     /* R/W, vendor specific 
> field */
>  #define EXT_CSD_ENH_START_ADDR               136     /* R/W */
>  #define EXT_CSD_ENH_SIZE_MULT                140     /* R/W */

Would be good to split this out into a separate patch since it touches a
separate subsytem.

I would also expect an explantion of why we need EXT_CSD_CACHE_CTRL when
U-Boot hasn't needed it until now.

> diff --git a/lib/Kconfig b/lib/Kconfig
> index b6e65b17ab6..147bf6865be 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -1364,3 +1364,4 @@ config UTHREAD_STACK_SIZE
>  endmenu
>  
>  source "lib/fwu_updates/Kconfig"
> +source "lib/mediatek/Kconfig"
> diff --git a/lib/Makefile b/lib/Makefile
> index 8710be39f3f..646a25a4630 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -3,6 +3,8 @@
>  # (C) Copyright 2000-2006
>  # Wolfgang Denk, DENX Software Engineering, [email protected].
>  
> +obj-$(CONFIG_$(PHASE_)MTK_AB) += mediatek/
> +
>  ifndef CONFIG_XPL_BUILD
>  
>  obj-$(CONFIG_EFI_CLIENT) += efi_client/
> diff --git a/lib/mediatek/Kconfig b/lib/mediatek/Kconfig
> new file mode 100644
> index 00000000000..20110734e1e
> --- /dev/null
> +++ b/lib/mediatek/Kconfig
> @@ -0,0 +1,9 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +config SPL_MTK_AB
> +     bool
> +     depends on SPL && SPL_EFI_PARTITION
> +     select SPL_CRC32
> +     help
> +       Select and account for firmware boot attempts using MediaTek v1
> +       metadata in the misc GPT partition.
> diff --git a/lib/mediatek/Makefile b/lib/mediatek/Makefile
> new file mode 100644
> index 00000000000..71f8dbb374c
> --- /dev/null
> +++ b/lib/mediatek/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-y += mtk_ab.o
> diff --git a/lib/mediatek/mtk_ab.c b/lib/mediatek/mtk_ab.c
> new file mode 100644
> index 00000000000..8fa69bc1dbc
> --- /dev/null
> +++ b/lib/mediatek/mtk_ab.c
> @@ -0,0 +1,139 @@
> +// SPDX-License-Identifier: BSD-3-Clause
> +/*
> + * Copyright (c) 2023, Mediatek Inc. All rights reserved.
> + * Copyright (c) 2026 BayLibre SAS
> + *
> + * Disk format and valid-record transitions follow MediaTek's TF-A mtk_ab.c.
> + */
> +
> +#include <blk.h>
> +#include <log.h>

Either should be including <stdio.h> instead for printf() or switch to log
functions.

> +#include <malloc.h>
> +#include <memalign.h>
> +#include <mediatek/mtk_ab.h>
> +#include <part.h>
> +#include <linux/build_bug.h>
> +#include <linux/errno.h>
> +#include <linux/log2.h>
> +#include <u-boot/crc.h>

And a few more that are only included indirectly.

linux/string.h (memcmp), asm/byteorder.h (cpu_to_le32), linux/kernel.h
(ARRAY_SIZE).

> +
> +#define MTK_AB_MISC_INDEX    2
> +
> +static_assert(sizeof(struct mtk_ab_control) == 28);
> +static_assert(offsetof(struct mtk_ab_control, padding) == 11);
> +static_assert(offsetof(struct mtk_ab_control, reserved) == 12);
> +static_assert(offsetof(struct mtk_ab_control, crc32) == 24);
> +
> +static u32 mtk_ab_crc(const struct mtk_ab_control *ctrl)
> +{
> +     return crc32(0, (const void *)ctrl, offsetof(struct mtk_ab_control, 
> crc32));
> +}
> +
> +static int mtk_ab_layout(struct blk_desc *desc, struct disk_partition *parts,
> +                      int *numbers)
> +{
> +     static const char * const names[] = { "bootloaders", "bootloaders_b", 
> "misc" };
> +     int i;
> +
> +     part_init(desc);
> +     if (desc->part_type != PART_TYPE_EFI)
> +             return -EPROTONOSUPPORT;
> +
> +     for (i = 0; i < ARRAY_SIZE(names); i++) {
> +             numbers[i] = part_get_info_by_name(desc, names[i], &parts[i]);
> +             if (numbers[i] < 0)
> +                     return numbers[i];
> +     }
> +
> +     /* The metadata read-modify-write needs one block in misc. */
> +     if (!parts[MTK_AB_MISC_INDEX].start || !parts[MTK_AB_MISC_INDEX].size ||
> +         parts[MTK_AB_MISC_INDEX].start >= desc->lba)
> +             return -EINVAL;
> +
> +     return 0;
> +}
> +
> +int mtk_ab_select(struct blk_desc *desc, unsigned int *slot)
> +{
> +     struct disk_partition parts[3];
> +     struct mtk_ab_control *ctrl;
> +     unsigned int selected;
> +     int numbers[3], ret;
> +     void *block, *verify;
> +     bool changed = false;
> +
> +     if (!desc || !slot || !desc->lba || desc->hwpart || desc->blksz < 512 ||
> +         desc->blksz > 4096 || !is_power_of_2(desc->blksz) ||
> +         desc->blksz % ARCH_DMA_MINALIGN)
> +             return -EINVAL;
> +
> +     /* Locate all required partitions before updating the metadata. */
> +     ret = mtk_ab_layout(desc, parts, numbers);
> +     if (ret)
> +             return ret;
> +
> +     block = malloc_cache_aligned(2 * desc->blksz);
> +     if (!block)
> +             return -ENOMEM;
> +     verify = block + desc->blksz;
> +     ctrl = block;
> +
> +     ret = -EIO;
> +     blkcache_invalidate(desc->uclass_id, desc->devnum);
> +     if (blk_dread(desc, parts[MTK_AB_MISC_INDEX].start, 1, block) != 1)
> +             goto out;
> +
> +     if (!memchr_inv(ctrl, 0, sizeof(*ctrl)) ||
> +         !memchr_inv(ctrl, 0xff, sizeof(*ctrl))) {
> +             puts("MediaTek A/B: initializing blank metadata\n");
> +             memset(ctrl, 0, sizeof(*ctrl));
> +             ctrl->magic = cpu_to_le32(MTK_AB_MAGIC);
> +             ctrl->version = MTK_AB_VERSION;
> +             ctrl->tries[0] = 1;
> +             ctrl->tries[1] = 1;
> +             selected = 0;
> +             changed = true;
> +     } else {
> +             ret = -EINVAL;
> +             selected = le32_to_cpu(ctrl->slot);
> +             if (le32_to_cpu(ctrl->magic) != MTK_AB_MAGIC ||
> +                 ctrl->version != MTK_AB_VERSION || selected > 1 ||
> +                 ctrl->tries[0] > MTK_AB_MAX_TRIES ||
> +                 ctrl->tries[1] > MTK_AB_MAX_TRIES)
> +                     goto out;
> +             ret = -EBADMSG;
> +             if (le32_to_cpu(ctrl->crc32) != mtk_ab_crc(ctrl))
> +                     goto out;
> +
> +             if (ctrl->tries[selected] == MTK_AB_MAX_TRIES) {
> +                     selected ^= 1;
> +                     ret = -ENOENT;
> +                     if (ctrl->tries[selected] == MTK_AB_MAX_TRIES)
> +                             goto out;
> +                     ctrl->slot = cpu_to_le32(selected);
> +                     changed = true;
> +             }
> +             if (ctrl->tries[selected]) {
> +                     ctrl->tries[selected]++;
> +                     changed = true;
> +             }
> +     }
> +
> +     if (changed) {
> +             ctrl->crc32 = cpu_to_le32(mtk_ab_crc(ctrl));
> +             ret = -EIO;
> +             if (blk_dwrite(desc, parts[MTK_AB_MISC_INDEX].start, 1, block) 
> != 1)
> +                     goto out;
> +             /* Do not verify a write against U-Boot's cached copy. */
> +             blkcache_invalidate(desc->uclass_id, desc->devnum);
> +             if (blk_dread(desc, parts[MTK_AB_MISC_INDEX].start, 1, verify) 
> != 1 ||
> +                 memcmp(block, verify, desc->blksz))
> +                     goto out;
> +     }
> +
> +     *slot = selected;
> +     ret = numbers[selected];
> +out:
> +     free(block);
> +     return ret;
> +}
> 
> ---
> base-commit: e3ed6c6436abc18af0c7a0298ac72f83ebf2b5d1
> change-id: 20260924-ccaione-upstream-mt8390-ab-631b4d4537f7
> 
> Best regards,
> --  
> Carlo Caione <[email protected]>

Reply via email to