grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] UUID support


From: Robert Millan
Subject: Re: [PATCH] UUID support
Date: Fri, 30 May 2008 13:04:18 +0200
User-agent: Mutt/1.5.13 (2006-08-11)

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
> address@hidden
> 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 /.)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]