2008-06-06 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(). 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 . + */ + +#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 -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;