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.
This commit is contained in:
+82
-15
@@ -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 */
|
||||
|
||||
return sd_bus_reply_method_return(message, "s", "na");
|
||||
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";
|
||||
}
|
||||
|
||||
} 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",
|
||||
|
||||
Reference in New Issue
Block a user