summaryrefslogtreecommitdiff
path: root/src/login
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-10-22 20:02:25 +0200
committerLennart Poettering <lennart@poettering.net>2019-03-05 16:50:58 +0100
commite667266a74d7bb3edab43ad63b5de76c6915e6b7 (patch)
tree6d60babd57702608dc2aa8114c5028555f5c6dbb /src/login
parent327969237080aaf0c2303943cb9df6dcf96f1566 (diff)
downloadsystemd-e667266a74d7bb3edab43ad63b5de76c6915e6b7.tar.gz
systemd-e667266a74d7bb3edab43ad63b5de76c6915e6b7.tar.bz2
systemd-e667266a74d7bb3edab43ad63b5de76c6915e6b7.zip
logind: optionally support non-EFI reboot-to-firmware
This extends the reboot-to-firmware logic in logind, so that other than EFI firmwares could be theoretically support. The scheme is like this: if you want to support this, set the $SYSTEMD_REBOOT_TO_FIRMWARE=1 env var for logind. If so, this will override the EFI logic, and cause a file /run/systemd/reboot-to-firmware file to be created when reboot-to-firmware is requested. This file has no contents, it's mere existance indicates a reboot with reboot-to-firmware set. The idea is that for alternative firmwares a drop-in for logind is added that sets the env var, in combination with some code run during shutdown that checks for the file and does the right thing.
Diffstat (limited to 'src/login')
-rw-r--r--src/login/logind-dbus.c97
1 files changed, 82 insertions, 15 deletions
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index b9ea370ec0..262b0290a8 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -18,6 +18,7 @@
#include "device-util.h"
#include "dirent-util.h"
#include "efivars.h"
+#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio-label.h"
@@ -2392,9 +2393,24 @@ static int property_get_reboot_to_firmware_setup(
assert(reply);
assert(userdata);
- r = efi_get_reboot_to_firmware();
- if (r < 0 && r != -EOPNOTSUPP)
- log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
+ r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+ if (r == -ENXIO) {
+ /* EFI case: let's see what is currently configured in the EFI variables */
+ r = efi_get_reboot_to_firmware();
+ if (r < 0 && r != -EOPNOTSUPP)
+ log_warning_errno(r, "Failed to determine reboot-to-firmware-setup state: %m");
+ } else if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+ else if (r > 0) {
+ /* Non-EFI case: let's see whether /run/systemd/reboot-to-firmware-setup exists. */
+ if (access("/run/systemd/reboot-to-firmware-setup", F_OK) < 0) {
+ if (errno != ENOENT)
+ log_warning_errno(errno, "Failed to check whether /run/systemd/reboot-to-firmware-setup exists: %m");
+
+ r = false;
+ } else
+ r = true;
+ }
return sd_bus_message_append(reply, "b", r > 0);
}
@@ -2404,8 +2420,9 @@ static int method_set_reboot_to_firmware_setup(
void *userdata,
sd_bus_error *error) {
- int b, r;
Manager *m = userdata;
+ bool use_efi;
+ int b, r;
assert(message);
assert(m);
@@ -2414,6 +2431,29 @@ static int method_set_reboot_to_firmware_setup(
if (r < 0)
return r;
+ r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+ if (r == -ENXIO) {
+ /* EFI case: let's see what the firmware supports */
+
+ r = efi_reboot_to_firmware_supported();
+ if (r == -EOPNOTSUPP)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+ if (r < 0)
+ return r;
+
+ use_efi = true;
+
+ } else if (r <= 0) {
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to off */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+ } else
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */
+ use_efi = false;
+
r = bus_verify_polkit_async(message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.set-reboot-to-firmware-setup",
@@ -2427,9 +2467,20 @@ static int method_set_reboot_to_firmware_setup(
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- r = efi_set_reboot_to_firmware(b);
- if (r < 0)
- return r;
+ if (use_efi) {
+ r = efi_set_reboot_to_firmware(b);
+ if (r < 0)
+ return r;
+ } else {
+ if (b) {
+ r = touch("/run/systemd/reboot-to-firmware-setup");
+ if (r < 0)
+ return r;
+ } else {
+ if (unlink("/run/systemd/reboot-to-firmware-setup") < 0 && errno != ENOENT)
+ return -errno;
+ }
+ }
return sd_bus_reply_method_return(message, NULL);
}
@@ -2439,22 +2490,38 @@ static int method_can_reboot_to_firmware_setup(
void *userdata,
sd_bus_error *error) {
- int r;
- bool challenge;
- const char *result;
+ const char *result = NULL;
Manager *m = userdata;
+ bool challenge;
+ int r;
assert(message);
assert(m);
- r = efi_reboot_to_firmware_supported();
- if (r < 0) {
- if (r != -EOPNOTSUPP)
- log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
+ r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+ if (r == -ENXIO) {
+ /* EFI case: let's see what the firmware supports */
+
+ r = efi_reboot_to_firmware_supported();
+ if (r < 0) {
+ if (r != -EOPNOTSUPP)
+ log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
+
+ result = "na";
+ }
- return sd_bus_reply_method_return(message, "s", "na");
+ } else if (r <= 0) {
+ /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+
+ result = "na";
}
+ if (result)
+ return sd_bus_reply_method_return(message, "s", result);
+
r = bus_test_polkit(message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.set-reboot-to-firmware-setup",