1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-10 05:18:17 +03:00

Merge pull request #31286 from poettering/bootctl-varlink

bootctl: add simple varlink IPC interface
This commit is contained in:
Luca Boccassi 2024-02-14 18:59:33 +00:00 committed by GitHub
commit 76995e7dc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 351 additions and 43 deletions

View File

@ -2,6 +2,7 @@
#include "bootctl-reboot-to-firmware.h"
#include "efi-api.h"
#include "errno-util.h"
#include "parse-util.h"
int verb_reboot_to_firmware(int argc, char *argv[], void *userdata) {
@ -17,7 +18,7 @@ int verb_reboot_to_firmware(int argc, char *argv[], void *userdata) {
puts("supported");
return 1; /* recognizable error #1 */
}
if (r == -EOPNOTSUPP) {
if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) {
puts("not supported");
return 2; /* recognizable error #2 */
}
@ -36,3 +37,39 @@ int verb_reboot_to_firmware(int argc, char *argv[], void *userdata) {
return 0;
}
}
int vl_method_set_reboot_to_firmware(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
static const JsonDispatch dispatch_table[] = {
{ "state", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, 0, 0 },
{}
};
bool b;
int r;
r = varlink_dispatch(link, parameters, dispatch_table, &b);
if (r != 0)
return r;
r = efi_set_reboot_to_firmware(b);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return varlink_error(link, "io.systemd.BootControl.RebootToFirmwareNotSupported", NULL);
if (r < 0)
return r;
return varlink_reply(link, NULL);
}
int vl_method_get_reboot_to_firmware(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
int r;
if (json_variant_elements(parameters) > 0)
return varlink_error_invalid_parameter(link, parameters);
r = efi_get_reboot_to_firmware();
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return varlink_error(link, "io.systemd.BootControl.RebootToFirmwareNotSupported", NULL);
if (r < 0)
return r;
return varlink_replyb(link, JSON_BUILD_OBJECT(JSON_BUILD_PAIR_BOOLEAN("state", r)));
}

View File

