Skip to content
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

UKI direct boot #341357

Open
ilya-fedin opened this issue Sep 12, 2024 · 18 comments
Open

UKI direct boot #341357

ilya-fedin opened this issue Sep 12, 2024 · 18 comments

Comments

@ilya-fedin
Copy link
Contributor

Issue description

Currently NixOS lets to load UKI only with systemd-boot, there's no alternative to the virt-firmware's kernel-install hook that users of e.g. Fedora can use to have boot entries directly in the UEFI boot menu.

Steps to reproduce

  1. Try to build a UKI

Technical details

  • system: "x86_64-linux"
  • host os: Linux 6.10.7-cachyos, NixOS, 24.11 (Vicuna), 24.11.19700101.dirty
  • multi-user?: yes
  • sandbox: yes
  • version: nix-env (Nix) 2.18.5
  • nixpkgs: /etc/static/nixpkgs
@surfaceflinger
Copy link
Member

boot entries directly in the UEFI boot menu

in case of boot.loader.efi.canTouchEfiVariables = false; current generation could be instead put as /EFI/BOOT/BOOTX64.efi and older ones could be accessible using boot from file functionality in firmware

@misuzu
Copy link
Contributor

misuzu commented Sep 12, 2024

and older ones could be accessible using boot from file functionality in firmware

The kernel requires the init= argument pointing to the required system generation.

@ilya-fedin
Copy link
Contributor Author

in case of boot.loader.efi.canTouchEfiVariables = false; current generation could be instead put as /EFI/BOOT/BOOTX64.efi and older ones could be accessible using boot from file functionality in firmware

How to choose other configurations? 🤔
The point is to have all the generations in UEFI boot menu and conveniently siwtch between them.

@surfaceflinger
Copy link
Member

surfaceflinger commented Sep 12, 2024

The kernel requires the init= argument pointing to the required system generation.

UKIs can contain cmdline too and are the only used cmdline when secureboot is on

Huge amounts of generations would waste lots of space tho but it would still be possible to do

@misuzu
Copy link
Contributor

misuzu commented Sep 12, 2024

This should be possible to implement using the bootspec + efibootmgr + a script à la systemd-boot-builder.py

@msanft
Copy link
Contributor

msanft commented Sep 12, 2024

You could just use an activation script to add the boot entry via EFI variables if I get your question right here.

I don't think this is something that upstream-NixOS should support, as most users will just have a boot menu. But feel free to open a PR adding such a hook if you think that this is useful.

@ilya-fedin
Copy link
Contributor Author

I don't think this is something that upstream-NixOS should support

That's quite sad. Fedora seem to move in the direction of having such setup by default and it would be very disappointing if this wouldn't be possible to get with upstream module.

Personally I really like the boot menu my UEFI has and systemd-boot feels like an unnecessary middleware.

@msanft
Copy link
Contributor

msanft commented Sep 12, 2024

Is there a specification for variables that will be considered by such firmware-built-in boot menus for their versions? I'm open to have such a thing per se, but it shouldn't be scoped to a single firmware vendor

@ilya-fedin
Copy link
Contributor Author

Is there a specification for variables that will be considered by such firmware-built-in boot menus for their versions?

I'm not sure... Aren't those the ones efibootmgr shows/manipulates?

@SigmaSquadron
Copy link
Contributor

@ilya-fedin A small question: are you proposing that the UKIs pack both the kernel and initrd used by each generation? We faced a similar conundrum in #324911 where a full UKI would cost almost 100MiB per specialisation per profile per generation on the ESP. The solution we achieved there was to just pack the EFI executable and the configuration file containing the path to the kernel/initrd and the cmdline in a tiny 2MiB UKI.

Packing the whole kernel would make it significantly easier to manage the generations, while only using small UKIs that point to separate kernel files would mean that the UKIs are dependent on files with possibly varying path names.

@ilya-fedin
Copy link
Contributor Author

A small question: are you proposing that the UKIs pack both the kernel and initrd used by each generation?

What I propose should be orthogonal to how UKIs are created? All I propose is NixOS scripts adding/removing each boot entry to UEFI instead of boot loader.

@msanft
Copy link
Contributor

msanft commented Sep 20, 2024

I think we could add something that simply does a bootctl set-default on each activation, which would probably handle deltas in EFI variable naming between different implementations, if any.

@ilya-fedin
Copy link
Contributor Author

I think we could add something that simply does a bootctl set-default on each activation

Not sure how that would fulfill the request given that it is about bypassing systemd-boot or any other boot loader

@msanft
Copy link
Contributor

msanft commented Sep 21, 2024

I think we could add something that simply does a bootctl set-default on each activation

Not sure how that would fulfill the request given that it is about bypassing systemd-boot or any other boot loader

I think this should only use EFI variables, which are not really coupled to systemd-boot?

@ilya-fedin
Copy link
Contributor Author

It seem to operate on systemd-boot's own EFI variables? The only generic EFI commands seem to be:

Generic EFI Firmware/Boot Loader Commands:
  status               Show status of installed boot loader and EFI variables
  reboot-to-firmware [BOOL]
                       Query or set reboot-to-firmware EFI flag

@msanft
Copy link
Contributor

msanft commented Sep 22, 2024

Hmm. Looks like that when scrolling through their code. I'd have expected this to be generic. Another possibility would be to replace the /EFI/BOOT/BOOTX64.EFI in the ESP directly. That would - however - also make your system non-recoverable if anything goes wrong in the early boot stages (i.e. before the emergency shell or if the emergency shell is deactivated)

@ilya-fedin
Copy link
Contributor Author

why couldn't just the same scripts (from virt-firmware package) or efibootmgr be used?

@surfaceflinger
Copy link
Member

With systemd v257, we provide a middle ground now: UKIs may now contain multiple "profiles": multiple sets of PE sections can be combined in different ways and then labelled as different profiles. Typically this would be used to build a single UKI that contains 1 kernel and 1 initrd, but 4 different kernel command lines, which would then be combined in 4 profiles, always combining the kernel/initrd and a different command line.

is it possible to pick a profile automatically using eg. only efi vars or by passing an argument in efi shell? or are these completely "dumb" and meant to be parsed by a separate executable?

you can invoke a UKI and prefix its command line with a string like @4 to pick profile number 4. The rules are relatively strict and separate from the usual command line syntax, since we profile is parsed and remove from the cmdline before measurement. (the chosen profile is measured separetly).

https://mastodon.social/@pid_eins/113431706149996315

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants