[systemd-commits] 3 commits - TODO man/systemctl.xml shell-completion/bash shell-completion/zsh src/core src/login src/shared src/systemctl

Lennart Poettering lennart at kemper.freedesktop.org
Tue Apr 7 09:52:24 PDT 2015


 TODO                                       |    4 +
 man/systemctl.xml                          |   12 +++
 shell-completion/bash/systemctl.in         |    2 
 shell-completion/zsh/_systemctl.in         |    1 
 src/core/socket.c                          |    6 -
 src/login/logind-dbus.c                    |  102 +++++++++++++++++++++++++++++
 src/login/org.freedesktop.login1.conf      |    8 ++
 src/login/org.freedesktop.login1.policy.in |   10 ++
 src/shared/efivars.c                       |   72 ++++++++++++++++++++
 src/shared/efivars.h                       |    3 
 src/systemctl/systemctl.c                  |   15 ++++
 11 files changed, 231 insertions(+), 4 deletions(-)

New commits:
commit 449a22a58f0fa55d9d0fd2eb597272446e032acd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 7 18:47:47 2015 +0200

    update TODO

diff --git a/TODO b/TODO
index 6330d49..6755078 100644
--- a/TODO
+++ b/TODO
@@ -43,6 +43,10 @@ Before 220:
 
 Features:
 
+* mounting and unmounting mount points manually with different source
+  devices will result in collected collected on all devices used.
+  http://lists.freedesktop.org/archives/systemd-devel/2015-April/030225.html
+
 * whe should apply a stop limit (similar to the existing start limit),
   so that we don't enter unbounded umount loops:
   http://lists.freedesktop.org/archives/systemd-devel/2015-April/030224.html

commit e5403f09aa0c548d2739f132c2699a6ad44dad51
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 7 18:47:35 2015 +0200

    socket: minor modernizations

diff --git a/src/core/socket.c b/src/core/socket.c
index f67370b..c81fd66 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2315,8 +2315,7 @@ static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                                 if (errno == EINTR)
                                         continue;
 
-                                log_unit_error(UNIT(p->socket)->id,
-                                               "Failed to accept socket: %m");
+                                log_unit_error(UNIT(p->socket)->id, "Failed to accept socket: %m");
                                 goto fail;
                         }
 
@@ -2523,7 +2522,8 @@ int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
                 return 0;
         }
 
-        if (!(rfds = new(int, rn_fds)))
+        rfds = new(int, rn_fds);
+        if (!rfds)
                 return -ENOMEM;
 
         k = 0;

commit 5bdf22430e367799dfa66c724144b624c5479518
Author: Jan Janssen <medhefgo at web.de>
Date:   Fri Apr 3 18:03:06 2015 +0200

    logind,systemctl: add reboot to EFI firmware support

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 50e6bc9..8c0a01d 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -527,6 +527,18 @@
       </varlistentry>
 
       <varlistentry>
