diff options
Diffstat (limited to 'gnu/bootloader/grub.scm')
| -rw-r--r-- | gnu/bootloader/grub.scm | 220 |
1 files changed, 138 insertions, 82 deletions
diff --git a/gnu/bootloader/grub.scm b/gnu/bootloader/grub.scm index 72832573547..aab766fd6ca 100644 --- a/gnu/bootloader/grub.scm +++ b/gnu/bootloader/grub.scm | |||
| @@ -53,13 +53,14 @@ | |||
| 53 | grub-theme-gfxmode | 53 | grub-theme-gfxmode |
| 54 | 54 | ||
| 55 | install-grub-efi-removable | 55 | install-grub-efi-removable |
| 56 | install-grub-efi-netboot | 56 | make-grub-efi-netboot-installer |
| 57 | 57 | ||
| 58 | grub-bootloader | 58 | grub-bootloader |
| 59 | grub-efi-bootloader | 59 | grub-efi-bootloader |
| 60 | grub-efi-removable-bootloader | 60 | grub-efi-removable-bootloader |
| 61 | grub-efi32-bootloader | 61 | grub-efi32-bootloader |
| 62 | grub-efi-netboot-bootloader | 62 | grub-efi-netboot-bootloader |
| 63 | grub-efi-netboot-removable-bootloader | ||
| 63 | grub-mkrescue-bootloader | 64 | grub-mkrescue-bootloader |
| 64 | grub-minimal-bootloader | 65 | grub-minimal-bootloader |
| 65 | 66 | ||
| @@ -353,7 +354,7 @@ code." | |||
| 353 | ((or #f (? string?)) | 354 | ((or #f (? string?)) |
| 354 | #~(format #f "search --file --set ~a" #$file))))) | 355 | #~(format #f "search --file --set ~a" #$file))))) |
| 355 | 356 | ||
| 356 | (define* (grub-configuration-file config entries | 357 | (define* (make-grub-configuration grub config entries |
| 357 | #:key | 358 | #:key |
| 358 | (locale #f) | 359 | (locale #f) |
| 359 | (system (%current-system)) | 360 | (system (%current-system)) |
| @@ -453,9 +454,7 @@ menuentry ~s { | |||
| 453 | (define locale-config | 454 | (define locale-config |
| 454 | (let* ((entry (first all-entries)) | 455 | (let* ((entry (first all-entries)) |
| 455 | (device (menu-entry-device entry)) | 456 | (device (menu-entry-device entry)) |
| 456 | (mount-point (menu-entry-device-mount-point entry)) | 457 | (mount-point (menu-entry-device-mount-point entry))) |
| 457 | (bootloader (bootloader-configuration-bootloader config)) | ||
| 458 | (grub (bootloader-package bootloader))) | ||
| 459 | #~(let ((locale #$(and locale | 458 | #~(let ((locale #$(and locale |
| 460 | (locale-definition-source | 459 | (locale-definition-source |
| 461 | (locale-name->definition locale)))) | 460 | (locale-name->definition locale)))) |
| @@ -481,8 +480,6 @@ set lang=~a~%" | |||
| 481 | 480 | ||
| 482 | (define keyboard-layout-config | 481 | (define keyboard-layout-config |
| 483 | (let* ((layout (bootloader-configuration-keyboard-layout config)) | 482 | (let* ((layout (bootloader-configuration-keyboard-layout config)) |
| 484 | (grub (bootloader-package | ||
| 485 | (bootloader-configuration-bootloader config))) | ||
| 486 | (keymap* (and layout | 483 | (keymap* (and layout |
| 487 | (keyboard-layout-file layout #:grub grub))) | 484 | (keyboard-layout-file layout #:grub grub))) |
| 488 | (entry (first all-entries)) | 485 | (entry (first all-entries)) |
| @@ -533,6 +530,16 @@ fi~%")))) | |||
| 533 | #:options '(#:local-build? #t | 530 | #:options '(#:local-build? #t |
| 534 | #:substitutable? #f))) | 531 | #:substitutable? #f))) |
| 535 | 532 | ||
| 533 | (define (grub-configuration-file config . args) | ||
| 534 | (let* ((bootloader (bootloader-configuration-bootloader config)) | ||
| 535 | (grub (bootloader-package bootloader))) | ||
| 536 | (apply make-grub-configuration grub config args))) | ||
| 537 | |||
| 538 | (define (grub-efi-configuration-file . args) | ||
| 539 | (apply make-grub-configuration grub-efi args)) | ||
| 540 | |||
| 541 | (define grub-cfg "/boot/grub/grub.cfg") | ||
| 542 | |||
| 536 | 543 | ||
| 537 | 544 | ||
| 538 | ;;; | 545 | ;;; |
| @@ -674,42 +681,31 @@ fi~%")))) | |||
| 674 | ((target-arm?) "--target=arm-efi")) | 681 | ((target-arm?) "--target=arm-efi")) |
| 675 | "--efi-directory" target-esp))))) | 682 | "--efi-directory" target-esp))))) |
| 676 | 683 | ||
| 677 | (define (install-grub-efi-netboot subdir) | 684 | (define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir) |
| 678 | "Define a grub-efi-netboot bootloader installer for installation in SUBDIR, | 685 | "Make a bootloader-installer for a grub-efi-netboot bootloader, which expects |
| 679 | which is usually efi/Guix or efi/boot." | 686 | its files in SUBDIR and its configuration file in GRUB-CFG. |
| 680 | (let* ((system (string-split (nix-system->gnu-triplet | 687 | |
| 681 | (or (%current-target-system) | 688 | As a grub-efi-netboot package is already pre-installed by 'grub-mknetdir', the |
| 682 | (%current-system))) | 689 | installer basically copies all files from the bootloader-package (or profile) |
| 683 | #\-)) | 690 | into the bootloader-target directory. |
| 684 | (arch (first system)) | 691 | |
| 685 | (boot-efi-link (match system | 692 | Additionally for network booting over TFTP, two relative symlinks to the store |
| 686 | ;; These are the supportend systems and the names | 693 | and to the GRUB-CFG file are necessary. Due to this a TFTP root directory must |
| 687 | ;; defined by the UEFI standard for removable media. | 694 | not be located on a FAT file-system. |
| 688 | (("i686" _ ...) "/bootia32.efi") | 695 | |
| 689 | (("x86_64" _ ...) "/bootx64.efi") | 696 | If the bootloader-target does not support symlinks, then it is assumed to be a |
| 690 | (("arm" _ ...) "/bootarm.efi") | 697 | kind of EFI System Partition (ESP). In this case an intermediate configuration |
| 691 | (("aarch64" _ ...) "/bootaa64.efi") | 698 | file is created with the help of GRUB-EFI to load the GRUB-CFG. |
| 692 | (("riscv" _ ...) "/bootriscv32.efi") | 699 | |
| 693 | (("riscv64" _ ...) "/bootriscv64.efi") | 700 | The installer is usable for any efi-bootloader-chain, which prepares the |
| 694 | ;; Other systems are not supported, although defined. | 701 | bootloader-profile in a way ready for copying. |
| 695 | ;; (("riscv128" _ ...) "/bootriscv128.efi") | 702 | |
| 696 | ;; (("ia64" _ ...) "/bootia64.efi") | 703 | The installer does not manipulate the system's 'UEFI Boot Manager'. |
| 697 | ((_ ...) #f))) | 704 | |
| 698 | (core-efi (string-append | 705 | The returned installer accepts the BOOTLOADER, TARGET and MOUNT-POINT |
| 699 | ;; This is the arch dependent file name of GRUB, e.g. | 706 | arguments. Its job is to copy the BOOTLOADER, which must be a pre-installed |
| 700 | ;; i368-efi/core.efi or arm64-efi/core.efi. | 707 | grub-efi-netboot package with a SUBDIR like efi/boot or efi/Guix, below the |
| 701 | (match arch | 708 | directory TARGET for the system whose root is mounted at MOUNT-POINT. |
| 702 | ("i686" "i386") | ||
| 703 | ("aarch64" "arm64") | ||
| 704 | ("riscv" "riscv32") | ||
| 705 | (_ arch)) | ||
| 706 | "-efi/core.efi"))) | ||
| 707 | (with-imported-modules | ||
| 708 | '((guix build union)) | ||
| 709 | #~(lambda (bootloader target mount-point) | ||
| 710 | "Install the BOOTLOADER, which must be the package grub, as e.g. | ||
| 711 | bootx64.efi or bootaa64.efi into SUBDIR, which is usually efi/Guix or efi/boot, | ||
| 712 | below the directory TARGET for the system whose root is mounted at MOUNT-POINT. | ||
| 713 | 709 | ||
| 714 | MOUNT-POINT is the last argument in 'guix system init /etc/config.scm mnt/point' | 710 | MOUNT-POINT is the last argument in 'guix system init /etc/config.scm mnt/point' |
| 715 | or '/' for other 'guix system' commands. | 711 | or '/' for other 'guix system' commands. |
| @@ -719,17 +715,19 @@ bootloader-configuration in: | |||
| 719 | 715 | ||
| 720 | (operating-system | 716 | (operating-system |
| 721 | (bootloader (bootloader-configuration | 717 | (bootloader (bootloader-configuration |
| 722 | (targets '(\"/boot\")) | 718 | (targets '(\"/boot/efi\")) |
| 723 | …)) | 719 | …)) |
| 724 | …) | 720 | …) |
| 725 | 721 | ||
| 726 | TARGET is required to be an absolute directory name, usually mounted via NFS, | 722 | TARGET is required to be an absolute directory name, usually mounted via NFS, |
| 727 | and finally needs to be provided by a TFTP server as the TFTP root directory. | 723 | and finally needs to be provided by a TFTP server as |
| 724 | the TFTP root directory. | ||
| 728 | 725 | ||
| 726 | Usually the installer will be used to prepare network booting over TFTP. Then | ||
| 729 | GRUB will load tftp://server/SUBDIR/grub.cfg and this file will instruct it to | 727 | GRUB will load tftp://server/SUBDIR/grub.cfg and this file will instruct it to |
| 730 | load more files from the store like tftp://server/gnu/store/…-linux…/Image. | 728 | load more files from the store like tftp://server/gnu/store/…-linux…/Image. |
| 731 | 729 | ||
| 732 | To make this possible two symlinks will be created. The first symlink points | 730 | To make this possible two symlinks are created. The first symlink points |
| 733 | relatively form MOUNT-POINT/TARGET/SUBDIR/grub.cfg to | 731 | relatively form MOUNT-POINT/TARGET/SUBDIR/grub.cfg to |
| 734 | MOUNT-POINT/boot/grub/grub.cfg, and the second symlink points relatively from | 732 | MOUNT-POINT/boot/grub/grub.cfg, and the second symlink points relatively from |
| 735 | MOUNT-POINT/TARGET/%store-prefix to MOUNT-POINT/%store-prefix. | 733 | MOUNT-POINT/TARGET/%store-prefix to MOUNT-POINT/%store-prefix. |
| @@ -739,34 +737,80 @@ paths on the TFTP server side are unknown. | |||
| 739 | 737 | ||
| 740 | It is also important to note that both symlinks will point outside the TFTP root | 738 | It is also important to note that both symlinks will point outside the TFTP root |
| 741 | directory and that the TARGET/%store-prefix symlink makes the whole store | 739 | directory and that the TARGET/%store-prefix symlink makes the whole store |
| 742 | accessible via TFTP. Possibly the TFTP server must be configured | 740 | accessible via TFTP. Possibly the TFTP server must be configured to allow |
| 743 | to allow accesses outside its TFTP root directory. This may need to be | 741 | accesses outside its TFTP root directory. This all may need to be considered |
| 744 | considered for security aspects." | 742 | for security aspects. It is advised to disable any TFTP write access! |
| 745 | (use-modules ((guix build union) #:select (symlink-relative))) | 743 | |
| 746 | (let* ((net-dir (string-append mount-point target "/")) | 744 | The installer can also be used to prepare booting from local storage, if the |
| 747 | (sub-dir (string-append net-dir #$subdir "/")) | 745 | underlying file-system, like FAT on an EFI System Partition (ESP), does not |
| 748 | (store (string-append mount-point (%store-prefix))) | 746 | support symlinks. In this case the MOUNT-POINT/TARGET/SUBDIR/grub.cfg will be |
| 749 | (store-link (string-append net-dir (%store-prefix))) | 747 | created with the help of GRUB-EFI to load the /boot/grub/grub.cfg file. A |
| 750 | (grub-cfg (string-append mount-point "/boot/grub/grub.cfg")) | 748 | symlink to the store is not needed in this case." |
| 751 | (grub-cfg-link (string-append sub-dir (basename grub-cfg))) | 749 | (with-imported-modules '((guix build union)) |
| 752 | (boot-efi-link (string-append sub-dir #$boot-efi-link))) | 750 | #~(lambda (bootloader target mount-point) |
| 753 | ;; Prepare the symlink to the store. | 751 | ;; In context of a disk image creation TARGET will be #f and an |
| 754 | (mkdir-p (dirname store-link)) | 752 | ;; installer is expected to do necessary installations on MOUNT-POINT, |
| 755 | (false-if-exception (delete-file store-link)) | 753 | ;; which will become the root file system. If TARGET is #f, this |
| 756 | (symlink-relative store store-link) | 754 | ;; installer has nothing to do, as it only cares about the EFI System |
| 757 | ;; Prepare the symlink to the grub.cfg, which points into the store. | 755 | ;; Partition (ESP). |
| 758 | (mkdir-p (dirname grub-cfg-link)) | 756 | (when target |
| 759 | (false-if-exception (delete-file grub-cfg-link)) | 757 | (use-modules ((guix build union) #:select (symlink-relative)) |
| 760 | (symlink-relative grub-cfg grub-cfg-link) | 758 | (ice-9 popen) |
| 761 | ;; Install GRUB, which refers to the grub.cfg, with support for | 759 | (ice-9 rdelim)) |
| 762 | ;; encrypted partitions, | 760 | (let* ((mount-point/target (string-append mount-point target "/")) |
| 763 | (setenv "GRUB_ENABLE_CRYPTODISK" "y") | 761 | ;; When installing Guix, it is common to mount TARGET below |
| 764 | (invoke/quiet (string-append bootloader "/bin/grub-mknetdir") | 762 | ;; MOUNT-POINT rather than the root directory. |
| 765 | (string-append "--net-directory=" net-dir) | 763 | (bootloader-target (if (file-exists? mount-point/target) |
| 766 | (string-append "--subdir=" #$subdir)) | 764 | mount-point/target |
| 767 | ;; Prepare the bootloader symlink, which points to core.efi of GRUB. | 765 | target)) |
| 768 | (false-if-exception (delete-file boot-efi-link)) | 766 | (store (string-append mount-point (%store-prefix))) |
| 769 | (symlink #$core-efi boot-efi-link)))))) | 767 | (store-link (string-append bootloader-target (%store-prefix))) |
| 768 | (grub-cfg (string-append mount-point #$grub-cfg)) | ||
| 769 | (grub-cfg-link (string-append bootloader-target | ||
| 770 | #$subdir "/" | ||
| 771 | (basename grub-cfg)))) | ||
| 772 | ;; Copy the bootloader into the bootloader-target directory. | ||
| 773 | ;; Should we beforehand recursively delete any existing file? | ||
| 774 | (copy-recursively bootloader bootloader-target | ||
| 775 | #:follow-symlinks? #t | ||
| 776 | #:log (%make-void-port "w")) | ||
| 777 | ;; For TFTP we need to install additional relative symlinks. | ||
| 778 | ;; If we install on an EFI System Partition (ESP) or some other FAT | ||
| 779 | ;; file-system, then symlinks cannot be created and are not needed. | ||
| 780 | ;; Therefore we ignore exceptions when trying. | ||
| 781 | ;; Prepare the symlink to the grub.cfg. | ||
| 782 | (mkdir-p (dirname grub-cfg-link)) | ||
| 783 | (false-if-exception (delete-file grub-cfg-link)) | ||
| 784 | (if (unspecified? | ||
| 785 | (false-if-exception (symlink-relative grub-cfg grub-cfg-link))) | ||
| 786 | ;; Symlinks are supported. | ||
| 787 | (begin | ||
| 788 | ;; Prepare the symlink to the store. | ||
| 789 | (mkdir-p (dirname store-link)) | ||
| 790 | (false-if-exception (delete-file store-link)) | ||
| 791 | (symlink-relative store store-link)) | ||
| 792 | ;; Creating symlinks does not seem to be supported. Probably | ||
| 793 | ;; an ESP is used. Add a script to search and load the actual | ||
| 794 | ;; grub.cfg. | ||
| 795 | (let* ((probe #$(file-append grub-efi "/sbin/grub-probe")) | ||
| 796 | (port (open-pipe* OPEN_READ probe "--target=fs_uuid" | ||
| 797 | grub-cfg)) | ||
| 798 | (search-root | ||
| 799 | (match (read-line port) | ||
| 800 | ((? eof-object?) | ||
| 801 | ;; There is no UUID available. As a fallback search | ||
| 802 | ;; everywhere for the grub.cfg. | ||
| 803 | (string-append "search --file --set " #$grub-cfg)) | ||
| 804 | (fs-uuid | ||
| 805 | ;; The UUID to load the grub.cfg from is known. | ||
| 806 | (string-append "search --fs-uuid --set " fs-uuid)))) | ||
| 807 | (load-grub-cfg (string-append "configfile " #$grub-cfg))) | ||
| 808 | (close-pipe port) | ||
| 809 | (with-output-to-file grub-cfg-link | ||
| 810 | (lambda () | ||
| 811 | (display (string-join (list search-root | ||
| 812 | load-grub-cfg) | ||
| 813 | "\n"))))))))))) | ||
| 770 | 814 | ||
| 771 | 815 | ||
| 772 | 816 | ||
| @@ -784,7 +828,7 @@ considered for security aspects." | |||
| 784 | (package grub) | 828 | (package grub) |
| 785 | (installer install-grub) | 829 | (installer install-grub) |
| 786 | (disk-image-installer install-grub-disk-image) | 830 | (disk-image-installer install-grub-disk-image) |
| 787 | (configuration-file "/boot/grub/grub.cfg") | 831 | (configuration-file grub-cfg) |
| 788 | (configuration-file-generator grub-configuration-file))) | 832 | (configuration-file-generator grub-configuration-file))) |
| 789 | 833 | ||
| 790 | (define grub-minimal-bootloader | 834 | (define grub-minimal-bootloader |
| @@ -794,11 +838,12 @@ considered for security aspects." | |||
| 794 | 838 | ||
| 795 | (define grub-efi-bootloader | 839 | (define grub-efi-bootloader |
| 796 | (bootloader | 840 | (bootloader |
| 797 | (inherit grub-bootloader) | 841 | (name 'grub-efi) |
| 842 | (package grub-efi) | ||
| 798 | (installer install-grub-efi) | 843 | (installer install-grub-efi) |
| 799 | (disk-image-installer #f) | 844 | (disk-image-installer #f) |
| 800 | (name 'grub-efi) | 845 | (configuration-file grub-cfg) |
| 801 | (package grub-efi))) | 846 | (configuration-file-generator grub-configuration-file))) |
| 802 | 847 | ||
| 803 | (define grub-efi-removable-bootloader | 848 | (define grub-efi-removable-bootloader |
| 804 | (bootloader | 849 | (bootloader |
| @@ -813,11 +858,22 @@ considered for security aspects." | |||
| 813 | (name 'grub-efi32) | 858 | (name 'grub-efi32) |
| 814 | (package grub-efi32))) | 859 | (package grub-efi32))) |
| 815 | 860 | ||
| 816 | (define grub-efi-netboot-bootloader | 861 | (define (make-grub-efi-netboot-bootloader name subdir) |
| 817 | (bootloader | 862 | (bootloader |
| 818 | (inherit grub-efi-bootloader) | 863 | (name name) |
| 819 | (name 'grub-efi-netboot-bootloader) | 864 | (package (make-grub-efi-netboot (symbol->string name) subdir)) |
| 820 | (installer (install-grub-efi-netboot "efi/Guix")))) | 865 | (installer (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)) |
| 866 | (disk-image-installer #f) | ||
| 867 | (configuration-file grub-cfg) | ||
| 868 | (configuration-file-generator grub-efi-configuration-file))) | ||
| 869 | |||
| 870 | (define grub-efi-netboot-bootloader | ||
| 871 | (make-grub-efi-netboot-bootloader 'grub-efi-netboot-bootloader | ||
| 872 | "efi/Guix")) | ||
| 873 | |||
| 874 | (define grub-efi-netboot-removable-bootloader | ||
| 875 | (make-grub-efi-netboot-bootloader 'grub-efi-netboot-removable-bootloader | ||
| 876 | "efi/boot")) | ||
| 821 | 877 | ||
| 822 | (define grub-mkrescue-bootloader | 878 | (define grub-mkrescue-bootloader |
| 823 | (bootloader | 879 | (bootloader |
