2008-05-30 Robert Millan <rmh@aybabtu.com>

* commands/search.c (options): Add --fs_uuid option.
        (search_fs_uuid): New function.
        (grub_cmd_search): Fix --set argument passing.
        Use search_fs_uuid() when requested via --fs_uuid.
        (grub_search_init): Update help message.
        * fs/ext2.c (struct grub_ext2_sblock): Rename `unique_id' to `uuid'
        and redeclare it as an array of 16-bit words.
        (grub_ext2_uuid): New function.
        (grub_ext2_fs): Reference grub_ext2_uuid() in `uuid' struct member.
        * include/grub/fs.h (struct grub_fs): Add `uuid' struct member.
        * util/update-grub.in (GRUB_DEVICE_UUID, GRUB_DEVICE_BOOT)
        (GRUB_DEVICE_BOOT_UUID): New variables.
        (GRUB_DRIVE. GRUB_DRIVE_BOOT. GRUB_DRIVE_BOOT_GRUB): Remove.
        * util/grub.d/00_header.in: Set root using `search --fs_uuid' command
        whenever possible.
        * util/grub.d/10_hurd.in: Avoid explicit use of root drive.  Instead,
        just assume `root' variable has the right value.
        * util/grub.d/10_linux.in: Likewise.
        * util/grub-probe.c (probe): Probe for filesystem UUID when requested
        via PRINT_FS_UUID.
        (main): Recognise `-t fs_uuid' argument.
This commit is contained in:
robertmh 2008-05-30 11:04:08 +00:00
parent 01b73ec8eb
commit 6219127445
9 changed files with 159 additions and 37 deletions

View file

@ -1,3 +1,27 @@
2008-05-30 Robert Millan <rmh@aybabtu.com>
* commands/search.c (options): Add --fs_uuid option.
(search_fs_uuid): New function.
(grub_cmd_search): Fix --set argument passing.
Use search_fs_uuid() when requested via --fs_uuid.
(grub_search_init): Update help message.
* fs/ext2.c (struct grub_ext2_sblock): Rename `unique_id' to `uuid'
and redeclare it as an array of 16-bit words.
(grub_ext2_uuid): New function.
(grub_ext2_fs): Reference grub_ext2_uuid() in `uuid' struct member.
* include/grub/fs.h (struct grub_fs): Add `uuid' struct member.
* util/update-grub.in (GRUB_DEVICE_UUID, GRUB_DEVICE_BOOT)
(GRUB_DEVICE_BOOT_UUID): New variables.
(GRUB_DRIVE. GRUB_DRIVE_BOOT. GRUB_DRIVE_BOOT_GRUB): Remove.
* util/grub.d/00_header.in: Set root using `search --fs_uuid' command
whenever possible.
* util/grub.d/10_hurd.in: Avoid explicit use of root drive. Instead,
just assume `root' variable has the right value.
* util/grub.d/10_linux.in: Likewise.
* util/grub-probe.c (probe): Probe for filesystem UUID when requested
via PRINT_FS_UUID.
(main): Recognise `-t fs_uuid' argument.
2008-05-30 Robert Millan <rmh@aybabtu.com> 2008-05-30 Robert Millan <rmh@aybabtu.com>
* util/biosdisk.c (map): Redefine structure to hold information * util/biosdisk.c (map): Redefine structure to hold information

View file

@ -1,7 +1,7 @@
/* search.c - search devices based on a file or a filesystem label */ /* search.c - search devices based on a file or a filesystem label */
/* /*
* GRUB -- GRand Unified Bootloader * 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 * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -32,6 +32,7 @@ static const struct grub_arg_option options[] =
{ {
{"file", 'f', 0, "search devices by a file (default)", 0, 0}, {"file", 'f', 0, "search devices by a file (default)", 0, 0},
{"label", 'l', 0, "search devices by a filesystem label", 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}, {"set", 's', GRUB_ARG_OPTION_OPTIONAL, "set a variable to the first device found", "VAR", ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };
@ -84,6 +85,54 @@ search_label (const char *key, const char *var)
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
} }
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 static void
search_file (const char *key, const char *var) search_file (const char *key, const char *var)
{ {
@ -136,11 +185,13 @@ grub_cmd_search (struct grub_arg_list *state, int argc, char **args)
if (argc == 0) if (argc == 0)
return grub_error (GRUB_ERR_INVALID_COMMAND, "no argument specified"); return grub_error (GRUB_ERR_INVALID_COMMAND, "no argument specified");
if (state[2].set) if (state[3].set)
var = state[2].arg ? : "root"; var = state[3].arg ? state[3].arg : "root";
if (state[1].set) if (state[1].set)
search_label (args[0], var); search_label (args[0], var);
else if (state[2].set)
search_fs_uuid (args[0], var);
else else
search_file (args[0], var); search_file (args[0], var);
@ -151,8 +202,8 @@ GRUB_MOD_INIT(search)
{ {
(void) mod; /* To stop warning. */ (void) mod; /* To stop warning. */
grub_register_command ("search", grub_cmd_search, GRUB_COMMAND_FLAG_BOTH, grub_register_command ("search", grub_cmd_search, GRUB_COMMAND_FLAG_BOTH,
"search [-f|-l|-s] NAME", "search [-f|-l|-u|-s] NAME",
"Search devices by a file or a filesystem label." "Search devices by file, filesystem label or filesystem UUID."
" If --set is specified, the first device found is" " If --set is specified, the first device found is"
" set to a variable. If no variable name is" " set to a variable. If no variable name is"
" specified, \"root\" is used.", " specified, \"root\" is used.",

View file

@ -120,7 +120,7 @@ struct grub_ext2_sblock
grub_uint32_t feature_compatibility; grub_uint32_t feature_compatibility;
grub_uint32_t feature_incompat; grub_uint32_t feature_incompat;
grub_uint32_t feature_ro_compat; grub_uint32_t feature_ro_compat;
grub_uint32_t unique_id[4]; grub_uint16_t uuid[8];
char volume_name[16]; char volume_name[16];
char last_mounted_on[64]; char last_mounted_on[64];
grub_uint32_t compression_info; grub_uint32_t compression_info;
@ -861,7 +861,39 @@ grub_ext2_label (grub_device_t device, char **label)
if (data) if (data)
*label = grub_strndup (data->sblock.volume_name, 14); *label = grub_strndup (data->sblock.volume_name, 14);
else 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 #ifndef GRUB_UTIL
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -881,6 +913,7 @@ static struct grub_fs grub_ext2_fs =
.read = grub_ext2_read, .read = grub_ext2_read,
.close = grub_ext2_close, .close = grub_ext2_close,
.label = grub_ext2_label, .label = grub_ext2_label,
.uuid = grub_ext2_uuid,
.next = 0 .next = 0
}; };

View file

@ -51,6 +51,11 @@ struct grub_fs
caller. */ caller. */
grub_err_t (*label) (grub_device_t device, char **label); 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. */ /* The next filesystem. */
struct grub_fs *next; struct grub_fs *next;
}; };

View file

@ -44,6 +44,7 @@
enum { enum {
PRINT_FS, PRINT_FS,
PRINT_FS_UUID,
PRINT_DRIVE, PRINT_DRIVE,
PRINT_DEVICE, PRINT_DEVICE,
PRINT_PARTMAP, PRINT_PARTMAP,
@ -110,6 +111,7 @@ probe (const char *path, char *device_name)
char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL; char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
int abstraction_type; int abstraction_type;
grub_device_t dev = NULL; grub_device_t dev = NULL;
grub_fs_t fs;
if (path == NULL) if (path == NULL)
{ {
@ -185,10 +187,13 @@ probe (const char *path, char *device_name)
goto end; goto end;
} }
fs = grub_fs_probe (dev);
if (! fs)
grub_util_error ("%s", grub_errmsg);
if (print == PRINT_FS) if (print == PRINT_FS)
{ {
struct stat st; struct stat st;
grub_fs_t fs;
stat (path, &st); stat (path, &st);
@ -210,19 +215,21 @@ probe (const char *path, char *device_name)
if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size)) if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size))
grub_util_error ("files differ"); 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); 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: end:
if (dev) if (dev)
grub_device_close (dev); grub_device_close (dev);
@ -257,7 +264,7 @@ Probe device information for a given path (or device, if the -d option is given)
\n\ \n\
-d, --device given argument is a system device, not a path\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\ -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\ print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\
-h, --help display this message and exit\n\ -h, --help display this message and exit\n\
-V, --version print version information and exit\n\ -V, --version print version information and exit\n\
@ -302,6 +309,8 @@ main (int argc, char *argv[])
case 't': case 't':
if (!strcmp (optarg, "fs")) if (!strcmp (optarg, "fs"))
print = PRINT_FS; print = PRINT_FS;
else if (!strcmp (optarg, "fs_uuid"))
print = PRINT_FS_UUID;
else if (!strcmp (optarg, "drive")) else if (!strcmp (optarg, "drive"))
print = PRINT_DRIVE; print = PRINT_DRIVE;
else if (!strcmp (optarg, "device")) else if (!strcmp (optarg, "device"))

View file

@ -38,8 +38,12 @@ set default=${GRUB_DEFAULT}
set timeout=${GRUB_TIMEOUT} set timeout=${GRUB_TIMEOUT}
EOF EOF
if [ "x${GRUB_DRIVE}" = "x" ] ; then : ; else # If there's a filesystem UUID that GRUB is capable of identifiing, use it;
echo "set root=${GRUB_DRIVE}" # 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 fi
case ${platform}:${GRUB_TERMINAL} in case ${platform}:${GRUB_TERMINAL} in

View file

@ -31,9 +31,9 @@ for i in /boot/gnumach.gz /boot/gnumach ; do
if test -e $i ; then if test -e $i ; then
basename=`basename $i` basename=`basename $i`
dirname=`dirname $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 echo "Found GNU Mach: $i" >&2
kernel=${grub_dirname}/${basename} kernel=${rel_dirname}/${basename}
at_least_one=true at_least_one=true
fi fi
done done

