chiark / gitweb /
Support additional argument in reboot
authorWaLyong Cho <walyong.cho@samsung.com>
Wed, 6 Nov 2013 08:02:41 +0000 (17:02 +0900)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 7 Nov 2013 06:23:54 +0000 (01:23 -0500)
reboot syscall can be performed with an additional argument. In some
systems this functionality can be useful to modify the mode of the
next boot performed by the bootloader.

man/systemctl.xml
src/core/shutdown.c
src/shared/def.h
src/systemctl/systemctl.c

index c7313edcc2bcb1ea57b4c41db2ae983c737d4add..7f1e98f5c5472f84095b345514ffd417b03481d1 100644 (file)
@@ -1179,7 +1179,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
           </listitem>
         </varlistentry>
         <varlistentry>
           </listitem>
         </varlistentry>
         <varlistentry>
-          <term><command>reboot</command></term>
+          <term><command>reboot <optional><replaceable>arg</replaceable></optional></command></term>
 
           <listitem>
             <para>Shut down and reboot the system. This is mostly
 
           <listitem>
             <para>Shut down and reboot the system. This is mostly
@@ -1192,6 +1192,16 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             specified twice, the operation is immediately executed
             without terminating any processes or unmounting any file
             systems. This may result in data loss.</para>
             specified twice, the operation is immediately executed
             without terminating any processes or unmounting any file
             systems. This may result in data loss.</para>
+
+            <para>If the optional argument
+            <replaceable>arg</replaceable> is given, it 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
+            specific. As an example, <literal>recovery</literal> might
+            be used to trigger system recovery, and
+            <literal>fota</literal> might be used to trigger a
+            <quote>firmware over the air</quote> update.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           </listitem>
         </varlistentry>
         <varlistentry>
index aa9548e2a4700bb567aab34bb56db862902e659e..377c1971a37d130bc9addaf6f639e82a11d37c3d 100644 (file)
@@ -47,6 +47,7 @@
 #include "watchdog.h"
 #include "killall.h"
 #include "cgroup-util.h"
 #include "watchdog.h"
 #include "killall.h"
 #include "cgroup-util.h"
+#include "def.h"
 
 #define FINALIZE_ATTEMPTS 50
 
 
 #define FINALIZE_ATTEMPTS 50
 
