On 09/12/2013 02:20 AM, Lennart Poettering wrote:
> On Tue, 13.08.13 03:01, WaLyong Cho (fyd0...@gmail.com) wrote:
> 
>> From: WaLyong Cho <walyong....@samsung.com>
>>
>> reboot syscall can be performed with additional argument. In some of
>> system, this functionality can be useful to ask next boot mode to
>> bootloader.
> 
> Hmm, interesting stuff. 
> 
>> @@ -5200,9 +5204,19 @@ static int halt_parse_argv(int argc, char *argv[]) {
>>                  }
>>          }
>>  
> 
> Note that halt is not called during normal shutdown, but is only a
> compat fallback for the old sysv "halt" command. If you want this to
> work we probably need to come up with a way to pass the string from
> systemctl to the final systemd-shutdown process.
> 
> (A bit of background: systemctl normally will just tell PID 1 to
> shutdown cleanly, via D-Bus. As last step of that PID 1 will execute the
> special systemd-shutdown binary -- which will then also run as PID 1 --
> which will do some final shutdown steps and then invoke the reboot()
> syscall -- see src/core/shutdown.c for details)

Sorry for my long silence.

You were right. Previous my patch did not pass the argument without
force option. So I modified according to your opinion. But I think we
have to keep some codes in systemctl for supporting forced reboot.

> 
> So, before we continue with this, could you point me to some
> docs/commits/code which explain a bit how the new reboot() syscall
> semantics work? i.e. what the possible params are and such?

There are not any params specified. Any string can be used. That string
is used in kernel side.
http://lxr.linux.no/linux+v3.4/kernel/sys.c#L486

Sorry, there are no visible commits for Tizen in the web. But, for
simple example, fota, recovery, download and more are used in Tizen.
fota is used when restart to enter fota updated mode. In the mobile,
user can download firmware image by on air. And update device firmware
to downloaded. During this, reboot is performed. See
http://www.redbend.com/en/products-solutions/fota-updating for detail.
recovery is used for detecting hacked kernel. I am not sure that I can
explain more.
download is used to enter download mode. As you may know, most of
devices are downloaded(not installed) when the device is produced. At
this time, special boot mode is used to flush device.

I found similar codes in android.
https://github.com/CyanogenMod/android_system_core/blob/gingerbread/toolbox/reboot.c
https://github.com/CyanogenMod/android_system_core/blob/gingerbread/libreboot/reboot.c

> 
> One way to implement this could be to add add a new parameter to
> systemctl which is written to /run/systemd/reboot-param or so if
> specified. systemd-shutdown would then look for that file and pass it to
> the reboot() syscall.

According to man page of reboot. They called this 'arg'.
http://man7.org/linux/man-pages/man2/reboot.2.htm
I'm not sure which is more suitable word between 'param' and 'arg'. You
offered 'param', so I used also 'param'. Because, 'arg' can be confused
with argc/argv.

