]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Add --efi-boot-option-description argument to bootctl to control the name of the...
authorRene Hollander <mail@renehollander.at>
Sat, 13 Aug 2022 19:38:02 +0000 (21:38 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 19 Aug 2022 12:55:31 +0000 (14:55 +0200)
entry.

By default an entry named "Linux Boot Manager" is created (which is the
previous behavior). With the flag the name of the entry can be
controlled, which is useful when installing systemd-boot to multiple ESP
partitions and having uniquely named entries.

Fixes #17044.

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

index 1664f68157a2adb0c2d1a39d70cd16484ef68976..85820ff6068243a92aa1e8fa5090e34d0f7d3dd0 100644 (file)
         <listitem><para>Install binaries for all supported EFI architectures (this implies <option>--no-variables</option>).</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--efi-boot-option-description=</option></term>
+        <listitem><para>Description of the entry added to the firmware's boot option list. Defaults to <literal>Linux
+        Boot Manager</literal>.</para>
+
+        <para>Using the default entry name <literal>Linux Boot Manager</literal> is generally preferable as only
+        one bootloader installed to a single ESP partition should be used to boot any number of OS installations
+        found on the various disks installed in the system. Specifically distributions should not use this flag
+        to install a branded entry in the boot option list. However in situations with multiple disks, each with
+        their own ESP partition, it can be beneficial to make it easier to identify the bootloader being used in
+        the firmware's boot option menu.</para></listitem>
+      </varlistentry>
+
       <xi:include href="standard-options.xml" xpointer="no-pager"/>
       <xi:include href="standard-options.xml" xpointer="json" />
       <xi:include href="standard-options.xml" xpointer="help"/>
index 10da1c8d7f2973bae0de00fd60d4f7157c4e31e5..ddeeed0c3d0f989dbf211ccca46b2fb0eb0bfffc 100644 (file)
 #include "verbs.h"
 #include "virt.h"
 
+/* EFI_BOOT_OPTION_DESCRIPTION_MAX sets the maximum length for the boot option description
+ * stored in NVRAM. The UEFI spec does not specify a minimum or maximum length for this
+ * string, but we limit the length to something reasonable to prevent from the firmware
+ * having to deal with a potentially too long string. */
+#define EFI_BOOT_OPTION_DESCRIPTION_MAX ((size_t) 255)
+
 static char *arg_esp_path = NULL;
 static char *arg_xbootldr_path = NULL;
 static bool arg_print_esp_path = false;
@@ -85,6 +91,7 @@ static enum {
         ARG_INSTALL_SOURCE_HOST,
         ARG_INSTALL_SOURCE_AUTO,
 } arg_install_source = ARG_INSTALL_SOURCE_AUTO;
+static char *arg_efi_boot_option_description = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
@@ -92,12 +99,17 @@ STATIC_DESTRUCTOR_REGISTER(arg_install_layout, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_efi_boot_option_description, freep);
 
 static const char *arg_dollar_boot_path(void) {
         /* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */
         return arg_xbootldr_path ?: arg_esp_path;
 }
 
+static const char *pick_efi_boot_option_description(void) {
+        return arg_efi_boot_option_description ?: "Linux Boot Manager";
+}
+
 static int acquire_esp(
                 bool unprivileged_mode,
                 bool graceful,
@@ -321,7 +333,7 @@ static int settle_entry_token(void) {
                 break;
         }
 
-        if (isempty(arg_entry_token) || !string_is_safe(arg_entry_token))
+        if (isempty(arg_entry_token) || !(utf8_is_valid(arg_entry_token) && string_is_safe(arg_entry_token)))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Selected entry token not valid: %s", arg_entry_token);
 
         log_debug("Using entry token: %s", arg_entry_token);
@@ -1139,13 +1151,13 @@ static int install_variables(const char *esp_path,
                                        "Failed to determine current boot order: %m");
 
         if (first || r == 0) {
-                r = efi_add_boot_option(slot, "Linux Boot Manager",
+                r = efi_add_boot_option(slot, pick_efi_boot_option_description(),
                                         part, pstart, psize,
                                         uuid, path);
                 if (r < 0)
                         return log_error_errno(r, "Failed to create EFI Boot variable entry: %m");
 
-                log_info("Created EFI boot entry \"Linux Boot Manager\".");
+                log_info("Created EFI boot entry \"%s\".", pick_efi_boot_option_description());
         }
 
         return insert_into_order(slot, first);
@@ -1465,6 +1477,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "                       Generate JSON output\n"
                "     --all-architectures\n"
                "                       Install all supported EFI architectures\n"
+               "     --efi-boot-option-description=DESCRIPTION\n"
+               "                       Description of the entry in the boot option list\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
@@ -1491,29 +1505,31 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ENTRY_TOKEN,
                 ARG_JSON,
                 ARG_ARCH_ALL,
+                ARG_EFI_BOOT_OPTION_DESCRIPTION,
         };
 
         static const struct option options[] = {
-                { "help",                      no_argument,       NULL, 'h'                           },
-                { "version",                   no_argument,       NULL, ARG_VERSION                   },
-                { "esp-path",                  required_argument, NULL, ARG_ESP_PATH                  },
-                { "path",                      required_argument, NULL, ARG_ESP_PATH                  }, /* Compatibility alias */
-                { "boot-path",                 required_argument, NULL, ARG_BOOT_PATH                 },
-                { "root",                      required_argument, NULL, ARG_ROOT                      },
-                { "image",                     required_argument, NULL, ARG_IMAGE                     },
-                { "install-source",            required_argument, NULL, ARG_INSTALL_SOURCE            },
-                { "print-esp-path",            no_argument,       NULL, 'p'                           },
-                { "print-path",                no_argument,       NULL, 'p'                           }, /* Compatibility alias */
-                { "print-boot-path",           no_argument,       NULL, 'x'                           },
-                { "no-variables",              no_argument,       NULL, ARG_NO_VARIABLES              },
-                { "no-pager",                  no_argument,       NULL, ARG_NO_PAGER                  },
-                { "graceful",                  no_argument,       NULL, ARG_GRACEFUL                  },
-                { "quiet",                     no_argument,       NULL, 'q'                           },
-                { "make-entry-directory",      required_argument, NULL, ARG_MAKE_ENTRY_DIRECTORY      },
-                { "make-machine-id-directory", required_argument, NULL, ARG_MAKE_ENTRY_DIRECTORY      }, /* Compatibility alias */
-                { "entry-token",               required_argument, NULL, ARG_ENTRY_TOKEN               },
-                { "json",                      required_argument, NULL, ARG_JSON                      },
-                { "all-architectures",         no_argument,       NULL, ARG_ARCH_ALL                  },
+                { "help",                        no_argument,       NULL, 'h'                             },
+                { "version",                     no_argument,       NULL, ARG_VERSION                     },
+                { "esp-path",                    required_argument, NULL, ARG_ESP_PATH                    },
+                { "path",                        required_argument, NULL, ARG_ESP_PATH                    }, /* Compatibility alias */
+                { "boot-path",                   required_argument, NULL, ARG_BOOT_PATH                   },
+                { "root",                        required_argument, NULL, ARG_ROOT                        },
+                { "image",                       required_argument, NULL, ARG_IMAGE                       },
+                { "install-source",              required_argument, NULL, ARG_INSTALL_SOURCE              },
+                { "print-esp-path",              no_argument,       NULL, 'p'                             },
+                { "print-path",                  no_argument,       NULL, 'p'                             }, /* Compatibility alias */
+                { "print-boot-path",             no_argument,       NULL, 'x'                             },
+                { "no-variables",                no_argument,       NULL, ARG_NO_VARIABLES                },
+                { "no-pager",                    no_argument,       NULL, ARG_NO_PAGER                    },
+                { "graceful",                    no_argument,       NULL, ARG_GRACEFUL                    },
+                { "quiet",                       no_argument,       NULL, 'q'                             },
+                { "make-entry-directory",        required_argument, NULL, ARG_MAKE_ENTRY_DIRECTORY        },
+                { "make-machine-id-directory",   required_argument, NULL, ARG_MAKE_ENTRY_DIRECTORY        }, /* Compatibility alias */
+                { "entry-token",                 required_argument, NULL, ARG_ENTRY_TOKEN                 },
+                { "json",                        required_argument, NULL, ARG_JSON                        },
+                { "all-architectures",           no_argument,       NULL, ARG_ARCH_ALL                    },
+                { "efi-boot-option-description", required_argument, NULL, ARG_EFI_BOOT_OPTION_DESCRIPTION },
                 {}
         };
 
@@ -1647,6 +1663,22 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_arch_all = true;
                         break;
 
+                case ARG_EFI_BOOT_OPTION_DESCRIPTION:
+                        if (isempty(optarg) || !(string_is_safe(optarg) && utf8_is_valid(optarg))) {
+                                _cleanup_free_ char *escaped = NULL;
+
+                                escaped = cescape(optarg);
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Invalid --efi-boot-option-description=: %s", strna(escaped));
+                        }
+                        if (strlen(optarg) > EFI_BOOT_OPTION_DESCRIPTION_MAX)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "--efi-boot-option-description= too long: %zu > %zu", strlen(optarg), EFI_BOOT_OPTION_DESCRIPTION_MAX);
+                        r = free_and_strdup_warn(&arg_efi_boot_option_description, optarg);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case '?':
                         return -EINVAL;