I like this. +1 On 26 March 2015 at 15:09, Jan Janssen <medhe...@web.de> wrote: > --- > man/systemctl.xml | 6 +++- > src/libsystemd/sd-bus/bus-common-errors.h | 1 + > src/login/logind-dbus.c | 49 +++++++++++++++++++++++++++-- > src/login/org.freedesktop.login1.conf | 8 +++++ > src/shared/efivars.c | 52 > +++++++++++++++++++++++++++++++ > src/shared/efivars.h | 2 ++ > src/systemctl/systemctl.c | 16 ++++++++-- > 7 files changed, 127 insertions(+), 7 deletions(-) > > diff --git a/man/systemctl.xml b/man/systemctl.xml > index 50e6bc9..eafdd73 100644 > --- a/man/systemctl.xml > +++ b/man/systemctl.xml > @@ -1538,7 +1538,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket > systemd-udevd.service > systems. This may result in data loss.</para> > > <para>If the optional argument > - <replaceable>arg</replaceable> is given, it will be passed > + <replaceable>arg</replaceable> is given and is equal to > + <literal>efi</literal>, the system will be rebooted to > + the EFI firmware interface on machines that support it. > + Note that this requires the system to be booted in EFI mode. > + Otherwise, the argument will be passed > as the optional argument to the > > <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> > system call. The value is architecture and firmware > diff --git a/src/libsystemd/sd-bus/bus-common-errors.h > b/src/libsystemd/sd-bus/bus-common-errors.h > index b17b62a..3019140 100644 > --- a/src/libsystemd/sd-bus/bus-common-errors.h > +++ b/src/libsystemd/sd-bus/bus-common-errors.h > @@ -57,6 +57,7 @@ > #define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken" > #define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken" > #define BUS_ERROR_OPERATION_IN_PROGRESS > "org.freedesktop.login1.OperationInProgress" > +#define BUS_ERROR_REBOOT_TO_EFI_NOT_SUPPORTED > "org.freedesktop.login1.RebootToEfiNotSupported" > #define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED > "org.freedesktop.login1.SleepVerbNotSupported" > > #define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED > "org.freedesktop.timedate1.AutomaticTimeSyncEnabled" > diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c > index a3d49ef..8fec90f 100644 > --- a/src/login/logind-dbus.c > +++ b/src/login/logind-dbus.c > @@ -38,8 +38,11 @@ > #include "bus-common-errors.h" > #include "udev-util.h" > #include "selinux-util.h" > +#include "efivars.h" > #include "logind.h" > > +#define SPECIAL_REBOOT_TO_EFI_TARGET "x-logind-reboot-to-efi.target" > + > int manager_get_session_from_creds(Manager *m, sd_bus_message *message, > const char *name, sd_bus_error *error, Session **ret) { > _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; > Session *session; > @@ -1422,6 +1425,13 @@ static int execute_shutdown_or_sleep( > assert(w < _INHIBIT_WHAT_MAX); > assert(unit_name); > > + if (streq(unit_name, SPECIAL_REBOOT_TO_EFI_TARGET)) { > + unit_name = SPECIAL_REBOOT_TARGET; > + r = efi_indicate_reboot_to_fw(); > + if (r < 0) > + return r; > + } > + > bus_manager_log_shutdown(m, w, unit_name); > > r = sd_bus_call_method( > @@ -1563,6 +1573,9 @@ static int method_do_shutdown_or_sleep( > if (m->action_what) > return sd_bus_error_setf(error, > BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep > operation in progress"); > > + if (streq(unit_name, SPECIAL_REBOOT_TO_EFI_TARGET) && > !is_efi_reboot_to_fw_supported()) > + return sd_bus_error_setf(error, > BUS_ERROR_REBOOT_TO_EFI_NOT_SUPPORTED, "Reboot to EFI not supported"); > + > if (sleep_verb) { > r = can_sleep(sleep_verb); > if (r < 0) > @@ -1648,6 +1661,21 @@ static int method_reboot(sd_bus *bus, sd_bus_message > *message, void *userdata, s > error); > } > > +static int method_reboot_to_efi(sd_bus *bus, sd_bus_message *message, void > *userdata, sd_bus_error *error) { > + Manager *m = userdata; > + > + return method_do_shutdown_or_sleep( > + m, message, > + SPECIAL_REBOOT_TO_EFI_TARGET, > + INHIBIT_SHUTDOWN, > + "org.freedesktop.login1.reboot", > + "org.freedesktop.login1.reboot-multiple-sessions", > + "org.freedesktop.login1.reboot-ignore-inhibit", > + NULL, > + method_reboot_to_efi, > + error); > +} > + > static int method_suspend(sd_bus *bus, sd_bus_message *message, void > *userdata, sd_bus_error *error) { > Manager *m = userdata; > > @@ -1700,7 +1728,7 @@ static int method_can_shutdown_or_sleep( > const char *action, > const char *action_multiple_sessions, > const char *action_ignore_inhibit, > - const char *sleep_verb, > + const char *arg, > sd_bus_error *error) { > > _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; > @@ -1717,8 +1745,8 @@ static int method_can_shutdown_or_sleep( > assert(action_multiple_sessions); > assert(action_ignore_inhibit); > > - if (sleep_verb) { > - r = can_sleep(sleep_verb); > + if (arg) { > + r = streq(arg, "reboot-to-efi") ? > is_efi_reboot_to_fw_supported() : can_sleep(arg); > if (r < 0) > return r; > if (r == 0) > @@ -1811,6 +1839,19 @@ static int method_can_reboot(sd_bus *bus, > sd_bus_message *message, void *userdat > error); > } > > +static int method_can_reboot_to_efi(sd_bus *bus, sd_bus_message *message, > void *userdata, sd_bus_error *error) { > + Manager *m = userdata; > + > + return method_can_shutdown_or_sleep( > + m, message, > + INHIBIT_SHUTDOWN, > + "org.freedesktop.login1.reboot", > + "org.freedesktop.login1.reboot-multiple-sessions", > + "org.freedesktop.login1.reboot-ignore-inhibit", > + "reboot-to-efi", > + error); > +} > + > static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void > *userdata, sd_bus_error *error) { > Manager *m = userdata; > > @@ -2014,11 +2055,13 @@ const sd_bus_vtable manager_vtable[] = { > SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, > SD_BUS_VTABLE_UNPRIVILEGED), > + SD_BUS_METHOD("RebootToEfi", "b", NULL, method_reboot_to_efi, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, > SD_BUS_VTABLE_UNPRIVILEGED), > + SD_BUS_METHOD("CanRebootToEfi", NULL, "s", method_can_reboot_to_efi, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, > SD_BUS_VTABLE_UNPRIVILEGED), > SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, > SD_BUS_VTABLE_UNPRIVILEGED), > diff --git a/src/login/org.freedesktop.login1.conf > b/src/login/org.freedesktop.login1.conf > index 1318328..7ea3014 100644 > --- a/src/login/org.freedesktop.login1.conf > +++ b/src/login/org.freedesktop.login1.conf > @@ -98,6 +98,10 @@ > > <allow send_destination="org.freedesktop.login1" > send_interface="org.freedesktop.login1.Manager" > + send_member="RebootToEfi"/> > + > + <allow send_destination="org.freedesktop.login1" > + send_interface="org.freedesktop.login1.Manager" > send_member="Suspend"/> > > <allow send_destination="org.freedesktop.login1" > @@ -118,6 +122,10 @@ > > <allow send_destination="org.freedesktop.login1" > send_interface="org.freedesktop.login1.Manager" > + send_member="CanRebootToEfi"/> > + > + <allow send_destination="org.freedesktop.login1" > + send_interface="org.freedesktop.login1.Manager" > send_member="CanSuspend"/> > > <allow send_destination="org.freedesktop.login1" > diff --git a/src/shared/efivars.c b/src/shared/efivars.c > index 20067c6..ea80d6b 100644 > --- a/src/shared/efivars.c > +++ b/src/shared/efivars.c > @@ -25,6 +25,7 @@ > > #include "util.h" > #include "utf8.h" > +#include "virt.h" > #include "efivars.h" > > #ifdef ENABLE_EFI > @@ -37,6 +38,7 @@ > #define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 > #define END_DEVICE_PATH_TYPE 0x7f > #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff > +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 > > struct boot_option { > uint32_t attr; > @@ -93,6 +95,56 @@ int is_efi_secure_boot_setup_mode(void) { > return read_flag("SetupMode"); > } > > +bool is_efi_reboot_to_fw_supported(void) { > + int r; > + size_t s; > + uint64_t b; > + _cleanup_free_ void *v = NULL; > + > + if (!is_efi_boot() || detect_container(NULL) > 0) > + return false; > + > + r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", > NULL, &v, &s); > + if (r < 0 || s != sizeof(uint64_t)) > + return false; > + > + b = *(uint64_t *)v; > + return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI); > +} > + > +int efi_indicate_reboot_to_fw(void) { > + int r; > + size_t s; > + uint64_t b; > + _cleanup_free_ void *v = NULL; > + > + if (!is_efi_boot() || detect_container(NULL) > 0) > + return -EOPNOTSUPP; > + > + r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", > NULL, &v, &s); > + if (r < 0) > + return r; > + else if (s != sizeof(uint64_t)) > + return -EINVAL; > + > + b = *(uint64_t *)v; > + if (!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) > + return -EOPNOTSUPP; > + > + free(v); > + v = NULL; > + r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, > &s); > + if (r < 0) > + return r; > + else if (s != sizeof(uint64_t)) > + return -EINVAL; > + > + b = *(uint64_t *)v; > + b |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; > + r = efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b, s); > + return r; > +} > + > int efi_get_variable( > sd_id128_t vendor, > const char *name, > diff --git a/src/shared/efivars.h b/src/shared/efivars.h > index 2492893..5c1e28f 100644 > --- a/src/shared/efivars.h > +++ b/src/shared/efivars.h > @@ -35,6 +35,8 @@ > bool is_efi_boot(void); > int is_efi_secure_boot(void); > int is_efi_secure_boot_setup_mode(void); > +bool is_efi_reboot_to_fw_supported(void); > +int efi_indicate_reboot_to_fw(void); > > int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t > *attribute, void **value, size_t *size); > int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, > size_t size); > diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c > index 3158a38..372542b 100644 > --- a/src/systemctl/systemctl.c > +++ b/src/systemctl/systemctl.c > @@ -68,6 +68,7 @@ > #include "bus-common-errors.h" > #include "mkdir.h" > #include "dropin.h" > +#include "efivars.h" > > static char **arg_types = NULL; > static char **arg_states = NULL; > @@ -2929,9 +2930,18 @@ static int start_special(sd_bus *bus, char **args) { > } > > if (a == ACTION_REBOOT && args[1]) { > - r = update_reboot_param_file(args[1]); > - if (r < 0) > - return r; > + if (streq(args[1], "efi")) { > + if (!is_efi_reboot_to_fw_supported()) > + return log_error_errno(EOPNOTSUPP, "Reboot > to EFI not supported."); > + > + r = efi_indicate_reboot_to_fw(); > + if (r < 0) > + return log_error_errno(r, "Failed to > indicate reboot to EFI: %m"); > + } else { > + r = update_reboot_param_file(args[1]); > + if (r < 0) > + return r; > + } > } > > if (arg_force >= 2 && > -- > 2.3.4 > > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- Regards, Dimitri. https://clearlinux.org Open Source Technology Center Intel Corporation (UK) Ltd. - Co. Reg. #1134945 - Pipers Way, Swindon SN3 1RJ. _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel