GNU bug report logs - #79248
[PATCH] 006-rebootload: Propose GCD006 "Rewrite Bootloader Subsystem"

Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.

Package: guix-patches; Reported by: Lilah Tascheter <lilah@HIDDEN>; Keywords: patch; dated Fri, 15 Aug 2025 20:06:01 UTC; Maintainer for guix-patches is guix-patches@HIDDEN.

Message received at 79248 <at> debbugs.gnu.org:


Received: (at 79248) by debbugs.gnu.org; 15 Aug 2025 20:14:06 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Aug 15 16:14:06 2025
Received: from localhost ([127.0.0.1]:39770 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1un0oP-0004MN-9J
	for submit <at> debbugs.gnu.org; Fri, 15 Aug 2025 16:14:06 -0400
Received: from sendmail.purelymail.com ([34.202.193.197]:32908)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <lilah@HIDDEN>)
 id 1un0oM-0004Lk-Gj
 for 79248 <at> debbugs.gnu.org; Fri, 15 Aug 2025 16:14:03 -0400
DKIM-Signature: a=rsa-sha256;
 b=UzJPNCUSLYpGVVfk7Z7aBrHmMK3K5wF+1Jv+FpB6jsYhasZuPjlvM9IsHti9sTPAOJJL4rSljcJijyctZUYu41V5Xk0SJULztxrd7nKKDG/xE1X57uPzvUWiicdKabWm1HaWc9kfoywe2f39+z8Q8NPJW1tFXihJIyWTHhInsFJDRuXXjXHYxbIrzAKkCKwU/572WBPTBtNsAfAlaNiK9/saySEU5lC7jmXTtvxLpWJ2Y6UCFILZJiKZBk0fz5qk/fCwmnY3tEJGH+o6ICGPcSS4lo+rrJsfl6a9ymz45Fa4Eg8u5Z8abLiv7tDyKA+7AFXPdrLcAjhTjeKTkXGVRg==;
 s=purelymail2; d=lunabee.space; v=1;
 bh=xxReMUpfFZcxYrV3zo0+UqQHWfhRGxtKS3JOsR+ea94=;
 h=Received:Subject:From:To:Date; 
DKIM-Signature: a=rsa-sha256;
 b=hCtSS0dRScbia+qI6ZR8orT0XAMODxjjj2DvztDjiwbf6xpixX4/JkbbCFLUz8hK1WQ0n6qfT6mrUbNekZg6dOE1SbTXPD+eBrjoheGVfeKQN68QxGneMSGJnob/JvnCXtk0W/jrKg6KyibRBaG9q2GvpM76GzKzG4tjVKp6uGF3ShKJKqVZaKB1dI97pGE2wIBXgq/onNnUw38bEYS99UGyN3mjdjJCjkaia8plnSBGvxgV9TJ70mgGkxiqmh4redBTxV7B8i5Zb31WYO8+YW472zfFHKrDCCVTmT1O9sqRZyuALBeafihlBDnTbrUc1vpAonht88or6PsCL1E2kw==;
 s=purelymail2; d=purelymail.com; v=1;
 bh=xxReMUpfFZcxYrV3zo0+UqQHWfhRGxtKS3JOsR+ea94=;
 h=Feedback-ID:Received:Subject:From:To:Date; 
Feedback-ID: 8937:2070:null:purelymail
X-Pm-Original-To: 79248 <at> debbugs.gnu.org
Received: by smtp.purelymail.com (Purelymail SMTP) with ESMTPSA id 839358000; 
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 15 Aug 2025 20:13:50 +0000 (UTC)
Message-ID: <912fd9f161309a065423b062997a9226b92e60fb.camel@HIDDEN>
Subject: GCD006: Rewrite bootloader subsystem
From: Lilah Tascheter <lilah@HIDDEN>
To: guix-devel@HIDDEN, 79248 <at> debbugs.gnu.org
Date: Fri, 15 Aug 2025 15:13:49 -0500
Organization: Dissociation for Heresiographal Computation
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
User-Agent: Evolution 3.54.3 
MIME-Version: 1.0
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79248
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

hey everyone!

about a year ago I proposed a patch series rewriting bootloader handling
in Guix. seeing the new GCD process, I figured it was perfect for
gathering discussion and consent for the rewrite. so, I rewrote
the=C2=A0rewrite, and I'm proposing it here!

this is a draft; if anyone has suggestions at this stage, please let me
know! I'll need at least one sponsor, as well, for this to move to the
discussion period.

lilah



title: Bootloader Subsystem Rewrite
id: 006
status: draft
discussion: https://issues.guix.gnu.org/79248
authors: Lilah Tascheter
sponsors: <Sponsor Name>
date: <date when the discussion period starts>
SPDX-License-Identifier: CC-BY-SA-4.0 OR GFDL-1.3-no-invariants-or-later
---

# Summary

Guix's bootloader handling was originally designed solely for GRUB but, wit=
h
greater adoption and widened system compatibility, this has proved insuffic=
ient.
Unfortunately, core aspects of bootloader handling have remained unchanged,
resulting in a system hard to fit new bootloaders into and confusing for
end-users to configure.

We propose an in-depth rewrite in order to create a more flexible and easie=
r to
understand interface for both end users and bootloader packagers.

