Committed. On Thu, May 29, 2008 at 05:13:36PM +0200, Robert Millan wrote: > > This patch implements UUID support in ext2, then in grub-probe and search > command, and finally in update-grub scripts. > > The result is that when UUID can be used (i.e. our /boot is ext2), update-grub > puts the number in grub.cfg as a parameter to search command, and no longer > relies on hardcoded values for the `root' variable. > > This is very helpful specially when device.map only maps to broken drive > names (which happens always on OFW and sometimes on BIOS). > > -- > 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 /.)
> diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/commands/search.c ./commands/search.c > --- ../grub2/commands/search.c 2007-07-22 01:32:19.000000000 +0200 > +++ ./commands/search.c 2008-05-29 16:00:53.000000000 +0200 > @@ -1,7 +1,7 @@ > /* search.c - search devices based on a file or a filesystem label */ > /* > * GRUB -- GRand Unified Bootloader > - * Copyright (C) 2005,2007 Free Software Foundation, Inc. > + * Copyright (C) 2005,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 > @@ -32,6 +32,7 @@ static const struct grub_arg_option opti > { > {"file", 'f', 0, "search devices by a file (default)", 0, 0}, > {"label", 'l', 0, "search devices by a filesystem label", 0, 0}, > + {"fs_uuid", 'u', 0, "search devices by a filesystem UUID", 0, 0}, > {"set", 's', GRUB_ARG_OPTION_OPTIONAL, "set a variable to the first > device found", "VAR", ARG_TYPE_STRING}, > {0, 0, 0, 0, 0, 0} > }; > @@ -85,6 +86,54 @@ search_label (const char *key, const cha > } > > static void > +search_fs_uuid (const char *key, const char *var) > +{ > + int count = 0; > + 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) > + { > + if (grub_strcmp (uuid, key) == 0) > + { > + /* Found! */ > + grub_printf (" %s", name); > + if (count++ == 0 && var) > + grub_env_set (var, name); > + } > + > + grub_free (uuid); > + } > + } > + > + grub_device_close (dev); > + } > + > + grub_errno = GRUB_ERR_NONE; > + return 0; > + } > + > + grub_device_iterate (iterate_device); > + > + if (count == 0) > + grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); > +} > + > +static void > search_file (const char *key, const char *var) > { > int count = 0; > @@ -136,11 +185,13 @@ grub_cmd_search (struct grub_arg_list *s > if (argc == 0) > return grub_error (GRUB_ERR_INVALID_COMMAND, "no argument specified"); > > - if (state[2].set) > - var = state[2].arg ? : "root"; > + if (state[3].set) > + var = state[3].arg ? state[3].arg : "root"; > > if (state[1].set) > search_label (args[0], var); > + else if (state[2].set) > + search_fs_uuid (args[0], var); > else > search_file (args[0], var); > > @@ -151,8 +202,8 @@ GRUB_MOD_INIT(search) > { > (void) mod; /* To stop warning. */ > grub_register_command ("search", grub_cmd_search, GRUB_COMMAND_FLAG_BOTH, > - "search [-f|-l|-s] NAME", > - "Search devices by a file or a filesystem label." > + "search [-f|-l|-u|-s] NAME", > + "Search devices by file, filesystem label or > filesystem UUID." > " If --set is specified, the first device found is" > " set to a variable. If no variable name is" > " specified, \"root\" is used.", > diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/fs/ext2.c ./fs/ext2.c > --- ../grub2/fs/ext2.c 2008-05-29 15:02:13.000000000 +0200 > +++ ./fs/ext2.c 2008-05-29 15:39:27.000000000 +0200 > @@ -120,7 +120,7 @@ struct grub_ext2_sblock > grub_uint32_t feature_compatibility; > grub_uint32_t feature_incompat; > grub_uint32_t feature_ro_compat; > - grub_uint32_t unique_id[4]; > + grub_uint16_t uuid[8]; > char volume_name[16]; > char last_mounted_on[64]; > grub_uint32_t compression_info; > @@ -861,7 +861,39 @@ grub_ext2_label (grub_device_t device, c > if (data) > *label = grub_strndup (data->sblock.volume_name, 14); > else > - *label = 0; > + *label = NULL; > + > +#ifndef GRUB_UTIL > + grub_dl_unref (my_mod); > +#endif > + > + grub_free (data); > + > + return grub_errno; > +} > + > +static grub_err_t > +grub_ext2_uuid (grub_device_t device, char **uuid) > +{ > + struct grub_ext2_data *data; > + grub_disk_t disk = device->disk; > + > +#ifndef GRUB_UTIL > + grub_dl_ref (my_mod); > +#endif > + > + data = grub_ext2_mount (disk); > + if (data) > + { > + *uuid = grub_malloc (40 + sizeof ('\0')); > + grub_sprintf (*uuid, "%02x%02x-%02x-%02x-%02x-%02x%02x%02x", > + grub_be_to_cpu16 (data->sblock.uuid[0]), grub_be_to_cpu16 > (data->sblock.uuid[1]), > + grub_be_to_cpu16 (data->sblock.uuid[2]), grub_be_to_cpu16 > (data->sblock.uuid[3]), > + grub_be_to_cpu16 (data->sblock.uuid[4]), grub_be_to_cpu16 > (data->sblock.uuid[5]), > + grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 > (data->sblock.uuid[7])); > + } > + else > + *uuid = NULL; > > #ifndef GRUB_UTIL > grub_dl_unref (my_mod); > @@ -881,6 +913,7 @@ static struct grub_fs grub_ext2_fs = > .read = grub_ext2_read, > .close = grub_ext2_close, > .label = grub_ext2_label, > + .uuid = grub_ext2_uuid, > .next = 0 > }; > > diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/include/grub/fs.h ./include/grub/fs.h > --- ../grub2/include/grub/fs.h 2008-01-25 23:33:57.000000000 +0100 > +++ ./include/grub/fs.h 2008-05-29 15:21:57.000000000 +0200 > @@ -51,6 +51,11 @@ struct grub_fs > caller. */ > grub_err_t (*label) (grub_device_t device, char **label); > > + /* Return the uuid of the device DEVICE in UUID. The uuid is > + returned in a grub_malloc'ed buffer and should be freed by the > + caller. */ > + grub_err_t (*uuid) (grub_device_t device, char **uuid); > + > /* The next filesystem. */ > struct grub_fs *next; > }; > diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/util/grub.d/00_header.in ./util/grub.d/00_header.in > --- ../grub2/util/grub.d/00_header.in 2008-02-03 19:27:41.000000000 +0100 > +++ ./util/grub.d/00_header.in 2008-05-29 17:04:42.000000000 +0200 > @@ -38,8 +38,12 @@ set default=${GRUB_DEFAULT} > set timeout=${GRUB_TIMEOUT} > EOF > > -if [ "x${GRUB_DRIVE}" = "x" ] ; then : ; else > - echo "set root=${GRUB_DRIVE}" > +# If there's a filesystem UUID that GRUB is capable of identifiing, use it; > +# otherwise set root as per value in device.map. > +if [ "x${GRUB_DEVICE_BOOT_UUID}" = "x" ] ; then > + echo "set root=`grub-probe --device ${GRUB_DEVICE_BOOT} --target=drive`" > +else > + echo "search --fs_uuid ${GRUB_DEVICE_BOOT_UUID} --set" > fi > > case ${platform}:${GRUB_TERMINAL} in > diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/util/grub.d/10_hurd.in ./util/grub.d/10_hurd.in > --- ../grub2/util/grub.d/10_hurd.in 2008-01-10 14:52:24.000000000 +0100 > +++ ./util/grub.d/10_hurd.in 2008-05-29 16:19:11.000000000 +0200 > @@ -31,9 +31,9 @@ for i in /boot/gnumach.gz /boot/gnumach > if test -e $i ; then > basename=`basename $i` > dirname=`dirname $i` > - grub_dirname=`echo ${dirname} | sed -e "s%^/boot%${GRUB_DRIVE_BOOT}%g"` > + rel_dirname=`make_system_path_relative_to_its_root $dirname` > echo "Found GNU Mach: $i" >&2 > - kernel=${grub_dirname}/${basename} > + kernel=${rel_dirname}/${basename} > at_least_one=true > fi > done > diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/util/grub.d/10_linux.in ./util/grub.d/10_linux.in > --- ../grub2/util/grub.d/10_linux.in 2008-04-30 23:08:32.000000000 +0200 > +++ ./util/grub.d/10_linux.in 2008-05-29 16:17:27.000000000 +0200 > @@ -87,7 +87,7 @@ while [ "x$list" != "x" ] ; do > echo "Found linux image: $linux" >&2 > basename=`basename $linux` > dirname=`dirname $linux` > - grub_dirname=`echo ${dirname} | sed -e "s%^/boot%${GRUB_DRIVE_BOOT}%g"` > + rel_dirname=`make_system_path_relative_to_its_root $dirname` > version=`echo $basename | sed -e "s,^[^0-9]*-,,g"` > alt_version=`echo $version | sed -e "s,\.old$,,g"` > > @@ -105,11 +105,11 @@ while [ "x$list" != "x" ] ; do > > cat << EOF > menuentry "${OS}, linux ${version}" { > - linux ${grub_dirname}/${basename} root=${GRUB_DEVICE} ro > ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} > + linux ${rel_dirname}/${basename} root=${GRUB_DEVICE} ro > ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} > EOF > if test -n "${initrd}" ; then > cat << EOF > - initrd ${grub_dirname}/${initrd} > + initrd ${rel_dirname}/${initrd} > EOF > fi > cat << EOF > @@ -118,11 +118,11 @@ EOF > > cat << EOF > menuentry "${OS}, linux ${version} (single-user mode)" { > - linux ${grub_dirname}/${basename} root=${GRUB_DEVICE} ro single > ${GRUB_CMDLINE_LINUX} > + linux ${rel_dirname}/${basename} root=${GRUB_DEVICE} ro single > ${GRUB_CMDLINE_LINUX} > EOF > if test -n "${initrd}" ; then > cat << EOF > - initrd ${grub_dirname}/${initrd} > + initrd ${rel_dirname}/${initrd} > EOF > fi > cat << EOF > diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/util/grub-probe.c ./util/grub-probe.c > --- ../grub2/util/grub-probe.c 2008-05-06 15:34:28.000000000 +0200 > +++ ./util/grub-probe.c 2008-05-29 15:38:29.000000000 +0200 > @@ -44,6 +44,7 @@ > > enum { > PRINT_FS, > + PRINT_FS_UUID, > PRINT_DRIVE, > PRINT_DEVICE, > PRINT_PARTMAP, > @@ -110,6 +111,7 @@ probe (const char *path, char *device_na > char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL; > int abstraction_type; > grub_device_t dev = NULL; > + grub_fs_t fs; > > if (path == NULL) > { > @@ -185,10 +187,13 @@ probe (const char *path, char *device_na > goto end; > } > > + fs = grub_fs_probe (dev); > + if (! fs) > + grub_util_error ("%s", grub_errmsg); > + > if (print == PRINT_FS) > { > struct stat st; > - grub_fs_t fs; > > stat (path, &st); > > @@ -210,19 +215,21 @@ probe (const char *path, char *device_na > > if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size)) > grub_util_error ("files differ"); > - > - fs = file->fs; > - } > - else > - { > - fs = grub_fs_probe (dev); > - if (! fs) > - grub_util_error ("%s", grub_errmsg); > } > - > printf ("%s\n", fs->name); > } > > + if (print == PRINT_FS_UUID) > + { > + char *uuid; > + if (! fs->uuid) > + grub_util_error ("%s does not support UUIDs", fs->name); > + > + fs->uuid (dev, &uuid); > + > + printf ("%s\n", uuid); > + } > + > end: > if (dev) > grub_device_close (dev); > @@ -257,7 +264,7 @@ Probe device information for a given pat > \n\ > -d, --device given argument is a system device, not a path\n\ > -m, --device-map=FILE use FILE as the device map [default=%s]\n\ > - -t, --target=(fs|drive|device|partmap|abstraction)\n\ > + -t, --target=(fs|fs_uuid|drive|device|partmap|abstraction)\n\ > print filesystem module, GRUB drive, system > device, partition map module or abstraction module [default=fs]\n\ > -h, --help display this message and exit\n\ > -V, --version print version information and exit\n\ > @@ -302,6 +309,8 @@ main (int argc, char *argv[]) > case 't': > if (!strcmp (optarg, "fs")) > print = PRINT_FS; > + else if (!strcmp (optarg, "fs_uuid")) > + print = PRINT_FS_UUID; > else if (!strcmp (optarg, "drive")) > print = PRINT_DRIVE; > else if (!strcmp (optarg, "device")) > diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp > ../grub2/util/update-grub.in ./util/update-grub.in > --- ../grub2/util/update-grub.in 2008-05-28 21:56:26.000000000 +0200 > +++ ./util/update-grub.in 2008-05-29 17:03:44.000000000 +0200 > @@ -102,20 +102,16 @@ fi > > # Device containing our userland. Typically used for root= parameter. > GRUB_DEVICE="`grub-probe --target=device /`" > +GRUB_DEVICE_UUID="`grub-probe --device ${GRUB_DEVICE} --target=fs_uuid 2> > /dev/null`" > + > +# Device containing our /boot partition. Usually the same as GRUB_DEVICE. > +GRUB_DEVICE_BOOT="`grub-probe --target=device /boot`" > +GRUB_DEVICE_BOOT_UUID="`grub-probe --device ${GRUB_DEVICE_BOOT} > --target=fs_uuid 2> /dev/null`" > > # Filesystem for the device containing our userland. Used for stuff like > # choosing Hurd filesystem module. > GRUB_FS="`grub-probe --target=fs / 2> /dev/null || echo unknown`" > > -# GRUB path to /. Only used for "set root=". Not critical. > -GRUB_DRIVE="`grub-probe --target=drive /`" || true > - > -# GRUB path to /boot > -GRUB_DRIVE_BOOT="`convert_system_path_to_grub_path /boot`" > - > -# GRUB path to /boot/grub > -GRUB_DRIVE_BOOT_GRUB="`convert_system_path_to_grub_path /boot/grub`" > - > if test -f ${sysconfdir}/default/grub ; then > . ${sysconfdir}/default/grub > fi > @@ -155,7 +151,7 @@ esac > > # These are defined in this script, export them here so that user can > # override them. > -export GRUB_DEVICE GRUB_FS GRUB_DRIVE GRUB_DRIVE_BOOT GRUB_DRIVE_BOOT_GRUB > GRUB_FONT_PATH GRUB_PRELOAD_MODULES > +export GRUB_DEVICE GRUB_DEVICE_UUID GRUB_DEVICE_BOOT GRUB_DEVICE_BOOT_UUID > GRUB_FS GRUB_FONT_PATH GRUB_PRELOAD_MODULES > > # These are optional, user-defined variables. > export GRUB_DEFAULT GRUB_TIMEOUT GRUB_DISTRIBUTOR GRUB_CMDLINE_LINUX > GRUB_CMDLINE_LINUX_DEFAULT GRUB_TERMINAL GRUB_SERIAL_COMMAND > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel -- 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 /.) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel