Commit Graph
53 Commits
Author SHA1 Message Date
Lennart Poettering ad19aced00 bootctl: show platform lang in bootctl status output 2026-05-20 16:38:19 +02:00
Daan De Meyer 7b9d76cba7 boot,vconsole: Propagate UEFI HII keyboard layout to the OS
UEFI firmware can report the currently-active keyboard layout via
EFI_HII_DATABASE_PROTOCOL.GetKeyboardLayout(). The layout descriptor
includes an RFC 4646 / BCP 47 language tag (e.g. "en-US"). Query this
from sd-boot/sd-stub and write it to a new LoaderKeyboardLayout EFI
variable, advertised through a new EFI_LOADER_FEATURE_KEYBOARD_LAYOUT
feature bit.

On the OS side, systemd-vconsole-setup reads the variable as a
lowest-priority fallback for the console keymap. To map the BCP 47
tag to a vconsole keymap we extend /usr/share/systemd/kbd-model-map
with an optional sixth column listing the comma-separated BCP 47 tags
each row covers; a new find_vconsole_keymap_for_bcp47() helper walks
the file, preferring an exact tag match and otherwise falling back to
the row whose tag matches the input's primary subtag. Credentials,
/etc/vconsole.conf, and vconsole.keymap= on the kernel command line
continue to take precedence.

bootctl status surfaces the new variable, printing the language tag
or "n/a (not reported by firmware)" when sd-boot advertises the
feature but the firmware HII database didn't expose a layout (common
on QEMU without a USB keyboard, since EDK2's PS/2 driver does not
register an HII keyboard layout).
2026-05-11 21:10:11 +02:00
Lennart Poettering 853d0649d5 find-esp: return pinned fd to ESP/XBOOTLDR
The reworks the ESP/XBOOTLDR logic to pin the ESP/XBOOTLDR via an fd,
and return that as optional return parameter.

So far we only pinned the parent dir of the ESP/XBOOTLDR, which was
useful when verifying that ESP/XBOOTLDR is actually a mount point by
comparing mount ids. This however became obsolete with
a98a6eb95c. Hence, let's clean this up,
and pin the inode we really care about and return it.
2026-04-20 17:19:27 +02:00
Lennart Poettering b54af7ce9a bootctl: make bootspec-util.c independent of bootctl.c
This changes boot_config_load_and_select() to also take the root path as
input, just like the ESP and XBOOTLDR path.

This has the benefit of making the whole file independent of bootctl.c,
which means we can link it into a separate test, and is preparatory work
for a follow-up commit.
2026-04-17 18:52:35 +02:00
Zbigniew Jędrzejewski-Szmek ab3a2f375f sd-varlink: export sd_varlink_set_sentinel
I tried to implement a varlink service using sd-varlink, and
not being able to use the approach with sentinel is exteremely
painful. This is useful internally and likewise externally.
2026-03-29 20:32:15 +02:00
Lennart Poettering cd911bec6e core: introduce ConditionSecurity=measured-os
So far we always conditioned our TPM magic on the UKI having detected
TPM support in the firmware. This is a bit limiting when we want to
support a software TPM that is not visible to the firmware. Hence let's
split this up, and add a separate control that can be set via the kernel
command line.  However, as before, let's by default inherit the firmare
TPM discovery state into it, to retain the current behaviour unless
overriden.

With this in place, boot with "systemd.tpm2_measured_os=1
systemd.tpm2_software_fallback=1" on the kernel cmdline to get the swtpm
fallback and then a measured OS based on it.
2026-03-26 16:11:34 +01:00
Zbigniew Jędrzejewski-Szmek 31ddd87da0 tree-wide: extend verbs functions with extra per-verb data parameter
We often have a pattern where the same verb function is used for
multiple actions. This leads to an antipattern where we figure out what
action needs to be taken from argv[0] multiple times: often once in
parse_argv() to figure out what options are allowed, then once again
implicitly in dispatch_verb(), and then again in the action verb itself.
Let's allow passing a parameter into the verb to simplify this.

