This disk driver allows access to partitions that contain a filesystem with
known UUID via "(UUID=xxxxxxx)" syntax.

The iterator is unimplemented on purpose, because it makes the code smaller
and it isn't useful to waste time inspecting the same devices twice while
scanning for LVM / whatsoever.

Also note that as it currently stands it is highly inefficient.  I can't
understand why;  new UUIDs are searched everytime on each open() call, but
this shouldn't be much of an issue since we have a disk cache in kernel to
make that efficient.  At least, it isn't e.g. for grub_fs_probe() which is
called multiple times.

Even with this efficiency problem, since it doesn't interfere with anything
else I'm inclined to commit it, if nobody objects.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What good is a phone call… if you are unable to speak?
(as seen on /.)
2008-06-06  Robert Millan  <[EMAIL PROTECTED]>

	* disk/fs_uuid.c: New file.
	* conf/common.rmk (pkglib_MODULES): Add `fs_uuid.mod'.
	(fs_uuid_mod_SOURCES, fs_uuid_mod_CFLAGS)
	(fs_uuid_mod_LDFLAGS): New variables.
	* include/grub/disk.h (grub_disk_dev_id): Add
	`GRUB_DISK_DEVICE_UUID_ID'.
	* kern/disk.c (grub_disk_dev_iterate): Allow disk devices not to
	implement iterate().

diff -N -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/conf/common.rmk ./conf/common.rmk
--- ../grub2/conf/common.rmk	2008-04-13 14:11:33.000000000 +0200
+++ ./conf/common.rmk	2008-06-05 02:09:31.000000000 +0200
@@ -280,7 +280,7 @@ lvm_mod_LDFLAGS = $(COMMON_LDFLAGS)
 # Commands.
 pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod	\
 	cmp.mod cat.mod help.mod font.mod search.mod		\
-	loopback.mod configfile.mod echo.mod			\
+	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
 	read.mod sleep.mod
 
@@ -344,6 +344,11 @@ loopback_mod_SOURCES = disk/loopback.c
 loopback_mod_CFLAGS = $(COMMON_CFLAGS)
 loopback_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For fs_uuid.mod
+fs_uuid_mod_SOURCES = disk/fs_uuid.c
+fs_uuid_mod_CFLAGS = $(COMMON_CFLAGS)
+fs_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For configfile.mod
 configfile_mod_SOURCES = commands/configfile.c
 configfile_mod_CFLAGS = $(COMMON_CFLAGS)
diff -N -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/disk/fs_uuid.c ./disk/fs_uuid.c
--- ../grub2/disk/fs_uuid.c	1970-01-01 01:00:00.000000000 +0100
+++ ./disk/fs_uuid.c	2008-06-05 21:53:38.000000000 +0200
@@ -0,0 +1,137 @@
+/* fs_uuid.c - Access disks by their filesystem UUID.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+#include <grub/fs.h>
+
+static grub_device_t
+search_fs_uuid (const char *key, unsigned long *count)
+{
+  *count = 0;
+  grub_device_t ret = NULL;
+
+  auto int iterate_device (const char *name);
+  int iterate_device (const char *name)
+    {
+      grub_device_t dev;
+
+      dev = grub_device_open (name);
+      if (dev)
+	{
+	  grub_fs_t fs;
+	  
+	  fs = grub_fs_probe (dev);
+	  if (fs && fs->uuid)
+	    {
+	      char *uuid;
+	      
+	      (fs->uuid) (dev, &uuid);
+	      if (grub_errno == GRUB_ERR_NONE && uuid)
+		{
+		  *count++;
+
+		  if (grub_strcmp (uuid, key) == 0)
+		    {
+		      ret = dev;
+		      grub_free (uuid);
+		      return 1;
+		    }
+		  grub_free (uuid);
+		}
+	    }
+	  
+	  grub_device_close (dev);
+	}
+
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+  
+  grub_device_iterate (iterate_device);
+  
+  return ret;
+}
+
+static grub_err_t
+grub_fs_uuid_open (const char *name, grub_disk_t disk)
+{
+  grub_device_t dev;
+
+  if (grub_strncmp (name, "UUID=", sizeof ("UUID=")-1))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a UUID virtual volume");
+
+  dev = search_fs_uuid (name + sizeof ("UUID=") - 1, &disk->id);
+  if (! dev)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching UUID found");
+
+  disk->total_sectors = dev->disk->total_sectors;
+  disk->has_partitions = 0;
+  disk->partition = dev->disk->partition;
+  disk->data = dev->disk;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_fs_uuid_close (grub_disk_t disk __attribute((unused)))
+{
+}
+
+static grub_err_t
+grub_fs_uuid_read (grub_disk_t disk, grub_disk_addr_t sector,
+		   grub_size_t size, char *buf)
+{
+  grub_disk_t parent = disk->data;
+  return parent->dev->read (parent, sector, size, buf);
+}
+
+static grub_err_t
+grub_fs_uuid_write (grub_disk_t disk, grub_disk_addr_t sector,
+		    grub_size_t size, const char *buf)
+{
+  grub_disk_t parent = disk->data;
+  return parent->dev->write (parent, sector, size, buf);
+}
+
+static struct grub_disk_dev grub_fs_uuid_dev =
+  {
+    .name = "fs_uuid",
+    .id = GRUB_DISK_DEVICE_UUID_ID,
+    .open = grub_fs_uuid_open,
+    .close = grub_fs_uuid_close,
+    .read = grub_fs_uuid_read,
+    .write = grub_fs_uuid_write,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(fs_uuid)
+{
+  grub_disk_dev_register (&grub_fs_uuid_dev);
+}
+
+GRUB_MOD_FINI(fs_uuid)
+{
+  grub_disk_dev_unregister (&grub_fs_uuid_dev);
+}
diff -N -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/include/grub/disk.h ./include/grub/disk.h
--- ../grub2/include/grub/disk.h	2008-04-26 19:51:01.000000000 +0200
+++ ./include/grub/disk.h	2008-06-05 22:45:34.000000000 +0200
@@ -38,6 +38,7 @@ enum grub_disk_dev_id
     GRUB_DISK_DEVICE_ATA_ID,
     GRUB_DISK_DEVICE_MEMDISK_ID,
     GRUB_DISK_DEVICE_NAND_ID,
+    GRUB_DISK_DEVICE_UUID_ID,
   };
 
 struct grub_disk;
diff -N -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/kern/disk.c ./kern/disk.c
--- ../grub2/kern/disk.c	2008-02-08 13:22:51.000000000 +0100
+++ ./kern/disk.c	2008-06-05 22:46:24.000000000 +0200
@@ -202,7 +202,7 @@ grub_disk_dev_iterate (int (*hook) (cons
   grub_disk_dev_t p;
 
   for (p = grub_disk_dev_list; p; p = p->next)
-    if ((p->iterate) (hook))
+    if (p->iterate && (p->iterate) (hook))
       return 1;
 
   return 0;
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to