On Tue, Sep 29, 2026 at 14:38:08 +0100, David Lechner wrote: > 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.
I can probably add this to sandbox_spl but you probably want a more robust and general solution for the architecture? > > 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. Fair point. I'll move 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. Agreed, I'll remove it. > > + ret = -ENODEV; > > + goto error; > > + } > > + /* U-Boot does not enable the eMMC cache; reject an unexpected cache. */ > > What code path could lead to this? It was a speculative protection. I just checked if the cache is enabled and it is not, so we can remove the check. > > + 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. Ouch, this is actually something not related to this series. I'll push it as standalone. > > $ 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? No, that is unrelated. > > + > > +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. Wording is probably a bit too strong, it is just not used or tested, especially if the user tries to issue a 'fastboot continue' when in DA. > > + > > +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? That would require an entirely different work not related to this IMO. We are assuming a user intervention for recovery for these edge cases. > > 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. Indeed. > > +/* > > + * 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? This was the reason for the cache check. Not needed anymore. > > + * > > + * 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. This is going to be entirely removed in the next version. > > 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. I'll fix this. > > +#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). ACK > > + > > +#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]> > Thanks! -- Carlo Caione
