From aebe3d13bb9353bc4985f5731769a32f15d8d50a Mon Sep 17 00:00:00 2001 From: robertmh Date: Thu, 26 Jun 2008 14:26:07 +0000 Subject: [PATCH] 2008-06-26 Robert Millan * 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(). --- ChangeLog | 11 ++++ conf/common.mk | 58 ++++++++++++++++++- conf/common.rmk | 7 ++- disk/fs_uuid.c | 137 ++++++++++++++++++++++++++++++++++++++++++++ include/grub/disk.h | 1 + kern/disk.c | 2 +- 6 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 disk/fs_uuid.c diff --git a/ChangeLog b/ChangeLog index d5aa52455..d8a5674ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-06-26 Robert Millan + + * 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(). + 2008-06-26 Robert Millan * util/grub.d/10_linux.in: Avoid passing UUIDs to Linux when either diff --git a/conf/common.mk b/conf/common.mk index 0b8cacf66..9228f1cbf 100644 --- a/conf/common.mk +++ b/conf/common.mk @@ -1938,7 +1938,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 @@ -2614,6 +2614,62 @@ partmap-loopback_mod-disk_loopback.lst: disk/loopback.c $(disk/loopback.c_DEPEND loopback_mod_CFLAGS = $(COMMON_CFLAGS) loopback_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For fs_uuid.mod +fs_uuid_mod_SOURCES = disk/fs_uuid.c +CLEANFILES += fs_uuid.mod mod-fs_uuid.o mod-fs_uuid.c pre-fs_uuid.o fs_uuid_mod-disk_fs_uuid.o und-fs_uuid.lst +ifneq ($(fs_uuid_mod_EXPORTS),no) +CLEANFILES += def-fs_uuid.lst +DEFSYMFILES += def-fs_uuid.lst +endif +MOSTLYCLEANFILES += fs_uuid_mod-disk_fs_uuid.d +UNDSYMFILES += und-fs_uuid.lst + +fs_uuid.mod: pre-fs_uuid.o mod-fs_uuid.o + -rm -f $@ + $(TARGET_CC) $(fs_uuid_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-fs_uuid.o: $(fs_uuid_mod_DEPENDENCIES) fs_uuid_mod-disk_fs_uuid.o + -rm -f $@ + $(TARGET_CC) $(fs_uuid_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ fs_uuid_mod-disk_fs_uuid.o + +mod-fs_uuid.o: mod-fs_uuid.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -c -o $@ $< + +mod-fs_uuid.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'fs_uuid' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(fs_uuid_mod_EXPORTS),no) +def-fs_uuid.lst: pre-fs_uuid.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fs_uuid/' > $@ +endif + +und-fs_uuid.lst: pre-fs_uuid.o + echo 'fs_uuid' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +fs_uuid_mod-disk_fs_uuid.o: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES) + $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -MD -c -o $@ $< +-include fs_uuid_mod-disk_fs_uuid.d + +CLEANFILES += cmd-fs_uuid_mod-disk_fs_uuid.lst fs-fs_uuid_mod-disk_fs_uuid.lst partmap-fs_uuid_mod-disk_fs_uuid.lst +COMMANDFILES += cmd-fs_uuid_mod-disk_fs_uuid.lst +FSFILES += fs-fs_uuid_mod-disk_fs_uuid.lst +PARTMAPFILES += partmap-fs_uuid_mod-disk_fs_uuid.lst + +cmd-fs_uuid_mod-disk_fs_uuid.lst: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh fs_uuid > $@ || (rm -f $@; exit 1) + +fs-fs_uuid_mod-disk_fs_uuid.lst: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh fs_uuid > $@ || (rm -f $@; exit 1) + +partmap-fs_uuid_mod-disk_fs_uuid.lst: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh fs_uuid > $@ || (rm -f $@; exit 1) + + +fs_uuid_mod_CFLAGS = $(COMMON_CFLAGS) +fs_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For configfile.mod configfile_mod_SOURCES = commands/configfile.c CLEANFILES += configfile.mod mod-configfile.o mod-configfile.c pre-configfile.o configfile_mod-commands_configfile.o und-configfile.lst diff --git a/conf/common.rmk b/conf/common.rmk index acbebc7b7..f34a2bf3b 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -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 --git a/disk/fs_uuid.c b/disk/fs_uuid.c new file mode 100644 index 000000000..47eb228c0 --- /dev/null +++ b/disk/fs_uuid.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include + +#include + +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 --git a/include/grub/disk.h b/include/grub/disk.h index 3178203c0..0e2789219 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -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 --git a/kern/disk.c b/kern/disk.c index 2bbc8c54a..980b5056a 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -202,7 +202,7 @@ grub_disk_dev_iterate (int (*hook) (const char *name)) 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;