1 /* $NetBSD: console.c,v 1.2 2006/04/22 07:58:53 cherry Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 /* __FBSDID("$FreeBSD: src/sys/boot/common/console.c,v 1.6 2003/08/25 23:30:41 obrien Exp $"); */ 31 32 #include <lib/libsa/stand.h> 33 #include <lib/libkern/libkern.h> 34 35 #include "bootstrap.h" 36 /* 37 * Core console support 38 */ 39 40 static int cons_set(struct env_var *ev, int flags, void *value); 41 static int cons_find(char *name); 42 43 /* 44 * Detect possible console(s) to use. The first probed console 45 * is marked active. Also create the console variable. 46 * 47 * XXX Add logic for multiple console support. 48 */ 49 void 50 cons_probe(void) 51 { 52 int cons; 53 int active; 54 char *prefconsole; 55 56 /* Do all console probes */ 57 for (cons = 0; consoles[cons] != NULL; cons++) { 58 consoles[cons]->c_flags = 0; 59 consoles[cons]->c_probe(consoles[cons]); 60 } 61 /* Now find the first working one */ 62 active = -1; 63 for (cons = 0; consoles[cons] != NULL && active == -1; cons++) { 64 consoles[cons]->c_flags = 0; 65 consoles[cons]->c_probe(consoles[cons]); 66 if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)) 67 active = cons; 68 } 69 70 /* Check to see if a console preference has already been registered */ 71 prefconsole = getenv("console"); 72 if (prefconsole != NULL) 73 prefconsole = strdup(prefconsole); 74 if (prefconsole != NULL) { 75 unsetenv("console"); /* we want to replace this */ 76 for (cons = 0; consoles[cons] != NULL; cons++) 77 /* look for the nominated console, use it if it's functional */ 78 if (!strcmp(prefconsole, consoles[cons]->c_name) && 79 (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT))) 80 active = cons; 81 free(prefconsole); 82 } 83 if (active == -1) 84 active = 0; 85 consoles[active]->c_flags |= (C_ACTIVEIN | C_ACTIVEOUT); 86 consoles[active]->c_init(0); 87 88 printf("Console: %s\n", consoles[active]->c_desc); 89 env_setenv("console", EV_VOLATILE, consoles[active]->c_name, (ev_sethook_t *) cons_set, 90 env_nounset); 91 } 92 93 int 94 getchar(void) 95 { 96 int cons; 97 int rv; 98 99 /* Loop forever polling all active consoles */ 100 for(;;) 101 for (cons = 0; consoles[cons] != NULL; cons++) 102 if ((consoles[cons]->c_flags & C_ACTIVEIN) && 103 ((rv = consoles[cons]->c_in()) != -1)) 104 return(rv); 105 } 106 107 int 108 ischar(void) 109 { 110 int cons; 111 112 for (cons = 0; consoles[cons] != NULL; cons++) 113 if ((consoles[cons]->c_flags & C_ACTIVEIN) && 114 (consoles[cons]->c_ready() != 0)) 115 return(1); 116 return(0); 117 } 118 119 void 120 putchar(int c) 121 { 122 int cons; 123 124 /* Expand newlines */ 125 if (c == '\n') 126 putchar('\r'); 127 128 for (cons = 0; consoles[cons] != NULL; cons++) 129 if (consoles[cons]->c_flags & C_ACTIVEOUT) 130 consoles[cons]->c_out(c); 131 } 132 133 static int 134 cons_find(char *name) 135 { 136 int cons; 137 138 for (cons = 0; consoles[cons] != NULL; cons++) 139 if (!strcmp(consoles[cons]->c_name, name)) 140 return(cons); 141 return(-1); 142 } 143 144 145 /* 146 * Select a console. 147 * 148 * XXX Note that the console system design allows for some extension 149 * here (eg. multiple consoles, input/output only, etc.) 150 */ 151 static int 152 cons_set(struct env_var *ev, int flags, void *value) 153 { 154 int cons, active; 155 156 if ((value == NULL) || ((active = cons_find(value)) == -1)) { 157 if (value != NULL) 158 printf("no such console '%s'\n", (char *)value); 159 printf("Available consoles:\n"); 160 for (cons = 0; consoles[cons] != NULL; cons++) 161 printf(" %s\n", consoles[cons]->c_name); 162 return(CMD_ERROR); 163 } 164 165 /* disable all current consoles */ 166 for (cons = 0; consoles[cons] != NULL; cons++) 167 consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT); 168 169 /* enable selected console */ 170 consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; 171 consoles[active]->c_init(0); 172 173 env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 174 return(CMD_OK); 175 } 176