@@ -134,7 +135,7 @@ static int pivot_to_new_root(void) {
 int main(int argc, char *argv[]) {
         bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
         bool in_container, use_watchdog = false;
 int main(int argc, char *argv[]) {
         bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
         bool in_container, use_watchdog = false;
-        _cleanup_free_ char *line = NULL, *cgroup = NULL;
+        _cleanup_free_ char *line = NULL, *cgroup = NULL, *param = NULL;
         char *arguments[3];
         unsigned retries;
         int cmd, r;
         char *arguments[3];
         unsigned retries;
         int cmd, r;
@@ -173,9 +174,11 @@ int main(int argc, char *argv[]) {
 
         in_container = detect_container(NULL) > 0;
 
 
         in_container = detect_container(NULL) > 0;
 
-        if (streq(argv[1], "reboot"))
+        if (streq(argv[1], "reboot")) {
                 cmd = RB_AUTOBOOT;
                 cmd = RB_AUTOBOOT;
-        else if (streq(argv[1], "poweroff"))
+                /* if this fails, that's OK */
+                read_one_line_file(REBOOT_PARAM_FILE, &param);
+        } else if (streq(argv[1], "poweroff"))
                 cmd = RB_POWER_OFF;
         else if (streq(argv[1], "halt"))
                 cmd = RB_HALT_SYSTEM;
                 cmd = RB_POWER_OFF;
         else if (streq(argv[1], "halt"))
                 cmd = RB_HALT_SYSTEM;
@@ -337,7 +340,11 @@ int main(int argc, char *argv[]) {
                 cmd = RB_AUTOBOOT;
         }
 
                 cmd = RB_AUTOBOOT;
         }
 
-        reboot(cmd);
+        if (param)
+                syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                        LINUX_REBOOT_CMD_RESTART2, param);
+        else
+                reboot(cmd);
 
         if (errno == EPERM && in_container) {
                 /* If we are in a container, and we lacked
 
         if (errno == EPERM && in_container) {
                 /* If we are in a container, and we lacked
index edd0bcf7a42ae98877b7493b9c88edac2dbeda07..46b88a8a49e3040d24455fd5c183f35a1f29ab13 100644 (file)
@@ -38,3 +38,5 @@
 #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
 #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
 #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
 #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
+
+#define REBOOT_PARAM_FILE "/run/systemd/reboot-param"
index 9d22aad28700ebe1247aaa54ba769b862702a20a..6170cc93d56aa7695621c80eee25b7a902a07a8d 100644 (file)
@@ -20,6 +20,8 @@
 ***/
 
 #include <sys/reboot.h>
 ***/
 
 #include <sys/reboot.h>
+#include <linux/reboot.h>
+#include <sys/syscall.h>
 #include <stdio.h>
 #include <getopt.h>
 #include <locale.h>
 #include <stdio.h>
 #include <getopt.h>
 #include <locale.h>
@@ -4804,7 +4806,7 @@ static int systemctl_help(void) {
                "  emergency                       Enter system emergency mode\n"
                "  halt                            Shut down and halt the system\n"
                "  poweroff                        Shut down and power-off the system\n"
                "  emergency                       Enter system emergency mode\n"
                "  halt                            Shut down and halt the system\n"
                "  poweroff                        Shut down and power-off the system\n"
-               "  reboot                          Shut down and reboot the system\n"
+               "  reboot [ARG]                    Shut down and reboot the system\n"
                "  kexec                           Shut down and reboot the system with kexec\n"
                "  exit                            Request user instance exit\n"
                "  switch-root [ROOT] [INIT]       Change to a different root file system\n"
                "  kexec                           Shut down and reboot the system with kexec\n"
                "  exit                            Request user instance exit\n"
                "  switch-root [ROOT] [INIT]       Change to a different root file system\n"
@@ -4818,7 +4820,7 @@ static int systemctl_help(void) {
 
 static int halt_help(void) {
 
 
 static int halt_help(void) {
 
-        printf("%s [OPTIONS...]\n\n"
+        printf("%s [OPTIONS...]%s\n\n"
                "%s the system.\n\n"
                "     --help      Show this help\n"
                "     --halt      Halt the machine\n"
                "%s the system.\n\n"
                "     --help      Show this help\n"
                "     --halt      Halt the machine\n"
@@ -4829,6 +4831,7 @@ static int halt_help(void) {
                "  -d --no-wtmp   Don't write wtmp record\n"
                "     --no-wall   Don't send wall message before halt/power-off/reboot\n",
                program_invocation_short_name,
                "  -d --no-wtmp   Don't write wtmp record\n"
                "     --no-wall   Don't send wall message before halt/power-off/reboot\n",
                program_invocation_short_name,
+               arg_action == ACTION_REBOOT   ? " [ARG]" : "",
                arg_action == ACTION_REBOOT   ? "Reboot" :
                arg_action == ACTION_POWEROFF ? "Power off" :
                                                "Halt");
                arg_action == ACTION_REBOOT   ? "Reboot" :
                arg_action == ACTION_POWEROFF ? "Power off" :
                                                "Halt");
@@ -5253,7 +5256,7 @@ static int halt_parse_argv(int argc, char *argv[]) {
                 {}
         };
 
                 {}
         };
 
-        int c, runlevel;
+        int c, r, runlevel;
 
         assert(argc >= 0);
         assert(argv);
 
         assert(argc >= 0);
         assert(argv);
@@ -5311,7 +5314,14 @@ static int halt_parse_argv(int argc, char *argv[]) {
                 }
         }
 
                 }
         }
 
-        if (optind < argc) {
+        if (arg_action == ACTION_REBOOT && argc == optind + 1) {
+                r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
+                if (r < 0) {
+                        log_error("Failed to write reboot param to "
+                                  REBOOT_PARAM_FILE": %s", strerror(-r));
+                        return r;
+                }
+        } else if (optind < argc) {
                 log_error("Too many arguments.");
                 return -EINVAL;
         }
                 log_error("Too many arguments.");
                 return -EINVAL;
         }
@@ -5944,6 +5954,8 @@ done:
 
 static _noreturn_ void halt_now(enum action a) {
 
 
 static _noreturn_ void halt_now(enum action a) {
 
+        _cleanup_free_ char *param = NULL;
+
        /* Make sure C-A-D is handled by the kernel from this
          * point on... */
         reboot(RB_ENABLE_CAD);
        /* Make sure C-A-D is handled by the kernel from this
          * point on... */
         reboot(RB_ENABLE_CAD);
@@ -5961,8 +5973,14 @@ static _noreturn_ void halt_now(enum action a) {
                 break;
 
         case ACTION_REBOOT:
                 break;
 
         case ACTION_REBOOT:
-                log_info("Rebooting.");
-                reboot(RB_AUTOBOOT);
+                if (read_one_line_file(REBOOT_PARAM_FILE, &param) == 0) {
+                        log_info("Rebooting with arg '%s'.", param);
+                        syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                                LINUX_REBOOT_CMD_RESTART2, param);
+                } else {
+                        log_info("Rebooting.");
+                        reboot(RB_AUTOBOOT);
+                }
                 break;
 
         default:
                 break;
 
         default: