* [PATCH] UUID support
@ 2008-05-29 15:13 Robert Millan
2008-05-29 16:50 ` Bean
2008-05-30 11:04 ` Robert Millan
0 siblings, 2 replies; 9+ messages in thread
From: Robert Millan @ 2008-05-29 15:13 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 608 bytes --]
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 /.)
[-- Attachment #2: uuid.diff --]
[-- Type: text/x-diff, Size: 12715 bytes --]
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
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH] UUID support
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-30 11:04 ` Robert Millan
1 sibling, 1 reply; 9+ messages in thread
From: Bean @ 2008-05-29 16:50 UTC (permalink / raw)
To: The development of GRUB 2
On Thu, May 29, 2008 at 11:13 PM, Robert Millan <rmh@aybabtu.com> 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).
Nice, this is a much needed feature in grub2.
BTW, I think we can embed the UUID of the root device in
core.img/grub.elf, so that when the traditional root device fails to
locate normal.mod, it uses the UUID to scan for root device.
--
Bean
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] UUID support
2008-05-29 16:50 ` Bean
@ 2008-05-29 18:17 ` Robert Millan
2008-05-29 18:49 ` Bean
0 siblings, 1 reply; 9+ messages in thread
From: Robert Millan @ 2008-05-29 18:17 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, May 30, 2008 at 12:50:42AM +0800, Bean wrote:
>
> BTW, I think we can embed the UUID of the root device in
> core.img/grub.elf, so that when the traditional root device fails to
> locate normal.mod, it uses the UUID to scan for root device.
Good idea. But I'd check for UUID first. When you find a UUID match, it's
much more reliable than a filename one.
--
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 /.)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] UUID support
2008-05-29 18:17 ` Robert Millan
@ 2008-05-29 18:49 ` Bean
2008-05-30 10:41 ` Robert Millan
0 siblings, 1 reply; 9+ messages in thread
From: Bean @ 2008-05-29 18:49 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, May 30, 2008 at 2:17 AM, Robert Millan <rmh@aybabtu.com> wrote:
> On Fri, May 30, 2008 at 12:50:42AM +0800, Bean wrote:
>>
>> BTW, I think we can embed the UUID of the root device in
>> core.img/grub.elf, so that when the traditional root device fails to
>> locate normal.mod, it uses the UUID to scan for root device.
>
> Good idea. But I'd check for UUID first. When you find a UUID match, it's
> much more reliable than a filename one.
Here are some thought about how to store it. We can reuse the space
occupied by prefix. Instead of one variable, we use zero-end strings
like:
path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 \0
We can also add other variable, for example, debug and default. debug
is useful as it can show message before grub.cfg is loaded, and
default is used to control the default menu entry. Other variable
should be set in grub.cfg, as space is quite limited here.
path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 debug=all \0 default=1 \0 \0
The space need to expand slightly, I guess something about 100 byte is
more than enough. The whole block is prefixed by a magic number and
block length, so that it's easy to locate by utility.
This also solve the savedefault issue, we can add a command like this:
save_env /path_to_core.img variable_name ..
It finds the magic number, and store the value of selected variable in
the embedded environment block.
--
Bean
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] UUID support
2008-05-29 18:49 ` Bean
@ 2008-05-30 10:41 ` Robert Millan
2008-05-30 13:14 ` Robert Millan
0 siblings, 1 reply; 9+ messages in thread
From: Robert Millan @ 2008-05-30 10:41 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, May 30, 2008 at 02:49:22AM +0800, Bean wrote:
> On Fri, May 30, 2008 at 2:17 AM, Robert Millan <rmh@aybabtu.com> wrote:
> > On Fri, May 30, 2008 at 12:50:42AM +0800, Bean wrote:
> >>
> >> BTW, I think we can embed the UUID of the root device in
> >> core.img/grub.elf, so that when the traditional root device fails to
> >> locate normal.mod, it uses the UUID to scan for root device.
> >
> > Good idea. But I'd check for UUID first. When you find a UUID match, it's
> > much more reliable than a filename one.
>
> Here are some thought about how to store it. We can reuse the space
> occupied by prefix. Instead of one variable, we use zero-end strings
> like:
>
> path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 \0
>
> We can also add other variable, for example, debug and default. debug
> is useful as it can show message before grub.cfg is loaded, and
> default is used to control the default menu entry. Other variable
> should be set in grub.cfg, as space is quite limited here.
>
> path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 debug=all \0 default=1 \0 \0
>
> The space need to expand slightly, I guess something about 100 byte is
> more than enough. The whole block is prefixed by a magic number and
> block length, so that it's easy to locate by utility.
>
> This also solve the savedefault issue, we can add a command like this:
>
> save_env /path_to_core.img variable_name ..
>
> It finds the magic number, and store the value of selected variable in
> the embedded environment block.
Then I suppose we could have a module that gets $uuid from environment and
searches for it to set $prefix?
Maybe we could search for everything else in the same module too, this way
we only have to iterate once. It could check for things like:
- filesystem uuid
- partmap uuid (when we support it)
- filename (based on user input via variable, rather than hardcoded
normal.mod?)
- filesystem label
--
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 /.)
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH] UUID support
2008-05-30 10:41 ` Robert Millan
@ 2008-05-30 13:14 ` Robert Millan
2008-05-30 13:26 ` Bean
0 siblings, 1 reply; 9+ messages in thread
From: Robert Millan @ 2008-05-30 13:14 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, May 30, 2008 at 12:41:15PM +0200, Robert Millan wrote:
> >
> > Here are some thought about how to store it. We can reuse the space
> > occupied by prefix. Instead of one variable, we use zero-end strings
> > like:
> >
> > path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 \0
> >
> > We can also add other variable, for example, debug and default. debug
> > is useful as it can show message before grub.cfg is loaded, and
> > default is used to control the default menu entry. Other variable
> > should be set in grub.cfg, as space is quite limited here.
> >
> > path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 debug=all \0 default=1 \0 \0
> >
> > The space need to expand slightly, I guess something about 100 byte is
> > more than enough. The whole block is prefixed by a magic number and
> > block length, so that it's easy to locate by utility.
> >
> > This also solve the savedefault issue, we can add a command like this:
> >
> > save_env /path_to_core.img variable_name ..
> >
> > It finds the magic number, and store the value of selected variable in
> > the embedded environment block.
>
> Then I suppose we could have a module that gets $uuid from environment and
> searches for it to set $prefix?
However, a problem with this is that it only works for i386-pc, untill we
define a way to store this for each variant.
Perhaps we could instead use memdisk to store it? Rather than put a grub.cfg
in memdisk, which would require builtin normal.mod, we could put a simpler
file (let's call it 'env') with initial environment, in the binary format
you describe. Does that work?
Then to support it in other platforms, we just need to implement memdisk in
them.
--
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 /.)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] UUID support
2008-05-30 13:14 ` Robert Millan
@ 2008-05-30 13:26 ` Bean
2008-05-30 14:07 ` Robert Millan
0 siblings, 1 reply; 9+ messages in thread
From: Bean @ 2008-05-30 13:26 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, May 30, 2008 at 9:14 PM, Robert Millan <rmh@aybabtu.com> wrote:
> On Fri, May 30, 2008 at 12:41:15PM +0200, Robert Millan wrote:
>> >
>> > Here are some thought about how to store it. We can reuse the space
>> > occupied by prefix. Instead of one variable, we use zero-end strings
>> > like:
>> >
>> > path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 \0
>> >
>> > We can also add other variable, for example, debug and default. debug
>> > is useful as it can show message before grub.cfg is loaded, and
>> > default is used to control the default menu entry. Other variable
>> > should be set in grub.cfg, as space is quite limited here.
>> >
>> > path=/boot/grub \0 uuid=xxx-xxx-xxxx \0 debug=all \0 default=1 \0 \0
>> >
>> > The space need to expand slightly, I guess something about 100 byte is
>> > more than enough. The whole block is prefixed by a magic number and
>> > block length, so that it's easy to locate by utility.
>> >
>> > This also solve the savedefault issue, we can add a command like this:
>> >
>> > save_env /path_to_core.img variable_name ..
>> >
>> > It finds the magic number, and store the value of selected variable in
>> > the embedded environment block.
>>
>> Then I suppose we could have a module that gets $uuid from environment and
>> searches for it to set $prefix?
>
> However, a problem with this is that it only works for i386-pc, untill we
> define a way to store this for each variant.
>
> Perhaps we could instead use memdisk to store it? Rather than put a grub.cfg
> in memdisk, which would require builtin normal.mod, we could put a simpler
> file (let's call it 'env') with initial environment, in the binary format
> you describe. Does that work?
>
> Then to support it in other platforms, we just need to implement memdisk in
> them.
We can use some function like grub_machine_get_env to return a pointer
to the environment block, and parse it in main.c. The env block is
string base, it can be used in any platform.
BTW, since you have changed the filesystem structure, you need to add
the uuid member to other fs modules as well, otherwise it will cause
compile error.
--
Bean
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] UUID support
2008-05-30 13:26 ` Bean
@ 2008-05-30 14:07 ` Robert Millan
0 siblings, 0 replies; 9+ messages in thread
From: Robert Millan @ 2008-05-30 14:07 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, May 30, 2008 at 09:26:05PM +0800, Bean wrote:
> >
> > However, a problem with this is that it only works for i386-pc, untill we
> > define a way to store this for each variant.
> >
> > Perhaps we could instead use memdisk to store it? Rather than put a grub.cfg
> > in memdisk, which would require builtin normal.mod, we could put a simpler
> > file (let's call it 'env') with initial environment, in the binary format
> > you describe. Does that work?
> >
> > Then to support it in other platforms, we just need to implement memdisk in
> > them.
>
> We can use some function like grub_machine_get_env to return a pointer
> to the environment block, and parse it in main.c. The env block is
> string base, it can be used in any platform.
Sounds fine.
> BTW, since you have changed the filesystem structure, you need to add
> the uuid member to other fs modules as well, otherwise it will cause
> compile error.
Optional struct members are allowed (at least by gcc). I think we have many
incomplete struct declarations throurough the code.
--
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 /.)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] UUID support
2008-05-29 15:13 [PATCH] UUID support Robert Millan
2008-05-29 16:50 ` Bean
@ 2008-05-30 11:04 ` Robert Millan
1 sibling, 0 replies; 9+ messages in thread
From: Robert Millan @ 2008-05-30 11:04 UTC (permalink / raw)
To: grub-devel
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 /.)
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-05-30 14:07 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 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.