UUID support
PATCH 1/1 UUID support
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).
Signature · 5 lines
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 /.)
commands/search.c renamed from grub2/commands/search.c +56 -5
@@ -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 ; + autoint 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 *sif (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.",
fs/ext2.c renamed from grub2/fs/ext2.c +35 -2
@@ -120,7 +120,7 @@ struct grub_ext2_sblockgrub_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, cif (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 };
include/grub/fs.h renamed from grub2/include/grub/fs.h +5 -0
@@ -51,6 +51,11 @@ struct grub_fscaller. */ 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; };
util/grub.d/00_header.in renamed from grub2/util/grub.d/00_header.in +6 -2
@@ -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
util/grub.d/10_hurd.in renamed from grub2/util/grub.d/10_hurd.in +2 -2
@@ -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
util/grub.d/10_linux.in renamed from grub2/util/grub.d/10_linux.in +5 -5
@@ -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
util/grub-probe.c renamed from grub2/util/grub-probe.c +20 -11
@@ -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_nachar *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_naif (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" ))
util/update-grub.in renamed from grub2/util/update-grub.in +6 -10
@@ -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
Quoted 10 lines · Robert Millan
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.
Signature · 1 line
Bean
Quoted 4 lines · Bean
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.
Signature · 5 lines
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 /.)
Quoted 8 lines · Robert Millan
Quoted 4 lines · Bean
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.
Signature · 1 line
Bean
Quoted 27 lines · Bean
Quoted 8 lines · Robert Millan
Quoted 4 lines · Bean
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.
Quoted 6 lines
This also solve the savedefault issue, we can add a command like this:
save_env/path_to_core.imgvariable_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
Signature · 5 lines
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 /.)
Quoted 20 lines · Robert Millan
Quoted 20 lines
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:
Quoted 7 lines
Quoted 4 lines
save_env/path_to_core.imgvariable_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.
Signature · 5 lines
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 /.)
Quoted 32 lines · Robert Millan
Quoted 20 lines · Robert Millan
Quoted 20 lines
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:
Quoted 7 lines
Quoted 4 lines
save_env/path_to_core.imgvariable_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.
Quoted 7 lines
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.
Signature · 1 line
Bean
Quoted 9 lines · Bean
Quoted 9 lines
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?
Quoted 6 lines
Quoted 2 lines
Then to support it in other platforms, we just need to implement memdisk in them.
We can use some function like
grub_machine_get_envto return a pointer to the environment block, and parse it inmain.c. The env block is string base, it can be used in any platform.
Sounds fine.
Quoted 3 lines
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.
Signature · 5 lines
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 /.)
Committed.
Quoted 395 lines · Robert Millan
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).
Signature · 7 lines
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.ccommands/search.c renamed from grub2/commands/search.c +56
-5@@ -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 ; + autoint 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 *sif (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.cfs/ext2.c renamed from grub2/fs/ext2.c +35
-2@@ -120,7 +120,7 @@ struct grub_ext2_sblockgrub_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, cif (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.hinclude/grub/fs.h renamed from grub2/include/grub/fs.h +5
-0@@ -51,6 +51,11 @@ struct grub_fscaller. */ 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
util/grub.d/00_header.in renamed from grub2/util/grub.d/00_header.in +6
-2@@ -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} indiff -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
util/grub.d/10_hurd.in renamed from grub2/util/grub.d/10_hurd.in +2
-2@@ -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 donediff -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
util/grub.d/10_linux.in renamed from grub2/util/grub.d/10_linux.in +5
-5@@ -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 << EOFdiff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp
../grub2/util/grub-probe.c./util/grub-probe.cutil/grub-probe.c renamed from grub2/util/grub-probe.c +20
-11@@ -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_nachar *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_naif (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
util/update-grub.in renamed from grub2/util/update-grub.in +6
-10@@ -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
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel
Signature · 5 lines
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 /.)