+        <term><option>--firmware-setup</option></term>
+
+        <listitem>
+          <para>When used with the <command>reboot</command> command,
+          indicate to the system's firmware to boot into setup
+          mode. Note that this is currently only supported on some EFI
+          systems and only if the system was booted in EFI
+          mode.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>--plain</option></term>
 
         <listitem>
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index 8063316..773a59d 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -92,7 +92,7 @@ _systemctl () {
         local -A OPTS=(
                [STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global
                              --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall
-                             --quiet -q --privileged -P --system --user --version --runtime --recursive -r'
+                             --quiet -q --privileged -P --system --user --version --runtime --recursive -r --firmware-setup'
                       [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --root'
         )
 
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index 7f2d5ac..3bbfb6f 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -384,5 +384,6 @@ _arguments -s \
     {-P,--privileged}'[Acquire privileges before execution]' \
     {-n+,--lines=}'[Journal entries to show]:number of entries' \
     {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \
+    '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \
     '--plain[When used with list-dependencies, print output as a list]' \
     '*::systemctl command:_systemctl_command'
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 1571dd0..46185f4 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -38,6 +38,7 @@
 #include "bus-common-errors.h"
 #include "udev-util.h"
 #include "selinux-util.h"
+#include "efivars.h"
 #include "logind.h"
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
@@ -1850,6 +1851,104 @@ static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *u
                         error);
 }
 
+static int property_get_reboot_to_firmware_setup(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+        int r;
+
+        assert(bus);
+        assert(reply);
+        assert(userdata);
+
+        r = efi_get_reboot_to_firmware();
+        if (r < 0 && r != -EOPNOTSUPP)
+                return r;
+
+        return sd_bus_message_append(reply, "b", r > 0);
+}
+
+static int method_set_reboot_to_firmware_setup(
+                sd_bus *bus,
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error) {
+
+        int b, r;
+        int interactive;
+        Manager *m = userdata;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "bb", &b, &interactive);
+        if (r < 0)
+                return r;
+
+        r = bus_verify_polkit_async(message,
+                                    CAP_SYS_ADMIN,
+                                    "org.freedesktop.login1.set-reboot-to-firmware-setup",
+                                    interactive,
+                                    UID_INVALID,
+                                    &m->polkit_registry,
+                                    error);
+        if (r < 0)
+                return r;
+        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;
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_can_reboot_to_firmware_setup(
+                sd_bus *bus,
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error) {
+
+        int r;
+        bool challenge;
+        const char *result;
+        Manager *m = userdata;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = efi_reboot_to_firmware_supported();
+        if (r == -EOPNOTSUPP)
+                return sd_bus_reply_method_return(message, "s", "na");
+        else if (r < 0)
+                return r;
+
+        r = bus_test_polkit(message,
+                            CAP_SYS_ADMIN,
+                            "org.freedesktop.login1.set-reboot-to-firmware-setup",
+                            UID_INVALID,
+                            &challenge,
+                            error);
+        if (r < 0)
+                return r;
+
+        if (r > 0)
+                result = "yes";
+        else if (challenge)
+                result = "challenge";
+        else
+                result = "no";
+
+        return sd_bus_reply_method_return(message, "s", result);
+}
+
 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         const char *who, *why, *what, *mode;
@@ -1970,6 +2069,7 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -2023,6 +2123,8 @@ const sd_bus_vtable manager_vtable[] = {
         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),
         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("SetRebootToFirmwareSetup", "bb", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
 
         SD_BUS_SIGNAL("SessionNew", "so", 0),
         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index 1318328..0ad7880 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -130,6 +130,14 @@
 
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Manager"
+                       send_member="CanRebootToFirmwareSetup"/>
+
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Manager"
+                       send_member="SetRebootToFirmwareSetup"/>
+
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Manager"
                        send_member="AttachDevice"/>
 
                 <allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index c45491b..83e7183 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -290,4 +290,14 @@
                 </defaults>
         </action>
 
+        <action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
+                <_description>Allow indication to the firmware to boot to setup interface</_description>
+                <_message>Authentication is required to indicate to the firmware to boot to setup interface.</_message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
 </policyconfig>
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index 20067c6..b82f74a 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,76 @@ int is_efi_secure_boot_setup_mode(void) {
         return read_flag("SetupMode");
 }
 
+int efi_reboot_to_firmware_supported(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;
+        b &= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+        return b > 0 ? 0 : -EOPNOTSUPP;
+}
+
+static int get_os_indications(uint64_t *os_indication) {
+        int r;
+        size_t s;
+        _cleanup_free_ void *v = NULL;
+
+        r = efi_reboot_to_firmware_supported();
+        if (r < 0)
+                return r;
+
+        r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s);
+        if (r < 0)
+                return r;
+        else if (s != sizeof(uint64_t))
+                return -EINVAL;
+
+        *os_indication = *(uint64_t *)v;
+        return 0;
+}
+
+int efi_get_reboot_to_firmware(void) {
+        int r;
+        uint64_t b;
+
+        r = get_os_indications(&b);
+        if (r < 0)
+                return r;
+
+        return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
+}
+
+int efi_set_reboot_to_firmware(bool value) {
+        int r;
+        uint64_t b, b_new;
+
+        r = get_os_indications(&b);
+        if (r < 0)
+                return r;
+
+        if (value)
+                b_new = b | EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+        else
+                b_new = b & ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+
+        /* Avoid writing to efi vars store if we can due to firmware bugs. */
+        if (b != b_new)
+                return efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b_new, sizeof(uint64_t));
+
+        return 0;
+}
+
 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..e796bf4 100644
--- a/src/shared/efivars.h
+++ b/src/shared/efivars.h
@@ -35,6 +35,9 @@
 bool is_efi_boot(void);
 int is_efi_secure_boot(void);
 int is_efi_secure_boot_setup_mode(void);
+int efi_reboot_to_firmware_supported(void);
+int efi_get_reboot_to_firmware(void);
+int efi_set_reboot_to_firmware(bool value);
 
 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..ae87e44 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;
@@ -132,6 +133,7 @@ static char *arg_host = NULL;
 static unsigned arg_lines = 10;
 static OutputMode arg_output = OUTPUT_SHORT;
 static bool arg_plain = false;
+static bool arg_firmware_setup = false;
 
 static bool original_stdout_is_tty;
 
@@ -2928,6 +2930,12 @@ static int start_special(sd_bus *bus, char **args) {
                 return -EPERM;
         }
 
+        if (arg_firmware_setup) {
+                r = efi_set_reboot_to_firmware(true);
+                if (r < 0)
+                        return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %m");
+        }
+
         if (a == ACTION_REBOOT && args[1]) {
                 r = update_reboot_param_file(args[1]);
                 if (r < 0)
@@ -5971,6 +5979,7 @@ static void systemctl_help(void) {
                "  -o --output=STRING  Change journal output mode (short, short-iso,\n"
                "                              short-precise, short-monotonic, verbose,\n"
                "                              export, json, json-pretty, json-sse, cat)\n"
+               "     --firmware-setup Tell the firmware to show the setup menu on next boot\n"
                "     --plain          Print unit dependencies as a list instead of a tree\n\n"
                "Unit Commands:\n"
                "  list-units [PATTERN...]         List loaded units\n"
@@ -6150,6 +6159,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_STATE,
                 ARG_JOB_MODE,
                 ARG_PRESET_MODE,
+                ARG_FIRMWARE_SETUP,
         };
 
         static const struct option options[] = {
@@ -6192,6 +6202,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "state",               required_argument, NULL, ARG_STATE               },
                 { "recursive",           no_argument,       NULL, 'r'                     },
                 { "preset-mode",         required_argument, NULL, ARG_PRESET_MODE         },
+                { "firmware-setup",      no_argument,       NULL, ARG_FIRMWARE_SETUP      },
                 {}
         };
 
@@ -6432,6 +6443,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_plain = true;
                         break;
 
+                case ARG_FIRMWARE_SETUP:
+                        arg_firmware_setup = true;
+                        break;
+
                 case ARG_STATE: {
                         const char *word, *state;
                         size_t size;



More information about the systemd-commits mailing list