summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorStefan <stefan-guix@vodafonemail.de>2022-11-30 19:59:09 -0500
committerMaxim Cournoyer <maxim.cournoyer@gmail.com>2022-12-01 14:31:28 -0500
commita9acbf919a7668e26863d2d26d48c5fd41b57fcd (patch)
treee29c25d793f35b03a711ed865d20eecb55033034 /gnu
parent1a63aea94340f6a24ac09e1c348401e9dfd05395 (diff)
gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.
This rework allows to use an (efi-bootloader-chain) like this, which is able to boot over network or local storage, depending on whether the bootloader target has support for symbolic links: (operating-system (bootloader (bootloader-configuration (bootloader (efi-bootloader-chain grub-efi-netboot-removable-bootloader #:packages (list my-firmware-package my-u-boot-package) #:files (list (plain-file "config.txt" "kernel=u-boot.bin")) #:hooks my-special-bootloader-profile-manipulator)) (targets '("/booti/efi")) …)) …) * doc/guix.texi (Bootloader Configuration): Describe the new ‘grub-efi-netboot-removable-bootloader’. Mention the file names used and that the UEFI Boot Manager is not modified. Advise to disable write-access over TFTP. * gnu/bootloader.scm (efi-bootloader-profile): Allow a list of packages and collect everything directly in the profile, avoiding a separate collection directory. Renamed the profile from "bootloader-profile" to "efi-bootloader-profile". [bootloader-collection]: Rename to... [efi-bootloader-profile-hook]: ... this and remove unused modules. Do not create the now extraneous collection directory. (efi-bootloader-chain): Add PACKAGES and DISK-IMAGE-INSTALLER arguments. Remove handling of the collection directory, now only calling the given installer procedure. * gnu/bootloader/grub.scm (make-grub-efi-netboot-installer): New helper. (make-grub-configuration): New helper based on (grub-configuration-file). Add a GRUB argument, fix indentation, remove previous code retrieving GRUB from CONFIG. (grub-configuration-file): Make use of make-grub-configuration. (grub-efi-configuration-file): New procedure. (grub-cfg): New variable to replace "/boot/grub/grub.cfg". (install-grub-efi-netboot): Remove, splitting logic to... (make-grub-efi-netboot-installer): ... this new helper procedure, as well as to make-grub-efi-netboot, added below. (grub-bootloader): Adjust to use the GRUB-CFG. (grub-efi-bootloader): Likewise. Removed inheritance and declare all fields explicitly. (make-grub-efi-netboot-bootloader): New procedure. (grub-efi-netboot-bootloader): Use it. (grub-efi-netboot-removable-bootloader): New variable. * gnu/packages/bootloaders.scm (make-grub-efi-netboot): New procedure. Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com> Modified-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Diffstat (limited to 'gnu')
-rw-r--r--gnu/bootloader.scm105
-rw-r--r--gnu/bootloader/grub.scm220
-rw-r--r--gnu/packages/bootloaders.scm90
3 files changed, 281 insertions, 134 deletions
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index da65b9d5d5..2c36d8c6cf 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -322,26 +322,22 @@ instead~%")))
(force %bootloaders))
(leave (G_ "~a: no such bootloader~%") name)))
-(define (efi-bootloader-profile files bootloader-package hooks)
- "Creates a profile with BOOTLOADER-PACKAGE and a directory collection/ with
-links to additional FILES from the store. This collection is meant to be used
-by the bootloader installer.
+(define (efi-bootloader-profile packages files hooks)
+ "Creates a profile from the lists of PACKAGES and FILES from the store.
+This profile is meant to be used by the bootloader-installer.
FILES is a list of file or directory names from the store, which will be
-symlinked into the collection/ directory. If a directory name ends with '/',
-then the directory content instead of the directory itself will be symlinked
-into the collection/ directory.
+symlinked into the profile. If a directory name ends with '/', then the
+directory content instead of the directory itself will be symlinked into the
+profile.
-FILES may contain file like objects produced by functions like plain-file,
+FILES may contain file like objects produced by procedures like plain-file,
local-file, etc., or package contents produced with file-append.
HOOKS lists additional hook functions to modify the profile."
- (define (bootloader-collection manifest)
+ (define (efi-bootloader-profile-hook manifest)
(define build
- (with-imported-modules '((guix build utils)
- (ice-9 ftw)
- (srfi srfi-1)
- (srfi srfi-26))
+ (with-imported-modules '((guix build utils))
#~(begin
(use-modules ((guix build utils)
#:select (mkdir-p strip-store-file-name))
@@ -365,8 +361,7 @@ HOOKS lists additional hook functions to modify the profile."
(define (name-is-store-entry? name)
"Return #t if NAME is a direct store entry and nothing inside."
(not (string-index (strip-store-file-name name) #\/)))
- (let* ((collection (string-append #$output "/collection"))
- (files '#$files)
+ (let* ((files '#$files)
(directories (filter name-ends-with-/? files))
(names-from-directories
(append-map (lambda (directory)
@@ -374,11 +369,11 @@ HOOKS lists additional hook functions to modify the profile."
directories))
(names (append names-from-directories
(remove name-ends-with-/? files))))
- (mkdir-p collection)
+ (mkdir-p #$output)
(if (every file-exists? names)
(begin
(for-each (lambda (name)
- (symlink-to name collection
+ (symlink-to name #$output
(if (name-is-store-entry? name)
strip-store-file-name
basename)))
@@ -386,57 +381,63 @@ HOOKS lists additional hook functions to modify the profile."
#t)
#f)))))
- (gexp->derivation "bootloader-collection"
+ (gexp->derivation "efi-bootloader-profile"
build
#:local-build? #t
#:substitutable? #f
#:properties
`((type . profile-hook)
- (hook . bootloader-collection))))
+ (hook . efi-bootloader-profile-hook))))
- (profile (content (packages->manifest (list bootloader-package)))
- (name "bootloader-profile")
- (hooks (append (list bootloader-collection) hooks))
+ (profile (content (packages->manifest packages))
+ (name "efi-bootloader-profile")
+ (hooks (cons efi-bootloader-profile-hook hooks))
(locales? #f)
(allow-collisions? #f)
(relative-symlinks? #f)))
-(define* (efi-bootloader-chain files
- final-bootloader
+(define* (efi-bootloader-chain final-bootloader
#:key
+ (packages '())
+ (files '())
(hooks '())
- installer)
- "Define a bootloader chain with FINAL-BOOTLOADER as the final bootloader and
-certain directories and files from the store given in the list of FILES.
+ installer
+ disk-image-installer)
+ "Define a chain of bootloaders with the FINAL-BOOTLOADER, optional PACKAGES,
+and optional directories and files from the store given in the list of FILES.
-FILES may contain file like objects produced by functions like plain-file,
-local-file, etc., or package contents produced with file-append. They will be
-collected inside a directory collection/ inside a generated bootloader profile,
-which will be passed to the INSTALLER.
+The package of the FINAL-BOOTLOADER and all PACKAGES and FILES will be placed
+in an efi-bootloader-profile, which will be passed to the INSTALLER.
+
+FILES may contain file-like objects produced by procedures like plain-file,
+local-file, etc., or package contents produced with file-append.
If a directory name in FILES ends with '/', then the directory content instead
-of the directory itself will be symlinked into the collection/ directory.
+of the directory itself will be symlinked into the efi-bootloader-profile.
The procedures in the HOOKS list can be used to further modify the bootloader
profile. It is possible to pass a single function instead of a list.
-If the INSTALLER argument is used, then this function will be called to install
-the bootloader. Otherwise the installer of the FINAL-BOOTLOADER will be called."
- (let* ((final-installer (or installer
- (bootloader-installer final-bootloader)))
- (profile (efi-bootloader-profile files
- (bootloader-package final-bootloader)
- (if (list? hooks)
- hooks
- (list hooks)))))
- (bootloader
- (inherit final-bootloader)
- (package profile)
- (installer
- #~(lambda (bootloader target mount-point)
- (#$final-installer bootloader target mount-point)
- (copy-recursively
- (string-append bootloader "/collection")
- (string-append mount-point target)
- #:follow-symlinks? #t
- #:log (%make-void-port "w")))))))
+If the INSTALLER argument is used, then this gexp procedure will be called to
+install the efi-bootloader-profile. Otherwise the installer of the
+FINAL-BOOTLOADER will be called.
+
+If the DISK-IMAGE-INSTALLER is used, then this gexp procedure will be called
+to install the efi-bootloader-profile into a disk image. Otherwise the
+disk-image-installer of the FINAL-BOOTLOADER will be called."
+ (bootloader
+ (inherit final-bootloader)
+ (name "efi-bootloader-chain")
+ (package
+ (efi-bootloader-profile (cons (bootloader-package final-bootloader)
+ packages)
+ files
+ (if (list? hooks)
+ hooks
+ (list hooks))))
+ (installer
+ (or installer
+ (bootloader-installer final-bootloader)))
+ (disk-image-installer
+ (or disk-image-installer
+ (bootloader-disk-image-installer final-bootloader)))))
diff --git a/gnu/bootloader/grub.scm b/gnu/bootloader/grub.scm
index 7283257354..aab766fd6c 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -53,13 +53,14 @@
grub-theme-gfxmode
install-grub-efi-removable
- install-grub-efi-netboot
+ make-grub-efi-netboot-installer
grub-bootloader
grub-efi-bootloader
grub-efi-removable-bootloader
grub-efi32-bootloader
grub-efi-netboot-bootloader
+ grub-efi-netboot-removable-bootloader
grub-mkrescue-bootloader
grub-minimal-bootloader
@@ -353,7 +354,7 @@ code."
((or #f (? string?))
#~(format #f "search --file --set ~a" #$file)))))
-(define* (grub-configuration-file config entries
+(define* (make-grub-configuration grub config entries
#:key
(locale #f)
(system (%current-system))
@@ -453,9 +454,7 @@ menuentry ~s {
(define locale-config
(let* ((entry (first all-entries))
(device (menu-entry-device entry))
- (mount-point (menu-entry-device-mount-point entry))
- (bootloader (bootloader-configuration-bootloader config))
- (grub (bootloader-package bootloader)))
+ (mount-point (menu-entry-device-mount-point entry)))
#~(let ((locale #$(and locale
(locale-definition-source
(locale-name->definition locale))))
@@ -481,8 +480,6 @@ set lang=~a~%"
(define keyboard-layout-config
(let* ((layout (bootloader-configuration-keyboard-layout config))
- (grub (bootloader-package
- (bootloader-configuration-bootloader config)))
(keymap* (and layout
(keyboard-layout-file layout #:grub grub)))
(entry (first all-entries))
@@ -533,6 +530,16 @@ fi~%"))))
#:options '(#:local-build? #t
#:substitutable? #f)))
+(define (grub-configuration-file config . args)
+ (let* ((bootloader (bootloader-configuration-bootloader config))
+ (grub (bootloader-package bootloader)))
+ (apply make-grub-configuration grub config args)))
+
+(define (grub-efi-configuration-file . args)
+ (apply make-grub-configuration grub-efi args))
+
+(define grub-cfg "/boot/grub/grub.cfg")
+
;;;
@@ -674,42 +681,31 @@ fi~%"))))
((target-arm?) "--target=arm-efi"))
"--efi-directory" target-esp)))))
-(define (install-grub-efi-netboot subdir)
- "Define a grub-efi-netboot bootloader installer for installation in SUBDIR,
-which is usually efi/Guix or efi/boot."
- (let* ((system (string-split (nix-system->gnu-triplet
- (or (%current-target-system)
- (%current-system)))
- #\-))
- (arch (first system))
- (boot-efi-link (match system
- ;; These are the supportend systems and the names
- ;; defined by the UEFI standard for removable media.
- (("i686" _ ...) "/bootia32.efi")
- (("x86_64" _ ...) "/bootx64.efi")
- (("arm" _ ...) "/bootarm.efi")
- (("aarch64" _ ...) "/bootaa64.efi")
- (("riscv" _ ...) "/bootriscv32.efi")
- (("riscv64" _ ...) "/bootriscv64.efi")
- ;; Other systems are not supported, although defined.
- ;; (("riscv128" _ ...) "/bootriscv128.efi")
- ;; (("ia64" _ ...) "/bootia64.efi")
- ((_ ...) #f)))
- (core-efi (string-append
- ;; This is the arch dependent file name of GRUB, e.g.
- ;; i368-efi/core.efi or arm64-efi/core.efi.
- (match arch
- ("i686" "i386")
- ("aarch64" "arm64")
- ("riscv" "riscv32")
- (_ arch))
- "-efi/core.efi")))
- (with-imported-modules
- '((guix build union))
- #~(lambda (bootloader target mount-point)
- "Install the BOOTLOADER, which must be the package grub, as e.g.
-bootx64.efi or bootaa64.efi into SUBDIR, which is usually efi/Guix or efi/boot,
-below the directory TARGET for the system whose root is mounted at MOUNT-POINT.
+(define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
+ "Make a bootloader-installer for a grub-efi-netboot bootloader, which expects
+its files in SUBDIR and its configuration file in GRUB-CFG.
+
+As a grub-efi-netboot package is already pre-installed by 'grub-mknetdir', the
+installer basically copies all files from the bootloader-package (or profile)
+into the bootloader-target directory.
+
+Additionally for network booting over TFTP, two relative symlinks to the store
+and to the GRUB-CFG file are necessary. Due to this a TFTP root directory must
+not be located on a FAT file-system.
+
+If the bootloader-target does not support symlinks, then it is assumed to be a
+kind of EFI System Partition (ESP). In this case an intermediate configuration
+file is created with the help of GRUB-EFI to load the GRUB-CFG.
+
+The installer is usable for any efi-bootloader-chain, which prepares the
+bootloader-profile in a way ready for copying.
+
+The installer does not manipulate the system's 'UEFI Boot Manager'.
+
+The returned installer accepts the BOOTLOADER, TARGET and MOUNT-POINT
+arguments. Its job is to copy the BOOTLOADER, which must be a pre-installed
+grub-efi-netboot package with a SUBDIR like efi/boot or efi/Guix, below the
+directory TARGET for the system whose root is mounted at MOUNT-POINT.
MOUNT-POINT is the last argument in 'guix system init /etc/config.scm mnt/point'
or '/' for other 'guix system' commands.
@@ -719,17 +715,19 @@ bootloader-configuration in:
(operating-system
(bootloader (bootloader-configuration
- (targets '(\"/boot\"))
+ (targets '(\"/boot/efi\"))
…))
…)
TARGET is required to be an absolute directory name, usually mounted via NFS,
-and finally needs to be provided by a TFTP server as the TFTP root directory.
+and finally needs to be provided by a TFTP server as
+the TFTP root directory.
+Usually the installer will be used to prepare network booting over TFTP. Then
GRUB will load tftp://server/SUBDIR/grub.cfg and this file will instruct it to
load more files from the store like tftp://server/gnu/store/…-linux…/Image.
-To make this possible two symlinks will be created. The first symlink points
+To make this possible two symlinks are created. The first symlink points
relatively form MOUNT-POINT/TARGET/SUBDIR/grub.cfg to
MOUNT-POINT/boot/grub/grub.cfg, and the second symlink points relatively from
MOUNT-POINT/TARGET/%store-prefix to MOUNT-POINT/%store-prefix.
@@ -739,34 +737,80 @@ paths on the TFTP server side are unknown.
It is also important to note that both symlinks will point outside the TFTP root
directory and that the TARGET/%store-prefix symlink makes the whole store
-accessible via TFTP. Possibly the TFTP server must be configured
-to allow accesses outside its TFTP root directory. This may need to be
-considered for security aspects."
- (use-modules ((guix build union) #:select (symlink-relative)))
- (let* ((net-dir (string-append mount-point target "/"))
- (sub-dir (string-append net-dir #$subdir "/"))
- (store (string-append mount-point (%store-prefix)))
- (store-link (string-append net-dir (%store-prefix)))
- (grub-cfg (string-append mount-point "/boot/grub/grub.cfg"))
- (grub-cfg-link (string-append sub-dir (basename grub-cfg)))
- (boot-efi-link (string-append sub-dir #$boot-efi-link)))
- ;; Prepare the symlink to the store.
- (mkdir-p (dirname store-link))
- (false-if-exception (delete-file store-link))
- (symlink-relative store store-link)
- ;; Prepare the symlink to the grub.cfg, which points into the store.
- (mkdir-p (dirname grub-cfg-link))
- (false-if-exception (delete-file grub-cfg-link))
- (symlink-relative grub-cfg grub-cfg-link)
- ;; Install GRUB, which refers to the grub.cfg, with support for
- ;; encrypted partitions,
- (setenv "GRUB_ENABLE_CRYPTODISK" "y")
- (invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
- (string-append "--net-directory=" net-dir)
- (string-append "--subdir=" #$subdir))
- ;; Prepare the bootloader symlink, which points to core.efi of GRUB.
- (false-if-exception (delete-file boot-efi-link))
- (symlink #$core-efi boot-efi-link))))))
+accessible via TFTP. Possibly the TFTP server must be configured to allow
+accesses outside its TFTP root directory. This all may need to be considered
+for security aspects. It is advised to disable any TFTP write access!
+
+The installer can also be used to prepare booting from local storage, if the
+underlying file-system, like FAT on an EFI System Partition (ESP), does not
+support symlinks. In this case the MOUNT-POINT/TARGET/SUBDIR/grub.cfg will be
+created with the help of GRUB-EFI to load the /boot/grub/grub.cfg file. A
+symlink to the store is not needed in this case."
+ (with-imported-modules '((guix build union))
+ #~(lambda (bootloader target mount-point)
+ ;; In context of a disk image creation TARGET will be #f and an
+ ;; installer is expected to do necessary installations on MOUNT-POINT,
+ ;; which will become the root file system. If TARGET is #f, this
+ ;; installer has nothing to do, as it only cares about the EFI System
+ ;; Partition (ESP).
+ (when target
+ (use-modules ((guix build union) #:select (symlink-relative))
+ (ice-9 popen)
+ (ice-9 rdelim))
+ (let* ((mount-point/target (string-append mount-point target "/"))
+ ;; When installing Guix, it is common to mount TARGET below
+ ;; MOUNT-POINT rather than the root directory.
+ (bootloader-target (if (file-exists? mount-point/target)
+ mount-point/target
+ target))
+ (store (string-append mount-point (%store-prefix)))
+ (store-link (string-append bootloader-target (%store-prefix)))
+ (grub-cfg (string-append mount-point #$grub-cfg))
+ (grub-cfg-link (string-append bootloader-target
+ #$subdir "/"
+ (basename grub-cfg))))
+ ;; Copy the bootloader into the bootloader-target directory.
+ ;; Should we beforehand recursively delete any existing file?
+ (copy-recursively bootloader bootloader-target
+ #:follow-symlinks? #t
+ #:log (%make-void-port "w"))
+ ;; For TFTP we need to install additional relative symlinks.
+ ;; If we install on an EFI System Partition (ESP) or some other FAT
+ ;; file-system, then symlinks cannot be created and are not needed.
+ ;; Therefore we ignore exceptions when trying.
+ ;; Prepare the symlink to the grub.cfg.
+ (mkdir-p (dirname grub-cfg-link))
+ (false-if-exception (delete-file grub-cfg-link))
+ (if (unspecified?
+ (false-if-exception (symlink-relative grub-cfg grub-cfg-link)))
+ ;; Symlinks are supported.
+ (begin
+ ;; Prepare the symlink to the store.
+ (mkdir-p (dirname store-link))
+ (false-if-exception (delete-file store-link))
+ (symlink-relative store store-link))
+ ;; Creating symlinks does not seem to be supported. Probably
+ ;; an ESP is used. Add a script to search and load the actual
+ ;; grub.cfg.
+ (let* ((probe #$(file-append grub-efi "/sbin/grub-probe"))
+ (port (open-pipe* OPEN_READ probe "--target=fs_uuid"
+ grub-cfg))
+ (search-root
+ (match (read-line port)
+ ((? eof-object?)
+ ;; There is no UUID available. As a fallback search
+ ;; everywhere for the grub.cfg.
+ (string-append "search --file --set " #$grub-cfg))
+ (fs-uuid
+ ;; The UUID to load the grub.cfg from is known.
+ (string-append "search --fs-uuid --set " fs-uuid))))
+ (load-grub-cfg (string-append "configfile " #$grub-cfg)))
+ (close-pipe port)
+ (with-output-to-file grub-cfg-link
+ (lambda ()
+ (display (string-join (list search-root
+ load-grub-cfg)
+ "\n")))))))))))
@@ -784,7 +828,7 @@ considered for security aspects."
(package grub)
(installer install-grub)
(disk-image-installer install-grub-disk-image)
- (configuration-file "/boot/grub/grub.cfg")
+ (configuration-file grub-cfg)
(configuration-file-generator grub-configuration-file)))
(define grub-minimal-bootloader
@@ -794,11 +838,12 @@ considered for security aspects."
(define grub-efi-bootloader
(bootloader
- (inherit grub-bootloader)
+ (name 'grub-efi)
+ (package grub-efi)
(installer install-grub-efi)
(disk-image-installer #f)
- (name 'grub-efi)
- (package grub-efi)))
+ (configuration-file grub-cfg)
+ (configuration-file-generator grub-configuration-file)))
(define grub-efi-removable-bootloader
(bootloader
@@ -813,11 +858,22 @@ considered for security aspects."
(name 'grub-efi32)
(package grub-efi32)))
-(define grub-efi-netboot-bootloader
+(define (make-grub-efi-netboot-bootloader name subdir)
(bootloader
- (inherit grub-efi-bootloader)
- (name 'grub-efi-netboot-bootloader)
- (installer (install-grub-efi-netboot "efi/Guix"))))
+ (name name)
+ (package (make-grub-efi-netboot (symbol->string name) subdir))
+ (installer (make-grub-efi-netboot-installer grub-efi grub-cfg subdir))
+ (disk-image-installer #f)
+ (configuration-file grub-cfg)
+ (configuration-file-generator grub-efi-configuration-file)))
+
+(define grub-efi-netboot-bootloader
+ (make-grub-efi-netboot-bootloader 'grub-efi-netboot-bootloader
+ "efi/Guix"))
+
+(define grub-efi-netboot-removable-bootloader
+ (make-grub-efi-netboot-bootloader 'grub-efi-netboot-removable-bootloader
+ "efi/boot"))
(define grub-mkrescue-bootloader
(bootloader
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index d21e2a1a8b..7a9cff1712 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -16,6 +16,7 @@
;;; Copyright © 2021 Vincent Legoll <vincent.legoll@gmail.com>
;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
;;; Copyright © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -67,7 +68,9 @@
#:use-module (gnu packages virtualization)
#:use-module (gnu packages xorg)
#:use-module (guix build-system gnu)
+ #:use-module (guix build-system trivial)
#:use-module (guix download)
+ #:use-module (guix gexp)
#:use-module (guix git-download)
#:use-module ((guix licenses) #:prefix license:)
#:use-module (guix packages)
@@ -75,6 +78,7 @@
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (ice-9 optargs)
+ #:use-module (ice-9 match)
#:use-module (ice-9 regex))
(define unifont
@@ -390,6 +394,92 @@ menu to select one of the installed operating systems.")
(scandir input-dir))
#t)))))))))
+(define-public (make-grub-efi-netboot name subdir)
+ "Make a grub-efi-netboot package named NAME, which will be able to boot over
+network via TFTP by accessing its files in the SUBDIR of a TFTP root directory.
+This package is also able to boot from local storage devices.
+
+A bootloader-installer basically needs to copy the package content into the
+bootloader-target directory, which will usually be the TFTP root, as
+'grub-mknetdir' will be invoked already during the package creation.
+
+Alternatively the bootloader-target directory can be a mounted EFI System
+Partition (ESP), or a similar partition with a FAT file system, for booting
+from local storage devices.
+
+The name of the GRUB EFI binary will conform to the UEFI specification for
+removable media. Depending on the system it will be e.g. bootx64.efi or
+bootaa64.efi below SUBDIR.
+
+The SUBDIR argument needs to be set to \"efi/boot\" to create a package which
+conforms to the UEFI specification for removable media.
+
+The SUBDIR argument defaults to \"efi/Guix\", as it is also the case for
+'grub-efi-bootloader'."
+ (package
+ (name name)
+ (version (package-version grub-efi))
+ ;; Source is not needed, but it cannot be omitted.
+ (source #f)
+ (build-system trivial-build-system)
+ (arguments
+ (let* ((system (string-split (nix-system->gnu-triplet
+ (or (%current-target-system)
+ (%current-system)))
+ #\-))
+ (arch (first system))
+ (boot-efi
+ (match system
+ ;; These are the supportend systems and the names defined by
+ ;; the UEFI standard for removable media.
+ (("i686" _ ...) "/bootia32.efi")
+ (("x86_64" _ ...) "/bootx64.efi")
+ (("arm" _ ...) "/bootarm.efi")
+ (("aarch64" _ ...) "/bootaa64.efi")
+ (("riscv" _ ...) "/bootriscv32.efi")
+ (("riscv64" _ ...) "/bootriscv64.efi")
+ ;; Other systems are not supported, although defined.
+ ;; (("riscv128" _ ...) "/bootriscv128.efi")
+ ;; (("ia64" _ ...) "/bootia64.efi")
+ ((_ ...) #f)))
+ (core-efi (string-append
+ ;; This is the arch dependent file name of GRUB, e.g.
+ ;; i368-efi/core.efi or arm64-efi/core.efi.
+ (match arch
+ ("i686" "i386")
+ ("aarch64" "arm64")
+ ("riscv" "riscv32")
+ (_ arch))
+ "-efi/core.efi")))
+ (list
+ #:modules '((guix build utils))
+ #:builder
+ #~(begin
+ (use-modules (guix build utils))
+ (let* ((bootloader #$(this-package-input "grub-efi"))
+ (net-dir #$output)
+ (sub-dir (string-append net-dir "/" #$subdir "/"))
+ (boot-efi (string-append sub-dir #$boot-efi))
+ (core-efi (string-append sub-dir #$core-efi)))
+ ;; Install GRUB, which refers to the grub.cfg, with support for
+ ;; encrypted partitions,
+ (setenv "GRUB_ENABLE_CRYPTODISK" "y")
+ (invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
+ (string-append "--net-directory=" net-dir)
+ (string-append "--subdir=" #$subdir)
+ ;; These modules must be pre-loaded to allow booting
+ ;; from an ESP or a similar partition with a FAT
+ ;; file system.
+ (string-append "--modules=part_msdos part_gpt fat"))
+ ;; Move GRUB's core.efi to the removable media name.
+ (false-if-exception (delete-file boot-efi))
+ (rename-file core-efi boot-efi))))))
+ (inputs (list grub-efi))
+ (synopsis (package-synopsis grub-efi))
+ (description (package-description grub-efi))
+ (home-page (package-home-page grub-efi))
+ (license (package-license grub-efi))))
+
(define-public syslinux
(let ((commit "bb41e935cc83c6242de24d2271e067d76af3585c"))
(package