Description: 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". Author: Alfonso Sanchez-beato Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/klibc/+bug/1692494 Forwarded: http://www.zytor.com/pipermail/klibc/2017-May/003957.html Last-Update: 2017-05-22 --- klibc-2.0.4.orig/usr/include/sys/reboot.h +++ klibc-2.0.4/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 *); --- klibc-2.0.4.orig/usr/klibc/reboot.c +++ klibc-2.0.4/usr/klibc/reboot.c @@ -6,10 +6,10 @@ #include #include -/* 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); } --- klibc-2.0.4.orig/usr/utils/halt.c +++ klibc-2.0.4/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);