diff mbox series

[V2] handlers: add new handler to check UUID

Message ID 20201027114253.56172-1-sbabic@denx.de
State Accepted
Headers show
Series [V2] handlers: add new handler to check UUID | expand

Commit Message

Stefano Babic Oct. 27, 2020, 11:42 a.m. UTC
This handler checks that FS-UUID are unique, that is there is not yet a
filesystem on the device with the same UUID as provided in one artefact
of the SWU. This is useful in case a bootloader (such as GRUB) will
choose the device to boot from the UUID instead of the partition number.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---

Changes since V1:
	- fix spelling in doc
	- rework help text in Config.in

 Kconfig                       |  4 ++
 Makefile.deps                 |  4 ++
 Makefile.flags                |  4 ++
 doc/source/handlers.rst       | 22 +++++++++++
 handlers/Config.in            | 17 ++++++++
 handlers/Makefile             |  1 +
 handlers/uniqueuuid_handler.c | 74 +++++++++++++++++++++++++++++++++++
 7 files changed, 126 insertions(+)
 create mode 100644 handlers/uniqueuuid_handler.c
diff mbox series

Patch

diff --git a/Kconfig b/Kconfig
index 144cdec..3b610cf 100644
--- a/Kconfig
+++ b/Kconfig
@@ -33,6 +33,10 @@  config HAVE_LIBFDISK
 	bool
 	option env="HAVE_LIBFDISK"
 
+config HAVE_LIBBLKID
+	bool
+	option env="HAVE_LIBBLKID"
+
 config HAVE_LIBGPIOD
 	bool
 	option env="HAVE_LIBGPIOD"
diff --git a/Makefile.deps b/Makefile.deps
index e93367f..6404ed9 100644
--- a/Makefile.deps
+++ b/Makefile.deps
@@ -18,6 +18,10 @@  ifeq ($(HAVE_LIBFDISK),)
 export HAVE_LIBFDISK = y
 endif
 
+ifeq ($(HAVE_LIBBLKID),)
+export HAVE_LIBBLKID = y
+endif
+
 ifeq ($(HAVE_LIBGPIOD),)
 export HAVE_LIBGPIOD = y
 endif
diff --git a/Makefile.flags b/Makefile.flags
index a56f8c2..7003af1 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -181,6 +181,10 @@  ifeq ($(CONFIG_DISKPART),y)
 LDLIBS += fdisk
 endif
 
+ifeq ($(CONFIG_UNIQUEUUID),y)
+LDLIBS += blkid
+endif
+
 ifeq ($(CONFIG_RDIFFHANDLER),y)
 LDLIBS += rsync
 endif
diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
index 603af48..07fb6c2 100644
--- a/doc/source/handlers.rst
+++ b/doc/source/handlers.rst
@@ -835,3 +835,25 @@  MBR Example:
 		partition-6 = ["size=512M", "start=2234368", "name=part6",  "type=0x83"];
 	   }
 	}
+
+Unique UUID Handler
+-------------------
+
+This handler checks if the device already has a filesystems with a provide UUID. This is helpful
+in case the bootloader chooses the device to boot from the UUID and not from the partition number.
+One use case is with the GRUB bootloader when GRUB_DISABLE_LINUX_UUID is not set, as usual on
+Linux Distro as Debian or Ubuntu.
+
+The handler iterates all UUIDs given in sw-description and raises error if one of them is
+found on the device. It is a partition handler and it runs before any image is installed.
+
+::
+
+	partitions: (
+	{
+		type = "uniqueuuid";
+		properties: {
+			fs-uuid = ["21f16cae-612f-4bc6-8ef5-e68cc9dc4380",
+                                   "18e12df1-d8e1-4283-8727-37727eb4261d"];
+		}
+	});
diff --git a/handlers/Config.in b/handlers/Config.in
index 5eea1ab..8571c0c 100644
--- a/handlers/Config.in
+++ b/handlers/Config.in
@@ -102,6 +102,23 @@  config DISKPART
 comment "diskpart support needs libfdisk"
 	depends on !HAVE_LIBFDISK
 
