diff options
| author | Stefan <stefan-guix@vodafonemail.de> | 2020-10-25 17:59:19 +0100 |
|---|---|---|
| committer | Danny Milosavljevic <dannym@scratchpost.org> | 2020-11-16 10:33:18 +0100 |
| commit | 74eeb11daee906cb012f10b6bb3afd254f9ea5c2 (patch) | |
| tree | b040ee55d155545fbf5ab843bf165bd9b07e0b66 /gnu | |
| parent | b720cf90e77f3143d7e46f2d9b25ada0355f13f9 (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')
| -rw-r--r-- | gnu/bootloader.scm | 125 |
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 | ||
| 237 | links to additional FILES from the store. This collection is meant to be used | ||
| 238 | by the bootloader installer. | ||
| 239 | |||
| 240 | FILES is a list of file or directory names from the store, which will be | ||
| 241 | symlinked into the collection/ directory. If a directory name ends with '/', | ||
| 242 | then the directory content instead of the directory itself will be symlinked | ||
| 243 | into the collection/ directory. | ||
| 244 | |||
| 245 | FILES may contain file like objects produced by functions like plain-file, | ||
| 246 | local-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 | ||
| 319 | certain directories and files from the store given in the list of FILES. | ||
| 320 | |||
| 321 | FILES may contain file like objects produced by functions like plain-file, | ||
| 322 | local-file, etc., or package contents produced with file-append. They will be | ||
| 323 | collected inside a directory collection/ inside a generated bootloader profile, | ||
| 324 | which will be passed to the INSTALLER. | ||
| 325 | |||
| 326 | If a directory name in FILES ends with '/', then the directory content instead | ||
| 327 | of the directory itself will be symlinked into the collection/ directory. | ||
| 328 | |||
| 329 | The PROFILE-HOOK function can be used to further modify the bootloader profile. | ||
| 330 | |||
| 331 | If the INSTALLER argument is used, then this function will be called to install | ||
| 332 | the bootloader. Otherwise the installer of the FINAL-BOOTLOADER will be called. | ||
| 333 | |||
| 334 | Independent of the INSTALLER argument, all files in the mentioned collection/ | ||
| 335 | directory of the bootloader profile will be copied into the bootloader target | ||
| 336 | directory 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"))))))) | ||
