summaryrefslogtreecommitdiff
path: root/gnu/bootloader.scm
diff options
context:
space:
mode:
authorStefan <stefan-guix@vodafonemail.de>2020-10-25 17:59:19 +0100
committerDanny Milosavljevic <dannym@scratchpost.org>2020-11-16 10:33:18 +0100
commit74eeb11daee906cb012f10b6bb3afd254f9ea5c2 (patch)
treeb040ee55d155545fbf5ab843bf165bd9b07e0b66 /gnu/bootloader.scm
parentb720cf90e77f3143d7e46f2d9b25ada0355f13f9 (diff)
gnu: bootloader: Support chain loading to an EFI bootloader.
* gnu/bootloader.scm (efi-bootloader-profile): New function. (efi-bootloader-chain): New function. Signed-off-by: Danny Milosavljevic <dannym@scratchpost.org>
Diffstat (limited to 'gnu/bootloader.scm')
-rw-r--r--gnu/bootloader.scm125
1 files changed, 124 insertions, 1 deletions
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index 2eebb8e9d9c..59f8f527b6e 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -22,6 +22,8 @@
22 22
23(define-module (gnu bootloader) 23(define-module (gnu bootloader)
24 #:use-module (guix discovery) 24 #:use-module (guix discovery)
25 #:use-module (guix gexp)
26 #:use-module (guix profiles)
25 #:use-module (guix records) 27 #:use-module (guix records)
26 #:use-module (guix ui) 28 #:use-module (guix ui)
27 #:use-module (srfi srfi-1) 29 #:use-module (srfi srfi-1)
@@ -66,7 +68,9 @@
66 bootloader-configuration-additional-configuration 68 bootloader-configuration-additional-configuration
67 69
68 %bootloaders 70 %bootloaders
69 lookup-bootloader-by-name)) 71 lookup-bootloader-by-name
72
73 efi-bootloader-chain))
70 74
71 75
72;;; 76;;;
@@ -227,3 +231,122 @@ record."
227 (eq? name (bootloader-name bootloader))) 231 (eq? name (bootloader-name bootloader)))
228 (force %bootloaders)) 232 (force %bootloaders))
229 (leave (G_ "~a: no such bootloader~%") name))) 233 (leave (G_ "~a: no such bootloader~%") name)))
234
235(define (efi-bootloader-profile files bootloader-package hook)
236 "Creates a profile with BOOTLOADER-PACKAGE and a directory collection/ with
237links to additional FILES from the store. This collection is meant to be used
238by the bootloader installer.
239
240FILES is a list of file or directory names from the store, which will be
241symlinked into the collection/ directory. If a directory name ends with '/',
242then the directory content instead of the directory itself will be symlinked
243into the collection/ directory.
244
245FILES may contain file like objects produced by functions like plain-file,
246local-file, etc., or package contents produced with file-append."
247 (define (bootloader-collection manifest)
248 (define build
249 (with-imported-modules '((guix build utils)
250 (ice-9 ftw)
251 (srfi srfi-1)
252 (srfi srfi-26))
253 #~(begin
254 (use-modules ((guix build utils)
255 #:select (mkdir-p strip-store-file-name))
256 ((ice-9 ftw)
257 #:select (scandir))
258 ((srfi srfi-1)
259 #:select (append-map every remove))
260 ((srfi srfi-26)
261 #:select (cut)))
262 (define (symlink-to file directory transform)
263 "Creates a symlink to FILE named (TRANSFORM FILE) in DIRECTORY."
264 (symlink file (string-append directory "/" (transform file))))
265 (define (directory-content directory)
266 "Creates a list of absolute path names inside DIRECTORY."
267 (map (lambda (name)
268 (string-append directory name))
269 (or (scandir directory (lambda (name)
270 (not (member name '("." "..")))))
271 '())))
272 (define name-ends-with-/? (cut string-suffix? "/" <>))
273 (define (name-is-store-entry? name)
274 "Return #t if NAME is a direct store entry and nothing inside."
275 (not (string-index (strip-store-file-name name) #\/)))
276 (let* ((collection (string-append #$output "/collection"))
277 (files '#$files)
278 (directories (filter name-ends-with-/? files))
279 (names-from-directories
280 (append-map (lambda (directory)
281 (directory-content directory))
282 directories))
283 (names (append names-from-directories
284 (remove name-ends-with-/? files))))
285 (mkdir-p collection)
286 (if (every file-exists? names)
287 (begin
288 (for-each (lambda (name)
289 (symlink-to name collection
290 (if (name-is-store-entry? name)
291 strip-store-file-name
292 basename)))
293 names)
294 #t)
295 #f)))))
296
297 (gexp->derivation "bootloader-collection"
298 build
299 #:local-build? #t
300 #:substitutable? #f
301 #:properties
302 `((type . profile-hook)
303 (hook . bootloader-collection))))
304
305 (profile (content (packages->manifest (list bootloader-package)))
306 (name "efi-bootloader-profile")
307 (hooks (append (list bootloader-collection)
308 (or hook '())))
309 (locales? #f)
310 (allow-collisions? #f)
311 (relative-symlinks? #f)))
312
313(define* (efi-bootloader-chain files
314 final-bootloader
315 #:key
316 hook
317 installer)
318 "Define a bootloader chain with FINAL-BOOTLOADER as the final bootloader and
319certain directories and files from the store given in the list of FILES.
320
321FILES may contain file like objects produced by functions like plain-file,
322local-file, etc., or package contents produced with file-append. They will be
323collected inside a directory collection/ inside a generated bootloader profile,
324which will be passed to the INSTALLER.
325
326If a directory name in FILES ends with '/', then the directory content instead
327of the directory itself will be symlinked into the collection/ directory.
328
329The PROFILE-HOOK function can be used to further modify the bootloader profile.
330
331If the INSTALLER argument is used, then this function will be called to install
332the bootloader. Otherwise the installer of the FINAL-BOOTLOADER will be called.
333
334Independent of the INSTALLER argument, all files in the mentioned collection/
335directory of the bootloader profile will be copied into the bootloader target
336directory after the actual bootloader installer has been called."
337 (let* ((final-installer (or installer
338 (bootloader-installer final-bootloader)))
339 (profile (efi-bootloader-profile files
340 (bootloader-package final-bootloader)
341 hook)))
342 (bootloader
343 (inherit final-bootloader)
344 (package profile)
345 (installer
346 #~(lambda (bootloader target mount-point)
347 (#$final-installer bootloader target mount-point)
348 (copy-recursively
349 (string-append bootloader "/collection")
350 (string-append mount-point target)
351 #:follow-symlinks? #t
352 #:log (%make-void-port "w")))))))