+config UNIQUEUUID
+	bool "uniqueuuid"
+	depends on HAVE_LIBBLKID
+	default n
+	help
+	  This handler checks that no filesystem on the device has
+	  a UUID from a list (list is added as part of "properties"
+	  in sw-description) for this handler.
+	  This is useful for bootloader (like GRUB) that use UUID to
+	  select the partition to be started, and in case two or
+	  more filesystem have the same UUID, a wrong one is started.
+	  This handler is a partition handler and it is guaranteed that
+	  it runs before any image is installed on the device.
+
+comment "uniqueuuid support needs libblkid"
+	depends on !HAVE_LIBBLKID
+
 config RAW
 	bool "raw"
 	default n
diff --git a/handlers/Makefile b/handlers/Makefile
index 1ad62be..1449139 100644
--- a/handlers/Makefile
+++ b/handlers/Makefile
@@ -12,6 +12,7 @@  obj-$(CONFIG_ARCHIVE) += archive_handler.o
 obj-$(CONFIG_BOOTLOADERHANDLER) += boot_handler.o
 obj-$(CONFIG_CFI)	+= flash_handler.o
 obj-$(CONFIG_DISKPART)	+= diskpart_handler.o
+obj-$(CONFIG_UNIQUEUUID)	+= uniqueuuid_handler.o
 obj-$(CONFIG_CFIHAMMING1)+= flash_hamming1_handler.o
 obj-$(CONFIG_LUASCRIPTHANDLER) += lua_scripthandler.o
 obj-$(CONFIG_RAW)	+= raw_handler.o
diff --git a/handlers/uniqueuuid_handler.c b/handlers/uniqueuuid_handler.c
new file mode 100644
index 0000000..fadc8fa
--- /dev/null
+++ b/handlers/uniqueuuid_handler.c
@@ -0,0 +1,74 @@ 
+/*
+ * (C) Copyright 2020
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
+ *
+ * SPDX-License-Identifier:     GPL-2.0-or-later
+ */
+
+/*
+ * This handler does not install, but checks that
+ * there is not a filesystem with a specific UUID on the device.
+ * This is useful in case the bootloader choses the partition to be
+ * started with FS-UUID.
+ */
+#include <stdio.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <blkid/blkid.h>
+#include <sys/types.h>
+#include "swupdate.h"
+#include "handler.h"
+#include "util.h"
+
+void uniqueuuid_handler(void);
+
+static int uniqueuuid(struct img_type *img,
+	void __attribute__ ((__unused__)) *data)
+{
+	struct dict_list *uuids;
+	struct dict_list_elem *uuid;
+	blkid_cache cache = NULL;
+	blkid_dev_iterate	iter;
+	blkid_dev		dev;
+	int ret = 0;
+
+	uuids = dict_get_list(&img->properties, "fs-uuid");
+	if (!uuids) {
+		ERROR("Check for uuids runs, but not uuid given !");
+		return -EINVAL;
+	}
+
+	blkid_get_cache(&cache, NULL);
+
+	blkid_probe_all(cache);
+
+	LIST_FOREACH(uuid, uuids, next) {
+		iter = blkid_dev_iterate_begin(cache);
+		blkid_dev_set_search(iter, "UUID", uuid->value);
+
+		while (blkid_dev_next(iter, &dev) == 0) {
+			dev = blkid_verify(cache, dev);
+			if (!dev)
+				continue;
+			ERROR("UUID=%s not unique on %s !", uuid->value,
+				blkid_dev_devname(dev));
+			ret = -EAGAIN;
+		}
+		blkid_dev_iterate_end(iter);
+	}
+
+	return ret;
+}
+
+__attribute__((constructor))
+void uniqueuuid_handler(void)
+{
+	register_handler("uniqueuuid", uniqueuuid,
+				PARTITION_HANDLER | NO_DATA_HANDLER, NULL);
+}
+