[RFC PATCH v2] cmd: part: add dupcheck command to detect duplicate PARTUUIDs
Begari, Padmarao
Padmarao.Begari at amd.com
Thu Feb 26 07:08:01 CET 2026
[Public]
Hi Kory Maincent,
> From: Kory Maincent <kory.maincent at bootlin.com>
> Sent: Monday, February 23, 2026 4:04 PM
> To: Begari, Padmarao <Padmarao.Begari at amd.com>
> Cc: u-boot at lists.denx.de; Simek, Michal <michal.simek at amd.com>; git (AMD-
> Xilinx) <git at amd.com>; Toomey, John <john.toomey at amd.com>; Tom Rini
> <trini at konsulko.com>; Ilias Apalodimas <ilias.apalodimas at linaro.org>; Heinrich
> Schuchardt <xypron.glpk at gmx.de>; Quentin Schulz <quentin.schulz at cherry.de>;
> Mikhail Kshevetskiy <mikhail.kshevetskiy at iopsys.eu>; Heiko Schocher
> <hs at nabladev.com>; Andrew Goodbody <andrew.goodbody at linaro.org>; Paul
> Barker <paul.barker.ct at bp.renesas.com>; Rasmus Villemoes <ravi at prevas.dk>
> Subject: Re: [RFC PATCH v2] cmd: part: add dupcheck command to detect duplicate
> PARTUUIDs
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Sun, 22 Feb 2026 12:37:39 +0530
> Padmarao Begari <padmarao.begari at amd.com> wrote:
>
> > Add a 'part dupcheck' subcommand that scans all block devices for
> > duplicate partition UUIDs. This helps detect situations where the same
> > disk image has been flashed to multiple boot devices (e.g., USB stick
> > and UFS), which can lead to unpredictable boot behavior when using
> > PARTUUID-based root filesystem specifications. It iterates all block
> > devices using blk_foreach_probe() and checks partition UUIDs via
> > part_get_info().
> >
> > When duplicates are found, a warning is printed for each occurrence:
> >
> > Warning: duplicate PARTUUID 20c5fba5-0171-457f-b9cd-f5129cd07228
> > first seen on usb_mass_storage.lun0:3
> > also on ufs_scsi.id0lun0:3
> >
> > Add Kconfig option `CMD_PART_DUPCHECK` and update the `part` help text
> > accordingly.
>
> It would be nice to also check the partition label, which is also used sometimes in the
> boot process.
Ok, will check.
>
> > Signed-off-by: John Toomey <john.toomey at amd.com>
> > Signed-off-by: Padmarao Begari <padmarao.begari at amd.com>
> > ---
> > Changes in v2:
> > -Add own kconfig symbol for dupcheck subcommand and guard it.
> > ---
> > cmd/Kconfig | 7 ++++
> > cmd/part.c | 104
> > +++++++++++++++++++++++++++++++++++++++++++++++++++-
> > 2 files changed, 110 insertions(+), 1 deletion(-)
> >
> > diff --git a/cmd/Kconfig b/cmd/Kconfig index 322ebe600c5..73d27fe2e28
> > 100644
> > --- a/cmd/Kconfig
> > +++ b/cmd/Kconfig
> > @@ -1663,6 +1663,13 @@ config CMD_PART
> > Read and display information about the partition table on
> > various media.
> >
> > +config CMD_PART_DUPCHECK
> > + bool "part dupcheck"
> > + depends on CMD_PART
> > + help
> > + Enable the 'part dupcheck' sub-command under 'part' to scan the
> > + current partition table and report any duplicate partition UUIDs.
> > +
> > config CMD_PCI
> > bool "pci - Access PCI devices"
> > help
> > diff --git a/cmd/part.c b/cmd/part.c
> > index 975a0a08a99..c4df5053936 100644
> > --- a/cmd/part.c
> > +++ b/cmd/part.c
> > @@ -15,9 +15,12 @@
> > * Pavel Bartusek <pba at sysgo.com>
> > */
> >
> > +#include <blk.h>
> > #include <config.h>
> > #include <command.h>
> > +#include <dm.h>
> > #include <env.h>
> > +#include <malloc.h>
> > #include <part.h>
> > #include <stdio.h>
> > #include <vsprintf.h>
> > @@ -246,6 +249,97 @@ static int do_part_type(int argc, char *const
> > argv[]) } #endif
> >
> > +#if CONFIG_IS_ENABLED(CMD_PART_DUPCHECK)
> > +struct part_seen {
> > + char uuid[UUID_STR_LEN + 1];
> > + struct udevice *dev;
> > + int part;
> > +};
> > +
> > +static int do_part_dupcheck(int argc, char *const argv[]) {
> > + struct part_seen *seen;
> > + int count = 0;
> > + int duplicates = 0;
> > + int max_entries;
> > + int dev_count;
> > + struct udevice *dev;
> > +
> > + if (argc)
> > + return CMD_RET_USAGE;
> > +
> > + dev_count = blk_count_devices(BLKF_BOTH);
> > + if (!dev_count) {
> > + printf("No block devices found\n");
> > + return CMD_RET_SUCCESS;
> > + }
> > +
> > + max_entries = dev_count * MAX_SEARCH_PARTITIONS;
> > + seen = calloc(max_entries, sizeof(*seen));
> > + if (!seen) {
> > + printf("Unable to allocate dupcheck table (%d entries)\n",
> > + max_entries);
> > + return CMD_RET_FAILURE;
> > + }
> > +
> > + blk_foreach_probe(BLKF_BOTH, dev) {
> > + struct blk_desc *desc = dev_get_uclass_plat(dev);
> > +
> > + for (int part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
> > + struct disk_partition info;
> > + int first_match = -1;
> > +
> > + if (part_get_info(desc, part, &info))
> > + continue;
> > + if (!info.uuid[0])
> > + continue;
> > +
> > + for (int i = 0; i < count; i++) {
> > + if (strcmp(seen[i].uuid, info.uuid))
> > + continue;
> > + if (first_match == -1) {
> > + printf("Warning: duplicate
> > + PARTUUID
> > %s\n",
> > + info.uuid);
> > + printf(" first seen on %s:%d\n",
> > + seen[i].dev->name,
> > + seen[i].part);
> > + printf(" also on %s:%d\n",
> > + dev->name, part);
> > + duplicates++;
> > + first_match = i;
> > + } else {
> > + printf(" also on %s:%d\n",
> > + seen[i].dev->name,
> > + seen[i].part);
> > + }
> > + }
>
> If you have 3 partitions (A,B,C) with the same uuid you will report the information
> twice:
> When processing B: "Warning ... first seen on A:x / also on B:x"
> When processing C: "Warning ... first seen on A:x / also on C:x / also on B:x"
>
> Also this means the duplicates variable will be incremented to 2 which is confusing
> for the print in my last comment:
Ok, will recheck and work on it.
>
> > +
> > + if (count >= max_entries) {
> > + printf("Error: dupcheck capacity %d
> > entries\n",
> > + max_entries);
> > + printf(" exceeded\n");
>
> Weird print here:
> Maybe something like that: "Error: dupcheck capacity exceeded (%d entries)"
Yes, want to do same but it is crossing 80 characters per line.
>
> > + free(seen);
> > + return CMD_RET_FAILURE;
> > + }
> > +
> > + strlcpy(seen[count].uuid, info.uuid,
> > + sizeof(seen[0].uuid));
> > + seen[count].dev = dev;
> > + seen[count].part = part;
> > + count++;
> > + }
> > + }
> > +
> > + if (duplicates)
> > + printf("Found %d duplicate(s) among %d partitions checked\n",
> > + duplicates, count);
>
> So with 3 partitions using the same uuid, it will report "Found 2 duplicate(s) ..."
>
> Which can be confusing. We should report either "1 UUID duplication" or "3 copies
> of the same UUID"
Ok got it.
Regards
Padmarao
>
> > +
> > + free(seen);
> > +
> > + return duplicates ? CMD_RET_FAILURE : CMD_RET_SUCCESS; } #endif
> > +
> > static int do_part_types(int argc, char * const argv[]) {
> > struct part_driver *drv = ll_entry_start(struct part_driver, @@
> > -291,6 +385,10 @@ static int do_part(struct cmd_tbl *cmdtp, int flag,
> > int argc, #ifdef CONFIG_PARTITION_TYPE_GUID
> > else if (!strcmp(argv[1], "type"))
> > return do_part_type(argc - 2, argv + 2);
> > +#endif
> > +#if CONFIG_IS_ENABLED(CMD_PART_DUPCHECK)
> > + else if (!strcmp(argv[1], "dupcheck"))
> > + return do_part_dupcheck(argc - 2, argv + 2);
> > #endif
> > return CMD_RET_USAGE;
> > }
> > @@ -328,5 +426,9 @@ U_BOOT_CMD(
> > "part set <interface> <dev> type\n"
> > " - set partition type for a device\n"
> > "part types\n"
> > - " - list supported partition table types"
> > + " - list supported partition table types\n"
> > +#if CONFIG_IS_ENABLED(CMD_PART_DUPCHECK)
> > + "part dupcheck\n"
> > + " - scan all block devices for duplicate partition UUIDs"
> > +#endif
> > );
>
>
>
> --
> Köry Maincent, Bootlin
> Embedded Linux and kernel engineering
> https://bootlin.com
More information about the U-Boot
mailing list