From 37185ec80ad372907a2a9388735655a7334babb6 Mon Sep 17 00:00:00 2001 From: WaLyong Cho Date: Wed, 6 Nov 2013 17:02:41 +0900 Subject: [PATCH] Support additional argument in reboot 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 | 12 +++++++++++- src/core/shutdown.c | 15 +++++++++++---- src/shared/def.h | 2 ++ src/systemctl/systemctl.c | 30 ++++++++++++++++++++++++------ 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index c7313edcc..7f1e98f5c 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1179,7 +1179,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service - reboot + reboot arg 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. + + If the optional argument + arg is given, it will be passed + as the optional argument to the + reboot2 + system call. The value is architecture and firmware + specific. As an example, recovery might + be used to trigger system recovery, and + fota might be used to trigger a + firmware over the air update. diff --git a/src/core/shutdown.c b/src/core/shutdown.c index aa9548e2a..377c1971a 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 "def.h" #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; - _cleanup_free_ char *line = NULL, *cgroup = NULL; + _cleanup_free_ char *line = NULL, *cgroup = NULL, *param = NULL; char *arguments[3]; unsigned retries; int cmd, r; @@ -173,9 +174,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 this fails, that's OK */ + read_one_line_file(REBOOT_PARAM_FILE, ¶m); + } else if (streq(argv[1], "poweroff")) 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; } - 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 diff --git a/src/shared/def.h b/src/shared/def.h index edd0bcf7a..46b88a8a4 100644 --- a/src/shared/def.h +++ b/src/shared/def.h @@ -38,3 +38,5 @@ #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS + +#define REBOOT_PARAM_FILE "/run/systemd/reboot-param" diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 9d22aad28..6170cc93d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -20,6 +20,8 @@ ***/ #include +#include +#include #include #include #include @@ -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" - " 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 +4820,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 +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, + arg_action == ACTION_REBOOT ? " [ARG]" : "", 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); @@ -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; } @@ -5944,6 +5954,8 @@ done: 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); @@ -5961,8 +5973,14 @@ static _noreturn_ void halt_now(enum action a) { break; case ACTION_REBOOT: - log_info("Rebooting."); - reboot(RB_AUTOBOOT); + if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) == 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: -- 2.30.2