[RFC PATCH] cmd: part: add dupcheck command to detect duplicate PARTUUIDs

Padmarao Begari padmarao.begari at amd.com
Sun Feb 15 14:10:47 CET 2026


Add a 'part dupcheck' subcommand (gated by CONFIG_PARTITION_UUIDS)
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

Signed-off-by: John Toomey <john.toomey at amd.com>
Signed-off-by: Padmarao Begari <padmarao.begari at amd.com>
---
 cmd/part.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 103 insertions(+), 1 deletion(-)

diff --git a/cmd/part.c b/cmd/part.c
index 975a0a08a99..31bcdec5e6d 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(PARTITION_UUIDS)
+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 (count >= max_entries) {
+				printf("Error: dupcheck capacity %d entries\n",
+				       max_entries);
+				printf("       exceeded\n");
+				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);
+
+	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(PARTITION_UUIDS)
+	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(PARTITION_UUIDS)
+	"part dupcheck\n"
+	"    - scan all block devices for duplicate partition UUIDs"
+#endif
 );
-- 
2.34.1



More information about the U-Boot mailing list