grub-devel
[Top][All Lists]
Advanced

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

Re: [RFC] grub-install: allow none or multiple install devices on PC BIO


From: Vladimir 'φ-coder/phcoder' Serbinenko
Subject: Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS
Date: Fri, 12 Feb 2016 19:41:56 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.5.0

On 08.05.2015 20:53, Andrei Borzenkov wrote:
> There are two main applications.
> 
> 1. Omit install device to create generic image intended for chainloading
> from other master loader. Such image can be put on any device (or file
> system) and will still be able to find its $root. Currently even with
> --no-bootsector grub-install optimizes image by skipping UUID search if
> possible.
> 
> 2. Redundant installation on multi-device filesystem, RAID or similar.
> This allows both optimizing image w.r.t. to using --prefix vs. load.cfg
> as well as creating image just once.
> 
> Patch allows transparently use none or multiple installation devices,
> similar to
> 
> grub_devices="/dev/sda /dev/sda1 /dev/sdb"
> grub-install $grub_devices
> 
> where grub_devices can be empty and still do the right thing.
> 
> This is work in progress, although it is functionally complete and just
> needs some cleanups.
> 
> Comments?
I like the idea and it was on my "nice to have" list for some time. Do
you want to clean it up first or should I review this version?
> 
> ---
>  grub-core/kern/disk.c |   5 +-
>  include/grub/disk.h   |   2 +
>  util/grub-install.c   | 217 
> +++++++++++++++++++++++++++++++-------------------
>  3 files changed, 143 insertions(+), 81 deletions(-)
> 
> diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
> index 789f8c0..56f16b4 100644
> --- a/grub-core/kern/disk.c
> +++ b/grub-core/kern/disk.c
> @@ -168,7 +168,10 @@ grub_disk_dev_unregister (grub_disk_dev_t dev)
>  
>  /* Return the location of the first ',', if any, which is not
>     escaped by a '\'.  */
> -static const char *
> +#if !defined (GRUB_UTIL)
> +static
> +#endif
> +const char *
>  find_part_sep (const char *name)
>  {
>    const char *p = name;
> diff --git a/include/grub/disk.h b/include/grub/disk.h
> index b385af8..b2081eb 100644
> --- a/include/grub/disk.h
> +++ b/include/grub/disk.h
> @@ -256,6 +256,8 @@ void grub_ldm_fini (void);
>  void grub_mdraid09_fini (void);
>  void grub_mdraid1x_fini (void);
>  void grub_diskfilter_fini (void);
> +extern const char *find_part_sep (const char *);
> +
>  #endif
>  
>  #endif /* ! GRUB_DISK_HEADER */
> diff --git a/util/grub-install.c b/util/grub-install.c
> index 7b394c9..bb6532c 100644
> --- a/util/grub-install.c
> +++ b/util/grub-install.c
> @@ -57,7 +57,10 @@ static char *target;
>  static int removable = 0;
>  static int recheck = 0;
>  static int update_nvram = 1;
> -static char *install_device = NULL;
> +static char **install_devices = NULL;
> +static char **install_drives = NULL;
> +static int n_install_devices;
> +static int n_allocated_devices;
>  static char *debug_image = NULL;
>  static char *rootdir = NULL;
>  static char *bootdir = NULL;
> @@ -234,9 +237,12 @@ argp_parser (int key, char *arg, struct argp_state 
> *state)
>        return 0;
>  
>      case ARGP_KEY_ARG:
> -      if (install_device)
> -     grub_util_error ("%s", _("More than one install device?"));
> -      install_device = xstrdup (arg);
> +      if (n_install_devices >= n_allocated_devices)
> +     {
> +       n_allocated_devices += 16;
> +       install_devices = xrealloc (install_devices, n_allocated_devices);
> +     }
> +      install_devices[n_install_devices++] = xstrdup (arg);
>        return 0;
>  
>      default:
> @@ -534,25 +540,55 @@ probe_cryptodisk_uuid (grub_disk_t disk)
>  }
>  
>  static int
> -is_same_disk (const char *a, const char *b)
> +same_disks (char **root_devs)
>  {
> -  while (1)
> +  int i;
> +
> +  for (i = 0; i < n_install_devices; i++)
>      {
> -      if ((*a == ',' || *a == '\0') && (*b == ',' || *b == '\0'))
> -     return 1;
> -      if (*a != *b)
> -     return 0;
> -      if (*a == '\\')
> +      char **d;
> +      const char *p1 = find_part_sep (install_drives[i]);
> +      size_t len1 = p1 ? p1 - install_drives[i] : strlen (install_drives[i]);
> +
> +      for (d = root_devs; *d; d++)
>       {
> -       if (a[1] != b[1])
> -         return 0;
> -       a += 2;
> -       b += 2;
> -       continue;
> +       const char *p2 = find_part_sep (*d);
> +       size_t len2 = p2 ? p2 - *d : strlen (*d);
> +
> +       if (len1 == len2 &&
> +           strncmp (install_drives[i], *d, len1) == 0)
> +         break;
>       }
> -      a++;
> -      b++;
> +      if (!*d)
> +     return 0;
> +    }
> +
> +  return 1;
> +}
> +
> +static int
> +same_partitions (char **root_devs)
> +{
> +  const char *first_part;
> +  char **p;
> +
> +  if (!root_devs[1])
> +    return 1;
> +
> +  first_part = find_part_sep (root_devs[0]);
> +  for (p = root_devs + 1; *p; p++)
> +    {
> +      const char *part = find_part_sep (*p);
> +
> +      if ((first_part == NULL) ^ (part == NULL))
> +     return 0;
> +      if (!first_part && !part)
> +     continue;
> +      if (strcmp (first_part, part))
> +     return 0;
>      }
> +
> +  return 1;
>  }
>  
>  static char *
> @@ -835,6 +871,8 @@ main (int argc, char *argv[])
>    int efidir_is_mac = 0;
>    int is_prep = 0;
>    const char *pkgdatadir;
> +  size_t i;
> +
>  
>    grub_util_host_init (&argc, &argv);
>    product_version = xstrdup (PACKAGE_VERSION);
> @@ -926,12 +964,26 @@ main (int argc, char *argv[])
>    switch (platform)
>      {
>      case GRUB_INSTALL_PLATFORM_I386_PC:
> +      break;
> +
> +    default:
> +      if (n_install_devices > 1)
> +     grub_util_error ("%s", _("More than one install device?"));
> +      break;
> +    }
> +
> +  switch (platform)
> +    {
> +    case GRUB_INSTALL_PLATFORM_I386_PC:
> +      if (!install_devices)
> +     install_bootsector = 0;
> +      break;
>      case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
> -      if (!install_device)
> +      if (!install_devices)
>       grub_util_error ("%s", _("install device isn't specified"));
>        break;
>      case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
> -      if (install_device)
> +      if (install_devices)
>       is_prep = 1;
>        break;
>      case GRUB_INSTALL_PLATFORM_MIPS_ARC:
> @@ -952,8 +1004,11 @@ main (int argc, char *argv[])
>      case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
>      case GRUB_INSTALL_PLATFORM_I386_XEN:
>      case GRUB_INSTALL_PLATFORM_X86_64_XEN:
> -      free (install_device);
> -      install_device = NULL;
> +      for (i = 0; i < n_install_devices; i++)
> +     free (install_devices[i]);
> +      free (install_devices);
> +      install_devices = NULL;
> +      n_install_devices = n_allocated_devices = 0;
>        break;
>  
>        /* pacify warning.  */
> @@ -996,11 +1051,6 @@ main (int argc, char *argv[])
>        is_efi = 1;
>        break;
>      default:
> -      is_efi = 0;
> -      break;
> -
> -      /* pacify warning.  */
> -    case GRUB_INSTALL_PLATFORM_MAX:
>        break;
>      }
>  
> @@ -1009,8 +1059,6 @@ main (int argc, char *argv[])
>    if (is_efi)
>      {
>        grub_fs_t fs;
> -      free (install_device);
> -      install_device = NULL;
>        if (!efidir)
>       {
>         char *d = grub_util_path_concat (2, bootdir, "efi");
> @@ -1045,7 +1093,9 @@ main (int argc, char *argv[])
>        if (!efidir_device_names || !efidir_device_names[0])
>       grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
>                            efidir);
> -      install_device = efidir_device_names[0];
> +      /* FIXME free install_devices */
> +      /* We will use just the first device */
> +      install_devices = efidir_device_names;
>  
>        for (curdev = efidir_device_names; *curdev; curdev++)
>         grub_util_pull_device (*curdev);
> @@ -1207,7 +1257,9 @@ main (int argc, char *argv[])
>         if (grub_strcmp (fs->name, "hfs") == 0
>             || grub_strcmp (fs->name, "hfsplus") == 0)
>           {
> -           install_device = macppcdir_device_names[0];
> +           /* FIXME free install_devices */
> +           /* We just use the first one */
> +           install_devices = macppcdir_device_names;
>             is_prep = 0;
>           }
>       }
> @@ -1318,35 +1370,37 @@ main (int argc, char *argv[])
>             debug_image);
>      }
>    char *prefix_drive = NULL;
> -  char *install_drive = NULL;
>  
> -  if (install_device)
> +  if (install_devices)
>      {
> -      if (install_device[0] == '('
> -       && install_device[grub_strlen (install_device) - 1] == ')')
> -        {
> -       size_t len = grub_strlen (install_device) - 2;
> -       install_drive = xmalloc (len + 1);
> -       memcpy (install_drive, install_device + 1, len);
> -       install_drive[len] = '\0';
> -        }
> -      else
> -     {
> -       grub_util_pull_device (install_device);
> -       install_drive = grub_util_get_grub_dev (install_device);
> -       if (!install_drive)
> -         grub_util_error (_("cannot find a GRUB drive for %s.  Check your 
> device.map"),
> -                          install_device);
> -     }
> +      install_drives = xmalloc (n_install_devices * sizeof 
> (*install_drives));
> +
> +      for (i = 0; i < n_install_devices; i++)
> +     if (install_devices[i][0] == '('
> +         && install_devices[i][grub_strlen (install_devices[i]) - 1] == ')')
> +       {
> +         size_t len = grub_strlen (install_devices[i]) - 2;
> +         install_drives[i] = xmalloc (len + 1);
> +         memcpy (install_drives[i], install_devices[i] + 1, len);
> +         install_drives[i][len] = '\0';
> +       }
> +     else
> +       {
> +         grub_util_pull_device (install_devices[i]);
> +         install_drives[i] = grub_util_get_grub_dev (install_devices[i]);
> +         if (!install_drives[i])
> +           grub_util_error (_("cannot find a GRUB drive for %s.  Check your 
> device.map"),
> +                            install_devices[i]);
> +       }
>      }
>  
>    if (!have_abstractions)
>      {
>        if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0)
> -       || grub_drives[1]
> -       || (!install_drive
> +       || (grub_drives[1] && !same_partitions (grub_drives))
> +       || (!install_drives
>             && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
> -       || (install_drive && !is_same_disk (grub_drives[0], install_drive))
> +       || (install_drives && !same_disks (grub_drives))
>         || !have_bootdev (platform))
>       {
>         char *uuid = NULL;
> @@ -1656,24 +1710,27 @@ main (int argc, char *argv[])
>                                             "boot.img");
>       grub_install_copy_file (boot_img_src, boot_img, 1);
>  
> -     grub_util_info ("%sgrub-bios-setup %s %s %s %s %s --directory='%s' 
> --device-map='%s' '%s'",
> -                     /* TRANSLATORS: This is a prefix in the log to indicate 
> that usually
> -                        a command would be executed but due to an option was 
> skipped.  */
> -                     install_bootsector ? "" : _("NOT RUNNING: "),
> -                     allow_floppy ? "--allow-floppy " : "",
> -                     verbosity ? "--verbose " : "",
> -                     force ? "--force " : "",
> -                     !fs_probe ? "--skip-fs-probe" : "",
> -                     !add_rs_codes ? "--no-rs-codes" : "",
> -                     platdir,
> -                     device_map,
> -                     install_device);
> -                     
> -     /*  Now perform the installation.  */
> -     if (install_bootsector)
> -       grub_util_bios_setup (platdir, "boot.img", "core.img",
> -                             install_drive, force,
> -                             fs_probe, allow_floppy, add_rs_codes);
> +     for (i = 0; i < n_install_devices; i++)
> +       {
> +         grub_util_info ("%sgrub-bios-setup %s %s %s %s %s --directory='%s' 
> --device-map='%s' '%s'",
> +                         /* TRANSLATORS: This is a prefix in the log to 
> indicate that usually
> +                            a command would be executed but due to an option 
> was skipped.  */
> +                         install_bootsector ? "" : _("NOT RUNNING: "),
> +                         allow_floppy ? "--allow-floppy " : "",
> +                         verbosity ? "--verbose " : "",
> +                         force ? "--force " : "",
> +                         !fs_probe ? "--skip-fs-probe" : "",
> +                         !add_rs_codes ? "--no-rs-codes" : "",
> +                         platdir,
> +                         device_map,
> +                         install_devices[i]);
> +
> +         /*  Now perform the installation.  */
> +         if (install_bootsector)
> +           grub_util_bios_setup (platdir, "boot.img", "core.img",
> +                                 install_drives[i], force,
> +                                 fs_probe, allow_floppy, add_rs_codes);
> +       }
>       break;
>        }
>      case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
> @@ -1693,12 +1750,12 @@ main (int argc, char *argv[])
>                       !fs_probe ? "--skip-fs-probe" : "",
>                       platdir,
>                       device_map,
> -                     install_drive);
> +                     install_drives[0]);
>                       
>       /*  Now perform the installation.  */
>       if (install_bootsector)
>         grub_util_sparc_setup (platdir, "boot.img", "core.img",
> -                              install_device, force,
> +                              install_devices[0], force,
>                                fs_probe, allow_floppy,
>                                0 /* unused */ );
>       break;
> @@ -1734,7 +1791,7 @@ main (int argc, char *argv[])
>  
>         fill_core_services (core_services);
>  
> -       ins_dev = grub_device_open (install_drive);
> +       ins_dev = grub_device_open (install_drives[0]);
>  
>         bless (ins_dev, core_services, 0);
>  
> @@ -1745,7 +1802,7 @@ main (int argc, char *argv[])
>  
>             partno = ins_dev->disk->partition
>               ? ins_dev->disk->partition->number + 1 : 0;
> -           dev = grub_util_get_os_disk (install_device);
> +           dev = grub_util_get_os_disk (install_devices[0]);
>             grub_install_register_ieee1275 (0, dev, partno,
>                                             "\\\\BootX");
>           }
> @@ -1757,10 +1814,10 @@ main (int argc, char *argv[])
>         break;
>       }
>        /* If a install device is defined, copy the core.elf to PReP 
> partition.  */
> -      if (is_prep && install_device && install_device[0])
> +      if (is_prep)
>       {
>         grub_device_t ins_dev;
> -       ins_dev = grub_device_open (install_drive);
> +       ins_dev = grub_device_open (install_drives[0]);
>         if (!ins_dev || !is_prep_partition (ins_dev))
>           {
>             grub_util_error ("%s", _("the chosen partition is not a PReP 
> partition"));
> @@ -1772,13 +1829,13 @@ main (int argc, char *argv[])
>           }
>         else
>           {
> -           char *s = xasprintf ("dd if=/dev/zero of=%s", install_device);
> +           char *s = xasprintf ("dd if=/dev/zero of=%s", install_devices[0]);
>             grub_util_error (_("the PReP partition is not empty. If you are 
> sure you want to use it, run dd to clear it: `%s'"),
>                              s);
>           }
>         grub_device_close (ins_dev);
>         if (update_nvram)
> -         grub_install_register_ieee1275 (1, grub_util_get_os_disk 
> (install_device),
> +         grub_install_register_ieee1275 (1, grub_util_get_os_disk 
> (install_devices[0]),
>                                           0, NULL);
>         break;
>        }
> @@ -1798,7 +1855,7 @@ main (int argc, char *argv[])
>       }
>        break;
>      case GRUB_INSTALL_PLATFORM_MIPS_ARC:
> -      grub_install_sgi_setup (install_device, imgfile, "grub");
> +      grub_install_sgi_setup (install_devices[0], imgfile, "grub");
>        break;
>  
>      case GRUB_INSTALL_PLATFORM_I386_EFI:
> @@ -1834,7 +1891,7 @@ main (int argc, char *argv[])
>  
>         fill_core_services(core_services);
>  
> -       ins_dev = grub_device_open (install_drive);
> +       ins_dev = grub_device_open (install_drives[0]);
>  
>         bless (ins_dev, boot_efi, 1);
>         if (!removable && update_nvram)
> 


Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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