Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: console.c,v 1.3 2009/07/20 04:59:03 kiyohara Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 Michael Smith <msmith (at) 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/libsa/loadfile.h>
     34 #include <lib/libkern/libkern.h>
     35 
     36 #include "bootstrap.h"
     37 /*
     38  * Core console support
     39  */
     40 
     41 static int	cons_set(struct env_var *ev, int flags, void *value);
     42 static int	cons_find(char *name);
     43 
     44 /*
     45  * Detect possible console(s) to use.  The first probed console
     46  * is marked active.  Also create the console variable.
     47  *
     48  * XXX Add logic for multiple console support.
     49  */
     50 void
     51 cons_probe(void)
     52 {
     53     int			cons;
     54     int			active;
     55     char		*prefconsole;
     56 
     57     /* Do all console probes */
     58     for (cons = 0; consoles[cons] != NULL; cons++) {
     59 	consoles[cons]->c_flags = 0;
     60  	consoles[cons]->c_probe(consoles[cons]);
     61     }
     62     /* Now find the first working one */
     63     active = -1;
     64     for (cons = 0; consoles[cons] != NULL && active == -1; cons++) {
     65 	consoles[cons]->c_flags = 0;
     66  	consoles[cons]->c_probe(consoles[cons]);
     67 	if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT))
     68 	    active = cons;
     69     }
     70 
     71     /* Check to see if a console preference has already been registered */
     72     prefconsole = getenv("console");
     73     if (prefconsole != NULL)
     74 	prefconsole = strdup(prefconsole);
     75     if (prefconsole != NULL) {
     76 	unsetenv("console");		/* we want to replace this */
     77 	for (cons = 0; consoles[cons] != NULL; cons++)
     78 	    /* look for the nominated console, use it if it's functional */
     79 	    if (!strcmp(prefconsole, consoles[cons]->c_name) &&
     80 		(consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)))
     81 		active = cons;
     82 	free(prefconsole);
     83     }
     84     if (active == -1)
     85 	active = 0;
     86     consoles[active]->c_flags |= (C_ACTIVEIN | C_ACTIVEOUT);
     87     consoles[active]->c_init(0);
     88 
     89     printf("Console: %s\n", consoles[active]->c_desc);
     90     env_setenv("console", EV_VOLATILE, consoles[active]->c_name, (ev_sethook_t *) cons_set,
     91 	env_nounset);
     92 }
     93 
     94 int
     95 getchar(void)
     96 {
     97     int		cons;
     98     int		rv;
     99 
    100     /* Loop forever polling all active consoles */
    101     for(;;)
    102 	for (cons = 0; consoles[cons] != NULL; cons++)
    103 	    if ((consoles[cons]->c_flags & C_ACTIVEIN) &&
    104 		((rv = consoles[cons]->c_in()) != -1))
    105 		return(rv);
    106 }
    107 
    108 int
    109 ischar(void)
    110 {
    111     int		cons;
    112 
    113     for (cons = 0; consoles[cons] != NULL; cons++)
    114 	if ((consoles[cons]->c_flags & C_ACTIVEIN) &&
    115 	    (consoles[cons]->c_ready() != 0))
    116 		return(1);
    117     return(0);
    118 }
    119 
    120 void
    121 putchar(int c)
    122 {
    123     int		cons;
    124 
    125     /* Expand newlines */
    126     if (c == '\n')
    127 	putchar('\r');
    128 
    129     for (cons = 0; consoles[cons] != NULL; cons++)
    130 	if (consoles[cons]->c_flags & C_ACTIVEOUT)
    131 	    consoles[cons]->c_out(c);
    132 }
    133 
    134 static int
    135 cons_find(char *name)
    136 {
    137     int		cons;
    138 
    139     for (cons = 0; consoles[cons] != NULL; cons++)
    140 	if (!strcmp(consoles[cons]->c_name, name))
    141 	    return(cons);
    142     return(-1);
    143 }
    144 
    145 
    146 /*
    147  * Select a console.
    148  *
    149  * XXX Note that the console system design allows for some extension
    150  *     here (eg. multiple consoles, input/output only, etc.)
    151  */
    152 static int
    153 cons_set(struct env_var *ev, int flags, void *value)
    154 {
    155     int		cons, active;
    156 
    157     if ((value == NULL) || ((active = cons_find(value)) == -1)) {
    158 	if (value != NULL)
    159 	    printf("no such console '%s'\n", (char *)value);
    160 	printf("Available consoles:\n");
    161 	for (cons = 0; consoles[cons] != NULL; cons++)
    162 	    printf("    %s\n", consoles[cons]->c_name);
    163 	return(CMD_ERROR);
    164     }
    165 
    166     /* disable all current consoles */
    167     for (cons = 0; consoles[cons] != NULL; cons++)
    168 	consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT);
    169 
    170     /* enable selected console */
    171     consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
    172     consoles[active]->c_init(0);
    173 
    174     env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
    175     return(CMD_OK);
    176 }
    177