From ef75c33357980d81d982cfa468847e639ba18832 Mon Sep 17 00:00:00 2001 From: Hilton Chain Date: Tue, 3 Mar 2026 15:19:35 +0800 Subject: [PATCH] bootloader: Add limine-efi-removable-bootloader. * modules/rosenthal/bootloader/limine.scm: New file. * modules/rosenthal.scm (%public-modules): Add it. --- modules/rosenthal.scm | 1 + modules/rosenthal/bootloader/limine.scm | 128 ++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 modules/rosenthal/bootloader/limine.scm diff --git a/modules/rosenthal.scm b/modules/rosenthal.scm index 9e2c09b..ca79707 100644 --- a/modules/rosenthal.scm +++ b/modules/rosenthal.scm @@ -17,6 +17,7 @@ (gnu system privilege) (rosenthal bootloader grub) (rosenthal bootloader uki) + (rosenthal bootloader limine) (gnu services desktop) (gnu services guix) diff --git a/modules/rosenthal/bootloader/limine.scm b/modules/rosenthal/bootloader/limine.scm new file mode 100644 index 0000000..65a3da8 --- /dev/null +++ b/modules/rosenthal/bootloader/limine.scm @@ -0,0 +1,128 @@ +;;; SPDX-License-Identifier: GPL-3.0-or-later +;;; Copyright © 2026 Hilton Chain + +(define-module (rosenthal bootloader limine) + ;; Guile builtins + #:use-module (ice-9 format) + #:use-module (srfi srfi-1) + ;; Utilities + #:use-module (guix gexp) + #:use-module (guix modules) + #:use-module (guix utils) + ;; Guix System - bootloaders + #:use-module (gnu bootloader) + #:use-module (gnu bootloader grub) + #:use-module (rosenthal bootloader uki) + ;; Guix packages + #:use-module (rosenthal packages bootloaders) + #:export (limine-efi-removable-bootloader)) + +(define script-path "/boot/install-limine.scm") + +(define* (limine-configuration-file config entries + #:key (old-entries '()) #:allow-other-keys) + (define limine + (file-append + (bootloader-package (bootloader-configuration-bootloader config)) + (format #f "/share/limine/BOOT~a.EFI" + (cond + ((target-x86-32?) "IA32") + ((target-x86-64?) "X64") + ((target-aarch64?) "AA64") + ((target-riscv64?) "RISCV64"))))) + + (define menu-entries + (cons (first entries) + old-entries)) + + (define labels + (map-in-order menu-entry-label menu-entries)) + + (define ukify-args + (map-in-order menu-entry->ukify-args menu-entries)) + + (program-file "install-limine" + (with-imported-modules + (source-module-closure + '((guix build syscalls) + (guix build utils))) + #~(begin + (use-modules (ice-9 match) + (srfi srfi-1) + (guix build syscalls) + (guix build utils)) + (let* ((args (command-line)) + (directory (second args)) + (limine-directory (in-vicinity directory "EFI/BOOT")) + (guix-directory (in-vicinity directory "EFI/Guix"))) + (for-each mkdir-p (list limine-directory guix-directory)) + (install-file #$limine limine-directory) + (call-with-output-file (in-vicinity limine-directory "limine.conf.tmp") + (lambda (port) + (let* ((ukify #$(file-append ukify "/bin/ukify")) + (script-path (first args)) + (minbytes (* 2 (stat:size (stat script-path)))) + (current-label (first '#$labels)) + (current-args (first (list #$@ukify-args))) + (old-labels (cdr '#$labels)) + (old-args (cdr (list #$@ukify-args)))) + (format port "timeout: 5~%") + (with-directory-excursion guix-directory + (for-each delete-file (find-files "." "^OLD-[0-9]+\\.EFI$")) + (apply invoke ukify "build" "--output" "CURRENT.EFI" + current-args) + (format port " +/~a + protocol: efi + path: boot():/EFI/Guix/CURRENT.EFI~%" + current-label) + (unless (null? old-labels) + (format port "~%/GNU system, old configurations...~%")) + (false-if-exception + (let loop ((count 1) + (labels old-labels) + (args old-args)) + (let* ((image-name (format #f "OLD-~a.EFI" count))) + (unless (null? labels) + (with-exception-handler + (lambda _ + (false-if-exception (delete-file image-name)) + (exit)) + (lambda () + (when (< (free-disk-space ".") minbytes) + (raise-exception 'insuffcient-disk-space)) + (apply invoke/quiet + ukify "build" "--output" image-name + (first args)) + (format port "~ +//~a + protocol: efi + path: boot():/EFI/Guix/OLD-~a.EFI~%" + (first labels) + count))) + (loop (1+ count) + (cdr labels) + (cdr args)))))))))) + (rename-file (in-vicinity limine-directory "limine.conf.tmp") + (in-vicinity limine-directory "limine.conf"))))))) + +(define install-limine-efi + #~(lambda (bootloader target mount-point) + (invoke (string-append mount-point #$script-path) + (string-append mount-point target)))) + +;; Limine + UKI +;; NOTE: ‘configuration-file’ here is actually an activation script to be invoked by +;; ‘installer’. +;; XXX: Not expected by ‘reinstall-bootloader’ so rolling-back and switching +;; generation won't work. +(define limine-efi-removable-bootloader + (bootloader + ;; NOTE: Don't change the name. Generation switching code only knows + ;; bootloaders defined in (gnu bootloader grub). + (name 'grub-efi-removable-bootloader) + (package limine) + (installer install-limine-efi) + (disk-image-installer #f) + (configuration-file script-path) + (configuration-file-generator limine-configuration-file)))