From: Robert Millan <rmh@aybabtu.com>
To: grub-devel@gnu.org
Subject: Re: [PATCH] UUID support
Date: Fri, 30 May 2008 13:04:18 +0200 [thread overview]
Message-ID: <20080530110418.GC21035@thorin> (raw)
In-Reply-To: <20080529151336.GA6158@thorin>
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 /.)
prev parent reply other threads:[~2008-05-30 11:04 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-29 15:13 [PATCH] UUID support Robert Millan
2008-05-29 16:50 ` Bean
2008-05-29 18:17 ` Robert Millan
2008-05-29 18:49 ` Bean
2008-05-30 10:41 ` Robert Millan
2008-05-30 13:14 ` Robert Millan
2008-05-30 13:26 ` Bean
2008-05-30 14:07 ` Robert Millan
2008-05-30 11:04 ` Robert Millan [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080530110418.GC21035@thorin \
--to=rmh@aybabtu.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.