@@ -70,6 +70,7 @@
%bootloaders
lookup-bootloader-by-name
+ chain-efi-bootloader-installer
efi-bootloader-chain))
^L
@@ -311,6 +312,38 @@ HOOKS lists additional hook functions to modify the profile."
(allow-collisions? #f)
(relative-symlinks? #f)))
+(define (chain-efi-bootloader-installer final-installer)
+ "Define a new bootloader installer gexp, which will invoke FINAL-INSTALLER
+before it will copy the content from a collection/ directory of its 'bootloader'
+argument into the directory of its 'target' argument.
+
+This order is by intention to allow overwriting bootloader files like
+device-trees with own files provided in that collection/ directory.
+
+The generated bootloader function will usually be used in this way:
+
+ (efi-bootloader-chain … #:installer (chain-efi-bootloader-installer …))"
+
+ #~(lambda (bootloader target mount-point)
+ (#$final-installer bootloader target mount-point)
+ (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))
+ (collection (string-append bootloader "/collection")))
+ (if (and (eq? (and=> (stat collection #f) stat:type)
+ 'directory)
+ (eq? (and=> (stat bootloader-target #f) stat:type)
+ 'directory))
+ ;; Now copy the content of the collection directory.
+ (copy-recursively collection bootloader-target
+ #:follow-symlinks? #t
+ #:log (%make-void-port "w"))
+ (error "expecting two directories for bootloader installation"
+ collection bootloader-target)))))
+
(define* (efi-bootloader-chain files
final-bootloader
#:key
@@ -330,10 +363,16 @@ of the directory itself will be symlinked into the collection/ directory.
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."
+If the INSTALLER argument is used, then this procedure will be called to install
+the bootloader and handle the files inside the collection directory of the
+profile. Otherwise the generated procedure from
+
+ (chain-efi-bootloader-installer (bootloader-installer FINAL-BOOTLOADER))
+
+will be used to install the bootloader."
(let* ((final-installer (or installer
- (bootloader-installer final-bootloader)))
+ (chain-efi-bootloader-installer
+ (bootloader-installer final-bootloader))))
(profile (efi-bootloader-profile files
(bootloader-package final-bootloader)
(if (list? hooks)
@@ -342,11 +381,4 @@ the bootloader. Otherwise the installer of the FINAL-BOOTLOADER will be called.
(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")))))))
+ (installer final-installer))))