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 48static Bool KeepTty = FALSE; 49static Bool UseConsole = FALSE; 50 51#ifdef HAS_USL_VTS 52static int VTnum = -1; 53static int xf86StartVT = -1; 54static int vtEnabled = 0; 55#endif 56 57/* Device to open as xf86Info.consoleFd */ 58static 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 64static void 65switch_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 80void 81xf86OpenConsole(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 261void 262xf86CloseConsole(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 337int 338xf86ProcessArgument(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 381void 382xf86UseMsg(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