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: stable/10/usr.sbin/vidcontrol/vidcontrol.c 313552 2017-02-10 15:02:56Z 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 396313552Semaste if ((t = malloc(sizeof *t * nmappings)) == NULL) { 397313552Semaste warn("malloc"); 398313552Semaste return (NULL); 399313552Semaste } 400267540Sray 401267540Sray if (fread(t, sizeof *t * nmappings, 1, f) != 1) { 402313552Semaste warn("read mappings"); 403313552Semaste free(t); 404313552Semaste return (NULL); 405267540Sray } 406267540Sray 407267540Sray for (i = 0; i < nmappings; i++) { 408267540Sray t[i].src = be32toh(t[i].src); 409267540Sray t[i].dst = be16toh(t[i].dst); 410267540Sray t[i].len = be16toh(t[i].len); 411267540Sray } 412267540Sray 413267540Sray return (t); 414267540Sray} 415267540Sray 416273921Sdumbbell/* 417273921Sdumbbell * Set the default vt font. 418273921Sdumbbell */ 419273921Sdumbbell 420273921Sdumbbellstatic void 421273921Sdumbbellload_default_vt4font(void) 422273921Sdumbbell{ 423273921Sdumbbell if (ioctl(0, PIO_VFONT_DEFAULT) == -1) { 424273921Sdumbbell revert(); 425273921Sdumbbell errc(1, errno, "loading default vt font"); 426273921Sdumbbell } 427273921Sdumbbell} 428273921Sdumbbell 429313552Semastestatic void 430267540Srayload_vt4font(FILE *f) 431267540Sray{ 432267540Sray struct vt4font_header fh; 433267540Sray static vfnt_t vfnt; 434267540Sray size_t glyphsize; 435267540Sray unsigned int i; 436267540Sray 437267540Sray if (fread(&fh, sizeof fh, 1, f) != 1) { 438313552Semaste warn("read file_header"); 439313552Semaste return; 440267540Sray } 441267540Sray 442267540Sray if (memcmp(fh.magic, "VFNT0002", 8) != 0) { 443313552Semaste warnx("bad magic in font file\n"); 444313552Semaste return; 445267540Sray } 446267540Sray 447267540Sray for (i = 0; i < VFNT_MAPS; i++) 448267540Sray vfnt.map_count[i] = be32toh(fh.map_count[i]); 449267540Sray vfnt.glyph_count = be32toh(fh.glyph_count); 450267540Sray vfnt.width = fh.width; 451267540Sray vfnt.height = fh.height; 452267540Sray 453267540Sray glyphsize = howmany(vfnt.width, 8) * vfnt.height * vfnt.glyph_count; 454313552Semaste if ((vfnt.glyphs = malloc(glyphsize)) == NULL) { 455313552Semaste warn("malloc"); 456313552Semaste return; 457313552Semaste } 458267540Sray 459267540Sray if (fread(vfnt.glyphs, glyphsize, 1, f) != 1) { 460313552Semaste warn("read glyphs"); 461313552Semaste free(vfnt.glyphs); 462313552Semaste return; 463267540Sray } 464267540Sray 465267540Sray for (i = 0; i < VFNT_MAPS; i++) 466267540Sray vfnt.map[i] = load_vt4mappingtable(vfnt.map_count[i], f); 467267540Sray 468313552Semaste if (ioctl(STDIN_FILENO, PIO_VFONT, &vfnt) == -1) 469313552Semaste warn("PIO_VFONT"); 470313552Semaste 471313552Semaste for (i = 0; i < VFNT_MAPS; i++) 472313552Semaste free(vfnt.map[i]); 473313552Semaste free(vfnt.glyphs); 474267540Sray} 475267540Sray 476146736Sdelphij/* 477146736Sdelphij * Load a font from file and set it. 478146736Sdelphij */ 479146736Sdelphij 480140159Sdelphijstatic void 481140159Sdelphijload_font(const char *type, const char *filename) 4822089Ssos{ 48392460Ssobomax FILE *fd; 48475344Ssobomax int h, i, size, w; 48575344Ssobomax unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 48692460Ssobomax char *name, *fontmap, size_sufx[6]; 487140159Sdelphij const char *a[] = {"", FONT_PATH, NULL}; 488267540Sray const char *vt4a[] = {"", VT_FONT_PATH, NULL}; 489140159Sdelphij const char *b[] = {filename, NULL}; 490140159Sdelphij const char *c[] = {"", size_sufx, NULL}; 491140159Sdelphij const char *d[] = {"", ".fnt", NULL}; 492140159Sdelphij vid_info_t _info; 4932089Ssos 49475344Ssobomax struct sizeinfo { 49575344Ssobomax int w; 49675344Ssobomax int h; 49775344Ssobomax unsigned long io; 49875344Ssobomax } sizes[] = {{8, 16, PIO_FONT8x16}, 49975344Ssobomax {8, 14, PIO_FONT8x14}, 50075344Ssobomax {8, 8, PIO_FONT8x8}, 50175344Ssobomax {0, 0, 0}}; 50275344Ssobomax 503267540Sray if (vt4_mode) { 504267540Sray size_sufx[0] = '\0'; 505267540Sray } else { 506267540Sray _info.size = sizeof(_info); 507267540Sray if (ioctl(0, CONS_GETINFO, &_info) == -1) { 508267540Sray revert(); 509267540Sray warn("failed to obtain current video mode parameters"); 510267540Sray return; 511267540Sray } 512267540Sray 513267540Sray snprintf(size_sufx, sizeof(size_sufx), "-8x%d", _info.font_size); 5142089Ssos } 515267540Sray fd = openguess((vt4_mode == 0) ? a : vt4a, b, c, d, &name); 516146736Sdelphij 5172089Ssos if (fd == NULL) { 518146736Sdelphij revert(); 519146736Sdelphij errx(1, "%s: can't load font file", filename); 5202089Ssos } 521146736Sdelphij 522267540Sray if (vt4_mode) { 523313552Semaste load_vt4font(fd); 524267540Sray fclose(fd); 525267540Sray return; 526267540Sray } 527267540Sray 52875344Ssobomax if (type != NULL) { 52975344Ssobomax size = 0; 530146736Sdelphij if (sscanf(type, "%dx%d", &w, &h) == 2) { 531146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 53275344Ssobomax if (sizes[i].w == w && sizes[i].h == h) { 53375344Ssobomax size = DATASIZE(sizes[i]); 53475344Ssobomax io = sizes[i].io; 535146736Sdelphij font_height = sizes[i].h; 53675344Ssobomax } 537146736Sdelphij } 538146736Sdelphij } 53975344Ssobomax if (size == 0) { 54075344Ssobomax fclose(fd); 541146736Sdelphij revert(); 542146736Sdelphij errx(1, "%s: bad font size specification", type); 54375344Ssobomax } 54475344Ssobomax } else { 54575344Ssobomax /* Apply heuristics */ 546146736Sdelphij 54775344Ssobomax int j; 54875344Ssobomax int dsize[2]; 54975344Ssobomax 55075344Ssobomax size = DATASIZE(sizes[0]); 55175344Ssobomax fontmap = (char*) malloc(size); 55275344Ssobomax dsize[0] = decode(fd, fontmap, size); 55375344Ssobomax dsize[1] = fsize(fd); 55475344Ssobomax free(fontmap); 55575344Ssobomax 55675344Ssobomax size = 0; 557146736Sdelphij for (j = 0; j < 2; j++) { 558146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 55975344Ssobomax if (DATASIZE(sizes[i]) == dsize[j]) { 56075344Ssobomax size = dsize[j]; 56175344Ssobomax io = sizes[i].io; 562146736Sdelphij font_height = sizes[i].h; 56375344Ssobomax j = 2; /* XXX */ 56475344Ssobomax break; 56575344Ssobomax } 566146736Sdelphij } 567146736Sdelphij } 56875344Ssobomax 56975344Ssobomax if (size == 0) { 57075344Ssobomax fclose(fd); 571146736Sdelphij revert(); 572146736Sdelphij errx(1, "%s: can't guess font size", filename); 57375344Ssobomax } 574146736Sdelphij 57575344Ssobomax rewind(fd); 5762089Ssos } 57775344Ssobomax 5782089Ssos fontmap = (char*) malloc(size); 579146736Sdelphij 58075344Ssobomax if (decode(fd, fontmap, size) != size) { 5812089Ssos rewind(fd); 582146736Sdelphij if (fsize(fd) != size || 583146736Sdelphij fread(fontmap, 1, size, fd) != (size_t)size) { 58475344Ssobomax warnx("%s: bad font file", filename); 58523457Sbrian fclose(fd); 5862089Ssos free(fontmap); 587146736Sdelphij revert(); 588146736Sdelphij errx(1, "%s: bad font file", filename); 5892089Ssos } 5902089Ssos } 591146736Sdelphij 592146736Sdelphij if (ioctl(0, io, fontmap) == -1) { 593146736Sdelphij revert(); 594146736Sdelphij errc(1, errno, "loading font"); 595146736Sdelphij } 596146736Sdelphij 59723457Sbrian fclose(fd); 5982089Ssos free(fontmap); 5992089Ssos} 6002089Ssos 601146736Sdelphij 602146736Sdelphij/* 603146736Sdelphij * Set the timeout for the screensaver. 604146736Sdelphij */ 605146736Sdelphij 606140159Sdelphijstatic void 6072089Ssosset_screensaver_timeout(char *arg) 6082089Ssos{ 6092089Ssos int nsec; 6102089Ssos 611146736Sdelphij if (!strcmp(arg, "off")) { 6122089Ssos nsec = 0; 613146736Sdelphij } else { 6142089Ssos nsec = atoi(arg); 615146736Sdelphij 6162089Ssos if ((*arg == '\0') || (nsec < 1)) { 617146736Sdelphij revert(); 618146736Sdelphij errx(1, "argument must be a positive number"); 6192089Ssos } 6202089Ssos } 621146736Sdelphij 622146736Sdelphij if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) { 623146736Sdelphij revert(); 624146736Sdelphij errc(1, errno, "setting screensaver period"); 625146736Sdelphij } 6262089Ssos} 6272089Ssos 628146736Sdelphij 629146736Sdelphij/* 630146736Sdelphij * Set the cursor's shape/type. 631146736Sdelphij */ 632146736Sdelphij 633140159Sdelphijstatic void 634228990Suqsset_cursor_type(char *appearance) 6352089Ssos{ 6365536Ssos int type; 6372089Ssos 638228990Suqs if (!strcmp(appearance, "normal")) 6396230Ssos type = 0; 640228990Suqs else if (!strcmp(appearance, "blink")) 6415536Ssos type = 1; 642228990Suqs else if (!strcmp(appearance, "destructive")) 6436230Ssos type = 3; 6445536Ssos else { 645146736Sdelphij revert(); 646146736Sdelphij errx(1, "argument to -c must be normal, blink or destructive"); 6472089Ssos } 648146736Sdelphij 649146736Sdelphij if (ioctl(0, CONS_CURSORTYPE, &type) == -1) { 650146736Sdelphij revert(); 651146736Sdelphij errc(1, errno, "setting cursor type"); 652146736Sdelphij } 6532089Ssos} 6542089Ssos 655146736Sdelphij 656146736Sdelphij/* 657146736Sdelphij * Set the video mode. 658146736Sdelphij */ 659146736Sdelphij 660140159Sdelphijstatic int 661146736Sdelphijvideo_mode(int argc, char **argv, int *mode_index) 6622089Ssos{ 66339592Syokota static struct { 664140159Sdelphij const char *name; 66539592Syokota unsigned long mode; 666146736Sdelphij unsigned long mode_num; 66739592Syokota } modes[] = { 668146736Sdelphij { "80x25", SW_TEXT_80x25, M_TEXT_80x25 }, 669146736Sdelphij { "80x30", SW_TEXT_80x30, M_TEXT_80x30 }, 670146736Sdelphij { "80x43", SW_TEXT_80x43, M_TEXT_80x43 }, 671146736Sdelphij { "80x50", SW_TEXT_80x50, M_TEXT_80x50 }, 672146736Sdelphij { "80x60", SW_TEXT_80x60, M_TEXT_80x60 }, 673146736Sdelphij { "132x25", SW_TEXT_132x25, M_TEXT_132x25 }, 674146736Sdelphij { "132x30", SW_TEXT_132x30, M_TEXT_132x30 }, 675146736Sdelphij { "132x43", SW_TEXT_132x43, M_TEXT_132x43 }, 676146736Sdelphij { "132x50", SW_TEXT_132x50, M_TEXT_132x50 }, 677146736Sdelphij { "132x60", SW_TEXT_132x60, M_TEXT_132x60 }, 678146736Sdelphij { "VGA_40x25", SW_VGA_C40x25, M_VGA_C40x25 }, 679146736Sdelphij { "VGA_80x25", SW_VGA_C80x25, M_VGA_C80x25 }, 680146736Sdelphij { "VGA_80x30", SW_VGA_C80x30, M_VGA_C80x30 }, 681146736Sdelphij { "VGA_80x50", SW_VGA_C80x50, M_VGA_C80x50 }, 682146736Sdelphij { "VGA_80x60", SW_VGA_C80x60, M_VGA_C80x60 }, 68348105Syokota#ifdef SW_VGA_C90x25 684146736Sdelphij { "VGA_90x25", SW_VGA_C90x25, M_VGA_C90x25 }, 685146736Sdelphij { "VGA_90x30", SW_VGA_C90x30, M_VGA_C90x30 }, 686146736Sdelphij { "VGA_90x43", SW_VGA_C90x43, M_VGA_C90x43 }, 687146736Sdelphij { "VGA_90x50", SW_VGA_C90x50, M_VGA_C90x50 }, 688146736Sdelphij { "VGA_90x60", SW_VGA_C90x60, M_VGA_C90x60 }, 68948105Syokota#endif 690146736Sdelphij { "VGA_320x200", SW_VGA_CG320, M_CG320 }, 691146736Sdelphij { "EGA_80x25", SW_ENH_C80x25, M_ENH_C80x25 }, 692146736Sdelphij { "EGA_80x43", SW_ENH_C80x43, M_ENH_C80x43 }, 693146736Sdelphij { "VESA_132x25", SW_VESA_C132x25,M_VESA_C132x25 }, 694146736Sdelphij { "VESA_132x43", SW_VESA_C132x43,M_VESA_C132x43 }, 695146736Sdelphij { "VESA_132x50", SW_VESA_C132x50,M_VESA_C132x50 }, 696146736Sdelphij { "VESA_132x60", SW_VESA_C132x60,M_VESA_C132x60 }, 697146736Sdelphij { "VESA_800x600", SW_VESA_800x600,M_VESA_800x600 }, 698146736Sdelphij { NULL, 0, 0 }, 69939592Syokota }; 700146736Sdelphij 701146736Sdelphij int new_mode_num = 0; 70242605Smjacob unsigned long mode = 0; 70348105Syokota int cur_mode; 70448105Syokota int ioerr; 70539287Ssos int size[3]; 70639592Syokota int i; 7072089Ssos 70848105Syokota if (ioctl(0, CONS_GET, &cur_mode) < 0) 70948105Syokota err(1, "cannot get the current video mode"); 710146736Sdelphij 711146736Sdelphij /* 712146736Sdelphij * Parse the video mode argument... 713146736Sdelphij */ 714146736Sdelphij 715146736Sdelphij if (*mode_index < argc) { 716146736Sdelphij if (!strncmp(argv[*mode_index], "MODE_", 5)) { 717146736Sdelphij if (!isdigit(argv[*mode_index][5])) 718146736Sdelphij errx(1, "invalid video mode number"); 719146736Sdelphij 720146736Sdelphij new_mode_num = atoi(&argv[*mode_index][5]); 721146736Sdelphij } else { 722146736Sdelphij for (i = 0; modes[i].name != NULL; ++i) { 723146736Sdelphij if (!strcmp(argv[*mode_index], modes[i].name)) { 724146736Sdelphij mode = modes[i].mode; 725146736Sdelphij new_mode_num = modes[i].mode_num; 726146736Sdelphij break; 727146736Sdelphij } 72839592Syokota } 729146736Sdelphij 730146736Sdelphij if (modes[i].name == NULL) 731146736Sdelphij return EXIT_FAILURE; 732146736Sdelphij if (ioctl(0, mode, NULL) < 0) { 733146736Sdelphij warn("cannot set videomode"); 734146736Sdelphij return EXIT_FAILURE; 735146736Sdelphij } 73639592Syokota } 737146736Sdelphij 738146736Sdelphij /* 739146736Sdelphij * Collect enough information about the new video mode... 740146736Sdelphij */ 741146736Sdelphij 742146736Sdelphij new_mode_info.vi_mode = new_mode_num; 743146736Sdelphij 744146736Sdelphij if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) { 745146736Sdelphij revert(); 746146736Sdelphij errc(1, errno, "obtaining new video mode parameters"); 747120201Seivind } 748146736Sdelphij 749146736Sdelphij if (mode == 0) { 750146736Sdelphij if (new_mode_num >= M_VESA_BASE) 751146736Sdelphij mode = _IO('V', new_mode_num - M_VESA_BASE); 752146736Sdelphij else 753146736Sdelphij mode = _IO('S', new_mode_num); 754146736Sdelphij } 755146736Sdelphij 756146736Sdelphij /* 757146736Sdelphij * Try setting the new mode. 758146736Sdelphij */ 759146736Sdelphij 760146736Sdelphij if (ioctl(0, mode, NULL) == -1) { 761146736Sdelphij revert(); 762146736Sdelphij errc(1, errno, "setting video mode"); 763146736Sdelphij } 764146736Sdelphij 765146736Sdelphij /* 766146736Sdelphij * For raster modes it's not enough to just set the mode. 767146736Sdelphij * We also need to explicitly set the raster mode. 768146736Sdelphij */ 769146736Sdelphij 770146736Sdelphij if (new_mode_info.vi_flags & V_INFO_GRAPHICS) { 771146736Sdelphij /* font size */ 772146736Sdelphij 773146736Sdelphij if (font_height == 0) 774146736Sdelphij font_height = cur_info.console_info.font_size; 775146736Sdelphij 776146736Sdelphij size[2] = font_height; 777146736Sdelphij 778146736Sdelphij /* adjust columns */ 779146736Sdelphij 780146736Sdelphij if ((vesa_cols * 8 > new_mode_info.vi_width) || 781146736Sdelphij (vesa_cols <= 0)) { 782146736Sdelphij size[0] = new_mode_info.vi_width / 8; 78371642Ssobomax } else { 78471642Ssobomax size[0] = vesa_cols; 78571642Ssobomax } 786146736Sdelphij 787146736Sdelphij /* adjust rows */ 788146736Sdelphij 789146736Sdelphij if ((vesa_rows * font_height > new_mode_info.vi_height) || 790146736Sdelphij (vesa_rows <= 0)) { 791146736Sdelphij size[1] = new_mode_info.vi_height / 792146736Sdelphij font_height; 79371642Ssobomax } else { 79471642Ssobomax size[1] = vesa_rows; 79571642Ssobomax } 796146736Sdelphij 797146736Sdelphij /* set raster mode */ 798146736Sdelphij 79948105Syokota if (ioctl(0, KDRASTER, size)) { 80048105Syokota ioerr = errno; 80148105Syokota if (cur_mode >= M_VESA_BASE) 80280148Syokota ioctl(0, 80380148Syokota _IO('V', cur_mode - M_VESA_BASE), 80480148Syokota NULL); 80548105Syokota else 80648105Syokota ioctl(0, _IO('S', cur_mode), NULL); 807146736Sdelphij revert(); 80848105Syokota warnc(ioerr, "cannot activate raster display"); 809120201Seivind return EXIT_FAILURE; 81048105Syokota } 81139287Ssos } 812146736Sdelphij 813146736Sdelphij video_mode_changed = 1; 814146736Sdelphij 815146736Sdelphij (*mode_index)++; 8162089Ssos } 817120201Seivind return EXIT_SUCCESS; 8182089Ssos} 8198857Srgrimes 820146736Sdelphij 821146736Sdelphij/* 822146736Sdelphij * Return the number for a specified color name. 823146736Sdelphij */ 824146736Sdelphij 825140159Sdelphijstatic int 8262089Ssosget_color_number(char *color) 8272089Ssos{ 8282089Ssos int i; 8292089Ssos 830146736Sdelphij for (i=0; i<16; i++) { 8312089Ssos if (!strcmp(color, legal_colors[i])) 8322089Ssos return i; 833146736Sdelphij } 8342089Ssos return -1; 8352089Ssos} 8362089Ssos 837146736Sdelphij 838146736Sdelphij/* 839146736Sdelphij * Get normal text and background colors. 840146736Sdelphij */ 841146736Sdelphij 842140159Sdelphijstatic void 843146736Sdelphijget_normal_colors(int argc, char **argv, int *_index) 8442089Ssos{ 8452089Ssos int color; 8462089Ssos 847140159Sdelphij if (*_index < argc && (color = get_color_number(argv[*_index])) != -1) { 848140159Sdelphij (*_index)++; 849146241Snyan fprintf(stderr, "\033[=%dF", color); 850150246Srodrigc normal_fore_color=color; 851150246Srodrigc colors_changed = 1; 852140159Sdelphij if (*_index < argc 853140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 8542089Ssos && color < 8) { 855140159Sdelphij (*_index)++; 856146241Snyan fprintf(stderr, "\033[=%dG", color); 857150246Srodrigc normal_back_color=color; 8582089Ssos } 8592089Ssos } 8602089Ssos} 8612089Ssos 862146736Sdelphij 863146736Sdelphij/* 864146736Sdelphij * Get reverse text and background colors. 865146736Sdelphij */ 866146736Sdelphij 867140159Sdelphijstatic void 868146736Sdelphijget_reverse_colors(int argc, char **argv, int *_index) 8692089Ssos{ 8702089Ssos int color; 8712089Ssos 872140159Sdelphij if ((color = get_color_number(argv[*(_index)-1])) != -1) { 873146241Snyan fprintf(stderr, "\033[=%dH", color); 874150246Srodrigc revers_fore_color=color; 875150246Srodrigc colors_changed = 1; 876140159Sdelphij if (*_index < argc 877140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 8782089Ssos && color < 8) { 879140159Sdelphij (*_index)++; 880146241Snyan fprintf(stderr, "\033[=%dI", color); 881150246Srodrigc revers_back_color=color; 8822089Ssos } 8832089Ssos } 8842089Ssos} 8852089Ssos 886146736Sdelphij 887146736Sdelphij/* 888146736Sdelphij * Set normal and reverse foreground and background colors. 889146736Sdelphij */ 890146736Sdelphij 891140159Sdelphijstatic void 892146736Sdelphijset_colors(void) 893146736Sdelphij{ 894146736Sdelphij fprintf(stderr, "\033[=%dF", normal_fore_color); 895146736Sdelphij fprintf(stderr, "\033[=%dG", normal_back_color); 896146736Sdelphij fprintf(stderr, "\033[=%dH", revers_fore_color); 897146736Sdelphij fprintf(stderr, "\033[=%dI", revers_back_color); 898146736Sdelphij} 899146736Sdelphij 900146736Sdelphij 901146736Sdelphij/* 902146736Sdelphij * Switch to virtual terminal #arg. 903146736Sdelphij */ 904146736Sdelphij 905146736Sdelphijstatic void 90623457Sbrianset_console(char *arg) 90723457Sbrian{ 90823457Sbrian int n; 90923457Sbrian 910146736Sdelphij if(!arg || strspn(arg,"0123456789") != strlen(arg)) { 911146736Sdelphij revert(); 912146736Sdelphij errx(1, "bad console number"); 91323457Sbrian } 91423457Sbrian 91523457Sbrian n = atoi(arg); 916146736Sdelphij 91751393Syokota if (n < 1 || n > 16) { 918146736Sdelphij revert(); 919146736Sdelphij errx(1, "console number out of range"); 920162671Sru } else if (ioctl(0, VT_ACTIVATE, n) == -1) { 921146736Sdelphij revert(); 922146736Sdelphij errc(1, errno, "switching vty"); 923146736Sdelphij } 92423457Sbrian} 92523457Sbrian 926146736Sdelphij 927146736Sdelphij/* 928146736Sdelphij * Sets the border color. 929146736Sdelphij */ 930146736Sdelphij 931140159Sdelphijstatic void 9322089Ssosset_border_color(char *arg) 9332089Ssos{ 9342089Ssos int color; 9352089Ssos 9362089Ssos if ((color = get_color_number(arg)) != -1) { 937146241Snyan fprintf(stderr, "\033[=%dA", color); 9382089Ssos } 9392089Ssos else 9408857Srgrimes usage(); 9412089Ssos} 9422089Ssos 943140159Sdelphijstatic void 94455849Syokotaset_mouse_char(char *arg) 94555849Syokota{ 94655849Syokota struct mouse_info mouse; 94755849Syokota long l; 94855849Syokota 94955849Syokota l = strtol(arg, NULL, 0); 950146736Sdelphij 95175788Sache if ((l < 0) || (l > UCHAR_MAX - 3)) { 952146736Sdelphij revert(); 95375788Sache warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3); 95455849Syokota return; 95555849Syokota } 956146736Sdelphij 95755849Syokota mouse.operation = MOUSE_MOUSECHAR; 95855849Syokota mouse.u.mouse_char = (int)l; 959146736Sdelphij 960146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 961146736Sdelphij revert(); 962146736Sdelphij errc(1, errno, "setting mouse character"); 963146736Sdelphij } 96455849Syokota} 96555849Syokota 966146736Sdelphij 967146736Sdelphij/* 968146736Sdelphij * Show/hide the mouse. 969146736Sdelphij */ 970146736Sdelphij 971140159Sdelphijstatic void 97216565Ssosset_mouse(char *arg) 97316565Ssos{ 97416565Ssos struct mouse_info mouse; 97516565Ssos 976146736Sdelphij if (!strcmp(arg, "on")) { 97716565Ssos mouse.operation = MOUSE_SHOW; 978146736Sdelphij } else if (!strcmp(arg, "off")) { 97916565Ssos mouse.operation = MOUSE_HIDE; 980146736Sdelphij } else { 981146736Sdelphij revert(); 982146736Sdelphij errx(1, "argument to -m must be either on or off"); 98316565Ssos } 984146736Sdelphij 985146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 986146736Sdelphij revert(); 987146736Sdelphij errc(1, errno, "%sing the mouse", 988146736Sdelphij mouse.operation == MOUSE_SHOW ? "show" : "hid"); 989146736Sdelphij } 99016565Ssos} 99116565Ssos 992146736Sdelphij 993140159Sdelphijstatic void 99499705Sddset_lockswitch(char *arg) 99599705Sdd{ 99699705Sdd int data; 99799705Sdd 998146736Sdelphij if (!strcmp(arg, "off")) { 99999705Sdd data = 0x01; 1000146736Sdelphij } else if (!strcmp(arg, "on")) { 100199705Sdd data = 0x02; 1002146736Sdelphij } else { 1003146736Sdelphij revert(); 1004146736Sdelphij errx(1, "argument to -S must be either on or off"); 100599705Sdd } 1006146736Sdelphij 1007146736Sdelphij if (ioctl(0, VT_LOCKSWITCH, &data) == -1) { 1008146736Sdelphij revert(); 1009146736Sdelphij errc(1, errno, "turning %s vty switching", 1010146736Sdelphij data == 0x01 ? "off" : "on"); 1011146736Sdelphij } 101299705Sdd} 101399705Sdd 1014146736Sdelphij 1015146736Sdelphij/* 1016146736Sdelphij * Return the adapter name for a specified type. 1017146736Sdelphij */ 1018146736Sdelphij 1019140159Sdelphijstatic const char 102039287Ssos*adapter_name(int type) 102139287Ssos{ 102239287Ssos static struct { 102339287Ssos int type; 1024140159Sdelphij const char *name; 102539287Ssos } names[] = { 102639287Ssos { KD_MONO, "MDA" }, 102739287Ssos { KD_HERCULES, "Hercules" }, 102839287Ssos { KD_CGA, "CGA" }, 102939287Ssos { KD_EGA, "EGA" }, 103039287Ssos { KD_VGA, "VGA" }, 103139287Ssos { KD_PC98, "PC-98xx" }, 103248105Syokota { KD_TGA, "TGA" }, 103339287Ssos { -1, "Unknown" }, 103439287Ssos }; 1035146736Sdelphij 103639287Ssos int i; 103739287Ssos 103839287Ssos for (i = 0; names[i].type != -1; ++i) 103939287Ssos if (names[i].type == type) 104039287Ssos break; 104139287Ssos return names[i].name; 104239287Ssos} 104339287Ssos 1044146736Sdelphij 1045146736Sdelphij/* 1046146736Sdelphij * Show graphics adapter information. 1047146736Sdelphij */ 1048146736Sdelphij 1049140159Sdelphijstatic void 105039287Ssosshow_adapter_info(void) 105139287Ssos{ 105242505Syokota struct video_adapter_info ad; 105339287Ssos 105439287Ssos ad.va_index = 0; 1055146736Sdelphij 1056146736Sdelphij if (ioctl(0, CONS_ADPINFO, &ad) == -1) { 1057146736Sdelphij revert(); 1058146736Sdelphij errc(1, errno, "obtaining adapter information"); 105939287Ssos } 106039287Ssos 106142505Syokota printf("fb%d:\n", ad.va_index); 106242505Syokota printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 106342505Syokota (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 106439287Ssos (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 106542505Syokota adapter_name(ad.va_type), ad.va_type, ad.va_flags); 106639287Ssos printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 106739287Ssos ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 1068140159Sdelphij printf(" frame buffer window:0x%zx, buffer size:0x%zx\n", 106948105Syokota ad.va_window, ad.va_buffer_size); 1070140159Sdelphij printf(" window size:0x%zx, origin:0x%x\n", 107148105Syokota ad.va_window_size, ad.va_window_orig); 107248105Syokota printf(" display start address (%d, %d), scan line width:%d\n", 107348105Syokota ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); 1074140159Sdelphij printf(" reserved:0x%zx\n", ad.va_unused0); 107539287Ssos} 107639287Ssos 1077146736Sdelphij 1078146736Sdelphij/* 1079146736Sdelphij * Show video mode information. 1080146736Sdelphij */ 1081146736Sdelphij 1082140159Sdelphijstatic void 108339287Ssosshow_mode_info(void) 108439287Ssos{ 1085205855Sjkim char buf[80]; 1086140159Sdelphij struct video_info _info; 1087205855Sjkim int c; 1088205855Sjkim int mm; 108939287Ssos int mode; 109039287Ssos 109139287Ssos printf(" mode# flags type size " 109239287Ssos "font window linear buffer\n"); 109339287Ssos printf("---------------------------------------" 109439287Ssos "---------------------------------------\n"); 1095146736Sdelphij 1096250509Seadler for (mode = 0; mode <= M_VESA_MODE_MAX; ++mode) { 1097140159Sdelphij _info.vi_mode = mode; 1098140159Sdelphij if (ioctl(0, CONS_MODEINFO, &_info)) 109939287Ssos continue; 1100140159Sdelphij if (_info.vi_mode != mode) 110148105Syokota continue; 110239287Ssos 110339287Ssos printf("%3d (0x%03x)", mode, mode); 1104140159Sdelphij printf(" 0x%08x", _info.vi_flags); 1105140159Sdelphij if (_info.vi_flags & V_INFO_GRAPHICS) { 110639287Ssos c = 'G'; 1107146736Sdelphij 1108205855Sjkim if (_info.vi_mem_model == V_INFO_MM_PLANAR) 1109205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %d", 1110205855Sjkim _info.vi_width, _info.vi_height, 1111205855Sjkim _info.vi_depth, _info.vi_planes); 1112205855Sjkim else { 1113205855Sjkim switch (_info.vi_mem_model) { 1114205855Sjkim case V_INFO_MM_PACKED: 1115205855Sjkim mm = 'P'; 1116205855Sjkim break; 1117205855Sjkim case V_INFO_MM_DIRECT: 1118205855Sjkim mm = 'D'; 1119205855Sjkim break; 1120205855Sjkim case V_INFO_MM_CGA: 1121205855Sjkim mm = 'C'; 1122205855Sjkim break; 1123205855Sjkim case V_INFO_MM_HGC: 1124205855Sjkim mm = 'H'; 1125205855Sjkim break; 1126205855Sjkim case V_INFO_MM_VGAX: 1127205855Sjkim mm = 'V'; 1128205855Sjkim break; 1129205855Sjkim default: 1130205855Sjkim mm = ' '; 1131205855Sjkim break; 1132205855Sjkim } 1133205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %c", 1134205855Sjkim _info.vi_width, _info.vi_height, 1135205855Sjkim _info.vi_depth, mm); 1136205855Sjkim } 113739287Ssos } else { 113839287Ssos c = 'T'; 1139146736Sdelphij 114039287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1141140159Sdelphij _info.vi_width, _info.vi_height); 114239287Ssos } 1143146736Sdelphij 114439287Ssos printf(" %c %-15s", c, buf); 114539287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1146140159Sdelphij _info.vi_cwidth, _info.vi_cheight); 114739287Ssos printf(" %-5s", buf); 1148140159Sdelphij printf(" 0x%05zx %2dk %2dk", 1149140159Sdelphij _info.vi_window, (int)_info.vi_window_size/1024, 1150140159Sdelphij (int)_info.vi_window_gran/1024); 1151140159Sdelphij printf(" 0x%08zx %dk\n", 1152140159Sdelphij _info.vi_buffer, (int)_info.vi_buffer_size/1024); 115339287Ssos } 115439287Ssos} 115539287Ssos 1156146736Sdelphij 1157140159Sdelphijstatic void 115839287Ssosshow_info(char *arg) 115939287Ssos{ 1160146736Sdelphij if (!strcmp(arg, "adapter")) { 116139287Ssos show_adapter_info(); 1162146736Sdelphij } else if (!strcmp(arg, "mode")) { 116339287Ssos show_mode_info(); 1164146736Sdelphij } else { 1165146736Sdelphij revert(); 1166146736Sdelphij errx(1, "argument to -i must be either adapter or mode"); 116739287Ssos } 116839287Ssos} 116939287Ssos 1170146736Sdelphij 1171140159Sdelphijstatic void 1172140159Sdelphijtest_frame(void) 11732089Ssos{ 1174146237Snyan int i, cur_mode, fore; 11752089Ssos 1176146237Snyan fore = 15; 1177146237Snyan 1178146237Snyan if (ioctl(0, CONS_GET, &cur_mode) < 0) 1179146237Snyan err(1, "must be on a virtual console"); 1180146237Snyan switch (cur_mode) { 1181146237Snyan case M_PC98_80x25: 1182146237Snyan case M_PC98_80x30: 1183146237Snyan fore = 7; 1184146237Snyan break; 1185146237Snyan } 1186146237Snyan 1187146241Snyan fprintf(stdout, "\033[=0G\n\n"); 11882089Ssos for (i=0; i<8; i++) { 1189146241Snyan fprintf(stdout, "\033[=%dF\033[=0G %2d \033[=%dF%-16s" 1190146241Snyan "\033[=%dF\033[=0G %2d \033[=%dF%-16s " 1191146241Snyan "\033[=%dF %2d \033[=%dGBACKGROUND\033[=0G\n", 1192146237Snyan fore, i, i, legal_colors[i], 1193146237Snyan fore, i+8, i+8, legal_colors[i+8], 1194146237Snyan fore, i, i); 11952089Ssos } 1196146241Snyan fprintf(stdout, "\033[=%dF\033[=%dG\033[=%dH\033[=%dI\n", 11978857Srgrimes info.mv_norm.fore, info.mv_norm.back, 11982089Ssos info.mv_rev.fore, info.mv_rev.back); 11992089Ssos} 12002089Ssos 1201146736Sdelphij 120276845Ssobomax/* 120376845Ssobomax * Snapshot the video memory of that terminal, using the CONS_SCRSHOT 120476845Ssobomax * ioctl, and writes the results to stdout either in the special 120576845Ssobomax * binary format (see manual page for details), or in the plain 120676845Ssobomax * text format. 120776845Ssobomax */ 1208146736Sdelphij 1209140159Sdelphijstatic void 1210102111Ssobomaxdump_screen(int mode, int opt) 121176845Ssobomax{ 121276845Ssobomax scrshot_t shot; 1213140159Sdelphij vid_info_t _info; 121476845Ssobomax 1215140159Sdelphij _info.size = sizeof(_info); 1216146736Sdelphij 1217140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 1218146736Sdelphij revert(); 1219146736Sdelphij errc(1, errno, "obtaining current video mode parameters"); 122076845Ssobomax return; 122176845Ssobomax } 122276845Ssobomax 1223102111Ssobomax shot.x = shot.y = 0; 1224140159Sdelphij shot.xsize = _info.mv_csz; 1225140159Sdelphij shot.ysize = _info.mv_rsz; 1226102111Ssobomax if (opt == DUMP_ALL) 1227140159Sdelphij shot.ysize += _info.mv_hsz; 1228102111Ssobomax 1229102111Ssobomax shot.buf = alloca(shot.xsize * shot.ysize * sizeof(u_int16_t)); 123076845Ssobomax if (shot.buf == NULL) { 1231146736Sdelphij revert(); 1232146736Sdelphij errx(1, "failed to allocate memory for dump"); 123376845Ssobomax } 123476845Ssobomax 123576845Ssobomax if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { 1236146736Sdelphij revert(); 1237146736Sdelphij errc(1, errno, "dumping screen"); 123876845Ssobomax } 123976845Ssobomax 1240102111Ssobomax if (mode == DUMP_FMT_RAW) { 124176845Ssobomax printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, 124276845Ssobomax shot.xsize, shot.ysize); 1243146736Sdelphij 124476845Ssobomax fflush(stdout); 124576845Ssobomax 1246146736Sdelphij write(STDOUT_FILENO, shot.buf, 1247146736Sdelphij shot.xsize * shot.ysize * sizeof(u_int16_t)); 124876845Ssobomax } else { 124976845Ssobomax char *line; 125076845Ssobomax int x, y; 125176845Ssobomax u_int16_t ch; 125276845Ssobomax 125376845Ssobomax line = alloca(shot.xsize + 1); 1254146736Sdelphij 125576845Ssobomax if (line == NULL) { 1256146736Sdelphij revert(); 1257146736Sdelphij errx(1, "failed to allocate memory for line buffer"); 125876845Ssobomax } 125976845Ssobomax 126076845Ssobomax for (y = 0; y < shot.ysize; y++) { 126176845Ssobomax for (x = 0; x < shot.xsize; x++) { 126276845Ssobomax ch = shot.buf[x + (y * shot.xsize)]; 126376845Ssobomax ch &= 0xff; 1264146736Sdelphij 126576845Ssobomax if (isprint(ch) == 0) 126676845Ssobomax ch = ' '; 1267146736Sdelphij 126876845Ssobomax line[x] = (char)ch; 126976845Ssobomax } 127076845Ssobomax 127176845Ssobomax /* Trim trailing spaces */ 1272146736Sdelphij 127376845Ssobomax do { 127476845Ssobomax line[x--] = '\0'; 127576845Ssobomax } while (line[x] == ' ' && x != 0); 127676845Ssobomax 127776845Ssobomax puts(line); 127876845Ssobomax } 1279146736Sdelphij 128076845Ssobomax fflush(stdout); 128176845Ssobomax } 128276845Ssobomax} 128376845Ssobomax 1284146736Sdelphij 1285146736Sdelphij/* 1286146736Sdelphij * Set the console history buffer size. 1287146736Sdelphij */ 1288146736Sdelphij 1289140159Sdelphijstatic void 129077329Sdesset_history(char *opt) 129177329Sdes{ 129277329Sdes int size; 129377329Sdes 129477329Sdes size = atoi(opt); 1295146736Sdelphij 129677329Sdes if ((*opt == '\0') || size < 0) { 1297146736Sdelphij revert(); 1298146736Sdelphij errx(1, "argument must be a positive number"); 129977329Sdes } 1300146736Sdelphij 1301146736Sdelphij if (ioctl(0, CONS_HISTORY, &size) == -1) { 1302146736Sdelphij revert(); 1303146736Sdelphij errc(1, errno, "setting history buffer size"); 1304146736Sdelphij } 130577329Sdes} 130677329Sdes 1307146736Sdelphij 1308146736Sdelphij/* 1309146736Sdelphij * Clear the console history buffer. 1310146736Sdelphij */ 1311146736Sdelphij 1312140159Sdelphijstatic void 1313140159Sdelphijclear_history(void) 131477329Sdes{ 1315146736Sdelphij if (ioctl(0, CONS_CLRHIST) == -1) { 1316146736Sdelphij revert(); 1317146736Sdelphij errc(1, errno, "clearing history buffer"); 1318146736Sdelphij } 131977329Sdes} 132077329Sdes 1321199174Sedstatic void 1322199174Sedset_terminal_mode(char *arg) 1323199174Sed{ 1324146736Sdelphij 1325199174Sed if (strcmp(arg, "xterm") == 0) 1326199174Sed fprintf(stderr, "\033[=T"); 1327199174Sed else if (strcmp(arg, "cons25") == 0) 1328199174Sed fprintf(stderr, "\033[=1T"); 1329199174Sed} 1330199174Sed 1331199174Sed 133223457Sbrianint 13332089Ssosmain(int argc, char **argv) 13342089Ssos{ 1335237777Sache char *font, *type, *termmode; 1336267540Sray const char *opts; 1337102111Ssobomax int dumpmod, dumpopt, opt; 1338120201Seivind int reterr; 13392089Ssos 1340267540Sray vt4_mode = is_vt4(); 1341267540Sray 1342146736Sdelphij init(); 1343146736Sdelphij 13442089Ssos info.size = sizeof(info); 1345146736Sdelphij 1346146736Sdelphij if (ioctl(0, CONS_GETINFO, &info) == -1) 134730764Scharnier err(1, "must be on a virtual console"); 1348102111Ssobomax dumpmod = 0; 1349102111Ssobomax dumpopt = DUMP_FBF; 1350237777Sache termmode = NULL; 1351267540Sray if (vt4_mode) 1352273921Sdumbbell opts = "b:Cc:fg:h:Hi:M:m:pPr:S:s:T:t:x"; 1353267540Sray else 1354286291Semaste opts = "b:Cc:dfg:h:Hi:l:LM:m:pPr:S:s:T:t:x"; 1355267540Sray 1356267540Sray while ((opt = getopt(argc, argv, opts)) != -1) 13572089Ssos switch(opt) { 135877329Sdes case 'b': 135977329Sdes set_border_color(optarg); 136077329Sdes break; 136177329Sdes case 'C': 136277329Sdes clear_history(); 136377329Sdes break; 136477329Sdes case 'c': 136577329Sdes set_cursor_type(optarg); 136677329Sdes break; 136777329Sdes case 'd': 1368267540Sray if (vt4_mode) 1369267540Sray break; 137077329Sdes print_scrnmap(); 137177329Sdes break; 137277329Sdes case 'f': 1373273921Sdumbbell optarg = nextarg(argc, argv, &optind, 'f', 0); 1374273921Sdumbbell if (optarg != NULL) { 1375273921Sdumbbell font = nextarg(argc, argv, &optind, 'f', 0); 1376146736Sdelphij 1377273921Sdumbbell if (font == NULL) { 1378273921Sdumbbell type = NULL; 1379273921Sdumbbell font = optarg; 1380273921Sdumbbell } else 1381273921Sdumbbell type = optarg; 1382273921Sdumbbell 1383273921Sdumbbell load_font(type, font); 1384273921Sdumbbell } else { 1385273921Sdumbbell if (!vt4_mode) 1386273921Sdumbbell usage(); /* Switch syscons to ROM? */ 1387273921Sdumbbell 1388273921Sdumbbell load_default_vt4font(); 138977329Sdes } 139077329Sdes break; 139177329Sdes case 'g': 1392146736Sdelphij if (sscanf(optarg, "%dx%d", 1393146736Sdelphij &vesa_cols, &vesa_rows) != 2) { 1394146736Sdelphij revert(); 139577329Sdes warnx("incorrect geometry: %s", optarg); 13962089Ssos usage(); 139777329Sdes } 1398146736Sdelphij break; 139977329Sdes case 'h': 140077329Sdes set_history(optarg); 140177329Sdes break; 1402102111Ssobomax case 'H': 1403102111Ssobomax dumpopt = DUMP_ALL; 1404102111Ssobomax break; 140577329Sdes case 'i': 140677329Sdes show_info(optarg); 140777329Sdes break; 140877329Sdes case 'l': 1409267540Sray if (vt4_mode) 1410267540Sray break; 141177329Sdes load_scrnmap(optarg); 141277329Sdes break; 141377329Sdes case 'L': 1414267540Sray if (vt4_mode) 1415267540Sray break; 141677329Sdes load_default_scrnmap(); 141777329Sdes break; 141877329Sdes case 'M': 141977329Sdes set_mouse_char(optarg); 142077329Sdes break; 142177329Sdes case 'm': 142277329Sdes set_mouse(optarg); 142377329Sdes break; 142477329Sdes case 'p': 1425102111Ssobomax dumpmod = DUMP_FMT_RAW; 142677329Sdes break; 142777329Sdes case 'P': 1428102111Ssobomax dumpmod = DUMP_FMT_TXT; 142977329Sdes break; 143077329Sdes case 'r': 1431146736Sdelphij get_reverse_colors(argc, argv, &optind); 143277329Sdes break; 143399705Sdd case 'S': 143499705Sdd set_lockswitch(optarg); 143599705Sdd break; 143677329Sdes case 's': 143777329Sdes set_console(optarg); 143877329Sdes break; 1439199174Sed case 'T': 1440237777Sache if (strcmp(optarg, "xterm") != 0 && 1441237777Sache strcmp(optarg, "cons25") != 0) 1442237777Sache usage(); 1443237777Sache termmode = optarg; 1444199174Sed break; 144577329Sdes case 't': 144677329Sdes set_screensaver_timeout(optarg); 144777329Sdes break; 144877329Sdes case 'x': 144977329Sdes hex = 1; 145077329Sdes break; 145177329Sdes default: 145277329Sdes usage(); 14532089Ssos } 1454146736Sdelphij 1455102111Ssobomax if (dumpmod != 0) 1456102111Ssobomax dump_screen(dumpmod, dumpopt); 1457120201Seivind reterr = video_mode(argc, argv, &optind); 1458146736Sdelphij get_normal_colors(argc, argv, &optind); 1459146736Sdelphij 14602089Ssos if (optind < argc && !strcmp(argv[optind], "show")) { 14612089Ssos test_frame(); 14622089Ssos optind++; 14632089Ssos } 1464146736Sdelphij 1465146736Sdelphij video_mode(argc, argv, &optind); 1466237777Sache if (termmode != NULL) 1467237777Sache set_terminal_mode(termmode); 1468146736Sdelphij 1469146736Sdelphij get_normal_colors(argc, argv, &optind); 1470146736Sdelphij 1471146736Sdelphij if (colors_changed || video_mode_changed) { 1472146736Sdelphij if (!(new_mode_info.vi_flags & V_INFO_GRAPHICS)) { 1473146736Sdelphij if ((normal_back_color < 8) && (revers_back_color < 8)) { 1474146736Sdelphij set_colors(); 1475146736Sdelphij } else { 1476146736Sdelphij revert(); 1477146736Sdelphij errx(1, "bg color for text modes must be < 8"); 1478146736Sdelphij } 1479146736Sdelphij } else { 1480146736Sdelphij set_colors(); 1481146736Sdelphij } 1482146736Sdelphij } 1483146736Sdelphij 148430764Scharnier if ((optind != argc) || (argc == 1)) 14852089Ssos usage(); 1486120201Seivind return reterr; 14872089Ssos} 14882089Ssos 1489