-
-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC 0153] Non-legacy boot NixOS #154
Draft
RaitoBezarius
wants to merge
1
commit into
NixOS:master
Choose a base branch
from
RaitoBezarius:uefi-only
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
--- | ||
feature: non_legacy_boot | ||
start-date: 2023-06-16 | ||
author: Ryan Lahfa | ||
co-authors: (find a buddy later to help out with the RFC) | ||
shepherd-team: (names, to be nominated and accepted by RFC steering committee) | ||
shepherd-leader: (name to be appointed by RFC steering committee) | ||
related-issues: (will contain links to implementation PRs) | ||
--- | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
NixOS will have first-class support for UEFI | ||
and uses it as a default boot environment, for supported architectures, | ||
even in situations where only BIOS Boot Specification's legacy boot is available, | ||
via a dual-stage payload consisting of a polyfill bootloader/firmware and a standard | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please no. If you want these Rube Goldberg contraptions on your machine, great. Don't force them on everybody else. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I stopped reading at this point. |
||
UEFI bootloader. | ||
|
||
To achieve this, it will downgrade the GRUB privileged position | ||
in the project and offer it as a "best effort" basis alternative bootloader. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
Legacy boot is defined by the BIOS Boot specification, written in 1996: https://www.scs.stanford.edu/nyu/04fa/lab/specsbbs101.pdf. | ||
Nowadays, computers are defaulting to UEFI more and more for the extended features provided (e.g. SecureBoot, native network boot, etc.). | ||
|
||
Nevertheless, many legacy boots machines or machines that does not have support for UEFI are used with NixOS: Single Board Computers for example | ||
on other architectures. | ||
|
||
Let's put aside non-legacy boot payloads such as [Linuxboot](https://www.linuxboot.org/), [Ownerboot](https://sr.ht/~amjoseph/ownerboot/) and any similar payloads, | ||
those are not legacy and they definitely have their places in the project, though, at the time of writing, no such payload is offered in NixOS. | ||
|
||
In nixpkgs, legacy boot forces a dichotomy between `boot.loader.efi` and... at least two legacy bootloaders **in tree**: GRUB and a family of UBoot/extlinux-compatible/etc. | ||
|
||
In the case of GRUB, there are increasing problems with this bootloader: | ||
|
||
- Upstream do not do releases anymore: https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/tools/misc/grub/default.nix#L62-L350 | ||
- Co-maintenance / release work with other ecosystems such as the kernel is simply not done: https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/tools/misc/grub/default.nix#L345-L349 causing GRUB's drivers to explode in production for our users: https://github.com/NixOS/nixpkgs/pull/235222 | ||
- Our own maintenance of GRUB is subpar: https://github.com/NixOS/nixpkgs/pull/227741 https://github.com/NixOS/nixpkgs/pull/226821 https://github.com/NixOS/nixpkgs/pull/195805 https://github.com/NixOS/nixpkgs/pull/95901 https://github.com/NixOS/nixpkgs/pull/236027 | ||
- GRUB installation procedure uses `install-grub.pl`, one of the remaining Perl script: https://github.com/NixOS/nixpkgs/pull/95901#issuecomment-756702696 offered to rewrite it with sponsoring, but no one took the offer yet, it is also very complicated to integrate with it: https://github.com/nix-community/lanzaboote/pull/96 | ||
- GRUB installation procedure for UEFI-only is still confusing because our scripts does not handle well UEFI-only (you have to pass `nodev` and this is not very well documented). See https://github.com/NixOS/nixpkgs/issues/222491 | ||
|
||
The worse about this, is this is our **default** bootloader for our install images **because** of legacy boot. | ||
|
||
In the case of UBoot/extlinux-compatible/etc. : we should definitely keep it, polish it and improve it for a better support of embedded systems, e.g. merging the differences | ||
between Raspberry Pi's bootloader and extlinux-compatible's ones. | ||
|
||
Getting rid of legacy boot opens up the way to get rid of GRUB as a default and offering an UEFI environment opens up the way to: | ||
|
||
- having a default ISO booting systemd-boot which is a maintained (by systemd) bootloader with active releases, smaller code footprint, maintained also by Systemd team in Nixpkgs | ||
- Features like https://github.com/NixOS/nixpkgs/pull/84204 could also be enabled for legacy boot users | ||
- Users who wants to use GRUB drivers to mount non-standard ESP can make use of https://efi.akeo.ie/ which is compatible with any UEFI bootloader | ||
- Boot testing can split into 2 ways: legacy boot compatibility layer tests and UEFI boot tests | ||
- Successful adoption gives a positive signal to others distribution to consider it, provide development resources to improve it rather than being held by the existing things, etc. | ||
|
||
# Detailed design | ||
[design]: #detailed-design | ||
|
||
Currently, most x86 computers^[For a more complete reference, read: https://safeboot.dev/chain-of-trust/] boot in a similar way to this **on a very high level** : | ||
|
||
```mermaid | ||
flowchart | ||
subgraph Firmware | ||
A((Power On)) --->|boots Intel Management Engine| M | ||
M((Intel Management Engine)) ---->|starts x86 CPU| C((x86 CPU)) | ||
C -->|starts OEM payload: BIOS or UEFI| O((BIOS or UEFI)) | ||
end | ||
subgraph Distribution | ||
O -->|boot further bootloaders| BL((GRUB or systemd-boot)) | ||
BL -->|boot operating system| OS((NixOS)) | ||
end | ||
``` | ||
|
||
In other platforms, you can see extra payloads like <https://github.com/ARM-software/arm-trusted-firmware> or <https://github.com/riscv-software-src/opensbi> | ||
before the distribution part, sometimes, it can be part of the distribution if control can be exerted. | ||
|
||
Some machines does even have control on the OEM payload or a good subset of the firmware, for example, via <https://www.coreboot.org/> or | ||
<https://github.com/oreboot/oreboot>. | ||
|
||
The idea is to transform this flowchart into: | ||
|
||
```mermaid | ||
flowchart | ||
subgraph Firmware | ||
A((Power On)) --->|boots Intel Management Engine| M | ||
M((Intel Management Engine)) ---->|starts x86 CPU| C((x86 CPU)) | ||
C -->|starts OEM payload: BIOS| O((BIOS)) | ||
end | ||
subgraph Distribution | ||
O -->|boot UEFI environment| UB((U-Boot)) | ||
UB -->|boot further bootloaders| BL((any UEFI-enabled bootloader)) | ||
BL -->|boot operating system| OS((NixOS)) | ||
end | ||
``` | ||
|
||
and keep it the old way whenever the OEM payload is UEFI already. | ||
|
||
If we take a step back, we can notice this 2-stage payload boot story can be generalized in those situations: | ||
|
||
```mermaid | ||
flowchart | ||
subgraph Firmware | ||
A((Power On)) --->|boots some evil chip| M | ||
M((Evil Chip 2000)) ---->|starts some architecture CPU| C(($arch CPU)) | ||
end | ||
subgraph Distribution | ||
C -->|starts user-provided firmware| CBL((coreboot)) | ||
CBL -->|starts user-provided payload| O((TianoCore, LinuxBoot, OwnerBoot, etc.)) | ||
O -->|boot Linux operating system| OS((U-Boot)) | ||
end | ||
``` | ||
|
||
In this situation, (c)oreboot could be a replacement of U-Boot environment and any UEFI-enabled bootloader could be replaced by any payload. | ||
|
||
Therefore, the design has to be general enough to support both usecases. | ||
|
||
Removing legacy boot will use a deprecation schedule and proceed into multiple steps. This RFC is dependent on accepted minimal implementations, where 'minimal' has to | ||
be defined in this RFC. | ||
|
||
# Examples and Interactions | ||
[examples-and-interactions]: #examples-and-interactions | ||
|
||
Fedora is considering doing this: https://lists.fedoraproject.org/archives/list/[email protected]/thread/GOETDM5SWINBX5ZDV37SWMHIPRRUVVTT/. | ||
|
||
Asahi Linux is booting UEFI via UBoot without EFI variables and it has been great for them. | ||
|
||
People who want to boot off strange partitions at boot-time can exploit UEFI drivers capability to load any filesystem driver and | ||
open the EFI System Partition in ZFS if they really insist. | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
- 2-stage boot for legacy BIOS systems is more than 1-stage boot | ||
- Increased internal complexity in the boot story of NixOS | ||
- Increased load and reliance on UBoot | ||
- The runtime service `SetVariable` will probably stay highly unstable for a while (variable storage) | ||
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
||
- Keeping legacy BIOS, doing nothing | ||
Then, we will continue to have users relying on bootloaders with shady maintenance stories and a skewed perception of what a bootloader can do (e.g. boot on a ZFS partition?). | ||
|
||
- Keeping legacy BIOS, offering this new way as an option | ||
Then, we will continue to have users relying on bootloaders with shady maintenance stories and a skewed perception of what a bootloader can do (e.g. boot on a ZFS partition?). | ||
|
||
- Keeping legacy BIOS, offering this new way as an option, deprecating legacy BIOS on a time schedule | ||
It is a minor variant of the proposal. | ||
|
||
- Keeping legacy BIOS, switching only new users to this mechanism without any deprecation of legacy BIOS for the time being | ||
This turns the problem into maintenance in-tree of GRUB2, which is fine by me. | ||
|
||
- Removing legacy BIOS, switching all users to this mechanism | ||
This does not have any deprecation schedule. | ||
|
||
# Unresolved questions | ||
[unresolved]: #unresolved-questions | ||
|
||
- How to migrate existing installs without any GPT partition table? | ||
- How to migrate existing installs with a GPT partition table but without a supported EFI System Partition, e.g. LVM | ||
- NTFS, XFS, exFAT, Amiga FFS/SFS, BFS, UFS, ZFS are handled via https://efi.akeo.ie/ which is an EFI driver that can be loaded | ||
- Subquestion: how to load EFI drivers for unsupported EFI System Partition? | ||
- Answer: Build EDK2 or UBoot with https://github.com/pbatard/efifs them. | ||
- When to do it? | ||
- What to do about variable storage (Asahi Linux showed this is not that important for a start)? | ||
- What to do about (>)dual boot configurations if variable storage is not available? (writing the EFI fallback directory will break the dual boot configuration.) | ||
- Design architecture in nixpkgs? | ||
|
||
# Future work | ||
[future]: #future-work | ||
|
||
- Improved support for UEFI features on non-UEFI native systems |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UEFI does not "support" entire architectures in any meaningful sense. It "supports" MIPS and yet there is not a single UEFI MIPS machine in existence! Talking about "UEFI-supported architectures" is extremely misleading.