bootctl: optionally include backing disk name in efi boot option description
This commit is contained in:
@@ -524,6 +524,18 @@
|
||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--efi-boot-option-description-with-device=</option></term>
|
||||
<listitem><para>Takes a boolean, defaults to false. Controls whether to append disk model information
|
||||
to the firmware boot option item description (as configured with
|
||||
<option>--efi-boot-option-description=</option> above). This is useful when installing multiple
|
||||
operating systems on separate disks on the same system, as it ensures the firmware boot options are discernable
|
||||
and give a hint which disk is booted into. Note that this uses hardware model information, and hence
|
||||
might not be too useful in case multiple disks of an identical model are used.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--dry-run</option></term>
|
||||
<listitem><para>Dry run for <option>unlink</option> and <option>cleanup</option>.</para>
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-device.h"
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "boot-entry.h"
|
||||
#include "bootctl.h"
|
||||
#include "bootctl-install.h"
|
||||
@@ -1321,8 +1323,56 @@ static int remove_from_order(uint16_t slot) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *pick_efi_boot_option_description(void) {
|
||||
return arg_efi_boot_option_description ?: "Linux Boot Manager";
|
||||
static int pick_efi_boot_option_description(int esp_fd, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(esp_fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
/* early declarations, so that they are definitely initialized even if we follow any of the gotos */
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
_cleanup_free_ char *j = NULL;
|
||||
|
||||
const char *b = arg_efi_boot_option_description ?: "Linux Boot Manager";
|
||||
if (!arg_efi_boot_option_description_with_device)
|
||||
goto fallback;
|
||||
|
||||
r = block_device_new_from_fd(
|
||||
esp_fd,
|
||||
BLOCK_DEVICE_LOOKUP_WHOLE_DISK|BLOCK_DEVICE_LOOKUP_BACKING,
|
||||
&d);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to find backing device of ESP: %m");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
const char *serial;
|
||||
r = sd_device_get_property_value(d, "ID_SERIAL", &serial);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Unable to read ID_SERIAL field of backing device of ESP: %m");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
j = strjoin(b, " (", serial, ")");
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
if (strlen(j) > EFI_BOOT_OPTION_DESCRIPTION_MAX) {
|
||||
log_debug("Boot option string suffixed with device serial would be too long, skipping: %s", j);
|
||||
j = mfree(j);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(j);
|
||||
return 0;
|
||||
|
||||
fallback:
|
||||
j = strdup(b);
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
*ret = TAKE_PTR(j);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int install_variables(
|
||||
@@ -1369,9 +1419,15 @@ static int install_variables(
|
||||
bool existing = r > 0;
|
||||
|
||||
if (c->operation == INSTALL_NEW || !existing) {
|
||||
_cleanup_free_ char *description = NULL;
|
||||
|
||||
r = pick_efi_boot_option_description(esp_fd, &description);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = efi_add_boot_option(
|
||||
slot,
|
||||
pick_efi_boot_option_description(),
|
||||
description,
|
||||
c->esp_part,
|
||||
c->esp_pstart,
|
||||
c->esp_psize,
|
||||
@@ -1388,7 +1444,7 @@ static int install_variables(
|
||||
|
||||
log_info("%s EFI boot entry \"%s\".",
|
||||
existing ? "Updated" : "Created",
|
||||
pick_efi_boot_option_description());
|
||||
description);
|
||||
}
|
||||
|
||||
return insert_into_order(c, slot);
|
||||
|
||||
+46
-42
@@ -40,12 +40,6 @@
|
||||
#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 GracefulMode _arg_graceful = ARG_GRACEFUL_NO;
|
||||
|
||||
char *arg_esp_path = NULL;
|
||||
@@ -70,6 +64,7 @@ char *arg_root = NULL;
|
||||
char *arg_image = NULL;
|
||||
InstallSource arg_install_source = INSTALL_SOURCE_AUTO;
|
||||
char *arg_efi_boot_option_description = NULL;
|
||||
bool arg_efi_boot_option_description_with_device = false;
|
||||
bool arg_dry_run = false;
|
||||
ImagePolicy *arg_image_policy = NULL;
|
||||
bool arg_varlink = false;
|
||||
@@ -349,6 +344,8 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" Install all supported EFI architectures\n"
|
||||
" --efi-boot-option-description=DESCRIPTION\n"
|
||||
" Description of the entry in the boot option list\n"
|
||||
" --efi-boot-option-description-with-device=yes\n"
|
||||
" Suffix description with disk vendor/model/serial\n"
|
||||
" --dry-run Dry run (unlink and cleanup)\n"
|
||||
" --secure-boot-auto-enroll=yes|no\n"
|
||||
" Set up secure boot auto-enrollment\n"
|
||||
@@ -398,6 +395,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_JSON,
|
||||
ARG_ARCH_ALL,
|
||||
ARG_EFI_BOOT_OPTION_DESCRIPTION,
|
||||
ARG_EFI_BOOT_OPTION_DESCRIPTION_WITH_DEVICE,
|
||||
ARG_DRY_RUN,
|
||||
ARG_PRINT_LOADER_PATH,
|
||||
ARG_PRINT_STUB_PATH,
|
||||
@@ -409,39 +407,40 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
};
|
||||
|
||||
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 },
|
||||
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
|
||||
{ "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' },
|
||||
{ "print-loader-path", no_argument, NULL, ARG_PRINT_LOADER_PATH },
|
||||
{ "print-stub-path", no_argument, NULL, ARG_PRINT_STUB_PATH },
|
||||
{ "print-root-device", no_argument, NULL, 'R' },
|
||||
{ "variables", required_argument, NULL, ARG_VARIABLES },
|
||||
{ "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, /* Compatibility alias */
|
||||
{ "random-seed", required_argument, NULL, ARG_RANDOM_SEED },
|
||||
{ "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 },
|
||||
{ "dry-run", no_argument, NULL, ARG_DRY_RUN },
|
||||
{ "secure-boot-auto-enroll", required_argument, NULL, ARG_SECURE_BOOT_AUTO_ENROLL },
|
||||
{ "certificate", required_argument, NULL, ARG_CERTIFICATE },
|
||||
{ "certificate-source", required_argument, NULL, ARG_CERTIFICATE_SOURCE },
|
||||
{ "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
|
||||
{ "private-key-source", required_argument, NULL, ARG_PRIVATE_KEY_SOURCE },
|
||||
{ "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 },
|
||||
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
|
||||
{ "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' },
|
||||
{ "print-loader-path", no_argument, NULL, ARG_PRINT_LOADER_PATH },
|
||||
{ "print-stub-path", no_argument, NULL, ARG_PRINT_STUB_PATH },
|
||||
{ "print-root-device", no_argument, NULL, 'R' },
|
||||
{ "variables", required_argument, NULL, ARG_VARIABLES },
|
||||
{ "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, /* Compatibility alias */
|
||||
{ "random-seed", required_argument, NULL, ARG_RANDOM_SEED },
|
||||
{ "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 },
|
||||
{ "efi-boot-option-description-with-device", required_argument, NULL, ARG_EFI_BOOT_OPTION_DESCRIPTION_WITH_DEVICE },
|
||||
{ "dry-run", no_argument, NULL, ARG_DRY_RUN },
|
||||
{ "secure-boot-auto-enroll", required_argument, NULL, ARG_SECURE_BOOT_AUTO_ENROLL },
|
||||
{ "certificate", required_argument, NULL, ARG_CERTIFICATE },
|
||||
{ "certificate-source", required_argument, NULL, ARG_CERTIFICATE_SOURCE },
|
||||
{ "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
|
||||
{ "private-key-source", required_argument, NULL, ARG_PRIVATE_KEY_SOURCE },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -577,9 +576,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
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);
|
||||
_cleanup_free_ char *escaped = cescape(optarg);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid --efi-boot-option-description=: %s", strna(escaped));
|
||||
}
|
||||
@@ -592,6 +589,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_EFI_BOOT_OPTION_DESCRIPTION_WITH_DEVICE:
|
||||
r = parse_boolean_argument("--efi-boot-option-description-with-device=", optarg, &arg_efi_boot_option_description_with_device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_DRY_RUN:
|
||||
arg_dry_run = true;
|
||||
break;
|
||||
|
||||
@@ -37,6 +37,7 @@ extern char *arg_root;
|
||||
extern char *arg_image;
|
||||
extern InstallSource arg_install_source;
|
||||
extern char *arg_efi_boot_option_description;
|
||||
extern bool arg_efi_boot_option_description_with_device;
|
||||
extern bool arg_dry_run;
|
||||
extern ImagePolicy *arg_image_policy;
|
||||
extern bool arg_varlink;
|
||||
@@ -59,3 +60,9 @@ int acquire_esp(int unprivileged_mode, bool graceful, uint32_t *ret_part, uint64
|
||||
int acquire_xbootldr(int unprivileged_mode, sd_id128_t *ret_uuid, dev_t *ret_devid);
|
||||
|
||||
bool touch_variables(void);
|
||||
|
||||
/* 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)
|
||||
|
||||
Reference in New Issue
Block a user