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.
</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
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>
#include "watchdog.h"
#include "killall.h"
#include "cgroup-util.h"
#include "watchdog.h"
#include "killall.h"
#include "cgroup-util.h"
#define FINALIZE_ATTEMPTS 50
#define FINALIZE_ATTEMPTS 50
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;
in_container = detect_container(NULL) > 0;
in_container = detect_container(NULL) > 0;
- if (streq(argv[1], "reboot"))
+ if (streq(argv[1], "reboot")) {
- 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;
cmd = RB_POWER_OFF;
else if (streq(argv[1], "halt"))
cmd = RB_HALT_SYSTEM;
+ 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
#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"
***/
#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>
" 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"
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"
" -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");
assert(argc >= 0);
assert(argv);
assert(argc >= 0);
assert(argv);
+ 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;
}
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);
break;
case ACTION_REBOOT:
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);
+ }