/*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/boot/common/console.c,v 1.5 1999/08/28 00:39:46 peter Exp $ */ #include #include #include "bootstrap.h" /* * Core console support */ static int cons_set(struct env_var *ev, int flags, void *value); static int cons_find(char *name); struct kbxlat { u_char in; u_char out; }; static struct kbxlat kb_49[] = { { '@', '"' }, { '\'', ' ' }, { '^', '&' }, { '&', '/' }, { '*', '(' }, { '(', ')' }, { ')', '=' }, { '_', '?' }, { '-', '\\' }, { '+', '`' }, { '=', '\'' }, { 'z', 'y' }, { 'Z', 'Y' }, { 'y', 'z' }, { 'Y', 'Z' }, { '\\', '<' }, { '|', '>' }, { '<', ';' }, { '>', ':' }, { '?', '_' }, { '/', '-' }, { 0, 0 } }; struct kbptr { u_char country; struct kbxlat *kbxp; }; static struct kbptr kbptrtab[] = { { 49, kb_49 }, /* german keyboard translation */ { 0, NULL } }; static struct kbxlat *kxp = NULL; static u_char xlat(u_char in, struct kbxlat *kb_tab); /* * Detect possible console(s) to use. The first probed console * is marked active. Also create the console variable. * * XXX Add logic for multiple console support. */ void cons_probe(void) { int cons; int active; char *prefconsole; /* Do all console probes */ for (cons = 0; consoles[cons] != NULL; cons++) { consoles[cons]->c_flags = 0; consoles[cons]->c_probe(consoles[cons]); } /* Now find the first working one */ active = -1; for (cons = 0; consoles[cons] != NULL && active == -1; cons++) { consoles[cons]->c_flags = 0; consoles[cons]->c_probe(consoles[cons]); if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)) active = cons; } /* Check to see if a console preference has already been registered */ prefconsole = getenv("console"); if (prefconsole != NULL) prefconsole = strdup(prefconsole); if (prefconsole != NULL) { unsetenv("console"); /* we want to replace this */ for (cons = 0; consoles[cons] != NULL; cons++) /* look for the nominated console, use it if it's functional */ if (!strcmp(prefconsole, consoles[cons]->c_name) && (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT))) active = cons; free(prefconsole); } if (active == -1) active = 0; consoles[active]->c_flags |= (C_ACTIVEIN | C_ACTIVEOUT); consoles[active]->c_init(0); printf("Console: %s\n", consoles[active]->c_desc); env_setenv("console", EV_VOLATILE, consoles[active]->c_name, cons_set, env_nounset); } int getchar(void) { int cons; int rv; /* Loop forever polling all active consoles */ for(;;) for (cons = 0; consoles[cons] != NULL; cons++) if ((consoles[cons]->c_flags & C_ACTIVEIN) && ((rv = consoles[cons]->c_in()) != -1)) { if(kxp == NULL) return(rv); return(xlat(rv, kxp)); } } int ischar(void) { int cons; for (cons = 0; consoles[cons] != NULL; cons++) if ((consoles[cons]->c_flags & C_ACTIVEIN) && (consoles[cons]->c_ready() != 0)) return(1); return(0); } void putchar(int c) { int cons; /* Expand newlines */ if (c == '\n') putchar('\r'); for (cons = 0; consoles[cons] != NULL; cons++) if (consoles[cons]->c_flags & C_ACTIVEOUT) consoles[cons]->c_out(c); } static int cons_find(char *name) { int cons; for (cons = 0; consoles[cons] != NULL; cons++) if (!strcmp(consoles[cons]->c_name, name)) return(cons); return(-1); } /* * Select a console. * * XXX Note that the console system design allows for some extension * here (eg. multiple consoles, input/output only, etc.) */ static int cons_set(struct env_var *ev, int flags, void *value) { int cons, active; if ((value == NULL) || ((active = cons_find(value)) == -1)) { if (value != NULL) printf("no such console '%s'\n", (char *)value); printf("Available consoles:\n"); for (cons = 0; consoles[cons] != NULL; cons++) printf(" %s\n", consoles[cons]->c_name); return(CMD_ERROR); } /* disable all current consoles */ for (cons = 0; consoles[cons] != NULL; cons++) consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT); /* enable selected console */ consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; consoles[active]->c_init(0); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return(CMD_OK); } static u_char xlat(u_char in, struct kbxlat *kb_tab) { for(;;) { if(kb_tab->in == 0 && kb_tab->out == 0) return(in); if(kb_tab->in == in) return(kb_tab->out); kb_tab++; } } COMMAND_SET(keyboard, "keyboard", "set keyboard translate table", command_keyboard); static int command_keyboard(int argc, char *argv[]) { int country; char *cp; int i; if (argc != 2) { command_errmsg = "wrong number of arguments"; return(CMD_ERROR); } country = strtol(argv[1], &cp, 10); if (*cp != 0) { kxp = NULL; sprintf(command_errbuf, "bad country code '%s'", argv[1]); return(CMD_ERROR); } if(country == 0 || country == 1) { kxp = NULL; return(CMD_OK); } for(i=0;;i++) { if(kbptrtab[i].country == 0 && kbptrtab[i].kbxp == NULL) { kxp = NULL; sprintf(command_errbuf, "bad country code '%s'", argv[1]); return(CMD_ERROR); break; } if(kbptrtab[i].country == country) { kxp = kbptrtab[i].kbxp; return(CMD_OK); } } }