bootctl parts of installer PR (#40447)

This contains the "bootctl install" related work from the #38764 split
out, but also includes the preparatory work already split out into
#40446.

I'll rebase this PR once the prep work is merged.

This has a simple CI test already, and has docs
This commit is contained in:
Daan De Meyer
2026-02-09 09:46:39 +01:00
committed by GitHub
13 changed files with 1328 additions and 475 deletions

View File

@@ -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>

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "shared-forward.h"
int verb_install(int argc, char *argv[], void *userdata);
int verb_remove(int argc, char *argv[], void *userdata);
int verb_is_installed(int argc, char *argv[], void *userdata);
int vl_method_install(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);

View File

@@ -75,6 +75,8 @@ int get_file_version(int fd, char **ret) {
assert(fd >= 0);
assert(ret);
/* Does not reposition file offset (as it uses mmap()) */
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to stat EFI binary: %m");

View File

@@ -31,6 +31,7 @@
#include "parse-argument.h"
#include "path-util.h"
#include "pretty-print.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
@@ -39,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;
@@ -69,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;
@@ -93,6 +89,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_certificate_source, freep);
STATIC_DESTRUCTOR_REGISTER(arg_private_key, freep);
STATIC_DESTRUCTOR_REGISTER(arg_private_key_source, freep);
static const char* const install_source_table[_INSTALL_SOURCE_MAX] = {
[INSTALL_SOURCE_IMAGE] = "image",
[INSTALL_SOURCE_HOST] = "host",
[INSTALL_SOURCE_AUTO] = "auto",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(install_source, InstallSource);
int acquire_esp(
int unprivileged_mode,
bool graceful,
@@ -340,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"
@@ -389,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,
@@ -400,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 },
{}
};
@@ -481,18 +489,14 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
case ARG_INSTALL_SOURCE:
if (streq(optarg, "auto"))
arg_install_source = INSTALL_SOURCE_AUTO;
else if (streq(optarg, "image"))
arg_install_source = INSTALL_SOURCE_IMAGE;
else if (streq(optarg, "host"))
arg_install_source = INSTALL_SOURCE_HOST;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unexpected parameter for --install-source=: %s", optarg);
case ARG_INSTALL_SOURCE: {
InstallSource is = install_source_from_string(optarg);
if (is < 0)
return log_error_errno(is, "Unexpected parameter for --install-source=: %s", optarg);
arg_install_source = is;
break;
}
case 'p':
arg_print_esp_path = true;
@@ -572,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));
}
@@ -587,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;
@@ -711,7 +720,7 @@ static int vl_server(void) {
r = varlink_server_new(
&varlink_server,
SD_VARLINK_SERVER_ROOT_ONLY,
SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_ALLOW_FD_PASSING_INPUT,
/* userdata= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
@@ -724,7 +733,8 @@ static int vl_server(void) {
varlink_server,
"io.systemd.BootControl.ListBootEntries", vl_method_list_boot_entries,
"io.systemd.BootControl.SetRebootToFirmware", vl_method_set_reboot_to_firmware,
"io.systemd.BootControl.GetRebootToFirmware", vl_method_get_reboot_to_firmware);
"io.systemd.BootControl.GetRebootToFirmware", vl_method_get_reboot_to_firmware,
"io.systemd.BootControl.Install", vl_method_install);
if (r < 0)
return log_error_errno(r, "Failed to bind Varlink methods: %m");

View File

@@ -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)

View File

@@ -155,6 +155,8 @@ int boot_entry_token_ensure_at(
assert(type);
assert(token);
/* Returns -EUNATCH if the selected token is not set */
if (*token)
return 0; /* Already set. */
@@ -181,7 +183,7 @@ int boot_entry_token_ensure_at(
return r;
}
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH),
"No machine ID set, and /etc/os-release carries no ID=/IMAGE_ID= fields.");
case BOOT_ENTRY_TOKEN_MACHINE_ID:
@@ -189,14 +191,14 @@ int boot_entry_token_ensure_at(
if (r != 0)
return r;
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No machine ID set.");
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH), "No machine ID set.");
case BOOT_ENTRY_TOKEN_OS_IMAGE_ID:
r = entry_token_from_os_release(rfd, type, token);
if (r != 0)
return r;
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH),
"IMAGE_ID= field not set in /etc/os-release.");
case BOOT_ENTRY_TOKEN_OS_ID:
@@ -204,12 +206,12 @@ int boot_entry_token_ensure_at(
if (r != 0)
return r;
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH),
"ID= field not set in /etc/os-release.");
case BOOT_ENTRY_TOKEN_LITERAL:
/* In this case, the token should be already set by the user input. */
return -EINVAL;
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH), "Literal token indicated but not specified.");
default:
assert_not_reached();
@@ -291,4 +293,4 @@ static const char *const boot_entry_token_type_table[] = {
[BOOT_ENTRY_TOKEN_AUTO] = "auto",
};
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_token_type, BootEntryTokenType);
DEFINE_STRING_TABLE_LOOKUP(boot_entry_token_type, BootEntryTokenType);

