From: Дамјан Георгиевски Date: Tue, 13 Oct 2020 10:25:59 +0000 (+0200) Subject: bootctl: add @current/@oneshot/@default targets to set-default/set-oneshot X-Git-Tag: v247-rc1~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c4b843473a75fb38ed5bf54e9d3cfb1cb3719efa;p=thirdparty%2Fsystemd.git bootctl: add @current/@oneshot/@default targets to set-default/set-oneshot Using `bootctl set-default @current` will set the default loader entry to the currently booted entry as read from the `LoaderEntrySelected` EFI variable. Also `bootctl set-oneshot @current` will set the oneshot loader entry to the current booted entry. Correspondingly `@default` and `@oneshot` can be used to read from the LoaderEntryDefault and LoaderEntryOneshot EFI variables. --- diff --git a/man/bootctl.xml b/man/bootctl.xml index d908d52d972..479cbb5d92b 100644 --- a/man/bootctl.xml +++ b/man/bootctl.xml @@ -102,6 +102,17 @@ Sets the default boot loader entry. Takes a single boot loader entry ID string as argument. The command will set the default entry only for the next boot, the will set it persistently for all future boots. + + Optionally, the boot loader entry ID may be specified as one of: , + or , 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 + LoaderEntryDefault, LoaderEntryOneShot and LoaderEntrySelected, + see Boot Loader Specification 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. + diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 0e24f0a499a..bb8c7398f04 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -1661,6 +1661,31 @@ static int verb_is_installed(int argc, char *argv[], void *userdata) { return EXIT_SUCCESS; } +static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target, size_t *ret_target_size) { + int r; + if (streq(arg1, "@current")) { + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntrySelected", NULL, (void *) ret_target, ret_target_size); + if (r < 0) + return log_error_errno(r, "Failed to get EFI variable 'LoaderEntrySelected': %m"); + } else if (streq(arg1, "@oneshot")) { + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, (void *) ret_target, ret_target_size); + if (r < 0) + return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryOneShot': %m"); + } else if (streq(arg1, "@default")) { + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntryDefault", NULL, (void *) ret_target, ret_target_size); + if (r < 0) + return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryDefault': %m"); + } else { + char16_t *encoded = NULL; + encoded = utf8_to_utf16(arg1, strlen(arg1)); + if (!encoded) + return log_oom(); + *ret_target = encoded; + *ret_target_size = char16_strlen(encoded) * 2 + 2; + } + return 0; +} + static int verb_set_default(int argc, char *argv[], void *userdata) { const char *name; int r; @@ -1693,17 +1718,17 @@ static int verb_set_default(int argc, char *argv[], void *userdata) { if (isempty(argv[1])) { r = efi_set_variable(EFI_VENDOR_LOADER, name, NULL, 0); if (r < 0 && r != -ENOENT) - return log_error_errno(r, "Failed to remove EFI variale: %m"); + return log_error_errno(r, "Failed to remove EFI variable '%s': %m", name); } else { - _cleanup_free_ char16_t *encoded = NULL; - - encoded = utf8_to_utf16(argv[1], strlen(argv[1])); - if (!encoded) - return log_oom(); + _cleanup_free_ char16_t *target = NULL; + size_t target_size = 0; - r = efi_set_variable(EFI_VENDOR_LOADER, name, encoded, char16_strlen(encoded) * 2 + 2); + r = parse_loader_entry_target_arg(argv[1], &target, &target_size); + if (r < 0) + return r; + r = efi_set_variable(EFI_VENDOR_LOADER, name, target, target_size); if (r < 0) - return log_error_errno(r, "Failed to update EFI variable: %m"); + return log_error_errno(r, "Failed to update EFI variable '%s': %m", name); } return 0;