Prior work has been done as patchsets #69343, #73202, and #72457 on Mumi. T=
his
GCD is a new proposal improving upon these patches.

# Motivation

We identify three main ways the current bootloader handling proves insuffic=
ient:
1. Structural assumptions of GRUB exist in both user-facing bootloader
   configuration options as well as the packager-facing bootloader interfac=
e.
2. Multiple special cases exist in bootloader packaging and installation, m=
aking
   it incredibly easy to package bootloaders that either install onto the h=
ost
   during disk-image building or fail during system rollback.
3. Bootloader packaging is ill-documented and relies on a confusing interfa=
ce,
   which is especially bad for such a sensitive part of system configuratio=
n.

Take, first, the user-facing side of things. 11/14 fields of the
`<bootloader-configuration>` record are only used in GRUB, with multiple ha=
ving
no imaginable use for non-GRUB bootloaders in the first place. Theoreticall=
y,
new bootloaders could add fields to the record if they need their own
configuration, but any external channels would not be able to do even that.

Disk image handling is not well-specified, especially when attempting to cr=
eate
a disk image with a custom bootloader. Examples provide `/dev/vda1`, so a u=
ser
would assume that Guix looks for that magic string, but instead bootloader
handling uses a special install procedure. Notably, an unused target must b=
e
specified anyway.

The `<menu-entry>` record is, also, made solely with GRUB in mind, even tho=
ugh
dual-booting is theoretically something that should be supported by bootloa=
ders
in general. Fields are documented with semantics based solely on how GRUB
interprets them.

More notably, the current state of affairs hampers bootloader packaging
significantly. The `<bootloader>` record contains the following fields:
* `bootloader-name`: containing a symbol supposed to uniquely identify a
  bootloader package, for use in rollbacks. Notably, u-boot bootloaders ign=
ore
  this requirement, to potentially disasterous consequences. It doesn't hel=
p
  that the only time one would notice problems with this (for example, a
  channel's bootloader defined outside gnu/bootloader, a bootloader defined=
 as a
  procedure, or reused `bootloader-name`s) is when you already need to roll
  back to a different bootloader.
* `bootloader-package`: This is only useful for switching which GRUB packag=
e is
  used for GRUB bootloaders.
* `bootloader-configuration-file`: This is the sole mechanism through which
  rollbacks function. Few bootloaders utilize config file semantics, making
  bootloader packaging a pain of trying to coerce semantics to fit in this =
rigid
  box. This, also, prevents use of non-deterministic config files, such as =
those
  containing signed data for secure boot systems.
* `bootloader-installer` and `bootloader-disk-image-installer`: `installer`=
 is
  meant to be used on mounted filesystems. `disk-image-installer` is meant =
to be
  used on devices. `disk-image-installer` is used for disk image building o=
r as
  a fallback. Some bootloaders (even GRUB!) need access to both a filesyste=
m and
  disk, and the two separate code paths mean development can lead to poorly
  tested bootloading code. The arguments to both procedures are, also, poor=
ly
  documented (and weird choices in general; root-index is purely used by GR=
UB).

# Detailed Design

## Bootloader Definition
First, we go over the general architecture of bootloader packaging. Each
bootloader will have two things associated to it: a `<bootloader>` record
denoting what functions it provides, and a configuration record unique to e=
ach
type of bootloader. The `<bootloader>` record defines functions taking in t=
he
configuration record, as a way for the bootloader system to extract the
information it needs from each bootloader's config.

Going into specifics, the `<bootloader>` record will be redefined as such:
* `bootloader-predicate`: A predicate denoting whether the configuration is=
 of
  the right type, used to verify whether users provided the correct record.
* `bootloader-installers`: A list of `<bootloader-installer>` records.

`<bootloader-installer>` is a new record intended to split up individual
target installation methods. This is necessary as disk images do not have a=
ll
possible targets accessible at once (as the disk is generated strictly afte=
r
partitions). The record is defined as such:
* `<bootloader-installer-tag>`: An arbitrary symbol used by the bootloader =
to
  identify this installer and its targets. A `<bootloader>` may not have tw=
o
  `<bootloader-installers>` with the same tag.
* `<bootloader-installer-type>`: A symbol indicating the sort of values all=
owed
  as targets. Allowed the following values:
  - `'file`: Only strings allowed, interpreted as paths.
  - `'block`: Strings (interpreted as block devices), `file-system-label`s,=
 and
    `uuid`s allowed. `uuid`s are interpreted as filesystem UUIDs, partition
    UUIDs, or partition table UUIDs, attempted in that order.
* `<bootloader-installer-targets>`: A function from the bootloader's
  configuration to a list of targets specified by the user. Typically this =
is
  just a configuration record field accessor.
* `<bootloader-installer-installer>`: A function from the bootloader's
  configuration, an alist of generation numbers to `<boot-parameters>`, the
  current generation number, and the boot-time target map (see below), to a=
 gexp
  containing an installer procedure as specified below.

Installers are gexps containing a procedure taking keyword arguments. The
procedure is called once for each target in the `<bootloader-installer>`, a=
nd
provided keyword arguments depending on the `<bootloader-installer-type>`. =
Each
keyword argument has a side, either boot-side or install-side. Install-side=
 data