> 
>> -        if (optind < argc) {
>> -                log_error("Too many arguments.");
>> -                return -EINVAL;
>> +        if (arg_action == ACTION_REBOOT) {
>> +                /* reboot allow just one argument for his command string */
>> +                if (optind+1 == argc)
>> +                        arg_reboot = strdup(argv[argc-1]);
>> +                else if (optind+1 < argc) {
>> +                        log_error("Too many arguments.");
>> +                        return -EINVAL;
>> +                }
>> +        } else {
>> +                if (optind < argc) {
>> +                        log_error("Too many arguments.");
>> +                        return -EINVAL;
>> +                }
>>          }
>>  
>>          return 1;
>> @@ -5949,7 +5963,11 @@ static _noreturn_ void halt_now(enum action a) {
>>  
>>          case ACTION_REBOOT:
>>                  log_info("Rebooting.");
>> -                reboot(RB_AUTOBOOT);
>> +                if (arg_reboot)
>> +                        syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, 
>> LINUX_REBOOT_MAGIC2,
>> +                                LINUX_REBOOT_CMD_RESTART2, arg_reboot);
>> +                else
>> +                        reboot(RB_AUTOBOOT);
>>                  break;
>>  
>>          default:
> 
> 
> Lennart
> 

WaLyong
>From 3e68b25edab207cdeffb267368e24f6c3a5830ae Mon Sep 17 00:00:00 2001
From: WaLyong Cho <walyong....@samsung.com>
Date: Tue, 5 Nov 2013 17:11:09 +0900
Subject: [PATCH] make reboot to support additional command

reboot syscall can be performed with additional argument. In some of
system, this functionality can be useful to ask next boot mode to
bootloader.
---
 Makefile.am               |    4 ++-
 src/core/shutdown.c       |   15 +++++++---
 src/shared/reboot-param.c |   68 +++++++++++++++++++++++++++++++++++++++++++++
 src/shared/reboot-param.h |   28 +++++++++++++++++++
 src/systemctl/systemctl.c |   43 +++++++++++++++++++++++++---
 5 files changed, 149 insertions(+), 9 deletions(-)
 create mode 100644 src/shared/reboot-param.c
 create mode 100644 src/shared/reboot-param.h

diff --git a/Makefile.am b/Makefile.am
index ed61884..db79069 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -752,7 +752,9 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/ptyfwd.c \
 	src/shared/ptyfwd.h \
 	src/shared/net-util.c \
-	src/shared/net-util.h
+	src/shared/net-util.h \
+	src/shared/reboot-param.c \
+	src/shared/reboot-param.h
 
 #-------------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index aa9548e..7f82446 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -47,6 +47,7 @@
 #include "watchdog.h"
 #include "killall.h"
 #include "cgroup-util.h"
+#include "reboot-param.h"
 
 #define FINALIZE_ATTEMPTS 50
 
@@ -133,9 +134,10 @@ 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;
+        bool in_container, use_watchdog, with_param = false;
         _cleanup_free_ char *line = NULL, *cgroup = NULL;
         char *arguments[3];
+        char param[LINE_MAX];
         unsigned retries;
         int cmd, r;
 
@@ -173,9 +175,11 @@ int main(int argc, char *argv[]) {
 
         in_container = detect_container(NULL) > 0;
 
-        if (streq(argv[1], "reboot"))
+        if (streq(argv[1], "reboot")) {
                 cmd = RB_AUTOBOOT;
-        else if (streq(argv[1], "poweroff"))
+                if (reboot_get_param(param, sizeof(param)) > 0)
+                        with_param = true;
+        } else if (streq(argv[1], "poweroff"))
                 cmd = RB_POWER_OFF;
         else if (streq(argv[1], "halt"))
                 cmd = RB_HALT_SYSTEM;
@@ -337,7 +341,10 @@ int main(int argc, char *argv[]) {
                 cmd = RB_AUTOBOOT;
         }
 
-        reboot(cmd);
+        if (with_param)
+                reboot_with_param(param);
+        else
+                reboot(cmd);
 
         if (errno == EPERM && in_container) {
                 /* If we are in a container, and we lacked
diff --git a/src/shared/reboot-param.c b/src/shared/reboot-param.c
new file mode 100644
index 0000000..55f64dd
--- /dev/null
+++ b/src/shared/reboot-param.c
@@ -0,0 +1,68 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Samsung Electronics
+
+  Author: WaLyong Cho <walyong....@samsung.com>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/reboot.h>
+#include <linux/reboot.h>
+#include <sys/syscall.h>
+
+#include "reboot-param.h"
+#include "util.h"
+
+#define REBOOT_PARAM "/run/systemd/reboot-param"
+
+int reboot_set_param(const char *param) {
+        _cleanup_fclose_ FILE *f = NULL;
+
+        f = fopen(REBOOT_PARAM, "w");
+        if (!f) {
+                log_error("Failed to create %s: %m", REBOOT_PARAM);
+                return -errno;
+        }
+        fputs(param, f);
+        if (fflush(f)) {
+                log_error("Failed to flush %s: %m", REBOOT_PARAM);
+                return -errno;
+        }
+
+        return 0;
+}
+
+int reboot_get_param(char *param, int len) {
+        _cleanup_fclose_ FILE *f = NULL;
+
+        f = fopen(REBOOT_PARAM, "r");
+        if (f == NULL )
+                return 0;
+
+        if (!fgets(param, len, f)) {
+                log_error("Failed to read reboot param: %m");
+                return -errno;
+        }
+
+        return 1;
+}
+
+long int reboot_with_param(const char *param) {
+        return syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                       LINUX_REBOOT_CMD_RESTART2, param);
+}
diff --git a/src/shared/reboot-param.h b/src/shared/reboot-param.h
new file mode 100644
index 0000000..78dcd88
--- /dev/null
+++ b/src/shared/reboot-param.h
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Samsung Electronics
+
+  Author: WaLyong Cho <walyong....@samsung.com>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+int reboot_set_param(const char *param);
+int reboot_get_param(char *param, int len);
+long int reboot_with_param(const char *param);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 9f5e273..6f5700f 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -67,6 +67,7 @@
 #include "path-util.h"
 #include "socket-util.h"
 #include "fileio.h"
+#include "reboot-param.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
@@ -4804,7 +4805,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"
-               "  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"
@@ -4818,7 +4819,7 @@ static int systemctl_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"
@@ -4829,6 +4830,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,
+               arg_action == ACTION_REBOOT   ? " [ARG]" : "",
                arg_action == ACTION_REBOOT   ? "Reboot" :
                arg_action == ACTION_POWEROFF ? "Power off" :
                                                "Halt");
@@ -5235,6 +5237,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
 }
 
 static int halt_parse_argv(int argc, char *argv[]) {
+        _cleanup_fclose_ FILE *f = NULL;
+        int r;
+        const char *param;
 
         enum {
                 ARG_HELP = 0x100,
@@ -5315,6 +5320,28 @@ static int halt_parse_argv(int argc, char *argv[]) {
                 }
         }
 
+        param = argv[optind];
+
+        if (param != NULL) {
+                switch(arg_action) {
+
+                case ACTION_REBOOT:
+                        if (argc-optind != 1)
+                                log_error("Too many arguments.");
+                        else {
+                                if ((r = reboot_set_param(param)) < 0) {
+                                        log_error("Failed to set reboot param '%s'.", param);
+                                        return r;
+                                }
+                                argc--;
+                        }
+                        break;
+
+                default:
+                        break;
+                }
+        }
+
         if (optind < argc) {
                 log_error("Too many arguments.");
                 return -EINVAL;
@@ -5953,6 +5980,9 @@ done:
 
 static _noreturn_ void halt_now(enum action a) {
 
+        _cleanup_fclose_ FILE *f = NULL;
+        char param[LINE_MAX];
+
        /* Make sure C-A-D is handled by the kernel from this
          * point on... */
         reboot(RB_ENABLE_CAD);
@@ -5970,8 +6000,13 @@ static _noreturn_ void halt_now(enum action a) {
                 break;
 
         case ACTION_REBOOT:
-                log_info("Rebooting.");
-                reboot(RB_AUTOBOOT);
+                if (reboot_get_param(param, sizeof(param)) > 0) {
+                        log_info("Rebooting with arg '%s'.", param);
+                        reboot_with_param(param);
+                } else {
+                        log_info("Rebooting.");
+                        reboot(RB_AUTOBOOT);
+                }
                 break;
 
         default:
-- 
1.7.9.5

_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to