12089Ssos/*- 2228976Suqs * Copyright (c) 1994-1996 S��ren Schmidt 32089Ssos * All rights reserved. 42089Ssos * 5146736Sdelphij * Portions of this software are based in part on the work of 6146736Sdelphij * Sascha Wildner <saw@online.de> contributed to The DragonFly Project 7146736Sdelphij * 82089Ssos * Redistribution and use in source and binary forms, with or without 92089Ssos * modification, are permitted provided that the following conditions 102089Ssos * are met: 112089Ssos * 1. Redistributions of source code must retain the above copyright 125994Ssos * notice, this list of conditions and the following disclaimer, 135994Ssos * in this position and unchanged. 142089Ssos * 2. Redistributions in binary form must reproduce the above copyright 152089Ssos * notice, this list of conditions and the following disclaimer in the 162089Ssos * documentation and/or other materials provided with the distribution. 172089Ssos * 3. The name of the author may not be used to endorse or promote products 1897748Sschweikh * derived from this software without specific prior written permission 192089Ssos * 202089Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 212089Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 222089Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 232089Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 242089Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 252089Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 262089Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 272089Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 282089Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 292089Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30146736Sdelphij * 31146736Sdelphij * $DragonFly: src/usr.sbin/vidcontrol/vidcontrol.c,v 1.10 2005/03/02 06:08:29 joerg Exp $ 322089Ssos */ 332089Ssos 3430764Scharnier#ifndef lint 3530764Scharnierstatic const char rcsid[] = 3650479Speter "$FreeBSD: releng/10.3/usr.sbin/vidcontrol/vidcontrol.c 286291 2015-08-04 15:15:06Z emaste $"; 3730764Scharnier#endif /* not lint */ 3830764Scharnier 392089Ssos#include <ctype.h> 4030764Scharnier#include <err.h> 4155849Syokota#include <limits.h> 422089Ssos#include <stdio.h> 4323457Sbrian#include <stdlib.h> 4430764Scharnier#include <string.h> 4523702Speter#include <unistd.h> 4666834Sphk#include <sys/fbio.h> 4766834Sphk#include <sys/consio.h> 48267540Sray#include <sys/endian.h> 492089Ssos#include <sys/errno.h> 50267540Sray#include <sys/param.h> 5175344Ssobomax#include <sys/types.h> 5275344Ssobomax#include <sys/stat.h> 53267540Sray#include <sys/sysctl.h> 542089Ssos#include "path.h" 5523457Sbrian#include "decode.h" 562089Ssos 5771642Ssobomax 58146736Sdelphij#define DATASIZE(x) ((x).w * (x).h * 256 / 8) 59146736Sdelphij 60102111Ssobomax/* Screen dump modes */ 61102111Ssobomax#define DUMP_FMT_RAW 1 62102111Ssobomax#define DUMP_FMT_TXT 2 63102111Ssobomax/* Screen dump options */ 64102111Ssobomax#define DUMP_FBF 0 65102111Ssobomax#define DUMP_ALL 1 66102111Ssobomax/* Screen dump file format revision */ 6776845Ssobomax#define DUMP_FMT_REV 1 6876845Ssobomax 69228425Sedstatic const char *legal_colors[16] = { 702089Ssos "black", "blue", "green", "cyan", 712089Ssos "red", "magenta", "brown", "white", 722089Ssos "grey", "lightblue", "lightgreen", "lightcyan", 732089Ssos "lightred", "lightmagenta", "yellow", "lightwhite" 746628Ssos}; 752089Ssos 76241737Sedstatic struct { 77146736Sdelphij int active_vty; 78146736Sdelphij vid_info_t console_info; 79146736Sdelphij unsigned char screen_map[256]; 80146736Sdelphij int video_mode_number; 81146736Sdelphij struct video_info video_mode_info; 82146736Sdelphij} cur_info; 832089Ssos 84267540Sraystruct vt4font_header { 85267540Sray uint8_t magic[8]; 86267540Sray uint8_t width; 87267540Sray uint8_t height; 88267540Sray uint16_t pad; 89267540Sray uint32_t glyph_count; 90267540Sray uint32_t map_count[4]; 91267540Sray} __packed; 92267540Sray 93228425Sedstatic int hex = 0; 94228425Sedstatic int vesa_cols; 95228425Sedstatic int vesa_rows; 96228425Sedstatic int font_height; 97228425Sedstatic int colors_changed; 98228425Sedstatic int video_mode_changed; 99228425Sedstatic int normal_fore_color, normal_back_color; 100228425Sedstatic int revers_fore_color, revers_back_color; 101267540Sraystatic int vt4_mode = 0; 102228425Sedstatic struct vid_info info; 103228425Sedstatic struct video_info new_mode_info; 104146736Sdelphij 105146736Sdelphij 106146736Sdelphij/* 107146736Sdelphij * Initialize revert data. 108146736Sdelphij * 109146736Sdelphij * NOTE: the following parameters are not yet saved/restored: 110146736Sdelphij * 111146736Sdelphij * screen saver timeout 112146736Sdelphij * cursor type 113146736Sdelphij * mouse character and mouse show/hide state 114146736Sdelphij * vty switching on/off state 115146736Sdelphij * history buffer size 116146736Sdelphij * history contents 117146736Sdelphij * font maps 118146736Sdelphij */ 119146736Sdelphij 12030764Scharnierstatic void 121146736Sdelphijinit(void) 122146736Sdelphij{ 123146736Sdelphij if (ioctl(0, VT_GETACTIVE, &cur_info.active_vty) == -1) 124146736Sdelphij errc(1, errno, "getting active vty"); 125146736Sdelphij 126146736Sdelphij cur_info.console_info.size = sizeof(cur_info.console_info); 127146736Sdelphij 128146736Sdelphij if (ioctl(0, CONS_GETINFO, &cur_info.console_info) == -1) 129146736Sdelphij errc(1, errno, "getting console information"); 130146736Sdelphij 131267540Sray /* vt(4) use unicode, so no screen mapping required. */ 132267540Sray if (vt4_mode == 0 && 133267540Sray ioctl(0, GIO_SCRNMAP, &cur_info.screen_map) == -1) 134146736Sdelphij errc(1, errno, "getting screen map"); 135146736Sdelphij 136146736Sdelphij if (ioctl(0, CONS_GET, &cur_info.video_mode_number) == -1) 137146736Sdelphij errc(1, errno, "getting video mode number"); 138146736Sdelphij 139146736Sdelphij cur_info.video_mode_info.vi_mode = cur_info.video_mode_number; 140146736Sdelphij 141146736Sdelphij if (ioctl(0, CONS_MODEINFO, &cur_info.video_mode_info) == -1) 142146736Sdelphij errc(1, errno, "getting video mode parameters"); 143146736Sdelphij 144146736Sdelphij normal_fore_color = cur_info.console_info.mv_norm.fore; 145146736Sdelphij normal_back_color = cur_info.console_info.mv_norm.back; 146146736Sdelphij revers_fore_color = cur_info.console_info.mv_rev.fore; 147146736Sdelphij revers_back_color = cur_info.console_info.mv_rev.back; 148146736Sdelphij} 149146736Sdelphij 150146736Sdelphij 151146736Sdelphij/* 152146736Sdelphij * If something goes wrong along the way we call revert() to go back to the 153146736Sdelphij * console state we came from (which is assumed to be working). 154146736Sdelphij * 155146736Sdelphij * NOTE: please also read the comments of init(). 156146736Sdelphij */ 157146736Sdelphij 158146736Sdelphijstatic void 159146736Sdelphijrevert(void) 160146736Sdelphij{ 161146736Sdelphij int size[3]; 162146736Sdelphij 163162671Sru ioctl(0, VT_ACTIVATE, cur_info.active_vty); 164146736Sdelphij 165146736Sdelphij fprintf(stderr, "\033[=%dA", cur_info.console_info.mv_ovscan); 166146736Sdelphij fprintf(stderr, "\033[=%dF", cur_info.console_info.mv_norm.fore); 167146736Sdelphij fprintf(stderr, "\033[=%dG", cur_info.console_info.mv_norm.back); 168146736Sdelphij fprintf(stderr, "\033[=%dH", cur_info.console_info.mv_rev.fore); 169146736Sdelphij fprintf(stderr, "\033[=%dI", cur_info.console_info.mv_rev.back); 170146736Sdelphij 171267540Sray if (vt4_mode == 0) 172267540Sray ioctl(0, PIO_SCRNMAP, &cur_info.screen_map); 173146736Sdelphij 174146736Sdelphij if (cur_info.video_mode_number >= M_VESA_BASE) 175146736Sdelphij ioctl(0, _IO('V', cur_info.video_mode_number - M_VESA_BASE), 176146736Sdelphij NULL); 177146736Sdelphij else 178146736Sdelphij ioctl(0, _IO('S', cur_info.video_mode_number), NULL); 179146736Sdelphij 180146736Sdelphij if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) { 181146736Sdelphij size[0] = cur_info.video_mode_info.vi_width / 8; 182146736Sdelphij size[1] = cur_info.video_mode_info.vi_height / 183146736Sdelphij cur_info.console_info.font_size; 184146736Sdelphij size[2] = cur_info.console_info.font_size; 185146736Sdelphij 186146736Sdelphij ioctl(0, KDRASTER, size); 187146736Sdelphij } 188146736Sdelphij} 189146736Sdelphij 190146736Sdelphij 191146736Sdelphij/* 192146736Sdelphij * Print a short usage string describing all options, then exit. 193146736Sdelphij */ 194146736Sdelphij 195146736Sdelphijstatic void 196140159Sdelphijusage(void) 1976628Ssos{ 198267540Sray if (vt4_mode) 199267540Sray fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 200273921Sdumbbell"usage: vidcontrol [-CHPpx] [-b color] [-c appearance] [-f [[size] file]]", 201267540Sray" [-g geometry] [-h size] [-i adapter | mode]", 202267540Sray" [-M char] [-m on | off] [-r foreground background]", 203267540Sray" [-S on | off] [-s number] [-T xterm | cons25] [-t N | off]", 204267540Sray" [mode] [foreground [background]] [show]"); 205267540Sray else 206267540Sray fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 207102111Ssobomax"usage: vidcontrol [-CdHLPpx] [-b color] [-c appearance] [-f [size] file]", 20877329Sdes" [-g geometry] [-h size] [-i adapter | mode] [-l screen_map]", 20999706Sdd" [-M char] [-m on | off] [-r foreground background]", 210199174Sed" [-S on | off] [-s number] [-T xterm | cons25] [-t N | off]", 211199174Sed" [mode] [foreground [background]] [show]"); 21230764Scharnier exit(1); 2136628Ssos} 2146628Ssos 215267540Sray/* Detect presence of vt(4). */ 216267540Sraystatic int 217267540Srayis_vt4(void) 218267540Sray{ 219268366Sray char vty_name[4] = ""; 220268366Sray size_t len = sizeof(vty_name); 221146736Sdelphij 222268366Sray if (sysctlbyname("kern.vty", vty_name, &len, NULL, 0) != 0) 223268366Sray return (0); 224268366Sray return (strcmp(vty_name, "vt") == 0); 225267540Sray} 226267540Sray 227146736Sdelphij/* 228146736Sdelphij * Retrieve the next argument from the command line (for options that require 229146736Sdelphij * more than one argument). 230146736Sdelphij */ 231146736Sdelphij 232140159Sdelphijstatic char * 23375344Ssobomaxnextarg(int ac, char **av, int *indp, int oc, int strict) 2342089Ssos{ 2352089Ssos if (*indp < ac) 2362089Ssos return(av[(*indp)++]); 237146736Sdelphij 238146736Sdelphij if (strict != 0) { 239146736Sdelphij revert(); 24075344Ssobomax errx(1, "option requires two arguments -- %c", oc); 241146736Sdelphij } 242146736Sdelphij 24375344Ssobomax return(NULL); 2442089Ssos} 2452089Ssos 246146736Sdelphij 247146736Sdelphij/* 248146736Sdelphij * Guess which file to open. Try to open each combination of a specified set 249146736Sdelphij * of file name components. 250146736Sdelphij */ 251146736Sdelphij 252140159Sdelphijstatic FILE * 253140159Sdelphijopenguess(const char *a[], const char *b[], const char *c[], const char *d[], char **name) 2542089Ssos{ 25592460Ssobomax FILE *f; 25692460Ssobomax int i, j, k, l; 2572089Ssos 25892460Ssobomax for (i = 0; a[i] != NULL; i++) { 25992460Ssobomax for (j = 0; b[j] != NULL; j++) { 26092460Ssobomax for (k = 0; c[k] != NULL; k++) { 26192460Ssobomax for (l = 0; d[l] != NULL; l++) { 262146736Sdelphij asprintf(name, "%s%s%s%s", 263146736Sdelphij a[i], b[j], c[k], d[l]); 264146736Sdelphij 26592460Ssobomax f = fopen(*name, "r"); 266146736Sdelphij 26792460Ssobomax if (f != NULL) 26892460Ssobomax return (f); 269146736Sdelphij 27092460Ssobomax free(*name); 27192460Ssobomax } 27292460Ssobomax } 27392460Ssobomax } 27452262Sbillf } 27592460Ssobomax return (NULL); 2762089Ssos} 2772089Ssos 278146736Sdelphij 279146736Sdelphij/* 280146736Sdelphij * Load a screenmap from a file and set it. 281146736Sdelphij */ 282146736Sdelphij 283140159Sdelphijstatic void 284140159Sdelphijload_scrnmap(const char *filename) 2852089Ssos{ 28692460Ssobomax FILE *fd; 28792460Ssobomax int size; 2882089Ssos char *name; 2892089Ssos scrmap_t scrnmap; 290140159Sdelphij const char *a[] = {"", SCRNMAP_PATH, NULL}; 291140159Sdelphij const char *b[] = {filename, NULL}; 292140159Sdelphij const char *c[] = {"", ".scm", NULL}; 293140159Sdelphij const char *d[] = {"", NULL}; 2942089Ssos 29592460Ssobomax fd = openguess(a, b, c, d, &name); 296146736Sdelphij 2972089Ssos if (fd == NULL) { 298146736Sdelphij revert(); 299146736Sdelphij errx(1, "screenmap file not found"); 3002089Ssos } 301146736Sdelphij 3022089Ssos size = sizeof(scrnmap); 303146736Sdelphij 30475344Ssobomax if (decode(fd, (char *)&scrnmap, size) != size) { 3052089Ssos rewind(fd); 306146736Sdelphij 307146736Sdelphij if (fread(&scrnmap, 1, size, fd) != (size_t)size) { 30830764Scharnier warnx("bad screenmap file"); 30923457Sbrian fclose(fd); 310146736Sdelphij revert(); 311146736Sdelphij errx(1, "bad screenmap file"); 3122089Ssos } 3132089Ssos } 314146736Sdelphij 315146736Sdelphij if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { 316146736Sdelphij revert(); 317146736Sdelphij errc(1, errno, "loading screenmap"); 318146736Sdelphij } 319146736Sdelphij 32023457Sbrian fclose(fd); 3212089Ssos} 3222089Ssos 323146736Sdelphij 324146736Sdelphij/* 325146736Sdelphij * Set the default screenmap. 326146736Sdelphij */ 327146736Sdelphij 328140159Sdelphijstatic void 329140159Sdelphijload_default_scrnmap(void) 3302089Ssos{ 3316628Ssos scrmap_t scrnmap; 3322089Ssos int i; 3332089Ssos 3342089Ssos for (i=0; i<256; i++) 3352089Ssos *((char*)&scrnmap + i) = i; 336146736Sdelphij 337146736Sdelphij if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { 338146736Sdelphij revert(); 339146736Sdelphij errc(1, errno, "loading default screenmap"); 340146736Sdelphij } 3412089Ssos} 3422089Ssos 343146736Sdelphij 344146736Sdelphij/* 345146736Sdelphij * Print the current screenmap to stdout. 346146736Sdelphij */ 347146736Sdelphij 348140159Sdelphijstatic void 349140159Sdelphijprint_scrnmap(void) 3502089Ssos{ 3512089Ssos unsigned char map[256]; 352140159Sdelphij size_t i; 3532089Ssos 354146736Sdelphij if (ioctl(0, GIO_SCRNMAP, &map) == -1) { 355146736Sdelphij revert(); 356146736Sdelphij errc(1, errno, "getting screenmap"); 3572089Ssos } 3582089Ssos for (i=0; i<sizeof(map); i++) { 359140159Sdelphij if (i != 0 && i % 16 == 0) 3602089Ssos fprintf(stdout, "\n"); 361146736Sdelphij 362146736Sdelphij if (hex != 0) 3638857Srgrimes fprintf(stdout, " %02x", map[i]); 3642089Ssos else 3652089Ssos fprintf(stdout, " %03d", map[i]); 3662089Ssos } 3672089Ssos fprintf(stdout, "\n"); 3682089Ssos 3692089Ssos} 3702089Ssos 371146736Sdelphij 372146736Sdelphij/* 373146736Sdelphij * Determine a file's size. 374146736Sdelphij */ 375146736Sdelphij 376140159Sdelphijstatic int 37775344Ssobomaxfsize(FILE *file) 37875344Ssobomax{ 37975344Ssobomax struct stat sb; 38075344Ssobomax 38175344Ssobomax if (fstat(fileno(file), &sb) == 0) 38275344Ssobomax return sb.st_size; 38375344Ssobomax else 38475344Ssobomax return -1; 38575344Ssobomax} 38675344Ssobomax 387267540Sraystatic vfnt_map_t * 388267540Srayload_vt4mappingtable(unsigned int nmappings, FILE *f) 389267540Sray{ 390267540Sray vfnt_map_t *t; 391267540Sray unsigned int i; 39275344Ssobomax 393267540Sray if (nmappings == 0) 394267540Sray return (NULL); 395267540Sray 396267540Sray t = malloc(sizeof *t * nmappings); 397267540Sray 398267540Sray if (fread(t, sizeof *t * nmappings, 1, f) != 1) { 399267540Sray perror("mappings"); 400267540Sray exit(1); 401267540Sray } 402267540Sray 403267540Sray for (i = 0; i < nmappings; i++) { 404267540Sray t[i].src = be32toh(t[i].src); 405267540Sray t[i].dst = be16toh(t[i].dst); 406267540Sray t[i].len = be16toh(t[i].len); 407267540Sray } 408267540Sray 409267540Sray return (t); 410267540Sray} 411267540Sray 412273921Sdumbbell/* 413273921Sdumbbell * Set the default vt font. 414273921Sdumbbell */ 415273921Sdumbbell 416273921Sdumbbellstatic void 417273921Sdumbbellload_default_vt4font(void) 418273921Sdumbbell{ 419273921Sdumbbell if (ioctl(0, PIO_VFONT_DEFAULT) == -1) { 420273921Sdumbbell revert(); 421273921Sdumbbell errc(1, errno, "loading default vt font"); 422273921Sdumbbell } 423273921Sdumbbell} 424273921Sdumbbell 425267540Sraystatic int 426267540Srayload_vt4font(FILE *f) 427267540Sray{ 428267540Sray struct vt4font_header fh; 429267540Sray static vfnt_t vfnt; 430267540Sray size_t glyphsize; 431267540Sray unsigned int i; 432267540Sray 433267540Sray if (fread(&fh, sizeof fh, 1, f) != 1) { 434267540Sray perror("file_header"); 435267540Sray return (1); 436267540Sray } 437267540Sray 438267540Sray if (memcmp(fh.magic, "VFNT0002", 8) != 0) { 439267540Sray fprintf(stderr, "Bad magic\n"); 440267540Sray return (1); 441267540Sray } 442267540Sray 443267540Sray for (i = 0; i < VFNT_MAPS; i++) 444267540Sray vfnt.map_count[i] = be32toh(fh.map_count[i]); 445267540Sray vfnt.glyph_count = be32toh(fh.glyph_count); 446267540Sray vfnt.width = fh.width; 447267540Sray vfnt.height = fh.height; 448267540Sray 449267540Sray glyphsize = howmany(vfnt.width, 8) * vfnt.height * vfnt.glyph_count; 450267540Sray vfnt.glyphs = malloc(glyphsize); 451267540Sray 452267540Sray if (fread(vfnt.glyphs, glyphsize, 1, f) != 1) { 453267540Sray perror("glyphs"); 454267540Sray return (1); 455267540Sray } 456267540Sray 457267540Sray for (i = 0; i < VFNT_MAPS; i++) 458267540Sray vfnt.map[i] = load_vt4mappingtable(vfnt.map_count[i], f); 459267540Sray 460267540Sray if (ioctl(STDIN_FILENO, PIO_VFONT, &vfnt) == -1) { 461267540Sray perror("PIO_VFONT"); 462267540Sray return (1); 463267540Sray } 464267540Sray return (0); 465267540Sray} 466267540Sray 467146736Sdelphij/* 468146736Sdelphij * Load a font from file and set it. 469146736Sdelphij */ 470146736Sdelphij 471140159Sdelphijstatic void 472140159Sdelphijload_font(const char *type, const char *filename) 4732089Ssos{ 47492460Ssobomax FILE *fd; 47575344Ssobomax int h, i, size, w; 47675344Ssobomax unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 47792460Ssobomax char *name, *fontmap, size_sufx[6]; 478140159Sdelphij const char *a[] = {"", FONT_PATH, NULL}; 479267540Sray const char *vt4a[] = {"", VT_FONT_PATH, NULL}; 480140159Sdelphij const char *b[] = {filename, NULL}; 481140159Sdelphij const char *c[] = {"", size_sufx, NULL}; 482140159Sdelphij const char *d[] = {"", ".fnt", NULL}; 483140159Sdelphij vid_info_t _info; 4842089Ssos 48575344Ssobomax struct sizeinfo { 48675344Ssobomax int w; 48775344Ssobomax int h; 48875344Ssobomax unsigned long io; 48975344Ssobomax } sizes[] = {{8, 16, PIO_FONT8x16}, 49075344Ssobomax {8, 14, PIO_FONT8x14}, 49175344Ssobomax {8, 8, PIO_FONT8x8}, 49275344Ssobomax {0, 0, 0}}; 49375344Ssobomax 494267540Sray if (vt4_mode) { 495267540Sray size_sufx[0] = '\0'; 496267540Sray } else { 497267540Sray _info.size = sizeof(_info); 498267540Sray if (ioctl(0, CONS_GETINFO, &_info) == -1) { 499267540Sray revert(); 500267540Sray warn("failed to obtain current video mode parameters"); 501267540Sray return; 502267540Sray } 503267540Sray 504267540Sray snprintf(size_sufx, sizeof(size_sufx), "-8x%d", _info.font_size); 5052089Ssos } 506267540Sray fd = openguess((vt4_mode == 0) ? a : vt4a, b, c, d, &name); 507146736Sdelphij 5082089Ssos if (fd == NULL) { 509146736Sdelphij revert(); 510146736Sdelphij errx(1, "%s: can't load font file", filename); 5112089Ssos } 512146736Sdelphij 513267540Sray if (vt4_mode) { 514267540Sray if(load_vt4font(fd)) 515267540Sray warn("failed to load font \"%s\"", filename); 516267540Sray fclose(fd); 517267540Sray return; 518267540Sray } 519267540Sray 52075344Ssobomax if (type != NULL) { 52175344Ssobomax size = 0; 522146736Sdelphij if (sscanf(type, "%dx%d", &w, &h) == 2) { 523146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 52475344Ssobomax if (sizes[i].w == w && sizes[i].h == h) { 52575344Ssobomax size = DATASIZE(sizes[i]); 52675344Ssobomax io = sizes[i].io; 527146736Sdelphij font_height = sizes[i].h; 52875344Ssobomax } 529146736Sdelphij } 530146736Sdelphij } 53175344Ssobomax if (size == 0) { 53275344Ssobomax fclose(fd); 533146736Sdelphij revert(); 534146736Sdelphij errx(1, "%s: bad font size specification", type); 53575344Ssobomax } 53675344Ssobomax } else { 53775344Ssobomax /* Apply heuristics */ 538146736Sdelphij 53975344Ssobomax int j; 54075344Ssobomax int dsize[2]; 54175344Ssobomax 54275344Ssobomax size = DATASIZE(sizes[0]); 54375344Ssobomax fontmap = (char*) malloc(size); 54475344Ssobomax dsize[0] = decode(fd, fontmap, size); 54575344Ssobomax dsize[1] = fsize(fd); 54675344Ssobomax free(fontmap); 54775344Ssobomax 54875344Ssobomax size = 0; 549146736Sdelphij for (j = 0; j < 2; j++) { 550146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 55175344Ssobomax if (DATASIZE(sizes[i]) == dsize[j]) { 55275344Ssobomax size = dsize[j]; 55375344Ssobomax io = sizes[i].io; 554146736Sdelphij font_height = sizes[i].h; 55575344Ssobomax j = 2; /* XXX */ 55675344Ssobomax break; 55775344Ssobomax } 558146736Sdelphij } 559146736Sdelphij } 56075344Ssobomax 56175344Ssobomax if (size == 0) { 56275344Ssobomax fclose(fd); 563146736Sdelphij revert(); 564146736Sdelphij errx(1, "%s: can't guess font size", filename); 56575344Ssobomax } 566146736Sdelphij 56775344Ssobomax rewind(fd); 5682089Ssos } 56975344Ssobomax 5702089Ssos fontmap = (char*) malloc(size); 571146736Sdelphij 57275344Ssobomax if (decode(fd, fontmap, size) != size) { 5732089Ssos rewind(fd); 574146736Sdelphij if (fsize(fd) != size || 575146736Sdelphij fread(fontmap, 1, size, fd) != (size_t)size) { 57675344Ssobomax warnx("%s: bad font file", filename); 57723457Sbrian fclose(fd); 5782089Ssos free(fontmap); 579146736Sdelphij revert(); 580146736Sdelphij errx(1, "%s: bad font file", filename); 5812089Ssos } 5822089Ssos } 583146736Sdelphij 584146736Sdelphij if (ioctl(0, io, fontmap) == -1) { 585146736Sdelphij revert(); 586146736Sdelphij errc(1, errno, "loading font"); 587146736Sdelphij } 588146736Sdelphij 58923457Sbrian fclose(fd); 5902089Ssos free(fontmap); 5912089Ssos} 5922089Ssos 593146736Sdelphij 594146736Sdelphij/* 595146736Sdelphij * Set the timeout for the screensaver. 596146736Sdelphij */ 597146736Sdelphij 598140159Sdelphijstatic void 5992089Ssosset_screensaver_timeout(char *arg) 6002089Ssos{ 6012089Ssos int nsec; 6022089Ssos 603146736Sdelphij if (!strcmp(arg, "off")) { 6042089Ssos nsec = 0; 605146736Sdelphij } else { 6062089Ssos nsec = atoi(arg); 607146736Sdelphij 6082089Ssos if ((*arg == '\0') || (nsec < 1)) { 609146736Sdelphij revert(); 610146736Sdelphij errx(1, "argument must be a positive number"); 6112089Ssos } 6122089Ssos } 613146736Sdelphij 614146736Sdelphij if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) { 615146736Sdelphij revert(); 616146736Sdelphij errc(1, errno, "setting screensaver period"); 617146736Sdelphij } 6182089Ssos} 6192089Ssos 620146736Sdelphij 621146736Sdelphij/* 622146736Sdelphij * Set the cursor's shape/type. 623146736Sdelphij */ 624146736Sdelphij 625140159Sdelphijstatic void 626228990Suqsset_cursor_type(char *appearance) 6272089Ssos{ 6285536Ssos int type; 6292089Ssos 630228990Suqs if (!strcmp(appearance, "normal")) 6316230Ssos type = 0; 632228990Suqs else if (!strcmp(appearance, "blink")) 6335536Ssos type = 1; 634228990Suqs else if (!strcmp(appearance, "destructive")) 6356230Ssos type = 3; 6365536Ssos else { 637146736Sdelphij revert(); 638146736Sdelphij errx(1, "argument to -c must be normal, blink or destructive"); 6392089Ssos } 640146736Sdelphij 641146736Sdelphij if (ioctl(0, CONS_CURSORTYPE, &type) == -1) { 642146736Sdelphij revert(); 643146736Sdelphij errc(1, errno, "setting cursor type"); 644146736Sdelphij } 6452089Ssos} 6462089Ssos 647146736Sdelphij 648146736Sdelphij/* 649146736Sdelphij * Set the video mode. 650146736Sdelphij */ 651146736Sdelphij 652140159Sdelphijstatic int 653146736Sdelphijvideo_mode(int argc, char **argv, int *mode_index) 6542089Ssos{ 65539592Syokota static struct { 656140159Sdelphij const char *name; 65739592Syokota unsigned long mode; 658146736Sdelphij unsigned long mode_num; 65939592Syokota } modes[] = { 660146736Sdelphij { "80x25", SW_TEXT_80x25, M_TEXT_80x25 }, 661146736Sdelphij { "80x30", SW_TEXT_80x30, M_TEXT_80x30 }, 662146736Sdelphij { "80x43", SW_TEXT_80x43, M_TEXT_80x43 }, 663146736Sdelphij { "80x50", SW_TEXT_80x50, M_TEXT_80x50 }, 664146736Sdelphij { "80x60", SW_TEXT_80x60, M_TEXT_80x60 }, 665146736Sdelphij { "132x25", SW_TEXT_132x25, M_TEXT_132x25 }, 666146736Sdelphij { "132x30", SW_TEXT_132x30, M_TEXT_132x30 }, 667146736Sdelphij { "132x43", SW_TEXT_132x43, M_TEXT_132x43 }, 668146736Sdelphij { "132x50", SW_TEXT_132x50, M_TEXT_132x50 }, 669146736Sdelphij { "132x60", SW_TEXT_132x60, M_TEXT_132x60 }, 670146736Sdelphij { "VGA_40x25", SW_VGA_C40x25, M_VGA_C40x25 }, 671146736Sdelphij { "VGA_80x25", SW_VGA_C80x25, M_VGA_C80x25 }, 672146736Sdelphij { "VGA_80x30", SW_VGA_C80x30, M_VGA_C80x30 }, 673146736Sdelphij { "VGA_80x50", SW_VGA_C80x50, M_VGA_C80x50 }, 674146736Sdelphij { "VGA_80x60", SW_VGA_C80x60, M_VGA_C80x60 }, 67548105Syokota#ifdef SW_VGA_C90x25 676146736Sdelphij { "VGA_90x25", SW_VGA_C90x25, M_VGA_C90x25 }, 677146736Sdelphij { "VGA_90x30", SW_VGA_C90x30, M_VGA_C90x30 }, 678146736Sdelphij { "VGA_90x43", SW_VGA_C90x43, M_VGA_C90x43 }, 679146736Sdelphij { "VGA_90x50", SW_VGA_C90x50, M_VGA_C90x50 }, 680146736Sdelphij { "VGA_90x60", SW_VGA_C90x60, M_VGA_C90x60 }, 68148105Syokota#endif 682146736Sdelphij { "VGA_320x200", SW_VGA_CG320, M_CG320 }, 683146736Sdelphij { "EGA_80x25", SW_ENH_C80x25, M_ENH_C80x25 }, 684146736Sdelphij { "EGA_80x43", SW_ENH_C80x43, M_ENH_C80x43 }, 685146736Sdelphij { "VESA_132x25", SW_VESA_C132x25,M_VESA_C132x25 }, 686146736Sdelphij { "VESA_132x43", SW_VESA_C132x43,M_VESA_C132x43 }, 687146736Sdelphij { "VESA_132x50", SW_VESA_C132x50,M_VESA_C132x50 }, 688146736Sdelphij { "VESA_132x60", SW_VESA_C132x60,M_VESA_C132x60 }, 689146736Sdelphij { "VESA_800x600", SW_VESA_800x600,M_VESA_800x600 }, 690146736Sdelphij { NULL, 0, 0 }, 69139592Syokota }; 692146736Sdelphij 693146736Sdelphij int new_mode_num = 0; 69442605Smjacob unsigned long mode = 0; 69548105Syokota int cur_mode; 69648105Syokota int ioerr; 69739287Ssos int size[3]; 69839592Syokota int i; 6992089Ssos 70048105Syokota if (ioctl(0, CONS_GET, &cur_mode) < 0) 70148105Syokota err(1, "cannot get the current video mode"); 702146736Sdelphij 703146736Sdelphij /* 704146736Sdelphij * Parse the video mode argument... 705146736Sdelphij */ 706146736Sdelphij 707146736Sdelphij if (*mode_index < argc) { 708146736Sdelphij if (!strncmp(argv[*mode_index], "MODE_", 5)) { 709146736Sdelphij if (!isdigit(argv[*mode_index][5])) 710146736Sdelphij errx(1, "invalid video mode number"); 711146736Sdelphij 712146736Sdelphij new_mode_num = atoi(&argv[*mode_index][5]); 713146736Sdelphij } else { 714146736Sdelphij for (i = 0; modes[i].name != NULL; ++i) { 715146736Sdelphij if (!strcmp(argv[*mode_index], modes[i].name)) { 716146736Sdelphij mode = modes[i].mode; 717146736Sdelphij new_mode_num = modes[i].mode_num; 718146736Sdelphij break; 719146736Sdelphij } 72039592Syokota } 721146736Sdelphij 722146736Sdelphij if (modes[i].name == NULL) 723146736Sdelphij return EXIT_FAILURE; 724146736Sdelphij if (ioctl(0, mode, NULL) < 0) { 725146736Sdelphij warn("cannot set videomode"); 726146736Sdelphij return EXIT_FAILURE; 727146736Sdelphij } 72839592Syokota } 729146736Sdelphij 730146736Sdelphij /* 731146736Sdelphij * Collect enough information about the new video mode... 732146736Sdelphij */ 733146736Sdelphij 734146736Sdelphij new_mode_info.vi_mode = new_mode_num; 735146736Sdelphij 736146736Sdelphij if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) { 737146736Sdelphij revert(); 738146736Sdelphij errc(1, errno, "obtaining new video mode parameters"); 739120201Seivind } 740146736Sdelphij 741146736Sdelphij if (mode == 0) { 742146736Sdelphij if (new_mode_num >= M_VESA_BASE) 743146736Sdelphij mode = _IO('V', new_mode_num - M_VESA_BASE); 744146736Sdelphij else 745146736Sdelphij mode = _IO('S', new_mode_num); 746146736Sdelphij } 747146736Sdelphij 748146736Sdelphij /* 749146736Sdelphij * Try setting the new mode. 750146736Sdelphij */ 751146736Sdelphij 752146736Sdelphij if (ioctl(0, mode, NULL) == -1) { 753146736Sdelphij revert(); 754146736Sdelphij errc(1, errno, "setting video mode"); 755146736Sdelphij } 756146736Sdelphij 757146736Sdelphij /* 758146736Sdelphij * For raster modes it's not enough to just set the mode. 759146736Sdelphij * We also need to explicitly set the raster mode. 760146736Sdelphij */ 761146736Sdelphij 762146736Sdelphij if (new_mode_info.vi_flags & V_INFO_GRAPHICS) { 763146736Sdelphij /* font size */ 764146736Sdelphij 765146736Sdelphij if (font_height == 0) 766146736Sdelphij font_height = cur_info.console_info.font_size; 767146736Sdelphij 768146736Sdelphij size[2] = font_height; 769146736Sdelphij 770146736Sdelphij /* adjust columns */ 771146736Sdelphij 772146736Sdelphij if ((vesa_cols * 8 > new_mode_info.vi_width) || 773146736Sdelphij (vesa_cols <= 0)) { 774146736Sdelphij size[0] = new_mode_info.vi_width / 8; 77571642Ssobomax } else { 77671642Ssobomax size[0] = vesa_cols; 77771642Ssobomax } 778146736Sdelphij 779146736Sdelphij /* adjust rows */ 780146736Sdelphij 781146736Sdelphij if ((vesa_rows * font_height > new_mode_info.vi_height) || 782146736Sdelphij (vesa_rows <= 0)) { 783146736Sdelphij size[1] = new_mode_info.vi_height / 784146736Sdelphij font_height; 78571642Ssobomax } else { 78671642Ssobomax size[1] = vesa_rows; 78771642Ssobomax } 788146736Sdelphij 789146736Sdelphij /* set raster mode */ 790146736Sdelphij 79148105Syokota if (ioctl(0, KDRASTER, size)) { 79248105Syokota ioerr = errno; 79348105Syokota if (cur_mode >= M_VESA_BASE) 79480148Syokota ioctl(0, 79580148Syokota _IO('V', cur_mode - M_VESA_BASE), 79680148Syokota NULL); 79748105Syokota else 79848105Syokota ioctl(0, _IO('S', cur_mode), NULL); 799146736Sdelphij revert(); 80048105Syokota warnc(ioerr, "cannot activate raster display"); 801120201Seivind return EXIT_FAILURE; 80248105Syokota } 80339287Ssos } 804146736Sdelphij 805146736Sdelphij video_mode_changed = 1; 806146736Sdelphij 807146736Sdelphij (*mode_index)++; 8082089Ssos } 809120201Seivind return EXIT_SUCCESS; 8102089Ssos} 8118857Srgrimes 812146736Sdelphij 813146736Sdelphij/* 814146736Sdelphij * Return the number for a specified color name. 815146736Sdelphij */ 816146736Sdelphij 817140159Sdelphijstatic int 8182089Ssosget_color_number(char *color) 8192089Ssos{ 8202089Ssos int i; 8212089Ssos 822146736Sdelphij for (i=0; i<16; i++) { 8232089Ssos if (!strcmp(color, legal_colors[i])) 8242089Ssos return i; 825146736Sdelphij } 8262089Ssos return -1; 8272089Ssos} 8282089Ssos 829146736Sdelphij 830146736Sdelphij/* 831146736Sdelphij * Get normal text and background colors. 832146736Sdelphij */ 833146736Sdelphij 834140159Sdelphijstatic void 835146736Sdelphijget_normal_colors(int argc, char **argv, int *_index) 8362089Ssos{ 8372089Ssos int color; 8382089Ssos 839140159Sdelphij if (*_index < argc && (color = get_color_number(argv[*_index])) != -1) { 840140159Sdelphij (*_index)++; 841146241Snyan fprintf(stderr, "\033[=%dF", color); 842150246Srodrigc normal_fore_color=color; 843150246Srodrigc colors_changed = 1; 844140159Sdelphij if (*_index < argc 845140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 8462089Ssos && color < 8) { 847140159Sdelphij (*_index)++; 848146241Snyan fprintf(stderr, "\033[=%dG", color); 849150246Srodrigc normal_back_color=color; 8502089Ssos } 8512089Ssos } 8522089Ssos} 8532089Ssos 854146736Sdelphij 855146736Sdelphij/* 856146736Sdelphij * Get reverse text and background colors. 857146736Sdelphij */ 858146736Sdelphij 859140159Sdelphijstatic void 860146736Sdelphijget_reverse_colors(int argc, char **argv, int *_index) 8612089Ssos{ 8622089Ssos int color; 8632089Ssos 864140159Sdelphij if ((color = get_color_number(argv[*(_index)-1])) != -1) { 865146241Snyan fprintf(stderr, "\033[=%dH", color); 866150246Srodrigc revers_fore_color=color; 867150246Srodrigc colors_changed = 1; 868140159Sdelphij if (*_index < argc 869140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 8702089Ssos && color < 8) { 871140159Sdelphij (*_index)++; 872146241Snyan fprintf(stderr, "\033[=%dI", color); 873150246Srodrigc revers_back_color=color; 8742089Ssos } 8752089Ssos } 8762089Ssos} 8772089Ssos 878146736Sdelphij 879146736Sdelphij/* 880146736Sdelphij * Set normal and reverse foreground and background colors. 881146736Sdelphij */ 882146736Sdelphij 883140159Sdelphijstatic void 884146736Sdelphijset_colors(void) 885146736Sdelphij{ 886146736Sdelphij fprintf(stderr, "\033[=%dF", normal_fore_color); 887146736Sdelphij fprintf(stderr, "\033[=%dG", normal_back_color); 888146736Sdelphij fprintf(stderr, "\033[=%dH", revers_fore_color); 889146736Sdelphij fprintf(stderr, "\033[=%dI", revers_back_color); 890146736Sdelphij} 891146736Sdelphij 892146736Sdelphij 893146736Sdelphij/* 894146736Sdelphij * Switch to virtual terminal #arg. 895146736Sdelphij */ 896146736Sdelphij 897146736Sdelphijstatic void 89823457Sbrianset_console(char *arg) 89923457Sbrian{ 90023457Sbrian int n; 90123457Sbrian 902146736Sdelphij if(!arg || strspn(arg,"0123456789") != strlen(arg)) { 903146736Sdelphij revert(); 904146736Sdelphij errx(1, "bad console number"); 90523457Sbrian } 90623457Sbrian 90723457Sbrian n = atoi(arg); 908146736Sdelphij 90951393Syokota if (n < 1 || n > 16) { 910146736Sdelphij revert(); 911146736Sdelphij errx(1, "console number out of range"); 912162671Sru } else if (ioctl(0, VT_ACTIVATE, n) == -1) { 913146736Sdelphij revert(); 914146736Sdelphij errc(1, errno, "switching vty"); 915146736Sdelphij } 91623457Sbrian} 91723457Sbrian 918146736Sdelphij 919146736Sdelphij/* 920146736Sdelphij * Sets the border color. 921146736Sdelphij */ 922146736Sdelphij 923140159Sdelphijstatic void 9242089Ssosset_border_color(char *arg) 9252089Ssos{ 9262089Ssos int color; 9272089Ssos 9282089Ssos if ((color = get_color_number(arg)) != -1) { 929146241Snyan fprintf(stderr, "\033[=%dA", color); 9302089Ssos } 9312089Ssos else 9328857Srgrimes usage(); 9332089Ssos} 9342089Ssos 935140159Sdelphijstatic void 93655849Syokotaset_mouse_char(char *arg) 93755849Syokota{ 93855849Syokota struct mouse_info mouse; 93955849Syokota long l; 94055849Syokota 94155849Syokota l = strtol(arg, NULL, 0); 942146736Sdelphij 94375788Sache if ((l < 0) || (l > UCHAR_MAX - 3)) { 944146736Sdelphij revert(); 94575788Sache warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3); 94655849Syokota return; 94755849Syokota } 948146736Sdelphij 94955849Syokota mouse.operation = MOUSE_MOUSECHAR; 95055849Syokota mouse.u.mouse_char = (int)l; 951146736Sdelphij 952146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 953146736Sdelphij revert(); 954146736Sdelphij errc(1, errno, "setting mouse character"); 955146736Sdelphij } 95655849Syokota} 95755849Syokota 958146736Sdelphij 959146736Sdelphij/* 960146736Sdelphij * Show/hide the mouse. 961146736Sdelphij */ 962146736Sdelphij 963140159Sdelphijstatic void 96416565Ssosset_mouse(char *arg) 96516565Ssos{ 96616565Ssos struct mouse_info mouse; 96716565Ssos 968146736Sdelphij if (!strcmp(arg, "on")) { 96916565Ssos mouse.operation = MOUSE_SHOW; 970146736Sdelphij } else if (!strcmp(arg, "off")) { 97116565Ssos mouse.operation = MOUSE_HIDE; 972146736Sdelphij } else { 973146736Sdelphij revert(); 974146736Sdelphij errx(1, "argument to -m must be either on or off"); 97516565Ssos } 976146736Sdelphij 977146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 978146736Sdelphij revert(); 979146736Sdelphij errc(1, errno, "%sing the mouse", 980146736Sdelphij mouse.operation == MOUSE_SHOW ? "show" : "hid"); 981146736Sdelphij } 98216565Ssos} 98316565Ssos 984146736Sdelphij 985140159Sdelphijstatic void 98699705Sddset_lockswitch(char *arg) 98799705Sdd{ 98899705Sdd int data; 98999705Sdd 990146736Sdelphij if (!strcmp(arg, "off")) { 99199705Sdd data = 0x01; 992146736Sdelphij } else if (!strcmp(arg, "on")) { 99399705Sdd data = 0x02; 994146736Sdelphij } else { 995146736Sdelphij revert(); 996146736Sdelphij errx(1, "argument to -S must be either on or off"); 99799705Sdd } 998146736Sdelphij 999146736Sdelphij if (ioctl(0, VT_LOCKSWITCH, &data) == -1) { 1000146736Sdelphij revert(); 1001146736Sdelphij errc(1, errno, "turning %s vty switching", 1002146736Sdelphij data == 0x01 ? "off" : "on"); 1003146736Sdelphij } 100499705Sdd} 100599705Sdd 1006146736Sdelphij 1007146736Sdelphij/* 1008146736Sdelphij * Return the adapter name for a specified type. 1009146736Sdelphij */ 1010146736Sdelphij 1011140159Sdelphijstatic const char 101239287Ssos*adapter_name(int type) 101339287Ssos{ 101439287Ssos static struct { 101539287Ssos int type; 1016140159Sdelphij const char *name; 101739287Ssos } names[] = { 101839287Ssos { KD_MONO, "MDA" }, 101939287Ssos { KD_HERCULES, "Hercules" }, 102039287Ssos { KD_CGA, "CGA" }, 102139287Ssos { KD_EGA, "EGA" }, 102239287Ssos { KD_VGA, "VGA" }, 102339287Ssos { KD_PC98, "PC-98xx" }, 102448105Syokota { KD_TGA, "TGA" }, 102539287Ssos { -1, "Unknown" }, 102639287Ssos }; 1027146736Sdelphij 102839287Ssos int i; 102939287Ssos 103039287Ssos for (i = 0; names[i].type != -1; ++i) 103139287Ssos if (names[i].type == type) 103239287Ssos break; 103339287Ssos return names[i].name; 103439287Ssos} 103539287Ssos 1036146736Sdelphij 1037146736Sdelphij/* 1038146736Sdelphij * Show graphics adapter information. 1039146736Sdelphij */ 1040146736Sdelphij 1041140159Sdelphijstatic void 104239287Ssosshow_adapter_info(void) 104339287Ssos{ 104442505Syokota struct video_adapter_info ad; 104539287Ssos 104639287Ssos ad.va_index = 0; 1047146736Sdelphij 1048146736Sdelphij if (ioctl(0, CONS_ADPINFO, &ad) == -1) { 1049146736Sdelphij revert(); 1050146736Sdelphij errc(1, errno, "obtaining adapter information"); 105139287Ssos } 105239287Ssos 105342505Syokota printf("fb%d:\n", ad.va_index); 105442505Syokota printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 105542505Syokota (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 105639287Ssos (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 105742505Syokota adapter_name(ad.va_type), ad.va_type, ad.va_flags); 105839287Ssos printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 105939287Ssos ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 1060140159Sdelphij printf(" frame buffer window:0x%zx, buffer size:0x%zx\n", 106148105Syokota ad.va_window, ad.va_buffer_size); 1062140159Sdelphij printf(" window size:0x%zx, origin:0x%x\n", 106348105Syokota ad.va_window_size, ad.va_window_orig); 106448105Syokota printf(" display start address (%d, %d), scan line width:%d\n", 106548105Syokota ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); 1066140159Sdelphij printf(" reserved:0x%zx\n", ad.va_unused0); 106739287Ssos} 106839287Ssos 1069146736Sdelphij 1070146736Sdelphij/* 1071146736Sdelphij * Show video mode information. 1072146736Sdelphij */ 1073146736Sdelphij 1074140159Sdelphijstatic void 107539287Ssosshow_mode_info(void) 107639287Ssos{ 1077205855Sjkim char buf[80]; 1078140159Sdelphij struct video_info _info; 1079205855Sjkim int c; 1080205855Sjkim int mm; 108139287Ssos int mode; 108239287Ssos 108339287Ssos printf(" mode# flags type size " 108439287Ssos "font window linear buffer\n"); 108539287Ssos printf("---------------------------------------" 108639287Ssos "---------------------------------------\n"); 1087146736Sdelphij 1088250509Seadler for (mode = 0; mode <= M_VESA_MODE_MAX; ++mode) { 1089140159Sdelphij _info.vi_mode = mode; 1090140159Sdelphij if (ioctl(0, CONS_MODEINFO, &_info)) 109139287Ssos continue; 1092140159Sdelphij if (_info.vi_mode != mode) 109348105Syokota continue; 109439287Ssos 109539287Ssos printf("%3d (0x%03x)", mode, mode); 1096140159Sdelphij printf(" 0x%08x", _info.vi_flags); 1097140159Sdelphij if (_info.vi_flags & V_INFO_GRAPHICS) { 109839287Ssos c = 'G'; 1099146736Sdelphij 1100205855Sjkim if (_info.vi_mem_model == V_INFO_MM_PLANAR) 1101205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %d", 1102205855Sjkim _info.vi_width, _info.vi_height, 1103205855Sjkim _info.vi_depth, _info.vi_planes); 1104205855Sjkim else { 1105205855Sjkim switch (_info.vi_mem_model) { 1106205855Sjkim case V_INFO_MM_PACKED: 1107205855Sjkim mm = 'P'; 1108205855Sjkim break; 1109205855Sjkim case V_INFO_MM_DIRECT: 1110205855Sjkim mm = 'D'; 1111205855Sjkim break; 1112205855Sjkim case V_INFO_MM_CGA: 1113205855Sjkim mm = 'C'; 1114205855Sjkim break; 1115205855Sjkim case V_INFO_MM_HGC: 1116205855Sjkim mm = 'H'; 1117205855Sjkim break; 1118205855Sjkim case V_INFO_MM_VGAX: 1119205855Sjkim mm = 'V'; 1120205855Sjkim break; 1121205855Sjkim default: 1122205855Sjkim mm = ' '; 1123205855Sjkim break; 1124205855Sjkim } 1125205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %c", 1126205855Sjkim _info.vi_width, _info.vi_height, 1127205855Sjkim _info.vi_depth, mm); 1128205855Sjkim } 112939287Ssos } else { 113039287Ssos c = 'T'; 1131146736Sdelphij 113239287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1133140159Sdelphij _info.vi_width, _info.vi_height); 113439287Ssos } 1135146736Sdelphij 113639287Ssos printf(" %c %-15s", c, buf); 113739287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1138140159Sdelphij _info.vi_cwidth, _info.vi_cheight); 113939287Ssos printf(" %-5s", buf); 1140140159Sdelphij printf(" 0x%05zx %2dk %2dk", 1141140159Sdelphij _info.vi_window, (int)_info.vi_window_size/1024, 1142140159Sdelphij (int)_info.vi_window_gran/1024); 1143140159Sdelphij printf(" 0x%08zx %dk\n", 1144140159Sdelphij _info.vi_buffer, (int)_info.vi_buffer_size/1024); 114539287Ssos } 114639287Ssos} 114739287Ssos 1148146736Sdelphij 1149140159Sdelphijstatic void 115039287Ssosshow_info(char *arg) 115139287Ssos{ 1152146736Sdelphij if (!strcmp(arg, "adapter")) { 115339287Ssos show_adapter_info(); 1154146736Sdelphij } else if (!strcmp(arg, "mode")) { 115539287Ssos show_mode_info(); 1156146736Sdelphij } else { 1157146736Sdelphij revert(); 1158146736Sdelphij errx(1, "argument to -i must be either adapter or mode"); 115939287Ssos } 116039287Ssos} 116139287Ssos 1162146736Sdelphij 1163140159Sdelphijstatic void 1164140159Sdelphijtest_frame(void) 11652089Ssos{ 1166146237Snyan int i, cur_mode, fore; 11672089Ssos 1168146237Snyan fore = 15; 1169146237Snyan 1170146237Snyan if (ioctl(0, CONS_GET, &cur_mode) < 0) 1171146237Snyan err(1, "must be on a virtual console"); 1172146237Snyan switch (cur_mode) { 1173146237Snyan case M_PC98_80x25: 1174146237Snyan case M_PC98_80x30: 1175146237Snyan fore = 7; 1176146237Snyan break; 1177146237Snyan } 1178146237Snyan 1179146241Snyan fprintf(stdout, "\033[=0G\n\n"); 11802089Ssos for (i=0; i<8; i++) { 1181146241Snyan fprintf(stdout, "\033[=%dF\033[=0G %2d \033[=%dF%-16s" 1182146241Snyan "\033[=%dF\033[=0G %2d \033[=%dF%-16s " 1183146241Snyan "\033[=%dF %2d \033[=%dGBACKGROUND\033[=0G\n", 1184146237Snyan fore, i, i, legal_colors[i], 1185146237Snyan fore, i+8, i+8, legal_colors[i+8], 1186146237Snyan fore, i, i); 11872089Ssos } 1188146241Snyan fprintf(stdout, "\033[=%dF\033[=%dG\033[=%dH\033[=%dI\n", 11898857Srgrimes info.mv_norm.fore, info.mv_norm.back, 11902089Ssos info.mv_rev.fore, info.mv_rev.back); 11912089Ssos} 11922089Ssos 1193146736Sdelphij 119476845Ssobomax/* 119576845Ssobomax * Snapshot the video memory of that terminal, using the CONS_SCRSHOT 119676845Ssobomax * ioctl, and writes the results to stdout either in the special 119776845Ssobomax * binary format (see manual page for details), or in the plain 119876845Ssobomax * text format. 119976845Ssobomax */ 1200146736Sdelphij 1201140159Sdelphijstatic void 1202102111Ssobomaxdump_screen(int mode, int opt) 120376845Ssobomax{ 120476845Ssobomax scrshot_t shot; 1205140159Sdelphij vid_info_t _info; 120676845Ssobomax 1207140159Sdelphij _info.size = sizeof(_info); 1208146736Sdelphij 1209140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 1210146736Sdelphij revert(); 1211146736Sdelphij errc(1, errno, "obtaining current video mode parameters"); 121276845Ssobomax return; 121376845Ssobomax } 121476845Ssobomax 1215102111Ssobomax shot.x = shot.y = 0; 1216140159Sdelphij shot.xsize = _info.mv_csz; 1217140159Sdelphij shot.ysize = _info.mv_rsz; 1218102111Ssobomax if (opt == DUMP_ALL) 1219140159Sdelphij shot.ysize += _info.mv_hsz; 1220102111Ssobomax 1221102111Ssobomax shot.buf = alloca(shot.xsize * shot.ysize * sizeof(u_int16_t)); 122276845Ssobomax if (shot.buf == NULL) { 1223146736Sdelphij revert(); 1224146736Sdelphij errx(1, "failed to allocate memory for dump"); 122576845Ssobomax } 122676845Ssobomax 122776845Ssobomax if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { 1228146736Sdelphij revert(); 1229146736Sdelphij errc(1, errno, "dumping screen"); 123076845Ssobomax } 123176845Ssobomax 1232102111Ssobomax if (mode == DUMP_FMT_RAW) { 123376845Ssobomax printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, 123476845Ssobomax shot.xsize, shot.ysize); 1235146736Sdelphij 123676845Ssobomax fflush(stdout); 123776845Ssobomax 1238146736Sdelphij write(STDOUT_FILENO, shot.buf, 1239146736Sdelphij shot.xsize * shot.ysize * sizeof(u_int16_t)); 124076845Ssobomax } else { 124176845Ssobomax char *line; 124276845Ssobomax int x, y; 124376845Ssobomax u_int16_t ch; 124476845Ssobomax 124576845Ssobomax line = alloca(shot.xsize + 1); 1246146736Sdelphij 124776845Ssobomax if (line == NULL) { 1248146736Sdelphij revert(); 1249146736Sdelphij errx(1, "failed to allocate memory for line buffer"); 125076845Ssobomax } 125176845Ssobomax 125276845Ssobomax for (y = 0; y < shot.ysize; y++) { 125376845Ssobomax for (x = 0; x < shot.xsize; x++) { 125476845Ssobomax ch = shot.buf[x + (y * shot.xsize)]; 125576845Ssobomax ch &= 0xff; 1256146736Sdelphij 125776845Ssobomax if (isprint(ch) == 0) 125876845Ssobomax ch = ' '; 1259146736Sdelphij 126076845Ssobomax line[x] = (char)ch; 126176845Ssobomax } 126276845Ssobomax 126376845Ssobomax /* Trim trailing spaces */ 1264146736Sdelphij 126576845Ssobomax do { 126676845Ssobomax line[x--] = '\0'; 126776845Ssobomax } while (line[x] == ' ' && x != 0); 126876845Ssobomax 126976845Ssobomax puts(line); 127076845Ssobomax } 1271146736Sdelphij 127276845Ssobomax fflush(stdout); 127376845Ssobomax } 127476845Ssobomax} 127576845Ssobomax 1276146736Sdelphij 1277146736Sdelphij/* 1278146736Sdelphij * Set the console history buffer size. 1279146736Sdelphij */ 1280146736Sdelphij 1281140159Sdelphijstatic void 128277329Sdesset_history(char *opt) 128377329Sdes{ 128477329Sdes int size; 128577329Sdes 128677329Sdes size = atoi(opt); 1287146736Sdelphij 128877329Sdes if ((*opt == '\0') || size < 0) { 1289146736Sdelphij revert(); 1290146736Sdelphij errx(1, "argument must be a positive number"); 129177329Sdes } 1292146736Sdelphij 1293146736Sdelphij if (ioctl(0, CONS_HISTORY, &size) == -1) { 1294146736Sdelphij revert(); 1295146736Sdelphij errc(1, errno, "setting history buffer size"); 1296146736Sdelphij } 129777329Sdes} 129877329Sdes 1299146736Sdelphij 1300146736Sdelphij/* 1301146736Sdelphij * Clear the console history buffer. 1302146736Sdelphij */ 1303146736Sdelphij 1304140159Sdelphijstatic void 1305140159Sdelphijclear_history(void) 130677329Sdes{ 1307146736Sdelphij if (ioctl(0, CONS_CLRHIST) == -1) { 1308146736Sdelphij revert(); 1309146736Sdelphij errc(1, errno, "clearing history buffer"); 1310146736Sdelphij } 131177329Sdes} 131277329Sdes 1313199174Sedstatic void 1314199174Sedset_terminal_mode(char *arg) 1315199174Sed{ 1316146736Sdelphij 1317199174Sed if (strcmp(arg, "xterm") == 0) 1318199174Sed fprintf(stderr, "\033[=T"); 1319199174Sed else if (strcmp(arg, "cons25") == 0) 1320199174Sed fprintf(stderr, "\033[=1T"); 1321199174Sed} 1322199174Sed 1323199174Sed 132423457Sbrianint 13252089Ssosmain(int argc, char **argv) 13262089Ssos{ 1327237777Sache char *font, *type, *termmode; 1328267540Sray const char *opts; 1329102111Ssobomax int dumpmod, dumpopt, opt; 1330120201Seivind int reterr; 13312089Ssos 1332267540Sray vt4_mode = is_vt4(); 1333267540Sray 1334146736Sdelphij init(); 1335146736Sdelphij 13362089Ssos info.size = sizeof(info); 1337146736Sdelphij 1338146736Sdelphij if (ioctl(0, CONS_GETINFO, &info) == -1) 133930764Scharnier err(1, "must be on a virtual console"); 1340102111Ssobomax dumpmod = 0; 1341102111Ssobomax dumpopt = DUMP_FBF; 1342237777Sache termmode = NULL; 1343267540Sray if (vt4_mode) 1344273921Sdumbbell opts = "b:Cc:fg:h:Hi:M:m:pPr:S:s:T:t:x"; 1345267540Sray else 1346286291Semaste opts = "b:Cc:dfg:h:Hi:l:LM:m:pPr:S:s:T:t:x"; 1347267540Sray 1348267540Sray while ((opt = getopt(argc, argv, opts)) != -1) 13492089Ssos switch(opt) { 135077329Sdes case 'b': 135177329Sdes set_border_color(optarg); 135277329Sdes break; 135377329Sdes case 'C': 135477329Sdes clear_history(); 135577329Sdes break; 135677329Sdes case 'c': 135777329Sdes set_cursor_type(optarg); 135877329Sdes break; 135977329Sdes case 'd': 1360267540Sray if (vt4_mode) 1361267540Sray break; 136277329Sdes print_scrnmap(); 136377329Sdes break; 136477329Sdes case 'f': 1365273921Sdumbbell optarg = nextarg(argc, argv, &optind, 'f', 0); 1366273921Sdumbbell if (optarg != NULL) { 1367273921Sdumbbell font = nextarg(argc, argv, &optind, 'f', 0); 1368146736Sdelphij 1369273921Sdumbbell if (font == NULL) { 1370273921Sdumbbell type = NULL; 1371273921Sdumbbell font = optarg; 1372273921Sdumbbell } else 1373273921Sdumbbell type = optarg; 1374273921Sdumbbell 1375273921Sdumbbell load_font(type, font); 1376273921Sdumbbell } else { 1377273921Sdumbbell if (!vt4_mode) 1378273921Sdumbbell usage(); /* Switch syscons to ROM? */ 1379273921Sdumbbell 1380273921Sdumbbell load_default_vt4font(); 138177329Sdes } 138277329Sdes break; 138377329Sdes case 'g': 1384146736Sdelphij if (sscanf(optarg, "%dx%d", 1385146736Sdelphij &vesa_cols, &vesa_rows) != 2) { 1386146736Sdelphij revert(); 138777329Sdes warnx("incorrect geometry: %s", optarg); 13882089Ssos usage(); 138977329Sdes } 1390146736Sdelphij break; 139177329Sdes case 'h': 139277329Sdes set_history(optarg); 139377329Sdes break; 1394102111Ssobomax case 'H': 1395102111Ssobomax dumpopt = DUMP_ALL; 1396102111Ssobomax break; 139777329Sdes case 'i': 139877329Sdes show_info(optarg); 139977329Sdes break; 140077329Sdes case 'l': 1401267540Sray if (vt4_mode) 1402267540Sray break; 140377329Sdes load_scrnmap(optarg); 140477329Sdes break; 140577329Sdes case 'L': 1406267540Sray if (vt4_mode) 1407267540Sray break; 140877329Sdes load_default_scrnmap(); 140977329Sdes break; 141077329Sdes case 'M': 141177329Sdes set_mouse_char(optarg); 141277329Sdes break; 141377329Sdes case 'm': 141477329Sdes set_mouse(optarg); 141577329Sdes break; 141677329Sdes case 'p': 1417102111Ssobomax dumpmod = DUMP_FMT_RAW; 141877329Sdes break; 141977329Sdes case 'P': 1420102111Ssobomax dumpmod = DUMP_FMT_TXT; 142177329Sdes break; 142277329Sdes case 'r': 1423146736Sdelphij get_reverse_colors(argc, argv, &optind); 142477329Sdes break; 142599705Sdd case 'S': 142699705Sdd set_lockswitch(optarg); 142799705Sdd break; 142877329Sdes case 's': 142977329Sdes set_console(optarg); 143077329Sdes break; 1431199174Sed case 'T': 1432237777Sache if (strcmp(optarg, "xterm") != 0 && 1433237777Sache strcmp(optarg, "cons25") != 0) 1434237777Sache usage(); 1435237777Sache termmode = optarg; 1436199174Sed break; 143777329Sdes case 't': 143877329Sdes set_screensaver_timeout(optarg); 143977329Sdes break; 144077329Sdes case 'x': 144177329Sdes hex = 1; 144277329Sdes break; 144377329Sdes default: 144477329Sdes usage(); 14452089Ssos } 1446146736Sdelphij 1447102111Ssobomax if (dumpmod != 0) 1448102111Ssobomax dump_screen(dumpmod, dumpopt); 1449120201Seivind reterr = video_mode(argc, argv, &optind); 1450146736Sdelphij get_normal_colors(argc, argv, &optind); 1451146736Sdelphij 14522089Ssos if (optind < argc && !strcmp(argv[optind], "show")) { 14532089Ssos test_frame(); 14542089Ssos optind++; 14552089Ssos } 1456146736Sdelphij 1457146736Sdelphij video_mode(argc, argv, &optind); 1458237777Sache if (termmode != NULL) 1459237777Sache set_terminal_mode(termmode); 1460146736Sdelphij 1461146736Sdelphij get_normal_colors(argc, argv, &optind); 1462146736Sdelphij 1463146736Sdelphij if (colors_changed || video_mode_changed) { 1464146736Sdelphij if (!(new_mode_info.vi_flags & V_INFO_GRAPHICS)) { 1465146736Sdelphij if ((normal_back_color < 8) && (revers_back_color < 8)) { 1466146736Sdelphij set_colors(); 1467146736Sdelphij } else { 1468146736Sdelphij revert(); 1469146736Sdelphij errx(1, "bg color for text modes must be < 8"); 1470146736Sdelphij } 1471146736Sdelphij } else { 1472146736Sdelphij set_colors(); 1473146736Sdelphij } 1474146736Sdelphij } 1475146736Sdelphij 147630764Scharnier if ((optind != argc) || (argc == 1)) 14772089Ssos usage(); 1478120201Seivind return reterr; 14792089Ssos} 14802089Ssos 1481