mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +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>
|
<varlistentry>
|
||||||
<term><option>set-default</option> <replaceable>ID</replaceable></term>
|
<term><option>set-default</option> <replaceable>ID</replaceable></term>
|
||||||
<term><option>set-oneshot</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
|
<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,
|
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
|
<para><command>bootctl list</command> can be used to list available boot loader entries and their
|
||||||
IDs.</para>
|
IDs.</para>
|
||||||
@@ -146,8 +150,9 @@
|
|||||||
<option>@oneshot</option> or <option>@current</option>, which correspond to the current default boot loader
|
<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
|
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
|
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>,
|
<varname>LoaderEntryDefault</varname>, <varname>LoaderEntrySysFail</varname>, <varname>LoaderEntryOneShot</varname>
|
||||||
see <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot Loader Specification</ulink> for details.
|
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
|
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
|
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>
|
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 getty@.service
|
||||||
|
|
||||||
|
enable systemd-boot-clear-sysfail.service
|
||||||
enable systemd-boot-update.service
|
enable systemd-boot-update.service
|
||||||
enable systemd-confext.service
|
enable systemd-confext.service
|
||||||
enable systemd-homed.service
|
enable systemd-homed.service
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ libefi_sources = files(
|
|||||||
'secure-boot.c',
|
'secure-boot.c',
|
||||||
'shim.c',
|
'shim.c',
|
||||||
'smbios.c',
|
'smbios.c',
|
||||||
|
'sysfail.c',
|
||||||
'ticks.c',
|
'ticks.c',
|
||||||
'url-discovery.c',
|
'url-discovery.c',
|
||||||
'util.c',
|
'util.c',
|
||||||
|
|||||||
@@ -1224,6 +1224,7 @@ static int remove_loader_variables(void) {
|
|||||||
EFI_LOADER_VARIABLE_STR("LoaderConfigTimeout"),
|
EFI_LOADER_VARIABLE_STR("LoaderConfigTimeout"),
|
||||||
EFI_LOADER_VARIABLE_STR("LoaderConfigTimeoutOneShot"),
|
EFI_LOADER_VARIABLE_STR("LoaderConfigTimeoutOneShot"),
|
||||||
EFI_LOADER_VARIABLE_STR("LoaderEntryDefault"),
|
EFI_LOADER_VARIABLE_STR("LoaderEntryDefault"),
|
||||||
|
EFI_LOADER_VARIABLE_STR("LoaderEntrySysFail"),
|
||||||
EFI_LOADER_VARIABLE_STR("LoaderEntryLastBooted"),
|
EFI_LOADER_VARIABLE_STR("LoaderEntryLastBooted"),
|
||||||
EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot"),
|
EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot"),
|
||||||
EFI_LOADER_VARIABLE_STR("LoaderSystemToken")) {
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryDefault': %m");
|
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"))
|
} else if (arg1[0] == '@' && !streq(arg1, "@saved"))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unsupported special entry identifier: %s", arg1);
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unsupported special entry identifier: %s", arg1);
|
||||||
else {
|
else {
|
||||||
@@ -144,6 +149,9 @@ int verb_set_efivar(int argc, char *argv[], void *userdata) {
|
|||||||
if (streq(argv[0], "set-default")) {
|
if (streq(argv[0], "set-default")) {
|
||||||
variable = EFI_LOADER_VARIABLE_STR("LoaderEntryDefault");
|
variable = EFI_LOADER_VARIABLE_STR("LoaderEntryDefault");
|
||||||
arg_parser = parse_loader_entry_target_arg;
|
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")) {
|
} else if (streq(argv[0], "set-oneshot")) {
|
||||||
variable = EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot");
|
variable = EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot");
|
||||||
arg_parser = parse_loader_entry_target_arg;
|
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" },
|
{ 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,
|
_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;
|
uint64_t loader_features = 0, stub_features = 0;
|
||||||
int have;
|
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("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("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("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();
|
SecureBootMode secure = efi_get_secure_boot_mode();
|
||||||
printf("%sSystem:%s\n", ansi_underline(), ansi_normal());
|
printf("%sSystem:%s\n", ansi_underline(), ansi_normal());
|
||||||
@@ -484,7 +486,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
if (loader) {
|
if (loader) {
|
||||||
printf("%sCurrent Boot Loader:%s\n", ansi_underline(), ansi_normal());
|
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++)
|
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);
|
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(loader_partition_uuid),
|
||||||
SD_ID128_FORMAT_VAL(esp_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));
|
SD_ID128_FORMAT_VAL(loader_partition_uuid));
|
||||||
} else if (loader_path)
|
} else if (loader_path)
|
||||||
printf(" Partition: n/a\n");
|
printf(" Partition: n/a\n");
|
||||||
|
|
||||||
if (loader_path)
|
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)
|
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)
|
if (current_entry)
|
||||||
printf("Current Entry: %s\n", current_entry);
|
printf(" Current Entry: %s\n", current_entry);
|
||||||
if (default_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))
|
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");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,6 +259,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||||||
"\n%3$sBoot Loader Interface Commands:%4$s\n"
|
"\n%3$sBoot Loader Interface Commands:%4$s\n"
|
||||||
" set-default ID Set default boot loader entry\n"
|
" set-default ID Set default boot loader entry\n"
|
||||||
" set-oneshot ID Set default boot loader entry, for next boot only\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 SECONDS Set the menu timeout\n"
|
||||||
" set-timeout-oneshot SECONDS\n"
|
" set-timeout-oneshot SECONDS\n"
|
||||||
" Set the menu timeout for the next boot only\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-oneshot", 2, 2, 0, verb_set_efivar },
|
||||||
{ "set-timeout", 2, 2, 0, verb_set_efivar },
|
{ "set-timeout", 2, 2, 0, verb_set_efivar },
|
||||||
{ "set-timeout-oneshot", 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 },
|
{ "random-seed", VERB_ANY, 1, 0, verb_random_seed },
|
||||||
{ "reboot-to-firmware", VERB_ANY, 2, 0, verb_reboot_to_firmware },
|
{ "reboot-to-firmware", VERB_ANY, 2, 0, verb_reboot_to_firmware },
|
||||||
{}
|
{}
|
||||||
|
|||||||
@@ -286,6 +286,10 @@ units = [
|
|||||||
'conditions' : ['ENABLE_BOOTLOADER'],
|
'conditions' : ['ENABLE_BOOTLOADER'],
|
||||||
'symlinks' : ['sysinit.target.wants/'],
|
'symlinks' : ['sysinit.target.wants/'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'file' : 'systemd-boot-clear-sysfail.service',
|
||||||
|
'conditions' : ['ENABLE_BOOTLOADER'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'file' : 'systemd-boot-update.service',
|
'file' : 'systemd-boot-update.service',
|
||||||
'conditions' : ['ENABLE_BOOTLOADER'],
|
'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