--- README.swsusp +++ README.swsusp 2005-10-19 13:52:54.000000000 +0200 @@ -0,0 +1,5 @@ + This version of sysvinit contains a patch for supporting the + Software suspend feature for Linux. + In order to really use it, you need to patch your kernel + with Gabor Kuti's software-suspend patch: + http://falcon.sch.bme.hu/~seasons/linux/ --- man/halt.8 +++ man/halt.8 2005-10-19 13:52:54.000000000 +0200 @@ -4,7 +4,7 @@ .\"}}} .\"{{{ Name .SH NAME -halt, reboot, poweroff \- stop the system. +halt, reboot, poweroff, suspend \- stop the system. .\"}}} .\"{{{ Synopsis .SH SYNOPSIS @@ -31,12 +31,16 @@ .RB [ \-f ] .RB [ \-i ] .RB [ \-h ] +.br +.B /sbin/swsusp +.RB [ \-w ] +.RB [ \-d ] .\"}}} .\"{{{ Description .SH DESCRIPTION \fBHalt\fP notes that the system is being brought down in the file -\fI/var/log/wtmp\fP, and then either tells the kernel to halt, reboot or -poweroff the system. +\fI/var/log/wtmp\fP, and then either tells the kernel to halt, reboot, poweroff, +or suspend the system. .PP If \fBhalt\fP or \fBreboot\fP is called when the system is \fInot\fP in runlevel \fB0\fP or \fB6\fP, in other words when it's running --- man/inittab.5 +++ man/inittab.5 2005-10-19 13:52:54.000000000 +0200 @@ -137,6 +137,13 @@ the external UPS is almost empty and the power is failing (provided that the external UPS and the monitoring process are able to detect this condition). .\"}}} +.\"{{{ resume +.IP \fBresume\fP +This process will be executed when \fBinit\fP is told by the kernel that +Software Suspend has resumed the machine. This way you may specify userland +programs what can restore hardware states the kernel cannot (for example +svgatextmode and hdparm). +.\"}}} .\"{{{ ctrlaltdel .IP \fBctrlaltdel\fP The process will be executed when \fBinit\fP receives the SIGINT signal. --- man/shutdown.8 +++ man/shutdown.8 2005-10-19 13:52:54.000000000 +0200 @@ -11,7 +11,7 @@ .B /sbin/shutdown .RB [ \-t .IR sec ] -.RB [ \-arkhncfFHP ] +.RB [ \-arkhzncfFHP ] .I time .RI [ warning-message ] .\"}}} @@ -71,6 +71,12 @@ The use of this option is discouraged, and its results are not always what you'd expect. .\"}}} +.\"{{{ -z +.IP \fB\-z\fP +Shutdown using software suspend. Using this option will not kill processes +but pass the control to the kernel what makes the proper steps to stop and +save processes to swaps. 'Software\ Suspend' needs to be compiled in. +.\"}}} .\"{{{ -f .IP \fB\-f\fP Skip fsck on reboot. --- man/swsusp.8 +++ man/swsusp.8 2005-10-19 13:52:54.000000000 +0200 @@ -0,0 +1 @@ +.so man8/halt.8 --- src/Makefile +++ src/Makefile 2005-10-19 13:54:38.000000000 +0200 @@ -52,7 +52,7 @@ SBIN += sulogin USRBIN += utmpdump MAN1 += mountpoint.1 -MAN8 += sulogin.8 +MAN8 += sulogin.8 swsusp.8 endif BIN_OWNER = root @@ -131,6 +131,7 @@ for i in $(USRBIN); do \ $(INSTALL) -m 755 $$i $(ROOT)/usr/bin/; \ done + ln -sf halt $(ROOT)/sbin/swsusp ln -sf halt $(ROOT)/sbin/reboot ln -sf halt $(ROOT)/sbin/poweroff ln -sf init $(ROOT)/sbin/telinit --- src/dowall.c +++ src/dowall.c 2005-10-19 13:52:54.000000000 +0200 @@ -27,6 +27,7 @@ #include #include #include +#include static sigjmp_buf jbuf; @@ -214,6 +215,7 @@ if (tp != NULL) fclose(tp); } endutent(); + sched_yield(); exit(0); } --- src/halt.c +++ src/halt.c 2005-10-19 13:52:54.000000000 +0200 @@ -172,6 +172,7 @@ int do_ifdown = 0; int do_hddown = 0; int do_poweroff = 0; + int do_swsusp = 0; int c; char *tm = NULL; @@ -185,6 +186,7 @@ if (!strcmp(progname, "reboot")) do_reboot = 1; if (!strcmp(progname, "poweroff")) do_poweroff = 1; + if (!strcmp(progname, "swsusp")) do_swsusp = 1; /* * Get flags @@ -220,6 +222,14 @@ usage(); } } + if(do_swsusp) { /* This implies some flags.. */ + do_sync = 0; + do_ifdown = 0; + do_poweroff = 0; + do_reboot = 0; + do_hard = 1; + } + if (argc != optind) usage(); if (geteuid() != 0) { @@ -264,6 +274,8 @@ if (do_reboot) { init_reboot(BMAGIC_REBOOT); + } else if(do_swsusp) { + init_reboot(BMAGIC_SWSUSP); } else { /* * Turn on hard reboot, CTRL-ALT-DEL will reboot now --- src/init.c +++ src/init.c 2005-10-19 13:52:54.000000000 +0200 @@ -85,6 +85,10 @@ # define CBAUDEX 0 #endif +#ifndef SIGRESUME +# define SIGRESUME SIGXCPU +#endif + /* Set a signal handler. */ #define SETSIG(sa, sig, fun, flags) \ do { \ @@ -143,7 +147,7 @@ /* Macro to see if this is a special action */ #define ISPOWER(i) ((i) == POWERWAIT || (i) == POWERFAIL || \ (i) == POWEROKWAIT || (i) == POWERFAILNOW || \ - (i) == CTRLALTDEL) + (i) == CTRLALTDEL || (i) == RESUME) /* ascii values for the `action' field. */ struct actions { @@ -165,6 +169,7 @@ { "initdefault", INITDEFAULT }, { "sysinit", SYSINIT }, { "kbrequest", KBREQUEST }, + { "resume", RESUME }, { NULL, 0 }, }; @@ -1129,6 +1134,7 @@ case POWERWAIT: case POWERFAILNOW: case POWEROKWAIT: + case RESUME: case CTRLALTDEL: if (!(ch->flags & XECUTED)) ch->flags |= WAITING; case KBREQUEST: @@ -1822,6 +1828,22 @@ } /* + * Start up userland hwstate restoring. + */ +void do_hwstate_restore(void) +{ + CHILD *ch; + + /* + * Tell resume entries to start up + */ + for (ch = family; ch; ch = ch->next) { + if (ch->action == RESUME) + ch->flags &= ~XECUTED; + } +} + +/* * Start up powerfail entries. */ static @@ -2318,6 +2340,14 @@ int fd; char c; + if (ISMEMBER(got_signals, SIGRESUME)) { +#if DEBUG + log(L_VB, "got SIGRESUME"); +#endif + do_hwstate_restore(); + DELSET(got_signals, SIGRESUME); + } + if (ISMEMBER(got_signals, SIGPWR)) { INITDBG(L_VB, "got SIGPWR"); /* See _what_ kind of SIGPWR this is. */ @@ -2474,6 +2504,7 @@ SETSIG(sa, SIGPWR, signal_handler, 0); SETSIG(sa, SIGWINCH, signal_handler, 0); SETSIG(sa, SIGUSR1, signal_handler, 0); + SETSIG(sa, SIGRESUME,signal_handler, 0); SETSIG(sa, SIGSTOP, stop_handler, SA_RESTART); SETSIG(sa, SIGTSTP, stop_handler, SA_RESTART); SETSIG(sa, SIGCONT, cont_handler, SA_RESTART); --- src/init.h +++ src/init.h 2005-10-19 13:52:54.000000000 +0200 @@ -53,6 +53,7 @@ #define SYSINIT 13 #define POWERFAILNOW 14 #define KBREQUEST 15 +#define RESUME 16 /* Information about a process in the in-core inittab */ typedef struct _child_ { --- src/reboot.h +++ src/reboot.h 2005-10-19 13:52:54.000000000 +0200 @@ -32,5 +32,9 @@ # define BMAGIC_POWEROFF BMAGIC_HALT #endif +#ifndef BMAGIC_SWSUSP +# define BMAGIC_SWSUSP 0xd000fce2 +#endif + #define init_reboot(magic) reboot(magic) --- src/shutdown.c +++ src/shutdown.c 2005-10-19 13:52:54.000000000 +0200 @@ -1,10 +1,11 @@ /* * shutdown.c Shut the system down. * - * Usage: shutdown [-krhfnc] time [warning message] + * Usage: shutdown [-krhzfnc] time [warning message] * -k: don't really shutdown, only warn. * -r: reboot after shutdown. * -h: halt after shutdown. + * -z: shutdown using software suspend. * -f: do a 'fast' reboot (skip fsck). * -F: Force fsck on reboot. * -n: do not go through init but do it ourselves. @@ -113,6 +114,7 @@ "\t\t -f: do a 'fast' reboot (skip fsck).\n" "\t\t -F: Force fsck on reboot.\n" "\t\t -n: do not go through \"init\" but go down real fast.\n" + "\t\t -z: shutdown using software suspend.\n" "\t\t -c: cancel a running shutdown.\n" "\t\t -t secs: delay between warning and kill signal.\n" "\t\t ** the \"time\" argument is mandatory! (try \"now\") **\n"); @@ -271,6 +273,7 @@ void fastdown() { int do_halt = (down_level[0] == '0'); + int do_swsusp = (down_level[0] == 'z'); int i; #if 0 char cmd[128]; @@ -293,6 +296,8 @@ script = REBOOTSCRIPT2; } #endif + if(do_swsusp) + init_reboot(BMAGIC_SWSUSP); /* First close all files. */ for(i = 0; i < 3; i++) @@ -364,7 +369,9 @@ int do_halt = (down_level[0] == '0'); /* Warn for the last time */ - warn(0); + /* I don't want to mess up the later resumed screen */ + if(down_level[0] != 'z') + warn(0); if (dontshut) { hardsleep(1); stopit(0); @@ -467,7 +474,7 @@ halttype = NULL; /* Process the options. */ - while((c = getopt(argc, argv, "HPacqkrhnfFyt:g:i:")) != EOF) { + while((c = getopt(argc, argv, "HPacqkrhnzfFyt:g:i:")) != EOF) { switch(c) { case 'H': halttype = "HALT"; @@ -499,6 +506,9 @@ case 'n': /* Don't switch runlevels. */ doself = 1; break; + case 'z': /* Shutdown using software suspend */ + down_level[0] = 'z'; + break; case 't': /* Delay between TERM and KILL */ sltime = optarg; break; @@ -592,6 +602,18 @@ } if (message[0]) strcat(message, "\r\n"); + if(down_level[0] == 'z') { + doself = 1; + if(fastboot) { + fprintf(stderr, "shutdown: -f option ignored"); + fastboot = 0; + } + if(forcefsck) { + fprintf(stderr, "shutdown: -F option ignored"); + forcefsck = 0; + } + } + /* See if we want to run or cancel. */ if (cancel) { if (pid <= 0) { @@ -621,7 +643,8 @@ } /* Extra check. */ - if (doself && down_level[0] != '0' && down_level[0] != '6') { + if (doself && down_level[0] != '0' && down_level[0] != '6' && + down_level[0] != 'z') { fprintf(stderr, "shutdown: can use \"-n\" for halt or reboot only.\r\n"); exit(1); @@ -638,6 +661,9 @@ case '1': strcpy(newstate, "to maintenance mode"); break; + case 'z': + strcpy(newstate, "for system suspend"); + break; default: sprintf(newstate, "to runlevel %s", down_level); break;