@ -1,3 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "varlink.h"
int verb_reboot_to_firmware(int argc, char *argv[], void *userdata);
int vl_method_set_reboot_to_firmware(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
int vl_method_get_reboot_to_firmware(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);

View File

@ -318,7 +318,13 @@ int verb_status(int argc, char *argv[], void *userdata) {
dev_t esp_devid = 0, xbootldr_devid = 0;
int r, k;
r = acquire_esp(/* unprivileged_mode= */ -1, /* graceful= */ false, NULL, NULL, NULL, &esp_uuid, &esp_devid);
r = acquire_esp(/* unprivileged_mode= */ -1,
/* graceful= */ false,
/* ret_part= */ NULL,
/* ret_pstart= */ NULL,
/* ret_psize= */ NULL,
&esp_uuid,
&esp_devid);
if (arg_print_esp_path) {
if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only
* error the find_esp_and_warn() won't log on its own) */
@ -330,7 +336,10 @@ int verb_status(int argc, char *argv[], void *userdata) {
return 0;
}
r = acquire_xbootldr(/* unprivileged_mode= */ -1, &xbootldr_uuid, &xbootldr_devid);
r = acquire_xbootldr(
/* unprivileged_mode= */ -1,
&xbootldr_uuid,
&xbootldr_devid);
if (arg_print_dollar_boot_path) {
if (r == -EACCES)
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
@ -825,3 +834,58 @@ int verb_list(int argc, char *argv[], void *userdata) {
int verb_unlink(int argc, char *argv[], void *userdata) {
return verb_list(argc, argv, userdata);
}
int vl_method_list_boot_entries(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
dev_t esp_devid = 0, xbootldr_devid = 0;
int r;
assert(link);
if (json_variant_elements(parameters) > 0)
return varlink_error_invalid_parameter(link, parameters);
r = acquire_esp(/* unprivileged_mode= */ false,
/* graceful= */ false,
/* ret_part= */ NULL,
/* ret_pstart= */ NULL,
/* ret_psize= */ NULL,
/* ret_uuid=*/ NULL,
&esp_devid);
if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
return log_error_errno(r, "Failed to determine ESP location: %m");
if (r < 0)
return r;
r = acquire_xbootldr(
/* unprivileged_mode= */ false,
/* ret_uuid= */ NULL,
&xbootldr_devid);
if (r == -EACCES)
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
if (r < 0)
return r;
r = boot_config_load_and_select(&config, arg_esp_path, esp_devid, arg_xbootldr_path, xbootldr_devid);
if (r < 0)
return r;
_cleanup_(json_variant_unrefp) JsonVariant *previous = NULL;
for (size_t i = 0; i < config.n_entries; i++) {
if (previous) {
r = varlink_notifyb(link, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR_VARIANT("entry", previous)));
if (r < 0)
return r;
previous = json_variant_unref(previous);
}
r = boot_entry_to_json(&config, i, &previous);
if (r < 0)
return r;
}
return varlink_replyb(link, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR_CONDITION(previous, "entry", JSON_BUILD_VARIANT(previous))));
}

View File

@ -1,5 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "varlink.h"
int verb_status(int argc, char *argv[], void *userdata);
int verb_list(int argc, char *argv[], void *userdata);
int verb_unlink(int argc, char *argv[], void *userdata);
int vl_method_list_boot_entries(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);

View File

@ -22,6 +22,8 @@
#include "parse-argument.h"
#include "pretty-print.h"
#include "utf8.h"
#include "varlink.h"
#include "varlink-io.systemd.BootControl.h"
#include "verbs.h"
#include "virt.h"
@ -53,6 +55,7 @@ InstallSource arg_install_source = ARG_INSTALL_SOURCE_AUTO;
char *arg_efi_boot_option_description = NULL;
bool arg_dry_run = false;
ImagePolicy *arg_image_policy = NULL;
bool arg_varlink = false;
STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
@ -418,6 +421,14 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_dry_run && argv[optind] && !STR_IN_SET(argv[optind], "unlink", "cleanup"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--dry is only supported with --unlink or --cleanup");
r = varlink_invocation(VARLINK_ALLOW_ACCEPT);
if (r < 0)
return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m");
if (r > 0) {
arg_varlink = true;
arg_pager_flags |= PAGER_DISABLE;
}
return 1;
}
@ -462,6 +473,34 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
if (arg_varlink) {
_cleanup_(varlink_server_unrefp) VarlinkServer *varlink_server = NULL;
/* Invocation as Varlink service */
r = varlink_server_new(&varlink_server, VARLINK_SERVER_ROOT_ONLY);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
r = varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_BootControl);
if (r < 0)
return log_error_errno(r, "Failed to add Varlink interface: %m");
r = varlink_server_bind_method_many(
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);
if (r < 0)
return log_error_errno(r, "Failed to bind Varlink methods: %m");
r = varlink_server_loop_auto(varlink_server);
if (r < 0)
return log_error_errno(r, "Failed to run Varlink event loop: %m");
return EXIT_SUCCESS;
}
if (arg_print_root_device > 0) {
_cleanup_free_ char *path = NULL;
dev_t devno;

View File

@ -36,6 +36,7 @@ extern InstallSource arg_install_source;
extern char *arg_efi_boot_option_description;
extern bool arg_dry_run;
extern ImagePolicy *arg_image_policy;
extern bool arg_varlink;
static inline const char *arg_dollar_boot_path(void) {
/* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */

View File

@ -1668,6 +1668,63 @@ int show_boot_entry(
return -status;
}
int boot_entry_to_json(const BootConfig *c, size_t i, JsonVariant **ret) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
const BootEntry *e;
int r;
assert(c);
assert(ret);
if (i >= c->n_entries) {
*ret = NULL;
return 0;
}
e = c->entries + i;
r = json_variant_merge_objectb(
&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("type", JSON_BUILD_STRING(boot_entry_type_json_to_string(e->type))),
JSON_BUILD_PAIR_CONDITION(e->id, "id", JSON_BUILD_STRING(e->id)),
JSON_BUILD_PAIR_CONDITION(e->path, "path", JSON_BUILD_STRING(e->path)),
JSON_BUILD_PAIR_CONDITION(e->root, "root", JSON_BUILD_STRING(e->root)),
JSON_BUILD_PAIR_CONDITION(e->title, "title", JSON_BUILD_STRING(e->title)),
JSON_BUILD_PAIR_CONDITION(boot_entry_title(e), "showTitle", JSON_BUILD_STRING(boot_entry_title(e))),
JSON_BUILD_PAIR_CONDITION(e->sort_key, "sortKey", JSON_BUILD_STRING(e->sort_key)),
JSON_BUILD_PAIR_CONDITION(e->version, "version", JSON_BUILD_STRING(e->version)),
JSON_BUILD_PAIR_CONDITION(e->machine_id, "machineId", JSON_BUILD_STRING(e->machine_id)),
JSON_BUILD_PAIR_CONDITION(e->architecture, "architecture", JSON_BUILD_STRING(e->architecture)),
JSON_BUILD_PAIR_CONDITION(e->kernel, "linux", JSON_BUILD_STRING(e->kernel)),
JSON_BUILD_PAIR_CONDITION(e->efi, "efi", JSON_BUILD_STRING(e->efi)),
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", JSON_BUILD_STRV(e->initrd)),
JSON_BUILD_PAIR_CONDITION(e->device_tree, "devicetree", JSON_BUILD_STRING(e->device_tree)),
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", JSON_BUILD_STRV(e->device_tree_overlay))));
if (r < 0)
return log_oom();
/* Sanitizers (only memory sanitizer?) do not like function call with too many
* arguments and trigger false positive warnings. Let's not add too many json objects
* at once. */
r = json_variant_merge_objectb(
&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("isReported", JSON_BUILD_BOOLEAN(e->reported_by_loader)),
JSON_BUILD_PAIR_CONDITION(e->tries_left != UINT_MAX, "triesLeft", JSON_BUILD_UNSIGNED(e->tries_left)),
JSON_BUILD_PAIR_CONDITION(e->tries_done != UINT_MAX, "triesDone", JSON_BUILD_UNSIGNED(e->tries_done)),
JSON_BUILD_PAIR_CONDITION(c->default_entry >= 0, "isDefault", JSON_BUILD_BOOLEAN(i == (size_t) c->default_entry)),
JSON_BUILD_PAIR_CONDITION(c->selected_entry >= 0, "isSelected", JSON_BUILD_BOOLEAN(i == (size_t) c->selected_entry))));
if (r < 0)
return log_oom();
r = json_cmdline(e, &c->global_addons, &v);
if (r < 0)
return log_oom();
*ret = TAKE_PTR(v);
return 1;
}
int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
int r;
@ -1677,44 +1734,9 @@ int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
_cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
for (size_t i = 0; i < config->n_entries; i++) {
const BootEntry *e = config->entries + i;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
r = json_variant_merge_objectb(
&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("type", JSON_BUILD_STRING(boot_entry_type_json_to_string(e->type))),
JSON_BUILD_PAIR_CONDITION(e->id, "id", JSON_BUILD_STRING(e->id)),
JSON_BUILD_PAIR_CONDITION(e->path, "path", JSON_BUILD_STRING(e->path)),
JSON_BUILD_PAIR_CONDITION(e->root, "root", JSON_BUILD_STRING(e->root)),
JSON_BUILD_PAIR_CONDITION(e->title, "title", JSON_BUILD_STRING(e->title)),
JSON_BUILD_PAIR_CONDITION(boot_entry_title(e), "showTitle", JSON_BUILD_STRING(boot_entry_title(e))),
JSON_BUILD_PAIR_CONDITION(e->sort_key, "sortKey", JSON_BUILD_STRING(e->sort_key)),
JSON_BUILD_PAIR_CONDITION(e->version, "version", JSON_BUILD_STRING(e->version)),
JSON_BUILD_PAIR_CONDITION(e->machine_id, "machineId", JSON_BUILD_STRING(e->machine_id)),
JSON_BUILD_PAIR_CONDITION(e->architecture, "architecture", JSON_BUILD_STRING(e->architecture)),
JSON_BUILD_PAIR_CONDITION(e->kernel, "linux", JSON_BUILD_STRING(e->kernel)),
JSON_BUILD_PAIR_CONDITION(e->efi, "efi", JSON_BUILD_STRING(e->efi)),
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", JSON_BUILD_STRV(e->initrd)),
JSON_BUILD_PAIR_CONDITION(e->device_tree, "devicetree", JSON_BUILD_STRING(e->device_tree)),
JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", JSON_BUILD_STRV(e->device_tree_overlay))));
if (r < 0)
return log_oom();
r = json_cmdline(e, &config->global_addons, &v);
if (r < 0)
return log_oom();
/* Sanitizers (only memory sanitizer?) do not like function call with too many
* arguments and trigger false positive warnings. Let's not add too many json objects
* at once. */
r = json_variant_merge_objectb(
&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("isReported", JSON_BUILD_BOOLEAN(e->reported_by_loader)),
JSON_BUILD_PAIR_CONDITION(e->tries_left != UINT_MAX, "triesLeft", JSON_BUILD_UNSIGNED(e->tries_left)),
JSON_BUILD_PAIR_CONDITION(e->tries_done != UINT_MAX, "triesDone", JSON_BUILD_UNSIGNED(e->tries_done)),
JSON_BUILD_PAIR_CONDITION(config->default_entry >= 0, "isDefault", JSON_BUILD_BOOLEAN(i == (size_t) config->default_entry)),
JSON_BUILD_PAIR_CONDITION(config->selected_entry >= 0, "isSelected", JSON_BUILD_BOOLEAN(i == (size_t) config->selected_entry))));
r = boot_entry_to_json(config, i, &v);
if (r < 0)
return log_oom();
@ -1723,8 +1745,7 @@ int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
return log_oom();
}
json_variant_dump(array, json_format | JSON_FORMAT_EMPTY_ARRAY, NULL, NULL);
return json_variant_dump(array, json_format | JSON_FORMAT_EMPTY_ARRAY, NULL, NULL);
} else {
for (size_t n = 0; n < config->n_entries; n++) {
r = show_boot_entry(

View File

@ -143,3 +143,5 @@ int show_boot_entries(
JsonFormatFlags json_format);
int boot_filename_extract_tries(const char *fname, char **ret_stripped, unsigned *ret_tries_left, unsigned *ret_tries_done);
int boot_entry_to_json(const BootConfig *c, size_t i, JsonVariant **ret);

View File

@ -102,7 +102,8 @@ int efi_loader_get_entries(char ***ret) {
if (r < 0)
return r;
/* The variable contains a series of individually NUL terminated UTF-16 strings. */
/* The variable contains a series of individually NUL terminated UTF-16 strings. We gracefully
* consider the final NUL byte optional (i.e. the last string may or may not end in a NUL byte).*/
for (size_t i = 0, start = 0;; i++) {
_cleanup_free_ char *decoded = NULL;
@ -116,6 +117,11 @@ int efi_loader_get_entries(char ***ret) {
if (!end && entries[i] != 0)
continue;
/* Empty string at the end of variable? That's the trailer, we are done (i.e. we have a final
* NUL terminator). */
if (end && start == i)
break;
/* We reached the end of a string, let's decode it into UTF-8 */
decoded = utf16_to_utf8(entries + start, (i - start) * sizeof(char16_t));
if (!decoded)
@ -128,7 +134,8 @@ int efi_loader_get_entries(char ***ret) {
} else
log_debug("Ignoring invalid loader entry '%s'.", decoded);
/* We reached the end of the variable */
/* Exit the loop if we reached the end of the variable (i.e. we do not have a final NUL
* terminator) */
if (end)
break;

View File

@ -174,6 +174,7 @@ shared_sources = files(
'varlink.c',
'varlink-idl.c',
'varlink-io.systemd.c',
'varlink-io.systemd.BootControl.c',
'varlink-io.systemd.Credentials.c',
'varlink-io.systemd.Hostname.c',
'varlink-io.systemd.Journal.c',

View File

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "varlink-io.systemd.BootControl.h"
static VARLINK_DEFINE_ENUM_TYPE(
BootEntryType,
VARLINK_DEFINE_ENUM_VALUE(type1),
VARLINK_DEFINE_ENUM_VALUE(type2),
VARLINK_DEFINE_ENUM_VALUE(loader),
VARLINK_DEFINE_ENUM_VALUE(auto));
static VARLINK_DEFINE_STRUCT_TYPE(
BootEntry,
VARLINK_DEFINE_FIELD_BY_TYPE(type, BootEntryType, 0),
VARLINK_DEFINE_FIELD(id, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(path, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(root, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(title, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(showTitle, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(sortKey, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(version, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(machineId, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(architecture, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(options, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(linux, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(efi, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(initrd, VARLINK_STRING, VARLINK_NULLABLE|VARLINK_ARRAY),
VARLINK_DEFINE_FIELD(devicetree, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(devicetreeOverlay, VARLINK_STRING, VARLINK_NULLABLE|VARLINK_ARRAY),
VARLINK_DEFINE_FIELD(isReported, VARLINK_BOOL, 0),
VARLINK_DEFINE_FIELD(triesLeft, VARLINK_INT, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(triesDone, VARLINK_INT, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(isDefault, VARLINK_BOOL, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(isSelected, VARLINK_BOOL, VARLINK_NULLABLE));
static VARLINK_DEFINE_METHOD(
ListBootEntries,
VARLINK_DEFINE_OUTPUT_BY_TYPE(entry, BootEntry, VARLINK_NULLABLE));
static VARLINK_DEFINE_METHOD(
SetRebootToFirmware,
VARLINK_DEFINE_INPUT(state, VARLINK_BOOL, 0));
static VARLINK_DEFINE_METHOD(
GetRebootToFirmware,
VARLINK_DEFINE_OUTPUT(state, VARLINK_BOOL, 0));
static VARLINK_DEFINE_ERROR(
RebootToFirmwareNotSupported);
VARLINK_DEFINE_INTERFACE(
io_systemd_BootControl,
"io.systemd.BootControl",
&vl_type_BootEntryType,
&vl_type_BootEntry,
&vl_method_ListBootEntries,
&vl_method_SetRebootToFirmware,
&vl_method_GetRebootToFirmware,
&vl_error_RebootToFirmwareNotSupported);

View File

@ -0,0 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "varlink-idl.h"
extern const VarlinkInterface vl_interface_io_systemd_BootControl;

View File

@ -8,6 +8,7 @@
#include "varlink.h"
#include "varlink-idl.h"
#include "varlink-io.systemd.h"
#include "varlink-io.systemd.BootControl.h"
#include "varlink-io.systemd.Credentials.h"
#include "varlink-io.systemd.Journal.h"
#include "varlink-io.systemd.ManagedOOM.h"
@ -152,6 +153,8 @@ TEST(parse_format) {
print_separator();
test_parse_format_one(&vl_interface_io_systemd_Credentials);
print_separator();
test_parse_format_one(&vl_interface_io_systemd_BootControl);
print_separator();
test_parse_format_one(&vl_interface_xyz_test);
}

View File

@ -263,4 +263,13 @@ EOF
SYSTEMD_RELAX_ESP_CHECKS=yes SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes basic_tests --root "${IMAGE_DIR}/root"
}
testcase_bootctl_varlink() {
varlinkctl call --collect /run/systemd/io.systemd.BootControl io.systemd.BootControl.ListBootEntries '{}'
# We have no UEFI in the test environment, hence just check that this fails cleanly
( SYSTEMD_LOG_TARGET=console varlinkctl call --json=short /run/systemd/io.systemd.BootControl io.systemd.BootControl.GetRebootToFirmware '{}' 2>&1 || true ) | grep -q io.systemd.BootControl.RebootToFirmwareNotSupported
( SYSTEMD_LOG_TARGET=console varlinkctl call --json=short /run/systemd/io.systemd.BootControl io.systemd.BootControl.SetRebootToFirmware '{"state":true}' 2>&1 || true ) | grep -q io.systemd.BootControl.RebootToFirmwareNotSupported
( SYSTEMD_LOG_TARGET=console varlinkctl call --json=short /run/systemd/io.systemd.BootControl io.systemd.BootControl.SetRebootToFirmware '{"state":false}' 2>&1 || true ) | grep -q io.systemd.BootControl.RebootToFirmwareNotSupported
}
run_testcases

View File

@ -267,6 +267,15 @@ units = [
'file' : 'systemd-boot-update.service',
'conditions' : ['ENABLE_BOOTLOADER'],
},
{
'file' : 'systemd-bootctl@.service.in',
'conditions' : ['ENABLE_BOOTLOADER'],
},
{
'file' : 'systemd-bootctl.socket',
'conditions' : ['ENABLE_BOOTLOADER'],
'symlinks' : ['sockets.target.wants/'],
},
{
'file' : 'systemd-confext.service',
'conditions' : ['ENABLE_SYSEXT'],

View File

@ -0,0 +1,21 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Boot Control (Varlink)
Documentation=man:bootctl(1)
DefaultDependencies=no
After=local-fs.target
Before=sockets.target
[Socket]
ListenStream=/run/systemd/io.systemd.BootControl
FileDescriptorName=varlink
SocketMode=0600
Accept=yes

View File

@ -0,0 +1,20 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Boot Control (Varlink)
Documentation=man:bootctl(1)
DefaultDependencies=no
Conflicts=shutdown.target
After=local-fs.target
Before=shutdown.target
[Service]
Environment=LISTEN_FDNAMES=varlink
ExecStart={{BINDIR}}/bootctl