is only valid during installation of the bootloader, and should not be used
during bootup. This data is generated from system state at install-time.
Boot-side data is usable during bootup, and generated from a given system's
`<file-system>` records. However, if a `'block` type installer is provided =
a
path to a block device, boot-time data must be generated at install-time. F=
or
this reason, usage of a path `'block` is not recommended. Keyword arguments=
 are
as follows:
* `#:mount` (`'file`, install-time): Absolute path to the mount point of th=
e
  filesystem the file is stored on.
* `#:path` (`'file`, install-time): Absolute path to the specified file.
* `#:device` (`'block`, install-time): Device file for the block device.
* `#:offset` (`'file`, boot-time): Filesystem-relative path. Includes the b=
trfs
  subvolume prefix when applicable, so `#:path` may not always be
  `string-append`'ed `#:mount` and `#:offset`.
* `#:label` (all, boot-time): Filesystem label.
* `#:uuid` (all, boot-time): Filesystem uuid, unless `'block` and a partiti=
on
  UUID or partition table UUID is provided.

In the future, more installer types and keyword arguments may be provided
fully backwards-compatibly.

The boot-time target map provieded to `bootloader-installers` is an alist o=
f
tags to lists of boot-time data, one for each target. Boot-time data is
exactly the boot-time keyword arguments provided to installer gexp procedur=
es,
but are provided here for certain installers to know about others (for exam=
ple,
the GRUB early loader installed to a disk knowing about the full GRUB
installation's partition and location).

## User Configuration
Users will specify the `<bootloader>` they wish to use directly in the
`operating-system-bootloader` field, which will be changed to allow `#f` (f=
or no
bootloaders, as in virtualized images with direct linux booting).
`<operating-system>` will also receive a new
`operating-system-bootloader-configuration` field. This field will accept a
configuration used by the `operating-system-bootloader`, verified by
`bootloader-predicate`.

All further bootloader configuration, including targets and additional boot
options, will be provided in the `operating-system-bootloader-configuration=
`.

The current `<menu-entry>` and `<bootloader-configuration>` records will be
re-adapted into grub-specific configuration.

## Rollbacks
As the entire bootloader install process exists in gexps, each generation w=
ill
simply save its combined bootloader install script as a GC root to be calle=
d on
rollback, the exact way it's called on install. This eliminates the need fo=
r
bootloader module search and bootloader configuration guessing (as is curre=
ntly
used), as well as making bootloader rollbacks more reliable.

Due to this, the following `<boot-parameters>` fields may be removed:
`boot-parameters-root-device`, `boot-parameter-bootloader-name`, and
`boot-parameter-menu-entries`. The record shall be updated to version 2 to
match.

## Disk Images
While disk images will work automatically with the above system through the
keyword argument discovery mechanisms, one instance of special-casing is
unfortunately required. Any `<bootloader-installer>` with the tag `'disk`
will, instead of using targets from `bootloader-installer-targets`, provide
a single target, generated from the resulting disk image file.

All other handling will be done invisibly to both end-users and bootloader
packagers, due to the above defined semantics of target conversion into key=
word
arguments.

## Cascading Changes
These changes will necessitate some edits to specific bootloaders and
supporting code. The current GRUB bootloader installer calls `grub-install`=
,
which guesses a lot of information about the system it's currently run on. =
This
approach, of course, does not work for disk images, and so manual image cre=
ation
is used there. We propose unifying the two approaches, manually creating di=
sk
images with the information given to us by the new targeting system.

Furthermore, a new utility procedure will be created to facilitate EFI
bootloaders, handling copying to the ESP, setting EFI boot options,
configuring removability, and ensuring sufficient storage space in the ESP.

## Documentation
A page will be added to the manual under the `Programming Interface` sectio=
n
describing the new bootloader interfaces. This page will note the default
modules provided to installer gexps and the special-casing of the `'disk` t=
ag.

The `Bootloader Configuration` page will be updated to act as a unified
documentation of the peculiarities of each bootloader and how to use it. Ma=
nual
pages pertaining to bootloader installation will be updated to document the=
 new
user configuration format, and a blog post will be made to ease the transit=
ion.

## Bootloading Team
Lastly, a bootloading team will be created as a point of contact and
implementation group for the above changes. This team would develop the pro=
posed
changes in a public fork of Guix in order to facilitate user testing across=
 the
wide range of supported hardware. Merging with mainline will be done once p=
atch
review and sufficiently diverse testing as to minimize user impact has been
completed.

## Examples
```scheme
(define-record-type* <simple-configuration>
  simple-configuration make-simple-configuration simple-configuration?
  (copy-to simple-configuration-copy-to))
(define (simple-bootloader-installer conf params current targets)
  #~(lambda* (#:key path #:allow-other-keys)
      (copy-file #$(file-append simple-bootloader-pkg "/share/config") path=
)))
(define simple-bootloader
  (bootloader
    (predicate simple-configuration?)
    (installers (bootloader-installer
                  (tag 'copy-to)
                  (type 'file)
                  (targets (compose list simple-configuration-copy-to))
                  (installer simple-bootloader-installer)))))
```
```scheme
(operating-system
  (bootloader simple-bootloader)
  (bootloader-configuration (simple-configuration (copy-to "/boot/config"))=
))
```

# Migration
Even though bootloader management may be considered part of the Guix API
surface, we do not attempt to provide a clean migration path. Thus, upon me=
rge
immediate incompatibilities will occur for all channels packaging bootloade=
rs.
This, thankfully, proves to be a very small number.

For operating system configuration, however, the existing
`<bootloader-configuration>` and `<menu-entry>` structures shall be depreca=
ted.
`<operating-system>`s will go through a pass converting such structures int=
o the
new format, through a `bootloader-migration` field in `<bootloader>` allowe=
d to
be `#f`. This field may contain a function from `<bootloader-configuration>=
` to
the bootloader's configuration. The fixup procedure will operate as follows=
,
taking
```scheme
(operating-system
  (bootloader (bootloader-configuration
                (bootloader test-bootloader))))
```
to
```scheme
(operating-system
  (bootloader test-bootloader)
  (bootloader-configuration ((bootloader-migrate test-bootloader)
                             (bootloader-configuration
                               (bootloader test-bootloader)))))
```

Target handling would require little to no special-casing in such migration
functions.

After a year, this deprecation will expire, and the fixup code, old records=
, and
`bootloader-migration` field may be removed. This way, existing
`<operating-system>`s may be used as-is for the period necessitated by the
Deprecation Policy.

## Study of Affected Channels
We have taken an informal study of Guix channels as of 2025-08-13 in order =
to
estimate the impact of breaking API changes. 98 Guix channels were located
from the following roots:
* [whereiseverything channel toys](https://toys.whereis.social/channels)
* [Github awesome-guix](https://github.com/franzos/awesome-guix)
* [crafted-guix](https://codeberg.org/SystemCrafters/crafted-guix), an
  additional channel found through internet search.
* [gooy-guix](https://git.squircle.space/gooy-guix.git), mentioned to me by=
 Ada
  Avery and posted on guix-devel.

Of those 98, we were able to locate exactly 4 which add bootloaders, none o=
f
which managed to fully support Guix's existing bootloader handling:
* [rosenthal](https://codeberg.org/hako/Rosenthal), which just packages GRU=
B
  with an overridden package that supports LUKS2. Does not support rollback=
s.
* [gooy-guix](https://git.squircle.space/gooy-guix.git), packaging a
  systemd-boot EFI bootloader. It is impossible for this bootloader to supp=
ort
  disk images in the current system.
* [waggle](https://git.lunabee.space/waggle/files.html), my channel, which
  adds p-boot for the Pinephone and a UKI bootloader, whose roundabout
  implementation necessitated by the current system prompted me to begin th=
is
  rewrite in the first place. Does not support rollbacks, and I didn't real=
ize
  until after I needed one in the first place. It is impossible for these t=
o
  support disk images in the current system.
* [sakura](https://g.freya.cat/freya/sakura). The bootloader added is entir=
ely
  copied from my channel and the channel's owner has switched to Nix anyway=
.

We thus conclude change to be necessary, and the potential impact of breaki=
ng
changes minimal.

# Cost of Reverting
While these changes will drastically affect internals, the vast majority of
users should see a smooth transition. Similar methods to the above mentione=
d
migration path may be employed if this changeset needs to be reverted, at t=
he
cost of another breaking change to bootloader-packaging channels.

However, another roadblock in reverting could take place in the removal of =
boot
parameter options. Thus, we propose postponing the boot parameter changes u=
ntil
after reverting is precluded as a possibility. Only then will the version b=
e
incremented and unnecessary fields dropped.

# Drawbacks and Open Issues
As these are bootloader changes, patches will need to be tested carefully i=
n
order to ensure no devices get bricked. And, even then, there could still b=
e a
risk due to how sensitiive bootloader installation and handling can be. Thi=
s is
the main obstacle for implementation. It may be useful, then, to have a mor=
e
concrete procedure set in place to ensure proper testing after patch
development.

The deprecation process is not ideal, especially with the removal of the
`bootloader-migrate` field resulting in two breaking changes to
bootloader-packaging channels.

The special-casing of the `'disk` tag is also not ideal. We could not think=
 of
any better method to provide such information.





Information forwarded to guix-patches@HIDDEN:
bug#79248; Package guix-patches. Full text available.

Message received at submit <at> debbugs.gnu.org:


Received: (at submit) by debbugs.gnu.org; 15 Aug 2025 20:05:42 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Aug 15 16:05:42 2025
Received: from localhost ([127.0.0.1]:39749 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1un0gD-0003zE-4l
	for submit <at> debbugs.gnu.org; Fri, 15 Aug 2025 16:05:42 -0400
Received: from lists.gnu.org ([2001:470:142::17]:53242)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <lilah@HIDDEN>)
 id 1un0g8-0003ys-1S
 for submit <at> debbugs.gnu.org; Fri, 15 Aug 2025 16:05:35 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <lilah@HIDDEN>)
 id 1un0g2-0007wB-CZ
 for guix-patches@HIDDEN; Fri, 15 Aug 2025 16:05:26 -0400
Received: from sendmail.purelymail.com ([34.202.193.197])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <lilah@HIDDEN>)
 id 1un0fy-0006L7-Qy
 for guix-patches@HIDDEN; Fri, 15 Aug 2025 16:05:26 -0400
Authentication-Results: purelymail.com; auth=pass
DKIM-Signature: a=rsa-sha256;
 b=CUoRc2qrGV9VGo6ntSyHNG6NYbVwYb2IYfyO3+UHl9AFBW0D0r1SNWuwUo7Z/2OkmtofqV6oPlKJ4UyZLLkrNtVrlTNyul14wJrEjuw8xD5Wa6mBC6wFty14fQ9lOHB8kV5KbvYIrPdMHTLnWf3Y/RlEOkLBFWKshPmH8Y9wSWxqoNMvAr4vCZJaPeS9WEaUMMZCE45LJVevForqr/d6CfkIluull1yo8SyFJnRjPV5l9rTBmAQe0GeejdzPD+lcoxqD/tse5KmvHP2Q6D4BS2d73UVz4zCEToel6Y2nKnUmlLuL5/Qkug8E8XqOXxF+RngTpES22DaumVm1VxMxrQ==;
 s=purelymail2; d=lunabee.space; v=1;
 bh=FpWz5TlxNgc4lelpX0ztOvDJujhbHGTb19DnYjhhzGU=;
 h=Received:From:To:Subject:Date; 
DKIM-Signature: a=rsa-sha256;
 b=JYWiZJ9EowXVeUn9EpVFYnHdvHRQoD3G986rpzcntjbIhavjB8gWIe4YgcsQMGttCYcvE88s5GFPrGvqc+BD3I2sTh4M160P7jPBzpZseWZGvSilXKB+pZT6XH6agMwXz5bpZYGqXXYmfXDXyx5l7rMU+gTCOUt64TsbQ6Tt2BUoRbUlx6KwU1Lb0qp9tYMzvfgbSJRqJh2Duv1idvUOn6UBur4Wl9+5dbmHdFPZhmvFqozcm12Gr7qHfqpLsiQpSFoDKo18C4gfyBf8qWpMqWpB76DmJBBqmmiotr/4bLEe9/r+bcKsSgebygvIxpunTuY7wxEYp0nQF9DWvI4iOw==;
 s=purelymail2; d=purelymail.com; v=1;
 bh=FpWz5TlxNgc4lelpX0ztOvDJujhbHGTb19DnYjhhzGU=;
 h=Feedback-ID:Received:From:To:Subject:Date; 
Feedback-ID: 8937:2070:null:purelymail
X-Pm-Original-To: guix-patches@HIDDEN
Received: by smtp.purelymail.com (Purelymail SMTP) with ESMTPSA id 1192003627; 
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 15 Aug 2025 20:05:18 +0000 (UTC)
From: Lilah Tascheter <lilah@HIDDEN>
To: guix-patches@HIDDEN
Subject: [PATCH] 006-rebootload: Propose GCD006 "Rewrite Bootloader Subsystem"
Date: Fri, 15 Aug 2025 15:03:55 -0500
Message-ID: <3dafe1c7491f0c26601286406cb421efc80c9d34.1755288235.git.lilah@HIDDEN>
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
X-MIME-Autoconverted: from 8bit to quoted-printable by Purelymail
Content-Type: text/plain; charset=UTF-8
Received-SPF: pass client-ip=34.202.193.197; envelope-from=lilah@HIDDEN;
 helo=sendmail.purelymail.com
X-Spam_score_int: -20
X-Spam_score: -2.1
X-Spam_bar: --
X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,
 DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,
 RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001,
 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001,
 SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no
X-Spam_action: no action
X-Spam-Score: 1.0 (+)
X-Debbugs-Envelope-To: submit
Cc: Lilah Tascheter <lilah@HIDDEN>
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -0.0 (/)

* 006-rebootload.md: New file.
---
 006-rebootload.md | 324 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 324 insertions(+)
 create mode 100644 006-rebootload.md

diff --git a/006-rebootload.md b/006-rebootload.md
new file mode 100644
index 0000000..5c1788b
--- /dev/null
+++ b/006-rebootload.md
@@ -0,0 +1,324 @@
+title: Bootloader Subsystem Rewrite
+id: 006
+status: draft
+discussion: https://issues.guix.gnu.org/<number assigned by issue tracker>
+authors: Lilah Tascheter
+sponsors: <Sponsor Name>
+date: <date when the discussion period starts>
+SPDX-License-Identifier: CC-BY-SA-4.0 OR GFDL-1.3-no-invariants-or-later
+---
+
+# Summary
+
+Guix's bootloader handling was originally designed solely for GRUB but, wi=
th
+greater adoption and widened system compatibility, this has proved insuffi=
cient.
+Unfortunately, core aspects of bootloader handling have remained unchanged=
,
+resulting in a system hard to fit new bootloaders into and confusing for
+end-users to configure.
+
+We propose an in-depth rewrite in order to create a more flexible and easi=
er to
+understand interface for both end users and bootloader packagers.
+
+Prior work has been done as patchsets #69343, #73202, and #72457 on Mumi. =
This
+GCD is a new proposal improving upon these patches.
+
+# Motivation
+
+We identify three main ways the current bootloader handling proves insuffi=
cient:
+1. Structural assumptions of GRUB exist in both user-facing bootloader
+   configuration options as well as the packager-facing bootloader interfa=
ce.
+2. Multiple special cases exist in bootloader packaging and installation, =
making
+   it incredibly easy to package bootloaders that either install onto the =
host
+   during disk-image building or fail during system rollback.
+3. Bootloader packaging is ill-documented and relies on a confusing interf=
ace,
+   which is especially bad for such a sensitive part of system configurati=
on.
+
+Take, first, the user-facing side of things. 11/14 fields of the
+`<bootloader-configuration>` record are only used in GRUB, with multiple h=
aving
+no imaginable use for non-GRUB bootloaders in the first place. Theoretical=
ly,
+new bootloaders could add fields to the record if they need their own
+configuration, but any external channels would not be able to do even that=
.
+
+Disk image handling is not well-specified, especially when attempting to c=
reate
+a disk image with a custom bootloader. Examples provide `/dev/vda1`, so a =
user
+would assume that Guix looks for that magic string, but instead bootloader
+handling uses a special install procedure. Notably, an unused target must =
be
+specified anyway.
+
+The `<menu-entry>` record is, also, made solely with GRUB in mind, even th=
ough
+dual-booting is theoretically something that should be supported by bootlo=
aders
+in general. Fields are documented with semantics based solely on how GRUB
+interprets them.
+
+More notably, the current state of affairs hampers bootloader packaging
+significantly. The `<bootloader>` record contains the following fields:
+* `bootloader-name`: containing a symbol supposed to uniquely identify a
+  bootloader package, for use in rollbacks. Notably, u-boot bootloaders ig=
nore
+  this requirement, to potentially disasterous consequences. It doesn't he=
lp
+  that the only time one would notice problems with this (for example, a
+  channel's bootloader defined outside gnu/bootloader, a bootloader define=
d as a
+  procedure, or reused `bootloader-name`s) is when you already need to rol=
l
+  back to a different bootloader.
+* `bootloader-package`: This is only useful for switching which GRUB packa=
ge is
+  used for GRUB bootloaders.
+* `bootloader-configuration-file`: This is the sole mechanism through whic=
h
+  rollbacks function. Few bootloaders utilize config file semantics, makin=
g
+  bootloader packaging a pain of trying to coerce semantics to fit in this=
 rigid
+  box. This, also, prevents use of non-deterministic config files, such as=
 those
+  containing signed data for secure boot systems.
+* `bootloader-installer` and `bootloader-disk-image-installer`: `installer=
` is
+  meant to be used on mounted filesystems. `disk-image-installer` is meant=
 to be
+  used on devices. `disk-image-installer` is used for disk image building =
or as
+  a fallback. Some bootloaders (even GRUB!) need access to both a filesyst=
em and
+  disk, and the two separate code paths mean development can lead to poorl=
y
+  tested bootloading code. The arguments to both procedures are, also, poo=
rly
+  documented (and weird choices in general; root-index is purely used by G=
RUB).
+
+# Detailed Design
+
+## Bootloader Definition
+First, we go over the general architecture of bootloader packaging. Each
+bootloader will have two things associated to it: a `<bootloader>` record
+denoting what functions it provides, and a configuration record unique to =
each
+type of bootloader. The `<bootloader>` record defines functions taking in =
the
+configuration record, as a way for the bootloader system to extract the
+information it needs from each bootloader's config.
+
+Going into specifics, the `<bootloader>` record will be redefined as such:
+* `bootloader-predicate`: A predicate denoting whether the configuration i=
s of
+  the right type, used to verify whether users provided the correct record=
.
+* `bootloader-installers`: A list of `<bootloader-installer>` records.
+
+`<bootloader-installer>` is a new record intended to split up individual
+target installation methods. This is necessary as disk images do not have =
all
+possible targets accessible at once (as the disk is generated strictly aft=
er
+partitions). The record is defined as such:
+* `<bootloader-installer-tag>`: An arbitrary symbol used by the bootloader=
 to
+  identify this installer and its targets. A `<bootloader>` may not have t=
wo
+  `<bootloader-installers>` with the same tag.
+* `<bootloader-installer-type>`: A symbol indicating the sort of values al=
lowed
+  as targets. Allowed the following values:
+  - `'file`: Only strings allowed, interpreted as paths.
+  - `'block`: Strings (interpreted as block devices), `file-system-label`s=
, and
+    `uuid`s allowed. `uuid`s are interpreted as filesystem UUIDs, partitio=
n
+    UUIDs, or partition table UUIDs, attempted in that order.
+* `<bootloader-installer-targets>`: A function from the bootloader's
+  configuration to a list of targets specified by the user. Typically this=
 is
+  just a configuration record field accessor.
+* `<bootloader-installer-installer>`: A function from the bootloader's
+  configuration, an alist of generation numbers to `<boot-parameters>`, th=
e
+  current generation number, and the boot-time target map (see below), to =
a gexp
+  containing an installer procedure as specified below.
+
+Installers are gexps containing a procedure taking keyword arguments. The
+procedure is called once for each target in the `<bootloader-installer>`, =
and
+provided keyword arguments depending on the `<bootloader-installer-type>`.=
 Each
+keyword argument has a side, either boot-side or install-side. Install-sid=
e data
+is only valid during installation of the bootloader, and should not be use=
d
+during bootup. This data is generated from system state at install-time.
+Boot-side data is usable during bootup, and generated from a given system'=
s
+`<file-system>` records. However, if a `'block` type installer is provided=
 a
+path to a block device, boot-time data must be generated at install-time. =
For
+this reason, usage of a path `'block` is not recommended. Keyword argument=
s are
+as follows:
+* `#:mount` (`'file`, install-time): Absolute path to the mount point of t=
he
+  filesystem the file is stored on.
+* `#:path` (`'file`, install-time): Absolute path to the specified file.
+* `#:device` (`'block`, install-time): Device file for the block device.
+* `#:offset` (`'file`, boot-time): Filesystem-relative path. Includes the =
btrfs
+  subvolume prefix when applicable, so `#:path` may not always be
+  `string-append`'ed `#:mount` and `#:offset`.
+* `#:label` (all, boot-time): Filesystem label.
+* `#:uuid` (all, boot-time): Filesystem uuid, unless `'block` and a partit=
ion
+  UUID or partition table UUID is provided.
+
+In the future, more installer types and keyword arguments may be provided
+fully backwards-compatibly.
+
+The boot-time target map provieded to `bootloader-installers` is an alist =
of
+tags to lists of boot-time data, one for each target. Boot-time data is
+exactly the boot-time keyword arguments provided to installer gexp procedu=
res,
+but are provided here for certain installers to know about others (for exa=
mple,
+the GRUB early loader installed to a disk knowing about the full GRUB
+installation's partition and location).
+
+## User Configuration
+Users will specify the `<bootloader>` they wish to use directly in the
+`operating-system-bootloader` field, which will be changed to allow `#f` (=
for no
+bootloaders, as in virtualized images with direct linux booting).
+`<operating-system>` will also receive a new
+`operating-system-bootloader-configuration` field. This field will accept =
a
+configuration used by the `operating-system-bootloader`, verified by
+`bootloader-predicate`.
+
+All further bootloader configuration, including targets and additional boo=
t
+options, will be provided in the `operating-system-bootloader-configuratio=
n`.
+
+The current `<menu-entry>` and `<bootloader-configuration>` records will b=
e
+re-adapted into grub-specific configuration.
+
+## Rollbacks
+As the entire bootloader install process exists in gexps, each generation =
will
+simply save its combined bootloader install script as a GC root to be call=
ed on
+rollback, the exact way it's called on install. This eliminates the need f=
or
+bootloader module search and bootloader configuration guessing (as is curr=
ently
+used), as well as making bootloader rollbacks more reliable.
+
+Due to this, the following `<boot-parameters>` fields may be removed:
+`boot-parameters-root-device`, `boot-parameter-bootloader-name`, and
+`boot-parameter-menu-entries`. The record shall be updated to version 2 to
+match.
+
+## Disk Images
+While disk images will work automatically with the above system through th=
e
+keyword argument discovery mechanisms, one instance of special-casing is
+unfortunately required. Any `<bootloader-installer>` with the tag `'disk`
+will, instead of using targets from `bootloader-installer-targets`, provid=
e
+a single target, generated from the resulting disk image file.
+
+All other handling will be done invisibly to both end-users and bootloader
+packagers, due to the above defined semantics of target conversion into ke=
yword
+arguments.
+
+## Cascading Changes
+These changes will necessitate some edits to specific bootloaders and
+supporting code. The current GRUB bootloader installer calls `grub-install=
`,
+which guesses a lot of information about the system it's currently run on.=
 This
+approach, of course, does not work for disk images, and so manual image cr=
eation
+is used there. We propose unifying the two approaches, manually creating d=
isk
+images with the information given to us by the new targeting system.
+
+Furthermore, a new utility procedure will be created to facilitate EFI
+bootloaders, handling copying to the ESP, setting EFI boot options,
+configuring removability, and ensuring sufficient storage space in the ESP=
.
+
+## Documentation
+A page will be added to the manual under the `Programming Interface` secti=
on
+describing the new bootloader interfaces. This page will note the default
+modules provided to installer gexps and the special-casing of the `'disk` =
tag.
+
+The `Bootloader Configuration` page will be updated to act as a unified
+documentation of the peculiarities of each bootloader and how to use it. M=
anual
+pages pertaining to bootloader installation will be updated to document th=
e new
+user configuration format, and a blog post will be made to ease the transi=
tion.
+
+## Bootloading Team
+Lastly, a bootloading team will be created as a point of contact and
+implementation group for the above changes. This team would develop the pr=
oposed
+changes in a public fork of Guix in order to facilitate user testing acros=
s the
+wide range of supported hardware. Merging with mainline will be done once =
patch
+review and sufficiently diverse testing as to minimize user impact has bee=
n completed.
+
+## Examples
+```scheme
+(define-record-type* <simple-configuration>
+  simple-configuration make-simple-configuration simple-configuration?
+  (copy-to simple-configuration-copy-to))
+(define (simple-bootloader-installer conf params current targets)
+  #~(lambda* (#:key path #:allow-other-keys)
+      (copy-file #$(file-append simple-bootloader-pkg "/share/config") pat=
h)))
+(define simple-bootloader
+  (bootloader
+    (predicate simple-configuration?)
+    (installers (bootloader-installer
+                  (tag 'copy-to)
+                  (type 'file)
+                  (targets (compose list simple-configuration-copy-to))
+                  (installer simple-bootloader-installer)))))
+```
+```scheme
+(operating-system
+  (bootloader simple-bootloader)
+  (bootloader-configuration (simple-configuration (copy-to "/boot/config")=
)))
+```
+
+# Migration
+Even though bootloader management may be considered part of the Guix API
+surface, we do not attempt to provide a clean migration path. Thus, upon m=
erge
+immediate incompatibilities will occur for all channels packaging bootload=
ers.
+This, thankfully, proves to be a very small number.
+
+For operating system configuration, however, the existing
+`<bootloader-configuration>` and `<menu-entry>` structures shall be deprec=
ated.
+`<operating-system>`s will go through a pass converting such structures in=
to the
+new format, through a `bootloader-migration` field in `<bootloader>` allow=
ed to
+be `#f`. This field may contain a function from `<bootloader-configuration=
>` to
+the bootloader's configuration. The fixup procedure will operate as follow=
s,
+taking
+```scheme
+(operating-system
+  (bootloader (bootloader-configuration
+                (bootloader test-bootloader))))
+```
+to
+```scheme
+(operating-system
+  (bootloader test-bootloader)
+  (bootloader-configuration ((bootloader-migrate test-bootloader)
+                             (bootloader-configuration
+                               (bootloader test-bootloader)))))
+```
+
+Target handling would require little to no special-casing in such migratio=
n
+functions.
+
+After a year, this deprecation will expire, and the fixup code, old record=
s, and
+`bootloader-migration` field may be removed. This way, existing
+`<operating-system>`s may be used as-is for the period necessitated by the
+Deprecation Policy.
+
+## Study of Affected Channels
+We have taken an informal study of Guix channels as of 2025-08-13 in order=
 to
+estimate the impact of breaking API changes. 98 Guix channels were located
+from the following roots:
+* [whereiseverything channel toys](https://toys.whereis.social/channels)
+* [Github awesome-guix](https://github.com/franzos/awesome-guix)
+* [crafted-guix](https://codeberg.org/SystemCrafters/crafted-guix), an
+  additional channel found through internet search.
+* [gooy-guix](https://git.squircle.space/gooy-guix.git), mentioned to me b=
y Ada
+  Avery and posted on guix-devel.
+
+Of those 98, we were able to locate exactly 4 which add bootloaders, none =
of
+which managed to fully support Guix's existing bootloader handling:
+* [rosenthal](https://codeberg.org/hako/Rosenthal), which just packages GR=
UB
+  with an overridden package that supports LUKS2. Does not support rollbac=
ks.
+* [gooy-guix](https://git.squircle.space/gooy-guix.git), packaging a
+  systemd-boot EFI bootloader. It is impossible for this bootloader to sup=
port
+  disk images in the current system.
+* [waggle](https://git.lunabee.space/waggle/files.html), my channel, which
+  adds p-boot for the Pinephone and a UKI bootloader, whose roundabout
+  implementation necessitated by the current system prompted me to begin t=
his
+  rewrite in the first place. Does not support rollbacks, and I didn't rea=
lize
+  until after I needed one in the first place. It is impossible for these =
to
+  support disk images in the current system.
+* [sakura](https://g.freya.cat/freya/sakura). The bootloader added is enti=
rely
+  copied from my channel and the channel's owner has switched to Nix anywa=
y.
+
+We thus conclude change to be necessary, and the potential impact of break=
ing
+changes minimal.
+
+# Cost of Reverting
+While these changes will drastically affect internals, the vast majority o=
f
+users should see a smooth transition. Similar methods to the above mention=
ed
+migration path may be employed if this changeset needs to be reverted, at =
the
+cost of another breaking change to bootloader-packaging channels.
+
+However, another roadblock in reverting could take place in the removal of=
 boot
+parameter options. Thus, we propose postponing the boot parameter changes =
until
+after reverting is precluded as a possibility. Only then will the version =
be
+incremented and unnecessary fields dropped.
+
+# Drawbacks and Open Issues
+As these are bootloader changes, patches will need to be tested carefully =
in
+order to ensure no devices get bricked. And, even then, there could still =
be a
+risk due to how sensitiive bootloader installation and handling can be. Th=
is is
+the main obstacle for implementation. It may be useful, then, to have a mo=
re
+concrete procedure set in place to ensure proper testing after patch
+development.
+
+The deprecation process is not ideal, especially with the removal of the
+`bootloader-migrate` field resulting in two breaking changes to
+bootloader-packaging channels.
+
+The special-casing of the `'disk` tag is also not ideal. We could not thin=
k of
+any better method to provide such information.
--=20
2.50.0





Acknowledgement sent to Lilah Tascheter <lilah@HIDDEN>:
New bug report received and forwarded. Copy sent to guix-patches@HIDDEN. Full text available.
Report forwarded to guix-patches@HIDDEN:
bug#79248; Package guix-patches. Full text available.
Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.
Last modified: Fri, 15 Aug 2025 20:30:02 UTC

GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997 nCipher Corporation Ltd, 1994-97 Ian Jackson.