Hello everyone, I'm writing to this list since I would like to get some feedback on an additional option to the grub-install tool we would find very convenient to have. The diff is attached to the e-mail (also available as a pastebin [1]).
The idea of the --auto-nvram (the name is just a proposition) flag is a bit similar to what --no-nvram does. After providing the option during grub-install, the tool will attempt to guess if there is access to NVRAM variables for EFI and/or IEEE1275 and, if yes, perform the usual variable updates. If no access to the NVRAM is available the whole thing is handled somewhat similar to --no-nvram + a warning message displayed. Rationale: We would like to use this in Ubuntu for cases of dual BIOS/EFI bootloaders installed (at the same time), helpful for the situation of calling grub-install --target=x86_64-efi from the shim-efi package on a BIOS legacy-mode booted machine. For this legacy-mode case when running on a EFI-enabled device, currently this causes grub-install to fail as obviously there is no access to the NVRAM and no --no-nvram is given. We don't want to unconditionally append --no-nvram as this is not what we want to happen for the case of a system that is actually booted in EFI-mode. With this flag, we would be simply performing a grub-install --target=x86_64-efi --auto-nvram unconditionally which would do the right thing in both cases, allowing for a much simpler handling of this dual-bootloader case in Ubuntu. Having it being done inside grub-installer makes everything much cleaner. This is of course just a proposition about which I wanted to get some feedback from people that know the codebase the most. It's my first time working on the grub project so apologies for any flukes or silliness in the code or the idea itself. Thank you! Best regards, [1] http://paste.ubuntu.com/p/cWR3k3NZgF/ -- Ćukasz 'sil2100' Zemczak Foundations Team lukasz.zemc...@canonical.com www.canonical.com
diff --git a/grub-core/osdep/basic/no_platform.c b/grub-core/osdep/basic/no_platform.c index d76c34c14..b39e97f48 100644 --- a/grub-core/osdep/basic/no_platform.c +++ b/grub-core/osdep/basic/no_platform.c @@ -25,7 +25,7 @@ void grub_install_register_ieee1275 (int is_prep, const char *install_device, - int partno, const char *relpath) + int partno, const char *relpath, int detect_nvram) { grub_util_error ("%s", _("no IEEE1275 routines are available for your platform")); } @@ -33,7 +33,8 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device, void grub_install_register_efi (grub_device_t efidir_grub_dev, const char *efifile_path, - const char *efi_distributor) + const char *efi_distributor, + int detect_nvram) { grub_util_error ("%s", _("no EFI routines are available for your platform")); } diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c index ca448bc11..4eb2c11c9 100644 --- a/grub-core/osdep/unix/platform.c +++ b/grub-core/osdep/unix/platform.c @@ -134,7 +134,8 @@ grub_install_remove_efi_entries_by_distributor (const char *efi_distributor) int grub_install_register_efi (grub_device_t efidir_grub_dev, const char *efifile_path, - const char *efi_distributor) + const char *efi_distributor, + int detect_nvram) { const char * efidir_disk; int efidir_part; @@ -153,6 +154,21 @@ grub_install_register_efi (grub_device_t efidir_grub_dev, #ifdef __linux__ grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL }); #endif + + /* If requested, we try to detect if NVRAM access is available and if not, + warn the user and resume normal operation. */ + if (detect_nvram) + { + error = grub_util_exec_redirect_null ((const char * []){ "efibootmgr", NULL }); + if (error == 2) + { + grub_util_warn ("%s", _("Auto-NVRAM selected and no EFI variable support detected on the system.")); + return 0; + } + else if (error) + return error; + } + /* Delete old entries from the same distributor. */ ret = grub_install_remove_efi_entries_by_distributor (efi_distributor); if (ret) @@ -178,7 +194,7 @@ grub_install_register_efi (grub_device_t efidir_grub_dev, void grub_install_register_ieee1275 (int is_prep, const char *install_device, - int partno, const char *relpath) + int partno, const char *relpath, int detect_nvram) { char *boot_device; @@ -189,6 +205,14 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device, grub_util_error (_("%s: not found"), "ofpathname"); } + /* If requested, we try to detect if NVRAM access is available and if not, + warn the user and resume normal operation. */ + if (detect_nvram && grub_util_exec_redirect_null ((const char * []){ "nvram", NULL })) + { + grub_util_warn ("%s", _("Auto-NVRAM selected and no IEEE1275 variable support detected on the system.")); + return; + } + /* Get the Open Firmware device tree path translation. */ if (!is_prep) { diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c index 912269191..f4c5bd47b 100644 --- a/grub-core/osdep/windows/platform.c +++ b/grub-core/osdep/windows/platform.c @@ -204,7 +204,8 @@ set_efi_variable_bootn (grub_uint16_t n, void *in, grub_size_t len) void grub_install_register_efi (grub_device_t efidir_grub_dev, const char *efifile_path, - const char *efi_distributor) + const char *efi_distributor, + int detect_nvram) { grub_uint16_t *boot_order, *new_boot_order; grub_uint16_t *distributor16; @@ -411,7 +412,7 @@ grub_install_register_efi (grub_device_t efidir_grub_dev, void grub_install_register_ieee1275 (int is_prep, const char *install_device, - int partno, const char *relpath) + int partno, const char *relpath, int detect_nvram) { grub_util_error ("%s", _("no IEEE1275 routines are available for your platform")); } diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 0dba8b67f..ba5140b5a 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -213,11 +213,12 @@ grub_install_get_default_x86_platform (void); int grub_install_register_efi (grub_device_t efidir_grub_dev, const char *efifile_path, - const char *efi_distributor); + const char *efi_distributor, + int detect_nvram); void grub_install_register_ieee1275 (int is_prep, const char *install_device, - int partno, const char *relpath); + int partno, const char *relpath, int detect_nvram); void grub_install_sgi_setup (const char *install_device, diff --git a/util/grub-install.c b/util/grub-install.c index 690f180c5..f963e72cb 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -57,6 +57,7 @@ static char *target; static int removable = 0; static int recheck = 0; static int update_nvram = 1; +static int auto_nvram = 0; static char *install_device = NULL; static char *debug_image = NULL; static char *rootdir = NULL; @@ -109,7 +110,8 @@ enum OPTION_LABEL_FONT, OPTION_LABEL_COLOR, OPTION_LABEL_BGCOLOR, - OPTION_PRODUCT_VERSION + OPTION_PRODUCT_VERSION, + OPTION_AUTO_NVRAM }; static int fs_probe = 1; @@ -200,6 +202,10 @@ argp_parser (int key, char *arg, struct argp_state *state) update_nvram = 0; return 0; + case OPTION_AUTO_NVRAM: + auto_nvram = 1; + return 0; + case OPTION_FORCE: force = 1; return 0; @@ -278,6 +284,9 @@ static struct argp_option options[] = { {"no-nvram", OPTION_NO_NVRAM, 0, 0, N_("don't update the `boot-device'/`Boot*' NVRAM variables. " "This option is only available on EFI and IEEE1275 targets."), 2}, + {"auto-nvram", OPTION_AUTO_NVRAM, 0, 0, + N_("only update NVRAM variables if possible. " + "This option is only available on EFI and IEEE1275 targets."), 2}, {"skip-fs-probe",'s',0, 0, N_("do not probe for filesystems in DEVICE"), 0}, {"no-bootsector", OPTION_NO_BOOTSECTOR, 0, 0, @@ -1755,7 +1764,7 @@ main (int argc, char *argv[]) ? ins_dev->disk->partition->number + 1 : 0; dev = grub_util_get_os_disk (install_device); grub_install_register_ieee1275 (0, dev, partno, - "\\\\BootX"); + "\\\\BootX", auto_nvram); } grub_device_close (ins_dev); free (grub_elf); @@ -1787,7 +1796,7 @@ main (int argc, char *argv[]) grub_device_close (ins_dev); if (update_nvram) grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device), - 0, NULL); + 0, NULL, auto_nvram); break; } /* fallthrough. */ @@ -1802,7 +1811,7 @@ main (int argc, char *argv[]) ? grub_dev->disk->partition->number + 1 : 0; dev = grub_util_get_os_disk (grub_devices[0]); grub_install_register_ieee1275 (0, dev, - partno, relpath); + partno, relpath, auto_nvram); } break; case GRUB_INSTALL_PLATFORM_MIPS_ARC: @@ -1851,7 +1860,7 @@ main (int argc, char *argv[]) int ret; ret = grub_install_register_efi (efidir_grub_dev, "\\System\\Library\\CoreServices", - efi_distributor); + efi_distributor, auto_nvram); if (ret) grub_util_error (_("efibootmgr failed to register the boot entry: %s"), strerror (ret)); @@ -1893,7 +1902,7 @@ main (int argc, char *argv[]) (part ? ",": ""), (part ? : "")); grub_free (part); ret = grub_install_register_efi (efidir_grub_dev, - efifile_path, efi_distributor); + efifile_path, efi_distributor, auto_nvram); if (ret) grub_util_error (_("efibootmgr failed to register the boot entry: %s"), strerror (ret));
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel