* [RFC] grub-install: allow none or multiple install devices on PC BIOS @ 2015-05-08 18:53 Andrei Borzenkov 2015-05-12 10:52 ` Michael Chang 2016-02-12 18:41 ` Vladimir 'φ-coder/phcoder' Serbinenko 0 siblings, 2 replies; 10+ messages in thread From: Andrei Borzenkov @ 2015-05-08 18:53 UTC (permalink / raw) To: grub-devel 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? --- 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) -- tg: (0725881..) e/optional-install-device (depends on: master) ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2015-05-08 18:53 [RFC] grub-install: allow none or multiple install devices on PC BIOS Andrei Borzenkov @ 2015-05-12 10:52 ` Michael Chang 2015-05-12 11:57 ` Andrei Borzenkov 2016-02-12 18:41 ` Vladimir 'φ-coder/phcoder' Serbinenko 1 sibling, 1 reply; 10+ messages in thread From: Michael Chang @ 2015-05-12 10:52 UTC (permalink / raw) To: The development of GNU GRUB On Fri, May 08, 2015 at 09:53:41PM +0300, 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. I can only tell it to solve the problem of time wasting in copying modules and images creation due to multiple invocation of grub-install for doing redundency install. Beside that, do you foresee any other improvement it can provide? > > Patch allows transparently use none or multiple installation devices, > similar to > > grub_devices="/dev/sda /dev/sda1 /dev/sdb" It also looks to me that this patch can solve the problem of multiple device install with blocklists. Think about the user installs to mbr (sda) and partition (sda1) because he someshow wants the paritition to be chainload-able for resuce or for any of his own interests. If the user occasionally do. grub-install /dev/sda1 grub-install /dev/sda The chainload will fail for sda1 since later install to mbr replaces the core.img. You patch can avoid such pit-fall by doing it once. > grub-install $grub_devices What if one of the device failed, should it continue installing the rest or abort immediately ? Thanks, Michael ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2015-05-12 10:52 ` Michael Chang @ 2015-05-12 11:57 ` Andrei Borzenkov 2015-05-12 14:57 ` Michael Chang 2015-05-12 15:22 ` Michael Chang 0 siblings, 2 replies; 10+ messages in thread From: Andrei Borzenkov @ 2015-05-12 11:57 UTC (permalink / raw) To: Michael Chang; +Cc: The development of GNU GRUB В Tue, 12 May 2015 18:52:22 +0800 Michael Chang <mchang@suse.com> пишет: > On Fri, May 08, 2015 at 09:53:41PM +0300, 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. > > Actually I think it is useful for all platforms. > > 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. > > I can only tell it to solve the problem of time wasting in copying > modules and images creation due to multiple invocation of grub-install > for doing redundency install. Beside that, do you foresee any other > improvement it can provide? > You answered it yourself below. That is why I think it is useful mostly for PC BIOS that is unique with embedding problem. > > > > Patch allows transparently use none or multiple installation devices, > > similar to > > > > grub_devices="/dev/sda /dev/sda1 /dev/sdb" > > It also looks to me that this patch can solve the problem of multiple > device install with blocklists. Think about the user installs to mbr > (sda) and partition (sda1) because he someshow wants the paritition to > be chainload-able for resuce or for any of his own interests. > > If the user occasionally do. > > grub-install /dev/sda1 grub-install /dev/sda > > The chainload will fail for sda1 since later install to mbr replaces the > core.img. > Exactly. This was common problem for openSUSE users as at least in earlier versions installer defaulted to multiple bootloader locations and only some of them allowed embedding. > You patch can avoid such pit-fall by doing it once. > > > grub-install $grub_devices > > What if one of the device failed, should it continue installing the rest > or abort immediately ? > It will abort, unfortunately. Changing it is really intrusive as it may happen deep in call chain which simply does grub_util_error(). It is something that may be considered for the future. BTW as far as I can tell pbl aborts installation if any of grub-install invocation failed. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2015-05-12 11:57 ` Andrei Borzenkov @ 2015-05-12 14:57 ` Michael Chang 2015-05-12 15:22 ` Michael Chang 1 sibling, 0 replies; 10+ messages in thread From: Michael Chang @ 2015-05-12 14:57 UTC (permalink / raw) To: The development of GNU GRUB On Tue, May 12, 2015 at 02:57:00PM +0300, Andrei Borzenkov wrote: > В Tue, 12 May 2015 18:52:22 +0800 > Michael Chang <mchang@suse.com> пишет: > > > On Fri, May 08, 2015 at 09:53:41PM +0300, Andrei Borzenkov wrote: > > > There are two main applications. > > > > > It will abort, unfortunately. Changing it is really intrusive as it > may happen deep in call chain which simply does grub_util_error(). It > is something that may be considered for the future. BTW as far as I can > tell pbl aborts installation if any of grub-install invocation failed. > Yes. That's why I would like to confirm the default behavior. It may be able to proceed regardless of error, but aborting looks better decision to me. Thanks, Michael ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2015-05-12 11:57 ` Andrei Borzenkov 2015-05-12 14:57 ` Michael Chang @ 2015-05-12 15:22 ` Michael Chang 2016-02-13 7:29 ` Andrei Borzenkov 1 sibling, 1 reply; 10+ messages in thread From: Michael Chang @ 2015-05-12 15:22 UTC (permalink / raw) To: The development of GNU GRUB On Tue, May 12, 2015 at 02:57:00PM +0300, Andrei Borzenkov wrote: > В Tue, 12 May 2015 18:52:22 +0800 > Michael Chang <mchang@suse.com> пишет: > > > On Fri, May 08, 2015 at 09:53:41PM +0300, 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. > > > > > Actually I think it is useful for all platforms. As it works across all platform, os-prober should consider chanloading core images if possible rather than digging into grub configs. Is there any plan for that ? Thanks, Michael ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2015-05-12 15:22 ` Michael Chang @ 2016-02-13 7:29 ` Andrei Borzenkov 2016-02-16 4:11 ` Michael Chang 0 siblings, 1 reply; 10+ messages in thread From: Andrei Borzenkov @ 2016-02-13 7:29 UTC (permalink / raw) To: grub-devel 12.05.2015 18:22, Michael Chang пишет: > On Tue, May 12, 2015 at 02:57:00PM +0300, Andrei Borzenkov wrote: >> В Tue, 12 May 2015 18:52:22 +0800 >> Michael Chang <mchang@suse.com> пишет: >> >>> On Fri, May 08, 2015 at 09:53:41PM +0300, 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. >>>> >> >> Actually I think it is useful for all platforms. > > As it works across all platform, os-prober should consider chanloading > core images if possible rather than digging into grub configs. Is there > any plan for that ? > At least on EFI it is not possible to chainload GRUB from /boot until it supports multiboot; and even then it will be multiboot2, so it means separate commands. We have enough issues with efi-specific linux loaders :( ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2016-02-13 7:29 ` Andrei Borzenkov @ 2016-02-16 4:11 ` Michael Chang 2016-02-16 18:11 ` Andrei Borzenkov 0 siblings, 1 reply; 10+ messages in thread From: Michael Chang @ 2016-02-16 4:11 UTC (permalink / raw) To: The development of GNU GRUB [-- Attachment #1: Type: text/plain, Size: 1821 bytes --] On Sat, Feb 13, 2016 at 10:29:58AM +0300, Andrei Borzenkov wrote: > 12.05.2015 18:22, Michael Chang пишет: > > On Tue, May 12, 2015 at 02:57:00PM +0300, Andrei Borzenkov wrote: > >> В Tue, 12 May 2015 18:52:22 +0800 > >> Michael Chang <mchang@suse.com> пишет: > >> > >>> On Fri, May 08, 2015 at 09:53:41PM +0300, 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. > >>>> > >> > >> Actually I think it is useful for all platforms. > > > > As it works across all platform, os-prober should consider chanloading > > core images if possible rather than digging into grub configs. Is there > > any plan for that ? > > > > At least on EFI it is not possible to chainload GRUB from /boot until it I'm skeptical to this. From what I know it's possible because grub's efi chainloader reads efi image via it's own filesystem support, so that it did not limited by what firmware could offer. And LoadImage can accept SourceBuffer as an option to pass the pointer of loaded image buffer directly. Honestly I didn't really test it, but glancing at the source code it sounds promoising to work to me. Thanks, Michael > supports multiboot; and even then it will be multiboot2, so it means > separate commands. We have enough issues with efi-specific linux loaders :( > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 473 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2016-02-16 4:11 ` Michael Chang @ 2016-02-16 18:11 ` Andrei Borzenkov 0 siblings, 0 replies; 10+ messages in thread From: Andrei Borzenkov @ 2016-02-16 18:11 UTC (permalink / raw) To: grub-devel [-- Attachment #1: Type: text/plain, Size: 1737 bytes --] 16.02.2016 07:11, Michael Chang пишет: > On Sat, Feb 13, 2016 at 10:29:58AM +0300, Andrei Borzenkov wrote: >> 12.05.2015 18:22, Michael Chang пишет: >>> On Tue, May 12, 2015 at 02:57:00PM +0300, Andrei Borzenkov wrote: >>>> В Tue, 12 May 2015 18:52:22 +0800 >>>> Michael Chang <mchang@suse.com> пишет: >>>> >>>>> On Fri, May 08, 2015 at 09:53:41PM +0300, 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. >>>>>> >>>> >>>> Actually I think it is useful for all platforms. >>> >>> As it works across all platform, os-prober should consider chanloading >>> core images if possible rather than digging into grub configs. Is there >>> any plan for that ? >>> >> >> At least on EFI it is not possible to chainload GRUB from /boot until it > > I'm skeptical to this. From what I know it's possible because grub's efi > chainloader reads efi image via it's own filesystem support, so that it > did not limited by what firmware could offer. And LoadImage can accept > SourceBuffer as an option to pass the pointer of loaded image buffer > directly. > > Honestly I didn't really test it, but glancing at the source code it > sounds promoising to work to me. > Yes, indeed. I'm not sure what went wrong last time I tried it; I had problem with device path. Still, this is core.img vs. core.elf, which means it is platform dependent. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2015-05-08 18:53 [RFC] grub-install: allow none or multiple install devices on PC BIOS Andrei Borzenkov 2015-05-12 10:52 ` Michael Chang @ 2016-02-12 18:41 ` Vladimir 'φ-coder/phcoder' Serbinenko 2016-02-13 7:27 ` Andrei Borzenkov 1 sibling, 1 reply; 10+ messages in thread From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2016-02-12 18:41 UTC (permalink / raw) To: The development of GNU GRUB [-- Attachment #1: Type: text/plain, Size: 15064 bytes --] 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 #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 213 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] grub-install: allow none or multiple install devices on PC BIOS 2016-02-12 18:41 ` Vladimir 'φ-coder/phcoder' Serbinenko @ 2016-02-13 7:27 ` Andrei Borzenkov 0 siblings, 0 replies; 10+ messages in thread From: Andrei Borzenkov @ 2016-02-13 7:27 UTC (permalink / raw) To: grub-devel [-- Attachment #1.1: Type: text/plain, Size: 2355 bytes --] 12.02.2016 21:41, Vladimir 'φ-coder/phcoder' Serbinenko пишет: > 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? I updated it to the current master with small cleanup. See attached. Open questions - we probably should not allow empty install list by default. This is too error prone to have grub-install silently succeed leaving unbootable system. Should we add special argument or --force will do? - it still may be useful to be able to force UUID search instead of encoding partition number irrespectively of install device locations. But that is separate topic. - messages from grub-setup need now qualification with device. It is otherwise confusing when you have several devices and do not know which one it refers to. - for completeness this should really be pushed into grub-bios-setup as well. But this is a lot of work for rather small gain (only when installing on multiple partitions on the same disk). Most common applications I had in mind are zero install devices or different disks in RAID. - this makes grub-install even less atomic than it is now. It would be really useful to have framework for alternative /boot/grub locations so that boot sector always refers to valid boot location. Or notion of "undo" where we could revert changes. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1.2: optional-install-device.patch --] [-- Type: text/x-patch; name="optional-install-device.patch", Size: 14346 bytes --] From: Andrei Borzenkov <arvidjaar@gmail.com> Subject: [PATCH] grub-install: allow none or multiple install devices on PC BIOS 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. --- grub-core/kern/disk.c | 9 ++- include/grub/disk.h | 2 + util/grub-install.c | 202 ++++++++++++++++++++++++++++---------------------- 3 files changed, 122 insertions(+), 91 deletions(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 789f8c0..29e39a5 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -168,8 +168,11 @@ 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 * -find_part_sep (const char *name) +#if !defined (GRUB_UTIL) +static +#endif +const char * +grub_find_part_sep (const char *name) { const char *p = name; char c; @@ -203,7 +206,7 @@ grub_disk_open (const char *name) disk->max_agglomerate = 1048576 >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS); - p = find_part_sep (name); + p = grub_find_part_sep (name); if (p) { grub_size_t len = p - name; diff --git a/include/grub/disk.h b/include/grub/disk.h index b385af8..254c920 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); +const char *grub_find_part_sep (const char *); + #endif #endif /* ! GRUB_DISK_HEADER */ diff --git a/util/grub-install.c b/util/grub-install.c index 6c89c2b..9a0919c 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,22 @@ probe_cryptodisk_uuid (grub_disk_t disk) } static int -is_same_disk (const char *a, const char *b) +is_same_disk (const char *root, char **install_devs) { - while (1) + char **d; + const char *root_part = grub_find_part_sep (root); + size_t root_len = root_part ? root_part - root : strlen (root); + + for (d = install_devs; *d; d++) { - if ((*a == ',' || *a == '\0') && (*b == ',' || *b == '\0')) - return 1; - if (*a != *b) + const char *p = grub_find_part_sep (*d); + size_t len = p ? p - *d : strlen (*d); + + if (len != root_len || (len && strncmp (root, *d, len))) return 0; - if (*a == '\\') - { - if (a[1] != b[1]) - return 0; - a += 2; - b += 2; - continue; - } - a++; - b++; } + + return 1; } static char * @@ -815,6 +818,21 @@ fill_core_services (const char *core_services) free (sysv_plist); } +static void +free_install_devices (void) +{ + size_t i; + + if (!install_devices) + return; + + 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; +} + int main (int argc, char *argv[]) { @@ -835,6 +853,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,14 +946,25 @@ 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_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_I386_PC: case GRUB_INSTALL_PLATFORM_MIPS_ARC: case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: break; @@ -952,8 +983,7 @@ 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; + free_install_devices (); break; /* pacify warning. */ @@ -1009,8 +1039,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 +1073,8 @@ 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]; + /* 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 +1236,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]; + /* We just use the first one */ + free_install_devices (); + install_devices = macppcdir_device_names; is_prep = 0; } } @@ -1319,35 +1350,38 @@ 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 + 1) * 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]); + } + install_drives[n_install_devices] = NULL; } if (!have_abstractions) { if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0) || grub_drives[1] - || (!install_drive + || (!install_drives && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275) - || (install_drive && !is_same_disk (grub_drives[0], install_drive)) + || (install_drives && !is_same_disk (grub_drives[0], install_drives)) || !have_bootdev (platform)) { char *uuid = NULL; @@ -1480,19 +1514,8 @@ main (int argc, char *argv[]) else { /* We need to hardcode the partition number in the core image's prefix. */ - char *p; - for (p = grub_drives[0]; *p; ) - { - if (*p == '\\' && p[1]) - { - p += 2; - continue; - } - if (*p == ',' || *p == '\0') - break; - p++; - } - prefix_drive = xasprintf ("(%s)", p); + const char *p = grub_find_part_sep (grub_drives[0]); + prefix_drive = xasprintf ("(%s)", p ?: ""); } } else @@ -1657,24 +1680,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: @@ -1694,12 +1720,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_drive, force, + install_drives[0], force, fs_probe, allow_floppy, 0 /* unused */ ); break; @@ -1735,7 +1761,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); @@ -1746,7 +1772,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"); } @@ -1758,10 +1784,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")); @@ -1773,13 +1799,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; } @@ -1799,7 +1825,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: @@ -1835,7 +1861,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) -- tg: (080a208..) u/optional-install-device (depends on: master) [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-02-16 18:11 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-05-08 18:53 [RFC] grub-install: allow none or multiple install devices on PC BIOS Andrei Borzenkov 2015-05-12 10:52 ` Michael Chang 2015-05-12 11:57 ` Andrei Borzenkov 2015-05-12 14:57 ` Michael Chang 2015-05-12 15:22 ` Michael Chang 2016-02-13 7:29 ` Andrei Borzenkov 2016-02-16 4:11 ` Michael Chang 2016-02-16 18:11 ` Andrei Borzenkov 2016-02-12 18:41 ` Vladimir 'φ-coder/phcoder' Serbinenko 2016-02-13 7:27 ` Andrei Borzenkov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).