This matches a pattern we have in conf-parser.h, where we have both
void *userdata (more global) and void *data (per-config item). Here,
I opted for uintptr_t userdata. It seems that most of the time we'll
want to just pass an enum value. This works OK with no casts. I also
tried a void* and union. In both cases, much more boilerplate is needed:
either a cast or a macro to help avoid compiler warnings. uintptr_t
seems generic enough to cover foreseeable usecases with no fuss.

This is a noop refactoring. See next commit for an example.
2026-03-18 10:28:47 +00:00
Zbigniew Jędrzejewski-Szmek 04897fbbee bootctl: override is_efi_boot() check by --variables= option (#40413)
Fixes #40392.
2026-02-25 15:42:53 +01:00
r-vdp 450e0dce02 systemd-boot: add a preferred setting that's similar to default but avoids booting known-bad entries
Motivation:
Currently, when setting the default boot pattern, boot assessment status
is not taken into account. This means that with boot assessment enabled,
when an explicit boot entry is configured as the default entry using an
EFI var, as is common for instance in A/B boot schemes, the configured
entry will be booted indefinitly, regardless of the entry's boot
assessment status.
In order to allow for this use case in combination with boot assessment,
we introduce a new `preferred` keyword, both in the config file and in the
bootctl CLI, that acts very similar to the existing `default` keyword but
takes boot assessment into account and never selects any entries that
have been marked as bad.
If the preferred pattern does not resolve to any bootable entry, and a
default pattern is also specified, then the default pattern will be
considered next, and we may then still select a known-bad entry to be
booted.

Fixes: https://github.com/systemd/systemd/issues/31215
Fixes: https://github.com/systemd/systemd/issues/40192
2026-02-18 03:28:12 +09:00
Mike Yuan 09388a6b9e tree-wide: drop redundant check for SD_VARLINK_METHOD_MORE flag
If the IDL declares the method requires 'more' yet the call doesn't
have it set, varlink_idl_validate_method_call() should have rejected
it and the callback shouldn't be reached.
2026-02-16 09:44:54 +01:00
Yu Watanabe 9bc1336abd bootctl: do not show an empty () for ESP partition
Before:
```
$ run0 systemd-nspawn -xD / --private-network --bind=/sys/firmware/efi/efivars --bind=/boot -- build/bootctl --variables=yes --no-pager
(snip)
Boot Loader Entry Locations:
          ESP: /boot ()
       config: /boot//loader/loader.conf
     XBOOTLDR: /boot ($BOOT)
        token: fedora
(snip)
```

After:
```
run0 systemd-nspawn -xD / --private-network --bind=/sys/firmware/efi/efivars --bind=/boot -- build/bootctl --variables=yes --no-pager
(snip)
Boot Loader Entry Locations:
          ESP: /boot
       config: /boot//loader/loader.conf
     XBOOTLDR: /boot ($BOOT)
        token: fedora
(snip)
```

This also moves spurious position of new line in each output.
2026-02-13 16:11:33 +09:00
Yu Watanabe 340c82c454 bootctl: make list command take --variables= option 2026-02-13 16:11:33 +09:00
Yu Watanabe 865f0fe28f bootctl: make status command take --variables= option 2026-02-13 16:11:33 +09:00
Daan De Meyer 4f5d44ef53 tree-wide: Migrate to varlink_set_sentinel() 2026-02-11 14:25:36 +01:00
Lennart Poettering 8b736d94cd bootctl: decouple "list", "unlink", "cleanup"
These operations to quite different things, they just share 2 common
funcs. Let's split them out into separate files.

This also splits up verb_list() into separate calls for the three
operations. This actually fixes issues, as for status/list we want
"unpriv" ESP discovery logic, but for the other two we really should
have privileged discovery logic.

This is preparation for adding "bootctl link" later, but this makes
sense either way, I am sure.
2026-02-10 19:43:04 +00:00
Luca Boccassi b262ded0bd Boot loader menu docs and tweaks (#39842) 2025-12-17 23:00:59 +00:00
Zbigniew Jędrzejewski-Szmek 3cdd80d3e0 sd-boot: correct typos 2025-12-17 22:55:38 +01:00
Yu Watanabe 93378148d4 tree-wide: normalize comment style 2025-12-15 08:50:13 +09:00
jouyouyun 49ca2d8778 bootctl: fix typo 2025-11-03 11:30:42 +01:00
Felix Pehla 4a94a1b83f shared/bootspec: parse 'uki' boot entry option
Commit e2a3d56218 (as part of #36314)
makes sd-boot recognize a 'uki' stanza in a boot loader entry and
uapi-group/specifications@3f2bd8236d adds
it to the BLS, but bootctl and other components parsing said config do
not know about it, leading to the error message
`Unknown line 'uki', ignoring.` when attempting to parse the same entry.

This commit makes it get parsed the same way that that 'efi' is.
2025-09-29 22:59:49 +02:00
Yu Watanabe bed2723caa bootctl: drop unnecessary verb_unlink()
It is a trivial wrapper for verb_list(). Let's directly use verb_list()
and drop verb_unlink().

Follow-up for 8702496bfb.
2025-09-17 14:35:45 +02:00
Yu Watanabe 37d1f1573b bootctl: do not fail on removing unfied kernel image
A boot loader entry for a unified kernel image has
BootEntry.kernel : path to the image relative to ESP or XBOOTLDR,
BootEntry.path   : path to the image.
Hence, these two effectively point to the same file.

Hence, by unlink command, the image is removed by
```
deref_unlink_file(&known_files, e->kernel, e->root);
```
then later tried again by
```
r = chase_and_unlink(e->path, root, ...);
```
and of course it fails with -ENOENT.

Let's ignore the failure there. We already ignore ENOENT on removal
at various places, especially in deref_unlink_file().

Fixes #38706.
Follow-ups for 8702496bfb.
2025-08-26 15:45:44 +02:00
Yu WatanabeandLuca Boccassi 4279336618 chase: trigger automount only when explicitly requested
Since c5de7b14ae
file searching implies a new mount api syscall by default,
to trigger automounts.

But, this is not necessary in most cases, e.g. when chasing
syspath in sd-device (actually this causes regression in umockdev,
see https://github.com/martinpitt/umockdev/issues/271).
Another example is reading unit files, especially .network files,
as automount may trigger mounting network filesystems...

Also, when this is used in NSS plugins, programs that load the
plugins may fail because of spuriously configured seccomp. See #38565.

Let's not trigger automount by default, and do only when explicitly
requested.

This introduces CHASE_TRIGGER_AUTOFS, and use it in
- service manager,
- bootctl and finding ESP/xbootldr,
- sysupdate,
- mountfsd,
- systemd-mount.

There may be several more places we should trigger automount, but let's
do that later.

Follow-up for c5de7b14ae.
Fixes #38565.
Replaces #38569.

Co-authored-by: Luca Boccassi <luca.boccassi@gmail.com>
2025-08-20 02:32:02 +09:00
Yu Watanabe 2e7d7e929e Revert "chase: invert CHASE_NO_AUTOFS and only set it where needed"
This reverts commit 490aa05ca1.

As commented https://github.com/systemd/systemd/pull/38569#discussion_r2284978273,
the commit makes autofs check bypassed. Before the commit, when
CHASE_NO_AUTOFS is set, we did not shortcut chasing paths, and refused
any autofs mount points in the path. However, with the commit, the flag
was swapped but even when CHASE_AUTOFS is unset, the autofs check may be
skipped.

To fix the issue, rather than swapping the flag, we should introduce
another flag, say CHASE_TRIGGER_AUTOFS. This revert the commit, and in a
later commit, the new flag will be introduced.
2025-08-20 02:15:36 +09:00
Luca Boccassi 490aa05ca1 chase: invert CHASE_NO_AUTOFS and only set it where needed
Since https://github.com/systemd/systemd/commit/c5de7b14ae2e08d267d8d75bc88934ac6aa7dcd6
file searching implies a new mount api syscall by default,
to trigger automounts.

This is problematic in NSS plugins, as they are dlopen'ed inside
processes by glibc, for two reasons.

First of all, potentially searching on a networked filesystem
automount could lead to nasty surprises, such as the process
responsible for setting up the network filesystem trying to
search on that same filesystem.

More importantly, the new mount api syscall was never part of
the filesystem seccomp filter that we provide by default, and
given mounting/remounting/bind mounting is one of the possible
ways to bypass sandboxing it is very likely not allowed when
custom filters are used in sandboxed processes, if they don't
need to do these operations otherwise.
The filesystem seccomp mask we provide has been updated, however
this only takes effect on the next restart of a service. When
systemd is upgraded via a package upgrade, the new nss plugin is
installed and will be immediately dlopen'ed by glibc when needed,
without waiting for the process to restart, which means the existing
seccomp filter applies, causing the filter to trigger.
Given it's not really possible for any arbitrary program to
predict which NSS modules glibc will load, given programs do not
configure that and instead nsswitch is set up by the sysadmin,
it's impossible to handle at each process level. It's also not
possible to know when it will be triggered, given the plugin
is not linked in each binary tools like need-restart cannot
even pre-emptively restart services that may be affected.

This means in practice, upgrading from systemd << v258 to >= v258
requires a reboot to avoid either subtle or catastrophic system
failures.

By avoiding to trigger automounts in nss-systemd we can avoid
both issues.

userdb drop-ins are searched for in:

/etc/userdb/
/run/userdb/
/run/host/userdb/
/usr/local/lib/userdb/
/usr/lib/userdb/

none of which are supported as automounts anyway.

Note that this happens only when the userdbd service is not running,
as otherwise nss-systemd will go through the varlink IPC, rather than
doing the searches in-process.

So invert CHASE_NO_AUTOFS to CHASE_AUTOFS and set it in the places where
we do want to trigger automounts, like looking for the ESP.

Follow-up for https://github.com/systemd/systemd/commit/c5de7b14ae2e08d267d8d75bc88934ac6aa7dcd6
Fixes https://github.com/systemd/systemd/issues/38565
2025-08-19 16:48:13 +02:00
Zbigniew Jędrzejewski-Szmek 57684a2554 bootctl: print location/status of loader.conf
The usual pattern of using colors to distinguish the mount path (/efi/)
and the rest is used. If the file cannot be read for reasons other than
-ENOENT, the error message is highlighted.

I considered a few places where to add this, but this section seems the
most reaosonable. We already print the 'token' there, which is also part of
the configuration.

Boot Loader Entry Locations:
          ESP: /efi (/dev/disk/by-partuuid/31659406-5a17-46ec-8195-0dea1667db58)
       config: /efi//loader/loader.conf
     XBOOTLDR: /boot (/dev/disk/by-partuuid/4f8a8fe9-4b45-4070-9e9b-a681be51c902, $BOOT)
        token: fedora
2025-07-29 11:36:21 +02:00
Luca Boccassi 6eab4cd44c boot: add LoaderTpm2ActivePcrBanks runtime variable
It turns out checking sysfs is not 100% reliable to figure out whether
the firmware had TPM2 support enabled or not. For example with EDK2 arm64, the
default upstream build config bundles TPM2 support with SecureBoot support,
so if the latter is disabled, TPM2 is also unavailable. But still, the ACPI
TPM2 table is created just as if it was enabled. So /sys/firmware/acpi/tables/TPM2
exists and looks correct, but there are no measurements, neither the firmware
nor the loader/stub can do them, and /sys/kernel/security/tpm0/binary_bios_measurements
does not exist.

The loader can use the apposite UEFI protocol to check, which is a more
definitive answer. Given userspace can also make use of this information, export
the bitmask with the list of active banks as-is. If it's not 0, then we can be
sure a working TPM2 was available in EFI mode.

Partially fixes https://github.com/systemd/systemd/issues/38071
2025-07-14 20:56:22 +01:00
Yu Watanabe 91c60ff528 bootctl: do not print slash more than once
When bootctl is called by an unprivileged user, then previously we got
```
Failed to read "/boot/EFI/systemd": Permission denied
Failed to open '/boot//loader/loader.conf': Permission denied
```
Now, with this patch, we get
```
Failed to read "/boot/EFI/systemd": Permission denied
Failed to open '/boot/loader/loader.conf': Permission denied
```
2025-05-31 13:53:04 +02:00
Daan De Meyer f712008289 bootctl: Clean up includes
Split out of #37344.
2025-05-22 02:14:09 +09:00
Zbigniew Jędrzejewski-Szmek 5270c085d4 bootctl: prefix all paths with the mountpoint prefix
Continuation of 7851732262 and
5a65d2e535. Absolute paths are always
nicer for the user because it's much easier to figure out where the
file is located. And printing some paths with the prefix and some
without was quite confusing.
2025-05-20 18:20:36 +02:00
Zbigniew Jędrzejewski-Szmek e187450648 bootctl: rework Boot Loader Entries section in status
Kernels are loaded from two partitions (XBOOTLDR and ESP). In the past this
wasn't always so, but a while ago the docs and the code were updated to load
from both locations. The $BOOT location specifies where to install only. So
rework the status output to print both locations and indicate which one is
$BOOT by appending ", $BOOT".

Also change the section title to "… Locations". We don't show *entries* here,
so the old title could be a bit confusing.

Example:
Boot Loader Entry Locations:
          ESP: /efi (/dev/disk/by-partuuid/31659406-5a17-46ec-8195-0dea1667db58)
     XBOOTLDR: /boot (/dev/disk/by-partuuid/4f8a8fe9-4b45-4070-9e9b-a681be51c902, $BOOT)
        token: fedora
2025-05-20 18:20:28 +02:00
Jelle van der Waa 346c62f9ca treewide: correct argument comments 2025-05-15 15:39:20 +02:00
Igor Opaniuk 2857a83975 bootctl: configure a sysfail entry
You can configure the sysfail boot entry using the bootctl command:
$ bootctl set-sysfail sysfail.conf

The value will be stored in the `LoaderEntrySysFail` EFI variable.

The `LoaderEntrySysFail` EFI variable would be unset automatically
during next boot by `systemd-boot-clear-sysfail.service` if no
system failure occured, otherwise it would be kept as it is and a system
failure reason will be saved to `LoaderSysFailReason` EFI variable.

Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
2025-05-12 15:37:47 +02:00
Daan De Meyer e53d4f343d iovec-util: Reduce transitive includes 2025-05-07 22:04:46 +09:00
Daan De Meyer 6553db6063 strv: Reduce transitive includes 2025-05-07 22:04:46 +09:00
Jelle van der Waa 1c04b172f1 treewide: correct argument comments for show_boot_entry 2025-05-06 16:26:47 +02:00
Daan De Meyer 69369fd322 bootctl: adjust feature message (#36372) 2025-03-21 11:17:00 +01:00
Zbigniew Jędrzejewski-Szmek 1ae9b0cfa8 basic/glyph-util: rename "special glyph" to just "glyph"
Admittedly, some of our glyphs _are_ special, e.g. "O=" for SPECIAL_GLYPH_TOUCH ;)
But we don't need this in the name. The very long names make some invocations
very wordy, e.g. special_glyph(SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY).
Also, I want to add GLYPH_SPACE, which is not special at all.
2025-03-15 14:40:39 +01:00
Zbigniew Jędrzejewski-Szmek 16fa8dbbe9 bootctl: fix boolean logic in id128 comparisons
There were too many levels of negation there. Add a comment to explain the
reasoning at a high level.
2025-03-14 12:21:45 +01:00
Zbigniew Jędrzejewski-Szmek f25e4e5af0 bootctl: stop printing "Stub/Boot loader set partition information"
... and "Stub/Boot loader set network boot URL information".

This reverts 26bfd97216
('bootctl: also shown whether stub loader partition data was passed'),
and one line from bfcf48b842
('bootctl: show stub partition data too in "status" too'),
and two lines from e15d18b4c6
('sd-stub: if we are http booted, query source URL and write to EFI variable').

As discussed in https://github.com/systemd/systemd/pull/36372, those are not
"features", but optional pieces of information that may or may not be set, also
depending on how the boot loader and stub were loaded. We already prominently
show this information right below: either we print the device path or "n/a" or
skip the output. The user already has all the information, and the status
output should be dense, so it doesn't make sense to repeat this twice.

               ✓ Boot loader set partition information
    Partition: /dev/disk/by-partuuid/3f003ec5-5673-5b4f-b9a4-cbac1ca4461a
OR
               - Boot loader set partition information
    Partition: n/a

               ✓ Stub loader set partition information
    Partition: /dev/disk/by-partuuid/3f003ec5-5673-5b4f-b9a4-cbac1ca4461a
OR
               - Stub loader set partition information
    Partition: n/a
2025-03-13 12:30:59 +01:00
Lennart Poettering a462280c9a bootctl: tweak status output when operating on --image= files
Let's not claim the system was not booted with UEFI if we use --image=.
The system wasn't booted at all, after all. Hence supress the whole
section altogether in this case.
2025-03-13 10:49:53 +01:00
Lennart Poettering 1089d0f89e boot: add new 'uki-url' bls type #1 menu items for booting remote UKIs
Companion BLS spec PR:

https://github.com/uapi-group/specifications/pull/135
2025-02-21 10:04:15 +01:00
Lennart Poettering e2a3d56218 boot: add new bls type #1 stanza "uki"
This one is between "efi" and "linux": we'll recognize such entries as
linux, but we'll just invoke them as EFI binaries.

This creates a high-level concept for invoking UKIs via indirection of a
bls type #1 entry, for example to permit invocation from a non-standard
path or for giving entries a different name.

Companion BLS spec PR:

https://github.com/uapi-group/specifications/pull/135

(Let's rename LOADER_UNIFIED_LINUX to LOADER_TYPE2_UKI at the same time
to reduce confusion what is what)
2025-02-21 10:04:15 +01:00
Lennart Poettering e15d18b4c6 sd-stub: if we are http booted, query source URL and write to EFI variable
This way userspace can read the field, and use it to retrieve more
resources from the same place.
2025-02-21 10:03:32 +01:00
Lennart Poettering af5b961ad8 bootctl: minor reordering of fields in output
Let's move the currently used/default/oneshot entry output after the
basic info about the boot loader itself, since conceptually these are
objects kinda "one level down" from the boot loader perspective. Hence,
let's *first* show all info about the boot loader itself before we
display the objects it manages.

This is just a trivial change in output, just swaps th elines for these
fields with the ones showing where the boot loader is installed.
2025-02-09 23:34:29 +01:00
Lennart Poettering df418fa234 bootctl: suppress output of empty partition info if we also have no idea about EFI binary path
So far we'd output both the partition and the binary path always, even
if we didn't know either (but in that case show empty information).
Let's address this, and show partition info only if we know it, or if we
know the EFI binary path, but suppress both if we know neither.

Note that we'll show the partition info if we don't know it still if we
know the EFI binary path used for boot, since it is relative to the
partition of course, and hence it's really strange to know one but not
the other, hence it deserves some mentioning in the output.
2025-02-09 23:23:38 +01:00
Lennart Poettering 26bfd97216 bootctl: also shown whether stub loader partition data was passed
Let's make the stub and loader output sections more alike, and say in
both cases whether we recieved that data from the boot phase or not the
same way.
2025-02-09 23:21:14 +01:00
Lennart Poettering df28afe9b2 bootctl: fix potential uninitialized memory access
And while we are at it, let' get rid of have_xyz_partition_uuid
variables, to simplify things.
2025-02-09 23:19:46 +01:00
Lennart Poettering f90efd2d13 bootctl: improve output regarding random seed if we cannot access ESP 2025-02-09 09:14:21 +01:00
Yu Watanabe c1bfee0bdb bootctl: use hash ops with destructor
This also makes the hashmap allocated when necessary.
2025-01-23 18:19:28 +09:00