summaryrefslogtreecommitdiff
blob: 4948806d9eb908b77e0b18135eea27a302e07734 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
halt: add a -k kexec flag

--- a/man/halt.8
+++ b/man/halt.8
@@ -40,6 +40,7 @@ halt, reboot, poweroff \- stop the system.
 .RB [ \-d ]
 .RB [ \-f ]
 .RB [ \-i ]
+.RB [ \-k ]
 .br
 .B /sbin/poweroff
 .RB [ \-n ]
@@ -83,6 +84,8 @@ Put all hard drives on the system in stand-by mode just before halt or power-off
 .IP \fB\-p\fP
 When halting the system, switch off the power. This is the default when halt is
 called as \fBpoweroff\fP.
+.IP \fB\-k\fP
+Try to reboot using \fBkexec\fP, if kernel supports it.
 .\"}}}
 .\"{{{  Diagnostics
 .SH DIAGNOSTICS
--- a/src/halt.c
+++ b/src/halt.c
@@ -8,7 +8,7 @@
  *		execute an "shutdown -r". This is for compatibility with
  *		sysvinit 2.4.
  *
- * Usage:	halt [-n] [-w] [-d] [-f] [-h] [-i] [-p]
+ * Usage:	halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] [-k]
  *		-n: don't sync before halting the system
  *		-w: only write a wtmp reboot record and exit.
  *		-d: don't write a wtmp record.
@@ -16,6 +16,7 @@
  *		-h: put harddisks in standby mode
  *		-i: shut down all network interfaces.
  *		-p: power down the system (if possible, otherwise halt).
+ *		-k: reboot the system using kexec.
  *
  *		Reboot and halt are both this program. Reboot
  *		is just a link to halt. Invoking the program
@@ -74,8 +75,10 @@ extern void write_wtmp(char *user, char *id, int pid, int type, char *line);
  */
 void usage(void)
 {
-	fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s\n",
-		progname, strcmp(progname, "halt") ? "" : " [-p]");
+	fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s%s\n",
+		progname,
+		strcmp(progname, "halt") ? "" : " [-p]",
+		strcmp(progname, "reboot") ? "" : " [-k]");
 	fprintf(stderr, "\t-n: don't sync before halting the system\n");
 	fprintf(stderr, "\t-w: only write a wtmp reboot record and exit.\n");
 	fprintf(stderr, "\t-d: don't write a wtmp record.\n");
@@ -84,6 +87,8 @@ void usage(void)
 	fprintf(stderr, "\t-i: shut down all network interfaces.\n");
 	if (!strcmp(progname, "halt"))
 		fprintf(stderr, "\t-p: power down the system (if possible, otherwise halt).\n");
+	if (!strcmp(progname, "reboot"))
+		fprintf(stderr, "\t-k: reboot the system using kexec.\n");
 	exit(1);
 }
 
@@ -182,6 +187,7 @@ int main(int argc, char **argv)
 	int do_ifdown = 0;
 	int do_hddown = 0;
 	int do_poweroff = 0;
+	int do_kexec = 0;
 	int c;
 	char *tm = NULL;
 
@@ -201,7 +207,7 @@ int main(int argc, char **argv)
 	/*
 	 *	Get flags
 	 */
-	while((c = getopt(argc, argv, ":ihdfnpwt:")) != EOF) {
+	while((c = getopt(argc, argv, ":ihdfnpwkt:")) != EOF) {
 		switch(c) {
 			case 'n':
 				do_sync = 0;
@@ -225,6 +231,9 @@ int main(int argc, char **argv)
 			case 'p':
 				do_poweroff = 1;
 				break;
+			case 'k':
+				do_kexec = 1;
+				break;
 			case 't':
 				tm = optarg;
 				break;
@@ -242,10 +251,24 @@ int main(int argc, char **argv)
 	(void)chdir("/");
 
 	if (!do_hard && !do_nothing) {
+		c = get_runlevel();
+
+		/*
+		 *	 We can't reboot using kexec through this path.
+		 */
+		if (c != '6' && do_reboot && do_kexec) {
+			fprintf(stderr, "ERROR: using -k at this"
+				" runlevel requires also -f\n"
+				"  (You probably want instead to reboot"
+				" normally and let your reboot\n"
+				"   script, usually /etc/init.d/reboot,"
+				" specify -k)\n");
+			exit(1);
+		}
+
 		/*
 		 *	See if we are in runlevel 0 or 6.
 		 */
-		c = get_runlevel();
 		if (c != '0' && c != '6')
 			do_shutdown(do_reboot ? "-r" : "-h", tm);
 	}
@@ -277,6 +300,15 @@ int main(int argc, char **argv)
 	if (do_nothing) exit(0);
 
 	if (do_reboot) {
+		/*
+		 *	kexec or reboot
+		 */
+		if (do_kexec)
+			init_reboot(BMAGIC_KEXEC);
+
+		/*
+		 *	Fall through if failed
+		 */
 		init_reboot(BMAGIC_REBOOT);
 	} else {
 		/*
--- a/src/reboot.h
+++ b/src/reboot.h
@@ -47,5 +47,8 @@
 #  define BMAGIC_POWEROFF	BMAGIC_HALT
 #endif
 
+/* for kexec support */
+#define BMAGIC_KEXEC  0x45584543
+
 #define init_reboot(magic)	reboot(magic)