diff options
Diffstat (limited to 'nixpkgs/pkgs/tools/misc/grub')
6 files changed, 505 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/tools/misc/grub/add-hidden-menu-entries.patch b/nixpkgs/pkgs/tools/misc/grub/add-hidden-menu-entries.patch new file mode 100644 index 000000000000..836a9853708f --- /dev/null +++ b/nixpkgs/pkgs/tools/misc/grub/add-hidden-menu-entries.patch @@ -0,0 +1,204 @@ +diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c +index e9e9d94ef..54e08a1b4 100644 +--- a/grub-core/commands/legacycfg.c ++++ b/grub-core/commands/legacycfg.c +@@ -143,7 +143,7 @@ legacy_file (const char *filename) + args[0] = oldname; + grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy", + NULL, NULL, +- entrysrc, 0); ++ entrysrc, 0, 0); + grub_free (args); + entrysrc[0] = 0; + grub_free (oldname); +@@ -205,7 +205,7 @@ legacy_file (const char *filename) + } + args[0] = entryname; + grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, +- NULL, NULL, entrysrc, 0); ++ NULL, NULL, entrysrc, 0, 0); + grub_free (args); + } + +diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c +index 720e6d8ea..50632ccce 100644 +--- a/grub-core/commands/menuentry.c ++++ b/grub-core/commands/menuentry.c +@@ -78,7 +78,7 @@ grub_normal_add_menu_entry (int argc, const char **args, + char **classes, const char *id, + const char *users, const char *hotkey, + const char *prefix, const char *sourcecode, +- int submenu) ++ int submenu, int hidden) + { + int menu_hotkey = 0; + char **menu_args = NULL; +@@ -188,8 +188,11 @@ grub_normal_add_menu_entry (int argc, const char **args, + (*last)->args = menu_args; + (*last)->sourcecode = menu_sourcecode; + (*last)->submenu = submenu; ++ (*last)->hidden = hidden; ++ ++ if (!hidden) ++ menu->size++; + +- menu->size++; + return GRUB_ERR_NONE; + + fail: +@@ -286,7 +289,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) + users, + ctxt->state[2].arg, 0, + ctxt->state[3].arg, +- ctxt->extcmd->cmd->name[0] == 's'); ++ ctxt->extcmd->cmd->name[0] == 's', ++ ctxt->extcmd->cmd->name[0] == 'h'); + + src = args[argc - 1]; + args[argc - 1] = NULL; +@@ -303,7 +307,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) + ctxt->state[0].args, ctxt->state[4].arg, + users, + ctxt->state[2].arg, prefix, src + 1, +- ctxt->extcmd->cmd->name[0] == 's'); ++ ctxt->extcmd->cmd->name[0] == 's', ++ ctxt->extcmd->cmd->name[0] == 'h'); + + src[len - 1] = ch; + args[argc - 1] = src; +@@ -311,7 +316,7 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) + return r; + } + +-static grub_extcmd_t cmd, cmd_sub; ++static grub_extcmd_t cmd, cmd_sub, cmd_hidden; + + void + grub_menu_init (void) +@@ -327,6 +332,12 @@ grub_menu_init (void) + | GRUB_COMMAND_FLAG_EXTRACTOR, + N_("BLOCK"), N_("Define a submenu."), + options); ++ cmd_hidden = grub_register_extcmd ("hiddenentry", grub_cmd_menuentry, ++ GRUB_COMMAND_FLAG_BLOCKS ++ | GRUB_COMMAND_ACCEPT_DASH ++ | GRUB_COMMAND_FLAG_EXTRACTOR, ++ N_("BLOCK"), N_("Define a hidden menu entry."), ++ options); + } + + void +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index 6a90e091f..4236f55bc 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -37,6 +37,8 @@ + entry failing to boot. */ + #define DEFAULT_ENTRY_ERROR_DELAY_MS 2500 + ++#define MENU_INCLUDE_HIDDEN 0x10000 ++ + grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu, + int nested) = NULL; + +@@ -80,8 +82,20 @@ grub_menu_get_entry (grub_menu_t menu, int no) + { + grub_menu_entry_t e; + +- for (e = menu->entry_list; e && no > 0; e = e->next, no--) +- ; ++ if (no & MENU_INCLUDE_HIDDEN) { ++ no &= ~MENU_INCLUDE_HIDDEN; ++ ++ for (e = menu->entry_list; e && no > 0; e = e->next, no--) ++ ; ++ } else { ++ for (e = menu->entry_list; e && no > 0; e = e->next, no--) { ++ /* Skip hidden entries */ ++ while (e && e->hidden) ++ e = e->next; ++ } ++ while (e && e->hidden) ++ e = e->next; ++ } + + return e; + } +@@ -93,10 +107,10 @@ get_entry_index_by_hotkey (grub_menu_t menu, int hotkey) + grub_menu_entry_t entry; + int i; + +- for (i = 0, entry = menu->entry_list; i < menu->size; ++ for (i = 0, entry = menu->entry_list; entry; + i++, entry = entry->next) + if (entry->hotkey == hotkey) +- return i; ++ return i | MENU_INCLUDE_HIDDEN; + + return -1; + } +@@ -509,6 +523,10 @@ get_entry_number (grub_menu_t menu, const char *name) + grub_menu_entry_t e = menu->entry_list; + int i; + ++ /* Skip hidden entries */ ++ while (e && e->hidden) ++ e = e->next; ++ + grub_errno = GRUB_ERR_NONE; + + for (i = 0; e; i++) +@@ -520,6 +538,10 @@ get_entry_number (grub_menu_t menu, const char *name) + break; + } + e = e->next; ++ ++ /* Skip hidden entries */ ++ while (e && e->hidden) ++ e = e->next; + } + + if (! e) +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index b1321eb26..d2e46cac8 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -289,7 +289,11 @@ print_entries (grub_menu_t menu, const struct menu_viewer_data *data) + print_entry (data->geo.first_entry_y + i, data->offset == i, + e, data); + if (e) +- e = e->next; ++ e = e->next; ++ ++ /* Skip hidden entries */ ++ while (e && e->hidden) ++ e = e->next; + } + + grub_term_gotoxy (data->term, +diff --git a/include/grub/menu.h b/include/grub/menu.h +index ee2b5e910..eb8a86ba9 100644 +--- a/include/grub/menu.h ++++ b/include/grub/menu.h +@@ -58,6 +58,8 @@ struct grub_menu_entry + + int submenu; + ++ int hidden; ++ + /* The next element. */ + struct grub_menu_entry *next; + }; +diff --git a/include/grub/normal.h b/include/grub/normal.h +index 218cbabcc..bcb412466 100644 +--- a/include/grub/normal.h ++++ b/include/grub/normal.h +@@ -145,7 +145,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, + const char *id, + const char *users, const char *hotkey, + const char *prefix, const char *sourcecode, +- int submenu); ++ int submenu, int hidden); + + grub_err_t + grub_normal_set_password (const char *user, const char *password); diff --git a/nixpkgs/pkgs/tools/misc/grub/default.nix b/nixpkgs/pkgs/tools/misc/grub/default.nix new file mode 100644 index 000000000000..5fc189a4de11 --- /dev/null +++ b/nixpkgs/pkgs/tools/misc/grub/default.nix @@ -0,0 +1,222 @@ +{ lib, stdenv, runCommand, fetchFromSavannah, fetchpatch, flex, bison, python3, autoconf, automake, libtool, bash +, rsync, gettext, ncurses, libusb-compat-0_1, freetype, qemu, lvm2, unifont, pkg-config +, buildPackages +, nixosTests +, fuse # only needed for grub-mount +, runtimeShell +, zfs ? null +, efiSupport ? false +, zfsSupport ? false +, xenSupport ? false +, kbdcompSupport ? false, ckbcomp +}: + +let + pcSystems = { + i686-linux.target = "i386"; + x86_64-linux.target = "i386"; + }; + + efiSystemsBuild = { + i686-linux.target = "i386"; + x86_64-linux.target = "x86_64"; + armv7l-linux.target = "arm"; + aarch64-linux.target = "aarch64"; + riscv32-linux.target = "riscv32"; + riscv64-linux.target = "riscv64"; + }; + + # For aarch64, we need to use '--target=aarch64-efi' when building, + # but '--target=arm64-efi' when installing. Insanity! + efiSystemsInstall = { + i686-linux.target = "i386"; + x86_64-linux.target = "x86_64"; + armv7l-linux.target = "arm"; + aarch64-linux.target = "arm64"; + riscv32-linux.target = "riscv32"; + riscv64-linux.target = "riscv64"; + }; + + canEfi = lib.any (system: stdenv.hostPlatform.system == system) (lib.mapAttrsToList (name: _: name) efiSystemsBuild); + inPCSystems = lib.any (system: stdenv.hostPlatform.system == system) (lib.mapAttrsToList (name: _: name) pcSystems); + + gnulib = fetchFromSavannah { + repo = "gnulib"; + # NOTE: keep in sync with bootstrap.conf! + rev = "9f48fb992a3d7e96610c4ce8be969cff2d61a01b"; + hash = "sha256-mzbF66SNqcSlI+xmjpKpNMwzi13yEWoc1Fl7p4snTto="; + }; + + src = fetchFromSavannah { + repo = "grub"; + rev = "grub-2.12-rc1"; + hash = "sha256-DrNFzi2o7ZUfL3bMdG63xivZIjcTgv8RODJz7hLJ3WY="; + }; + + # HACK: the translations are stored on a different server, + # not versioned and not included in the git repo, so fetch them + # and hope they don't change often + locales = runCommand "grub-locales" { + nativeBuildInputs = [rsync]; + + outputHashAlgo = "sha256"; + outputHashMode = "recursive"; + outputHash = "sha256-bQPQ65gAcuUQ8ELB2hKywuXZ0kdC2bBCsUII/b4FkvQ="; + } + '' + mkdir -p po + ${src}/linguas.sh + + mv po $out + ''; +in ( + +assert efiSupport -> canEfi; +assert zfsSupport -> zfs != null; +assert !(efiSupport && xenSupport); + +stdenv.mkDerivation rec { + pname = "grub"; + version = "2.12-rc1"; + inherit src; + + patches = [ + ./fix-bash-completion.patch + ./add-hidden-menu-entries.patch + + # Revert upstream commit that breaks reading XFS filesystems + # FIXME: remove when fixed upstream + (fetchpatch { + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=ef7850c757fb3dd2462a512cfa0ff19c89fcc0b1"; + revert = true; + hash = "sha256-p8Kcv9d7ri4eJU6Fgqyzdj0hV5MHSe50AF02FPDJx2Y="; + }) + ]; + + postPatch = if kbdcompSupport then '' + sed -i util/grub-kbdcomp.in -e 's@\bckbcomp\b@${ckbcomp}/bin/ckbcomp@' + '' else '' + echo '#! ${runtimeShell}' > util/grub-kbdcomp.in + echo 'echo "Compile grub2 with { kbdcompSupport = true; } to enable support for this command."' >> util/grub-kbdcomp.in + ''; + + depsBuildBuild = [ buildPackages.stdenv.cc ]; + nativeBuildInputs = [ bison flex python3 pkg-config gettext freetype autoconf automake ]; + buildInputs = [ ncurses libusb-compat-0_1 freetype lvm2 fuse libtool bash ] + ++ lib.optional doCheck qemu + ++ lib.optional zfsSupport zfs; + + strictDeps = true; + + hardeningDisable = [ "all" ]; + + separateDebugInfo = !xenSupport; + + preConfigure = + '' for i in "tests/util/"*.in + do + sed -i "$i" -e's|/bin/bash|${stdenv.shell}|g' + done + + # Apparently, the QEMU executable is no longer called + # `qemu-system-i386', even on i386. + # + # In addition, use `-nodefaults' to avoid errors like: + # + # chardev: opening backend "stdio" failed + # qemu: could not open serial device 'stdio': Invalid argument + # + # See <http://www.mail-archive.com/qemu-devel@nongnu.org/msg22775.html>. + sed -i "tests/util/grub-shell.in" \ + -e's/qemu-system-i386/qemu-system-x86_64 -nodefaults/g' + + unset CPP # setting CPP intereferes with dependency calculation + + patchShebangs . + + GNULIB_REVISION=$(. bootstrap.conf; echo $GNULIB_REVISION) + if [ "$GNULIB_REVISION" != ${gnulib.rev} ]; then + echo "This version of GRUB requires a different gnulib revision!" + echo "We have: ${gnulib.rev}" + echo "GRUB needs: $GNULIB_REVISION" + exit 1 + fi + + cp -f --no-preserve=mode ${locales}/* po + + ./bootstrap --no-git --gnulib-srcdir=${gnulib} + + substituteInPlace ./configure --replace '/usr/share/fonts/unifont' '${unifont}/share/fonts' + ''; + + postConfigure = '' + # make sure .po files are up to date to workaround + # parallel `msgmerge --update` on autogenerated .po files: + # https://github.com/NixOS/nixpkgs/pull/248747#issuecomment-1676301670 + make dist + ''; + + configureFlags = [ + "--enable-grub-mount" # dep of os-prober + ] ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [ + # grub doesn't do cross-compilation as usual and tries to use unprefixed + # tools to target the host. Provide toolchain information explicitly for + # cross builds. + # + # Ref: # https://github.com/buildroot/buildroot/blob/master/boot/grub2/grub2.mk#L108 + "TARGET_CC=${stdenv.cc.targetPrefix}cc" + "TARGET_NM=${stdenv.cc.targetPrefix}nm" + "TARGET_OBJCOPY=${stdenv.cc.targetPrefix}objcopy" + "TARGET_RANLIB=${stdenv.cc.targetPrefix}ranlib" + "TARGET_STRIP=${stdenv.cc.targetPrefix}strip" + ] ++ lib.optional zfsSupport "--enable-libzfs" + ++ lib.optionals efiSupport [ "--with-platform=efi" "--target=${efiSystemsBuild.${stdenv.hostPlatform.system}.target}" "--program-prefix=" ] + ++ lib.optionals xenSupport [ "--with-platform=xen" "--target=${efiSystemsBuild.${stdenv.hostPlatform.system}.target}"]; + + # save target that grub is compiled for + grubTarget = if efiSupport + then "${efiSystemsInstall.${stdenv.hostPlatform.system}.target}-efi" + else lib.optionalString inPCSystems "${pcSystems.${stdenv.hostPlatform.system}.target}-pc"; + + doCheck = false; + enableParallelBuilding = true; + + postInstall = '' + # Avoid a runtime reference to gcc + sed -i $out/lib/grub/*/modinfo.sh -e "/grub_target_cppflags=/ s|'.*'|' '|" + # just adding bash to buildInputs wasn't enough to fix the shebang + substituteInPlace $out/lib/grub/*/modinfo.sh \ + --replace ${buildPackages.bash} "/usr/bin/bash" + ''; + + passthru.tests = { + nixos-grub = nixosTests.grub; + nixos-install-simple = nixosTests.installer.simple; + nixos-install-grub-uefi = nixosTests.installer.simpleUefiGrub; + nixos-install-grub-uefi-spec = nixosTests.installer.simpleUefiGrubSpecialisation; + }; + + meta = with lib; { + description = "GNU GRUB, the Grand Unified Boot Loader"; + + longDescription = + '' GNU GRUB is a Multiboot boot loader. It was derived from GRUB, GRand + Unified Bootloader, which was originally designed and implemented by + Erich Stefan Boleyn. + + Briefly, the boot loader is the first software program that runs when a + computer starts. It is responsible for loading and transferring + control to the operating system kernel software (such as the Hurd or + the Linux). The kernel, in turn, initializes the rest of the + operating system (e.g., GNU). + ''; + + homepage = "https://www.gnu.org/software/grub/"; + + license = licenses.gpl3Plus; + + platforms = platforms.gnu ++ platforms.linux; + + maintainers = [ maintainers.samueldr ]; + }; +}) diff --git a/nixpkgs/pkgs/tools/misc/grub/fix-bash-completion.patch b/nixpkgs/pkgs/tools/misc/grub/fix-bash-completion.patch new file mode 100644 index 000000000000..97cecdce373f --- /dev/null +++ b/nixpkgs/pkgs/tools/misc/grub/fix-bash-completion.patch @@ -0,0 +1,24 @@ +diff -ubr grub-2.00-orig/util/bash-completion.d/grub-completion.bash.in grub-2.00/util/bash-completion.d/grub-completion.bash.in +--- grub-2.00-orig/util/bash-completion.d/grub-completion.bash.in 2012-10-16 19:02:36.342733957 +0200 ++++ grub-2.00/util/bash-completion.d/grub-completion.bash.in 2012-10-16 19:04:48.262733941 +0200 +@@ -17,6 +17,12 @@ + # along with GRUB. If not, see <http://www.gnu.org/licenses/>. + # bash completion for grub + ++have() ++{ ++ unset -v have ++ _have $1 && have=yes ++} ++ + __grub_dir() { + local i c=1 boot_dir + +@@ -479,6 +485,7 @@ + have ${__grub_script_check_program} && \ + complete -F _grub_script_check -o filenames ${__grub_script_check_program} + ++unset -f have + + # Local variables: + # mode: shell-script diff --git a/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/configs/grub-bootstrap.cfg b/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/configs/grub-bootstrap.cfg new file mode 100644 index 000000000000..e9883149ab5d --- /dev/null +++ b/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/configs/grub-bootstrap.cfg @@ -0,0 +1 @@ +normal (memdisk)/grub.cfg diff --git a/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/configs/grub.cfg b/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/configs/grub.cfg new file mode 100644 index 000000000000..69115b7101c9 --- /dev/null +++ b/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/configs/grub.cfg @@ -0,0 +1,10 @@ +# The parentheses around ${root} here to match Grub's config file syntax +if search -s -f /boot/grub/grub.cfg ; then + echo "Reading (${root})/boot/grub/grub.cfg" + configfile /boot/grub/grub.cfg +fi + +if search -s -f /grub/grub.cfg ; then + echo "Reading (${root})/grub/grub.cfg" + configfile /grub/grub.cfg +fi diff --git a/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/default.nix b/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/default.nix new file mode 100644 index 000000000000..b6883e570802 --- /dev/null +++ b/nixpkgs/pkgs/tools/misc/grub/pvgrub_image/default.nix @@ -0,0 +1,44 @@ +{ lib, stdenv, grub2_xen }: + +let + efiSystemsBuild = { + i686-linux.target = "i386"; + x86_64-linux.target = "x86_64"; + armv7l-linux.target = "arm"; + aarch64-linux.target = "aarch64"; + riscv32-linux.target = "riscv32"; + riscv64-linux.target = "riscv64"; + }; + +in ( + +stdenv.mkDerivation rec { + name = "pvgrub-image"; + + configs = ./configs; + + buildInputs = [ grub2_xen ]; + + buildCommand = '' + cp "${configs}"/* . + tar -cf memdisk.tar grub.cfg + # We include all modules except all_video.mod as otherwise grub will fail printing "no symbol table" + # if we include it. + grub-mkimage -O "${efiSystemsBuild.${stdenv.hostPlatform.system}.target}-xen" -c grub-bootstrap.cfg \ + -m memdisk.tar -o "grub-${efiSystemsBuild.${stdenv.hostPlatform.system}.target}-xen.bin" \ + $(ls "${grub2_xen}/lib/grub/${efiSystemsBuild.${stdenv.hostPlatform.system}.target}-xen/" |grep 'mod''$'|grep -v '^all_video\.mod''$') + mkdir -p "$out/lib/grub-xen" + cp "grub-${efiSystemsBuild.${stdenv.hostPlatform.system}.target}-xen.bin" $out/lib/grub-xen/ + ''; + + meta = with lib; { + description = "PvGrub image for use for booting PV Xen guests"; + + longDescription = + '' This package provides a PvGrub image for booting Para-Virtualized (PV) + Xen guests + ''; + + platforms = platforms.gnu ++ platforms.linux; + }; +}) |