View File

@@ -34,4 +34,4 @@ int boot_entry_token_ensure_at(
int parse_boot_entry_token_type(const char *s, BootEntryTokenType *type, char **token);
DECLARE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_token_type, BootEntryTokenType);
DECLARE_STRING_TABLE_LOOKUP(boot_entry_token_type, BootEntryTokenType);

View File

@@ -12,6 +12,8 @@
#include "string-table.h"
#include "string-util.h"
/* Note: none of these function change the file position of the provided fd, as they use pread() */
bool pe_header_is_64bit(const PeHeader *h) {
assert(h);

View File

@@ -36,21 +36,37 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD_BY_TYPE(source, BootEntrySource, 0),
SD_VARLINK_FIELD_COMMENT("The string identifier of the entry"),
SD_VARLINK_DEFINE_FIELD(id, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the primary definition file for the entry"),
SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Directory path of the file system root the entry was found on"),
SD_VARLINK_DEFINE_FIELD(root, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The entry's title string"),
SD_VARLINK_DEFINE_FIELD(title, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The possibly mangled/augmented title to show for the entry"),
SD_VARLINK_DEFINE_FIELD(showTitle, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("An explicitly configured sorting key for the enry"),
SD_VARLINK_DEFINE_FIELD(sortKey, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The version of the entry"),
SD_VARLINK_DEFINE_FIELD(version, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Machine ID of the OS installation belonging to the entry, if known"),
SD_VARLINK_DEFINE_FIELD(machineId, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("EFI architecture name for this entry"),
SD_VARLINK_DEFINE_FIELD(architecture, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Command line options to pass to the invoked kernel or EFI binary"),
SD_VARLINK_DEFINE_FIELD(options, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the Linux kernel to invoke, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(linux, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the EFI binary to invoke, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(efi, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to an UKI EFI binary to invoke, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(uki, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("An UKI profile index to invoke. If not specified defaults to the first profile."),
SD_VARLINK_DEFINE_FIELD(profile, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the initrd image to pass to the invoked kernel, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(initrd, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("Devicetree file to pass to the invoked kernel, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(devicetree, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Devicetree overlay file to pass to the invoked kernel, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(devicetreeOverlay, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("Indicates whether the boot loader reported this entry on the current boot"),
SD_VARLINK_DEFINE_FIELD(isReported, SD_VARLINK_BOOL, 0),
@@ -83,12 +99,53 @@ static SD_VARLINK_DEFINE_METHOD(
SD_VARLINK_FIELD_COMMENT("The current state of the reboot-to-firmware-UI flag"),
SD_VARLINK_DEFINE_OUTPUT(state, SD_VARLINK_BOOL, 0));
static SD_VARLINK_DEFINE_ENUM_TYPE(
Operation,
SD_VARLINK_FIELD_COMMENT("Install the boot loader afresh, creating everything it needs"),
SD_VARLINK_DEFINE_ENUM_VALUE(new),
SD_VARLINK_FIELD_COMMENT("Just update existing boot loader binaries"),
SD_VARLINK_DEFINE_ENUM_VALUE(update));
static SD_VARLINK_DEFINE_ENUM_TYPE(
BootEntryTokenType,
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on /etc/machine-id"),
SD_VARLINK_DEFINE_ENUM_VALUE(machine_id),
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on the IMAGE_ID= field from /etc/os-release"),
SD_VARLINK_DEFINE_ENUM_VALUE(os_image_id),
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on the ID= field from /etc/os-release"),
SD_VARLINK_DEFINE_ENUM_VALUE(os_id),
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on a manually chosen string"),
SD_VARLINK_DEFINE_ENUM_VALUE(literal),
SD_VARLINK_FIELD_COMMENT("Choose automatically how to pick identifiers for type #1 boot entries"),
SD_VARLINK_DEFINE_ENUM_VALUE(auto));
static SD_VARLINK_DEFINE_METHOD(
Install,
SD_VARLINK_FIELD_COMMENT("Operation, either 'new' or 'update'"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(operation, Operation, 0),
SD_VARLINK_FIELD_COMMENT("If true, continue on various failures"),
SD_VARLINK_DEFINE_INPUT(graceful, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Index into array of file descriptors passed along with this message, pointing to file descriptor to root file system to operate on"),
SD_VARLINK_DEFINE_INPUT(rootFileDescriptor, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Root directory to operate relative to. If both this and rootFileDescriptor is specified, this is purely informational. If only this is specified, it is what will be used."),
SD_VARLINK_DEFINE_INPUT(rootDirectory, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Selects how to identify boot entries"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(bootEntryTokenType, BootEntryTokenType, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("If true the boot loader will be registered in an EFI boot entry via EFI variables, otherwise this is omitted"),
SD_VARLINK_DEFINE_INPUT(touchVariables, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_ERROR(
RebootToFirmwareNotSupported);
static SD_VARLINK_DEFINE_ERROR(
NoSuchBootEntry);
static SD_VARLINK_DEFINE_ERROR(
NoESPFound);
static SD_VARLINK_DEFINE_ERROR(
BootEntryTokenUnavailable);
SD_VARLINK_DEFINE_INTERFACE(
io_systemd_BootControl,
"io.systemd.BootControl",
@@ -101,13 +158,23 @@ SD_VARLINK_DEFINE_INTERFACE(
&vl_type_BootEntryAddon,
SD_VARLINK_SYMBOL_COMMENT("A structure encapsulating a boot entry"),
&vl_type_BootEntry,
SD_VARLINK_SYMBOL_COMMENT("The operation to execute"),
&vl_type_Operation,
SD_VARLINK_SYMBOL_COMMENT("Enumerates boot entries. Method call must be called with 'more' flag set. Each response returns one entry. If no entries are defined returns the NoSuchBootEntry error."),
&vl_method_ListBootEntries,
SD_VARLINK_SYMBOL_COMMENT("Sets the reboot-to-firmware-UI flag of the firmware, if this concept exists. Returns the RebootToFirmwareNotSupported error if not."),
&vl_method_SetRebootToFirmware,
SD_VARLINK_SYMBOL_COMMENT("Gets the current state of the reboot-to-firmware-UI flag of the firmware, if this concept exists. Returns the RebootToFirmwareNotSupported error if not."),
&vl_method_GetRebootToFirmware,
SD_VARLINK_SYMBOL_COMMENT("The boot entry token type to use."),
&vl_type_BootEntryTokenType,
SD_VARLINK_SYMBOL_COMMENT("Install the boot loader on the ESP."),
&vl_method_Install,
SD_VARLINK_SYMBOL_COMMENT("SetRebootToFirmware() and GetRebootToFirmware() return this if the firmware does not actually support the reboot-to-firmware-UI concept."),
&vl_error_RebootToFirmwareNotSupported,
SD_VARLINK_SYMBOL_COMMENT("No boot entry defined."),
&vl_error_NoSuchBootEntry);
&vl_error_NoSuchBootEntry,
SD_VARLINK_SYMBOL_COMMENT("No EFI System Partition (ESP) found."),
&vl_error_NoESPFound,
SD_VARLINK_SYMBOL_COMMENT("The select boot entry token could not be determined."),
&vl_error_BootEntryTokenUnavailable);

View File

@@ -27,9 +27,11 @@ restore_esp() {
fi
if [ -d /tmp/esp.bak/EFI/ ]; then
mkdir -p "$(bootctl --print-esp-path)/EFI/"
cp -r /tmp/esp.bak/EFI/* "$(bootctl --print-esp-path)/EFI/"
fi
if [ -d /tmp/esp.bak/loader/ ]; then
mkdir -p "$(bootctl --print-esp-path)/loader/"
cp -r /tmp/esp.bak/loader/* "$(bootctl --print-esp-path)/loader/"
fi
rm -rf /tmp/esp.bak
@@ -40,13 +42,19 @@ backup_esp() {
return
fi
# make a backup of the two key dirs in the ESP, and delete them
if [[ -d "$(bootctl --print-esp-path)/EFI" ]]; then
mkdir -p /tmp/esp.bak
cp -r "$(bootctl --print-esp-path)/EFI/" /tmp/esp.bak/
rm -rf "$(bootctl --print-esp-path)/EFI"
mkdir "$(bootctl --print-esp-path)/EFI"
fi
if [[ -d "$(bootctl --print-esp-path)/loader" ]]; then
mkdir -p /tmp/esp.bak
cp -r "$(bootctl --print-esp-path)/loader/" /tmp/esp.bak/
rm -rf "$(bootctl --print-esp-path)/loader"
mkdir "$(bootctl --print-esp-path)/loader"
fi
}
@@ -364,4 +372,22 @@ testcase_00_secureboot() {
grep -q addonfoobar /proc/cmdline
}
remove_root_dir() {
rm -rf "$ROOTDIR"
}
testcase_install_varlink() {
varlinkctl introspect "$(type -p bootctl)"
if [ $# -eq 0 ]; then
backup_esp
trap restore_esp RETURN ERR
fi
(! bootctl is-installed )
SYSTEMD_LOG_TARGET=console varlinkctl call "$(type -p bootctl)" io.systemd.BootControl.Install "{\"operation\":\"new\",\"touchVariables\":false}"
bootctl is-installed
}
run_testcases

View File

@@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
Description=Boot Entries Service Socket
Description=Boot Loader Control Service Socket
Documentation=man:bootctl(1)
DefaultDependencies=no
After=local-fs.target

View File

@@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
Description=Boot Entries Service
Description=Boot Loader Control Service
Documentation=man:bootctl(1)
DefaultDependencies=no
Conflicts=shutdown.target