1 /*
2 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
3 * Copyright 1993 by David Wexelblat <dwex@goblin.org>
4 * Copyright 1999 by David Holland <davidh@iquest.net>
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that copyright
9 * notice and this permission notice appear in supporting documentation, and
10 * that the names of the copyright holders not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. The copyright holders make no representations
13 * about the suitability of this software for any purpose. It is provided "as
14 * is" without express or implied warranty.
15 *
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND IN NO
18 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25 #ifdef HAVE_XORG_CONFIG_H
26 #include <xorg-config.h>
27 #endif
28
29 #include "xf86.h"
30 #include "xf86Priv.h"
31 #include "xf86_OSlib.h"
32 #ifdef HAVE_SYS_KD_H
33 #include <sys/kd.h>
34 #endif
35
36 /*
37 * Applications see VT number as consecutive integers starting from 1.
38 * VT number VT device
39 * -------------------------------------------------------
40 * 1 : /dev/vt/0 (Alt + Ctrl + F1)
41 * 2 : /dev/vt/2 (Alt + Ctrl + F2)
42 * 3 : /dev/vt/3 (Alt + Ctrl + F3)
43 * ... ...
44 */
45 #define CONSOLE_VTNO 1
46 #define SOL_CONSOLE_DEV "/dev/console"
47
48 static Bool KeepTty = FALSE;
49 static Bool UseConsole = FALSE;
50
51 #ifdef HAS_USL_VTS
52 static int VTnum = -1;
53 static int xf86StartVT = -1;
54 static int vtEnabled = 0;
55 #endif
56
57 /* Device to open as xf86Info.consoleFd */
58 static char consoleDev[PATH_MAX] = "/dev/fb";
59
60 /* Set by -dev argument on CLI
61 Used by hw/xfree86/common/xf86AutoConfig.c for VIS_GETIDENTIFIER */
62 _X_HIDDEN char xf86SolarisFbDev[PATH_MAX] = "/dev/fb";
63
64 static void
switch_to(int vt,const char * from)65 switch_to(int vt, const char *from)
66 {
67 int ret;
68
69 SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_ACTIVATE, vt));
70 if (ret != 0)
71 xf86Msg(X_WARNING, "%s: VT_ACTIVATE failed: %s\n",
72 from, strerror(errno));
73
74 SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_WAITACTIVE, vt));
75 if (ret != 0)
76 xf86Msg(X_WARNING, "%s: VT_WAITACTIVE failed: %s\n",
77 from, strerror(errno));
78 }
79
80 void
xf86OpenConsole(void)81 xf86OpenConsole(void)
82 {
83 int i;
84
85 #ifdef HAS_USL_VTS
86 int fd;
87 struct vt_mode VT;
88 struct vt_stat vtinfo;
89 MessageType from = X_PROBED;
90 #endif
91
92 if (serverGeneration == 1) {
93 /* Check if we're run with euid==0 */
94 if (geteuid() != 0)
95 FatalError("xf86OpenConsole: Server must be suid root\n");
96
97 #ifdef HAS_USL_VTS
98
99 /*
100 * Setup the virtual terminal manager
101 */
102 if ((fd = open("/dev/vt/0", O_RDWR, 0)) == -1) {
103 xf86ErrorF("xf86OpenConsole: Cannot open /dev/vt/0 (%s)\n",
104 strerror(errno));
105 vtEnabled = 0;
106 }
107 else {
108 if (ioctl(fd, VT_ENABLED, &vtEnabled) < 0) {
109 xf86ErrorF("xf86OpenConsole: VT_ENABLED failed (%s)\n",
110 strerror(errno));
111 vtEnabled = 0;
112 }
113 }
114 #endif /* HAS_USL_VTS */
115
116 if (UseConsole) {
117 strlcpy(consoleDev, SOL_CONSOLE_DEV, sizeof(consoleDev));
118
119 #ifdef HAS_USL_VTS
120 xf86Info.vtno = CONSOLE_VTNO;
121
122 if (vtEnabled == 0) {
123 xf86StartVT = 0;
124 }
125 else {
126 if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
127 FatalError
128 ("xf86OpenConsole: Cannot determine current VT\n");
129 xf86StartVT = vtinfo.v_active;
130 }
131 #endif /* HAS_USL_VTS */
132 goto OPENCONSOLE;
133 }
134
135 #ifdef HAS_USL_VTS
136 if (vtEnabled == 0) {
137 /* VT not enabled - kernel too old or Sparc platforms
138 without visual_io support */
139 xf86Msg(from, "VT infrastructure is not available\n");
140
141 xf86StartVT = 0;
142 xf86Info.vtno = 0;
143 strlcpy(consoleDev, xf86SolarisFbDev, sizeof(consoleDev));
144 goto OPENCONSOLE;
145 }
146
147 if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
148 FatalError("xf86OpenConsole: Cannot determine current VT\n");
149
150 xf86StartVT = vtinfo.v_active;
151
152 if (VTnum != -1) {
153 xf86Info.vtno = VTnum;
154 from = X_CMDLINE;
155 }
156 else if (xf86Info.ShareVTs) {
157 xf86Info.vtno = vtinfo.v_active;
158 from = X_CMDLINE;
159 }
160 else {
161 if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
162 (xf86Info.vtno == -1)) {
163 FatalError("xf86OpenConsole: Cannot find a free VT\n");
164 }
165 }
166
167 xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
168 snprintf(consoleDev, PATH_MAX, "/dev/vt/%d", xf86Info.vtno);
169
170 if (fd != -1) {
171 close(fd);
172 }
173
174 #endif /* HAS_USL_VTS */
175
176 OPENCONSOLE:
177 if (!KeepTty)
178 setpgrp();
179
180 if (((xf86Info.consoleFd = open(consoleDev, O_RDWR | O_NDELAY, 0)) < 0))
181 FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
182 consoleDev, strerror(errno));
183
184 /* Change ownership of the vt or console */
185 chown(consoleDev, getuid(), getgid());
186
187 #ifdef HAS_USL_VTS
188 if (xf86Info.ShareVTs)
189 return;
190
191 if (vtEnabled) {
192 /*
193 * Now get the VT
194 */
195 switch_to(xf86Info.vtno, "xf86OpenConsole");
196
197 #ifdef VT_SET_CONSUSER /* added in snv_139 */
198 if (strcmp(display, "0") == 0)
199 if (ioctl(xf86Info.consoleFd, VT_SET_CONSUSER) != 0)
200 xf86Msg(X_WARNING,
201 "xf86OpenConsole: VT_SET_CONSUSER failed\n");
202 #endif
203
204 if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
205 FatalError("xf86OpenConsole: VT_GETMODE failed\n");
206
207 OsSignal(SIGUSR1, xf86VTAcquire);
208 OsSignal(SIGUSR2, xf86VTRelease);
209
210 VT.mode = VT_PROCESS;
211 VT.acqsig = SIGUSR1;
212 VT.relsig = SIGUSR2;
213
214 if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
215 FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
216
217 if (ioctl(xf86Info.consoleFd, VT_SETDISPINFO, atoi(display)) < 0)
218 xf86Msg(X_WARNING, "xf86OpenConsole: VT_SETDISPINFO failed\n");
219 }
220 #endif
221
222 #ifdef KDSETMODE
223 SYSCALL(i = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
224 if (i < 0) {
225 xf86Msg(X_WARNING,
226 "xf86OpenConsole: KDSETMODE KD_GRAPHICS failed on %s (%s)\n",
227 consoleDev, strerror(errno));
228 }
229 #endif
230 }
231 else { /* serverGeneration != 1 */
232
233 #ifdef HAS_USL_VTS
234 if (vtEnabled && !xf86Info.ShareVTs) {
235 /*
236 * Now re-get the VT
237 */
238 if (xf86Info.autoVTSwitch)
239 switch_to(xf86Info.vtno, "xf86OpenConsole");
240
241 #ifdef VT_SET_CONSUSER /* added in snv_139 */
242 if (strcmp(display, "0") == 0)
243 if (ioctl(xf86Info.consoleFd, VT_SET_CONSUSER) != 0)
244 xf86Msg(X_WARNING,
245 "xf86OpenConsole: VT_SET_CONSUSER failed\n");
246 #endif
247
248 /*
249 * If the server doesn't have the VT when the reset occurs,
250 * this is to make sure we don't continue until the activate
251 * signal is received.
252 */
253 if (!xf86VTOwner())
254 sleep(5);
255 }
256 #endif /* HAS_USL_VTS */
257
258 }
259 }
260
261 void
xf86CloseConsole(void)262 xf86CloseConsole(void)
263 {
264 #ifdef HAS_USL_VTS
265 struct vt_mode VT;
266 #endif
267
268 #if !defined(__i386__) && !defined(__i386) && !defined(__x86)
269
270 if (!xf86DoConfigure) {
271 int fd;
272
273 /*
274 * Wipe out framebuffer just like the non-SI Xsun server does. This
275 * could be improved by saving framebuffer contents in
276 * xf86OpenConsole() above and restoring them here. Also, it's unclear
277 * at this point whether this should be done for all framebuffers in
278 * the system, rather than only the console.
279 */
280 if ((fd = open(xf86SolarisFbDev, O_RDWR, 0)) < 0) {
281 xf86Msg(X_WARNING,
282 "xf86CloseConsole(): unable to open framebuffer (%s)\n",
283 strerror(errno));
284 }
285 else {
286 struct fbgattr fbattr;
287
288 if ((ioctl(fd, FBIOGATTR, &fbattr) < 0) &&
289 (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0)) {
290 xf86Msg(X_WARNING,
291 "xf86CloseConsole(): unable to retrieve framebuffer"
292 " attributes (%s)\n", strerror(errno));
293 }
294 else {
295 void *fbdata;
296
297 fbdata = mmap(NULL, fbattr.fbtype.fb_size,
298 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
299 if (fbdata == MAP_FAILED) {
300 xf86Msg(X_WARNING,
301 "xf86CloseConsole(): unable to mmap framebuffer"
302 " (%s)\n", strerror(errno));
303 }
304 else {
305 memset(fbdata, 0, fbattr.fbtype.fb_size);
306 munmap(fbdata, fbattr.fbtype.fb_size);
307 }
308 }
309
310 close(fd);
311 }
312 }
313
314 #endif
315
316 #ifdef KDSETMODE
317 /* Reset the display back to text mode */
318 SYSCALL(ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
319 #endif
320
321 #ifdef HAS_USL_VTS
322 if (vtEnabled) {
323 if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) {
324 VT.mode = VT_AUTO; /* Set default vt handling */
325 ioctl(xf86Info.consoleFd, VT_SETMODE, &VT);
326 }
327
328 /* Activate the VT that X was started on */
329 if (xf86Info.autoVTSwitch)
330 switch_to(xf86StartVT, "xf86CloseConsole");
331 }
332 #endif /* HAS_USL_VTS */
333
334 close(xf86Info.consoleFd);
335 }
336
337 int
xf86ProcessArgument(int argc,char ** argv,int i)338 xf86ProcessArgument(int argc, char **argv, int i)
339 {
340 /*
341 * Keep server from detaching from controlling tty. This is useful when
342 * debugging, so the server can receive keyboard signals.
343 */
344 if (!strcmp(argv[i], "-keeptty")) {
345 KeepTty = TRUE;
346 return 1;
347 }
348
349 /*
350 * Use /dev/console as the console device.
351 */
352 if (!strcmp(argv[i], "-C")) {
353 UseConsole = TRUE;
354 return 1;
355 }
356
357 #ifdef HAS_USL_VTS
358
359 if ((argv[i][0] == 'v') && (argv[i][1] == 't')) {
360 if (sscanf(argv[i], "vt%d", &VTnum) == 0) {
361 UseMsg();
362 VTnum = -1;
363 return 0;
364 }
365
366 return 1;
367 }
368
369 #endif /* HAS_USL_VTS */
370
371 if ((i + 1) < argc) {
372 if (!strcmp(argv[i], "-dev")) {
373 strlcpy(xf86SolarisFbDev, argv[i + 1], sizeof(xf86SolarisFbDev));
374 return 2;
375 }
376 }
377
378 return 0;
379 }
380
381 void
xf86UseMsg(void)382 xf86UseMsg(void)
383 {
384 #ifdef HAS_USL_VTS
385 ErrorF("vtX Use the specified VT number\n");
386 #endif
387 ErrorF("-dev <fb> Framebuffer device\n");
388 ErrorF("-keeptty Don't detach controlling tty\n");
389 ErrorF(" (for debugging only)\n");
390 ErrorF("-C Use /dev/console as the console device\n");
391 }
392