gnu: bootloaders: Add uki-efi-bootloader.

* gnu/bootloader.scm (<bootloader-configuration>): New keypair field.
* gnu/bootloader/uki.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add bootloader/uki.scm.
* doc/guix.texi (Bootloader Configuration): Document UKI bootloader.

Change-Id: I2097da9f3dd35137b3419f6d0545de26d53cb6da
This commit is contained in:
Lilah Tascheter 2024-08-06 19:11:24 -05:00 committed by Ryan Schanzenbacher
parent 33894a8d17
commit 29de5f6410
Signed by: ryan77627
GPG key ID: 81B0E222A3E2308E
4 changed files with 133 additions and 2 deletions

View file

@ -42327,6 +42327,24 @@ It requires a @code{'disk} target providing either a @code{device},
@item @code{extlinux-gpt-bootloader} @item @code{extlinux-gpt-bootloader}
This is the same as above, but for systems with a GPT partition table. This is the same as above, but for systems with a GPT partition table.
@cindex Secure Boot, UEFI
@vindex uki-efi-bootloader
@item @code{uki-efi-bootloader}
Makes and installs UKI images for UEFI systems. Requires an @code{'esp}
target providing a @code{path} to the mount point of the EFI System
Partition. Not all system generations may be available with this
option, as UKI images contain the entire kernel and initramfs, and ESPs
tend to be small.
Full disk encryption with @code{uki-efi-bootloader} only requires a
single password entry with fast decryption, in contrast to GRUB2
requiring a second password entry with slow, LUKS1-only decryption.
This is the only bootloader to currently support UEFI Secure Boot, when
configured as below.
[THE CONFIGURATION BELOW]
@cindex ARM, bootloaders @cindex ARM, bootloaders
@cindex AArch64, bootloaders @cindex AArch64, bootloaders
@vindex u-boot-a20-olinuxino-lime-bootloader @vindex u-boot-a20-olinuxino-lime-bootloader
@ -42695,8 +42713,11 @@ The list of commands for loading Multiboot modules. For example:
@end lisp @end lisp
@item @code{chain-loader} (default: @code{#f}) @item @code{chain-loader} (default: @code{#f})
Varies slightly depending on bootloader. For @code{grub}, this is anything that Varies slightly depending on bootloader. For @code{grub}, this is
the @code{chainloader} directive can accept anything that the @code{chainloader} directive can accept
(@pxref{Chain-loading,,, grub, GNU GRUB manual}). For @code{uki-efi},
this is any efi binary to be installed alongside the system. The
following is an example of chainloading a different GNU/Linux system.
@lisp @lisp
(bootloader (bootloader

View file

@ -105,6 +105,7 @@ (define-module (gnu bootloader)
bootloader-configuration-default-entry bootloader-configuration-default-entry
bootloader-configuration-efi-removable? bootloader-configuration-efi-removable?
bootloader-configuration-32bit? bootloader-configuration-32bit?
bootloader-configuration-keypair
bootloader-configuration-timeout bootloader-configuration-timeout
bootloader-configuration-keyboard-layout bootloader-configuration-keyboard-layout
bootloader-configuration-theme bootloader-configuration-theme
@ -613,6 +614,8 @@ (define-record-type* <bootloader-configuration>
(default #f)) ;bool (default #f)) ;bool
(32bit? bootloader-configuration-32bit? (32bit? bootloader-configuration-32bit?
(default #f)) ;bool (default #f)) ;bool
(keypair bootloader-configuration-keypair
(default #f)) ;(cert . priv) pair
(timeout bootloader-configuration-timeout (timeout bootloader-configuration-timeout
(default 5)) ;seconds as integer (default 5)) ;seconds as integer
(keyboard-layout bootloader-configuration-keyboard-layout (keyboard-layout bootloader-configuration-keyboard-layout

106
gnu/bootloader/uki.scm Normal file
View file

@ -0,0 +1,106 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2024 Lilah Tascheter <lilah@lunabee.space>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu bootloader uki)
#:use-module (gnu bootloader)
#:use-module (gnu packages bootloaders)
#:use-module (gnu packages efi)
#:use-module (gnu packages linux)
#:use-module (gnu system boot)
#:use-module (guix gexp)
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (guix records)
#:use-module (ice-9 match)
#:export (uki-efi-bootloader))
;; TODO: Support 32bit/mixed-mode UEFI. May be relevant:
;; https://github.com/systemd/systemd/issues/17056
(define (menu-entry+bootcfg->builder entry bootcfg)
(match-menu-entry entry
(label linux linux-arguments initrd chain-loader)
(match-bootloader-configuration bootcfg (32bit? theme keypair)
(cond
;; Support chainloader in order to allow arbitrary signed EFI
;; binaries.
(chain-loader
(match keypair
((cert key)
#~(lambda (dest)
(invoke/quiet #+(sbsigntools "/bin/sbsign")
"--cert" #$cert "--key" #$key
"--output" dest #$chain-loader)
(invoke/quiet #+(sbsigntools "/bin/sbverify")
"--cert" #$(car keypair) dest)))
(#f #~(lambda (dest) (copy-file #$chain-loader dest)))))
(linux
(let* ((arch (efi-arch #:32? 32bit?))
(stub (file-append systemd-stub "/libexec/linux" arch
".efi.stub")))
#~(lambda (dest)
(invoke/quiet
#+(file-append ukify "/bin/ukify") "build"
"--output" dest "--linux" #$linux "--initrd" #$initrd
"--cmdline" (string-join (list #$@linux-arguments))
"--os-release" #$label "--stub" #$stub
"--efi-arch" #$arch
#$@(if theme #~("--splash" #$theme) '())
#$@(match keypair
((cert key)
#~("--secureboot-certificate" #$cert
"--secureboot-private-key" #$key))
(#f '()))))))
(else
(leave
(G_ "uki-efi-bootloader doesn't support multiboot")))))))
;; We cannot use Guix's build system to make UKI images for two reasons:
;; 1. signing is necessarily non-reproducable, especially since keys
;; should not be in the store, or else risk being publically accessible.
;; 2. Menu-entries may reference files which do not exist in the store.
(define* (install-uki #:key
bootloader-config
current-boot-alternative
old-boot-alternatives
#:allow-other-keys)
(define* (menu-entry->plan entry num #:optional (prefix "menu-entry"))
#~(cons* #$(menu-entry+bootcfg->builder entry bootloader-config)
#$(string-append prefix "-" (number->string num) ".efi")
#$(menu-entry-label entry)))
(define (boot-alternative->plan alt)
(menu-entry->plan (boot-alternative->menu-entry alt)
(boot-alternative-generation alt)
"generation"))
(install-efi
bootloader-config
(let ((entries
(bootloader-configuration-menu-entries bootloader-config)))
#~(list #$(boot-alternative->plan current-boot-alternative)
#$@(map menu-entry->plan entries (iota (length entries)))
#$@(map boot-alternative->plan old-boot-alternatives)))))
(define uki-efi-bootloader
(bootloader
(name 'uki-efi)
(default-targets (list (bootloader-target
(type 'vendir)
(offset 'esp)
(path "EFI/Guix"))))
(installer install-uki)))

View file

@ -94,6 +94,7 @@ GNU_SYSTEM_MODULES = \
%D%/bootloader/extlinux.scm \ %D%/bootloader/extlinux.scm \
%D%/bootloader/u-boot.scm \ %D%/bootloader/u-boot.scm \
%D%/bootloader/depthcharge.scm \ %D%/bootloader/depthcharge.scm \
%D%/bootloader/uki.scm \
%D%/ci.scm \ %D%/ci.scm \
%D%/compression.scm \ %D%/compression.scm \
%D%/home.scm \ %D%/home.scm \