View file

@ -87,7 +87,7 @@ while [ "x$list" != "x" ] ; do
echo "Found linux image: $linux" >&2 echo "Found linux image: $linux" >&2
basename=`basename $linux` basename=`basename $linux`
dirname=`dirname $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"` version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
alt_version=`echo $version | sed -e "s,\.old$,,g"` alt_version=`echo $version | sed -e "s,\.old$,,g"`
@ -105,11 +105,11 @@ while [ "x$list" != "x" ] ; do
cat << EOF cat << EOF
menuentry "${OS}, linux ${version}" { 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 EOF
if test -n "${initrd}" ; then if test -n "${initrd}" ; then
cat << EOF cat << EOF
initrd ${grub_dirname}/${initrd} initrd ${rel_dirname}/${initrd}
EOF EOF
fi fi
cat << EOF cat << EOF
@ -118,11 +118,11 @@ EOF
cat << EOF cat << EOF
menuentry "${OS}, linux ${version} (single-user mode)" { 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 EOF
if test -n "${initrd}" ; then if test -n "${initrd}" ; then
cat << EOF cat << EOF
initrd ${grub_dirname}/${initrd} initrd ${rel_dirname}/${initrd}
EOF EOF
fi fi
cat << EOF cat << EOF

View file

@ -102,20 +102,16 @@ fi
# Device containing our userland. Typically used for root= parameter. # Device containing our userland. Typically used for root= parameter.
GRUB_DEVICE="`grub-probe --target=device /`" 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 # Filesystem for the device containing our userland. Used for stuff like
# choosing Hurd filesystem module. # choosing Hurd filesystem module.
GRUB_FS="`grub-probe --target=fs / 2> /dev/null || echo unknown`" 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 if test -f ${sysconfdir}/default/grub ; then
. ${sysconfdir}/default/grub . ${sysconfdir}/default/grub
fi fi
@ -155,7 +151,7 @@ esac
# These are defined in this script, export them here so that user can # These are defined in this script, export them here so that user can
# override them. # 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. # 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 export GRUB_DEFAULT GRUB_TIMEOUT GRUB_DISTRIBUTOR GRUB_CMDLINE_LINUX GRUB_CMDLINE_LINUX_DEFAULT GRUB_TERMINAL GRUB_SERIAL_COMMAND