aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlfonso Sanchez-beato <alfonso.sanchez-beato@canonical.com>2017-05-31 08:34:04 +0200
committerBen Hutchings <ben@decadent.org.uk>2019-01-02 03:06:15 +0000
commit6b621b8705ce5901dcf49607c8a3523c9e521901 (patch)
tree51410286b6c5ff97a34af882e1edd0534a66156f
parent31810c21e6e7ee7c0478e80cee35b0b7e51de826 (diff)
downloadklibc-6b621b8705ce5901dcf49607c8a3523c9e521901.tar.gz
[klibc] Add support for reboot syscall argument
Add support to the reboot command so an argument for the 4th parameter of the syscall can be passed around. This can be useful in, say, devices that follow Android partitions conventions, so we can do things like rebootinig to the kernel in recovery partition with "reboot recovery". References: https://bugs.launchpad.net/ubuntu/+source/klibc/+bug/1692494 Link: https://www.zytor.com/pipermail/klibc/2017-May/003957.html Link: https://bugs.debian.org/863761 Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--usr/include/sys/reboot.h4
-rw-r--r--usr/klibc/reboot.c6
-rw-r--r--usr/utils/halt.c34
3 files changed, 25 insertions, 19 deletions
diff --git a/usr/include/sys/reboot.h b/usr/include/sys/reboot.h
index 3337d2731c7166..b46a1c555f99ab 100644
--- a/usr/include/sys/reboot.h
+++ b/usr/include/sys/reboot.h
@@ -16,8 +16,8 @@
#define RB_DISABLE_CAD LINUX_REBOOT_CMD_CAD_OFF
#define RB_POWER_OFF LINUX_REBOOT_CMD_POWER_OFF
-/* glibc-ish one-argument version */
-__extern int reboot(int);
+/* two-arguments version of reboot */
+__extern int reboot(int, void *);
/* Native four-argument system call */
__extern int __reboot(int, int, int, void *);
diff --git a/usr/klibc/reboot.c b/usr/klibc/reboot.c
index 5795dc3c5f0444..5aab039044a033 100644
--- a/usr/klibc/reboot.c
+++ b/usr/klibc/reboot.c
@@ -6,10 +6,10 @@
#include <sys/reboot.h>
#include <sys/syscall.h>
-/* This provides the one-argument glibc-ish version of reboot.
+/* This provides two-argument reboot function (glibc flag plus reboot argument).
The full four-argument system call is available as __reboot(). */
-int reboot(int flag)
+int reboot(int flag, void *arg)
{
- return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, flag, NULL);
+ return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, flag, arg);
}
diff --git a/usr/utils/halt.c b/usr/utils/halt.c
index eed0a460491348..368f095221713a 100644
--- a/usr/utils/halt.c
+++ b/usr/utils/halt.c
@@ -6,7 +6,7 @@
static __noreturn usage(void)
{
- static char mesg[] = "Usage: {halt|reboot|poweroff} [-n]\n";
+ static char mesg[] = "Usage: {halt|reboot|poweroff} [-n] [reboot-arg]\n";
write(2, mesg, sizeof(mesg) - 1);
exit(1);
}
@@ -16,6 +16,7 @@ int main(int argc, char *argv[])
int cmd = 0; /* initalize to shut gcc up */
int do_sync = 1;
char *ptr, *ptr2;
+ char *reboot_arg = NULL;
/* Which action (program name)? */
ptr2 = ptr = argv[0];
@@ -32,23 +33,28 @@ int main(int argc, char *argv[])
usage();
/* Walk options */
- while (*++argv && **argv == '-')
- switch (*++*argv) {
- case 'f':
- break; /* -f assumed */
- case 'n':
- do_sync = 0;
- break;
- default:
- usage();
+ while (*++argv)
+ if (**argv == '-') {
+ switch (*++*argv) {
+ case 'f':
+ break; /* -f assumed */
+ case 'n':
+ do_sync = 0;
+ break;
+ default:
+ usage();
+ }
+ } else if (cmd == LINUX_REBOOT_CMD_RESTART) {
+ reboot_arg = *argv;
+ cmd = LINUX_REBOOT_CMD_RESTART2;
+ } else {
+ usage(); /* args, not reboot == error */
}
- if (*argv)
- usage(); /* any args == error */
if (do_sync)
sync();
- reboot(LINUX_REBOOT_CMD_CAD_OFF); /* Enable CTRL+ALT+DEL */
- if (!reboot(cmd)) {
+ reboot(LINUX_REBOOT_CMD_CAD_OFF, NULL); /* Enable CTRL+ALT+DEL */
+ if (!reboot(cmd, reboot_arg)) {
/* Success. Currently, CMD_HALT returns, so stop the world */
/* kill(-1, SIGSTOP); */
kill(getpid(), SIGSTOP);