mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
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>
This commit is contained in:
@@ -134,10 +134,14 @@
|
||||
<varlistentry>
|
||||
<term><option>set-default</option> <replaceable>ID</replaceable></term>
|
||||
<term><option>set-oneshot</option> <replaceable>ID</replaceable></term>
|
||||
<term><option>set-sysfail</option> <replaceable>ID</replaceable></term>
|
||||
|
||||
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string or a glob
|
||||
pattern as argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
|
||||
the <option>set-default</option> will set it persistently for all future boots.</para>
|
||||
the <option>set-default</option> will set it persistently for all future boots. The <option>set-sysfail</option> command
|
||||
will set the boot loader entry to be used in case of a system failure. System failure (SysFail) boot entries can
|
||||
optionally modify the automatic selection order in the event of a failure, such as a boot firmware update failure with
|
||||
the failure status recorded in the EFI system table.</para>
|
||||
|
||||
<para><command>bootctl list</command> can be used to list available boot loader entries and their
|
||||
IDs.</para>
|
||||
@@ -146,8 +150,9 @@
|
||||
<option>@oneshot</option> or <option>@current</option>, which correspond to the current default boot loader
|
||||
entry for all future boots, the current default boot loader entry for the next boot, and the currently booted
|
||||
boot loader entry. These special IDs are resolved to the current values of the EFI variables
|
||||
<varname>LoaderEntryDefault</varname>, <varname>LoaderEntryOneShot</varname> and <varname>LoaderEntrySelected</varname>,
|
||||
see <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot Loader Specification</ulink> for details.
|
||||
<varname>LoaderEntryDefault</varname>, <varname>LoaderEntrySysFail</varname>, <varname>LoaderEntryOneShot</varname>
|
||||
and <varname>LoaderEntrySelected</varname>, see <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">
|
||||
Boot Loader Specification</ulink> for details.
|
||||
These special IDs are primarily useful as a quick way to persistently make the currently booted boot loader
|
||||
entry the default choice, or to upgrade the default boot loader entry for the next boot to the default boot
|
||||
loader entry for all future boots, but may be used for other operations too.</para>
|
||||
|
||||
52
man/systemd-boot-clear-sysfail.service.xml
Normal file
52
man/systemd-boot-clear-sysfail.service.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||
|
||||
<refentry id="systemd-boot-clear-sysfail.service" conditional='ENABLE_BOOTLOADER'
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>systemd-boot-clear-sysfail.service</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>systemd-boot-clear-sysfail.service</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd-boot-clear-sysfail.service</refname>
|
||||
<refpurpose>Clear LoaderEntrySysFail entry </refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>systemd-boot-clear-sysfail.service</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><filename>systemd-boot-clear-sysfail.service</filename> is a system service that automatically clears the
|
||||
'LoaderEntrySysFail' boot loader entry if the boot was successful and the 'LoaderSysFailReason' EFI variable,
|
||||
which indicates the reason for the system failure, is not set. </para>
|
||||
|
||||
<para>The <filename>systemd-boot-random-seed.service</filename> unit invokes the <command>bootctl --graceful
|
||||
set-sysfail ""</command> command, which clears the LoaderEntrySysFail entry. The service is conditionalized
|
||||
so that it is run only when a LoaderSysFailReason entry is not set.</para><para>For further details see
|
||||
<citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>, regarding
|
||||
the command this service invokes.</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para><simplelist type="inline">
|
||||
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
|
||||
</simplelist></para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
@@ -19,6 +19,7 @@ enable machines.target
|
||||
|
||||
enable getty@.service
|
||||
|
||||
enable systemd-boot-clear-sysfail.service
|
||||
enable systemd-boot-update.service
|
||||
enable systemd-confext.service
|
||||
enable systemd-homed.service
|
||||
|
||||
@@ -307,6 +307,7 @@ libefi_sources = files(
|
||||
'secure-boot.c',
|
||||
'shim.c',
|
||||
'smbios.c',
|
||||
'sysfail.c',
|
||||
'ticks.c',
|
||||
'url-discovery.c',
|
||||
'util.c',
|
||||
|
||||
@@ -1224,6 +1224,7 @@ static int remove_loader_variables(void) {
|
||||
EFI_LOADER_VARIABLE_STR("LoaderConfigTimeout"),
|
||||
EFI_LOADER_VARIABLE_STR("LoaderConfigTimeoutOneShot"),
|
||||
EFI_LOADER_VARIABLE_STR("LoaderEntryDefault"),
|
||||
EFI_LOADER_VARIABLE_STR("LoaderEntrySysFail"),
|
||||
EFI_LOADER_VARIABLE_STR("LoaderEntryLastBooted"),
|
||||
EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot"),
|
||||
EFI_LOADER_VARIABLE_STR("LoaderSystemToken")) {
|
||||
|
||||
@@ -89,6 +89,11 @@ static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryDefault': %m");
|
||||
|
||||
} else if (streq(arg1, "@sysfail")) {
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE_STR("LoaderEntrySysFail"), NULL, (void *) ret_target, ret_target_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntrySysFail': %m");
|
||||
|
||||
} else if (arg1[0] == '@' && !streq(arg1, "@saved"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unsupported special entry identifier: %s", arg1);
|
||||
else {
|
||||
@@ -144,6 +149,9 @@ int verb_set_efivar(int argc, char *argv[], void *userdata) {
|
||||
if (streq(argv[0], "set-default")) {
|
||||
variable = EFI_LOADER_VARIABLE_STR("LoaderEntryDefault");
|
||||
arg_parser = parse_loader_entry_target_arg;
|
||||
} else if (streq(argv[0], "set-sysfail")) {
|
||||
variable = EFI_LOADER_VARIABLE_STR("LoaderEntrySysFail");
|
||||
arg_parser = parse_loader_entry_target_arg;
|
||||
} else if (streq(argv[0], "set-oneshot")) {
|
||||
variable = EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot");
|
||||
arg_parser = parse_loader_entry_target_arg;
|
||||
|
||||
@@ -420,7 +420,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
||||
{ EFI_STUB_FEATURE_MULTI_PROFILE_UKI, "Stub understands profile selector" },
|
||||
};
|
||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL, *stub_path = NULL,
|
||||
*current_entry = NULL, *oneshot_entry = NULL, *default_entry = NULL;
|
||||
*current_entry = NULL, *oneshot_entry = NULL, *default_entry = NULL, *sysfail_entry = NULL, *sysfail_reason = NULL;
|
||||
uint64_t loader_features = 0, stub_features = 0;
|
||||
int have;
|
||||
|
||||
@@ -435,6 +435,8 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE_STR("LoaderEntrySelected"), ¤t_entry);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot"), &oneshot_entry);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE_STR("LoaderEntryDefault"), &default_entry);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE_STR("LoaderEntrySysFail"), &sysfail_entry);
|
||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE_STR("LoaderSysFailReason"), &sysfail_reason);
|
||||
|
||||
SecureBootMode secure = efi_get_secure_boot_mode();
|
||||
printf("%sSystem:%s\n", ansi_underline(), ansi_normal());
|
||||
@@ -484,7 +486,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
||||
|
||||
if (loader) {
|
||||
printf("%sCurrent Boot Loader:%s\n", ansi_underline(), ansi_normal());
|
||||
printf(" Product: %s%s%s\n", ansi_highlight(), loader, ansi_normal());
|
||||
printf(" Product: %s%s%s\n", ansi_highlight(), loader, ansi_normal());
|
||||
for (size_t i = 0; i < ELEMENTSOF(loader_flags); i++)
|
||||
print_yes_no_line(i == 0, FLAGS_SET(loader_features, loader_flags[i].flag), loader_flags[i].name);
|
||||
|
||||
@@ -502,23 +504,28 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
||||
SD_ID128_FORMAT_VAL(loader_partition_uuid),
|
||||
SD_ID128_FORMAT_VAL(esp_uuid));
|
||||
|
||||
printf(" Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
|
||||
printf(" Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n",
|
||||
SD_ID128_FORMAT_VAL(loader_partition_uuid));
|
||||
} else if (loader_path)
|
||||
printf(" Partition: n/a\n");
|
||||
printf(" Partition: n/a\n");
|
||||
|
||||
if (loader_path)
|
||||
printf(" Loader: %s%s\n", glyph(GLYPH_TREE_RIGHT), strna(loader_path));
|
||||
printf(" Loader: %s%s\n", glyph(GLYPH_TREE_RIGHT), strna(loader_path));
|
||||
|
||||
if (loader_url)
|
||||
printf(" Net Boot URL: %s\n", loader_url);
|
||||
printf(" Net Boot URL: %s\n", loader_url);
|
||||
|
||||
if (sysfail_entry)
|
||||
printf("SysFail Reason: %s\n", sysfail_reason);
|
||||
|
||||
if (current_entry)
|
||||
printf("Current Entry: %s\n", current_entry);
|
||||
printf(" Current Entry: %s\n", current_entry);
|
||||
if (default_entry)
|
||||
printf("Default Entry: %s\n", default_entry);
|
||||
printf(" Default Entry: %s\n", default_entry);
|
||||
if (oneshot_entry && !streq_ptr(oneshot_entry, default_entry))
|
||||
printf("OneShot Entry: %s\n", oneshot_entry);
|
||||
printf(" OneShot Entry: %s\n", oneshot_entry);
|
||||
if (sysfail_entry)
|
||||
printf(" SysFail Entry: %s\n", sysfail_entry);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -259,6 +259,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
"\n%3$sBoot Loader Interface Commands:%4$s\n"
|
||||
" set-default ID Set default boot loader entry\n"
|
||||
" set-oneshot ID Set default boot loader entry, for next boot only\n"
|
||||
" set-sysfail ID Set boot loader entry used in case of a system failure\n"
|
||||
" set-timeout SECONDS Set the menu timeout\n"
|
||||
" set-timeout-oneshot SECONDS\n"
|
||||
" Set the menu timeout for the next boot only\n"
|
||||
@@ -660,6 +661,7 @@ static int bootctl_main(int argc, char *argv[]) {
|
||||
{ "set-oneshot", 2, 2, 0, verb_set_efivar },
|
||||
{ "set-timeout", 2, 2, 0, verb_set_efivar },
|
||||
{ "set-timeout-oneshot", 2, 2, 0, verb_set_efivar },
|
||||
{ "set-sysfail", 2, 2, 0, verb_set_efivar },
|
||||
{ "random-seed", VERB_ANY, 1, 0, verb_random_seed },
|
||||
{ "reboot-to-firmware", VERB_ANY, 2, 0, verb_reboot_to_firmware },
|
||||
{}
|
||||
|
||||
@@ -286,6 +286,10 @@ units = [
|
||||
'conditions' : ['ENABLE_BOOTLOADER'],
|
||||
'symlinks' : ['sysinit.target.wants/'],
|
||||
},
|
||||
{
|
||||
'file' : 'systemd-boot-clear-sysfail.service',
|
||||
'conditions' : ['ENABLE_BOOTLOADER'],
|
||||
},
|
||||
{
|
||||
'file' : 'systemd-boot-update.service',
|
||||
'conditions' : ['ENABLE_BOOTLOADER'],
|
||||
|
||||
29
units/systemd-boot-clear-sysfail.service
Normal file
29
units/systemd-boot-clear-sysfail.service
Normal file
@@ -0,0 +1,29 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Clear SysFail Entry If The Boot Is Successful
|
||||
Documentation=man:systemd-boot-sysfail.service(8)
|
||||
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
||||
Before=sysinit.target shutdown.target
|
||||
|
||||
ConditionPathExists=!/etc/initrd-release
|
||||
# If LoaderSysFailReason is set we should not clear SysFail entry
|
||||
ConditionPathExists=!/sys/firmware/efi/efivars/LoaderSysFailReason-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
|
||||
ConditionPathExists=/sys/firmware/efi/efivars/LoaderEntrySysFail-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=bootctl --graceful set-sysfail ""
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
||||
Reference in New Issue
Block a user