]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: add @current/@oneshot/@default targets to set-default/set-oneshot
authorДамјан Георгиевски <gdamjan@gmail.com>
Tue, 13 Oct 2020 10:25:59 +0000 (12:25 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Oct 2020 13:02:58 +0000 (15:02 +0200)
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.

man/bootctl.xml
src/boot/bootctl.c

index d908d52d972f7c9173b5010ccc46ad41c6cb7fe6..479cbb5d92bc8e704f6358b018dc2c3902159255 100644 (file)
         <listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string 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></listitem>
+
+        <listitem><para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
+        <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://systemd.io/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></listitem>
       </varlistentry>
 
     </variablelist>
index 0e24f0a499a58c0c4da9dbe46fd7f762db9e71d5..bb8c7398f048182fb31b7b229f812c4902cb491a 100644 (file)
@@ -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;